Skip to content

Commit 83fc915

Browse files
committed
Add new range check macro FIXABLE_FLOAT(); ref #3652
When MRB_INT64, valid value range of mrb_int is bigger than double, which only has 53 bits significant precision.
1 parent 3c31278 commit 83fc915

File tree

4 files changed

+17
-8
lines changed

4 files changed

+17
-8
lines changed

include/mruby/numeric.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ MRB_BEGIN_DECL
2020
#define NEGFIXABLE(f) ((f) >= MRB_INT_MIN)
2121
#define FIXABLE(f) (POSFIXABLE(f) && NEGFIXABLE(f))
2222

23+
#ifdef MRB_INT64
24+
#define FIXABLE_FLOAT(f) FIXABLE((mrb_int)(f))
25+
#else
26+
#define FIXABLE_FLOAT(f) FIXABLE(f)
27+
#endif
28+
2329
MRB_API mrb_value mrb_flo_to_fixnum(mrb_state *mrb, mrb_value val);
2430
MRB_API mrb_value mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, int base);
2531
/* ArgumentError if format string doesn't match /%(\.[0-9]+)?[aAeEfFgG]/ */

src/class.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -800,7 +800,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
800800
{
801801
mrb_float f = mrb_float(ARGV[arg_i]);
802802

803-
if (!FIXABLE(f)) {
803+
if (!FIXABLE_FLOAT(f)) {
804804
mrb_raise(mrb, E_RANGE_ERROR, "float too big for int");
805805
}
806806
*p = (mrb_int)f;

src/numeric.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ flo_shift(mrb_state *mrb, mrb_value x, mrb_int width)
392392
val *= 2;
393393
}
394394
}
395-
if (FIXABLE(val)) {
395+
if (FIXABLE_FLOAT(val)) {
396396
return mrb_fixnum_value((mrb_int)val);
397397
}
398398
return mrb_float_value(mrb, val);
@@ -515,7 +515,7 @@ flo_floor(mrb_state *mrb, mrb_value num)
515515
{
516516
mrb_float f = floor(mrb_float(num));
517517

518-
if (!FIXABLE(f)) {
518+
if (!FIXABLE_FLOAT(f)) {
519519
return mrb_float_value(mrb, f);
520520
}
521521
return mrb_fixnum_value((mrb_int)f);
@@ -540,7 +540,7 @@ flo_ceil(mrb_state *mrb, mrb_value num)
540540
{
541541
mrb_float f = ceil(mrb_float(num));
542542

543-
if (!FIXABLE(f)) {
543+
if (!FIXABLE_FLOAT(f)) {
544544
return mrb_float_value(mrb, f);
545545
}
546546
return mrb_fixnum_value((mrb_int)f);
@@ -661,7 +661,7 @@ flo_truncate(mrb_state *mrb, mrb_value num)
661661
if (f > 0.0) f = floor(f);
662662
if (f < 0.0) f = ceil(f);
663663

664-
if (!FIXABLE(f)) {
664+
if (!FIXABLE_FLOAT(f)) {
665665
mrb_check_num_exact(mrb, f);
666666
return mrb_float_value(mrb, f);
667667
}
@@ -1099,7 +1099,7 @@ mrb_flo_to_fixnum(mrb_state *mrb, mrb_value x)
10991099
if (isnan(d)) {
11001100
mrb_raise(mrb, E_FLOATDOMAIN_ERROR, "NaN");
11011101
}
1102-
if (FIXABLE(d)) {
1102+
if (FIXABLE_FLOAT(d)) {
11031103
z = (mrb_int)d;
11041104
}
11051105
else {

src/object.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -534,8 +534,11 @@ mrb_convert_to_integer(mrb_state *mrb, mrb_value val, int base)
534534
switch (mrb_type(val)) {
535535
case MRB_TT_FLOAT:
536536
if (base != 0) goto arg_error;
537-
if (FIXABLE(mrb_float(val))) {
538-
break;
537+
else {
538+
mrb_float f = mrb_float(val);
539+
if (FIXABLE_FLOAT(f)) {
540+
break;
541+
}
539542
}
540543
return mrb_flo_to_fixnum(mrb, val);
541544

0 commit comments

Comments
 (0)