summaryrefslogtreecommitdiff
path: root/enumerator.c
diff options
context:
space:
mode:
authornagachika <nagachika@ruby-lang.org>2021-03-20 15:35:30 +0900
committernagachika <nagachika@ruby-lang.org>2021-03-20 15:35:30 +0900
commit82bce422ba9e131e62b528854dea69a6e8cc0c04 (patch)
treecf44dea8aaa0f021c4fcf97990ce28d43de8cd35 /enumerator.c
parentc02f4c1c5aa5056d6eae8f0c2d6414adf5293b2b (diff)
merge revision(s) 254bed302752a401b5fcc3b6c65a9c93711d91d6,fad3023e94c45e7f03478732f7641b6f39ba9d12,3156fb0f2c3ebf8229f392c8502c08fe165ab181: [Backport #17218]
Renamed `nurat_sub` compliant with `rb_rational_plus` --- internal/rational.h | 1 + rational.c | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) Fix ArithmeticSequence#last and ArithmeticSequence#each for non-integer sequences (#3870) [Bug #17218] [ruby-core:100312] --- common.mk | 2 + enumerator.c | 99 ++++++++++++++++++++++++++++++++--- internal/numeric.h | 2 + internal/rational.h | 2 + numeric.c | 53 ++++++++++--------- rational.c | 28 +++++++--- test/ruby/test_arithmetic_sequence.rb | 10 ++++ 7 files changed, 156 insertions(+), 40 deletions(-) test/ruby/test_arithmetic_sequence.rb: remove a duplicated test There is another "test_last_bug17218" --- test/ruby/test_arithmetic_sequence.rb | 5 ----- 1 file changed, 5 deletions(-)
Diffstat (limited to 'enumerator.c')
-rw-r--r--enumerator.c98
1 files changed, 90 insertions, 8 deletions
diff --git a/enumerator.c b/enumerator.c
index 9d0547da05..2dc1789974 100644
--- a/enumerator.c
+++ b/enumerator.c
@@ -3535,6 +3535,88 @@ arith_seq_first(int argc, VALUE *argv, VALUE self)
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, idDiv, 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
@@ -3559,7 +3641,7 @@ arith_seq_last(int argc, VALUE *argv, VALUE self)
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;
@@ -3567,9 +3649,9 @@ arith_seq_last(int argc, VALUE *argv, VALUE self)
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) {
@@ -3778,22 +3860,22 @@ arith_seq_each(VALUE self)
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);
}
}