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

ruby-changes:17637

From: nobu <ko1@a...>
Date: Sat, 30 Oct 2010 17:23:50 +0900 (JST)
Subject: [ruby-changes:17637] Ruby:r29645 (trunk): * util.c (ruby_strtod): get rid of overflow/underflow as possible.

nobu	2010-10-30 17:23:40 +0900 (Sat, 30 Oct 2010)

  New Revision: 29645

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=29645

  Log:
    * util.c (ruby_strtod): get rid of overflow/underflow as possible.

  Modified files:
    trunk/ChangeLog
    trunk/test/ruby/test_float.rb
    trunk/util.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 29644)
+++ ChangeLog	(revision 29645)
@@ -1,3 +1,7 @@
+Sat Oct 30 17:23:19 2010  Nobuyoshi Nakada  <nobu@r...>
+
+	* util.c (ruby_strtod): get rid of overflow/underflow as possible.
+
 Sat Oct 30 14:37:39 2010  Nobuyoshi Nakada  <nobu@r...>
 
 	* configure.in (ruby_pc): erase runtime-defined variables and
Index: util.c
===================================================================
--- util.c	(revision 29644)
+++ util.c	(revision 29645)
@@ -2122,22 +2122,39 @@
 	    static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF";
 	    s0 = ++s;
 	    adj = 0;
-	    aadj = -1;
+	    aadj = 1.0;
+	    nd0 = -4;
 
 	    if (!*++s || !(s1 = strchr(hexdigit, *s))) goto ret0;
-	    do {
-		adj *= 16;
-		adj += (s1 - hexdigit) & 15;
-	    } while (*++s && (s1 = strchr(hexdigit, *s)));
+	    while (*s == '0') s++;
+	    if ((s1 = strchr(hexdigit, *s)) != NULL) {
+		do {
+		    adj += aadj * ((s1 - hexdigit) & 15);
+		    nd0 += 4;
+		    aadj /= 16;
+		} while (*++s && (s1 = strchr(hexdigit, *s)));
+	    }
 
 	    if (*s == '.') {
-		aadj = 1.;
+		dsign = 1;
 		if (!*++s || !(s1 = strchr(hexdigit, *s))) goto ret0;
-		do {
-		    aadj /= 16;
+		if (nd0 < 0) {
+		    while (*s == '0') {
+			s++;
+			nd0 -= 4;
+		    }
+		}
+		for (; *s && (s1 = strchr(hexdigit, *s)); ++s) {
 		    adj += aadj * ((s1 - hexdigit) & 15);
-		} while (*++s && (s1 = strchr(hexdigit, *s)));
+		    if ((aadj /= 16) == 0.0) {
+			while (strchr(hexdigit, *++s));
+			break;
+		    }
+		}
 	    }
+	    else {
+		dsign = 0;
+	    }
 
 	    if (*s == 'P' || *s == 'p') {
 		dsign = 0x2C - *++s; /* +: 2B, -: 2D */
@@ -2153,17 +2170,16 @@
 		    nd -= '0';
 		    c = *++s;
 		    /* Float("0x0."+("0"*267)+"1fp2095") */
-		    if (abs(nd) > 2095) {
+		    if (nd + dsign * nd0 > 2095) {
 			while ('0' <= c && c <= '9') c = *++s;
 			break;
 		    }
 		} while ('0' <= c && c <= '9');
-		dval(rv) = ldexp(adj, nd * dsign);
 	    }
 	    else {
-		if (aadj != -1) goto ret0;
-		dval(rv) = adj;
+		if (dsign) goto ret0;
 	    }
+	    dval(rv) = ldexp(adj, nd * dsign + nd0);
 	    goto ret;
 	}
         nz0 = 1;
Index: test/ruby/test_float.rb
===================================================================
--- test/ruby/test_float.rb	(revision 29644)
+++ test/ruby/test_float.rb	(revision 29645)
@@ -102,7 +102,14 @@
     assert_equal(0.0009765625, Float("0x1p-10"))
     assert_equal(2.6881171418161356e+43, Float("0x1.3494a9b171bf5p+144"))
     assert_equal(-3.720075976020836e-44, Float("-0x1.a8c1f14e2af5dp-145"))
- 
+    assert_equal(31.0*2**1019, Float("0x0."+("0"*268)+"1fp2099"))
+    assert_equal(31.0*2**1019, Float("0x0."+("0"*600)+"1fp3427"))
+    assert_equal(-31.0*2**1019, Float("-0x0."+("0"*268)+"1fp2099"))
+    assert_equal(-31.0*2**1019, Float("-0x0."+("0"*600)+"1fp3427"))
+    assert_equal(31.0*2**-1027, Float("0x1f"+("0"*268)+".0p-2099"))
+    assert_equal(31.0*2**-1027, Float("0x1f"+("0"*600)+".0p-3427"))
+    assert_equal(-31.0*2**-1027, Float("-0x1f"+("0"*268)+".0p-2099"))
+    assert_equal(-31.0*2**-1027, Float("-0x1f"+("0"*600)+".0p-3427"))
   end
 
   def test_divmod

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

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