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/CPP/UInt128.h"
10 #include "src/__support/FPUtil/FPBits.h"
11 #include "src/stdlib/strtold.h"
12 
13 #include "utils/UnitTest/Test.h"
14 
15 #include <errno.h>
16 #include <limits.h>
17 #include <stddef.h>
18 
19 #if defined(LONG_DOUBLE_IS_DOUBLE)
20 #define SELECT_CONST(val, _, __) val
21 #elif defined(SPECIAL_X86_LONG_DOUBLE)
22 #define SELECT_CONST(_, val, __) val
23 #else
24 #define SELECT_CONST(_, __, val) val
25 #endif
26 
27 class LlvmLibcStrToLDTest : public __llvm_libc::testing::Test {
28 public:
29 #if defined(LONG_DOUBLE_IS_DOUBLE)
run_test(const char * inputString,const ptrdiff_t expectedStrLen,const uint64_t expectedRawData,const int expectedErrno=0)30   void run_test(const char *inputString, const ptrdiff_t expectedStrLen,
31                 const uint64_t expectedRawData, const int expectedErrno = 0)
32 #else
33   void run_test(const char *inputString, const ptrdiff_t expectedStrLen,
34                 const UInt128 expectedRawData, const int expectedErrno = 0)
35 #endif
36   {
37     // expectedRawData64 is the expected long double result as a uint64_t,
38     // organized according to the IEEE754 double precision format:
39     //
40     // +-- 1 Sign Bit                        +-- 52 Mantissa bits
41     // |                                     |
42     // |           +-------------------------+------------------------+
43     // |           |                                                  |
44     // SEEEEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
45     //  |         |
46     //  +----+----+
47     //       |
48     //       +-- 11 Exponent Bits
49 
50     // expectedRawData80 is the expected long double result as a UInt128,
51     // organized according to the x86 extended precision format:
52     //
53     // +-- 1 Sign Bit
54     // |
55     // |               +-- 1 Integer part bit (1 unless this is a subnormal)
56     // |               |
57     // SEEEEEEEEEEEEEEEIMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM...M
58     //  |             | |                                                      |
59     //  +------+------+ +---------------------------+--------------------------+
60     //         |                                    |
61     //         +-- 15 Exponent Bits                 +-- 63 Mantissa bits
62 
63     // expectedRawData128 is the expected long double result as a UInt128,
64     // organized according to IEEE754 quadruple precision format:
65     //
66     // +-- 1 Sign Bit                               +-- 112 Mantissa bits
67     // |                                            |
68     // |               +----------------------------+--------------------------+
69     // |               |                                                       |
70     // SEEEEEEEEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM...M
71     //  |             |
72     //  +------+------+
73     //         |
74     //         +-- 15 Exponent Bits
75     char *str_end = nullptr;
76 
77     __llvm_libc::fputil::FPBits<long double> expected_fp =
78         __llvm_libc::fputil::FPBits<long double>(expectedRawData);
79     const int expected_errno = expectedErrno;
80 
81     errno = 0;
82     long double result = __llvm_libc::strtold(inputString, &str_end);
83 
84     __llvm_libc::fputil::FPBits<long double> actual_fp =
85         __llvm_libc::fputil::FPBits<long double>();
86     actual_fp = __llvm_libc::fputil::FPBits<long double>(result);
87 
88     EXPECT_EQ(str_end - inputString, expectedStrLen);
89 
90     EXPECT_EQ(actual_fp.bits, expected_fp.bits);
91     EXPECT_EQ(actual_fp.get_sign(), expected_fp.get_sign());
92     EXPECT_EQ(actual_fp.get_exponent(), expected_fp.get_exponent());
93     EXPECT_EQ(actual_fp.get_mantissa(), expected_fp.get_mantissa());
94     EXPECT_EQ(errno, expected_errno);
95   }
96 };
97 
TEST_F(LlvmLibcStrToLDTest,SimpleTest)98 TEST_F(LlvmLibcStrToLDTest, SimpleTest) {
99   run_test("123", 3,
100            SELECT_CONST(uint64_t(0x405ec00000000000),
101                         UInt128(0x4005f60000) << 40,
102                         UInt128(0x4005ec0000000000) << 64));
103 
104   // This should fail on Eisel-Lemire, forcing a fallback to simple decimal
105   // conversion.
106   run_test("12345678901234549760", 20,
107            SELECT_CONST(uint64_t(0x43e56a95319d63d8),
108                         (UInt128(0x403eab54a9) << 40) + UInt128(0x8ceb1ec400),
109                         (UInt128(0x403e56a95319d63d) << 64) +
110                             UInt128(0x8800000000000000)));
111 
112   // Found while looking for difficult test cases here:
113   // https://github.com/nigeltao/parse-number-fxx-test-data/blob/main/more-test-cases/golang-org-issue-36657.txt
114   run_test("1090544144181609348835077142190", 31,
115            SELECT_CONST(uint64_t(0x462b8779f2474dfb),
116                         (UInt128(0x4062dc3bcf) << 40) + UInt128(0x923a6fd402),
117                         (UInt128(0x4062b8779f2474df) << 64) +
118                             UInt128(0xa804bfd8c6d5c000)));
119 
120   run_test("0x123", 5,
121            SELECT_CONST(uint64_t(0x4072300000000000),
122                         (UInt128(0x4007918000) << 40),
123                         (UInt128(0x4007230000000000) << 64)));
124 }
125 
126 // These are tests that have caused problems for doubles in the past.
TEST_F(LlvmLibcStrToLDTest,Float64SpecificFailures)127 TEST_F(LlvmLibcStrToLDTest, Float64SpecificFailures) {
128   run_test("3E70000000000000", 16,
129            SELECT_CONST(uint64_t(0x7FF0000000000000),
130                         (UInt128(0x7fff800000) << 40),
131                         (UInt128(0x7fff000000000000) << 64)),
132            ERANGE);
133   run_test("358416272e-33", 13,
134            SELECT_CONST(uint64_t(0x3adbbb2a68c9d0b9),
135                         (UInt128(0x3fadddd953) << 40) + UInt128(0x464e85c400),
136                         (UInt128(0x3fadbbb2a68c9d0b) << 64) +
137                             UInt128(0x8800e7969e1c5fc8)));
138   run_test("2.16656806400000023841857910156251e9", 36,
139            SELECT_CONST(uint64_t(0x41e0246690000001),
140                         (UInt128(0x401e812334) << 40) + UInt128(0x8000000400),
141                         (UInt128(0x401e024669000000) << 64) +
142                             UInt128(0x800000000000018)));
143   run_test("27949676547093071875", 20,
144            SELECT_CONST(uint64_t(0x43f83e132bc608c9),
145                         (UInt128(0x403fc1f099) << 40) + UInt128(0x5e30464402),
146                         (UInt128(0x403f83e132bc608c) << 64) +
147                             UInt128(0x8803000000000000)));
148 }
149 
TEST_F(LlvmLibcStrToLDTest,MaxSizeNumbers)150 TEST_F(LlvmLibcStrToLDTest, MaxSizeNumbers) {
151   run_test("1.1897314953572317650e4932", 26,
152            SELECT_CONST(uint64_t(0x7FF0000000000000),
153                         (UInt128(0x7ffeffffff) << 40) + UInt128(0xffffffffff),
154                         (UInt128(0x7ffeffffffffffff) << 64) +
155                             UInt128(0xfffd57322e3f8675)),
156            SELECT_CONST(ERANGE, 0, 0));
157   run_test("1.18973149535723176508e4932", 27,
158            SELECT_CONST(uint64_t(0x7FF0000000000000),
159                         (UInt128(0x7fff800000) << 40),
160                         (UInt128(0x7ffeffffffffffff) << 64) +
161                             UInt128(0xffffd2478338036c)),
162            SELECT_CONST(ERANGE, ERANGE, 0));
163 }
164 
165 // These tests check subnormal behavior for 80 bit and 128 bit floats. They will
166 // be too small for 64 bit floats.
TEST_F(LlvmLibcStrToLDTest,SubnormalTests)167 TEST_F(LlvmLibcStrToLDTest, SubnormalTests) {
168   run_test("1e-4950", 7,
169            SELECT_CONST(uint64_t(0), (UInt128(0x00000000000000000003)),
170                         (UInt128(0x000000000000000000057c9647e1a018))),
171            ERANGE);
172   run_test("1.89e-4951", 10,
173            SELECT_CONST(uint64_t(0), (UInt128(0x00000000000000000001)),
174                         (UInt128(0x0000000000000000000109778a006738))),
175            ERANGE);
176   run_test("4e-4966", 7,
177            SELECT_CONST(uint64_t(0), (UInt128(0)),
178                         (UInt128(0x00000000000000000000000000000001))),
179            ERANGE);
180 }
181 
TEST_F(LlvmLibcStrToLDTest,SmallNormalTests)182 TEST_F(LlvmLibcStrToLDTest, SmallNormalTests) {
183   run_test("3.37e-4932", 10,
184            SELECT_CONST(
185                uint64_t(0), (UInt128(0x1804cf7) << 40) + UInt128(0x908850712),
186                (UInt128(0x10099ee12110a) << 64) + UInt128(0xe24b75c0f50dc0c)),
187            SELECT_CONST(ERANGE, 0, 0));
188 }
189 
TEST_F(LlvmLibcStrToLDTest,ComplexHexadecimalTests)190 TEST_F(LlvmLibcStrToLDTest, ComplexHexadecimalTests) {
191   run_test("0x1p16383", 9,
192            SELECT_CONST(0x7ff0000000000000, (UInt128(0x7ffe800000) << 40),
193                         (UInt128(0x7ffe000000000000) << 64)),
194            SELECT_CONST(ERANGE, 0, 0));
195   run_test("0x123456789abcdef", 17,
196            SELECT_CONST(0x43723456789abcdf,
197                         (UInt128(0x403791a2b3) << 40) + UInt128(0xc4d5e6f780),
198                         (UInt128(0x403723456789abcd) << 64) +
199                             UInt128(0xef00000000000000)));
200   run_test("0x123456789abcdef0123456789ABCDEF", 33,
201            SELECT_CONST(0x47723456789abcdf,
202                         (UInt128(0x407791a2b3) << 40) + UInt128(0xc4d5e6f781),
203                         (UInt128(0x407723456789abcd) << 64) +
204                             UInt128(0xef0123456789abce)));
205 }
206 
TEST_F(LlvmLibcStrToLDTest,InfTests)207 TEST_F(LlvmLibcStrToLDTest, InfTests) {
208   run_test("INF", 3,
209            SELECT_CONST(0x7ff0000000000000, (UInt128(0x7fff800000) << 40),
210                         (UInt128(0x7fff000000000000) << 64)));
211   run_test("INFinity", 8,
212            SELECT_CONST(0x7ff0000000000000, (UInt128(0x7fff800000) << 40),
213                         (UInt128(0x7fff000000000000) << 64)));
214   run_test("-inf", 4,
215            SELECT_CONST(0xfff0000000000000, (UInt128(0xffff800000) << 40),
216                         (UInt128(0xffff000000000000) << 64)));
217 }
218 
TEST_F(LlvmLibcStrToLDTest,NaNTests)219 TEST_F(LlvmLibcStrToLDTest, NaNTests) {
220   run_test("NaN", 3,
221            SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
222                         (UInt128(0x7fff800000000000) << 64)));
223   run_test("-nAn", 4,
224            SELECT_CONST(0xfff8000000000000, (UInt128(0xffffc00000) << 40),
225                         (UInt128(0xffff800000000000) << 64)));
226   run_test("NaN()", 5,
227            SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
228                         (UInt128(0x7fff800000000000) << 64)));
229   run_test("NaN(1234)", 9,
230            SELECT_CONST(0x7ff80000000004d2,
231                         (UInt128(0x7fffc00000) << 40) + UInt128(0x4d2),
232                         (UInt128(0x7fff800000000000) << 64) + UInt128(0x4d2)));
233   run_test("NaN(0xffffffffffff)", 19,
234            SELECT_CONST(0x7ff8ffffffffffff,
235                         (UInt128(0x7fffc000ff) << 40) + UInt128(0xffffffffff),
236                         (UInt128(0x7fff800000000000) << 64) +
237                             UInt128(0xffffffffffff)));
238   run_test("NaN(0xfffffffffffff)", 20,
239            SELECT_CONST(0x7fffffffffffffff,
240                         (UInt128(0x7fffc00fff) << 40) + UInt128(0xffffffffff),
241                         (UInt128(0x7fff800000000000) << 64) +
242                             UInt128(0xfffffffffffff)));
243   run_test("NaN(0xffffffffffffffff)", 23,
244            SELECT_CONST(0x7fffffffffffffff,
245                         (UInt128(0x7fffffffff) << 40) + UInt128(0xffffffffff),
246                         (UInt128(0x7fff800000000000) << 64) +
247                             UInt128(0xffffffffffffffff)));
248   run_test("NaN( 1234)", 3,
249            SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
250                         (UInt128(0x7fff800000000000) << 64)));
251 }
252