diff options
author | Nobuyoshi Nakada <[email protected]> | 2024-09-05 22:08:41 +0900 |
---|---|---|
committer | Nobuyoshi Nakada <[email protected]> | 2024-10-05 23:29:42 +0900 |
commit | d17edf3a170b733356836353508319443d12c53c (patch) | |
tree | 94ccc35d2b289c15276f16c9f1c98454ff5d8102 | |
parent | f37e6d7f7b9dd0fac4fe01637a410dc4752a7ded (diff) |
[Bug #20705] Update `strtod` implementation
The absence of either the integer or fractional part should be
allowed.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/11807
-rw-r--r-- | missing/dtoa.c | 16 | ||||
-rw-r--r-- | spec/ruby/core/string/modulo_spec.rb | 4 | ||||
-rw-r--r-- | test/ruby/test_float.rb | 26 |
3 files changed, 20 insertions, 26 deletions
diff --git a/missing/dtoa.c b/missing/dtoa.c index bce2cb22a1..477b212a1b 100644 --- a/missing/dtoa.c +++ b/missing/dtoa.c @@ -1552,7 +1552,7 @@ break2: aadj = 1.0; nd0 = -4; - if (!*++s || !(s1 = strchr(hexdigit, *s))) goto ret0; + if (!*++s || (!(s1 = strchr(hexdigit, *s)) && *s != '.')) goto ret0; if (*s == '0') { while (*++s == '0'); if (!*s) goto ret; @@ -1566,9 +1566,7 @@ break2: } while (*++s && (s1 = strchr(hexdigit, *s))); } - if (*s == '.') { - dsign = 1; - if (!*++s || !(s1 = strchr(hexdigit, *s))) goto ret0; + if ((*s == '.') && *++s && (s1 = strchr(hexdigit, *s))) { if (nd0 < 0) { while (*s == '0') { s++; @@ -1583,9 +1581,6 @@ break2: } } } - else { - dsign = 0; - } if (*s == 'P' || *s == 'p') { dsign = 0x2C - *++s; /* +: 2B, -: 2D */ @@ -1608,9 +1603,6 @@ break2: } while ('0' <= c && c <= '9'); nd0 += nd * dsign; } - else { - if (dsign) goto ret0; - } dval(rv) = ldexp(adj, nd0); goto ret; } @@ -1647,9 +1639,9 @@ break2: } #endif if (c == '.') { - if (!ISDIGIT(s[1])) - goto dig_done; c = *++s; + if (!ISDIGIT(c)) + goto dig_done; if (!nd) { for (; c == '0'; c = *++s) nz++; diff --git a/spec/ruby/core/string/modulo_spec.rb b/spec/ruby/core/string/modulo_spec.rb index 5d8560000c..8e3853551f 100644 --- a/spec/ruby/core/string/modulo_spec.rb +++ b/spec/ruby/core/string/modulo_spec.rb @@ -749,6 +749,9 @@ describe "String#%" do (format % "-10.4e-20").should == (format % -10.4e-20) (format % ".5").should == (format % 0.5) (format % "-.5").should == (format % -0.5) + ruby_bug("#20705", ""..."3.4") do + (format % "10.").should == (format % 10) + end # Something's strange with this spec: # it works just fine in individual mode, but not when run as part of a group (format % "10_1_0.5_5_5").should == (format % 1010.555) @@ -758,7 +761,6 @@ describe "String#%" do -> { format % "" }.should raise_error(ArgumentError) -> { format % "x" }.should raise_error(ArgumentError) -> { format % "." }.should raise_error(ArgumentError) - -> { format % "10." }.should raise_error(ArgumentError) -> { format % "5x" }.should raise_error(ArgumentError) -> { format % "0b1" }.should raise_error(ArgumentError) -> { format % "10e10.5" }.should raise_error(ArgumentError) diff --git a/test/ruby/test_float.rb b/test/ruby/test_float.rb index 9f522c32bf..f2c56d1b41 100644 --- a/test/ruby/test_float.rb +++ b/test/ruby/test_float.rb @@ -129,9 +129,9 @@ class TestFloat < Test::Unit::TestCase assert_in_delta(a, 0, Float::EPSILON) a = Float("-.0") assert_in_delta(a, 0, Float::EPSILON) - assert_raise(ArgumentError){Float("0.")} - assert_raise(ArgumentError){Float("+0.")} - assert_raise(ArgumentError){Float("-0.")} + assert_equal(0.0, Float("0.")) + assert_equal(0.0, Float("+0.")) + assert_equal(0.0, Float("-0.")) assert_raise(ArgumentError){Float(".")} assert_raise(ArgumentError){Float("+")} assert_raise(ArgumentError){Float("+.")} @@ -139,12 +139,12 @@ class TestFloat < Test::Unit::TestCase assert_raise(ArgumentError){Float("-.")} assert_raise(ArgumentError){Float("1e")} assert_raise(ArgumentError){Float("1__1")} - assert_raise(ArgumentError){Float("1.")} - assert_raise(ArgumentError){Float("1.e+00")} - assert_raise(ArgumentError){Float("0x.1")} - assert_raise(ArgumentError){Float("0x1.")} - assert_raise(ArgumentError){Float("0x1.0")} - assert_raise(ArgumentError){Float("0x1.p+0")} + assert_equal(1.0, Float("1.")) + assert_equal(1.0, Float("1.e+00")) + assert_equal(0.0625, Float("0x.1")) + assert_equal(1.0, Float("0x1.")) + assert_equal(1.0, Float("0x1.0")) + assert_equal(1.0, Float("0x1.p+0")) # add expected behaviour here. assert_equal(10, Float("1_0")) @@ -191,7 +191,7 @@ class TestFloat < Test::Unit::TestCase break end end - assert_nil(x, ->{"%a" % x}) + assert_equal(1.0, x, ->{"%a" % x}) end def test_divmod @@ -833,10 +833,10 @@ class TestFloat < Test::Unit::TestCase assert_equal(15, Float('0xf')) assert_equal(15, Float('0xfp0')) assert_raise(ArgumentError) { Float('0xfp') } - assert_raise(ArgumentError) { Float('0xf.') } + assert_equal(15, Float('0xf.')) assert_raise(ArgumentError) { Float('0xf.p') } - assert_raise(ArgumentError) { Float('0xf.p0') } - assert_raise(ArgumentError) { Float('0xf.f') } + assert_equal(15, Float('0xf.p0')) + assert_equal(15.9375, Float('0xf.f')) assert_raise(ArgumentError) { Float('0xf.fp') } begin verbose_bak, $VERBOSE = $VERBOSE, nil |