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
28class LlvmLibcStrToLDTest : public LIBC_NAMESPACE::testing::Test {
29public:
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)
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 LIBC_NAMESPACE::fputil::FPBits<long double> expected_fp =
79 LIBC_NAMESPACE::fputil::FPBits<long double>(expectedRawData);
80 const int expected_errno = expectedErrno;
81
82 LIBC_NAMESPACE::libc_errno = 0;
83 long double result = LIBC_NAMESPACE::strtold(str: inputString, str_end: &str_end);
84
85 LIBC_NAMESPACE::fputil::FPBits<long double> actual_fp =
86 LIBC_NAMESPACE::fputil::FPBits<long double>();
87 actual_fp = LIBC_NAMESPACE::fputil::FPBits<long double>(result);
88
89 EXPECT_EQ(str_end - inputString, expectedStrLen);
90
91 EXPECT_EQ(actual_fp.uintval(), expected_fp.uintval());
92 EXPECT_EQ(actual_fp.is_neg(), expected_fp.is_neg());
93 EXPECT_EQ(actual_fp.get_exponent(), expected_fp.get_exponent());
94 EXPECT_EQ(actual_fp.get_mantissa(), expected_fp.get_mantissa());
95 ASSERT_ERRNO_EQ(expected_errno);
96 }
97};
98
99TEST_F(LlvmLibcStrToLDTest, SimpleTest) {
100 run_test(inputString: "123", expectedStrLen: 3,
101 SELECT_CONST(uint64_t(0x405ec00000000000),
102 UInt128(0x4005f60000) << 40,
103 UInt128(0x4005ec0000000000) << 64));
104
105 // This should fail on Eisel-Lemire, forcing a fallback to simple decimal
106 // conversion.
107 run_test(inputString: "12345678901234549760", expectedStrLen: 20,
108 SELECT_CONST(uint64_t(0x43e56a95319d63d8),
109 (UInt128(0x403eab54a9) << 40) + UInt128(0x8ceb1ec400),
110 (UInt128(0x403e56a95319d63d) << 64) +
111 UInt128(0x8800000000000000)));
112
113 // Found while looking for difficult test cases here:
114 // https://github.com/nigeltao/parse-number-fxx-test-data/blob/main/more-test-cases/golang-org-issue-36657.txt
115 run_test(inputString: "1090544144181609348835077142190", expectedStrLen: 31,
116 SELECT_CONST(uint64_t(0x462b8779f2474dfb),
117 (UInt128(0x4062dc3bcf) << 40) + UInt128(0x923a6fd402),
118 (UInt128(0x4062b8779f2474df) << 64) +
119 UInt128(0xa804bfd8c6d5c000)));
120
121 run_test(inputString: "0x123", expectedStrLen: 5,
122 SELECT_CONST(uint64_t(0x4072300000000000),
123 (UInt128(0x4007918000) << 40),
124 (UInt128(0x4007230000000000) << 64)));
125}
126
127// These are tests that have caused problems for doubles in the past.
128TEST_F(LlvmLibcStrToLDTest, Float64SpecificFailures) {
129 run_test(inputString: "3E70000000000000", expectedStrLen: 16,
130 SELECT_CONST(uint64_t(0x7FF0000000000000),
131 (UInt128(0x7fff800000) << 40),
132 (UInt128(0x7fff000000000000) << 64)),
133 ERANGE);
134 run_test(inputString: "358416272e-33", expectedStrLen: 13,
135 SELECT_CONST(uint64_t(0x3adbbb2a68c9d0b9),
136 (UInt128(0x3fadddd953) << 40) + UInt128(0x464e85c400),
137 (UInt128(0x3fadbbb2a68c9d0b) << 64) +
138 UInt128(0x8800e7969e1c5fc8)));
139 run_test(inputString: "2.16656806400000023841857910156251e9", expectedStrLen: 36,
140 SELECT_CONST(uint64_t(0x41e0246690000001),
141 (UInt128(0x401e812334) << 40) + UInt128(0x8000000400),
142 (UInt128(0x401e024669000000) << 64) +
143 UInt128(0x800000000000018)));
144 run_test(inputString: "27949676547093071875", expectedStrLen: 20,
145 SELECT_CONST(uint64_t(0x43f83e132bc608c9),
146 (UInt128(0x403fc1f099) << 40) + UInt128(0x5e30464402),
147 (UInt128(0x403f83e132bc608c) << 64) +
148 UInt128(0x8803000000000000)));
149}
150
151TEST_F(LlvmLibcStrToLDTest, Float80SpecificFailures) {
152 run_test(inputString: "7777777777777777777777777777777777777777777777777777777777777777777"
153 "777777777777777777777777777777777",
154 expectedStrLen: 100,
155 SELECT_CONST(uint64_t(0x54ac729b8fcaf734),
156 (UInt128(0x414ae394dc) << 40) + UInt128(0x7e57b9a0c2),
157 (UInt128(0x414ac729b8fcaf73) << 64) +
158 UInt128(0x4184a3d793224129)));
159}
160
161TEST_F(LlvmLibcStrToLDTest, MaxSizeNumbers) {
162 run_test(inputString: "1.1897314953572317650e4932", expectedStrLen: 26,
163 SELECT_CONST(uint64_t(0x7FF0000000000000),
164 (UInt128(0x7ffeffffff) << 40) + UInt128(0xffffffffff),
165 (UInt128(0x7ffeffffffffffff) << 64) +
166 UInt128(0xfffd57322e3f8675)),
167 SELECT_CONST(ERANGE, 0, 0));
168 run_test(inputString: "1.18973149535723176508e4932", expectedStrLen: 27,
169 SELECT_CONST(uint64_t(0x7FF0000000000000),
170 (UInt128(0x7fff800000) << 40),
171 (UInt128(0x7ffeffffffffffff) << 64) +
172 UInt128(0xffffd2478338036c)),
173 SELECT_CONST(ERANGE, ERANGE, 0));
174}
175
176// These tests check subnormal behavior for 80 bit and 128 bit floats. They will
177// be too small for 64 bit floats.
178TEST_F(LlvmLibcStrToLDTest, SubnormalTests) {
179 run_test(inputString: "1e-4950", expectedStrLen: 7,
180 SELECT_CONST(uint64_t(0), (UInt128(0x00000000000000000003)),
181 (UInt128(0x000000000000000000057c9647e1a018))),
182 ERANGE);
183 run_test(inputString: "1.89e-4951", expectedStrLen: 10,
184 SELECT_CONST(uint64_t(0), (UInt128(0x00000000000000000001)),
185 (UInt128(0x0000000000000000000109778a006738))),
186 ERANGE);
187 run_test(inputString: "4e-4966", expectedStrLen: 7,
188 SELECT_CONST(uint64_t(0), (UInt128(0)),
189 (UInt128(0x00000000000000000000000000000001))),
190 ERANGE);
191}
192
193TEST_F(LlvmLibcStrToLDTest, SmallNormalTests) {
194 run_test(inputString: "3.37e-4932", expectedStrLen: 10,
195 SELECT_CONST(
196 uint64_t(0), (UInt128(0x1804cf7) << 40) + UInt128(0x908850712),
197 (UInt128(0x10099ee12110a) << 64) + UInt128(0xe24b75c0f50dc0c)),
198 SELECT_CONST(ERANGE, 0, 0));
199}
200
201TEST_F(LlvmLibcStrToLDTest, ComplexHexadecimalTests) {
202 run_test(inputString: "0x1p16383", expectedStrLen: 9,
203 SELECT_CONST(0x7ff0000000000000, (UInt128(0x7ffe800000) << 40),
204 (UInt128(0x7ffe000000000000) << 64)),
205 SELECT_CONST(ERANGE, 0, 0));
206 run_test(inputString: "0x123456789abcdef", expectedStrLen: 17,
207 SELECT_CONST(0x43723456789abcdf,
208 (UInt128(0x403791a2b3) << 40) + UInt128(0xc4d5e6f780),
209 (UInt128(0x403723456789abcd) << 64) +
210 UInt128(0xef00000000000000)));
211 run_test(inputString: "0x123456789abcdef0123456789ABCDEF", expectedStrLen: 33,
212 SELECT_CONST(0x47723456789abcdf,
213 (UInt128(0x407791a2b3) << 40) + UInt128(0xc4d5e6f781),
214 (UInt128(0x407723456789abcd) << 64) +
215 UInt128(0xef0123456789abce)));
216}
217
218TEST_F(LlvmLibcStrToLDTest, InfTests) {
219 run_test(inputString: "INF", expectedStrLen: 3,
220 SELECT_CONST(0x7ff0000000000000, (UInt128(0x7fff800000) << 40),
221 (UInt128(0x7fff000000000000) << 64)));
222 run_test(inputString: "INFinity", expectedStrLen: 8,
223 SELECT_CONST(0x7ff0000000000000, (UInt128(0x7fff800000) << 40),
224 (UInt128(0x7fff000000000000) << 64)));
225 run_test(inputString: "-inf", expectedStrLen: 4,
226 SELECT_CONST(0xfff0000000000000, (UInt128(0xffff800000) << 40),
227 (UInt128(0xffff000000000000) << 64)));
228}
229
230TEST_F(LlvmLibcStrToLDTest, NaNTests) {
231 run_test(inputString: "NaN", expectedStrLen: 3,
232 SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
233 (UInt128(0x7fff800000000000) << 64)));
234 run_test(inputString: "-nAn", expectedStrLen: 4,
235 SELECT_CONST(0xfff8000000000000, (UInt128(0xffffc00000) << 40),
236 (UInt128(0xffff800000000000) << 64)));
237 run_test(inputString: "NaN()", expectedStrLen: 5,
238 SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
239 (UInt128(0x7fff800000000000) << 64)));
240 run_test(inputString: "NaN(1234)", expectedStrLen: 9,
241 SELECT_CONST(0x7ff80000000004d2,
242 (UInt128(0x7fffc00000) << 40) + UInt128(0x4d2),
243 (UInt128(0x7fff800000000000) << 64) + UInt128(0x4d2)));
244 run_test(inputString: "NaN(0xffffffffffff)", expectedStrLen: 19,
245 SELECT_CONST(0x7ff8ffffffffffff,
246 (UInt128(0x7fffc000ff) << 40) + UInt128(0xffffffffff),
247 (UInt128(0x7fff800000000000) << 64) +
248 UInt128(0xffffffffffff)));
249 run_test(inputString: "NaN(0xfffffffffffff)", expectedStrLen: 20,
250 SELECT_CONST(0x7fffffffffffffff,
251 (UInt128(0x7fffc00fff) << 40) + UInt128(0xffffffffff),
252 (UInt128(0x7fff800000000000) << 64) +
253 UInt128(0xfffffffffffff)));
254 run_test(inputString: "NaN(0xffffffffffffffff)", expectedStrLen: 23,
255 SELECT_CONST(0x7fffffffffffffff,
256 (UInt128(0x7fffffffff) << 40) + UInt128(0xffffffffff),
257 (UInt128(0x7fff800000000000) << 64) +
258 UInt128(0xffffffffffffffff)));
259 run_test(inputString: "NaN( 1234)", expectedStrLen: 3,
260 SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
261 (UInt128(0x7fff800000000000) << 64)));
262}
263

source code of libc/test/src/stdlib/strtold_test.cpp