зеркало из https://github.com/github/ruby.git
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:
Родитель
2694b2f937
Коммит
6125552c27
40
ChangeLog
40
ChangeLog
|
@ -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().
|
||||
|
|
21
bignum.c
21
bignum.c
|
@ -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 \
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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
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;
|
||||
|
|
4
inits.c
4
inits.c
|
@ -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();
|
||||
}
|
||||
|
|
644
lib/complex.rb
644
lib/complex.rb
|
@ -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
|
||||
|
||||
|
|
532
lib/rational.rb
532
lib/rational.rb
|
@ -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
|
||||
|
|
69
numeric.c
69
numeric.c
|
@ -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);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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
|
Загрузка…
Ссылка в новой задаче