Skip to content

Commit 82bce42

Browse files
committed
merge revision(s) 254bed3,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 (ruby#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(-)
1 parent c02f4c1 commit 82bce42

File tree

6 files changed

+153
-44
lines changed

6 files changed

+153
-44
lines changed

enumerator.c

Lines changed: 90 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3535,6 +3535,88 @@ arith_seq_first(int argc, VALUE *argv, VALUE self)
35353535
return rb_call_super(argc, argv);
35363536
}
35373537

3538+
static inline VALUE
3539+
num_plus(VALUE a, VALUE b)
3540+
{
3541+
if (RB_INTEGER_TYPE_P(a)) {
3542+
return rb_int_plus(a, b);
3543+
}
3544+
else if (RB_FLOAT_TYPE_P(a)) {
3545+
return rb_float_plus(a, b);
3546+
}
3547+
else if (RB_TYPE_P(a, T_RATIONAL)) {
3548+
return rb_rational_plus(a, b);
3549+
}
3550+
else {
3551+
return rb_funcallv(a, '+', 1, &b);
3552+
}
3553+
}
3554+
3555+
static inline VALUE
3556+
num_minus(VALUE a, VALUE b)
3557+
{
3558+
if (RB_INTEGER_TYPE_P(a)) {
3559+
return rb_int_minus(a, b);
3560+
}
3561+
else if (RB_FLOAT_TYPE_P(a)) {
3562+
return rb_float_minus(a, b);
3563+
}
3564+
else if (RB_TYPE_P(a, T_RATIONAL)) {
3565+
return rb_rational_minus(a, b);
3566+
}
3567+
else {
3568+
return rb_funcallv(a, '-', 1, &b);
3569+
}
3570+
}
3571+
3572+
static inline VALUE
3573+
num_mul(VALUE a, VALUE b)
3574+
{
3575+
if (RB_INTEGER_TYPE_P(a)) {
3576+
return rb_int_mul(a, b);
3577+
}
3578+
else if (RB_FLOAT_TYPE_P(a)) {
3579+
return rb_float_mul(a, b);
3580+
}
3581+
else if (RB_TYPE_P(a, T_RATIONAL)) {
3582+
return rb_rational_mul(a, b);
3583+
}
3584+
else {
3585+
return rb_funcallv(a, '*', 1, &b);
3586+
}
3587+
}
3588+
3589+
static inline VALUE
3590+
num_idiv(VALUE a, VALUE b)
3591+
{
3592+
VALUE q;
3593+
if (RB_INTEGER_TYPE_P(a)) {
3594+
q = rb_int_idiv(a, b);
3595+
}
3596+
else if (RB_FLOAT_TYPE_P(a)) {
3597+
q = rb_float_div(a, b);
3598+
}
3599+
else if (RB_TYPE_P(a, T_RATIONAL)) {
3600+
q = rb_rational_div(a, b);
3601+
}
3602+
else {
3603+
q = rb_funcallv(a, idDiv, 1, &b);
3604+
}
3605+
3606+
if (RB_INTEGER_TYPE_P(q)) {
3607+
return q;
3608+
}
3609+
else if (RB_FLOAT_TYPE_P(q)) {
3610+
return rb_float_floor(q, 0);
3611+
}
3612+
else if (RB_TYPE_P(q, T_RATIONAL)) {
3613+
return rb_rational_floor(q, 0);
3614+
}
3615+
else {
3616+
return rb_funcall(q, rb_intern("floor"), 0);
3617+
}
3618+
}
3619+
35383620
/*
35393621
* call-seq:
35403622
* aseq.last -> num or nil
@@ -3559,17 +3641,17 @@ arith_seq_last(int argc, VALUE *argv, VALUE self)
35593641
b = arith_seq_begin(self);
35603642
s = arith_seq_step(self);
35613643

3562-
len_1 = rb_int_idiv(rb_int_minus(e, b), s);
3644+
len_1 = num_idiv(num_minus(e, b), s);
35633645
if (rb_num_negative_int_p(len_1)) {
35643646
if (argc == 0) {
35653647
return Qnil;
35663648
}
35673649
return rb_ary_new_capa(0);
35683650
}
35693651

3570-
last = rb_int_plus(b, rb_int_mul(s, len_1));
3652+
last = num_plus(b, num_mul(s, len_1));
35713653
if ((last_is_adjusted = arith_seq_exclude_end_p(self) && rb_equal(last, e))) {
3572-
last = rb_int_minus(last, s);
3654+
last = num_minus(last, s);
35733655
}
35743656

35753657
if (argc == 0) {
@@ -3778,22 +3860,22 @@ arith_seq_each(VALUE self)
37783860
return self;
37793861
}
37803862

3781-
len_1 = rb_int_idiv(rb_int_minus(e, c), s);
3782-
last = rb_int_plus(c, rb_int_mul(s, len_1));
3863+
len_1 = num_idiv(num_minus(e, c), s);
3864+
last = num_plus(c, num_mul(s, len_1));
37833865
if (x && rb_equal(last, e)) {
3784-
last = rb_int_minus(last, s);
3866+
last = num_minus(last, s);
37853867
}
37863868

37873869
if (rb_num_negative_int_p(s)) {
37883870
while (NUM_GE(c, last)) {
37893871
rb_yield(c);
3790-
c = rb_int_plus(c, s);
3872+
c = num_plus(c, s);
37913873
}
37923874
}
37933875
else {
37943876
while (NUM_GE(last, c)) {
37953877
rb_yield(c);
3796-
c = rb_int_plus(c, s);
3878+
c = num_plus(c, s);
37973879
}
37983880
}
37993881

internal.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1812,6 +1812,7 @@ VALUE rb_float_uminus(VALUE num);
18121812
VALUE rb_int_plus(VALUE x, VALUE y);
18131813
VALUE rb_float_plus(VALUE x, VALUE y);
18141814
VALUE rb_int_minus(VALUE x, VALUE y);
1815+
VALUE rb_float_minus(VALUE x, VALUE y);
18151816
VALUE rb_int_mul(VALUE x, VALUE y);
18161817
VALUE rb_float_mul(VALUE x, VALUE y);
18171818
VALUE rb_float_div(VALUE x, VALUE y);
@@ -1840,6 +1841,7 @@ int rb_int_positive_p(VALUE num);
18401841
int rb_int_negative_p(VALUE num);
18411842
VALUE rb_num_pow(VALUE x, VALUE y);
18421843
VALUE rb_float_ceil(VALUE num, int ndigits);
1844+
VALUE rb_float_floor(VALUE x, int ndigits);
18431845

18441846
static inline VALUE
18451847
rb_num_compare_with_zero(VALUE num, ID mid)
@@ -2096,13 +2098,16 @@ void rb_last_status_clear(void);
20962098
VALUE rb_rational_canonicalize(VALUE x);
20972099
VALUE rb_rational_uminus(VALUE self);
20982100
VALUE rb_rational_plus(VALUE self, VALUE other);
2101+
VALUE rb_rational_minus(VALUE self, VALUE other);
20992102
VALUE rb_rational_mul(VALUE self, VALUE other);
2103+
VALUE rb_rational_div(VALUE self, VALUE other);
21002104
VALUE rb_lcm(VALUE x, VALUE y);
21012105
VALUE rb_rational_reciprocal(VALUE x);
21022106
VALUE rb_cstr_to_rat(const char *, int);
21032107
VALUE rb_rational_abs(VALUE self);
21042108
VALUE rb_rational_cmp(VALUE self, VALUE other);
21052109
VALUE rb_rational_pow(VALUE self, VALUE other);
2110+
VALUE rb_rational_floor(VALUE self, int ndigits);
21062111
VALUE rb_numeric_quo(VALUE x, VALUE y);
21072112
VALUE rb_float_numerator(VALUE x);
21082113
VALUE rb_float_denominator(VALUE x);

numeric.c

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,8 +1044,8 @@ rb_float_plus(VALUE x, VALUE y)
10441044
* Returns a new Float which is the difference of +float+ and +other+.
10451045
*/
10461046

1047-
static VALUE
1048-
flo_minus(VALUE x, VALUE y)
1047+
VALUE
1048+
rb_float_minus(VALUE x, VALUE y)
10491049
{
10501050
if (RB_TYPE_P(y, T_FIXNUM)) {
10511051
return DBL2NUM(RFLOAT_VALUE(x) - (double)FIX2LONG(y));
@@ -1894,6 +1894,31 @@ flo_prev_float(VALUE vx)
18941894
return DBL2NUM(y);
18951895
}
18961896

1897+
VALUE
1898+
rb_float_floor(VALUE num, int ndigits)
1899+
{
1900+
double number, f;
1901+
number = RFLOAT_VALUE(num);
1902+
if (number == 0.0) {
1903+
return ndigits > 0 ? DBL2NUM(number) : INT2FIX(0);
1904+
}
1905+
if (ndigits > 0) {
1906+
int binexp;
1907+
frexp(number, &binexp);
1908+
if (float_round_overflow(ndigits, binexp)) return num;
1909+
if (number > 0.0 && float_round_underflow(ndigits, binexp))
1910+
return DBL2NUM(0.0);
1911+
f = pow(10, ndigits);
1912+
f = floor(number * f) / f;
1913+
return DBL2NUM(f);
1914+
}
1915+
else {
1916+
num = dbl2ival(floor(number));
1917+
if (ndigits < 0) num = rb_int_floor(num, ndigits);
1918+
return num;
1919+
}
1920+
}
1921+
18971922
/*
18981923
* call-seq:
18991924
* float.floor([ndigits]) -> integer or float
@@ -1936,31 +1961,11 @@ flo_prev_float(VALUE vx)
19361961
static VALUE
19371962
flo_floor(int argc, VALUE *argv, VALUE num)
19381963
{
1939-
double number, f;
19401964
int ndigits = 0;
1941-
19421965
if (rb_check_arity(argc, 0, 1)) {
19431966
ndigits = NUM2INT(argv[0]);
19441967
}
1945-
number = RFLOAT_VALUE(num);
1946-
if (number == 0.0) {
1947-
return ndigits > 0 ? DBL2NUM(number) : INT2FIX(0);
1948-
}
1949-
if (ndigits > 0) {
1950-
int binexp;
1951-
frexp(number, &binexp);
1952-
if (float_round_overflow(ndigits, binexp)) return num;
1953-
if (number > 0.0 && float_round_underflow(ndigits, binexp))
1954-
return DBL2NUM(0.0);
1955-
f = pow(10, ndigits);
1956-
f = floor(number * f) / f;
1957-
return DBL2NUM(f);
1958-
}
1959-
else {
1960-
num = dbl2ival(floor(number));
1961-
if (ndigits < 0) num = rb_int_floor(num, ndigits);
1962-
return num;
1963-
}
1968+
return rb_float_floor(num, ndigits);
19641969
}
19651970

19661971
/*
@@ -5790,7 +5795,7 @@ Init_Numeric(void)
57905795
rb_define_method(rb_cFloat, "coerce", flo_coerce, 1);
57915796
rb_define_method(rb_cFloat, "-@", rb_float_uminus, 0);
57925797
rb_define_method(rb_cFloat, "+", rb_float_plus, 1);
5793-
rb_define_method(rb_cFloat, "-", flo_minus, 1);
5798+
rb_define_method(rb_cFloat, "-", rb_float_minus, 1);
57945799
rb_define_method(rb_cFloat, "*", rb_float_mul, 1);
57955800
rb_define_method(rb_cFloat, "/", rb_float_div, 1);
57965801
rb_define_method(rb_cFloat, "quo", flo_quo, 1);

rational.c

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -774,8 +774,8 @@ rb_rational_plus(VALUE self, VALUE other)
774774
* Rational(9, 8) - 4 #=> (-23/8)
775775
* Rational(20, 9) - 9.8 #=> -7.577777777777778
776776
*/
777-
static VALUE
778-
nurat_sub(VALUE self, VALUE other)
777+
VALUE
778+
rb_rational_minus(VALUE self, VALUE other)
779779
{
780780
if (RB_INTEGER_TYPE_P(other)) {
781781
{
@@ -912,8 +912,8 @@ rb_rational_mul(VALUE self, VALUE other)
912912
* Rational(9, 8) / 4 #=> (9/32)
913913
* Rational(20, 9) / 9.8 #=> 0.22675736961451246
914914
*/
915-
static VALUE
916-
nurat_div(VALUE self, VALUE other)
915+
VALUE
916+
rb_rational_div(VALUE self, VALUE other)
917917
{
918918
if (RB_INTEGER_TYPE_P(other)) {
919919
if (f_zero_p(other))
@@ -965,10 +965,10 @@ nurat_fdiv(VALUE self, VALUE other)
965965
{
966966
VALUE div;
967967
if (f_zero_p(other))
968-
return nurat_div(self, rb_float_new(0.0));
968+
return rb_rational_div(self, rb_float_new(0.0));
969969
if (FIXNUM_P(other) && other == LONG2FIX(1))
970970
return nurat_to_f(self);
971-
div = nurat_div(self, other);
971+
div = rb_rational_div(self, other);
972972
if (RB_TYPE_P(div, T_RATIONAL))
973973
return nurat_to_f(div);
974974
if (RB_FLOAT_TYPE_P(div))
@@ -1403,14 +1403,26 @@ f_round_common(int argc, VALUE *argv, VALUE self, VALUE (*func)(VALUE))
14031403

14041404
s = (*func)(s);
14051405

1406-
s = nurat_div(f_rational_new_bang1(CLASS_OF(self), s), b);
1406+
s = rb_rational_div(f_rational_new_bang1(CLASS_OF(self), s), b);
14071407

14081408
if (RB_TYPE_P(s, T_RATIONAL) && FIX2INT(rb_int_cmp(n, ONE)) < 0)
14091409
s = nurat_truncate(s);
14101410

14111411
return s;
14121412
}
14131413

1414+
VALUE
1415+
rb_rational_floor(VALUE self, int ndigits)
1416+
{
1417+
if (ndigits == 0) {
1418+
return nurat_floor(self);
1419+
}
1420+
else {
1421+
VALUE n = INT2NUM(ndigits);
1422+
return f_round_common(1, &n, self, nurat_floor);
1423+
}
1424+
}
1425+
14141426
/*
14151427
* call-seq:
14161428
* rat.floor([ndigits]) -> integer or rational
@@ -2027,7 +2039,7 @@ rb_numeric_quo(VALUE x, VALUE y)
20272039
else {
20282040
x = rb_convert_type(x, T_RATIONAL, "Rational", "to_r");
20292041
}
2030-
return nurat_div(x, y);
2042+
return rb_rational_div(x, y);
20312043
}
20322044

20332045
VALUE
@@ -2734,10 +2746,10 @@ Init_Rational(void)
27342746

27352747
rb_define_method(rb_cRational, "-@", rb_rational_uminus, 0);
27362748
rb_define_method(rb_cRational, "+", rb_rational_plus, 1);
2737-
rb_define_method(rb_cRational, "-", nurat_sub, 1);
2749+
rb_define_method(rb_cRational, "-", rb_rational_minus, 1);
27382750
rb_define_method(rb_cRational, "*", rb_rational_mul, 1);
2739-
rb_define_method(rb_cRational, "/", nurat_div, 1);
2740-
rb_define_method(rb_cRational, "quo", nurat_div, 1);
2751+
rb_define_method(rb_cRational, "/", rb_rational_div, 1);
2752+
rb_define_method(rb_cRational, "quo", rb_rational_div, 1);
27412753
rb_define_method(rb_cRational, "fdiv", nurat_fdiv, 1);
27422754
rb_define_method(rb_cRational, "**", nurat_expt, 1);
27432755

test/ruby/test_arithmetic_sequence.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,11 @@ def test_to_a_bug15444
284284
'[ruby-core:90648] [Bug #15444]')
285285
end
286286

287+
def test_last_bug17218
288+
seq = (1.0997r .. 1.1r).step(0.0001r)
289+
assert_equal([1.0997r, 1.0998r, 1.0999r, 1.1r], seq.to_a, '[ruby-core:100312] [Bug #17218]')
290+
end
291+
287292
def test_slice
288293
seq = 1.step(10, 2)
289294
assert_equal([[1, 3, 5], [7, 9]], seq.each_slice(3).to_a)

version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
33
#define RUBY_VERSION_TEENY 3
44
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
5-
#define RUBY_PATCHLEVEL 172
5+
#define RUBY_PATCHLEVEL 173
66

77
#define RUBY_RELEASE_YEAR 2021
88
#define RUBY_RELEASE_MONTH 3

0 commit comments

Comments
 (0)