1 //===-- Unittests for strtold ---------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "src/__support/FPUtil/FPBits.h"
10 #include "src/__support/uint128.h"
11 #include "src/errno/libc_errno.h"
12 #include "src/stdlib/strtold.h"
14 #include "test/UnitTest/Test.h"
18 #if defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
19 #define SELECT_CONST(val, _, __) val
20 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
21 #define SELECT_CONST(_, val, __) val
22 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
23 #define SELECT_CONST(_, __, val) val
25 #error "Unknown long double type"
28 class LlvmLibcStrToLDTest
: public LIBC_NAMESPACE::testing::Test
{
30 #if defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
31 void run_test(const char *inputString
, const ptrdiff_t expectedStrLen
,
32 const uint64_t expectedRawData
, const int expectedErrno
= 0)
34 void run_test(const char *inputString
, const ptrdiff_t expectedStrLen
,
35 const UInt128 expectedRawData
, const int expectedErrno
= 0)
38 // expectedRawData64 is the expected long double result as a uint64_t,
39 // organized according to the IEEE754 double precision format:
41 // +-- 1 Sign Bit +-- 52 Mantissa bits
43 // | +-------------------------+------------------------+
45 // SEEEEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
49 // +-- 11 Exponent Bits
51 // expectedRawData80 is the expected long double result as a UInt128,
52 // organized according to the x86 extended precision format:
56 // | +-- 1 Integer part bit (1 unless this is a subnormal)
58 // SEEEEEEEEEEEEEEEIMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM...M
60 // +------+------+ +---------------------------+--------------------------+
62 // +-- 15 Exponent Bits +-- 63 Mantissa bits
64 // expectedRawData128 is the expected long double result as a UInt128,
65 // organized according to IEEE754 quadruple precision format:
67 // +-- 1 Sign Bit +-- 112 Mantissa bits
69 // | +----------------------------+--------------------------+
71 // SEEEEEEEEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM...M
75 // +-- 15 Exponent Bits
76 char *str_end
= nullptr;
78 using FPBits
= LIBC_NAMESPACE::fputil::FPBits
<long double>;
80 FPBits(static_cast<FPBits::StorageType
>(expectedRawData
));
81 const int expected_errno
= expectedErrno
;
83 LIBC_NAMESPACE::libc_errno
= 0;
84 long double result
= LIBC_NAMESPACE::strtold(inputString
, &str_end
);
86 LIBC_NAMESPACE::fputil::FPBits
<long double> actual_fp
=
87 LIBC_NAMESPACE::fputil::FPBits
<long double>();
88 actual_fp
= LIBC_NAMESPACE::fputil::FPBits
<long double>(result
);
90 EXPECT_EQ(str_end
- inputString
, expectedStrLen
);
92 EXPECT_EQ(actual_fp
.uintval(), expected_fp
.uintval());
93 EXPECT_EQ(actual_fp
.is_neg(), expected_fp
.is_neg());
94 EXPECT_EQ(actual_fp
.get_exponent(), expected_fp
.get_exponent());
95 EXPECT_EQ(actual_fp
.get_mantissa(), expected_fp
.get_mantissa());
96 ASSERT_ERRNO_EQ(expected_errno
);
100 TEST_F(LlvmLibcStrToLDTest
, SimpleTest
) {
102 SELECT_CONST(uint64_t(0x405ec00000000000),
103 UInt128(0x4005f60000) << 40,
104 UInt128(0x4005ec0000000000) << 64));
106 // This should fail on Eisel-Lemire, forcing a fallback to simple decimal
108 run_test("12345678901234549760", 20,
109 SELECT_CONST(uint64_t(0x43e56a95319d63d8),
110 (UInt128(0x403eab54a9) << 40) + UInt128(0x8ceb1ec400),
111 (UInt128(0x403e56a95319d63d) << 64) +
112 UInt128(0x8800000000000000)));
114 // Found while looking for difficult test cases here:
115 // https://github.com/nigeltao/parse-number-fxx-test-data/blob/main/more-test-cases/golang-org-issue-36657.txt
116 run_test("1090544144181609348835077142190", 31,
117 SELECT_CONST(uint64_t(0x462b8779f2474dfb),
118 (UInt128(0x4062dc3bcf) << 40) + UInt128(0x923a6fd402),
119 (UInt128(0x4062b8779f2474df) << 64) +
120 UInt128(0xa804bfd8c6d5c000)));
123 SELECT_CONST(uint64_t(0x4072300000000000),
124 (UInt128(0x4007918000) << 40),
125 (UInt128(0x4007230000000000) << 64)));
128 // These are tests that have caused problems for doubles in the past.
129 TEST_F(LlvmLibcStrToLDTest
, Float64SpecificFailures
) {
130 run_test("3E70000000000000", 16,
131 SELECT_CONST(uint64_t(0x7FF0000000000000),
132 (UInt128(0x7fff800000) << 40),
133 (UInt128(0x7fff000000000000) << 64)),
135 run_test("358416272e-33", 13,
136 SELECT_CONST(uint64_t(0x3adbbb2a68c9d0b9),
137 (UInt128(0x3fadddd953) << 40) + UInt128(0x464e85c400),
138 (UInt128(0x3fadbbb2a68c9d0b) << 64) +
139 UInt128(0x8800e7969e1c5fc8)));
140 run_test("2.16656806400000023841857910156251e9", 36,
141 SELECT_CONST(uint64_t(0x41e0246690000001),
142 (UInt128(0x401e812334) << 40) + UInt128(0x8000000400),
143 (UInt128(0x401e024669000000) << 64) +
144 UInt128(0x800000000000018)));
145 run_test("27949676547093071875", 20,
146 SELECT_CONST(uint64_t(0x43f83e132bc608c9),
147 (UInt128(0x403fc1f099) << 40) + UInt128(0x5e30464402),
148 (UInt128(0x403f83e132bc608c) << 64) +
149 UInt128(0x8803000000000000)));
152 TEST_F(LlvmLibcStrToLDTest
, Float80SpecificFailures
) {
153 run_test("7777777777777777777777777777777777777777777777777777777777777777777"
154 "777777777777777777777777777777777",
156 SELECT_CONST(uint64_t(0x54ac729b8fcaf734),
157 (UInt128(0x414ae394dc) << 40) + UInt128(0x7e57b9a0c2),
158 (UInt128(0x414ac729b8fcaf73) << 64) +
159 UInt128(0x4184a3d793224129)));
162 TEST_F(LlvmLibcStrToLDTest
, MaxSizeNumbers
) {
163 run_test("1.1897314953572317650e4932", 26,
164 SELECT_CONST(uint64_t(0x7FF0000000000000),
165 (UInt128(0x7ffeffffff) << 40) + UInt128(0xffffffffff),
166 (UInt128(0x7ffeffffffffffff) << 64) +
167 UInt128(0xfffd57322e3f8675)),
168 SELECT_CONST(ERANGE
, 0, 0));
169 run_test("1.18973149535723176508e4932", 27,
170 SELECT_CONST(uint64_t(0x7FF0000000000000),
171 (UInt128(0x7fff800000) << 40),
172 (UInt128(0x7ffeffffffffffff) << 64) +
173 UInt128(0xffffd2478338036c)),
174 SELECT_CONST(ERANGE
, ERANGE
, 0));
177 // These tests check subnormal behavior for 80 bit and 128 bit floats. They will
178 // be too small for 64 bit floats.
179 TEST_F(LlvmLibcStrToLDTest
, SubnormalTests
) {
180 run_test("1e-4950", 7,
181 SELECT_CONST(uint64_t(0), (UInt128(0x00000000000000000003)),
182 (UInt128(0x000000000000000000057c9647e1a018))),
184 run_test("1.89e-4951", 10,
185 SELECT_CONST(uint64_t(0), (UInt128(0x00000000000000000001)),
186 (UInt128(0x0000000000000000000109778a006738))),
188 run_test("4e-4966", 7,
189 SELECT_CONST(uint64_t(0), (UInt128(0)),
190 (UInt128(0x00000000000000000000000000000001))),
194 TEST_F(LlvmLibcStrToLDTest
, SmallNormalTests
) {
195 run_test("3.37e-4932", 10,
197 uint64_t(0), (UInt128(0x1804cf7) << 40) + UInt128(0x908850712),
198 (UInt128(0x10099ee12110a) << 64) + UInt128(0xe24b75c0f50dc0c)),
199 SELECT_CONST(ERANGE
, 0, 0));
202 TEST_F(LlvmLibcStrToLDTest
, ComplexHexadecimalTests
) {
203 run_test("0x1p16383", 9,
204 SELECT_CONST(0x7ff0000000000000, (UInt128(0x7ffe800000) << 40),
205 (UInt128(0x7ffe000000000000) << 64)),
206 SELECT_CONST(ERANGE
, 0, 0));
207 run_test("0x123456789abcdef", 17,
208 SELECT_CONST(0x43723456789abcdf,
209 (UInt128(0x403791a2b3) << 40) + UInt128(0xc4d5e6f780),
210 (UInt128(0x403723456789abcd) << 64) +
211 UInt128(0xef00000000000000)));
212 run_test("0x123456789abcdef0123456789ABCDEF", 33,
213 SELECT_CONST(0x47723456789abcdf,
214 (UInt128(0x407791a2b3) << 40) + UInt128(0xc4d5e6f781),
215 (UInt128(0x407723456789abcd) << 64) +
216 UInt128(0xef0123456789abce)));
219 TEST_F(LlvmLibcStrToLDTest
, InfTests
) {
221 SELECT_CONST(0x7ff0000000000000, (UInt128(0x7fff800000) << 40),
222 (UInt128(0x7fff000000000000) << 64)));
223 run_test("INFinity", 8,
224 SELECT_CONST(0x7ff0000000000000, (UInt128(0x7fff800000) << 40),
225 (UInt128(0x7fff000000000000) << 64)));
227 SELECT_CONST(0xfff0000000000000, (UInt128(0xffff800000) << 40),
228 (UInt128(0xffff000000000000) << 64)));
231 TEST_F(LlvmLibcStrToLDTest
, NaNTests
) {
233 SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
234 (UInt128(0x7fff800000000000) << 64)));
236 SELECT_CONST(0xfff8000000000000, (UInt128(0xffffc00000) << 40),
237 (UInt128(0xffff800000000000) << 64)));
239 SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
240 (UInt128(0x7fff800000000000) << 64)));
241 run_test("NaN(1234)", 9,
242 SELECT_CONST(0x7ff80000000004d2,
243 (UInt128(0x7fffc00000) << 40) + UInt128(0x4d2),
244 (UInt128(0x7fff800000000000) << 64) + UInt128(0x4d2)));
245 run_test("NaN(0xffffffffffff)", 19,
246 SELECT_CONST(0x7ff8ffffffffffff,
247 (UInt128(0x7fffc000ff) << 40) + UInt128(0xffffffffff),
248 (UInt128(0x7fff800000000000) << 64) +
249 UInt128(0xffffffffffff)));
250 run_test("NaN(0xfffffffffffff)", 20,
251 SELECT_CONST(0x7fffffffffffffff,
252 (UInt128(0x7fffc00fff) << 40) + UInt128(0xffffffffff),
253 (UInt128(0x7fff800000000000) << 64) +
254 UInt128(0xfffffffffffff)));
255 run_test("NaN(0xffffffffffffffff)", 23,
256 SELECT_CONST(0x7fffffffffffffff,
257 (UInt128(0x7fffffffff) << 40) + UInt128(0xffffffffff),
258 (UInt128(0x7fff800000000000) << 64) +
259 UInt128(0xffffffffffffffff)));
260 run_test("NaN( 1234)", 3,
261 SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
262 (UInt128(0x7fff800000000000) << 64)));