summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNobuyoshi Nakada <[email protected]>2024-09-05 22:08:41 +0900
committerNobuyoshi Nakada <[email protected]>2024-10-05 23:29:42 +0900
commitd17edf3a170b733356836353508319443d12c53c (patch)
tree94ccc35d2b289c15276f16c9f1c98454ff5d8102
parentf37e6d7f7b9dd0fac4fe01637a410dc4752a7ded (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.c16
-rw-r--r--spec/ruby/core/string/modulo_spec.rb4
-rw-r--r--test/ruby/test_float.rb26
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