diff --git a/ChangeLog b/ChangeLog index 1039aca736..f52247a972 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +Sat Apr 5 23:17:20 2008 Tadayoshi Funaba + + * lib/cmath.rb: new. + + * lib/complex.rb: depends lib/cmath.rb. + + * lib/rational.rb: added rdiv. + + * complex.c: removed some math functions. + Sat Apr 5 05:50:57 2008 Eric Hodel * lib/rdoc/parsers/parse_rb.rb: Fix uninitialized variable warnings. diff --git a/complex.c b/complex.c index fdf4719551..fc42a04b84 100644 --- a/complex.c +++ b/complex.c @@ -474,47 +474,29 @@ nucomp_f_complex(int argc, VALUE *argv, VALUE klass) return rb_funcall2(rb_cComplex, id_convert, argc, argv); } -#if 1 -/* the following code is copied from math.c */ +extern VALUE math_atan2(VALUE obj, VALUE x, VALUE y); +extern VALUE math_cos(VALUE obj, VALUE x); +extern VALUE math_cosh(VALUE obj, VALUE x); +extern VALUE math_exp(VALUE obj, VALUE x); +extern VALUE math_log(int argc, VALUE *argv); +extern VALUE math_sin(VALUE obj, VALUE x); +extern VALUE math_sinh(VALUE obj, VALUE x); +extern VALUE math_sqrt(VALUE obj, VALUE x); -#include - -#define Need_Float(x) (x) = rb_Float(x) -#define Need_Float2(x,y) do {\ - Need_Float(x);\ - Need_Float(y);\ -} while (0) - -static void -domain_check(double x, char *msg) -{ - while(1) { - if (errno) { - rb_sys_fail(msg); - } - if (isnan(x)) { -#if defined(EDOM) - errno = EDOM; -#elif defined(ERANGE) - errno = ERANGE; -#endif - continue; - } - break; - } -} +#define m_atan2_bang(x,y) math_atan2(Qnil,x,y) +#define m_cos_bang(x) math_cos(Qnil,x) +#define m_cosh_bang(x) math_cosh(Qnil,x) +#define m_exp_bang(x) math_exp(Qnil,x) static VALUE -m_cos_bang(VALUE x) +m_log_bang(VALUE x) { - Need_Float(x); - return DOUBLE2NUM(cos(RFLOAT_VALUE(x))); + return math_log(1, &x); } -static VALUE m_cos_bang(VALUE); -static VALUE m_cosh_bang(VALUE); -static VALUE m_sin_bang(VALUE); -static VALUE m_sinh_bang(VALUE); +#define m_sin_bang(x) math_sin(Qnil,x) +#define m_sinh_bang(x) math_sinh(Qnil,x) +#define m_sqrt_bang(x) math_sqrt(Qnil,x) static VALUE m_cos(VALUE x) @@ -531,47 +513,6 @@ m_cos(VALUE x) m_sinh_bang(dat->image))); } -#ifndef HAVE_COSH -double -cosh(double x) -{ - return (exp(x) + exp(-x)) / 2; -} -#endif - -static VALUE -m_cosh_bang(VALUE x) -{ - Need_Float(x); - return DOUBLE2NUM(cosh(RFLOAT_VALUE(x))); -} - -static VALUE -m_exp_bang(VALUE x) -{ - Need_Float(x); - return DOUBLE2NUM(exp(RFLOAT_VALUE(x))); -} - -static VALUE -m_log_bang(VALUE x) -{ - double d; - - Need_Float(x); - errno = 0; - d = log(RFLOAT_VALUE(x)); - domain_check(d, "log"); - return DOUBLE2NUM(d); -} - -static VALUE -m_sin_bang(VALUE x) -{ - Need_Float(x); - return DOUBLE2NUM(sin(RFLOAT_VALUE(x))); -} - static VALUE m_sin(VALUE x) { @@ -587,33 +528,6 @@ m_sin(VALUE x) m_sinh_bang(dat->image))); } -#ifndef HAVE_SINH -double -sinh(double x) -{ - return (exp(x) - exp(-x)) / 2; -} -#endif - -static VALUE -m_sinh_bang(VALUE x) -{ - Need_Float(x); - return DOUBLE2NUM(sinh(RFLOAT_VALUE(x))); -} - -static VALUE -m_sqrt_bang(VALUE x) -{ - double d; - - Need_Float(x); - errno = 0; - d = sqrt(RFLOAT_VALUE(x)); - domain_check(d, "sqrt"); - return DOUBLE2NUM(d); -} - static VALUE m_sqrt(VALUE x) { @@ -636,23 +550,6 @@ m_sqrt(VALUE x) } } -static VALUE -m_atan2_bang(VALUE y, VALUE x) -{ - Need_Float2(y, x); - return DOUBLE2NUM(atan2(RFLOAT_VALUE(y), RFLOAT_VALUE(x))); -} - -#if 0 -static VALUE -m_hypot(VALUE x, VALUE y) -{ - Need_Float2(x, y); - return DOUBLE2NUM(hypot(RFLOAT_VALUE(x), RFLOAT_VALUE(y))); -} -#endif -#endif - static VALUE nucomp_s_polar(VALUE klass, VALUE abs, VALUE arg) { diff --git a/lib/cmath.rb b/lib/cmath.rb new file mode 100644 index 0000000000..158da4175d --- /dev/null +++ b/lib/cmath.rb @@ -0,0 +1,223 @@ +module CMath + + include Math + + alias exp! exp + alias log! log + alias log10! log10 + alias sqrt! sqrt + + alias sin! sin + alias cos! cos + alias tan! tan + + alias sinh! sinh + alias cosh! cosh + alias tanh! tanh + + alias asin! asin + alias acos! acos + alias atan! atan + alias atan2! atan2 + + 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 + sqrt!(z) + else + Complex(0,sqrt!(-z)) + end + else + if z.image < 0 + sqrt(z.conjugate).conjugate + else + r = z.abs + x = z.real + Complex(sqrt!((r + x) / 2), sqrt!((r - x) / 2)) + end + end + end + + def sin(z) + if Complex.generic?(z) + sin!(z) + else + Complex(sin!(z.real) * cosh!(z.image), + cos!(z.real) * sinh!(z.image)) + end + end + + 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) + else + sin(z)/cos(z) + end + end + + def sinh(z) + if Complex.generic?(z) + sinh!(z) + else + Complex(sinh!(z.real) * cos!(z.image), + cosh!(z.real) * sin!(z.image)) + end + end + + def cosh(z) + if Complex.generic?(z) + cosh!(z) + else + Complex(cosh!(z.real) * cos!(z.image), + sinh!(z.real) * sin!(z.image)) + end + end + + def tanh(z) + if Complex.generic?(z) + tanh!(z) + else + sinh(z) / cosh(z) + end + end + + def asin(z) + 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)) + 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 + + def atan(z) + if Complex.generic?(z) + atan!(z) + else + 1.0.im * log((1.0.im + z) / (1.0.im - z)) / 2.0 + end + end + + def atan2(y,x) + 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)) + end + end + + def acosh(z) + if Complex.generic?(z) and z >= 1 + acosh!(z) + else + log(z + sqrt(z * z - 1.0)) + end + end + + def asinh(z) + if Complex.generic?(z) + asinh!(z) + else + log(z + sqrt(1.0 + z * z)) + end + end + + def atanh(z) + if Complex.generic?(z) and z >= -1 and z <= 1 + atanh!(z) + else + log((1.0 + z) / (1.0 - z)) / 2.0 + end + end + + module_function :exp! + module_function :exp + module_function :log! + module_function :log + module_function :log10! + module_function :log10 + 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 :asin! + module_function :asin + module_function :acos! + module_function :acos + module_function :atan! + module_function :atan + module_function :atan2! + module_function :atan2 + + module_function :asinh! + module_function :asinh + module_function :acosh! + module_function :acosh + module_function :atanh! + module_function :atanh + +end diff --git a/lib/complex.rb b/lib/complex.rb index 9d926023a7..a585e95d97 100644 --- a/lib/complex.rb +++ b/lib/complex.rb @@ -1,3 +1,8 @@ +require 'cmath' + +Math = CMath + +=begin module Math alias exp! exp @@ -219,3 +224,4 @@ module Math module_function :atanh end +=end diff --git a/lib/rational.rb b/lib/rational.rb index 87c5d3f111..24774c357b 100644 --- a/lib/rational.rb +++ b/lib/rational.rb @@ -4,6 +4,7 @@ class Fixnum alias power! ** alias rpower ** + alias rdiv quo end @@ -13,5 +14,6 @@ class Bignum alias power! ** alias rpower ** + alias rdiv quo end diff --git a/math.c b/math.c index 1f78d98a55..815d9e72ff 100644 --- a/math.c +++ b/math.c @@ -50,7 +50,7 @@ domain_check(double x, char *msg) * */ -static VALUE +VALUE math_atan2(VALUE obj, VALUE y, VALUE x) { Need_Float2(y, x); @@ -66,7 +66,7 @@ math_atan2(VALUE obj, VALUE y, VALUE x) * -1..1. */ -static VALUE +VALUE math_cos(VALUE obj, VALUE x) { Need_Float(x); @@ -81,7 +81,7 @@ math_cos(VALUE obj, VALUE x) * -1..1. */ -static VALUE +VALUE math_sin(VALUE obj, VALUE x) { Need_Float(x); @@ -172,7 +172,7 @@ cosh(double x) * Computes the hyperbolic cosine of x (expressed in radians). */ -static VALUE +VALUE math_cosh(VALUE obj, VALUE x) { Need_Float(x); @@ -196,7 +196,7 @@ sinh(double x) * radians). */ -static VALUE +VALUE math_sinh(VALUE obj, VALUE x) { Need_Float(x); @@ -285,7 +285,7 @@ math_atanh(VALUE obj, VALUE x) * Returns e**x. */ -static VALUE +VALUE math_exp(VALUE obj, VALUE x) { Need_Float(x); @@ -311,7 +311,7 @@ math_exp(VALUE obj, VALUE x) * of logarithm. */ -static VALUE +VALUE math_log(int argc, VALUE *argv) { VALUE x, base; @@ -388,7 +388,7 @@ math_log10(VALUE obj, VALUE x) * Returns the non-negative square root of numeric. */ -static VALUE +VALUE math_sqrt(VALUE obj, VALUE x) { double d; diff --git a/rational.c b/rational.c index de5c7867c3..2cfe9288be 100644 --- a/rational.c +++ b/rational.c @@ -777,13 +777,9 @@ nurat_mul(VALUE self, VALUE other) } } -#define id_to_r rb_intern("to_r") -#define f_to_r(x) rb_funcall(x, id_to_r, 0) - static VALUE nurat_div(VALUE self, VALUE other) { - again: switch (TYPE(other)) { case T_FIXNUM: case T_BIGNUM: @@ -1407,6 +1403,9 @@ string_to_r(VALUE self) return rb_rational_new1(INT2FIX(0)); } +#define id_to_r rb_intern("to_r") +#define f_to_r(x) rb_funcall(x, id_to_r, 0) + static VALUE nurat_s_convert(int argc, VALUE *argv, VALUE klass) {