[前][次][番号順一覧][スレッド一覧]

ruby-changes:65780

From: usa <ko1@a...>
Date: Mon, 5 Apr 2021 10:22:25 +0900 (JST)
Subject: [ruby-changes:65780] 1a38986aed (ruby_2_6): merge revision(s) 254bed302752a401b5fcc3b6c65a9c93711d91d6,fad3023e94c45e7f03478732f7641b6f39ba9d12,3156fb0f2c3ebf8229f392c8502c08fe165ab181: [Backport #17218]

https://git.ruby-lang.org/ruby.git/commit/?id=1a38986aed

From 1a38986aedf63f676efded3e834c959059d21760 Mon Sep 17 00:00:00 2001
From: usa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
Date: Mon, 5 Apr 2021 01:22:11 +0000
Subject: merge revision(s)
 254bed302752a401b5fcc3b6c65a9c93711d91d6,fad3023e94c45e7f03478732f7641b6f39ba9d12,3156fb0f2c3ebf8229f392c8502c08fe165ab181:
 [Backport #17218]

	Renamed `nurat_sub` compliant with `rb_rational_plus`


	Fix ArithmeticSequence#last and ArithmeticSequence#each for
	non-integer sequences (#3870)

	[Bug #17218]
	[ruby-core:100312]


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_6@67936 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
---
 enumerator.c                          | 98 ++++++++++++++++++++++++++++++++---
 internal.h                            |  7 +++
 numeric.c                             | 59 +++++++++++----------
 rational.c                            | 34 ++++++++----
 test/ruby/test_arithmetic_sequence.rb |  5 ++
 version.h                             |  2 +-
 6 files changed, 158 insertions(+), 47 deletions(-)

diff --git a/enumerator.c b/enumerator.c
index 6db3bbe..686dab0 100644
--- a/enumerator.c
+++ b/enumerator.c
@@ -2939,6 +2939,88 @@ arith_seq_first(int argc, VALUE *argv, VALUE self) https://github.com/ruby/ruby/blob/trunk/enumerator.c#L2939
     return rb_call_super(argc, argv);
 }
 
+static inline VALUE
+num_plus(VALUE a, VALUE b)
+{
+    if (RB_INTEGER_TYPE_P(a)) {
+        return rb_int_plus(a, b);
+    }
+    else if (RB_FLOAT_TYPE_P(a)) {
+        return rb_float_plus(a, b);
+    }
+    else if (RB_TYPE_P(a, T_RATIONAL)) {
+        return rb_rational_plus(a, b);
+    }
+    else {
+        return rb_funcallv(a, '+', 1, &b);
+    }
+}
+
+static inline VALUE
+num_minus(VALUE a, VALUE b)
+{
+    if (RB_INTEGER_TYPE_P(a)) {
+        return rb_int_minus(a, b);
+    }
+    else if (RB_FLOAT_TYPE_P(a)) {
+        return rb_float_minus(a, b);
+    }
+    else if (RB_TYPE_P(a, T_RATIONAL)) {
+        return rb_rational_minus(a, b);
+    }
+    else {
+        return rb_funcallv(a, '-', 1, &b);
+    }
+}
+
+static inline VALUE
+num_mul(VALUE a, VALUE b)
+{
+    if (RB_INTEGER_TYPE_P(a)) {
+        return rb_int_mul(a, b);
+    }
+    else if (RB_FLOAT_TYPE_P(a)) {
+        return rb_float_mul(a, b);
+    }
+    else if (RB_TYPE_P(a, T_RATIONAL)) {
+        return rb_rational_mul(a, b);
+    }
+    else {
+        return rb_funcallv(a, '*', 1, &b);
+    }
+}
+
+static inline VALUE
+num_idiv(VALUE a, VALUE b)
+{
+    VALUE q;
+    if (RB_INTEGER_TYPE_P(a)) {
+        q = rb_int_idiv(a, b);
+    }
+    else if (RB_FLOAT_TYPE_P(a)) {
+        q = rb_float_div(a, b);
+    }
+    else if (RB_TYPE_P(a, T_RATIONAL)) {
+        q = rb_rational_div(a, b);
+    }
+    else {
+        q = rb_funcallv(a, '/', 1, &b);
+    }
+
+    if (RB_INTEGER_TYPE_P(q)) {
+        return q;
+    }
+    else if (RB_FLOAT_TYPE_P(q)) {
+        return rb_float_floor(q, 0);
+    }
+    else if (RB_TYPE_P(q, T_RATIONAL)) {
+        return rb_rational_floor(q, 0);
+    }
+    else {
+        return rb_funcall(q, rb_intern("floor"), 0);
+    }
+}
+
 /*
  * call-seq:
  *   aseq.last    -> num or nil
@@ -2963,7 +3045,7 @@ arith_seq_last(int argc, VALUE *argv, VALUE self) https://github.com/ruby/ruby/blob/trunk/enumerator.c#L3045
     b = arith_seq_begin(self);
     s = arith_seq_step(self);
 
-    len_1 = rb_int_idiv(rb_int_minus(e, b), s);
+    len_1 = num_idiv(num_minus(e, b), s);
     if (rb_num_negative_int_p(len_1)) {
         if (argc == 0) {
             return Qnil;
@@ -2971,9 +3053,9 @@ arith_seq_last(int argc, VALUE *argv, VALUE self) https://github.com/ruby/ruby/blob/trunk/enumerator.c#L3053
         return rb_ary_new_capa(0);
     }
 
-    last = rb_int_plus(b, rb_int_mul(s, len_1));
+    last = num_plus(b, num_mul(s, len_1));
     if ((last_is_adjusted = arith_seq_exclude_end_p(self) && rb_equal(last, e))) {
-        last = rb_int_minus(last, s);
+        last = num_minus(last, s);
     }
 
     if (argc == 0) {
@@ -3183,22 +3265,22 @@ arith_seq_each(VALUE self) https://github.com/ruby/ruby/blob/trunk/enumerator.c#L3265
         return self;
     }
 
-    len_1 = rb_int_idiv(rb_int_minus(e, c), s);
-    last = rb_int_plus(c, rb_int_mul(s, len_1));
+    len_1 = num_idiv(num_minus(e, c), s);
+    last = num_plus(c, num_mul(s, len_1));
     if (x && rb_equal(last, e)) {
-        last = rb_int_minus(last, s);
+        last = num_minus(last, s);
     }
 
     if (rb_num_negative_int_p(s)) {
         while (NUM_GE(c, last)) {
             rb_yield(c);
-            c = rb_int_plus(c, s);
+            c = num_plus(c, s);
         }
     }
     else {
         while (NUM_GE(last, c)) {
             rb_yield(c);
-            c = rb_int_plus(c, s);
+            c = num_plus(c, s);
         }
     }
 
diff --git a/internal.h b/internal.h
index 37e5c73..13a0424 100644
--- a/internal.h
+++ b/internal.h
@@ -1682,9 +1682,11 @@ VALUE rb_float_uminus(VALUE num); https://github.com/ruby/ruby/blob/trunk/internal.h#L1682
 VALUE rb_int_plus(VALUE x, VALUE y);
 VALUE rb_float_plus(VALUE x, VALUE y);
 VALUE rb_int_minus(VALUE x, VALUE y);
+VALUE rb_float_minus(VALUE x, VALUE y);
 VALUE rb_int_mul(VALUE x, VALUE y);
 VALUE rb_float_mul(VALUE x, VALUE y);
 VALUE rb_int_idiv(VALUE x, VALUE y);
+VALUE rb_float_div(VALUE x, VALUE y);
 VALUE rb_int_modulo(VALUE x, VALUE y);
 VALUE rb_int_round(VALUE num, int ndigits, enum ruby_num_rounding_mode mode);
 VALUE rb_int2str(VALUE num, int base);
@@ -1709,6 +1711,8 @@ VALUE rb_int_odd_p(VALUE num); https://github.com/ruby/ruby/blob/trunk/internal.h#L1711
 int rb_int_positive_p(VALUE num);
 int rb_int_negative_p(VALUE num);
 VALUE rb_num_pow(VALUE x, VALUE y);
+VALUE rb_float_floor(VALUE x, int ndigits);
+
 
 static inline VALUE
 rb_num_compare_with_zero(VALUE num, ID mid)
@@ -1975,13 +1979,16 @@ void rb_last_status_clear(void); https://github.com/ruby/ruby/blob/trunk/internal.h#L1979
 VALUE rb_rational_canonicalize(VALUE x);
 VALUE rb_rational_uminus(VALUE self);
 VALUE rb_rational_plus(VALUE self, VALUE other);
+VALUE rb_rational_minus(VALUE self, VALUE other);
 VALUE rb_rational_mul(VALUE self, VALUE other);
+VALUE rb_rational_div(VALUE self, VALUE other);
 VALUE rb_lcm(VALUE x, VALUE y);
 VALUE rb_rational_reciprocal(VALUE x);
 VALUE rb_cstr_to_rat(const char *, int);
 VALUE rb_rational_abs(VALUE self);
 VALUE rb_rational_cmp(VALUE self, VALUE other);
 VALUE rb_rational_pow(VALUE self, VALUE other);
+VALUE rb_rational_floor(VALUE self, int ndigits);
 VALUE rb_numeric_quo(VALUE x, VALUE y);
 
 /* re.c */
diff --git a/numeric.c b/numeric.c
index d602d0a..f5ae09b 100644
--- a/numeric.c
+++ b/numeric.c
@@ -1042,8 +1042,8 @@ rb_float_plus(VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/numeric.c#L1042
  * Returns a new Float which is the difference of +float+ and +other+.
  */
 
-static VALUE
-flo_minus(VALUE x, VALUE y)
+VALUE
+rb_float_minus(VALUE x, VALUE y)
 {
     if (RB_TYPE_P(y, T_FIXNUM)) {
 	return DBL2NUM(RFLOAT_VALUE(x) - (double)FIX2LONG(y));
@@ -1120,8 +1120,8 @@ rb_flo_div_flo(VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/numeric.c#L1120
  * Returns a new Float which is the result of dividing +float+ by +other+.
  */
 
-static VALUE
-flo_div(VALUE x, VALUE y)
+VALUE
+rb_float_div(VALUE x, VALUE y)
 {
     double num = RFLOAT_VALUE(x);
     double den;
@@ -1891,6 +1891,31 @@ flo_prev_float(VALUE vx) https://github.com/ruby/ruby/blob/trunk/numeric.c#L1891
     return DBL2NUM(y);
 }
 
+VALUE
+rb_float_floor(VALUE num, int ndigits)
+{
+    double number, f;
+    number = RFLOAT_VALUE(num);
+    if (number == 0.0) {
+	return ndigits > 0 ? DBL2NUM(number) : INT2FIX(0);
+    }
+    if (ndigits > 0) {
+	int binexp;
+	frexp(number, &binexp);
+	if (float_round_overflow(ndigits, binexp)) return num;
+	if (number > 0.0 && float_round_underflow(ndigits, binexp))
+	    return DBL2NUM(0.0);
+	f = pow(10, ndigits);
+	f = floor(number * f) / f;
+	return DBL2NUM(f);
+    }
+    else {
+	num = dbl2ival(floor(number));
+	if (ndigits < 0) num = rb_int_floor(num, ndigits);
+	return num;
+    }
+}
+
 /*
  *  call-seq:
  *     float.floor([ndigits])  ->  integer or float
@@ -1933,31 +1958,11 @@ flo_prev_float(VALUE vx) https://github.com/ruby/ruby/blob/trunk/numeric.c#L1958
 static VALUE
 flo_floor(int argc, VALUE *argv, VALUE num)
 {
-    double number, f;
     int ndigits = 0;
-
     if (rb_check_arity(argc, 0, 1)) {
 	ndigits = NUM2INT(argv[0]);
     }
-    number = RFLOAT_VALUE(num);
-    if (number == 0.0) {
-	return ndigits > 0 ? DBL2NUM(number) : INT2FIX(0);
-    }
-    if (ndigits > 0) {
-	int binexp;
-	frexp(number, &binexp);
-	if (float_round_overflow(ndigits, binexp)) return num;
-	if (number > 0.0 && float_round_underflow(ndigits, binexp))
-	    return DBL2NUM(0.0);
-	f = pow(10, ndigits);
-	f = floor(number * f) / f;
-	return DBL2NUM(f);
-    }
-    else {
-	num = dbl2ival(floor(number));
-	if (ndigits < 0) num = rb_int_floor(num, ndigits);
-	return num;
-    }
+    return rb_float_floor(num, ndigits);
 }
 
 /*
@@ -5676,9 +5681,9 @@ Init_Numeric(void) https://github.com/ruby/ruby/blob/trunk/numeric.c#L5681
     rb_define_method(rb_cFloat, "coerce", flo_coerce, 1);
     rb_define_method(rb_cFloat, "-@", rb_float_uminus, 0);
     rb_define_method(rb_cFloat, "+", rb_float_plus, 1);
-    rb_define_method(rb_cFloat, "-", flo_minus, 1);
+    rb_define_method(rb_cFloat, "-", rb_float_minus, 1);
     rb_define_method(rb_cFloat, "*", rb_float_mul, 1);
-    rb_define_method(rb_cFloat, "/", flo_div, 1);
+    rb_define_method(rb_cFloat, "/", rb_float_div, 1);
     rb_define_method(rb_cFloat, "quo", flo_quo, 1);
     rb_define_method(rb_cFloat, "fdiv", flo_quo, 1);
     rb_define_method(rb_cFloat, "%", flo_mod, 1);
diff --git a/rational.c b/rational.c
index 1038059..5058ce1 100644
--- a/rational.c
+++ b/rational.c
@@ -781,8 +781,8 @@ rb_rational_plus(VALUE self, VALUE other) https://github.com/ruby/ruby/blob/trunk/rational.c#L781
  *    Rational(9, 8)  - 4                #=> (-23/8)
  *    Rational(20, 9 (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]