both complex and rational are now builtin classes.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@15783 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
tadf 2008-03-16 00:23:43 +00:00
Родитель 2694b2f937
Коммит 6125552c27
16 изменённых файлов: 4952 добавлений и 1065 удалений

Просмотреть файл

@ -1,3 +1,43 @@
Sun Mar 16 08:51:41 2008 Tadayoshi Funaba <tadf@dotrb.org>
* include/ruby/intern.h: added some declarations.
* include/ruby/ruby.h: ditto.
* common.mk: added some entries.
* configure.in: added a check for signbit.
* lib/complex.rb: nearly all of core definitions have been removed.
* lib/rational.rb: ditto.
* lib/mathn.rb: some trivial adjustments.
* complex.c: new.
* rational.c: ditto.
* numeric.c (flo_{quo,rdiv}, fix_fdiv): added.
* numeric.c ({num,int}_{numerator,denominator}): ditto.
* bignum.c (rb_big_fdiv): ditto.
* numeric.c (fix_{quo,pow}): now may yield rational number.
* bignum.c (rb_big_{quo,pow}): ditto.
* numeric.c (rb_{int,flo}_induced_from): now can accept rational.
* gc.c (gc_mark_children, obj_free): now detects complex and rational.
* inits.c (rb_call_inits): now calls Init_{Complex,Rational}.
* test/ruby/test_complex.rb: new.
* test/ruby/test_rational.rb: ditto.
Sat Mar 15 17:48:48 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
* encoding.c (rb_enc_associate_index): pass unnecessary enc_capable().

Просмотреть файл

@ -1901,6 +1901,12 @@ static VALUE big_shift(VALUE x, int n)
static VALUE
rb_big_quo(VALUE x, VALUE y)
{
return rb_funcall(rb_rational_raw1(x), '/', 1, y);
}
static VALUE
rb_big_fdiv(VALUE x, VALUE y)
{
double dx = big2dbl(x);
double dy;
@ -1947,7 +1953,7 @@ rb_big_quo(VALUE x, VALUE y)
break;
default:
return rb_num_coerce_bin(x, y, rb_intern("quo"));
return rb_num_coerce_bin(x, y, rb_intern("fdiv"));
}
return DOUBLE2NUM(dx / dy);
}
@ -2025,13 +2031,19 @@ rb_big_pow(VALUE x, VALUE y)
break;
case T_BIGNUM:
if (rb_funcall(y, '<', 1, INT2FIX(0)))
return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
rb_warn("in a**b, b may be too big");
d = rb_big2dbl(y);
break;
case T_FIXNUM:
yy = FIX2LONG(y);
if (yy > 0) {
if (yy < 0)
return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
else {
VALUE z = 0;
SIGNED_VALUE mask;
const long BIGLEN_LIMIT = 1024*1024 / SIZEOF_BDIGITS;
@ -2050,7 +2062,7 @@ rb_big_pow(VALUE x, VALUE y)
}
return bignorm(z);
}
d = (double)yy;
/* NOTREACHED */
break;
default:
@ -2590,7 +2602,8 @@ Init_Bignum(void)
rb_define_method(rb_cBignum, "modulo", rb_big_modulo, 1);
rb_define_method(rb_cBignum, "remainder", rb_big_remainder, 1);
rb_define_method(rb_cBignum, "quo", rb_big_quo, 1);
rb_define_method(rb_cBignum, "fdiv", rb_big_quo, 1);
rb_define_method(rb_cBignum, "rdiv", rb_big_quo, 1);
rb_define_method(rb_cBignum, "fdiv", rb_big_fdiv, 1);
rb_define_method(rb_cBignum, "**", rb_big_pow, 1);
rb_define_method(rb_cBignum, "&", rb_big_and, 1);
rb_define_method(rb_cBignum, "|", rb_big_or, 1);

Просмотреть файл

@ -23,6 +23,7 @@ COMMONOBJS = array.$(OBJEXT) \
bignum.$(OBJEXT) \
class.$(OBJEXT) \
compar.$(OBJEXT) \
complex.$(OBJEXT) \
dir.$(OBJEXT) \
enum.$(OBJEXT) \
enumerator.$(OBJEXT) \
@ -45,6 +46,7 @@ COMMONOBJS = array.$(OBJEXT) \
prec.$(OBJEXT) \
random.$(OBJEXT) \
range.$(OBJEXT) \
rational.$(OBJEXT) \
re.$(OBJEXT) \
regcomp.$(OBJEXT) \
regenc.$(OBJEXT) \
@ -424,6 +426,9 @@ class.$(OBJEXT): {$(VPATH)}class.c {$(VPATH)}ruby.h {$(VPATH)}config.h \
compar.$(OBJEXT): {$(VPATH)}compar.c {$(VPATH)}ruby.h {$(VPATH)}config.h \
{$(VPATH)}defines.h {$(VPATH)}missing.h {$(VPATH)}intern.h \
{$(VPATH)}st.h
complex.$(OBJEXT): {$(VPATH)}complex.c {$(VPATH)}ruby.h {$(VPATH)}config.h \
{$(VPATH)}defines.h {$(VPATH)}missing.h {$(VPATH)}intern.h \
{$(VPATH)}st.h
dir.$(OBJEXT): {$(VPATH)}dir.c {$(VPATH)}ruby.h {$(VPATH)}config.h \
{$(VPATH)}defines.h {$(VPATH)}missing.h {$(VPATH)}intern.h \
{$(VPATH)}st.h {$(VPATH)}util.h
@ -530,6 +535,9 @@ random.$(OBJEXT): {$(VPATH)}random.c {$(VPATH)}ruby.h {$(VPATH)}config.h \
range.$(OBJEXT): {$(VPATH)}range.c {$(VPATH)}ruby.h {$(VPATH)}config.h \
{$(VPATH)}defines.h {$(VPATH)}missing.h {$(VPATH)}intern.h \
{$(VPATH)}st.h
rational.$(OBJEXT): {$(VPATH)}rational.c {$(VPATH)}ruby.h {$(VPATH)}config.h \
{$(VPATH)}defines.h {$(VPATH)}missing.h {$(VPATH)}intern.h \
{$(VPATH)}st.h
re.$(OBJEXT): {$(VPATH)}re.c {$(VPATH)}ruby.h {$(VPATH)}config.h \
{$(VPATH)}defines.h {$(VPATH)}missing.h {$(VPATH)}intern.h \
{$(VPATH)}st.h {$(VPATH)}re.h {$(VPATH)}regex.h {$(VPATH)}oniguruma.h \

1533
complex.c Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -693,7 +693,7 @@ AC_CHECK_FUNCS(fmod killpg wait4 waitpid fork spawnv syscall chroot fsync getcwd
getpgrp setpgrp getpgid setpgid initgroups getgroups setgroups\
getpriority getrlimit setrlimit sysconf group_member\
dlopen sigprocmask sigaction sigsetjmp _setjmp vsnprintf snprintf\
setsid telldir seekdir fchmod cosh sinh tanh log2 round\
setsid telldir seekdir fchmod cosh sinh tanh log2 round signbit\
setuid setgid daemon select_large_fdset setenv unsetenv\
mktime timegm clock_gettime gettimeofday)
AC_ARG_ENABLE(setreuid,

15
gc.c
Просмотреть файл

@ -127,6 +127,8 @@ typedef struct RVALUE {
struct RFile file;
struct RNode node;
struct RMatch match;
struct RRational rational;
struct RComplex complex;
} as;
#ifdef GC_DEBUG
char *file;
@ -1128,6 +1130,16 @@ gc_mark_children(VALUE ptr, int lev)
}
break;
case T_RATIONAL:
gc_mark(obj->as.rational.num, lev);
gc_mark(obj->as.rational.den, lev);
break;
case T_COMPLEX:
gc_mark(obj->as.complex.real, lev);
gc_mark(obj->as.complex.image, lev);
break;
case T_STRUCT:
{
long len = RSTRUCT_LEN(obj);
@ -1369,6 +1381,9 @@ obj_free(VALUE obj)
rb_io_fptr_finalize(RANY(obj)->as.file.fptr);
}
break;
case T_RATIONAL:
case T_COMPLEX:
break;
case T_ICLASS:
/* iClass shares table with the module */
break;

Просмотреть файл

@ -117,6 +117,26 @@ VALUE rb_big_or(VALUE, VALUE);
VALUE rb_big_xor(VALUE, VALUE);
VALUE rb_big_lshift(VALUE, VALUE);
VALUE rb_big_rshift(VALUE, VALUE);
/* rational.c */
VALUE rb_rational_raw(VALUE, VALUE);
#define rb_rational_raw1(x) rb_rational_raw(x, INT2FIX(1))
#define rb_rational_raw2(x,y) rb_rational_raw(x, y)
VALUE rb_rational_new(VALUE, VALUE);
#define rb_rational_new1(x) rb_rational_new(x, INT2FIX(1))
#define rb_rational_new2(x,y) rb_rational_new(x, y)
VALUE rb_Rational(VALUE, VALUE);
#define rb_Rational1(x) rb_Rational(x, INT2FIX(1))
#define rb_Rational2(x,y) rb_Rational(x, y)
/* complex.c */
VALUE rb_complex_raw(VALUE, VALUE);
#define rb_complex_raw1(x) rb_complex_raw(x, INT2FIX(0))
#define rb_complex_raw2(x,y) rb_complex_raw(x, y)
VALUE rb_complex_new(VALUE, VALUE);
#define rb_complex_new1(x) rb_complex_new(x, INT2FIX(0))
#define rb_complex_new2(x,y) rb_complex_new(x, y)
VALUE rb_Complex(VALUE, VALUE);
#define rb_Complex1(x) rb_Complex(x, INT2FIX(0))
#define rb_Complex2(x,y) rb_Complex(x, y)
/* class.c */
VALUE rb_class_boot(VALUE);
VALUE rb_class_new(VALUE);

Просмотреть файл

@ -273,6 +273,11 @@ enum ruby_value_type {
RUBY_T_SYMBOL = 0x14,
#define T_SYMBOL RUBY_T_SYMBOL
RUBY_T_RATIONAL = 0x15,
#define T_RATIONAL RUBY_T_RATIONAL
RUBY_T_COMPLEX = 0x16,
#define T_COMPLEX RUBY_T_COMPLEX
RUBY_T_VALUES = 0x1a,
#define T_VALUES RUBY_T_VALUES
RUBY_T_BLOCK = 0x1b,
@ -522,6 +527,18 @@ struct RFile {
struct rb_io_t *fptr;
};
struct RRational {
struct RBasic basic;
VALUE num;
VALUE den;
};
struct RComplex {
struct RBasic basic;
VALUE real;
VALUE image;
};
struct RData {
struct RBasic basic;
void (*dmark)(void*);
@ -622,6 +639,8 @@ struct RBignum {
#define RSTRUCT(obj) (R_CAST(RStruct)(obj))
#define RBIGNUM(obj) (R_CAST(RBignum)(obj))
#define RFILE(obj) (R_CAST(RFile)(obj))
#define RRATIONAL(obj) (R_CAST(RRational)(obj))
#define RCOMPLEX(obj) (R_CAST(RComplex)(obj))
#define RVALUES(obj) (R_CAST(RValues)(obj))
#define FL_SINGLETON FL_USER0
@ -851,6 +870,8 @@ RUBY_EXTERN VALUE rb_cNilClass;
RUBY_EXTERN VALUE rb_cNumeric;
RUBY_EXTERN VALUE rb_cProc;
RUBY_EXTERN VALUE rb_cRange;
RUBY_EXTERN VALUE rb_cRational;
RUBY_EXTERN VALUE rb_cComplex;
RUBY_EXTERN VALUE rb_cRegexp;
RUBY_EXTERN VALUE rb_cStat;
RUBY_EXTERN VALUE rb_cString;

Просмотреть файл

@ -15,6 +15,7 @@ void Init_Array(void);
void Init_Bignum(void);
void Init_Binding(void);
void Init_Comparable(void);
void Init_Complex(void);
void Init_transcode(void);
void Init_Dir(void);
void Init_Enumerable(void);
@ -39,6 +40,7 @@ void Init_id(void);
void Init_process(void);
void Init_Random(void);
void Init_Range(void);
void Init_Rational(void);
void Init_Regexp(void);
void Init_signal(void);
void Init_String(void);
@ -96,5 +98,7 @@ rb_call_inits()
Init_ISeq();
Init_Thread();
Init_Cont();
Init_Rational();
Init_Complex();
Init_version();
}

Просмотреть файл

@ -1,473 +1,90 @@
#
# complex.rb -
# $Release Version: 0.5 $
# $Revision: 1.3 $
# by Keiju ISHITSUKA(SHL Japan Inc.)
#
# ----
#
# complex.rb implements the Complex class for complex numbers. Additionally,
# some methods in other Numeric classes are redefined or added to allow greater
# interoperability with Complex numbers.
#
# Complex numbers can be created in the following manner:
# - <tt>Complex(a, b)</tt>
# - <tt>Complex.polar(radius, theta)</tt>
#
# Additionally, note the following:
# - <tt>Complex::I</tt> (the mathematical constant <i>i</i>)
# - <tt>Numeric#im</tt> (e.g. <tt>5.im -> 0+5i</tt>)
#
# The following +Math+ module methods are redefined to handle Complex arguments.
# They will work as normal with non-Complex arguments.
# sqrt exp cos sin tan log log10
# cosh sinh tanh acos asin atan atan2 acosh asinh atanh
#
#
# Numeric is a built-in class on which Fixnum, Bignum, etc., are based. Here
# some methods are added so that all number types can be treated to some extent
# as Complex numbers.
#
class Numeric
#
# Returns a Complex number <tt>(0,<i>self</i>)</tt>.
#
def im
Complex(0, self)
end
#
# The real part of a complex number, i.e. <i>self</i>.
#
def real
self
end
#
# The imaginary part of a complex number, i.e. 0.
#
def image
0
end
alias imag image
#
# See Complex#arg.
#
def arg
if self >= 0
return 0
else
return Math::PI
end
end
alias angle arg
#
# See Complex#polar.
#
def polar
return abs, arg
end
#
# See Complex#conjugate (short answer: returns <i>self</i>).
#
def conjugate
self
end
alias conj conjugate
end
#
# Creates a Complex number. +a+ and +b+ should be Numeric. The result will be
# <tt>a+bi</tt>.
#
def Complex(a, b = 0)
if b == 0 and (a.kind_of?(Complex) or defined? Complex::Unify)
a
elsif a.scalar? and b.scalar?
# Don't delete for -0.0
Complex.new(a, b)
else
Complex.new( a.real-b.imag, a.imag+b.real )
end
end
#
# The complex number class. See complex.rb for an overview.
#
class Complex < Numeric
@RCS_ID='-$Id: complex.rb,v 1.3 1998/07/08 10:05:28 keiju Exp keiju $-'
undef step
undef <, <=, <=>, >, >=
undef between?
undef div, divmod, modulo
undef floor, truncate, ceil, round
def scalar?
false
end
def Complex.generic?(other) # :nodoc:
other.kind_of?(Integer) or
other.kind_of?(Float) or
(defined?(Rational) and other.kind_of?(Rational))
end
#
# Creates a +Complex+ number in terms of +r+ (radius) and +theta+ (angle).
#
def Complex.polar(r, theta)
Complex(r*Math.cos(theta), r*Math.sin(theta))
end
#
# Creates a +Complex+ number <tt>a</tt>+<tt>b</tt><i>i</i>.
#
def Complex.new!(a, b=0)
new(a,b)
end
def initialize(a, b)
raise TypeError, "non numeric 1st arg `#{a.inspect}'" if !a.kind_of? Numeric
raise TypeError, "`#{a.inspect}' for 1st arg" if a.kind_of? Complex
raise TypeError, "non numeric 2nd arg `#{b.inspect}'" if !b.kind_of? Numeric
raise TypeError, "`#{b.inspect}' for 2nd arg" if b.kind_of? Complex
@real = a
@image = b
end
#
# Addition with real or complex number.
#
def + (other)
if other.kind_of?(Complex)
re = @real + other.real
im = @image + other.image
Complex(re, im)
elsif Complex.generic?(other)
Complex(@real + other, @image)
else
x , y = other.coerce(self)
x + y
end
end
#
# Subtraction with real or complex number.
#
def - (other)
if other.kind_of?(Complex)
re = @real - other.real
im = @image - other.image
Complex(re, im)
elsif Complex.generic?(other)
Complex(@real - other, @image)
else
x , y = other.coerce(self)
x - y
end
end
#
# Multiplication with real or complex number.
#
def * (other)
if other.kind_of?(Complex)
re = @real*other.real - @image*other.image
im = @real*other.image + @image*other.real
Complex(re, im)
elsif Complex.generic?(other)
Complex(@real * other, @image * other)
else
x , y = other.coerce(self)
x * y
end
end
#
# Division by real or complex number.
#
def / (other)
if other.kind_of?(Complex)
self*other.conjugate/other.abs2
elsif Complex.generic?(other)
Complex(@real/other, @image/other)
else
x, y = other.coerce(self)
x/y
end
end
def quo(other)
Complex(@real.quo(1), @image.quo(1)) / other
end
#
# Raise this complex number to the given (real or complex) power.
#
def ** (other)
if other == 0
return Complex(1)
end
if other.kind_of?(Complex)
r, theta = polar
ore = other.real
oim = other.image
nr = Math.exp!(ore*Math.log!(r) - oim * theta)
ntheta = theta*ore + oim*Math.log!(r)
Complex.polar(nr, ntheta)
elsif other.kind_of?(Integer)
if other > 0
x = self
z = x
n = other - 1
while n != 0
while (div, mod = n.divmod(2)
mod == 0)
x = Complex(x.real*x.real - x.image*x.image, 2*x.real*x.image)
n = div
end
z *= x
n -= 1
end
z
else
if defined? Rational
(Rational(1) / self) ** -other
else
self ** Float(other)
end
end
elsif Complex.generic?(other)
r, theta = polar
Complex.polar(r**other, theta*other)
else
x, y = other.coerce(self)
x**y
end
end
#
# Remainder after division by a real or complex number.
#
=begin
def % (other)
if other.kind_of?(Complex)
Complex(@real % other.real, @image % other.image)
elsif Complex.generic?(other)
Complex(@real % other, @image % other)
else
x , y = other.coerce(self)
x % y
end
end
=end
#--
# def divmod(other)
# if other.kind_of?(Complex)
# rdiv, rmod = @real.divmod(other.real)
# idiv, imod = @image.divmod(other.image)
# return Complex(rdiv, idiv), Complex(rmod, rmod)
# elsif Complex.generic?(other)
# Complex(@real.divmod(other), @image.divmod(other))
# else
# x , y = other.coerce(self)
# x.divmod(y)
# end
# end
#++
#
# Absolute value (aka modulus): distance from the zero point on the complex
# plane.
#
def abs
Math.hypot(@real, @image)
end
#
# Square of the absolute value.
#
def abs2
@real*@real + @image*@image
end
#
# Argument (angle from (1,0) on the complex plane).
#
def arg
Math.atan2!(@image, @real)
end
alias angle arg
#
# Returns the absolute value _and_ the argument.
#
def polar
return abs, arg
end
#
# Complex conjugate (<tt>z + z.conjugate = 2 * z.real</tt>).
#
def conjugate
Complex(@real, -@image)
end
alias conj conjugate
#
# Test for numerical equality (<tt>a == a + 0<i>i</i></tt>).
#
def == (other)
if other.kind_of?(Complex)
@real == other.real and @image == other.image
elsif Complex.generic?(other)
@real == other and @image == 0
else
other == self
end
end
#
# Attempts to coerce +other+ to a Complex number.
#
def coerce(other)
if Complex.generic?(other)
return Complex.new!(other), self
else
super
end
end
#
# FIXME
#
def denominator
@real.denominator.lcm(@image.denominator)
end
#
# FIXME
#
def numerator
cd = denominator
Complex(@real.numerator*(cd/@real.denominator),
@image.numerator*(cd/@image.denominator))
end
#
# Standard string representation of the complex number.
#
def to_s
if @real != 0
if defined?(Rational) and @image.kind_of?(Rational) and @image.denominator != 1
if @image >= 0
@real.to_s+"+("+@image.to_s+")i"
else
@real.to_s+"-("+(-@image).to_s+")i"
end
else
if @image >= 0
@real.to_s+"+"+@image.to_s+"i"
else
@real.to_s+"-"+(-@image).to_s+"i"
end
end
else
if defined?(Rational) and @image.kind_of?(Rational) and @image.denominator != 1
"("+@image.to_s+")i"
else
@image.to_s+"i"
end
end
end
#
# Returns a hash code for the complex number.
#
def hash
@real.hash ^ @image.hash
end
#
# Returns "<tt>Complex(<i>real</i>, <i>image</i>)</tt>".
#
def inspect
sprintf("Complex(%s, %s)", @real.inspect, @image.inspect)
end
#
# +I+ is the imaginary number. It exists at point (0,1) on the complex plane.
#
I = Complex(0,1)
# The real part of a complex number.
attr_reader :real
# The imaginary part of a complex number.
attr_reader :image
alias imag image
end
class Integer
unless defined?(1.numerator)
def numerator() self end
def denominator() 1 end
def gcd(other)
min = self.abs
max = other.abs
while min > 0
tmp = min
min = max % min
max = tmp
end
max
def gcd(other)
min = self.abs
max = other.abs
while min > 0
tmp = min
min = max % min
max = tmp
end
max
end
def lcm(other)
if self.zero? or other.zero?
0
else
(self.div(self.gcd(other)) * other).abs
end
def lcm(other)
if self.zero? or other.zero?
0
else
(self.div(self.gcd(other)) * other).abs
end
end
def gcdlcm(other)
gcd = self.gcd(other)
if self.zero? or other.zero?
[gcd, 0]
else
[gcd, (self.div(gcd) * other).abs]
end
end
end
module Math
alias sqrt! sqrt
alias exp! exp
alias log! log
alias log10! log10
alias cos! cos
alias sqrt! sqrt
alias sin! sin
alias cos! cos
alias tan! tan
alias cosh! cosh
alias sinh! sinh
alias cosh! cosh
alias tanh! tanh
alias acos! acos
alias asin! asin
alias acos! acos
alias atan! atan
alias atan2! atan2
alias acosh! acosh
alias asinh! asinh
alias atanh! atanh
# Redefined to handle a Complex argument.
alias asinh! asinh
alias acosh! acosh
alias atanh! atanh
def exp(z)
if Complex.generic?(z)
exp!(z)
else
Complex(exp!(z.real) * cos!(z.image),
exp!(z.real) * sin!(z.image))
end
end
def log(*args)
z, b = args
if Complex.generic?(z) and z >= 0 and (b.nil? or b >= 0)
log!(*args)
else
r, theta = z.polar
a = Complex(log!(r.abs), theta)
if b
a /= log(b)
end
a
end
end
def log10(z)
if Complex.generic?(z)
log10!(z)
else
log(z) / log!(10)
end
end
def sqrt(z)
if Complex.generic?(z)
if z >= 0
@ -481,41 +98,29 @@ module Math
else
r = z.abs
x = z.real
Complex( sqrt!((r+x)/2), sqrt!((r-x)/2) )
Complex(sqrt!((r + x) / 2), sqrt!((r - x) / 2))
end
end
end
# Redefined to handle a Complex argument.
def exp(z)
if Complex.generic?(z)
exp!(z)
else
Complex(exp!(z.real) * cos!(z.image), exp!(z.real) * sin!(z.image))
end
end
# Redefined to handle a Complex argument.
def cos(z)
if Complex.generic?(z)
cos!(z)
else
Complex(cos!(z.real)*cosh!(z.image),
-sin!(z.real)*sinh!(z.image))
end
end
# Redefined to handle a Complex argument.
def sin(z)
if Complex.generic?(z)
sin!(z)
else
Complex(sin!(z.real)*cosh!(z.image),
cos!(z.real)*sinh!(z.image))
Complex(sin!(z.real) * cosh!(z.image),
cos!(z.real) * sinh!(z.image))
end
end
# Redefined to handle a Complex argument.
def cos(z)
if Complex.generic?(z)
cos!(z)
else
Complex(cos!(z.real) * cosh!(z.image),
-sin!(z.real) * sinh!(z.image))
end
end
def tan(z)
if Complex.generic?(z)
tan!(z)
@ -528,7 +133,8 @@ module Math
if Complex.generic?(z)
sinh!(z)
else
Complex( sinh!(z.real)*cos!(z.image), cosh!(z.real)*sin!(z.image) )
Complex(sinh!(z.real) * cos!(z.image),
cosh!(z.real) * sin!(z.image))
end
end
@ -536,7 +142,8 @@ module Math
if Complex.generic?(z)
cosh!(z)
else
Complex( cosh!(z.real)*cos!(z.image), sinh!(z.real)*sin!(z.image) )
Complex(cosh!(z.real) * cos!(z.image),
sinh!(z.real) * sin!(z.image))
end
end
@ -544,34 +151,7 @@ module Math
if Complex.generic?(z)
tanh!(z)
else
sinh(z)/cosh(z)
end
end
# Redefined to handle a Complex argument.
def log(z)
if Complex.generic?(z) and z >= 0
log!(z)
else
r, theta = z.polar
Complex(log!(r.abs), theta)
end
end
# Redefined to handle a Complex argument.
def log10(z)
if Complex.generic?(z)
log10!(z)
else
log(z)/log!(10)
end
end
def acos(z)
if Complex.generic?(z) and z >= -1 and z <= 1
acos!(z)
else
-1.0.im * log( z + 1.0.im * sqrt(1.0-z*z) )
sinh(z) / cosh(z)
end
end
@ -579,7 +159,15 @@ module Math
if Complex.generic?(z) and z >= -1 and z <= 1
asin!(z)
else
-1.0.im * log( 1.0.im * z + sqrt(1.0-z*z) )
-1.0.im * log(1.0.im * z + sqrt(1.0 - z * z))
end
end
def acos(z)
if Complex.generic?(z) and z >= -1 and z <= 1
acos!(z)
else
-1.0.im * log(z + 1.0.im * sqrt(1.0 - z * z))
end
end
@ -587,7 +175,7 @@ module Math
if Complex.generic?(z)
atan!(z)
else
1.0.im * log( (1.0.im+z) / (1.0.im-z) ) / 2.0
1.0.im * log((1.0.im + z) / (1.0.im - z)) / 2.0
end
end
@ -595,7 +183,7 @@ module Math
if Complex.generic?(y) and Complex.generic?(x)
atan2!(y,x)
else
-1.0.im * log( (x+1.0.im*y) / sqrt(x*x+y*y) )
-1.0.im * log((x + 1.0.im * y) / sqrt(x * x + y * y))
end
end
@ -603,7 +191,7 @@ module Math
if Complex.generic?(z) and z >= 1
acosh!(z)
else
log( z + sqrt(z*z-1.0) )
log(z + sqrt(z * z - 1.0))
end
end
@ -611,7 +199,7 @@ module Math
if Complex.generic?(z)
asinh!(z)
else
log( z + sqrt(1.0+z*z) )
log(z + sqrt(1.0 + z * z))
end
end
@ -619,49 +207,47 @@ module Math
if Complex.generic?(z) and z >= -1 and z <= 1
atanh!(z)
else
log( (1.0+z) / (1.0-z) ) / 2.0
log((1.0 + z) / (1.0 - z)) / 2.0
end
end
module_function :sqrt!
module_function :sqrt
module_function :exp!
module_function :exp
module_function :log!
module_function :log
module_function :log10!
module_function :log10
module_function :cosh!
module_function :cosh
module_function :cos!
module_function :cos
module_function :sinh!
module_function :sinh
module_function :sqrt!
module_function :sqrt
module_function :sin!
module_function :sin
module_function :cos!
module_function :cos
module_function :tan!
module_function :tan
module_function :sinh!
module_function :sinh
module_function :cosh!
module_function :cosh
module_function :tanh!
module_function :tanh
module_function :acos!
module_function :acos
module_function :asin!
module_function :asin
module_function :acos!
module_function :acos
module_function :atan!
module_function :atan
module_function :atan2!
module_function :atan2
module_function :acosh!
module_function :acosh
module_function :asinh!
module_function :asinh
module_function :acosh!
module_function :acosh
module_function :atanh!
module_function :atanh
end
# Documentation comments:
# - source: original (researched from pickaxe)
# - a couple of fixme's
# - RDoc output for Bignum etc. is a bit short, with nothing but an
# (undocumented) alias. No big deal.
end

Просмотреть файл

@ -127,7 +127,7 @@ class Rational
if other.kind_of?(Rational)
other2 = other
if self < 0
return Complex.new!(self, 0) ** other
return Complex.__send__(:new!, self, 0) ** other
elsif other == 0
return Rational(1,1)
elsif self == 0
@ -175,7 +175,7 @@ class Rational
num = 1
den = 1
end
Rational.new!(num, den)
Rational(num, den)
elsif other.kind_of?(Float)
Float(self) ** other
else
@ -187,7 +187,7 @@ class Rational
def power2(other)
if other.kind_of?(Rational)
if self < 0
return Complex(self, 0) ** other
return Complex.__send__(:new!, self, 0) ** other
elsif other == 0
return Rational(1,1)
elsif self == 0
@ -219,7 +219,7 @@ class Rational
num = 1
den = 1
end
Rational.new!(num, den)
Rational(num, den)
elsif other.kind_of?(Float)
Float(self) ** other
else
@ -306,4 +306,3 @@ end
class Complex
Unify = true
end

Просмотреть файл

@ -1,469 +1,23 @@
#
# rational.rb -
# $Release Version: 0.5 $
# $Revision: 1.7 $
# by Keiju ISHITSUKA(SHL Japan Inc.)
#
# Documentation by Kevin Jackson and Gavin Sinclair.
#
# When you <tt>require 'rational'</tt>, all interactions between numbers
# potentially return a rational result. For example:
#
# 1.quo(2) # -> 0.5
# require 'rational'
# 1.quo(2) # -> Rational(1,2)
#
# See Rational for full documentation.
#
class Fixnum
alias quof fdiv
alias power! **
alias rpower **
#
# Creates a Rational number (i.e. a fraction). +a+ and +b+ should be Integers:
#
# Rational(1,3) # -> 1/3
#
# Note: trying to construct a Rational with floating point or real values
# produces errors:
#
# Rational(1.1, 2.3) # -> NoMethodError
#
def Rational(a, b = 1)
if a.kind_of?(Rational) && b == 1
a
else
Rational.reduce(a, b)
end
end
#
# Rational implements a rational class for numbers.
#
# <em>A rational number is a number that can be expressed as a fraction p/q
# where p and q are integers and q != 0. A rational number p/q is said to have
# numerator p and denominator q. Numbers that are not rational are called
# irrational numbers.</em> (http://mathworld.wolfram.com/RationalNumber.html)
#
# To create a Rational Number:
# Rational(a,b) # -> a/b
# Rational.new!(a,b) # -> a/b
#
# Examples:
# Rational(5,6) # -> 5/6
# Rational(5) # -> 5/1
#
# Rational numbers are reduced to their lowest terms:
# Rational(6,10) # -> 3/5
#
# But not if you use the unusual method "new!":
# Rational.new!(6,10) # -> 6/10
#
# Division by zero is obviously not allowed:
# Rational(3,0) # -> ZeroDivisionError
#
class Rational < Numeric
@RCS_ID='-$Id: rational.rb,v 1.7 1999/08/24 12:49:28 keiju Exp keiju $-'
class Bignum
#
# Reduces the given numerator and denominator to their lowest terms. Use
# Rational() instead.
#
def Rational.reduce(num, den = 1)
raise ZeroDivisionError, "denominator is zero" if den == 0
alias quof fdiv
if den < 0
num = -num
den = -den
end
gcd = num.gcd(den)
num = num.div(gcd)
den = den.div(gcd)
if den == 1 && defined?(Unify)
num
else
new!(num, den)
end
end
alias power! **
alias rpower **
#
# Implements the constructor. This method does not reduce to lowest terms or
# check for division by zero. Therefore #Rational() should be preferred in
# normal use.
#
def Rational.new!(num, den = 1)
new(num, den)
end
private_class_method :new
#
# This method is actually private.
#
def initialize(num, den)
if den < 0
num = -num
den = -den
end
if num.kind_of?(Integer) and den.kind_of?(Integer)
@numerator = num
@denominator = den
else
@numerator = num.to_i
@denominator = den.to_i
end
end
#
# Returns the addition of this value and +a+.
#
# Examples:
# r = Rational(3,4) # -> Rational(3,4)
# r + 1 # -> Rational(7,4)
# r + 0.5 # -> 1.25
#
def + (a)
if a.kind_of?(Rational)
num = @numerator * a.denominator
num_a = a.numerator * @denominator
Rational(num + num_a, @denominator * a.denominator)
elsif a.kind_of?(Integer)
self + Rational.new!(a, 1)
elsif a.kind_of?(Float)
Float(self) + a
else
x, y = a.coerce(self)
x + y
end
end
#
# Returns the difference of this value and +a+.
# subtracted.
#
# Examples:
# r = Rational(3,4) # -> Rational(3,4)
# r - 1 # -> Rational(-1,4)
# r - 0.5 # -> 0.25
#
def - (a)
if a.kind_of?(Rational)
num = @numerator * a.denominator
num_a = a.numerator * @denominator
Rational(num - num_a, @denominator*a.denominator)
elsif a.kind_of?(Integer)
self - Rational.new!(a, 1)
elsif a.kind_of?(Float)
Float(self) - a
else
x, y = a.coerce(self)
x - y
end
end
#
# Returns the product of this value and +a+.
#
# Examples:
# r = Rational(3,4) # -> Rational(3,4)
# r * 2 # -> Rational(3,2)
# r * 4 # -> Rational(3,1)
# r * 0.5 # -> 0.375
# r * Rational(1,2) # -> Rational(3,8)
#
def * (a)
if a.kind_of?(Rational)
num = @numerator * a.numerator
den = @denominator * a.denominator
Rational(num, den)
elsif a.kind_of?(Integer)
self * Rational.new!(a, 1)
elsif a.kind_of?(Float)
Float(self) * a
else
x, y = a.coerce(self)
x * y
end
end
#
# Returns the quotient of this value and +a+.
# r = Rational(3,4) # -> Rational(3,4)
# r / 2 # -> Rational(3,8)
# r / 2.0 # -> 0.375
# r / Rational(1,2) # -> Rational(3,2)
#
def / (a)
if a.kind_of?(Rational)
num = @numerator * a.denominator
den = @denominator * a.numerator
Rational(num, den)
elsif a.kind_of?(Integer)
raise ZeroDivisionError, "division by zero" if a == 0
self / Rational.new!(a, 1)
elsif a.kind_of?(Float)
Float(self) / a
else
x, y = a.coerce(self)
x / y
end
end
#
# Returns this value raised to the given power.
#
# Examples:
# r = Rational(3,4) # -> Rational(3,4)
# r ** 2 # -> Rational(9,16)
# r ** 2.0 # -> 0.5625
# r ** Rational(1,2) # -> 0.866025403784439
#
def ** (other)
if other.kind_of?(Rational)
Float(self) ** other
elsif other.kind_of?(Integer)
if other > 0
num = @numerator ** other
den = @denominator ** other
elsif other < 0
num = @denominator ** -other
den = @numerator ** -other
elsif other == 0
num = 1
den = 1
end
Rational.new!(num, den)
elsif other.kind_of?(Float)
Float(self) ** other
else
x, y = other.coerce(self)
x ** y
end
end
def div(other)
(self / other).floor
end
#
# Returns the remainder when this value is divided by +other+.
#
# Examples:
# r = Rational(7,4) # -> Rational(7,4)
# r % Rational(1,2) # -> Rational(1,4)
# r % 1 # -> Rational(3,4)
# r % Rational(1,7) # -> Rational(1,28)
# r % 0.26 # -> 0.19
#
def % (other)
value = (self / other).floor
return self - other * value
end
#
# Returns the quotient _and_ remainder.
#
# Examples:
# r = Rational(7,4) # -> Rational(7,4)
# r.divmod Rational(1,2) # -> [3, Rational(1,4)]
#
def divmod(other)
value = (self / other).floor
return value, self - other * value
end
#
# Returns the absolute value.
#
def abs
if @numerator > 0
self
else
Rational.new!(-@numerator, @denominator)
end
end
#
# Returns +true+ iff this value is numerically equal to +other+.
#
# But beware:
# Rational(1,2) == Rational(4,8) # -> true
# Rational(1,2) == Rational.new!(4,8) # -> false
#
# Don't use Rational.new!
#
def == (other)
if other.kind_of?(Rational)
@numerator == other.numerator and @denominator == other.denominator
elsif other.kind_of?(Integer)
self == Rational.new!(other, 1)
elsif other.kind_of?(Float)
Float(self) == other
else
other == self
end
end
#
# Standard comparison operator.
#
def <=> (other)
if other.kind_of?(Rational)
num = @numerator * other.denominator
num_a = other.numerator * @denominator
v = num - num_a
if v > 0
return 1
elsif v < 0
return -1
else
return 0
end
elsif other.kind_of?(Integer)
return self <=> Rational.new!(other, 1)
elsif other.kind_of?(Float)
return Float(self) <=> other
elsif defined? other.coerce
x, y = other.coerce(self)
return x <=> y
else
return nil
end
end
def coerce(other)
if other.kind_of?(Float)
return other, self.to_f
elsif other.kind_of?(Integer)
return Rational.new!(other, 1), self
else
super
end
end
#
# Converts the rational to an Integer. Not the _nearest_ integer, the
# truncated integer. Study the following example carefully:
# Rational(+7,4).to_i # -> 1
# Rational(-7,4).to_i # -> -2
# (-1.75).to_i # -> -1
#
# In other words:
# Rational(-7,4) == -1.75 # -> true
# Rational(-7,4).to_i == (-1.75).to_i # false
#
def floor()
@numerator.div(@denominator)
end
def ceil()
-((-@numerator).div(@denominator))
end
def truncate()
if @numerator < 0
return -((-@numerator).div(@denominator))
end
@numerator.div(@denominator)
end
alias_method :to_i, :truncate
def round()
if @numerator < 0
num = -@numerator
num = num * 2 + @denominator
den = @denominator * 2
-(num.div(den))
else
num = @numerator * 2 + @denominator
den = @denominator * 2
num.div(den)
end
end
#
# Converts the rational to a Float.
#
def to_f
@numerator.quof(@denominator)
end
#
# Returns a string representation of the rational number.
#
# Example:
# Rational(3,4).to_s # "3/4"
# Rational(8).to_s # "8"
#
def to_s
if @denominator == 1
@numerator.to_s
else
@numerator.to_s+"/"+@denominator.to_s
end
end
#
# Returns +self+.
#
def to_r
self
end
#
# Returns a reconstructable string representation:
#
# Rational(5,8).inspect # -> "Rational(5, 8)"
#
def inspect
sprintf("Rational(%s, %s)", @numerator.inspect, @denominator.inspect)
end
#
# Returns a hash code for the object.
#
def hash
@numerator.hash ^ @denominator.hash
end
attr :numerator
attr :denominator
private :initialize
end
class Integer
#
# In an integer, the value _is_ the numerator of its rational equivalent.
# Therefore, this method returns +self+.
#
def numerator
self
end
#
# In an integer, the denominator is 1. Therefore, this method returns 1.
#
def denominator
1
end
#
# Returns a Rational representation of this integer.
#
def to_r
Rational(self, 1)
end
#
# Returns the <em>greatest common denominator</em> of the two numbers (+self+
# and +n+).
#
# Examples:
# 72.gcd 168 # -> 24
# 19.gcd 36 # -> 1
#
# The result is positive, no matter the sign of the arguments.
#
def gcd(other)
min = self.abs
max = other.abs
@ -475,10 +29,6 @@ class Integer
max
end
# Examples:
# 6.lcm 7 # -> 42
# 6.lcm 9 # -> 18
#
def lcm(other)
if self.zero? or other.zero?
0
@ -486,15 +36,7 @@ class Integer
(self.div(self.gcd(other)) * other).abs
end
end
#
# Returns the GCD _and_ the LCM (see #gcd and #lcm) of the two arguments
# (+self+ and +other+). This is more efficient than calculating them
# separately.
#
# Example:
# 6.gcdlcm 9 # -> [3, 18]
#
def gcdlcm(other)
gcd = self.gcd(other)
if self.zero? or other.zero?
@ -503,55 +45,5 @@ class Integer
[gcd, (self.div(gcd) * other).abs]
end
end
end
class Fixnum
alias quof quo
remove_method :quo
# If Rational is defined, returns a Rational number instead of a Float.
def quo(other)
Rational.new!(self, 1) / other
end
alias rdiv quo
# Returns a Rational number if the result is in fact rational (i.e. +other+ < 0).
def rpower (other)
if other >= 0
self.power!(other)
else
Rational.new!(self, 1)**other
end
end
end
class Bignum
alias quof quo
remove_method :quo
# If Rational is defined, returns a Rational number instead of a Float.
def quo(other)
Rational.new!(self, 1) / other
end
alias rdiv quo
# Returns a Rational number if the result is in fact rational (i.e. +other+ < 0).
def rpower (other)
if other >= 0
self.power!(other)
else
Rational.new!(self, 1)**other
end
end
end
unless defined? 1.power!
class Fixnum
alias power! **
alias ** rpower
end
class Bignum
alias power! **
alias ** rpower
end
end

Просмотреть файл

@ -646,6 +646,17 @@ flo_div(VALUE x, VALUE y)
}
}
static VALUE
flo_quo(VALUE x, VALUE y)
{
return rb_funcall(x, '/', 1, y);
}
static VALUE
flo_rdiv(VALUE x, VALUE y)
{
return rb_funcall(rb_Rational1(x), '/', 1, y);
}
static void
flodivmod(double x, double y, double *divp, double *modp)
@ -1699,6 +1710,17 @@ rb_num2ull(VALUE val)
#endif /* HAVE_LONG_LONG */
static VALUE
num_numerator(VALUE num)
{
return rb_funcall(rb_Rational1(num), rb_intern("numerator"), 0);
}
static VALUE
num_denominator(VALUE num)
{
return rb_funcall(rb_Rational1(num), rb_intern("denominator"), 0);
}
/*
* Document-class: Integer
@ -1880,6 +1902,18 @@ int_chr(int argc, VALUE *argv, VALUE num)
return str;
}
static VALUE
int_numerator(VALUE num)
{
return num;
}
static VALUE
int_denominator(VALUE num)
{
return INT2FIX(1);
}
/********************************************************************
*
* Document-class: Fixnum
@ -1928,6 +1962,7 @@ rb_int_induced_from(VALUE klass, VALUE x)
case T_BIGNUM:
return x;
case T_FLOAT:
case T_RATIONAL:
return rb_funcall(x, id_to_i, 0);
default:
rb_raise(rb_eTypeError, "failed to convert %s into Integer",
@ -1948,6 +1983,7 @@ rb_flo_induced_from(VALUE klass, VALUE x)
switch (TYPE(x)) {
case T_FIXNUM:
case T_BIGNUM:
case T_RATIONAL:
return rb_funcall(x, rb_intern("to_f"), 0);
case T_FLOAT:
return x;
@ -2198,6 +2234,12 @@ fixdivmod(long x, long y, long *divp, long *modp)
static VALUE
fix_quo(VALUE x, VALUE y)
{
return rb_funcall(rb_rational_raw1(x), '/', 1, y);
}
static VALUE
fix_fdiv(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
return DOUBLE2NUM((double)FIX2LONG(x) / (double)FIX2LONG(y));
@ -2208,7 +2250,7 @@ fix_quo(VALUE x, VALUE y)
case T_FLOAT:
return DOUBLE2NUM((double)FIX2LONG(x) / RFLOAT_VALUE(y));
default:
return rb_num_coerce_bin(x, y, rb_intern("quo"));
return rb_num_coerce_bin(x, y, rb_intern("fdiv"));
}
}
@ -2392,6 +2434,9 @@ fix_pow(VALUE x, VALUE y)
if (FIXNUM_P(y)) {
long b = FIX2LONG(y);
if (b < 0)
return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
if (b == 0) return INT2FIX(1);
if (b == 1) return x;
if (a == 0) {
@ -2405,13 +2450,14 @@ fix_pow(VALUE x, VALUE y)
else
return INT2FIX(-1);
}
if (b > 0) {
return int_pow(a, b);
}
return DOUBLE2NUM(pow((double)a, (double)b));
return int_pow(a, b);
}
switch (TYPE(y)) {
case T_BIGNUM:
if (rb_funcall(y, '<', 1, INT2FIX(0)))
return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
if (a == 0) return INT2FIX(0);
if (a == 1) return INT2FIX(1);
if (a == -1) {
@ -3117,6 +3163,7 @@ Init_Numeric(void)
rb_define_method(rb_cNumeric, "<=>", num_cmp, 1);
rb_define_method(rb_cNumeric, "eql?", num_eql, 1);
rb_define_method(rb_cNumeric, "quo", num_quo, 1);
rb_define_method(rb_cNumeric, "rdiv", num_quo, 1);
rb_define_method(rb_cNumeric, "fdiv", num_quo, 1);
rb_define_method(rb_cNumeric, "div", num_div, 1);
rb_define_method(rb_cNumeric, "divmod", num_divmod, 1);
@ -3136,6 +3183,9 @@ Init_Numeric(void)
rb_define_method(rb_cNumeric, "truncate", num_truncate, 0);
rb_define_method(rb_cNumeric, "step", num_step, -1);
rb_define_method(rb_cNumeric, "numerator", num_numerator, 0);
rb_define_method(rb_cNumeric, "denominator", num_denominator, 0);
rb_cInteger = rb_define_class("Integer", rb_cNumeric);
rb_undef_alloc_func(rb_cInteger);
rb_undef_method(CLASS_OF(rb_cInteger), "new");
@ -3163,6 +3213,9 @@ Init_Numeric(void)
rb_define_singleton_method(rb_cFixnum, "induced_from", rb_fix_induced_from, 1);
rb_define_singleton_method(rb_cInteger, "induced_from", rb_int_induced_from, 1);
rb_define_method(rb_cInteger, "numerator", int_numerator, 0);
rb_define_method(rb_cInteger, "denominator", int_denominator, 0);
rb_define_method(rb_cFixnum, "to_s", fix_to_s, -1);
rb_define_method(rb_cFixnum, "id2name", fix_id2name, 0);
@ -3178,7 +3231,8 @@ Init_Numeric(void)
rb_define_method(rb_cFixnum, "modulo", fix_mod, 1);
rb_define_method(rb_cFixnum, "divmod", fix_divmod, 1);
rb_define_method(rb_cFixnum, "quo", fix_quo, 1);
rb_define_method(rb_cFixnum, "fdiv", fix_quo, 1);
rb_define_method(rb_cFixnum, "rdiv", fix_quo, 1);
rb_define_method(rb_cFixnum, "fdiv", fix_fdiv, 1);
rb_define_method(rb_cFixnum, "**", fix_pow, 1);
rb_define_method(rb_cFixnum, "abs", fix_abs, 0);
@ -3233,6 +3287,9 @@ Init_Numeric(void)
rb_define_method(rb_cFloat, "-", flo_minus, 1);
rb_define_method(rb_cFloat, "*", flo_mul, 1);
rb_define_method(rb_cFloat, "/", flo_div, 1);
rb_define_method(rb_cFloat, "quo", flo_quo, 1);
rb_define_method(rb_cFloat, "rdiv", flo_rdiv, 1);
rb_define_method(rb_cFloat, "fdiv", flo_quo, 1);
rb_define_method(rb_cFloat, "%", flo_mod, 1);
rb_define_method(rb_cFloat, "modulo", flo_mod, 1);
rb_define_method(rb_cFloat, "divmod", flo_divmod, 1);

1111
rational.c Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

1017
test/ruby/test_complex.rb Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

971
test/ruby/test_rational.rb Normal file
Просмотреть файл

@ -0,0 +1,971 @@
require 'test/unit'
class RationalSub < Rational; end
class Rational_Test < Test::Unit::TestCase
def test_sub
c = RationalSub.__send__(:new, 1)
cc = RationalSub.__send__(:convert, 1)
if defined?(RationalSub::Unify)
assert_instance_of(Fixnum, c)
assert_instance_of(Fixnum, cc)
else
assert_instance_of(RationalSub, c)
assert_instance_of(RationalSub, cc)
c2 = c + 1
assert_instance_of(RationalSub, c2)
c2 = c - 1
assert_instance_of(RationalSub, c2)
c3 = c - c2
assert_instance_of(RationalSub, c3)
s = Marshal.dump(c)
c5 = Marshal.load(s)
assert_equal(c, c5)
assert_instance_of(RationalSub, c5)
end
end
def test_hash
assert_instance_of(Fixnum, Rational(1,2).hash)
h = {}
h[Rational(0)] = 0
h[Rational(1,1)] = 1
h[Rational(2,1)] = 2
h[Rational(3,1)] = 3
assert_equal(4, h.size)
assert_equal(2, h[Rational(2,1)])
h[Rational(0,1)] = 9
assert_equal(4, h.size)
end
def test_freeze
c = Rational(1)
c.freeze
unless defined?(Rational::Unify)
assert_equal(true, c.frozen?)
end
assert_instance_of(String, c.to_s)
end
def test_new_bang # no unify & no reduce
assert_instance_of(Rational, Rational.__send__(:new!, 2,1))
assert_equal([2,1], Rational.__send__(:new!, 2,1).
instance_eval{[numerator, denominator]})
assert_equal([2,4], Rational.__send__(:new!, 2,4).
instance_eval{[numerator, denominator]})
assert_equal([-2,4], Rational.__send__(:new!, -2,4).
instance_eval{[numerator, denominator]})
assert_equal([-2,4], Rational.__send__(:new!, 2,-4).
instance_eval{[numerator, denominator]})
assert_equal([2,4], Rational.__send__(:new!, -2,-4).
instance_eval{[numerator, denominator]})
# to_i
assert_equal([2,1], Rational.__send__(:new!, Rational(2)).
instance_eval{[numerator, denominator]})
assert_equal([2,3], Rational.__send__(:new!, Rational(2), Rational(3)).
instance_eval{[numerator, denominator]})
assert_equal([2,3], Rational.__send__(:new!, 2, Rational(3)).
instance_eval{[numerator, denominator]})
assert_equal([1,1], Rational.__send__(:new!, 1.1).
instance_eval{[numerator, denominator]})
assert_equal([-1,1], Rational.__send__(:new!, -1.1).
instance_eval{[numerator, denominator]})
assert_equal([1,1], Rational.__send__(:new!, '1').
instance_eval{[numerator, denominator]})
assert_equal([0,1], Rational.__send__(:new!, nil).
instance_eval{[numerator, denominator]})
end
=begin
def test_reduce
if defined?(Rational::Unify)
assert_instance_of(Fixnum, Rational.__send__(:reduce, 2,1))
else
assert_instance_of(Rational, Rational.__send__(:reduce, 2,1))
assert_instance_of(Rational, Rational.__send__(:reduce, 2,1))
end
assert_equal([2,1], Rational.__send__(:reduce, 2,1).
instance_eval{[numerator, denominator]})
assert_equal([1,2], Rational.__send__(:reduce, 2,4).
instance_eval{[numerator, denominator]})
assert_equal([-1,2], Rational.__send__(:reduce, -2,4).
instance_eval{[numerator, denominator]})
assert_equal([-1,2], Rational.__send__(:reduce, 2,-4).
instance_eval{[numerator, denominator]})
assert_equal([1,2], Rational.__send__(:reduce, -2,-4).
instance_eval{[numerator, denominator]})
assert_raise(ArgumentError){Rational.__send__(:reduce, Rational(1,2),2)}
assert_raise(ArgumentError){Rational.__send__(:reduce, 2,Rational(1,2))}
assert_raise(ArgumentError){Rational.
__send__(:reduce, Rational(1,2),Rational(1,2))}
assert_raise(ArgumentError){Rational.__send__(:reduce, 1.1)}
assert_raise(ArgumentError){Rational.__send__(:reduce, -1.1)}
assert_raise(ArgumentError){Rational.__send__(:reduce, '1')}
assert_raise(ArgumentError){Rational.__send__(:reduce, nil)}
end
=end
def test_new
if defined?(Rational::Unify)
assert_instance_of(Fixnum, Rational.__send__(:new, 2,1))
else
assert_instance_of(Rational, Rational.__send__(:new, 2,1))
assert_equal([2,1], Rational.__send__(:new, 2,1).
instance_eval{[numerator, denominator]})
end
assert_equal([1,2], Rational.__send__(:new, 2,4).
instance_eval{[numerator, denominator]})
assert_equal([-1,2], Rational.__send__(:new, -2,4).
instance_eval{[numerator, denominator]})
assert_equal([-1,2], Rational.__send__(:new, 2,-4).
instance_eval{[numerator, denominator]})
assert_equal([1,2], Rational.__send__(:new, -2,-4).
instance_eval{[numerator, denominator]})
assert_raise(ArgumentError){Rational.__send__(:new, Rational(1,2),2)}
assert_raise(ArgumentError){Rational.__send__(:new, 2,Rational(1,2))}
assert_raise(ArgumentError){Rational.__send__(:new, Rational(1,2),Rational(1,2))}
assert_raise(ArgumentError){Rational.__send__(:new, 1.1)}
assert_raise(ArgumentError){Rational.__send__(:new, -1.1)}
assert_raise(ArgumentError){Rational.__send__(:new, '1')}
assert_raise(ArgumentError){Rational.__send__(:new, nil)}
=begin
assert_raise(ArgumentError){Rational.__send__(:new, Rational(1))}
if defined?(Complex)
assert_raise(ArgumentError){Rational.__send__(:new, Complex(1))}
end
=end
end
def test_conv
c = Rational(0,1)
assert_equal(Rational.__send__(:new, 0,1), c)
c = Rational(2**32, 2**32)
assert_equal(Rational.__send__(:new, 2**32,2**32), c)
assert_equal([1,1], [c.numerator,c.denominator])
c = Rational(-2**32, 2**32)
assert_equal(Rational.__send__(:new, -2**32,2**32), c)
assert_equal([-1,1], [c.numerator,c.denominator])
c = Rational(2**32, -2**32)
assert_equal(Rational.__send__(:new, 2**32,-2**32), c)
assert_equal([-1,1], [c.numerator,c.denominator])
c = Rational(-2**32, -2**32)
assert_equal(Rational.__send__(:new, -2**32,-2**32), c)
assert_equal([1,1], [c.numerator,c.denominator])
c = Rational(Rational(1,2),2)
assert_equal(Rational.__send__(:new, 1,4), c)
c = Rational(2,Rational(1,2))
assert_equal(Rational.__send__(:new, 4), c)
c = Rational(Rational(1,2),Rational(1,2))
assert_equal(Rational.__send__(:new, 1), c)
assert_equal(Rational.__send__(:new, 1),Rational(1))
assert_equal(1.1.to_r,Rational(1.1))
assert_equal(Rational.__send__(:new, 1),Rational('1'))
assert_raise(ArgumentError){Rational(nil)}
end
def test_attr
c = Rational(4)
assert_equal(4, c.numerator)
assert_equal(1, c.denominator)
c = Rational(4,5)
assert_equal(4, c.numerator)
assert_equal(5, c.denominator)
c = Rational.__send__(:new, 4)
assert_equal(4, c.numerator)
assert_equal(1, c.denominator)
c = Rational.__send__(:new, 4,5)
assert_equal(4, c.numerator)
assert_equal(5, c.denominator)
c = Rational.__send__(:new!, 4)
assert_equal(4, c.numerator)
assert_equal(1, c.denominator)
c = Rational.__send__(:new!, 4,5)
assert_equal(4, c.numerator)
assert_equal(5, c.denominator)
end
def test_attr2
c = Rational(1)
if defined?(Rational::Unify)
assert_equal(true, c.scalar?)
=begin
assert_equal(true, c.finite?)
assert_equal(false, c.infinite?)
assert_equal(false, c.nan?)
assert_equal(true, c.integer?)
assert_equal(false, c.float?)
assert_equal(true, c.rational?)
assert_equal(true, c.real?)
assert_equal(false, c.complex?)
assert_equal(true, c.exact?)
assert_equal(false, c.inexact?)
=end
else
assert_equal(true, c.scalar?)
=begin
assert_equal(true, c.finite?)
assert_equal(false, c.infinite?)
assert_equal(false, c.nan?)
assert_equal(false, c.integer?)
assert_equal(false, c.float?)
assert_equal(true, c.rational?)
assert_equal(true, c.real?)
assert_equal(false, c.complex?)
assert_equal(true, c.exact?)
assert_equal(false, c.inexact?)
=end
end
=begin
assert_equal(true, Rational(0).positive?)
assert_equal(true, Rational(1).positive?)
assert_equal(false, Rational(-1).positive?)
assert_equal(false, Rational(0).negative?)
assert_equal(false, Rational(1).negative?)
assert_equal(true, Rational(-1).negative?)
assert_equal(0, Rational(0).sign)
assert_equal(1, Rational(2).sign)
assert_equal(-1, Rational(-2).sign)
=end
assert_equal(true, Rational(0).zero?)
assert_equal(true, Rational(0,1).zero?)
assert_equal(false, Rational(1,1).zero?)
assert_equal(nil, Rational(0).nonzero?)
assert_equal(nil, Rational(0,1).nonzero?)
assert_equal(Rational(1,1), Rational(1,1).nonzero?)
end
def test_uplus
assert_equal(Rational(1), +Rational(1))
assert_equal(Rational(-1), +Rational(-1))
assert_equal(Rational(1,1), +Rational(1,1))
assert_equal(Rational(-1,1), +Rational(-1,1))
assert_equal(Rational(-1,1), +Rational(1,-1))
assert_equal(Rational(1,1), +Rational(-1,-1))
end
def test_negate
assert_equal(Rational(-1), -Rational(1))
assert_equal(Rational(1), -Rational(-1))
assert_equal(Rational(-1,1), -Rational(1,1))
assert_equal(Rational(1,1), -Rational(-1,1))
assert_equal(Rational(1,1), -Rational(1,-1))
assert_equal(Rational(-1,1), -Rational(-1,-1))
=begin
assert_equal(0, Rational(0).negate)
assert_equal(-2, Rational(2).negate)
assert_equal(2, Rational(-2).negate)
=end
end
def test_add
c = Rational(1,2)
c2 = Rational(2,3)
assert_equal(Rational(7,6), c + c2)
assert_equal(Rational(5,2), c + 2)
assert_equal(2.5, c + 2.0)
end
def test_sub
c = Rational(1,2)
c2 = Rational(2,3)
assert_equal(Rational(-1,6), c - c2)
assert_equal(Rational(-3,2), c - 2)
assert_equal(-1.5, c - 2.0)
end
def test_mul
c = Rational(1,2)
c2 = Rational(2,3)
assert_equal(Rational(1,3), c * c2)
assert_equal(Rational(1,1), c * 2)
assert_equal(1.0, c * 2.0)
end
def test_div
c = Rational(1,2)
c2 = Rational(2,3)
assert_equal(Rational(3,4), c / c2)
assert_equal(Rational(1,4), c / 2)
assert_equal(0.25, c / 2.0)
end
def assert_eql(exp, act, *args)
unless Array === exp
exp = [exp]
end
unless Array === act
act = [act]
end
exp.zip(act).each do |e, a|
na = [e, a] + args
assert_equal(*na)
na = [e.class, a] + args
assert_instance_of(*na)
end
end
def test_idiv
c = Rational(1,2)
c2 = Rational(2,3)
assert_eql(0, c.div(c2))
assert_eql(0, c.div(2))
assert_eql(0, c.div(2.0))
c = Rational(301,100)
c2 = Rational(7,5)
assert_equal(2, c.div(c2))
assert_equal(-3, c.div(-c2))
assert_equal(-3, (-c).div(c2))
assert_equal(2, (-c).div(-c2))
c = Rational(301,100)
c2 = Rational(2)
assert_equal(1, c.div(c2))
assert_equal(-2, c.div(-c2))
assert_equal(-2, (-c).div(c2))
assert_equal(1, (-c).div(-c2))
unless defined?(Rational::Unify)
c = Rational(11)
c2 = Rational(3)
assert_equal(3, c.div(c2))
assert_equal(-4, c.div(-c2))
assert_equal(-4, (-c).div(c2))
assert_equal(3, (-c).div(-c2))
end
end
def test_divmod
c = Rational(1,2)
c2 = Rational(2,3)
assert_eql([0, Rational(1,2)], c.divmod(c2))
assert_eql([0, Rational(1,2)], c.divmod(2))
assert_eql([0, 0.5], c.divmod(2.0))
c = Rational(301,100)
c2 = Rational(7,5)
assert_equal([2, Rational(21,100)], c.divmod(c2))
assert_equal([-3, Rational(-119,100)], c.divmod(-c2))
assert_equal([-3, Rational(119,100)], (-c).divmod(c2))
assert_equal([2, Rational(-21,100)], (-c).divmod(-c2))
c = Rational(301,100)
c2 = Rational(2)
assert_equal([1, Rational(101,100)], c.divmod(c2))
assert_equal([-2, Rational(-99,100)], c.divmod(-c2))
assert_equal([-2, Rational(99,100)], (-c).divmod(c2))
assert_equal([1, Rational(-101,100)], (-c).divmod(-c2))
unless defined?(Rational::Unify)
c = Rational(11)
c2 = Rational(3)
assert_equal([3,2], c.divmod(c2))
assert_equal([-4,-1], c.divmod(-c2))
assert_equal([-4,1], (-c).divmod(c2))
assert_equal([3,-2], (-c).divmod(-c2))
end
end
=begin
def test_quot
c = Rational(1,2)
c2 = Rational(2,3)
assert_eql(0, c.quot(c2))
assert_eql(0, c.quot(2))
assert_eql(0, c.quot(2.0))
c = Rational(301,100)
c2 = Rational(7,5)
assert_equal(2, c.quot(c2))
assert_equal(-2, c.quot(-c2))
assert_equal(-2, (-c).quot(c2))
assert_equal(2, (-c).quot(-c2))
c = Rational(301,100)
c2 = Rational(2)
assert_equal(1, c.quot(c2))
assert_equal(-1, c.quot(-c2))
assert_equal(-1, (-c).quot(c2))
assert_equal(1, (-c).quot(-c2))
unless defined?(Rational::Unify)
c = Rational(11)
c2 = Rational(3)
assert_equal(3, c.quot(c2))
assert_equal(-3, c.quot(-c2))
assert_equal(-3, (-c).quot(c2))
assert_equal(3, (-c).quot(-c2))
end
end
def test_quotrem
c = Rational(1,2)
c2 = Rational(2,3)
assert_eql([0, Rational(1,2)], c.quotrem(c2))
assert_eql([0, Rational(1,2)], c.quotrem(2))
assert_eql([0, 0.5], c.quotrem(2.0))
c = Rational(301,100)
c2 = Rational(7,5)
assert_equal([2, Rational(21,100)], c.quotrem(c2))
assert_equal([-2, Rational(21,100)], c.quotrem(-c2))
assert_equal([-2, Rational(-21,100)], (-c).quotrem(c2))
assert_equal([2, Rational(-21,100)], (-c).quotrem(-c2))
c = Rational(301,100)
c2 = Rational(2)
assert_equal([1, Rational(101,100)], c.quotrem(c2))
assert_equal([-1, Rational(101,100)], c.quotrem(-c2))
assert_equal([-1, Rational(-101,100)], (-c).quotrem(c2))
assert_equal([1, Rational(-101,100)], (-c).quotrem(-c2))
unless defined?(Rational::Unify)
c = Rational(11)
c2 = Rational(3)
assert_equal([3,2], c.quotrem(c2))
assert_equal([-3,2], c.quotrem(-c2))
assert_equal([-3,-2], (-c).quotrem(c2))
assert_equal([3,-2], (-c).quotrem(-c2))
end
end
=end
def test_quo
c = Rational(1,2)
c2 = Rational(2,3)
assert_equal(Rational(3,4), c.quo(c2))
assert_equal(Rational(1,4), c.quo(2))
assert_equal(Rational(0.25), c.quo(2.0))
end
def test_rdiv
c = Rational(1,2)
c2 = Rational(2,3)
assert_equal(Rational(3,4), c.rdiv(c2))
assert_equal(Rational(1,4), c.rdiv(2))
assert_equal(Rational(0.25), c.rdiv(2.0))
end
def test_fdiv
c = Rational(1,2)
c2 = Rational(2,3)
assert_equal(0.75, c.fdiv(c2))
assert_equal(0.25, c.fdiv(2))
assert_equal(0.25, c.fdiv(2.0))
end
def test_expt
c = Rational(1,2)
c2 = Rational(2,3)
r = c ** c2
assert_in_delta(0.6299, r, 0.001)
assert_equal(Rational(1,4), c ** 2)
assert_equal(Rational(4), c ** -2)
assert_equal(Rational(1,4), (-c) ** 2)
assert_equal(Rational(4), (-c) ** -2)
assert_equal(0.25, c ** 2.0)
assert_equal(4.0, c ** -2.0)
assert_equal(Rational(1,4), c ** Rational(2))
assert_equal(Rational(4), c ** Rational(-2))
assert_equal(Rational(1), 0 ** Rational(0))
assert_equal(Rational(1), Rational(0) ** 0)
assert_equal(Rational(1), Rational(0) ** Rational(0))
# p ** p
x = 2 ** Rational(2)
assert_equal(Rational(4), x)
unless defined?(Rational::Unify)
assert_instance_of(Rational, x)
end
assert_equal(4, x.numerator)
assert_equal(1, x.denominator)
x = Rational(2) ** 2
assert_equal(Rational(4), x)
unless defined?(Rational::Unify)
assert_instance_of(Rational, x)
end
assert_equal(4, x.numerator)
assert_equal(1, x.denominator)
x = Rational(2) ** Rational(2)
assert_equal(Rational(4), x)
unless defined?(Rational::Unify)
assert_instance_of(Rational, x)
end
assert_equal(4, x.numerator)
assert_equal(1, x.denominator)
# -p ** p
x = (-2) ** Rational(2)
assert_equal(Rational(4), x)
unless defined?(Rational::Unify)
assert_instance_of(Rational, x)
end
assert_equal(4, x.numerator)
assert_equal(1, x.denominator)
x = Rational(-2) ** 2
assert_equal(Rational(4), x)
unless defined?(Rational::Unify)
assert_instance_of(Rational, x)
end
assert_equal(4, x.numerator)
assert_equal(1, x.denominator)
x = Rational(-2) ** Rational(2)
assert_equal(Rational(4), x)
unless defined?(Rational::Unify)
assert_instance_of(Rational, x)
end
assert_equal(4, x.numerator)
assert_equal(1, x.denominator)
# p ** -p
x = 2 ** Rational(-2)
assert_equal(Rational(1,4), x)
assert_instance_of(Rational, x)
assert_equal(1, x.numerator)
assert_equal(4, x.denominator)
x = Rational(2) ** -2
assert_equal(Rational(1,4), x)
assert_instance_of(Rational, x)
assert_equal(1, x.numerator)
assert_equal(4, x.denominator)
x = Rational(2) ** Rational(-2)
assert_equal(Rational(1,4), x)
assert_instance_of(Rational, x)
assert_equal(1, x.numerator)
assert_equal(4, x.denominator)
# -p ** -p
x = (-2) ** Rational(-2)
assert_equal(Rational(1,4), x)
assert_instance_of(Rational, x)
assert_equal(1, x.numerator)
assert_equal(4, x.denominator)
x = Rational(-2) ** -2
assert_equal(Rational(1,4), x)
assert_instance_of(Rational, x)
assert_equal(1, x.numerator)
assert_equal(4, x.denominator)
x = Rational(-2) ** Rational(-2)
assert_equal(Rational(1,4), x)
assert_instance_of(Rational, x)
assert_equal(1, x.numerator)
assert_equal(4, x.denominator)
end
def test_cmp
assert_equal(-1, Rational(-1) <=> Rational(0))
assert_equal(0, Rational(0) <=> Rational(0))
assert_equal(+1, Rational(+1) <=> Rational(0))
assert_equal(-1, Rational(-1) <=> 0)
assert_equal(0, Rational(0) <=> 0)
assert_equal(+1, Rational(+1) <=> 0)
assert_equal(-1, Rational(-1) <=> 0.0)
assert_equal(0, Rational(0) <=> 0.0)
assert_equal(+1, Rational(+1) <=> 0.0)
assert_equal(-1, Rational(1,2) <=> Rational(2,3))
assert_equal(0, Rational(2,3) <=> Rational(2,3))
assert_equal(+1, Rational(2,3) <=> Rational(1,2))
f = 2**30-1
b = 2**30
assert_equal(0, Rational(f) <=> Rational(f))
assert_equal(-1, Rational(f) <=> Rational(b))
assert_equal(+1, Rational(b) <=> Rational(f))
assert_equal(0, Rational(b) <=> Rational(b))
assert_equal(-1, Rational(f-1) <=> Rational(f))
assert_equal(+1, Rational(f) <=> Rational(f-1))
assert_equal(-1, Rational(b-1) <=> Rational(b))
assert_equal(+1, Rational(b) <=> Rational(b-1))
assert_equal(false, Rational(0) < Rational(0))
assert_equal(true, Rational(0) <= Rational(0))
assert_equal(true, Rational(0) >= Rational(0))
assert_equal(false, Rational(0) > Rational(0))
end
def test_equal
assert(Rational(1,1) == Rational(1))
assert(Rational(1,1) == Rational.__send__(:new, 1))
assert(Rational(1,1) == Rational.__send__(:new, 1,1))
assert(Rational(1,1) == Rational.__send__(:new!, 1))
assert(Rational(1,1) == Rational.__send__(:new!, 1,1))
assert(Rational(-1,1) == Rational(-1))
assert(Rational(-1,1) == Rational.__send__(:new, -1))
assert(Rational(-1,1) == Rational.__send__(:new, -1,1))
assert(Rational(-1,1) == Rational.__send__(:new!, -1))
assert(Rational(-1,1) == Rational.__send__(:new!, -1,1))
assert_equal(false, Rational(2,1) == Rational(1))
assert_equal(true, Rational(2,1) != Rational(1))
assert_equal(false, Rational(1) == nil)
assert_equal(false, Rational(1) == '')
end
def test_unify
if defined?(Rational::Unify)
assert_instance_of(Fixnum, Rational(1,2) + Rational(1,2))
assert_instance_of(Fixnum, Rational(1,2) - Rational(1,2))
assert_instance_of(Fixnum, Rational(1,2) * 2)
assert_instance_of(Fixnum, Rational(1,2) / Rational(1,2))
assert_instance_of(Fixnum, Rational(1,2).div(Rational(1,2)))
assert_instance_of(Fixnum, Rational(1,2).quo(Rational(1,2)))
assert_instance_of(Fixnum, Rational(1,2) ** -2)
end
end
def test_to_s
c = Rational(1,2)
assert_instance_of(String, c.to_s)
assert_equal('1/2', c.to_s)
assert_equal('0', Rational(0,2).to_s)
assert_equal('0', Rational(0,-2).to_s)
assert_equal('1/2', Rational(1,2).to_s)
assert_equal('-1/2', Rational(-1,2).to_s)
assert_equal('1/2', Rational(-1,-2).to_s)
assert_equal('-1/2', Rational(1,-2).to_s)
assert_equal('1/2', Rational(-1,-2).to_s)
end
def test_inspect
c = Rational(1,2)
assert_instance_of(String, c.inspect)
assert_equal('Rational(1, 2)', c.inspect)
end
def test_marshal
c = Rational(1,2)
s = Marshal.dump(c)
c2 = Marshal.load(s)
assert_equal(c, c2)
assert_instance_of(Rational, c2)
end
def test_parse
assert_equal(Rational(0), ''.to_r)
assert_equal(Rational(0), ' '.to_r)
assert_equal(Rational(5), '5'.to_r)
assert_equal(Rational(-5), '-5'.to_r)
assert_equal(Rational(5,3), '5/3'.to_r)
assert_equal(Rational(-5,3), '-5/3'.to_r)
assert_equal(Rational(5,-3), '5/-3'.to_r)
assert_equal(Rational(-5,-3), '-5/-3'.to_r)
assert_equal(Rational(5), '5.0'.to_r)
assert_equal(Rational(-5), '-5.0'.to_r)
assert_equal(Rational(5,3), '5.0/3'.to_r)
assert_equal(Rational(-5,3), '-5.0/3'.to_r)
assert_equal(Rational(5,-3), '5.0/-3'.to_r)
assert_equal(Rational(-5,-3), '-5.0/-3'.to_r)
assert_equal(Rational(5), '5e0'.to_r)
assert_equal(Rational(-5), '-5e0'.to_r)
assert_equal(Rational(5,3), '5e0/3'.to_r)
assert_equal(Rational(-5,3), '-5e0/3'.to_r)
assert_equal(Rational(5,-3), '5e0/-3'.to_r)
assert_equal(Rational(-5,-3), '-5e0/-3'.to_r)
assert_equal(Rational(33,100), '0.33'.to_r)
assert_equal(Rational(-33,100), '-0.33'.to_r)
assert_equal(Rational(-33,100), '-0.3_3'.to_r)
assert_equal(Rational(1,2), '5e-1'.to_r)
assert_equal(Rational(50), '5e+1'.to_r)
assert_equal(Rational(1,2), '5.0e-1'.to_r)
assert_equal(Rational(50), '5.0e+1'.to_r)
assert_equal(Rational(50), '5e1'.to_r)
assert_equal(Rational(50), '5E1'.to_r)
assert_equal(Rational(500), '5e2'.to_r)
assert_equal(Rational(5000), '5e3'.to_r)
assert_equal(Rational(500000000000), '5e1_1'.to_r)
assert_equal(Rational(5), Rational('5'))
assert_equal(Rational(-5), Rational('-5'))
assert_equal(Rational(5,3), Rational('5/3'))
assert_equal(Rational(-5,3), Rational('-5/3'))
assert_equal(Rational(5,-3), Rational('5/-3'))
assert_equal(Rational(-5,-3), Rational('-5/-3'))
assert_equal(Rational(33,100), Rational('0.33'))
assert_equal(Rational(-33,100), Rational('-0.33'))
assert_equal(Rational(-33,100), Rational('-0.3_3'))
assert_equal(Rational(1,2), Rational('5e-1'))
assert_equal(Rational(50), Rational('5e1'))
assert_equal(Rational(50), Rational('5E1'))
assert_equal(Rational(500), Rational('5e2'))
assert_equal(Rational(5000), Rational('5e3'))
assert_equal(Rational(500000000000), Rational('5e1_1'))
assert_equal(Rational(5.0), Rational('5.0'))
assert_equal(Rational(-5.0), Rational('-5.0'))
assert_equal(Rational(5.0,3), Rational('5.0/3'))
assert_equal(Rational(-5.0,3), Rational('-5.0/3'))
assert_equal(Rational(5.0,-3), Rational('5.0/-3'))
assert_equal(Rational(-5.0,-3), Rational('-5.0/-3'))
assert_equal(Rational(0), '_'.to_r)
assert_equal(Rational(0), '_5'.to_r)
assert_equal(Rational(5), '5_'.to_r)
assert_equal(Rational(5), '5x'.to_r)
assert_equal(Rational(5), '5/_3'.to_r)
assert_equal(Rational(5,3), '5/3_'.to_r)
assert_equal(Rational(5,3), '5/3.3'.to_r)
assert_equal(Rational(5,3), '5/3x'.to_r)
assert_raise(ArgumentError){ Rational('')}
assert_raise(ArgumentError){ Rational('_')}
assert_raise(ArgumentError){ Rational('_5')}
assert_raise(ArgumentError){ Rational('5_')}
assert_raise(ArgumentError){ Rational('5x')}
assert_raise(ArgumentError){ Rational('5/_3')}
assert_raise(ArgumentError){ Rational('5/3_')}
assert_raise(ArgumentError){ Rational('5/3.3')}
assert_raise(ArgumentError){ Rational('5/3x')}
end
=begin
def test_reciprocal
assert_equal(Rational(1,9), Rational(9,1).reciprocal)
assert_equal(Rational(9,1), Rational(1,9).reciprocal)
assert_equal(Rational(-1,9), Rational(-9,1).reciprocal)
assert_equal(Rational(-9,1), Rational(-1,9).reciprocal)
end
=end
def test_to_i
assert_equal(1, Rational(3,2).to_i)
assert_equal(1, Integer(Rational(3,2)))
end
def test_to_f
assert_equal(1.5, Rational(3,2).to_f)
assert_equal(1.5, Float(Rational(3,2)))
end
def test_to_c
if defined?(Complex) && !Complex.instance_variable_get('@RCS_ID')
if defined?(Rational::Unify)
assert_equal(Rational(3,2), Rational(3,2).to_c)
assert_equal(Rational(3,2), Complex(Rational(3,2)))
else
assert_equal(Complex(Rational(3,2)), Rational(3,2).to_c)
assert_equal(Complex(Rational(3,2)), Complex(Rational(3,2)))
end
end
end
def test_to_r
c = nil.to_r
assert_equal([0,1] , [c.numerator, c.denominator])
c = 0.to_r
assert_equal([0,1] , [c.numerator, c.denominator])
c = 1.to_r
assert_equal([1,1] , [c.numerator, c.denominator])
c = 1.1.to_r
assert_equal([2476979795053773, 2251799813685248],
[c.numerator, c.denominator])
c = Rational(1,2).to_r
assert_equal([1,2] , [c.numerator, c.denominator])
if defined?(Complex)
if Complex.instance_variable_get('@RCS_ID')
assert_raise(NoMethodError){Complex(1,2).to_r}
else
assert_raise(RangeError){Complex(1,2).to_r}
end
end
end
def test_prec
assert_equal(true, Rational < Precision)
c = Rational(3,2)
assert_eql(1, c.prec(Integer))
assert_eql(1.5, c.prec(Float))
assert_eql(c, c.prec(Rational))
end
def test_supp
assert_equal(true, 1.scalar?)
assert_equal(true, 1.1.scalar?)
if defined?(Complex)
assert_equal(1, 1.real)
assert_equal(0, 1.image)
assert_equal(0, 1.imag)
assert_equal(1.1, 1.1.real)
assert_equal(0, 1.1.image)
assert_equal(0, 1.1.imag)
assert_equal(0, 1.arg)
assert_equal(0, 1.angle)
assert_equal(0, 1.0.arg)
assert_equal(0, 1.0.angle)
assert_equal(Math::PI, -1.arg)
assert_equal(Math::PI, -1.angle)
assert_equal(Math::PI, -1.0.arg)
assert_equal(Math::PI, -1.0.angle)
assert_equal([1,0], 1.polar)
assert_equal([1, Math::PI], -1.polar)
assert_equal([1.0,0], 1.0.polar)
assert_equal([1.0, Math::PI], -1.0.polar)
assert_equal(1, 1.conjugate)
assert_equal(-1, -1.conjugate)
assert_equal(1, 1.conj)
assert_equal(-1, -1.conj)
assert_equal(1.1, 1.1.conjugate)
assert_equal(-1.1, -1.1.conjugate)
assert_equal(1.1, 1.1.conj)
assert_equal(-1.1, -1.1.conj)
end
assert_equal(1, 1.numerator)
assert_equal(9, 9.numerator)
assert_equal(1, 1.denominator)
assert_equal(1, 9.denominator)
assert_equal(1.0, 1.0.numerator)
assert_equal(9.0, 9.0.numerator)
assert_equal(1.0, 1.0.denominator)
assert_equal(1.0, 9.0.denominator)
=begin
assert_equal(Rational(1,9), 9.reciprocal)
assert_equal(Rational(1,9), 9.0.reciprocal)
assert_equal(Rational(1,9), 9.inverse)
assert_equal(Rational(1,9), 9.0.inverse)
=end
assert_equal(Rational(1,2), 1.quo(2))
assert_equal(Rational(5000000000), 10000000000.quo(2))
assert_equal(0.5, 1.0.quo(2))
assert_equal(Rational(1,4), Rational(1,2).quo(2))
assert_equal(Rational(1,2), 1.rdiv(2))
assert_equal(Rational(5000000000), 10000000000.rdiv(2))
assert_equal(Rational(1,2), 1.0.rdiv(2))
assert_equal(Rational(1,4), Rational(1,2).rdiv(2))
assert_equal(0.5, 1.fdiv(2))
assert_equal(5000000000.0, 10000000000.fdiv(2))
assert_equal(0.5, 1.0.fdiv(2))
assert_equal(0.25, Rational(1,2).fdiv(2))
end
def test_fixed_bug
if defined?(Rational::Unify)
assert_instance_of(Fixnum, Rational(1,2) ** 0) # mathn's bug
end
end
=begin
def test_known_bug
n = Float::MAX.to_i * 2
assert_equal(1.0, Rational(n + 2, n + 1).to_f, '[ruby-dev:33852]')
end
=end
end