Commit dc6109e0 by Abseil Team Committed by Copybara-Service

Implement Eisel-Lemire for from_chars<double>

Eisel-Lemire is a fast Atod algorithm, discussed at
https://nigeltao.github.io/blog/2020/eisel-lemire.html

Median of 5 runs of "time atod_manual_test pnftd/data/*.txt"
user    0m1.477s  # Before
user    0m0.746s  # After (a speed-up of 1.98x)
where pnftd is https://github.com/nigeltao/parse-number-fxx-test-data

"benchy --reference=srcfs --benchmark_filter='SimpleAtod' :numbers_benchmark"
output (which uses deterministic but randomly generated input strings):
name                                    old cpu/op  new cpu/op  delta
BM_SimpleAtod<absl::string_view>/10/1   388ns ± 3%   330ns ± 2%  -15.06%  (p=0.000 n=49+44)
BM_SimpleAtod<absl::string_view>/10/2   428ns ± 3%   320ns ± 2%  -25.07%  (p=0.000 n=59+49)
BM_SimpleAtod<absl::string_view>/10/4   431ns ± 3%   353ns ± 4%  -18.04%  (p=0.000 n=59+48)
BM_SimpleAtod<absl::string_view>/10/8   512ns ± 3%   409ns ± 4%  -20.18%  (p=0.000 n=60+56)
BM_SimpleAtod<const char*>/10/1         411ns ± 4%   341ns ± 3%  -17.15%  (p=0.000 n=51+49)
BM_SimpleAtod<const char*>/10/2         431ns ± 3%   356ns ± 2%  -17.44%  (p=0.000 n=58+48)
BM_SimpleAtod<const char*>/10/4         437ns ± 3%   378ns ± 4%  -13.49%  (p=0.000 n=60+50)
BM_SimpleAtod<const char*>/10/8         552ns ± 2%   450ns ± 4%  -18.43%  (p=0.000 n=59+59)
BM_SimpleAtod<std::string>/10/1         404ns ± 2%   328ns ± 2%  -18.78%  (p=0.000 n=48+49)
BM_SimpleAtod<std::string>/10/2         438ns ± 3%   321ns ± 3%  -26.81%  (p=0.000 n=60+50)
BM_SimpleAtod<std::string>/10/4         446ns ± 2%   354ns ± 3%  -20.66%  (p=0.000 n=59+50)
BM_SimpleAtod<std::string>/10/8         519ns ± 2%   410ns ± 4%  -21.07%  (p=0.000 n=59+50)

sizeof(kPower10MantissaTable) doubles from 5208 to 10416 bytes.

PiperOrigin-RevId: 474174891
Change-Id: Iea6f6569419b6b55ab5978994f0adb1f4a8aafb2
parent 530cd52f
......@@ -406,6 +406,19 @@ TEST(NumbersTest, Atod) {
EXPECT_TRUE(absl::SimpleAtod("-INF", &d));
EXPECT_TRUE(std::isinf(d) && (d < 0));
// Parse DBL_MAX. Parsing something more than twice as big should also
// produce infinity.
EXPECT_TRUE(absl::SimpleAtod("1.7976931348623157e+308", &d));
EXPECT_EQ(d, 1.7976931348623157e+308);
EXPECT_TRUE(absl::SimpleAtod("5e308", &d));
EXPECT_TRUE(std::isinf(d) && (d > 0));
// Parse DBL_MIN (normal) and DBL_TRUE_MIN (subnormal).
EXPECT_TRUE(absl::SimpleAtod("2.2250738585072014e-308", &d));
EXPECT_EQ(d, 2.2250738585072014e-308);
EXPECT_TRUE(absl::SimpleAtod("4.9406564584124654e-324", &d));
EXPECT_EQ(d, 4.9406564584124654e-324);
// Leading and/or trailing whitespace is OK.
EXPECT_TRUE(absl::SimpleAtod(" \t\r\n 2.718", &d));
EXPECT_EQ(d, 2.718);
......@@ -439,6 +452,14 @@ TEST(NumbersTest, Atod) {
EXPECT_TRUE(absl::SimpleAtod("8.9", &d));
EXPECT_FALSE(absl::SimpleAtod("8,9", &d));
// These examples are called out in the EiselLemire function's comments.
EXPECT_TRUE(absl::SimpleAtod("4503599627370497.5", &d));
EXPECT_EQ(d, 4503599627370497.5);
EXPECT_TRUE(absl::SimpleAtod("1e+23", &d));
EXPECT_EQ(d, 1e+23);
EXPECT_TRUE(absl::SimpleAtod("9223372036854775807", &d));
EXPECT_EQ(d, 9223372036854775807);
// Some parsing algorithms don't always round correctly (but absl::SimpleAtod
// should). This test case comes from
// https://github.com/serde-rs/json/issues/707
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment