diff --git a/array.c b/array.c index 990bc076b1..8a9bcf59be 100644 --- a/array.c +++ b/array.c @@ -5423,7 +5423,7 @@ rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj) n = RARRAY_AREF(args, 0); } if (RARRAY_LEN(self) == 0) return INT2FIX(0); - if (n == Qnil) return DBL2NUM(HUGE_VAL); + if (n == Qnil) return rb_float_positive_infinity; mul = NUM2LONG(n); if (mul <= 0) return INT2FIX(0); n = LONG2FIX(mul); diff --git a/enum.c b/enum.c index a739d335a9..2fe281a6af 100644 --- a/enum.c +++ b/enum.c @@ -2937,7 +2937,7 @@ enum_cycle_size(VALUE self, VALUE args, VALUE eobj) size = enum_size(self, args, 0); if (NIL_P(size) || FIXNUM_ZERO_P(size)) return size; - if (NIL_P(n)) return DBL2NUM(HUGE_VAL); + if (NIL_P(n)) return rb_float_positive_infinity; if (mul <= 0) return INT2FIX(0); n = LONG2FIX(mul); return rb_funcallv(size, '*', 1, &n); diff --git a/enumerator.c b/enumerator.c index d2d3b29369..c8348d9414 100644 --- a/enumerator.c +++ b/enumerator.c @@ -3167,7 +3167,7 @@ arith_seq_size(VALUE self) } if (NIL_P(e)) { - return DBL2NUM(HUGE_VAL); + return rb_float_positive_infinity; } if (!rb_obj_is_kind_of(s, rb_cNumeric)) { @@ -3175,7 +3175,7 @@ arith_seq_size(VALUE self) } if (rb_equal(s, INT2FIX(0))) { - return DBL2NUM(HUGE_VAL); + return rb_float_positive_infinity; } len_1 = rb_int_idiv(rb_int_minus(e, b), s); diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h index d983114e0a..7f3b0ba9c9 100644 --- a/include/ruby/ruby.h +++ b/include/ruby/ruby.h @@ -2052,6 +2052,8 @@ RUBY_EXTERN VALUE rb_eMathDomainError; RUBY_EXTERN VALUE rb_stdin, rb_stdout, rb_stderr; +RUBY_EXTERN VALUE rb_float_negative_infinity, rb_float_positive_infinity; + static inline VALUE rb_class_of(VALUE obj) { diff --git a/internal.h b/internal.h index 1aad0c85a0..4f0d9335b8 100644 --- a/internal.h +++ b/internal.h @@ -1821,6 +1821,9 @@ rb_float_new_inline(double d) } /* out of range */ #endif + if (isinf(d)) { + return d < 0 ? rb_float_negative_infinity : rb_float_positive_infinity; + } return rb_float_new_in_heap(d); } diff --git a/math.c b/math.c index 509cd46ef2..859b7d58f5 100644 --- a/math.c +++ b/math.c @@ -382,8 +382,8 @@ math_atanh(VALUE unused_obj, VALUE x) /* check for domain error */ if (d < -1.0 || +1.0 < d) domain_error("atanh"); /* check for pole error */ - if (d == -1.0) return DBL2NUM(-HUGE_VAL); - if (d == +1.0) return DBL2NUM(+HUGE_VAL); + if (d == -1.0) return rb_float_negative_infinity; + if (d == +1.0) return rb_float_positive_infinity; return DBL2NUM(atanh(d)); } @@ -538,7 +538,7 @@ math_log2(VALUE unused_obj, VALUE x) /* check for domain error */ if (d < 0.0) domain_error("log2"); /* check for pole error */ - if (d == 0.0) return DBL2NUM(-HUGE_VAL); + if (d == 0.0) return rb_float_negative_infinity; return DBL2NUM(log2(d) + numbits); /* log2(d * 2 ** numbits) */ } @@ -568,7 +568,7 @@ math_log10(VALUE unused_obj, VALUE x) /* check for domain error */ if (d < 0.0) domain_error("log10"); /* check for pole error */ - if (d == 0.0) return DBL2NUM(-HUGE_VAL); + if (d == 0.0) return rb_float_negative_infinity; return DBL2NUM(log10(d) + numbits * log10(2)); /* log10(d * 2 ** numbits) */ } @@ -869,10 +869,10 @@ math_gamma(VALUE unused_obj, VALUE x) /* check for domain error */ if (isinf(d)) { if (signbit(d)) domain_error("gamma"); - return DBL2NUM(HUGE_VAL); + return rb_float_positive_infinity; } if (d == 0.0) { - return signbit(d) ? DBL2NUM(-HUGE_VAL) : DBL2NUM(HUGE_VAL); + return signbit(d) ? rb_float_negative_infinity : rb_float_positive_infinity; } if (d == floor(d)) { if (d < 0.0) domain_error("gamma"); @@ -907,11 +907,11 @@ math_lgamma(VALUE unused_obj, VALUE x) /* check for domain error */ if (isinf(d)) { if (signbit(d)) domain_error("lgamma"); - return rb_assoc_new(DBL2NUM(HUGE_VAL), INT2FIX(1)); + return rb_assoc_new(rb_float_positive_infinity, INT2FIX(1)); } if (d == 0.0) { VALUE vsign = signbit(d) ? INT2FIX(-1) : INT2FIX(+1); - return rb_assoc_new(DBL2NUM(HUGE_VAL), vsign); + return rb_assoc_new(rb_float_positive_infinity, vsign); } v = DBL2NUM(lgamma_r(d, &sign)); return rb_assoc_new(v, INT2FIX(sign)); diff --git a/numeric.c b/numeric.c index ef7c58e870..270c31b17f 100644 --- a/numeric.c +++ b/numeric.c @@ -186,6 +186,8 @@ VALUE rb_cFixnum; VALUE rb_eZeroDivError; VALUE rb_eFloatDomainError; +VALUE rb_float_negative_infinity, rb_float_positive_infinity; + static ID id_to, id_by; void @@ -2549,7 +2551,7 @@ ruby_num_interval_step_size(VALUE from, VALUE to, VALUE step, int excl) diff = FIX2LONG(step); if (diff == 0) { - return DBL2NUM(HUGE_VAL); + return rb_float_positive_infinity; } delta = FIX2LONG(to) - FIX2LONG(from); if (diff < 0) { @@ -2575,7 +2577,7 @@ ruby_num_interval_step_size(VALUE from, VALUE to, VALUE step, int excl) VALUE result; ID cmp = '>'; switch (rb_cmpint(rb_num_coerce_cmp(step, INT2FIX(0), id_cmp), step, INT2FIX(0))) { - case 0: return DBL2NUM(HUGE_VAL); + case 0: return rb_float_positive_infinity; case -1: cmp = '<'; break; } if (RTEST(rb_funcall(from, cmp, 1, to))) return INT2FIX(0); @@ -2656,7 +2658,7 @@ num_step_check_fix_args(int argc, VALUE *to, VALUE *step, VALUE by, int fix_nil, } desc = num_step_negative_p(*step); if (fix_nil && NIL_P(*to)) { - *to = desc ? DBL2NUM(-HUGE_VAL) : DBL2NUM(HUGE_VAL); + *to = desc ? rb_float_negative_infinity : rb_float_positive_infinity; } return desc; } @@ -4050,7 +4052,7 @@ fix_pow(VALUE x, VALUE y) if (b == 1) return x; if (a == 0) { if (b > 0) return INT2FIX(0); - return DBL2NUM(HUGE_VAL); + return rb_float_positive_infinity; } return int_pow(a, b); } @@ -4078,7 +4080,7 @@ fix_pow(VALUE x, VALUE y) double dy = RFLOAT_VALUE(y); if (dy == 0.0) return DBL2NUM(1.0); if (a == 0) { - return DBL2NUM(dy < 0 ? HUGE_VAL : 0.0); + return dy < 0 ? rb_float_positive_infinity : DBL2NUM(0.0); } if (a == 1) return DBL2NUM(1.0); { @@ -5664,7 +5666,8 @@ Init_Numeric(void) /* * An expression representing positive infinity. */ - rb_define_const(rb_cFloat, "INFINITY", DBL2NUM(HUGE_VAL)); + rb_define_const(rb_cFloat, "INFINITY", + rb_float_positive_infinity = rb_float_new_in_heap(HUGE_VAL)); /* * An expression representing a value which is "not a number". */ @@ -5715,6 +5718,9 @@ Init_Numeric(void) id_to = rb_intern("to"); id_by = rb_intern("by"); + + rb_float_negative_infinity = rb_float_new_in_heap(-HUGE_VAL); + rb_gc_register_mark_object(rb_float_negative_infinity); } #undef rb_float_value diff --git a/parse.y b/parse.y index 278c5b0296..6e757cdf69 100644 --- a/parse.y +++ b/parse.y @@ -10001,7 +10001,12 @@ negate_lit(struct parser_params *p, VALUE lit) RCOMPLEX_SET_IMAG(lit, negate_lit(p, RCOMPLEX(lit)->imag)); break; case T_FLOAT: - RFLOAT(lit)->float_value = -RFLOAT_VALUE(lit); + if (lit == rb_float_positive_infinity) { + lit = rb_float_negative_infinity; + } + else { + RFLOAT(lit)->float_value = -RFLOAT_VALUE(lit); + } break; unknown: default: diff --git a/range.c b/range.c index dab8314400..d0ae945e71 100644 --- a/range.c +++ b/range.c @@ -767,7 +767,7 @@ range_size(VALUE range) return ruby_num_interval_step_size(b, e, INT2FIX(1), EXCL(range)); } if (NIL_P(e)) { - return DBL2NUM(HUGE_VAL); + return rb_float_positive_infinity; } } diff --git a/rational.c b/rational.c index 076d42707f..4a05aadbcf 100644 --- a/rational.c +++ b/rational.c @@ -2442,7 +2442,7 @@ parse_rat(const char *s, const char *const e, int strict, int raise) VALUE mul; if (!FIXNUM_P(nexp)) { overflow: - return sign == '-' ? DBL2NUM(-HUGE_VAL) : DBL2NUM(HUGE_VAL); + return sign == '-' ? rb_float_negative_infinity : rb_float_positive_infinity; } mul = f_expt10(LONG2NUM(-FIX2LONG(nexp))); if (RB_FLOAT_TYPE_P(mul)) goto overflow; diff --git a/test/ruby/test_float.rb b/test/ruby/test_float.rb index 3453440694..82bb2d6bd5 100644 --- a/test/ruby/test_float.rb +++ b/test/ruby/test_float.rb @@ -961,4 +961,13 @@ class Float end end; end + + def test_predefined_infinity + assert_same(-Float::INFINITY, -1e1020) + assert_same(-Float::INFINITY, -1*Float::INFINITY) + assert_same(-Float::INFINITY, 1/-0.0) + assert_same(Float::INFINITY, 1e1020) + assert_same(Float::INFINITY, Float::INFINITY+1) + assert_same(Float::INFINITY, 1/0.0) + end end diff --git a/vm_eval.c b/vm_eval.c index a8764e2fa4..e4aaf10b6e 100644 --- a/vm_eval.c +++ b/vm_eval.c @@ -1068,7 +1068,7 @@ loop_stop(VALUE dummy, VALUE exc) static VALUE rb_f_loop_size(VALUE self, VALUE args, VALUE eobj) { - return DBL2NUM(HUGE_VAL); + return rb_float_positive_infinity; } /*