static VALUE f_round_common(int argc, VALUE *argv, VALUE self, VALUE (*func)(VALUE, SEL)) { VALUE n, b, s; if (argc == 0) return (*func)(self, NULL); rb_scan_args(argc, argv, "01", &n); if (!k_integer_p(n)) rb_raise(rb_eTypeError, "not an integer"); b = f_expt(INT2FIX(10), n); s = f_mul(self, b); s = (*func)(s, NULL); s = f_div(f_rational_new_bang1(CLASS_OF(self), s), b); if (f_lt_p(n, ONE)) s = f_to_i(s); return s; }
static VALUE float_to_r(VALUE self) { VALUE a = float_decode(self); return f_mul(RARRAY_AT(a, 0), f_expt(INT2FIX(FLT_RADIX), RARRAY_AT(a, 1))); }
/* * call-seq: * rat ** numeric -> numeric_result * * Performs exponentiation. * * For example: * * Rational(2) ** Rational(3) #=> (8/1) * Rational(10) ** -2 #=> (1/100) * Rational(10) ** -2.0 #=> 0.01 * Rational(-4) ** Rational(1,2) #=> (1.2246063538223773e-16+2.0i) * Rational(1, 2) ** 0 #=> (1/1) * Rational(1, 2) ** 0.0 #=> 1.0 */ static VALUE nurat_expt(VALUE self, SEL sel, VALUE other) { if (k_exact_zero_p(other)) return f_rational_new_bang1(CLASS_OF(self), ONE); if (k_rational_p(other)) { get_dat1(other); if (f_one_p(dat->den)) other = dat->num; /* c14n */ } switch (TYPE(other)) { case T_FIXNUM: { VALUE num, den; get_dat1(self); switch (FIX2INT(f_cmp(other, ZERO))) { case 1: num = f_expt(dat->num, other); den = f_expt(dat->den, other); break; case -1: num = f_expt(dat->den, f_negate(other)); den = f_expt(dat->num, f_negate(other)); break; default: num = ONE; den = ONE; break; } return f_rational_new2(CLASS_OF(self), num, den); } case T_BIGNUM: rb_warn("in a**b, b may be too big"); /* fall through */ case T_FLOAT: case T_RATIONAL: return f_expt(f_to_f(self), other); default: return rb_num_coerce_bin(self, other, id_expt); } }
static VALUE float_to_r(VALUE self) { VALUE f, n; float_decode_internal(self, &f, &n); return f_mul(f, f_expt(INT2FIX(FLT_RADIX), n)); }
/* * call-seq: * flt.to_r -> rational * * Returns the value as a rational. * * NOTE: 0.3.to_r isn't the same as '0.3'.to_r. The latter is * equivalent to '3/10'.to_r, but the former isn't so. * * For example: * * 2.0.to_r #=> (2/1) * 2.5.to_r #=> (5/2) * -0.75.to_r #=> (-3/4) * 0.0.to_r #=> (0/1) */ static VALUE float_to_r(VALUE self, SEL sel) { VALUE f, n; float_decode_internal(self, &f, &n); #if FLT_RADIX == 2 { long ln = FIX2LONG(n); if (ln == 0) return f_to_r(f); if (ln > 0) return f_to_r(f_lshift(f, n)); ln = -ln; return rb_rational_new2(f, f_lshift(ONE, INT2FIX(ln))); } #else return f_to_r(f_mul(f, f_expt(INT2FIX(FLT_RADIX), n))); #endif }
/* * 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); }
static VALUE string_to_r_internal(VALUE self) { VALUE s, m; s = self; if (RSTRING_LEN(s) == 0) return rb_assoc_new(Qnil, self); m = f_match(rat_pat, s); if (!NIL_P(m)) { VALUE v, ifp, exp, ip, fp; VALUE si = f_aref(m, INT2FIX(1)); VALUE nu = f_aref(m, INT2FIX(2)); VALUE de = f_aref(m, INT2FIX(3)); VALUE re = f_post_match(m); { VALUE a; a = f_split(nu, an_e_pat); ifp = RARRAY_PTR(a)[0]; if (RARRAY_LEN(a) != 2) exp = Qnil; else exp = RARRAY_PTR(a)[1]; a = f_split(ifp, a_dot_pat); ip = RARRAY_PTR(a)[0]; if (RARRAY_LEN(a) != 2) fp = Qnil; else fp = RARRAY_PTR(a)[1]; } v = rb_rational_new1(f_to_i(ip)); if (!NIL_P(fp)) { char *p = StringValuePtr(fp); long count = 0; VALUE l; while (*p) { if (rb_isdigit(*p)) count++; p++; } l = f_expt(INT2FIX(10), LONG2NUM(count)); v = f_mul(v, l); v = f_add(v, f_to_i(fp)); v = f_div(v, l); } if (!NIL_P(si) && *StringValuePtr(si) == '-') v = f_negate(v); if (!NIL_P(exp)) v = f_mul(v, f_expt(INT2FIX(10), f_to_i(exp))); #if 0 if (!NIL_P(de) && (!NIL_P(fp) || !NIL_P(exp))) return rb_assoc_new(v, rb_usascii_str_new2("dummy")); #endif if (!NIL_P(de)) v = f_div(v, f_to_i(de)); return rb_assoc_new(v, re); } return rb_assoc_new(Qnil, self); }
static VALUE nucomp_expt(VALUE self, VALUE other) { if (k_exact_p(other) && f_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); /* good? */ 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->imag; 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; x = self; z = x; n = f_sub(other, ONE); while (f_nonzero_p(n)) { VALUE a; while (a = f_divmod(n, TWO), f_zero_p(RARRAY_PTR(a)[1])) { get_dat1(x); x = f_complex_new2(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 = RARRAY_PTR(a)[0]; } z = f_mul(z, x); n = f_sub(n, ONE); } return z; } return f_expt(f_div(f_to_r(ONE), self), f_negate(other)); } if (k_numeric_p(other) && f_real_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); }