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/