inline static VALUE nurat_s_canonicalize_internal(VALUE klass, VALUE num, VALUE den) { VALUE gcd; switch (FIX2INT(f_cmp(den, ZERO))) { case -1: num = f_negate(num); den = f_negate(den); break; case 0: rb_raise_zerodiv(); break; } gcd = f_gcd(num, den); num = f_idiv(num, gcd); den = f_idiv(den, gcd); #ifdef CANON if (f_one_p(den) && canonicalization) return num; #endif return nurat_s_new_internal(klass, num, den); }
/* * call-seq: * rat.to_i -> integer * * Returns the truncated value as an integer. * * Equivalent to * rat.truncate. * * For example: * * Rational(2, 3).to_i #=> 0 * Rational(3).to_i #=> 3 * Rational(300.6).to_i #=> 300 * Rational(98,71).to_i #=> 1 * Rational(-30,2).to_i #=> -15 */ static VALUE nurat_truncate(VALUE self, SEL sel) { get_dat1(self); if (f_negative_p(dat->num)) return f_negate(f_idiv(f_negate(dat->num), dat->den)); return f_idiv(dat->num, dat->den); }
static VALUE nurat_round(VALUE self) { get_dat1(self); if (f_negative_p(dat->num)) { VALUE num, den; num = f_negate(dat->num); num = f_add(f_mul(num, TWO), dat->den); den = f_mul(dat->den, TWO); return f_negate(f_idiv(num, den)); } else { VALUE num = f_add(f_mul(dat->num, TWO), dat->den); VALUE den = f_mul(dat->den, TWO); return f_idiv(num, den); } }
inline static VALUE f_muldiv(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k) { VALUE num, den; if (k == '/') { VALUE t; if (f_negative_p(bnum)) { anum = f_negate(anum); bnum = f_negate(bnum); } t = bnum; bnum = bden; bden = t; } if (FIXNUM_P(anum) && FIXNUM_P(aden) && FIXNUM_P(bnum) && FIXNUM_P(bden)) { long an = FIX2LONG(anum); long ad = FIX2LONG(aden); long bn = FIX2LONG(bnum); long bd = FIX2LONG(bden); long g1 = i_gcd(an, bd); long g2 = i_gcd(ad, bn); num = f_imul(an / g1, bn / g2); den = f_imul(ad / g2, bd / g1); } else { VALUE g1 = f_gcd(anum, bden); VALUE g2 = f_gcd(aden, bnum); num = f_mul(f_idiv(anum, g1), f_idiv(bnum, g2)); den = f_mul(f_idiv(aden, g2), f_idiv(bden, g1)); } return f_rational_new_no_reduce2(CLASS_OF(self), num, den); }
inline static VALUE f_addsub(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k) { VALUE num, den; if (FIXNUM_P(anum) && FIXNUM_P(aden) && FIXNUM_P(bnum) && FIXNUM_P(bden)) { long an = FIX2LONG(anum); long ad = FIX2LONG(aden); long bn = FIX2LONG(bnum); long bd = FIX2LONG(bden); long ig = i_gcd(ad, bd); VALUE g = LONG2NUM(ig); VALUE a = f_imul(an, bd / ig); VALUE b = f_imul(bn, ad / ig); VALUE c; if (k == '+') c = f_add(a, b); else c = f_sub(a, b); b = f_idiv(aden, g); g = f_gcd(c, g); num = f_idiv(c, g); a = f_idiv(bden, g); den = f_mul(a, b); } else { VALUE g = f_gcd(aden, bden); VALUE a = f_mul(anum, f_idiv(bden, g)); VALUE b = f_mul(bnum, f_idiv(aden, g)); VALUE c; if (k == '+') c = f_add(a, b); else c = f_sub(a, b); b = f_idiv(aden, g); g = f_gcd(c, g); num = f_idiv(c, g); a = f_idiv(bden, g); den = f_mul(a, b); } return f_rational_new_no_reduce2(CLASS_OF(self), num, den); }
inline static VALUE nurat_s_canonicalize_internal(VALUE klass, VALUE num, VALUE den) { VALUE gcd; switch (FIX2INT(f_cmp(den, ZERO))) { case -1: num = f_negate(num); den = f_negate(den); break; case 0: rb_raise(rb_eZeroDivError, "devided by zero"); break; } gcd = f_gcd(num, den); num = f_idiv(num, gcd); den = f_idiv(den, gcd); if (f_one_p(den) && f_unify_p(klass)) return num; else return nurat_s_new_internal(klass, num, den); }
static VALUE nurat_round(VALUE self, SEL sel) { VALUE num, den, neg; get_dat1(self); num = dat->num; den = dat->den; neg = f_negative_p(num); if (neg) num = f_negate(num); num = f_add(f_mul(num, TWO), den); den = f_mul(den, TWO); num = f_idiv(num, den); if (neg) num = f_negate(num); return num; }
static VALUE nurat_ceil(VALUE self, SEL sel) { get_dat1(self); return f_negate(f_idiv(f_negate(dat->num), dat->den)); }
static VALUE nurat_floor(VALUE self, SEL sel) { get_dat1(self); return f_idiv(dat->num, dat->den); }
/* :nodoc: */ static VALUE nurat_idiv(VALUE self, VALUE other) { return f_idiv(self, other); }