summaryrefslogtreecommitdiff
path: root/numeric.c
diff options
context:
space:
mode:
authorKenta Murata <mrkn@users.noreply.github.com>2020-12-09 18:48:59 +0900
committerGitHub <noreply@github.com>2020-12-09 18:48:59 +0900
commitfad3023e94c45e7f03478732f7641b6f39ba9d12 (patch)
treea53e562ae444a5b3f8d76308af62afd2f5c5c985 /numeric.c
parentcacdf2681dcc7c431973f33a18979b10566ec2f9 (diff)
Fix ArithmeticSequence#last and ArithmeticSequence#each for non-integer sequences (#3870)
[Bug #17218] [ruby-core:100312]
Notes
Notes: Merged-By: mrkn <mrkn@ruby-lang.org>
Diffstat (limited to 'numeric.c')
-rw-r--r--numeric.c53
1 files changed, 29 insertions, 24 deletions
diff --git a/numeric.c b/numeric.c
index fe0a186b18..ab6e6d9ebf 100644
--- a/numeric.c
+++ b/numeric.c
@@ -1078,8 +1078,8 @@ rb_float_plus(VALUE x, VALUE y)
* 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));
@@ -1935,6 +1935,31 @@ flo_prev_float(VALUE vx)
return flo_nextafter(vx, -HUGE_VAL);
}
+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
@@ -1977,31 +2002,11 @@ flo_prev_float(VALUE vx)
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);
}
/*
@@ -5749,7 +5754,7 @@ Init_Numeric(void)
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, "/", rb_float_div, 1);
rb_define_method(rb_cFloat, "quo", flo_quo, 1);