/* * call-seq: * rat.fdiv(numeric) -> float * * Performs division and returns the value as a float. * * For example: * * Rational(2, 3).fdiv(1) #=> 0.6666666666666666 * Rational(2, 3).fdiv(0.5) #=> 1.3333333333333333 * Rational(2).fdiv(3) #=> 0.6666666666666666 */ static VALUE nurat_fdiv(VALUE self, SEL sel, VALUE other) { if (f_zero_p(other)) return f_div(self, f_to_f(other)); return f_to_f(f_div(self, other)); }
static VALUE nucomp_fdiv(VALUE self, VALUE other) { get_dat1(self); return f_div(f_complex_new2(CLASS_OF(self), f_to_f(dat->real), f_to_f(dat->imag)), other); }
/* * call-seq: * rat / numeric -> numeric_result * rat.quo(numeric) -> numeric_result * * Performs division. * * For example: * * Rational(2, 3) / Rational(2, 3) #=> (1/1) * Rational(900) / Rational(1) #=> (900/1) * Rational(-2, 9) / Rational(-9, 2) #=> (4/81) * Rational(9, 8) / 4 #=> (9/32) * Rational(20, 9) / 9.8 #=> 0.22675736961451246 */ static VALUE nurat_div(VALUE self, SEL sel, VALUE other) { switch (TYPE(other)) { case T_FIXNUM: case T_BIGNUM: if (f_zero_p(other)) rb_raise_zerodiv(); { get_dat1(self); return f_muldiv(self, dat->num, dat->den, other, ONE, '/'); } case T_FLOAT: return rb_funcall(f_to_f(self), '/', 1, other); case T_RATIONAL: if (f_zero_p(other)) rb_raise_zerodiv(); { get_dat2(self, other); if (f_one_p(self)) return f_rational_new_no_reduce2(CLASS_OF(self), bdat->den, bdat->num); return f_muldiv(self, adat->num, adat->den, bdat->num, bdat->den, '/'); } default: return rb_num_coerce_bin(self, other, '/'); } }
/* * call-seq: * rat * numeric -> numeric_result * * Performs multiplication. * * For example: * * Rational(2, 3) * Rational(2, 3) #=> (4/9) * Rational(900) * Rational(1) #=> (900/1) * Rational(-2, 9) * Rational(-9, 2) #=> (1/1) * Rational(9, 8) * 4 #=> (9/2) * Rational(20, 9) * 9.8 #=> 21.77777777777778 */ static VALUE nurat_mul(VALUE self, SEL sel, VALUE other) { switch (TYPE(other)) { case T_FIXNUM: case T_BIGNUM: { get_dat1(self); return f_muldiv(self, dat->num, dat->den, other, ONE, '*'); } case T_FLOAT: return f_mul(f_to_f(self), other); case T_RATIONAL: { get_dat2(self, other); return f_muldiv(self, adat->num, adat->den, bdat->num, bdat->den, '*'); } default: return rb_num_coerce_bin(self, other, '*'); } }
static VALUE nurat_equal_p(VALUE self, VALUE other) { switch (TYPE(other)) { case T_FIXNUM: case T_BIGNUM: { get_dat1(self); if (!FIXNUM_P(dat->den)) return Qfalse; if (FIX2LONG(dat->den) != 1) return Qfalse; if (f_equal_p(dat->num, other)) return Qtrue; else return Qfalse; } case T_FLOAT: return f_equal_p(f_to_f(self), other); case T_RATIONAL: { get_dat2(self, other); return f_boolcast(f_equal_p(adat->num, bdat->num) && f_equal_p(adat->den, bdat->den)); } default: return f_equal_p(other, self); } }
static VALUE nurat_div(VALUE self, VALUE other) { switch (TYPE(other)) { case T_FIXNUM: case T_BIGNUM: if (f_zero_p(other)) rb_raise(rb_eZeroDivError, "devided by zero"); { get_dat1(self); return f_muldiv(self, dat->num, dat->den, other, ONE, '/'); } case T_FLOAT: return rb_funcall(f_to_f(self), '/', 1, other); case T_RATIONAL: if (f_zero_p(other)) rb_raise(rb_eZeroDivError, "devided by zero"); { get_dat2(self, other); return f_muldiv(self, adat->num, adat->den, bdat->num, bdat->den, '/'); } default: return rb_num_coerce_bin(self, other, '/'); } }
/* * call-seq: * cmp.abs -> real * cmp.magnitude -> real * * Returns the absolute part of its polar form. * * Complex(-1).abs #=> 1 * Complex(3.0, -4.0).abs #=> 5.0 */ static VALUE nucomp_abs(VALUE self) { get_dat1(self); if (f_zero_p(dat->real)) { VALUE a = f_abs(dat->imag); if (k_float_p(dat->real) && !k_float_p(dat->imag)) a = f_to_f(a); return a; } if (f_zero_p(dat->imag)) { VALUE a = f_abs(dat->real); if (!k_float_p(dat->real) && k_float_p(dat->imag)) a = f_to_f(a); return a; } return m_hypot(dat->real, dat->imag); }
/* * call-seq: * cmp.to_f -> float * * Returns the value as a float if possible (the imaginary part should * be exactly zero). * * Complex(1, 0).to_f #=> 1.0 * Complex(1, 0.0).to_f # RangeError * Complex(1, 2).to_f # RangeError */ static VALUE nucomp_to_f(VALUE self) { get_dat1(self); if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) { rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Float", self); } return f_to_f(dat->real); }
/* * call-seq: * cmp.to_f -> float * * Returns the value as a float if possible. */ static VALUE nucomp_to_f(VALUE self) { get_dat1(self); if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) { VALUE s = f_to_s(self); rb_raise(rb_eRangeError, "can't convert %s into Float", StringValuePtr(s)); } return f_to_f(dat->real); }
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); } }
/* :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_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); } }
static VALUE string_to_c_internal(VALUE self) { VALUE s; s = self; if (RSTRING_LEN(s) == 0) return rb_assoc_new(Qnil, self); { VALUE m, sr, si, re, r, i; int po; m = f_match(comp_pat0, s); if (!NIL_P(m)) { sr = rb_reg_nth_match(1, m); si = rb_reg_nth_match(2, m); re = rb_reg_match_post(m); po = 1; } if (NIL_P(m)) { m = f_match(comp_pat1, s); if (!NIL_P(m)) { sr = Qnil; si = rb_reg_nth_match(1, m); if (NIL_P(si)) si = rb_usascii_str_new2(""); { VALUE t; t = rb_reg_nth_match(2, m); if (NIL_P(t)) t = rb_usascii_str_new2("1"); rb_str_concat(si, t); } re = rb_reg_match_post(m); po = 0; } } if (NIL_P(m)) { m = f_match(comp_pat2, s); if (NIL_P(m)) return rb_assoc_new(Qnil, self); sr = rb_reg_nth_match(1, m); if (NIL_P(rb_reg_nth_match(2, m))) si = Qnil; else { VALUE t; si = rb_reg_nth_match(3, m); t = rb_reg_nth_match(4, m); if (NIL_P(t)) t = rb_usascii_str_new2("1"); rb_str_concat(si, t); } re = rb_reg_match_post(m); po = 0; } r = INT2FIX(0); i = INT2FIX(0); if (!NIL_P(sr)) { if (strchr(RSTRING_PTR(sr), '/')) r = f_to_r(sr); else if (strpbrk(RSTRING_PTR(sr), ".eE")) r = f_to_f(sr); else r = f_to_i(sr); } if (!NIL_P(si)) { if (strchr(RSTRING_PTR(si), '/')) i = f_to_r(si); else if (strpbrk(RSTRING_PTR(si), ".eE")) i = f_to_f(si); else i = f_to_i(si); } if (po) return rb_assoc_new(rb_complex_polar(r, i), re); else return rb_assoc_new(rb_complex_new2(r, i), re); } }
static VALUE nurat_fdiv(VALUE self, VALUE other) { return f_div(f_to_f(self), other); }
static VALUE string_to_c_internal(VALUE self) { VALUE s; s = self; if (RSTRING_LEN(s) == 0) return rb_assoc_new(Qnil, self); { VALUE m, sr, si, re, r, i; int po; m = f_match(comp_pat0, s); if (!NIL_P(m)) { sr = f_aref(m, INT2FIX(1)); si = f_aref(m, INT2FIX(2)); re = f_post_match(m); po = 1; } if (NIL_P(m)) { m = f_match(comp_pat1, s); if (!NIL_P(m)) { sr = Qnil; si = f_aref(m, INT2FIX(1)); if (NIL_P(si)) si = rb_usascii_str_new2(""); { VALUE t; t = f_aref(m, INT2FIX(2)); if (NIL_P(t)) t = rb_usascii_str_new2("1"); rb_str_concat(si, t); } re = f_post_match(m); po = 0; } } if (NIL_P(m)) { m = f_match(comp_pat2, s); if (NIL_P(m)) return rb_assoc_new(Qnil, self); sr = f_aref(m, INT2FIX(1)); if (NIL_P(f_aref(m, INT2FIX(2)))) si = Qnil; else { VALUE t; si = f_aref(m, INT2FIX(3)); t = f_aref(m, INT2FIX(4)); if (NIL_P(t)) t = rb_usascii_str_new2("1"); rb_str_concat(si, t); } re = f_post_match(m); po = 0; } r = INT2FIX(0); i = INT2FIX(0); if (!NIL_P(sr)) { if (f_include_p(sr, a_slash)) r = f_to_r(sr); else if (f_gt_p(f_count(sr, a_dot_and_an_e), INT2FIX(0))) r = f_to_f(sr); else r = f_to_i(sr); } if (!NIL_P(si)) { if (f_include_p(si, a_slash)) i = f_to_r(si); else if (f_gt_p(f_count(si, a_dot_and_an_e), INT2FIX(0))) i = f_to_f(si); else i = f_to_i(si); } if (po) return rb_assoc_new(rb_complex_polar(r, i), re); else return rb_assoc_new(rb_complex_new2(r, i), re); } }