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; }
/* :nodoc: */ static VALUE nurat_coerce(VALUE self, SEL sel, VALUE other) { switch (TYPE(other)) { case T_FIXNUM: case T_BIGNUM: return rb_assoc_new(f_rational_new_bang1(CLASS_OF(self), other), self); case T_FLOAT: return rb_assoc_new(other, f_to_f(self)); case T_RATIONAL: return rb_assoc_new(other, self); case T_COMPLEX: if (k_exact_zero_p(RCOMPLEX(other)->imag)) return rb_assoc_new(f_rational_new_bang1 (CLASS_OF(self), RCOMPLEX(other)->real), self); } rb_raise(rb_eTypeError, "%s can't be coerced into %s", rb_obj_classname(other), rb_obj_classname(self)); return Qnil; }
static VALUE nurat_coerce(VALUE self, VALUE other) { switch (TYPE(other)) { case T_FIXNUM: case T_BIGNUM: return rb_assoc_new(f_rational_new_bang1(CLASS_OF(self), other), self); case T_FLOAT: return rb_assoc_new(other, f_to_f(self)); } rb_raise(rb_eTypeError, "%s can't be coerced into %s", rb_obj_classname(other), rb_obj_classname(self)); return Qnil; }
/* * 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 nurat_cmp(VALUE self, VALUE other) { switch (TYPE(other)) { case T_FIXNUM: case T_BIGNUM: { get_dat1(self); if (FIXNUM_P(dat->den) && FIX2LONG(dat->den) == 1) return f_cmp(dat->num, other); else return f_cmp(self, f_rational_new_bang1(CLASS_OF(self), other)); } case T_FLOAT: return f_cmp(f_to_f(self), other); case T_RATIONAL: { VALUE num1, num2; get_dat2(self, other); if (FIXNUM_P(adat->num) && FIXNUM_P(adat->den) && FIXNUM_P(bdat->num) && FIXNUM_P(bdat->den)) { num1 = f_imul(FIX2LONG(adat->num), FIX2LONG(bdat->den)); num2 = f_imul(FIX2LONG(bdat->num), FIX2LONG(adat->den)); } else { num1 = f_mul(adat->num, bdat->den); num2 = f_mul(bdat->num, adat->den); } return f_cmp(f_sub(num1, num2), ZERO); } default: return rb_num_coerce_bin(self, other, id_cmp); } }