aboutsummaryrefslogtreecommitdiffstats
path: root/rational.c
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2020-05-30 18:39:56 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2020-07-01 22:41:16 +0900
commit49029811d998d919c1f31f39e7a4b82f42ff3eaa (patch)
tree4dd0959f9980ffdffa03742ce2e8850f99fd74ac /rational.c
parent254bed302752a401b5fcc3b6c65a9c93711d91d6 (diff)
downloadruby-49029811d998d919c1f31f39e7a4b82f42ff3eaa.tar.gz
Reduced working `Rational` object allocations
When rationalizing negative values.
Diffstat (limited to 'rational.c')
-rw-r--r--rational.c43
1 files changed, 28 insertions, 15 deletions
diff --git a/rational.c b/rational.c
index 02c9003b7e..967cdce9c1 100644
--- a/rational.c
+++ b/rational.c
@@ -1712,21 +1712,30 @@ static VALUE
nurat_rationalize(int argc, VALUE *argv, VALUE self)
{
VALUE e, a, b, p, q;
+ VALUE rat = self;
+ get_dat1(self);
if (rb_check_arity(argc, 0, 1) == 0)
return self;
- if (nurat_negative_p(self))
- return rb_rational_uminus(nurat_rationalize(argc, argv, rb_rational_uminus(self)));
-
e = f_abs(argv[0]);
- a = f_sub(self, e);
- b = f_add(self, e);
+
+ if (INT_NEGATIVE_P(dat->num)) {
+ rat = f_rational_new2(RBASIC_CLASS(self), rb_int_uminus(dat->num), dat->den);
+ }
+
+ a = FIXNUM_ZERO_P(e) ? rat : rb_rational_minus(rat, e);
+ b = FIXNUM_ZERO_P(e) ? rat : rb_rational_plus(rat, e);
if (f_eqeq_p(a, b))
return self;
nurat_rationalize_internal(a, b, &p, &q);
+ if (rat != self) {
+ RATIONAL_SET_NUM(rat, rb_int_uminus(p));
+ RATIONAL_SET_DEN(rat, q);
+ return rat;
+ }
return f_rational_new2(CLASS_OF(self), p, q);
}
@@ -2238,7 +2247,7 @@ rb_flt_rationalize_with_prec(VALUE flt, VALUE prec)
VALUE
rb_flt_rationalize(VALUE flt)
{
- VALUE a, b, f, p, q;
+ VALUE a, b, f, p, q, den;
int n;
float_decode_internal(flt, &f, &n);
@@ -2246,7 +2255,7 @@ rb_flt_rationalize(VALUE flt)
return rb_rational_new1(rb_int_lshift(f, INT2FIX(n)));
{
- VALUE radix_times_f, den;
+ VALUE radix_times_f;
radix_times_f = rb_int_mul(INT2FIX(FLT_RADIX), f);
#if FLT_RADIX == 2 && 0
@@ -2255,13 +2264,15 @@ rb_flt_rationalize(VALUE flt)
den = rb_int_positive_pow(FLT_RADIX, 1-n);
#endif
- a = rb_rational_new2(rb_int_minus(radix_times_f, INT2FIX(FLT_RADIX - 1)), den);
- b = rb_rational_new2(rb_int_plus(radix_times_f, INT2FIX(FLT_RADIX - 1)), den);
+ a = rb_int_minus(radix_times_f, INT2FIX(FLT_RADIX - 1));
+ b = rb_int_plus(radix_times_f, INT2FIX(FLT_RADIX - 1));
}
- if (nurat_eqeq_p(a, b))
+ if (f_eqeq_p(a, b))
return float_to_r(flt);
+ a = rb_rational_new2(a, den);
+ b = rb_rational_new2(b, den);
nurat_rationalize_internal(a, b, &p, &q);
return rb_rational_new2(p, q);
}
@@ -2284,16 +2295,18 @@ static VALUE
float_rationalize(int argc, VALUE *argv, VALUE self)
{
double d = RFLOAT_VALUE(self);
-
- if (d < 0.0)
- return rb_rational_uminus(float_rationalize(argc, argv, DBL2NUM(-d)));
+ VALUE rat;
+ int neg = d < 0.0;
+ if (neg) self = DBL2NUM(-d);
if (rb_check_arity(argc, 0, 1)) {
- return rb_flt_rationalize_with_prec(self, argv[0]);
+ rat = rb_flt_rationalize_with_prec(self, argv[0]);
}
else {
- return rb_flt_rationalize(self);
+ rat = rb_flt_rationalize(self);
}
+ if (neg) RATIONAL_SET_NUM(rat, rb_int_uminus(RRATIONAL(rat)->num));
+ return rat;
}
inline static int