[前][次][番号順一覧][スレッド一覧]

ruby-changes:52685

From: nobu <ko1@a...>
Date: Wed, 3 Oct 2018 01:42:28 +0900 (JST)
Subject: [ruby-changes:52685] nobu:r64897 (trunk): Fix Rational of Float

nobu	2018-10-03 01:42:21 +0900 (Wed, 03 Oct 2018)

  New Revision: 64897

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=64897

  Log:
    Fix Rational of Float
    
    [ruby-core:89239] [Bug #15189]

  Modified files:
    trunk/bignum.c
    trunk/numeric.c
    trunk/object.c
    trunk/rational.c
    trunk/test/ruby/test_integer.rb
Index: bignum.c
===================================================================
--- bignum.c	(revision 64896)
+++ bignum.c	(revision 64897)
@@ -6207,6 +6207,7 @@ rb_big_pow(VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/bignum.c#L6207
 
   again:
     if (y == INT2FIX(0)) return INT2FIX(1);
+    if (y == INT2FIX(1)) return x;
     if (RB_FLOAT_TYPE_P(y)) {
 	d = RFLOAT_VALUE(y);
 	if ((BIGNUM_NEGATIVE_P(x) && !BIGZEROP(x))) {
@@ -6223,8 +6224,13 @@ rb_big_pow(VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/bignum.c#L6224
     else if (FIXNUM_P(y)) {
 	yy = FIX2LONG(y);
 
-	if (yy < 0)
-	    return rb_rational_raw(INT2FIX(1), rb_big_pow(x, INT2NUM(-yy)));
+        if (yy < 0) {
+            x = rb_big_pow(x, INT2NUM(-yy));
+            if (RB_INTEGER_TYPE_P(x))
+                return rb_rational_raw(INT2FIX(1), x);
+            else
+                return DBL2NUM(1.0 / NUM2DBL(x));
+        }
 	else {
 	    VALUE z = 0;
 	    SIGNED_VALUE mask;
Index: numeric.c
===================================================================
--- numeric.c	(revision 64896)
+++ numeric.c	(revision 64897)
@@ -4015,7 +4015,8 @@ fix_pow(VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/numeric.c#L4015
 	}
 	if (b < 0) {
 	    if (a == 0) rb_num_zerodiv();
-	    return rb_rational_raw(INT2FIX(1), rb_int_pow(x, LONG2NUM(-b)));
+            y = rb_int_pow(x, LONG2NUM(-b));
+            goto inverted;
 	}
 
 	if (b == 0) return INT2FIX(1);
@@ -4035,10 +4036,10 @@ fix_pow(VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/numeric.c#L4036
 	if (BIGNUM_NEGATIVE_P(y)) {
 	    if (a == 0) rb_num_zerodiv();
             y = rb_int_pow(x, rb_big_uminus(y));
-            if (0 && RB_FLOAT_TYPE_P(y)) {
-                /* Maybe should return a Float */
+          inverted:
+            if (RB_FLOAT_TYPE_P(y)) {
                 double d = pow((double)a, RFLOAT_VALUE(y));
-                return DBL2NUM(d);
+                return DBL2NUM(1.0 / d);
             }
             return rb_rational_raw(INT2FIX(1), y);
 	}
Index: object.c
===================================================================
--- object.c	(revision 64896)
+++ object.c	(revision 64897)
@@ -3421,9 +3421,18 @@ rb_str_to_dbl(VALUE str, int badcheck) https://github.com/ruby/ruby/blob/trunk/object.c#L3421
 #define big2dbl_without_to_f(x) rb_big2dbl(x)
 #define int2dbl_without_to_f(x) \
     (FIXNUM_P(x) ? fix2dbl_without_to_f(x) : big2dbl_without_to_f(x))
-#define rat2dbl_without_to_f(x) \
-    (int2dbl_without_to_f(rb_rational_num(x)) / \
-     int2dbl_without_to_f(rb_rational_den(x)))
+static inline double
+rat2dbl_without_to_f(VALUE x)
+{
+    VALUE num = rb_rational_num(x);
+    VALUE den = rb_rational_den(x);
+    if (RB_INTEGER_TYPE_P(num) && RB_INTEGER_TYPE_P(den)) {
+        return int2dbl_without_to_f(num) / int2dbl_without_to_f(den);
+    }
+    else {
+        return NUM2DBL(num) / NUM2DBL(den);
+    }
+}
 
 #define special_const_to_float(val, pre, post) \
     switch (val) { \
Index: test/ruby/test_integer.rb
===================================================================
--- test/ruby/test_integer.rb	(revision 64896)
+++ test/ruby/test_integer.rb	(revision 64897)
@@ -27,6 +27,29 @@ class TestInteger < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_integer.rb#L27
 
     x = EnvUtil.suppress_warning {2 ** -0x4000000000000000}
     assert_in_delta(0.0, (x / 2), Float::EPSILON)
+
+    <<~EXPRS.each_line.with_index(__LINE__+1) do |expr, line|
+      crash01: 111r+11**-11111161111111
+      crash02: 1118111111111**-1111111111111111**1+1==11111
+      crash03: -1111111**-1111*11 - -1111111** -111111111
+      crash04: 1118111111111** -1111111111111111**1+11111111111**1 ===111
+      crash05: 11** -111155555555555555  -55   !=5-555
+      crash07: 1 + 111111111**-1111811111
+      crash08: 18111111111**-1111111111111111**1 + 1111111111**-1111**1
+      crash10: -7 - -1111111** -1111**11
+      crash12: 1118111111111** -1111111111111111**1 + 1111 - -1111111** -1111*111111111119
+      crash13: 1.0i - -1111111** -111111111
+      crash14: 11111**111111111**111111 * -11111111111111111111**-111111111111
+      crash15: ~1**1111 + -~1**~1**111
+      crash17: 11** -1111111**1111 /11i
+      crash18: 5555i**-5155 - -9111111**-1111**11
+      crash19: 111111*-11111111111111111111**-1111111111111111
+      crash20: 1111**111-11**-11111**11
+      crash21: 11**-10111111119-1i -1r
+    EXPRS
+      name, expr = expr.split(':', 2)
+      assert_ruby_status(%w"-W0", expr, name)
+    end
   end
 
   def test_lshift
Index: rational.c
===================================================================
--- rational.c	(revision 64896)
+++ rational.c	(revision 64897)
@@ -696,7 +696,8 @@ f_addsub(VALUE self, VALUE anum, VALUE a https://github.com/ruby/ruby/blob/trunk/rational.c#L696
 	a = rb_int_idiv(bden, g);
 	den = rb_int_mul(a, b);
     }
-    else {
+    else if (RB_INTEGER_TYPE_P(anum) && RB_INTEGER_TYPE_P(aden) &&
+             RB_INTEGER_TYPE_P(bnum) && RB_INTEGER_TYPE_P(bden)) {
 	VALUE g = f_gcd(aden, bden);
 	VALUE a = rb_int_mul(anum, rb_int_idiv(bden, g));
 	VALUE b = rb_int_mul(bnum, rb_int_idiv(aden, g));
@@ -713,6 +714,12 @@ f_addsub(VALUE self, VALUE anum, VALUE a https://github.com/ruby/ruby/blob/trunk/rational.c#L714
 	a = rb_int_idiv(bden, g);
 	den = rb_int_mul(a, b);
     }
+    else {
+        double a = NUM2DBL(anum) / NUM2DBL(aden);
+        double b = NUM2DBL(bnum) / NUM2DBL(bden);
+        double c = k == '+' ? a + b : a - b;
+        return DBL2NUM(c);
+    }
     return f_rational_new_no_reduce2(CLASS_OF(self), num, den);
 }
 
@@ -1144,9 +1151,9 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/rational.c#L1151
 nurat_eqeq_p(VALUE self, VALUE other)
 {
     if (RB_INTEGER_TYPE_P(other)) {
-	{
-	    get_dat1(self);
+        get_dat1(self);
 
+        if (RB_INTEGER_TYPE_P(dat->num) && RB_INTEGER_TYPE_P(dat->den)) {
 	    if (INT_ZERO_P(dat->num) && INT_ZERO_P(other))
 		return Qtrue;
 
@@ -1156,6 +1163,10 @@ nurat_eqeq_p(VALUE self, VALUE other) https://github.com/ruby/ruby/blob/trunk/rational.c#L1163
 		return Qfalse;
 	    return rb_int_equal(dat->num, other);
 	}
+        else {
+            const double d = nurat_to_double(self);
+            return f_boolcast(FIXNUM_ZERO_P(rb_dbl_cmp(d, NUM2DBL(other))));
+        }
     }
     else if (RB_FLOAT_TYPE_P(other)) {
 	const double d = nurat_to_double(self);
@@ -1544,6 +1555,10 @@ static double https://github.com/ruby/ruby/blob/trunk/rational.c#L1555
 nurat_to_double(VALUE self)
 {
     get_dat1(self);
+    if (!RB_INTEGER_TYPE_P(dat->num) || !RB_INTEGER_TYPE_P(dat->den)) {
+        double d = NUM2DBL(dat->num) / NUM2DBL(dat->den);
+        return DBL2NUM(d);
+    }
     return rb_int_fdiv_double(dat->num, dat->den);
 }
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]