diff options
author | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-07-16 09:08:58 +0000 |
---|---|---|
committer | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-07-16 09:08:58 +0000 |
commit | 94735e9e54b7a64af86adf36ad8a5b849f11a938 (patch) | |
tree | b7cfebe287720b03fa19e36c35e12b3e69cfef3e /bignum.c | |
parent | 984729ba3016a1fd4b371edef71fcb8b7f3956b4 (diff) | |
download | ruby-94735e9e54b7a64af86adf36ad8a5b849f11a938.tar.gz |
* bignum.c (rb_big_float_cmp): compare an integer and float precisely.
[ruby-core:31376] [Bug #3589] reported by Tomasz Wegrzanowski.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36404 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'bignum.c')
-rw-r--r-- | bignum.c | 30 |
1 files changed, 29 insertions, 1 deletions
@@ -1435,6 +1435,8 @@ VALUE rb_big_float_cmp(VALUE x, VALUE y) { double a = RFLOAT_VALUE(y); + double yi, yf; + VALUE rel; if (isnan(a)) return Qnil; @@ -1442,15 +1444,41 @@ rb_big_float_cmp(VALUE x, VALUE y) if (a > 0.0) return INT2FIX(-1); else return INT2FIX(1); } + yf = modf(a, &yi); if (FIXNUM_P(x)) { +#if SIZEOF_LONG * CHAR_BIT < DBL_MANT_DIG /* assume FLT_RADIX == 2 */ double xd = (double)FIX2LONG(x); if (xd < a) return INT2FIX(-1); if (xd > a) return INT2FIX(1); return INT2FIX(0); +#else + long xl, yl; + if (yi < LONG_MIN) + return INT2FIX(1); + if (LONG_MAX < yi) + return INT2FIX(-1); + xl = FIX2LONG(x); + yl = (long)yi; + if (xl < yl) + return INT2FIX(-1); + if (xl > yl) + return INT2FIX(1); + if (yf < 0.0) + return INT2FIX(1); + if (0.0 < yf) + return INT2FIX(-1); + return INT2FIX(0); +#endif } - return rb_dbl_cmp(rb_big2dbl(x), a); + y = rb_dbl2big(yi); + rel = rb_big_cmp(x, y); + if (yf == 0.0 || rel != INT2FIX(0)) + return rel; + if (yf < 0.0) + return INT2FIX(1); + return INT2FIX(-1); } /* |