xref: /aosp_15_r20/external/llvm-libc/test/src/stdlib/strtold_test.cpp (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
1 //===-- Unittests for strtold ---------------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
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"
13 
14 #include "test/UnitTest/Test.h"
15 
16 #include <stddef.h>
17 
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
24 #else
25 #error "Unknown long double type"
26 #endif
27 
28 class LlvmLibcStrToLDTest : public LIBC_NAMESPACE::testing::Test {
29 public:
30 #if defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
run_test(const char * inputString,const ptrdiff_t expectedStrLen,const uint64_t expectedRawData,const int expectedErrno=0)31   void run_test(const char *inputString, const ptrdiff_t expectedStrLen,
32                 const uint64_t expectedRawData, const int expectedErrno = 0)
33 #else
34   void run_test(const char *inputString, const ptrdiff_t expectedStrLen,
35                 const UInt128 expectedRawData, const int expectedErrno = 0)
36 #endif
37   {
38     // expectedRawData64 is the expected long double result as a uint64_t,
39     // organized according to the IEEE754 double precision format:
40     //
41     // +-- 1 Sign Bit                        +-- 52 Mantissa bits
42     // |                                     |
43     // |           +-------------------------+------------------------+
44     // |           |                                                  |
45     // SEEEEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
46     //  |         |
47     //  +----+----+
48     //       |
49     //       +-- 11 Exponent Bits
50 
51     // expectedRawData80 is the expected long double result as a UInt128,
52     // organized according to the x86 extended precision format:
53     //
54     // +-- 1 Sign Bit
55     // |
56     // |               +-- 1 Integer part bit (1 unless this is a subnormal)
57     // |               |
58     // SEEEEEEEEEEEEEEEIMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM...M
59     //  |             | |                                                      |
60     //  +------+------+ +---------------------------+--------------------------+
61     //         |                                    |
62     //         +-- 15 Exponent Bits                 +-- 63 Mantissa bits
63 
64     // expectedRawData128 is the expected long double result as a UInt128,
65     // organized according to IEEE754 quadruple precision format:
66     //
67     // +-- 1 Sign Bit                               +-- 112 Mantissa bits
68     // |                                            |
69     // |               +----------------------------+--------------------------+
70     // |               |                                                       |
71     // SEEEEEEEEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM...M
72     //  |             |
73     //  +------+------+
74     //         |
75     //         +-- 15 Exponent Bits
76     char *str_end = nullptr;
77 
78     using FPBits = LIBC_NAMESPACE::fputil::FPBits<long double>;
79     FPBits expected_fp =
80         FPBits(static_cast<FPBits::StorageType>(expectedRawData));
81     const int expected_errno = expectedErrno;
82 
83     LIBC_NAMESPACE::libc_errno = 0;
84     long double result = LIBC_NAMESPACE::strtold(inputString, &str_end);
85 
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);
89 
90     EXPECT_EQ(str_end - inputString, expectedStrLen);
91 
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);
97   }
98 };
99 
TEST_F(LlvmLibcStrToLDTest,SimpleTest)100 TEST_F(LlvmLibcStrToLDTest, SimpleTest) {
101   run_test("123", 3,
102            SELECT_CONST(uint64_t(0x405ec00000000000),
103                         UInt128(0x4005f60000) << 40,
104                         UInt128(0x4005ec0000000000) << 64));
105 
106   // This should fail on Eisel-Lemire, forcing a fallback to simple decimal
107   // conversion.
108   run_test("12345678901234549760", 20,
109            SELECT_CONST(uint64_t(0x43e56a95319d63d8),
110                         (UInt128(0x403eab54a9) << 40) + UInt128(0x8ceb1ec400),
111                         (UInt128(0x403e56a95319d63d) << 64) +
112                             UInt128(0x8800000000000000)));
113 
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)));
121 
122   run_test("0x123", 5,
123            SELECT_CONST(uint64_t(0x4072300000000000),
124                         (UInt128(0x4007918000) << 40),
125                         (UInt128(0x4007230000000000) << 64)));
126 }
127 
128 // These are tests that have caused problems for doubles in the past.
TEST_F(LlvmLibcStrToLDTest,Float64SpecificFailures)129 TEST_F(LlvmLibcStrToLDTest, Float64SpecificFailures) {
130   run_test("3E70000000000000", 16,
131            SELECT_CONST(uint64_t(0x7FF0000000000000),
132                         (UInt128(0x7fff800000) << 40),
133                         (UInt128(0x7fff000000000000) << 64)),
134            ERANGE);
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)));
150 }
151 
TEST_F(LlvmLibcStrToLDTest,Float80SpecificFailures)152 TEST_F(LlvmLibcStrToLDTest, Float80SpecificFailures) {
153   run_test("7777777777777777777777777777777777777777777777777777777777777777777"
154            "777777777777777777777777777777777",
155            100,
156            SELECT_CONST(uint64_t(0x54ac729b8fcaf734),
157                         (UInt128(0x414ae394dc) << 40) + UInt128(0x7e57b9a0c2),
158                         (UInt128(0x414ac729b8fcaf73) << 64) +
159                             UInt128(0x4184a3d793224129)));
160 }
161 
TEST_F(LlvmLibcStrToLDTest,MaxSizeNumbers)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));
175 }
176 
177 // These tests check subnormal behavior for 80 bit and 128 bit floats. They will
178 // be too small for 64 bit floats.
TEST_F(LlvmLibcStrToLDTest,SubnormalTests)179 TEST_F(LlvmLibcStrToLDTest, SubnormalTests) {
180   run_test("1e-4950", 7,
181            SELECT_CONST(uint64_t(0), (UInt128(0x00000000000000000003)),
182                         (UInt128(0x000000000000000000057c9647e1a018))),
183            ERANGE);
184   run_test("1.89e-4951", 10,
185            SELECT_CONST(uint64_t(0), (UInt128(0x00000000000000000001)),
186                         (UInt128(0x0000000000000000000109778a006738))),
187            ERANGE);
188   run_test("4e-4966", 7,
189            SELECT_CONST(uint64_t(0), (UInt128(0)),
190                         (UInt128(0x00000000000000000000000000000001))),
191            ERANGE);
192 }
193 
TEST_F(LlvmLibcStrToLDTest,SmallNormalTests)194 TEST_F(LlvmLibcStrToLDTest, SmallNormalTests) {
195   run_test("3.37e-4932", 10,
196            SELECT_CONST(
197                uint64_t(0), (UInt128(0x1804cf7) << 40) + UInt128(0x908850712),
198                (UInt128(0x10099ee12110a) << 64) + UInt128(0xe24b75c0f50dc0c)),
199            SELECT_CONST(ERANGE, 0, 0));
200 }
201 
TEST_F(LlvmLibcStrToLDTest,ComplexHexadecimalTests)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)));
217 }
218 
TEST_F(LlvmLibcStrToLDTest,InfTests)219 TEST_F(LlvmLibcStrToLDTest, InfTests) {
220   run_test("INF", 3,
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)));
226   run_test("-inf", 4,
227            SELECT_CONST(0xfff0000000000000, (UInt128(0xffff800000) << 40),
228                         (UInt128(0xffff000000000000) << 64)));
229 }
230 
TEST_F(LlvmLibcStrToLDTest,NaNTests)231 TEST_F(LlvmLibcStrToLDTest, NaNTests) {
232   run_test("NaN", 3,
233            SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
234                         (UInt128(0x7fff800000000000) << 64)));
235   run_test("-nAn", 4,
236            SELECT_CONST(0xfff8000000000000, (UInt128(0xffffc00000) << 40),
237                         (UInt128(0xffff800000000000) << 64)));
238   run_test("NaN()", 5,
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)));
263 }
264