Index: complex.c =================================================================== --- complex.c (リビジョン 50638) +++ complex.c (作業コピー) @@ -967,7 +967,7 @@ nucomp_expt(VALUE self, VALUE other) return f_expt(f_reciprocal(self), f_negate(other)); } if (k_numeric_p(other) && f_real_p(other)) { - VALUE r, theta; + VALUE r, theta, theta2; if (k_bignum_p(other)) rb_warn("in a**b, b may be too big"); @@ -974,10 +974,73 @@ nucomp_expt(VALUE self, VALUE other) r = f_abs(self); theta = f_arg(self); + if (RB_TYPE_P(other, T_BIGNUM) && RBIGNUM_POSITIVE_P(other) && + k_float_p(theta) && !f_zero_p(theta)) { + double th = RFLOAT_VALUE(theta); + double epsilon; + while (fabs(th) >= M_PI * 2) { + if (th < 0) { + th += M_PI * 2; + } + else { + th -= M_PI * 2; + } + } + if (th < 0) { + th = th += M_PI * 2; + } - return f_complex_polar(CLASS_OF(self), f_expt(r, other), - f_mul(theta, other)); + epsilon = th * DBL_EPSILON; + if (fabs(th - M_PI_2) <= epsilon) { + switch (FIX2INT(rb_big_modulo(other, INT2FIX(4)))) { + case 0: + theta2 = DBL2NUM(0.0); + break; + case 1: + theta2 = DBL2NUM(th); + break; + case 2: + theta2 = DBL2NUM(M_PI); + break; + case 3: + theta2 = DBL2NUM(M_PI+th); + break; } + } + else if (fabs(th - M_PI) <= epsilon) { + if (f_zero_p(rb_big_modulo(other, INT2FIX(2)))) { + theta2 = DBL2NUM(th); + } + else { + theta2 = DBL2NUM(0.0); + } + } + else if (fabs(th - (M_PI+M_PI_2)) <= epsilon) { + switch (FIX2INT(rb_big_modulo(other, INT2FIX(4)))) { + case 0: + theta2 = DBL2NUM(0.0); + break; + case 1: + theta2 = DBL2NUM(M_PI+th); + break; + case 2: + theta2 = DBL2NUM(M_PI); + break; + case 3: + theta2 = DBL2NUM(th); + break; + } + } + else { + theta2 = f_mul(DBL2NUM(th), other); + } + } + else { + theta2 = f_mul(theta, other); + } + + return f_complex_polar(CLASS_OF(self), f_expt(r, other), theta2); + } return rb_num_coerce_bin(self, other, id_expt); }