xref: /llvm-project/libc/test/src/stdlib/strtold_test.cpp (revision 7302c8dbe71b7c03b73a35a21fa4b415fa1f4505)
1aa1902f9SMichael Jones //===-- Unittests for strtold ---------------------------------------------===//
2aa1902f9SMichael Jones //
3aa1902f9SMichael Jones // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4aa1902f9SMichael Jones // See https://llvm.org/LICENSE.txt for license information.
5aa1902f9SMichael Jones // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6aa1902f9SMichael Jones //
7aa1902f9SMichael Jones //===----------------------------------------------------------------------===//
8aa1902f9SMichael Jones 
9aa1902f9SMichael Jones #include "src/__support/FPUtil/FPBits.h"
1009efe848SGuillaume Chatelet #include "src/__support/uint128.h"
1104a9c625SMichael Jones #include "src/errno/libc_errno.h"
12aa1902f9SMichael Jones #include "src/stdlib/strtold.h"
13aa1902f9SMichael Jones 
14af1315c2SSiva Chandra Reddy #include "test/UnitTest/Test.h"
15aa1902f9SMichael Jones 
16aa1902f9SMichael Jones #include <stddef.h>
17aa1902f9SMichael Jones 
18f7d4236aSGuillaume Chatelet #if defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
195d1dbe11SMichael Jones #define SELECT_CONST(val, _, __) val
20f7d4236aSGuillaume Chatelet #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
215d1dbe11SMichael Jones #define SELECT_CONST(_, val, __) val
22f7d4236aSGuillaume Chatelet #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
235d1dbe11SMichael Jones #define SELECT_CONST(_, __, val) val
24f7d4236aSGuillaume Chatelet #else
25f7d4236aSGuillaume Chatelet #error "Unknown long double type"
265d1dbe11SMichael Jones #endif
275d1dbe11SMichael Jones 
28b6bc9d72SGuillaume Chatelet class LlvmLibcStrToLDTest : public LIBC_NAMESPACE::testing::Test {
29aa1902f9SMichael Jones public:
30f7d4236aSGuillaume Chatelet #if defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
3125226f3eSMichael Jones   void run_test(const char *inputString, const ptrdiff_t expectedStrLen,
325d1dbe11SMichael Jones                 const uint64_t expectedRawData, const int expectedErrno = 0)
335d1dbe11SMichael Jones #else
345d1dbe11SMichael Jones   void run_test(const char *inputString, const ptrdiff_t expectedStrLen,
35300f8da8SSiva Chandra Reddy                 const UInt128 expectedRawData, const int expectedErrno = 0)
365d1dbe11SMichael Jones #endif
375d1dbe11SMichael Jones   {
38aa1902f9SMichael Jones     // expectedRawData64 is the expected long double result as a uint64_t,
39aa1902f9SMichael Jones     // organized according to the IEEE754 double precision format:
40aa1902f9SMichael Jones     //
41aa1902f9SMichael Jones     // +-- 1 Sign Bit                        +-- 52 Mantissa bits
42aa1902f9SMichael Jones     // |                                     |
43aa1902f9SMichael Jones     // |           +-------------------------+------------------------+
44aa1902f9SMichael Jones     // |           |                                                  |
45aa1902f9SMichael Jones     // SEEEEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
46aa1902f9SMichael Jones     //  |         |
47aa1902f9SMichael Jones     //  +----+----+
48aa1902f9SMichael Jones     //       |
49aa1902f9SMichael Jones     //       +-- 11 Exponent Bits
50aa1902f9SMichael Jones 
51300f8da8SSiva Chandra Reddy     // expectedRawData80 is the expected long double result as a UInt128,
52aa1902f9SMichael Jones     // organized according to the x86 extended precision format:
53aa1902f9SMichael Jones     //
54aa1902f9SMichael Jones     // +-- 1 Sign Bit
55aa1902f9SMichael Jones     // |
56aa1902f9SMichael Jones     // |               +-- 1 Integer part bit (1 unless this is a subnormal)
57aa1902f9SMichael Jones     // |               |
58aa1902f9SMichael Jones     // SEEEEEEEEEEEEEEEIMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM...M
59aa1902f9SMichael Jones     //  |             | |                                                      |
60aa1902f9SMichael Jones     //  +------+------+ +---------------------------+--------------------------+
61aa1902f9SMichael Jones     //         |                                    |
62aa1902f9SMichael Jones     //         +-- 15 Exponent Bits                 +-- 63 Mantissa bits
63aa1902f9SMichael Jones 
64300f8da8SSiva Chandra Reddy     // expectedRawData128 is the expected long double result as a UInt128,
65aa1902f9SMichael Jones     // organized according to IEEE754 quadruple precision format:
66aa1902f9SMichael Jones     //
67aa1902f9SMichael Jones     // +-- 1 Sign Bit                               +-- 112 Mantissa bits
68aa1902f9SMichael Jones     // |                                            |
69aa1902f9SMichael Jones     // |               +----------------------------+--------------------------+
70aa1902f9SMichael Jones     // |               |                                                       |
71aa1902f9SMichael Jones     // SEEEEEEEEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM...M
72aa1902f9SMichael Jones     //  |             |
73aa1902f9SMichael Jones     //  +------+------+
74aa1902f9SMichael Jones     //         |
75aa1902f9SMichael Jones     //         +-- 15 Exponent Bits
7625226f3eSMichael Jones     char *str_end = nullptr;
77aa1902f9SMichael Jones 
78*7302c8dbSNick Desaulniers     using FPBits = LIBC_NAMESPACE::fputil::FPBits<long double>;
79*7302c8dbSNick Desaulniers     FPBits expected_fp =
80*7302c8dbSNick Desaulniers         FPBits(static_cast<FPBits::StorageType>(expectedRawData));
815d1dbe11SMichael Jones     const int expected_errno = expectedErrno;
82aa1902f9SMichael Jones 
833eb1e6d8Smichaelrj-google     LIBC_NAMESPACE::libc_errno = 0;
84b6bc9d72SGuillaume Chatelet     long double result = LIBC_NAMESPACE::strtold(inputString, &str_end);
85aa1902f9SMichael Jones 
86b6bc9d72SGuillaume Chatelet     LIBC_NAMESPACE::fputil::FPBits<long double> actual_fp =
87b6bc9d72SGuillaume Chatelet         LIBC_NAMESPACE::fputil::FPBits<long double>();
88b6bc9d72SGuillaume Chatelet     actual_fp = LIBC_NAMESPACE::fputil::FPBits<long double>(result);
89aa1902f9SMichael Jones 
9025226f3eSMichael Jones     EXPECT_EQ(str_end - inputString, expectedStrLen);
91aa1902f9SMichael Jones 
92d02471edSGuillaume Chatelet     EXPECT_EQ(actual_fp.uintval(), expected_fp.uintval());
9311ec512fSGuillaume Chatelet     EXPECT_EQ(actual_fp.is_neg(), expected_fp.is_neg());
9425226f3eSMichael Jones     EXPECT_EQ(actual_fp.get_exponent(), expected_fp.get_exponent());
9525226f3eSMichael Jones     EXPECT_EQ(actual_fp.get_mantissa(), expected_fp.get_mantissa());
9673874f7aSGuillaume Chatelet     ASSERT_ERRNO_EQ(expected_errno);
97aa1902f9SMichael Jones   }
98aa1902f9SMichael Jones };
99aa1902f9SMichael Jones 
100aa1902f9SMichael Jones TEST_F(LlvmLibcStrToLDTest, SimpleTest) {
1015d1dbe11SMichael Jones   run_test("123", 3,
1025d1dbe11SMichael Jones            SELECT_CONST(uint64_t(0x405ec00000000000),
103300f8da8SSiva Chandra Reddy                         UInt128(0x4005f60000) << 40,
104300f8da8SSiva Chandra Reddy                         UInt128(0x4005ec0000000000) << 64));
105aa1902f9SMichael Jones 
106aa1902f9SMichael Jones   // This should fail on Eisel-Lemire, forcing a fallback to simple decimal
107aa1902f9SMichael Jones   // conversion.
1085d1dbe11SMichael Jones   run_test("12345678901234549760", 20,
1095d1dbe11SMichael Jones            SELECT_CONST(uint64_t(0x43e56a95319d63d8),
110300f8da8SSiva Chandra Reddy                         (UInt128(0x403eab54a9) << 40) + UInt128(0x8ceb1ec400),
111300f8da8SSiva Chandra Reddy                         (UInt128(0x403e56a95319d63d) << 64) +
112300f8da8SSiva Chandra Reddy                             UInt128(0x8800000000000000)));
113aa1902f9SMichael Jones 
114aa1902f9SMichael Jones   // Found while looking for difficult test cases here:
115aa1902f9SMichael Jones   // https://github.com/nigeltao/parse-number-fxx-test-data/blob/main/more-test-cases/golang-org-issue-36657.txt
1165d1dbe11SMichael Jones   run_test("1090544144181609348835077142190", 31,
1175d1dbe11SMichael Jones            SELECT_CONST(uint64_t(0x462b8779f2474dfb),
118300f8da8SSiva Chandra Reddy                         (UInt128(0x4062dc3bcf) << 40) + UInt128(0x923a6fd402),
119300f8da8SSiva Chandra Reddy                         (UInt128(0x4062b8779f2474df) << 64) +
120300f8da8SSiva Chandra Reddy                             UInt128(0xa804bfd8c6d5c000)));
121aa1902f9SMichael Jones 
1225d1dbe11SMichael Jones   run_test("0x123", 5,
1235d1dbe11SMichael Jones            SELECT_CONST(uint64_t(0x4072300000000000),
124300f8da8SSiva Chandra Reddy                         (UInt128(0x4007918000) << 40),
125300f8da8SSiva Chandra Reddy                         (UInt128(0x4007230000000000) << 64)));
126aa1902f9SMichael Jones }
127aa1902f9SMichael Jones 
128aa1902f9SMichael Jones // These are tests that have caused problems for doubles in the past.
129aa1902f9SMichael Jones TEST_F(LlvmLibcStrToLDTest, Float64SpecificFailures) {
1305d1dbe11SMichael Jones   run_test("3E70000000000000", 16,
1315d1dbe11SMichael Jones            SELECT_CONST(uint64_t(0x7FF0000000000000),
132300f8da8SSiva Chandra Reddy                         (UInt128(0x7fff800000) << 40),
133300f8da8SSiva Chandra Reddy                         (UInt128(0x7fff000000000000) << 64)),
1345d1dbe11SMichael Jones            ERANGE);
1355d1dbe11SMichael Jones   run_test("358416272e-33", 13,
1365d1dbe11SMichael Jones            SELECT_CONST(uint64_t(0x3adbbb2a68c9d0b9),
137300f8da8SSiva Chandra Reddy                         (UInt128(0x3fadddd953) << 40) + UInt128(0x464e85c400),
138300f8da8SSiva Chandra Reddy                         (UInt128(0x3fadbbb2a68c9d0b) << 64) +
139300f8da8SSiva Chandra Reddy                             UInt128(0x8800e7969e1c5fc8)));
1405d1dbe11SMichael Jones   run_test("2.16656806400000023841857910156251e9", 36,
1415d1dbe11SMichael Jones            SELECT_CONST(uint64_t(0x41e0246690000001),
142300f8da8SSiva Chandra Reddy                         (UInt128(0x401e812334) << 40) + UInt128(0x8000000400),
143300f8da8SSiva Chandra Reddy                         (UInt128(0x401e024669000000) << 64) +
144300f8da8SSiva Chandra Reddy                             UInt128(0x800000000000018)));
1455d1dbe11SMichael Jones   run_test("27949676547093071875", 20,
1465d1dbe11SMichael Jones            SELECT_CONST(uint64_t(0x43f83e132bc608c9),
147300f8da8SSiva Chandra Reddy                         (UInt128(0x403fc1f099) << 40) + UInt128(0x5e30464402),
148300f8da8SSiva Chandra Reddy                         (UInt128(0x403f83e132bc608c) << 64) +
149300f8da8SSiva Chandra Reddy                             UInt128(0x8803000000000000)));
150aa1902f9SMichael Jones }
151aa1902f9SMichael Jones 
152ae3b59e6SMichael Jones TEST_F(LlvmLibcStrToLDTest, Float80SpecificFailures) {
153ae3b59e6SMichael Jones   run_test("7777777777777777777777777777777777777777777777777777777777777777777"
154ae3b59e6SMichael Jones            "777777777777777777777777777777777",
155ae3b59e6SMichael Jones            100,
156ae3b59e6SMichael Jones            SELECT_CONST(uint64_t(0x54ac729b8fcaf734),
157ae3b59e6SMichael Jones                         (UInt128(0x414ae394dc) << 40) + UInt128(0x7e57b9a0c2),
158ae3b59e6SMichael Jones                         (UInt128(0x414ac729b8fcaf73) << 64) +
159ae3b59e6SMichael Jones                             UInt128(0x4184a3d793224129)));
160ae3b59e6SMichael Jones }
161ae3b59e6SMichael Jones 
162aa1902f9SMichael Jones TEST_F(LlvmLibcStrToLDTest, MaxSizeNumbers) {
1635d1dbe11SMichael Jones   run_test("1.1897314953572317650e4932", 26,
1645d1dbe11SMichael Jones            SELECT_CONST(uint64_t(0x7FF0000000000000),
165300f8da8SSiva Chandra Reddy                         (UInt128(0x7ffeffffff) << 40) + UInt128(0xffffffffff),
166300f8da8SSiva Chandra Reddy                         (UInt128(0x7ffeffffffffffff) << 64) +
167300f8da8SSiva Chandra Reddy                             UInt128(0xfffd57322e3f8675)),
1685d1dbe11SMichael Jones            SELECT_CONST(ERANGE, 0, 0));
1695d1dbe11SMichael Jones   run_test("1.18973149535723176508e4932", 27,
1705d1dbe11SMichael Jones            SELECT_CONST(uint64_t(0x7FF0000000000000),
171300f8da8SSiva Chandra Reddy                         (UInt128(0x7fff800000) << 40),
172300f8da8SSiva Chandra Reddy                         (UInt128(0x7ffeffffffffffff) << 64) +
173300f8da8SSiva Chandra Reddy                             UInt128(0xffffd2478338036c)),
1745d1dbe11SMichael Jones            SELECT_CONST(ERANGE, ERANGE, 0));
175aa1902f9SMichael Jones }
176aa1902f9SMichael Jones 
177aa1902f9SMichael Jones // These tests check subnormal behavior for 80 bit and 128 bit floats. They will
178aa1902f9SMichael Jones // be too small for 64 bit floats.
179aa1902f9SMichael Jones TEST_F(LlvmLibcStrToLDTest, SubnormalTests) {
1805d1dbe11SMichael Jones   run_test("1e-4950", 7,
181300f8da8SSiva Chandra Reddy            SELECT_CONST(uint64_t(0), (UInt128(0x00000000000000000003)),
182300f8da8SSiva Chandra Reddy                         (UInt128(0x000000000000000000057c9647e1a018))),
183aa1902f9SMichael Jones            ERANGE);
1845d1dbe11SMichael Jones   run_test("1.89e-4951", 10,
185300f8da8SSiva Chandra Reddy            SELECT_CONST(uint64_t(0), (UInt128(0x00000000000000000001)),
186300f8da8SSiva Chandra Reddy                         (UInt128(0x0000000000000000000109778a006738))),
187aa1902f9SMichael Jones            ERANGE);
1885d1dbe11SMichael Jones   run_test("4e-4966", 7,
189300f8da8SSiva Chandra Reddy            SELECT_CONST(uint64_t(0), (UInt128(0)),
190300f8da8SSiva Chandra Reddy                         (UInt128(0x00000000000000000000000000000001))),
191aa1902f9SMichael Jones            ERANGE);
192aa1902f9SMichael Jones }
193aa1902f9SMichael Jones 
194aa1902f9SMichael Jones TEST_F(LlvmLibcStrToLDTest, SmallNormalTests) {
195300f8da8SSiva Chandra Reddy   run_test("3.37e-4932", 10,
196300f8da8SSiva Chandra Reddy            SELECT_CONST(
197300f8da8SSiva Chandra Reddy                uint64_t(0), (UInt128(0x1804cf7) << 40) + UInt128(0x908850712),
198300f8da8SSiva Chandra Reddy                (UInt128(0x10099ee12110a) << 64) + UInt128(0xe24b75c0f50dc0c)),
1995d1dbe11SMichael Jones            SELECT_CONST(ERANGE, 0, 0));
200aa1902f9SMichael Jones }
201aa1902f9SMichael Jones 
202aa1902f9SMichael Jones TEST_F(LlvmLibcStrToLDTest, ComplexHexadecimalTests) {
2035d1dbe11SMichael Jones   run_test("0x1p16383", 9,
204300f8da8SSiva Chandra Reddy            SELECT_CONST(0x7ff0000000000000, (UInt128(0x7ffe800000) << 40),
205300f8da8SSiva Chandra Reddy                         (UInt128(0x7ffe000000000000) << 64)),
2065d1dbe11SMichael Jones            SELECT_CONST(ERANGE, 0, 0));
2075d1dbe11SMichael Jones   run_test("0x123456789abcdef", 17,
2085d1dbe11SMichael Jones            SELECT_CONST(0x43723456789abcdf,
209300f8da8SSiva Chandra Reddy                         (UInt128(0x403791a2b3) << 40) + UInt128(0xc4d5e6f780),
210300f8da8SSiva Chandra Reddy                         (UInt128(0x403723456789abcd) << 64) +
211300f8da8SSiva Chandra Reddy                             UInt128(0xef00000000000000)));
2125d1dbe11SMichael Jones   run_test("0x123456789abcdef0123456789ABCDEF", 33,
2135d1dbe11SMichael Jones            SELECT_CONST(0x47723456789abcdf,
214300f8da8SSiva Chandra Reddy                         (UInt128(0x407791a2b3) << 40) + UInt128(0xc4d5e6f781),
215300f8da8SSiva Chandra Reddy                         (UInt128(0x407723456789abcd) << 64) +
216300f8da8SSiva Chandra Reddy                             UInt128(0xef0123456789abce)));
217aa1902f9SMichael Jones }
218aa1902f9SMichael Jones 
219aa1902f9SMichael Jones TEST_F(LlvmLibcStrToLDTest, InfTests) {
2205d1dbe11SMichael Jones   run_test("INF", 3,
221300f8da8SSiva Chandra Reddy            SELECT_CONST(0x7ff0000000000000, (UInt128(0x7fff800000) << 40),
222300f8da8SSiva Chandra Reddy                         (UInt128(0x7fff000000000000) << 64)));
2235d1dbe11SMichael Jones   run_test("INFinity", 8,
224300f8da8SSiva Chandra Reddy            SELECT_CONST(0x7ff0000000000000, (UInt128(0x7fff800000) << 40),
225300f8da8SSiva Chandra Reddy                         (UInt128(0x7fff000000000000) << 64)));
2265d1dbe11SMichael Jones   run_test("-inf", 4,
227300f8da8SSiva Chandra Reddy            SELECT_CONST(0xfff0000000000000, (UInt128(0xffff800000) << 40),
228300f8da8SSiva Chandra Reddy                         (UInt128(0xffff000000000000) << 64)));
229aa1902f9SMichael Jones }
230aa1902f9SMichael Jones 
231aa1902f9SMichael Jones TEST_F(LlvmLibcStrToLDTest, NaNTests) {
2325d1dbe11SMichael Jones   run_test("NaN", 3,
233300f8da8SSiva Chandra Reddy            SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
234300f8da8SSiva Chandra Reddy                         (UInt128(0x7fff800000000000) << 64)));
2355d1dbe11SMichael Jones   run_test("-nAn", 4,
236300f8da8SSiva Chandra Reddy            SELECT_CONST(0xfff8000000000000, (UInt128(0xffffc00000) << 40),
237300f8da8SSiva Chandra Reddy                         (UInt128(0xffff800000000000) << 64)));
2385d1dbe11SMichael Jones   run_test("NaN()", 5,
239300f8da8SSiva Chandra Reddy            SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
240300f8da8SSiva Chandra Reddy                         (UInt128(0x7fff800000000000) << 64)));
2415d1dbe11SMichael Jones   run_test("NaN(1234)", 9,
2425d1dbe11SMichael Jones            SELECT_CONST(0x7ff80000000004d2,
243300f8da8SSiva Chandra Reddy                         (UInt128(0x7fffc00000) << 40) + UInt128(0x4d2),
244300f8da8SSiva Chandra Reddy                         (UInt128(0x7fff800000000000) << 64) + UInt128(0x4d2)));
2455d1dbe11SMichael Jones   run_test("NaN(0xffffffffffff)", 19,
2465d1dbe11SMichael Jones            SELECT_CONST(0x7ff8ffffffffffff,
247300f8da8SSiva Chandra Reddy                         (UInt128(0x7fffc000ff) << 40) + UInt128(0xffffffffff),
248300f8da8SSiva Chandra Reddy                         (UInt128(0x7fff800000000000) << 64) +
249300f8da8SSiva Chandra Reddy                             UInt128(0xffffffffffff)));
2505d1dbe11SMichael Jones   run_test("NaN(0xfffffffffffff)", 20,
2515d1dbe11SMichael Jones            SELECT_CONST(0x7fffffffffffffff,
252300f8da8SSiva Chandra Reddy                         (UInt128(0x7fffc00fff) << 40) + UInt128(0xffffffffff),
253300f8da8SSiva Chandra Reddy                         (UInt128(0x7fff800000000000) << 64) +
254300f8da8SSiva Chandra Reddy                             UInt128(0xfffffffffffff)));
2555d1dbe11SMichael Jones   run_test("NaN(0xffffffffffffffff)", 23,
2565d1dbe11SMichael Jones            SELECT_CONST(0x7fffffffffffffff,
257300f8da8SSiva Chandra Reddy                         (UInt128(0x7fffffffff) << 40) + UInt128(0xffffffffff),
258300f8da8SSiva Chandra Reddy                         (UInt128(0x7fff800000000000) << 64) +
259300f8da8SSiva Chandra Reddy                             UInt128(0xffffffffffffffff)));
2605d1dbe11SMichael Jones   run_test("NaN( 1234)", 3,
261300f8da8SSiva Chandra Reddy            SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
262300f8da8SSiva Chandra Reddy                         (UInt128(0x7fff800000000000) << 64)));
263aa1902f9SMichael Jones }
264