From 8f40b265811a23eef5b8c9e0b677b7d15cd6ea45 Mon Sep 17 00:00:00 2001 From: tadf Date: Fri, 22 Aug 2008 12:27:54 +0000 Subject: * complex.c (nucomp_div): now behaves as quo. * complex.c (nucomp_s_generic_p): has been removed. * complex.c (nucomp_to_s): adopts new form. * complex.c (nucomp_inspect): ditto. * complex.c (string_to_c_internal): ditto and supports polar form. * complex.c (rb_complex_polar): new. * rational.c (nurat_to_s): did not canonicalize. * rational.c (nurat_inspect): adopts new form. * rational.c (string_to_r_internal): ditto. * include/ruby/intern.h: added a declaration. * lib/complex.rb: added an obsolate class method. * lib/cmath.rb: use scalar? instead of generic?. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@18778 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- complex.c | 412 +++++++++++++++++++++++++++----------------------------------- 1 file changed, 179 insertions(+), 233 deletions(-) (limited to 'complex.c') diff --git a/complex.c b/complex.c index 707383ac30..da8945ea9f 100644 --- a/complex.c +++ b/complex.c @@ -250,26 +250,6 @@ k_complex_p(VALUE x) return f_kind_of_p(x, rb_cComplex); } -inline static VALUE -f_generic_p(VALUE x) -{ - switch (TYPE(x)) { - case T_FIXNUM: - case T_BIGNUM: - case T_FLOAT: - case T_RATIONAL: - return Qtrue; - default: - return Qfalse; - } -} - -static VALUE -nucomp_s_generic_p(VALUE klass, VALUE x) -{ - return f_generic_p(x); -} - #define get_dat1(x) \ struct RComplex *dat;\ dat = ((struct RComplex *)(x)) @@ -322,12 +302,15 @@ nucomp_s_new_bang(int argc, VALUE *argv, VALUE klass) inline static VALUE f_complex_new_bang1(VALUE klass, VALUE x) { + assert(!k_complex_p(x)); return nucomp_s_new_internal(klass, x, ZERO); } inline static VALUE f_complex_new_bang2(VALUE klass, VALUE x, VALUE y) { + assert(!k_complex_p(x)); + assert(!k_complex_p(y)); return nucomp_s_new_internal(klass, x, y); } @@ -343,7 +326,8 @@ nucomp_real_check(VALUE num) case T_RATIONAL: break; default: - rb_raise(rb_eArgError, "not a real"); + if (!k_numeric_p(num) || !f_scalar_p(num)) + rb_raise(rb_eArgError, "not a real"); } } @@ -459,7 +443,7 @@ extern VALUE math_sqrt(VALUE obj, VALUE x); static VALUE m_log_bang(VALUE x) { - return math_log(1, &x); + return math_log(1, &x); } #define m_sin_bang(x) math_sin(Qnil,x) @@ -471,7 +455,7 @@ m_cos(VALUE x) { get_dat1(x); - if (f_generic_p(x)) + if (f_scalar_p(x)) return m_cos_bang(x); return f_complex_new2(rb_cComplex, f_mul(m_cos_bang(dat->real), @@ -485,7 +469,7 @@ m_sin(VALUE x) { get_dat1(x); - if (f_generic_p(x)) + if (f_scalar_p(x)) return m_sin_bang(x); return f_complex_new2(rb_cComplex, f_mul(m_sin_bang(dat->real), @@ -497,7 +481,7 @@ m_sin(VALUE x) static VALUE m_sqrt(VALUE x) { - if (f_generic_p(x)) { + if (f_scalar_p(x)) { if (!f_negative_p(x)) return m_sqrt_bang(x); return f_complex_new2(rb_cComplex, ZERO, m_sqrt_bang(f_negate(x))); @@ -516,12 +500,20 @@ m_sqrt(VALUE x) } } +inline static VALUE +f_complex_polar(VALUE klass, VALUE x, VALUE y) +{ + assert(!k_complex_p(x)); + assert(!k_complex_p(y)); + return nucomp_s_canonicalize_internal(klass, + f_mul(x, m_cos(y)), + f_mul(x, m_sin(y))); +} + static VALUE nucomp_s_polar(VALUE klass, VALUE abs, VALUE arg) { - return f_complex_new2(klass, - f_mul(abs, m_cos(arg)), - f_mul(abs, m_sin(arg))); + return f_complex_polar(klass, abs, arg); } static VALUE @@ -541,142 +533,105 @@ nucomp_image(VALUE self) static VALUE nucomp_add(VALUE self, VALUE other) { - switch (TYPE(other)) { - case T_FIXNUM: - case T_BIGNUM: - case T_FLOAT: - case T_RATIONAL: - { - get_dat1(self); + if (k_complex_p(other)) { + VALUE real, image; - return f_complex_new2(CLASS_OF(self), - f_add(dat->real, other), dat->image); - } - case T_COMPLEX: - { - VALUE real, image; + get_dat2(self, other); - get_dat2(self, other); + real = f_add(adat->real, bdat->real); + image = f_add(adat->image, bdat->image); - real = f_add(adat->real, bdat->real); - image = f_add(adat->image, bdat->image); + return f_complex_new2(CLASS_OF(self), real, image); + } + if (k_numeric_p(other) && f_scalar_p(other)) { + get_dat1(self); - return f_complex_new2(CLASS_OF(self), real, image); - } - default: - return rb_num_coerce_bin(self, other, '+'); + return f_complex_new2(CLASS_OF(self), + f_add(dat->real, other), dat->image); } + return rb_num_coerce_bin(self, other, '+'); } static VALUE nucomp_sub(VALUE self, VALUE other) { - switch (TYPE(other)) { - case T_FIXNUM: - case T_BIGNUM: - case T_FLOAT: - case T_RATIONAL: - { - get_dat1(self); + if (k_complex_p(other)) { + VALUE real, image; - return f_complex_new2(CLASS_OF(self), - f_sub(dat->real, other), dat->image); - } - case T_COMPLEX: - { - VALUE real, image; + get_dat2(self, other); - get_dat2(self, other); + real = f_sub(adat->real, bdat->real); + image = f_sub(adat->image, bdat->image); - real = f_sub(adat->real, bdat->real); - image = f_sub(adat->image, bdat->image); + return f_complex_new2(CLASS_OF(self), real, image); + } + if (k_numeric_p(other) && f_scalar_p(other)) { + get_dat1(self); - return f_complex_new2(CLASS_OF(self), real, image); - } - default: - return rb_num_coerce_bin(self, other, '-'); + return f_complex_new2(CLASS_OF(self), + f_sub(dat->real, other), dat->image); } + return rb_num_coerce_bin(self, other, '-'); } static VALUE nucomp_mul(VALUE self, VALUE other) { - switch (TYPE(other)) { - case T_FIXNUM: - case T_BIGNUM: - case T_FLOAT: - case T_RATIONAL: - { - get_dat1(self); + if (k_complex_p(other)) { + VALUE real, image; - return f_complex_new2(CLASS_OF(self), - f_mul(dat->real, other), - f_mul(dat->image, other)); - } - case T_COMPLEX: - { - VALUE real, image; + get_dat2(self, other); - get_dat2(self, other); + real = f_sub(f_mul(adat->real, bdat->real), + f_mul(adat->image, bdat->image)); + image = f_add(f_mul(adat->real, bdat->image), + f_mul(adat->image, bdat->real)); - real = f_sub(f_mul(adat->real, bdat->real), - f_mul(adat->image, bdat->image)); - image = f_add(f_mul(adat->real, bdat->image), - f_mul(adat->image, bdat->real)); + return f_complex_new2(CLASS_OF(self), real, image); + } + if (k_numeric_p(other) && f_scalar_p(other)) { + get_dat1(self); - return f_complex_new2(CLASS_OF(self), real, image); - } - default: - return rb_num_coerce_bin(self, other, '*'); + return f_complex_new2(CLASS_OF(self), + f_mul(dat->real, other), + f_mul(dat->image, other)); } + return rb_num_coerce_bin(self, other, '*'); } +#define f_div f_quo + static VALUE nucomp_div(VALUE self, VALUE other) { - switch (TYPE(other)) { - case T_FIXNUM: - case T_BIGNUM: - case T_FLOAT: - case T_RATIONAL: - { - get_dat1(self); - - return f_complex_new2(CLASS_OF(self), - f_div(dat->real, other), - f_div(dat->image, other)); - } - case T_COMPLEX: - { - get_dat2(self, other); - - if (TYPE(adat->real) == T_FLOAT || - TYPE(adat->image) == T_FLOAT || - TYPE(bdat->real) == T_FLOAT || - TYPE(bdat->image) == T_FLOAT) { - VALUE magn = m_hypot(bdat->real, bdat->image); - VALUE tmp = f_complex_new_bang2(CLASS_OF(self), - f_div(bdat->real, magn), - f_div(bdat->image, magn)); - return f_div(f_mul(self, f_conjugate(tmp)), magn); - } - return f_div(f_mul(self, f_conjugate(other)), f_abs2(other)); + if (k_complex_p(other)) { + get_dat2(self, other); + + if (TYPE(adat->real) == T_FLOAT || + TYPE(adat->image) == T_FLOAT || + TYPE(bdat->real) == T_FLOAT || + TYPE(bdat->image) == T_FLOAT) { + VALUE magn = m_hypot(bdat->real, bdat->image); + VALUE tmp = f_complex_new_bang2(CLASS_OF(self), + f_div(bdat->real, magn), + f_div(bdat->image, magn)); + return f_div(f_mul(self, f_conjugate(tmp)), magn); } - default: - return rb_num_coerce_bin(self, other, '/'); + return f_div(f_mul(self, f_conjugate(other)), f_abs2(other)); } -} + if (k_numeric_p(other) && f_scalar_p(other)) { + get_dat1(self); -static VALUE -nucomp_quo(VALUE self, VALUE other) -{ - get_dat1(self); - - return f_div(f_complex_new2(CLASS_OF(self), - f_quo(dat->real, ONE), - f_quo(dat->image, ONE)), other); + return f_complex_new2(CLASS_OF(self), + f_div(dat->real, other), + f_div(dat->image, other)); + } + return rb_num_coerce_bin(self, other, '/'); } +#undef f_div +#define nucomp_quo nucomp_div + static VALUE nucomp_fdiv(VALUE self, VALUE other) { @@ -696,9 +651,23 @@ nucomp_expt(VALUE self, VALUE other) if (k_rational_p(other) && f_one_p(f_denominator(other))) other = f_numerator(other); /* good? */ - switch (TYPE(other)) { - case T_FIXNUM: - case T_BIGNUM: + if (k_complex_p(other)) { + VALUE a, r, theta, ore, oim, nr, ntheta; + + get_dat1(other); + + a = f_polar(self); + r = RARRAY_PTR(a)[0]; + theta = RARRAY_PTR(a)[1]; + + ore = dat->real; + oim = dat->image; + nr = m_exp_bang(f_sub(f_mul(ore, m_log_bang(r)), + f_mul(oim, theta))); + ntheta = f_add(f_mul(theta, ore), f_mul(oim, m_log_bang(r))); + return f_complex_polar(CLASS_OF(self), nr, ntheta); + } + if (k_integer_p(other)) { if (f_gt_p(other, ZERO)) { VALUE x, z, n; @@ -725,74 +694,41 @@ nucomp_expt(VALUE self, VALUE other) return z; } return f_expt(f_div(f_to_r(ONE), self), f_negate(other)); - case T_FLOAT: - case T_RATIONAL: - { - VALUE a, r, theta; - - a = f_polar(self); - r = RARRAY_PTR(a)[0]; - theta = RARRAY_PTR(a)[1]; - return nucomp_s_polar(CLASS_OF(self), f_expt(r, other), - f_mul(theta, other)); - } - case T_COMPLEX: - { - VALUE a, r, theta, ore, oim, nr, ntheta; - - get_dat1(other); - - a = f_polar(self); - r = RARRAY_PTR(a)[0]; - theta = RARRAY_PTR(a)[1]; - - ore = dat->real; - oim = dat->image; - nr = m_exp_bang(f_sub(f_mul(ore, m_log_bang(r)), - f_mul(oim, theta))); - ntheta = f_add(f_mul(theta, ore), f_mul(oim, m_log_bang(r))); - return nucomp_s_polar(CLASS_OF(self), nr, ntheta); - } - default: - return rb_num_coerce_bin(self, other, id_expt); } + if (k_numeric_p(other) && f_scalar_p(other)) { + VALUE a, r, theta; + + a = f_polar(self); + r = RARRAY_PTR(a)[0]; + theta = RARRAY_PTR(a)[1]; + return f_complex_polar(CLASS_OF(self), f_expt(r, other), + f_mul(theta, other)); + } + return rb_num_coerce_bin(self, other, id_expt); } static VALUE nucomp_equal_p(VALUE self, VALUE other) { - switch (TYPE(other)) { - case T_FIXNUM: - case T_BIGNUM: - case T_FLOAT: - case T_RATIONAL: - { - get_dat1(self); + if (k_complex_p(other)) { + get_dat2(self, other); - return f_boolcast(f_equal_p(dat->real, other) && f_zero_p(dat->image)); - } - case T_COMPLEX: - { - get_dat2(self, other); + return f_boolcast(f_equal_p(adat->real, bdat->real) && + f_equal_p(adat->image, bdat->image)); + } + if (k_numeric_p(other) && f_scalar_p(other)) { + get_dat1(self); - return f_boolcast(f_equal_p(adat->real, bdat->real) && - f_equal_p(adat->image, bdat->image)); - } - default: - return f_equal_p(other, self); + return f_boolcast(f_equal_p(dat->real, other) && f_zero_p(dat->image)); } + return f_equal_p(other, self); } static VALUE nucomp_coerce(VALUE self, VALUE other) { - switch (TYPE(other)) { - case T_FIXNUM: - case T_BIGNUM: - case T_FLOAT: - case T_RATIONAL: + if (k_numeric_p(other) && f_scalar_p(other)) return rb_assoc_new(f_complex_new_bang1(CLASS_OF(self), other), self); - } rb_raise(rb_eTypeError, "%s can't be coerced into %s", rb_obj_classname(other), rb_obj_classname(self)); @@ -918,12 +854,6 @@ f_signbit(VALUE x) return f_negative_p(x); } -inline static VALUE -f_tzero_p(VALUE x) -{ - return f_boolcast(f_zero_p(x) && !f_signbit(x)); -} - inline static VALUE f_tpositive_p(VALUE x) { @@ -933,30 +863,17 @@ f_tpositive_p(VALUE x) static VALUE nucomp_to_s(VALUE self) { - VALUE s, rezero, impos; + VALUE s, impos; get_dat1(self); - rezero = f_tzero_p(dat->real); impos = f_tpositive_p(dat->image); - if (rezero) - s = rb_str_new2(""); - else { - s = f_to_s(dat->real); - rb_str_cat2(s, !impos ? "-" : "+"); - } + s = f_to_s(dat->real); + rb_str_cat2(s, !impos ? "-" : "+"); - if (k_rational_p(dat->image) && - !f_one_p(f_denominator(dat->image))) { - rb_str_cat2(s, "("); - rb_str_concat(s, f_to_s(rezero ? dat->image : f_abs(dat->image))); - rb_str_cat2(s, ")i"); - } - else { - rb_str_concat(s, f_to_s(rezero ? dat->image : f_abs(dat->image))); - rb_str_cat2(s, "i"); - } + rb_str_concat(s, f_to_s(f_abs(dat->image))); + rb_str_cat2(s, "i"); return s; } @@ -964,15 +881,18 @@ nucomp_to_s(VALUE self) static VALUE nucomp_inspect(VALUE self) { - VALUE s; + VALUE s, impos; get_dat1(self); - s = rb_str_new2("Complex("); + impos = f_tpositive_p(dat->image); + + s = rb_str_new2("("); rb_str_concat(s, f_inspect(dat->real)); - rb_str_cat2(s, ", "); - rb_str_concat(s, f_inspect(dat->image)); - rb_str_cat2(s, ")"); + rb_str_cat2(s, !impos ? "-" : "+"); + + rb_str_concat(s, f_inspect(f_abs(dat->image))); + rb_str_cat2(s, "i)"); return s; } @@ -1007,6 +927,12 @@ rb_complex_new(VALUE x, VALUE y) return nucomp_s_canonicalize_internal(rb_cComplex, x, y); } +VALUE +rb_complex_polar(VALUE x, VALUE y) +{ + return nucomp_s_polar(rb_cComplex, x, y); +} + static VALUE nucomp_s_convert(int argc, VALUE *argv, VALUE klass); VALUE @@ -1075,25 +1001,30 @@ numeric_to_c(VALUE self) return rb_complex_new1(self); } -static VALUE comp_pat1, comp_pat2, a_slash, a_dot_and_an_e, +static VALUE comp_pat0, comp_pat1, comp_pat2, a_slash, a_dot_and_an_e, null_string, underscores_pat, an_underscore; #define DIGITS "(?:\\d(?:_\\d|\\d)*)" #define NUMERATOR "(?:" DIGITS "?\\.)?" DIGITS "(?:[eE][-+]?" DIGITS ")?" -#define DENOMINATOR "[-+]?" DIGITS +#define DENOMINATOR DIGITS #define NUMBER "[-+]?" NUMERATOR "(?:\\/" DENOMINATOR ")?" #define NUMBERNOS NUMERATOR "(?:\\/" DENOMINATOR ")?" -#define PATTERN1 "\\A((" NUMBER ")|\\((" NUMBER ")\\))?[iIjJ]" -#define PATTERN2 "\\A(" NUMBER ")(([-+])(?:(" NUMBERNOS ")|\\((" NUMBER ")\\))?[iIjJ])?" +#define PATTERN0 "\\A(" NUMBER ")@(" NUMBER ")" +#define PATTERN1 "\\A([-+])?(" NUMBER ")?[iIjJ]" +#define PATTERN2 "\\A(" NUMBER ")(([-+])(" NUMBERNOS ")?[iIjJ])?" static void make_patterns(void) { + static const char comp_pat0_source[] = PATTERN0; static const char comp_pat1_source[] = PATTERN1; static const char comp_pat2_source[] = PATTERN2; static const char underscores_pat_source[] = "_+"; - if (comp_pat1) return; + if (comp_pat0) return; + + comp_pat0 = rb_reg_new(comp_pat0_source, sizeof comp_pat0_source - 1, 0); + rb_global_variable(&comp_pat0); comp_pat1 = rb_reg_new(comp_pat1_source, sizeof comp_pat1_source - 1, 0); rb_global_variable(&comp_pat1); @@ -1154,19 +1085,33 @@ string_to_c_internal(VALUE self) { VALUE m, sr, si, re, r, i; + int po; - m = f_match(comp_pat1, s); + m = f_match(comp_pat0, s); if (!NIL_P(m)) { - sr = Qnil; - si = f_aref(m, INT2FIX(1)); - if (NIL_P(si)) - si = rb_str_new2("1"); - else { - si = f_aref(m, INT2FIX(2)); + sr = f_aref(m, INT2FIX(1)); + si = f_aref(m, INT2FIX(2)); + re = f_post_match(m); + po = 1; + } + if (NIL_P(m)) { + m = f_match(comp_pat1, s); + if (!NIL_P(m)) { + sr = Qnil; + si = f_aref(m, INT2FIX(1)); if (NIL_P(si)) - si = f_aref(m, INT2FIX(3)); + si = rb_str_new2(""); + { + VALUE t; + + t = f_aref(m, INT2FIX(2)); + if (NIL_P(t)) + t = rb_str_new2("1"); + rb_str_concat(si, t); + } + re = f_post_match(m); + po = 0; } - re = f_post_match(m); } if (NIL_P(m)) { m = f_match(comp_pat2, s); @@ -1181,13 +1126,12 @@ string_to_c_internal(VALUE self) si = f_aref(m, INT2FIX(3)); t = f_aref(m, INT2FIX(4)); - if (NIL_P(t)) - t = f_aref(m, INT2FIX(5)); if (NIL_P(t)) t = rb_str_new2("1"); rb_str_concat(si, t); } re = f_post_match(m); + po = 0; } r = INT2FIX(0); i = INT2FIX(0); @@ -1207,7 +1151,11 @@ string_to_c_internal(VALUE self) else i = f_to_i(si); } - return rb_assoc_new(rb_complex_new2(r, i), re); + if (po) + return rb_assoc_new(rb_complex_polar(r, i), re); + else + return rb_assoc_new(rb_complex_new2(r, i), re); + } } @@ -1410,8 +1358,6 @@ Init_Complex(void) rb_funcall(rb_cComplex, rb_intern("private_class_method"), 1, ID2SYM(rb_intern("allocate"))); - rb_define_singleton_method(rb_cComplex, "generic?", nucomp_s_generic_p, 1); - rb_define_singleton_method(rb_cComplex, "new!", nucomp_s_new_bang, -1); rb_funcall(rb_cComplex, rb_intern("private_class_method"), 1, ID2SYM(rb_intern("new!"))); -- cgit v1.2.3