diff options
author | nagachika <nagachika@ruby-lang.org> | 2021-03-20 15:35:30 +0900 |
---|---|---|
committer | nagachika <nagachika@ruby-lang.org> | 2021-03-20 15:35:30 +0900 |
commit | 82bce422ba9e131e62b528854dea69a6e8cc0c04 (patch) | |
tree | cf44dea8aaa0f021c4fcf97990ce28d43de8cd35 /enumerator.c | |
parent | c02f4c1c5aa5056d6eae8f0c2d6414adf5293b2b (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.c | 98 |
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); } } |