summaryrefslogtreecommitdiff
path: root/bignum.c
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-07-16 09:08:58 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-07-16 09:08:58 +0000
commit94735e9e54b7a64af86adf36ad8a5b849f11a938 (patch)
treeb7cfebe287720b03fa19e36c35e12b3e69cfef3e /bignum.c
parent984729ba3016a1fd4b371edef71fcb8b7f3956b4 (diff)
* 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.c30
1 files changed, 29 insertions, 1 deletions
diff --git a/bignum.c b/bignum.c
index 32dace5d6f..18d564ebb5 100644
--- a/bignum.c
+++ b/bignum.c
@@ -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);
}
/*