summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-10-30 08:23:40 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-10-30 08:23:40 +0000
commit767fe5170d97461be5c79936b467dee3d4eb7179 (patch)
treee2bb64fac1f3a143f7e96b84358dbe4fa9775da8
parentbd7daa5ac5923692eb145d8f989efde689101d00 (diff)
* util.c (ruby_strtod): get rid of overflow/underflow as possible.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@29645 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog4
-rw-r--r--test/ruby/test_float.rb9
-rw-r--r--util.c42
3 files changed, 41 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index 4a9d1ab7fb..6c16c22e66 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+Sat Oct 30 17:23:19 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * util.c (ruby_strtod): get rid of overflow/underflow as possible.
+
Sat Oct 30 14:37:39 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
* configure.in (ruby_pc): erase runtime-defined variables and
diff --git a/test/ruby/test_float.rb b/test/ruby/test_float.rb
index dd61f1919b..7ab4ffc649 100644
--- a/test/ruby/test_float.rb
+++ b/test/ruby/test_float.rb
@@ -102,7 +102,14 @@ class TestFloat < Test::Unit::TestCase
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
diff --git a/util.c b/util.c
index 19602420b5..99b8a3fd9b 100644
--- a/util.c
+++ b/util.c
@@ -2122,21 +2122,38 @@ break2:
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') {
@@ -2153,17 +2170,16 @@ break2:
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;