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); }
static VALUE f_complex_polar(VALUE klass, VALUE x, VALUE y) { assert(!k_complex_p(x)); assert(!k_complex_p(y)); if (f_zero_p(x) || f_zero_p(y)) { if (canonicalization) return x; return nucomp_s_new_internal(klass, x, RFLOAT_0); } if (RB_FLOAT_TYPE_P(y)) { const double arg = RFLOAT_VALUE(y); if (arg == M_PI) { x = f_negate(x); if (canonicalization) return x; y = RFLOAT_0; } else if (arg == M_PI_2) { y = x; x = RFLOAT_0; } else if (arg == M_PI_2+M_PI) { y = f_negate(x); x = RFLOAT_0; } else if (RB_FLOAT_TYPE_P(x)) { const double abs = RFLOAT_VALUE(x); const double real = abs * cos(arg), imag = abs * sin(arg); x = DBL2NUM(real); if (canonicalization && imag == 0.0) return x; y = DBL2NUM(imag); } else { x = f_mul(x, DBL2NUM(cos(arg))); y = f_mul(y, DBL2NUM(sin(arg))); if (canonicalization && f_zero_p(y)) return x; } return nucomp_s_new_internal(klass, x, y); } return nucomp_s_canonicalize_internal(klass, f_mul(x, m_cos(y)), f_mul(x, m_sin(y))); }
inline static VALUE nucomp_s_canonicalize_internal(VALUE klass, VALUE real, VALUE imag) { #ifdef CANON #define CL_CANON #ifdef CL_CANON if (k_exact_zero_p(imag) && canonicalization) return real; #else if (f_zero_p(imag) && canonicalization) return real; #endif #endif if (f_real_p(real) && f_real_p(imag)) return nucomp_s_new_internal(klass, real, imag); else if (f_real_p(real)) { get_dat1(imag); return nucomp_s_new_internal(klass, f_sub(real, dat->imag), f_add(ZERO, dat->real)); } else if (f_real_p(imag)) { get_dat1(real); return nucomp_s_new_internal(klass, dat->real, f_add(dat->imag, imag)); } else { get_dat2(real, imag); return nucomp_s_new_internal(klass, f_sub(adat->real, bdat->imag), f_add(adat->imag, bdat->real)); } }
/* * call-seq: * Complex.polar(abs[, arg]) -> complex * * Returns a complex object which denotes the given polar form. * * Complex.polar(3, 0) #=> (3.0+0.0i) * Complex.polar(3, Math::PI/2) #=> (1.836909530733566e-16+3.0i) * Complex.polar(3, Math::PI) #=> (-3.0+3.673819061467132e-16i) * Complex.polar(3, -Math::PI/2) #=> (1.836909530733566e-16-3.0i) */ static VALUE nucomp_s_polar(int argc, VALUE *argv, VALUE klass) { VALUE abs, arg; switch (rb_scan_args(argc, argv, "11", &abs, &arg)) { case 1: nucomp_real_check(abs); if (canonicalization) return abs; return nucomp_s_new_internal(klass, abs, ZERO); default: nucomp_real_check(abs); nucomp_real_check(arg); break; } return f_complex_polar(klass, abs, arg); }
static VALUE nucomp_s_new_bang(int argc, VALUE *argv, VALUE klass) { VALUE real, imag; switch (rb_scan_args(argc, argv, "11", &real, &imag)) { case 1: if (!k_numeric_p(real)) real = f_to_i(real); imag = ZERO; break; default: if (!k_numeric_p(real)) real = f_to_i(real); if (!k_numeric_p(imag)) imag = f_to_i(imag); break; } return nucomp_s_new_internal(klass, real, imag); }
/* * call-seq: * cmp ** numeric -> complex * * Performs exponentiation. * * Complex('i') ** 2 #=> (-1+0i) * Complex(-8) ** Rational(1, 3) #=> (1.0000000000000002+1.7320508075688772i) */ static VALUE nucomp_expt(VALUE self, VALUE other) { if (k_numeric_p(other) && k_exact_zero_p(other)) return f_complex_new_bang1(CLASS_OF(self), ONE); if (k_rational_p(other) && f_one_p(f_denominator(other))) other = f_numerator(other); /* c14n */ if (k_complex_p(other)) { get_dat1(other); if (k_exact_zero_p(dat->imag)) other = dat->real; /* c14n */ } if (k_complex_p(other)) { VALUE r, theta, nr, ntheta; get_dat1(other); r = f_abs(self); theta = f_arg(self); nr = m_exp_bang(f_sub(f_mul(dat->real, m_log_bang(r)), f_mul(dat->imag, theta))); ntheta = f_add(f_mul(theta, dat->real), f_mul(dat->imag, m_log_bang(r))); return f_complex_polar(CLASS_OF(self), nr, ntheta); } if (k_fixnum_p(other)) { if (f_gt_p(other, ZERO)) { VALUE x, z; long n; x = self; z = x; n = FIX2LONG(other) - 1; while (n) { long q, r; while (1) { get_dat1(x); q = n / 2; r = n % 2; if (r) break; x = nucomp_s_new_internal(CLASS_OF(self), f_sub(f_mul(dat->real, dat->real), f_mul(dat->imag, dat->imag)), f_mul(f_mul(TWO, dat->real), dat->imag)); n = q; } z = f_mul(z, x); n--; } return z; } return f_expt(f_reciprocal(self), f_negate(other)); } if (k_numeric_p(other) && f_real_p(other)) { VALUE r, theta; if (k_bignum_p(other)) rb_warn("in a**b, b may be too big"); r = f_abs(self); theta = f_arg(self); return f_complex_polar(CLASS_OF(self), f_expt(r, other), f_mul(theta, other)); } return rb_num_coerce_bin(self, other, id_expt); }
inline static VALUE f_complex_new_bang1(VALUE klass, VALUE x) { assert(!k_complex_p(x)); return nucomp_s_new_internal(klass, x, ZERO); }
static VALUE nucomp_s_alloc(VALUE klass) { return nucomp_s_new_internal(klass, ZERO, ZERO); }
VALUE rb_complex_raw(VALUE x, VALUE y) { return nucomp_s_new_internal(rb_cComplex, x, y); }