From 7ed0640ffb938fcf246f5167c7062fbf2a46dcd3 Mon Sep 17 00:00:00 2001 From: naruse Date: Tue, 29 Dec 2009 07:05:39 +0000 Subject: [PATCH] Add Float::INFINITY and Float::NAN. * numeric.c (Init_Numeric): Add Float::INFINITY and Float::NAN. [ruby-dev:1657] [ruby-dev:4760] [ruby-list:7023] [ruby-list:46690] [ruby-core:26632] [ruby-talk:41352] [ruby-talk:203333] * include/ruby/defines.h (INFINITY): defined. * include/ruby/defines.h (NAN): defined. * include/ruby/util.h (ruby_div0): removed. * numeric.c (fix_pow): use INFINITY and NAN instead of ruby_div0(1.0). * marshal.c (r_object0): ditto. * bignum.c (big_fdiv): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@26197 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 20 ++++++++++++++++++++ bignum.c | 2 +- include/ruby/defines.h | 14 ++++++++++++++ include/ruby/util.h | 6 ------ marshal.c | 8 +++----- numeric.c | 22 ++++++++++++++++++---- test/ruby/test_float.rb | 22 +++++++++++----------- 7 files changed, 67 insertions(+), 27 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3a0aced8856d91..fea095dd3c9ba0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +Tue Dec 29 16:03:33 2009 NARUSE, Yui + + * numeric.c (Init_Numeric): Add Float::INFINITY and Float::NAN. + [ruby-dev:1657] [ruby-dev:4760] [ruby-list:7023] + [ruby-list:46690] + [ruby-core:26632] [ruby-talk:41352] [ruby-talk:203333] + + * include/ruby/defines.h (INFINITY): defined. + + * include/ruby/defines.h (NAN): defined. + + * include/ruby/util.h (ruby_div0): removed. + + * numeric.c (fix_pow): use INFINITY and NAN + instead of ruby_div0(1.0). + + * marshal.c (r_object0): ditto. + + * bignum.c (big_fdiv): ditto. + Tue Dec 29 10:36:23 2009 Nobuyoshi Nakada * lib/rexml/parsers/baseparser.rb (REXML::Parsers::BaseParser::STANDALONE): diff --git a/bignum.c b/bignum.c index f6fca9f546e115..7489ba523186e9 100644 --- a/bignum.c +++ b/bignum.c @@ -2485,7 +2485,7 @@ big_fdiv(VALUE x, VALUE y) #if SIZEOF_LONG > SIZEOF_INT { /* Visual C++ can't be here */ - if (l > INT_MAX) return DBL2NUM(ruby_div0(1.0)); + if (l > INT_MAX) return DBL2NUM(INFINITY); if (l < INT_MIN) return DBL2NUM(0.0); } #endif diff --git a/include/ruby/defines.h b/include/ruby/defines.h index 70b16858042486..a81aef841647c6 100644 --- a/include/ruby/defines.h +++ b/include/ruby/defines.h @@ -99,6 +99,20 @@ void xfree(void*); # define BDIGIT_DBL_SIGNED long #endif +#ifdef INFINITY +# define HAVE_INFINITY +#else +extern const unsigned char rb_infinity[]; +# define INFINITY (*(double *)rb_infinity) +#endif + +#ifdef NAN +# define HAVE_NAN +#else +extern const unsigned char rb_nan[]; +# define NAN (*(double *)rb_nan) +#endif + #ifdef __CYGWIN__ #undef _WIN32 #endif diff --git a/include/ruby/util.h b/include/ruby/util.h index 1c52c576da8f67..0c1e1c4ebc9bb6 100644 --- a/include/ruby/util.h +++ b/include/ruby/util.h @@ -74,12 +74,6 @@ double ruby_strtod(const char *, char **); #pragma warning(push) #pragma warning(disable:4723) #endif -static inline double -ruby_div0(double x) -{ - double t = 0.0; - return x / t; -} #if defined _MSC_VER && _MSC_VER >= 1300 #pragma warning(pop) #endif diff --git a/marshal.c b/marshal.c index 549a6f6c0c61f2..be33546a8963f0 100644 --- a/marshal.c +++ b/marshal.c @@ -1322,8 +1322,6 @@ obj_alloc_by_path(VALUE path, struct load_arg *arg) return rb_obj_alloc(klass); } -#define div0(x) ruby_div0(x) - static int has_encoding(struct load_arg *arg) { @@ -1449,13 +1447,13 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod) const char *ptr = RSTRING_PTR(str); if (strcmp(ptr, "nan") == 0) { - d = div0(0.0); + d = NAN; } else if (strcmp(ptr, "inf") == 0) { - d = div0(+1.0); + d = INFINITY; } else if (strcmp(ptr, "-inf") == 0) { - d = div0(-1.0); + d = -INFINITY; } else { char *e; diff --git a/numeric.c b/numeric.c index 11d67fef5d91db..319f7b2c482b6a 100644 --- a/numeric.c +++ b/numeric.c @@ -63,6 +63,20 @@ #define DBL_EPSILON 2.2204460492503131e-16 #endif +#ifdef HAVE_INFINITY +#elif BYTE_ORDER == LITTLE_ENDIAN +const unsigned char rb_infinity[] = "\x00\x00\x00\x00\x00\x00\xf0\x7f"; +#else +const unsigned char rb_infinity[] = "\x7f\xf0\x00\x00\x00\x00\x00\x00"; +#endif + +#ifdef HAVE_NAN +#elif BYTE_ORDER == LITTLE_ENDIAN +const unsigned char rb_nan[] = "\x00\x00\x00\x00\x00\x00\xf8\x7f"; +#else +const unsigned char rb_nan[] = "\x7f\xf8\x00\x00\x00\x00\x00\x00"; +#endif + extern double round(double); #ifndef HAVE_ROUND @@ -2467,8 +2481,6 @@ int_pow(long x, unsigned long y) return LONG2NUM(z); } -#define infinite_value() ruby_div0(1.0) - /* * call-seq: * fix ** numeric -> numeric_result @@ -2496,7 +2508,7 @@ fix_pow(VALUE x, VALUE y) if (b == 1) return x; if (a == 0) { if (b > 0) return INT2FIX(0); - return DBL2NUM(infinite_value()); + return DBL2NUM(INFINITY); } if (a == 1) return INT2FIX(1); if (a == -1) { @@ -2524,7 +2536,7 @@ fix_pow(VALUE x, VALUE y) case T_FLOAT: if (RFLOAT_VALUE(y) == 0.0) return DBL2NUM(1.0); if (a == 0) { - return DBL2NUM(RFLOAT_VALUE(y) < 0 ? infinite_value() : 0.0); + return DBL2NUM(RFLOAT_VALUE(y) < 0 ? INFINITY : 0.0); } if (a == 1) return DBL2NUM(1.0); { @@ -3305,6 +3317,8 @@ Init_Numeric(void) rb_define_const(rb_cFloat, "MIN", DBL2NUM(DBL_MIN)); rb_define_const(rb_cFloat, "MAX", DBL2NUM(DBL_MAX)); rb_define_const(rb_cFloat, "EPSILON", DBL2NUM(DBL_EPSILON)); + rb_define_const(rb_cFloat, "INFINITY", DBL2NUM(INFINITY)); + rb_define_const(rb_cFloat, "NAN", DBL2NUM(NAN)); rb_define_method(rb_cFloat, "to_s", flo_to_s, 0); rb_define_method(rb_cFloat, "coerce", flo_coerce, 1); diff --git a/test/ruby/test_float.rb b/test/ruby/test_float.rb index 15e17ad92a68c4..c18e4f0422b1dd 100644 --- a/test/ruby/test_float.rb +++ b/test/ruby/test_float.rb @@ -24,7 +24,7 @@ def nan_test(x,y) assert_equal(false, (x >= y)) end def test_nan - nan = 0.0/0 + nan = Float::NAN nan_test(nan, nan) nan_test(nan, 0) nan_test(nan, 1) @@ -118,7 +118,7 @@ def test_remainder end def test_to_s - inf = 1.0 / 0.0 + inf = Float::INFINITY assert_equal("Infinity", inf.to_s) assert_equal("-Infinity", (-inf).to_s) assert_equal("NaN", (inf / inf).to_s) @@ -171,7 +171,7 @@ def test_divmod2 assert_equal([1.0, 0.0], 2.0.divmod(2.0)) assert_raise(TypeError) { 2.0.divmod(nil) } - inf = 1.0 / 0.0 + inf = Float::INFINITY assert_raise(ZeroDivisionError) {inf.divmod(0)} a, b = (2.0**32).divmod(1.0) @@ -186,8 +186,8 @@ def test_pow end def test_eql - inf = 1.0 / 0.0 - nan = inf / inf + inf = Float::INFINITY + nan = Float::NAN assert(1.0.eql?(1.0)) assert(inf.eql?(inf)) assert(!(nan.eql?(nan))) @@ -200,8 +200,8 @@ def test_eql end def test_cmp - inf = 1.0 / 0.0 - nan = inf / inf + inf = Float::INFINITY + nan = Float::NAN assert_equal(0, 1.0 <=> 1.0) assert_equal(1, 1.0 <=> 0.0) assert_equal(-1, 1.0 <=> 2.0) @@ -232,14 +232,14 @@ def test_zero_p end def test_infinite_p - inf = 1.0 / 0.0 + inf = Float::INFINITY assert(1, inf.infinite?) assert(1, (-inf).infinite?) assert_nil(1.0.infinite?) end def test_finite_p - inf = 1.0 / 0.0 + inf = Float::INFINITY assert(!(inf.finite?)) assert(!((-inf).finite?)) assert(1.0.finite?) @@ -266,7 +266,7 @@ def test_floor_ceil_round_truncate assert_equal(-2, (-2.0).round) assert_equal(-2, (-2.0).truncate) - inf = 1.0/0.0 + inf = Float::INFINITY assert_raise(FloatDomainError) { inf.floor } assert_raise(FloatDomainError) { inf.ceil } assert_raise(FloatDomainError) { inf.round } @@ -413,7 +413,7 @@ def test_Float assert(Float("1e10_00").infinite?) assert_raise(TypeError) { Float(nil) } o = Object.new - def o.to_f; inf = 1.0/0.0; inf/inf; end + def o.to_f; inf = Float::INFINITY; inf/inf; end assert(Float(o).nan?) end