1 //===-- Unittests for str_to_float ----------------------------------------===//
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/str_to_float.h"
11 
12 #include "utils/UnitTest/Test.h"
13 
14 class LlvmLibcStrToFloatTest : public __llvm_libc::testing::Test {
15 public:
16   template <class T>
17   void clinger_fast_path_test(
18       const typename __llvm_libc::fputil::FPBits<T>::UIntType inputMantissa,
19       const int32_t inputExp10,
20       const typename __llvm_libc::fputil::FPBits<T>::UIntType
21           expectedOutputMantissa,
22       const uint32_t expectedOutputExp2) {
23     typename __llvm_libc::fputil::FPBits<T>::UIntType actual_output_mantissa =
24         0;
25     uint32_t actual_output_exp2 = 0;
26 
27     ASSERT_TRUE(__llvm_libc::internal::clinger_fast_path<T>(
28         inputMantissa, inputExp10, &actual_output_mantissa,
29         &actual_output_exp2));
30     EXPECT_EQ(actual_output_mantissa, expectedOutputMantissa);
31     EXPECT_EQ(actual_output_exp2, expectedOutputExp2);
32   }
33 
34   template <class T>
35   void clinger_fast_path_fails_test(
36       const typename __llvm_libc::fputil::FPBits<T>::UIntType inputMantissa,
37       const int32_t inputExp10) {
38     typename __llvm_libc::fputil::FPBits<T>::UIntType actual_output_mantissa =
39         0;
40     uint32_t actual_output_exp2 = 0;
41 
42     ASSERT_FALSE(__llvm_libc::internal::clinger_fast_path<T>(
43         inputMantissa, inputExp10, &actual_output_mantissa,
44         &actual_output_exp2));
45   }
46 
47   template <class T>
48   void eisel_lemire_test(
49       const typename __llvm_libc::fputil::FPBits<T>::UIntType inputMantissa,
50       const int32_t inputExp10,
51       const typename __llvm_libc::fputil::FPBits<T>::UIntType
52           expectedOutputMantissa,
53       const uint32_t expectedOutputExp2) {
54     typename __llvm_libc::fputil::FPBits<T>::UIntType actual_output_mantissa =
55         0;
56     uint32_t actual_output_exp2 = 0;
57 
58     ASSERT_TRUE(__llvm_libc::internal::eisel_lemire<T>(
59         inputMantissa, inputExp10, &actual_output_mantissa,
60         &actual_output_exp2));
61     EXPECT_EQ(actual_output_mantissa, expectedOutputMantissa);
62     EXPECT_EQ(actual_output_exp2, expectedOutputExp2);
63   }
64 
65   template <class T>
66   void simple_decimal_conversion_test(
67       const char *__restrict numStart,
68       const typename __llvm_libc::fputil::FPBits<T>::UIntType
69           expectedOutputMantissa,
70       const uint32_t expectedOutputExp2, const int expectedErrno = 0) {
71     typename __llvm_libc::fputil::FPBits<T>::UIntType actual_output_mantissa =
72         0;
73     uint32_t actual_output_exp2 = 0;
74     errno = 0;
75 
76     __llvm_libc::internal::simple_decimal_conversion<T>(
77         numStart, &actual_output_mantissa, &actual_output_exp2);
78     EXPECT_EQ(actual_output_mantissa, expectedOutputMantissa);
79     EXPECT_EQ(actual_output_exp2, expectedOutputExp2);
80     EXPECT_EQ(errno, expectedErrno);
81   }
82 };
83 
84 TEST(LlvmLibcStrToFloatTest, LeadingZeroes) {
85   uint64_t test_num64 = 1;
86   uint32_t num_of_zeroes = 63;
87   EXPECT_EQ(__llvm_libc::internal::leading_zeroes<uint64_t>(0), 64u);
88   for (; num_of_zeroes < 64; test_num64 <<= 1, num_of_zeroes--) {
89     EXPECT_EQ(__llvm_libc::internal::leading_zeroes<uint64_t>(test_num64),
90               num_of_zeroes);
91   }
92 
93   test_num64 = 3;
94   num_of_zeroes = 62;
95   for (; num_of_zeroes > 63; test_num64 <<= 1, num_of_zeroes--) {
96     EXPECT_EQ(__llvm_libc::internal::leading_zeroes<uint64_t>(test_num64),
97               num_of_zeroes);
98   }
99 
100   EXPECT_EQ(__llvm_libc::internal::leading_zeroes<uint64_t>(0xffffffffffffffff),
101             0u);
102 
103   test_num64 = 1;
104   num_of_zeroes = 63;
105   for (; num_of_zeroes > 63;
106        test_num64 = (test_num64 << 1) + 1, num_of_zeroes--) {
107     EXPECT_EQ(__llvm_libc::internal::leading_zeroes<uint64_t>(test_num64),
108               num_of_zeroes);
109   }
110 
111   uint64_t test_num32 = 1;
112   num_of_zeroes = 31;
113   EXPECT_EQ(__llvm_libc::internal::leading_zeroes<uint32_t>(0), 32u);
114   for (; num_of_zeroes < 32; test_num32 <<= 1, num_of_zeroes--) {
115     EXPECT_EQ(__llvm_libc::internal::leading_zeroes<uint32_t>(test_num32),
116               num_of_zeroes);
117   }
118 
119   EXPECT_EQ(__llvm_libc::internal::leading_zeroes<uint32_t>(0xffffffff), 0u);
120 }
121 
122 TEST_F(LlvmLibcStrToFloatTest, ClingerFastPathFloat64Simple) {
123   clinger_fast_path_test<double>(123, 0, 0xEC00000000000, 1029);
124   clinger_fast_path_test<double>(1234567890123456, 1, 0x5ee2a2eb5a5c0, 1076);
125   clinger_fast_path_test<double>(1234567890, -10, 0xf9add3739635f, 1019);
126 }
127 
128 TEST_F(LlvmLibcStrToFloatTest, ClingerFastPathFloat64ExtendedExp) {
129   clinger_fast_path_test<double>(1, 30, 0x93e5939a08cea, 1122);
130   clinger_fast_path_test<double>(1, 37, 0xe17b84357691b, 1145);
131   clinger_fast_path_fails_test<double>(10, 37);
132   clinger_fast_path_fails_test<double>(1, 100);
133 }
134 
135 TEST_F(LlvmLibcStrToFloatTest, ClingerFastPathFloat64NegativeExp) {
136   clinger_fast_path_test<double>(1, -10, 0xb7cdfd9d7bdbb, 989);
137   clinger_fast_path_test<double>(1, -20, 0x79ca10c924223, 956);
138   clinger_fast_path_fails_test<double>(1, -25);
139 }
140 
141 TEST_F(LlvmLibcStrToFloatTest, ClingerFastPathFloat32Simple) {
142   clinger_fast_path_test<float>(123, 0, 0x760000, 133);
143   clinger_fast_path_test<float>(1234567, 1, 0x3c6146, 150);
144   clinger_fast_path_test<float>(12345, -5, 0x7cd35b, 123);
145 }
146 
147 TEST_F(LlvmLibcStrToFloatTest, ClingerFastPathFloat32ExtendedExp) {
148   clinger_fast_path_test<float>(1, 15, 0x635fa9, 176);
149   clinger_fast_path_test<float>(1, 17, 0x31a2bc, 183);
150   clinger_fast_path_fails_test<float>(10, 17);
151   clinger_fast_path_fails_test<float>(1, 50);
152 }
153 
154 TEST_F(LlvmLibcStrToFloatTest, ClingerFastPathFloat32NegativeExp) {
155   clinger_fast_path_test<float>(1, -5, 0x27c5ac, 110);
156   clinger_fast_path_test<float>(1, -10, 0x5be6ff, 93);
157   clinger_fast_path_fails_test<float>(1, -15);
158 }
159 
160 TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat64Simple) {
161   eisel_lemire_test<double>(12345678901234567890u, 1, 0x1AC53A7E04BCDA, 1089);
162   eisel_lemire_test<double>(123, 0, 0x1EC00000000000, 1029);
163   eisel_lemire_test<double>(12345678901234568192u, 0, 0x156A95319D63E2, 1086);
164 }
165 
166 TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat64SpecificFailures) {
167   // These test cases have caused failures in the past.
168   eisel_lemire_test<double>(358416272, -33, 0x1BBB2A68C9D0B9, 941);
169   eisel_lemire_test<double>(2166568064000000238u, -9, 0x10246690000000, 1054);
170   eisel_lemire_test<double>(2794967654709307187u, 1, 0x183e132bc608c8, 1087);
171   eisel_lemire_test<double>(2794967654709307188u, 1, 0x183e132bc608c9, 1087);
172 }
173 
174 TEST_F(LlvmLibcStrToFloatTest, EiselLemireFallbackStates) {
175   // Check the fallback states for the algorithm:
176   uint32_t float_output_mantissa = 0;
177   uint64_t double_output_mantissa = 0;
178   __uint128_t too_long_mantissa = 0;
179   uint32_t output_exp2 = 0;
180 
181   // This Eisel-Lemire implementation doesn't support long doubles yet.
182   ASSERT_FALSE(__llvm_libc::internal::eisel_lemire<long double>(
183       too_long_mantissa, 0, &too_long_mantissa, &output_exp2));
184 
185   // This number can't be evaluated by Eisel-Lemire since it's exactly 1024 away
186   // from both of its closest floating point approximations
187   // (12345678901234548736 and 12345678901234550784)
188   ASSERT_FALSE(__llvm_libc::internal::eisel_lemire<double>(
189       12345678901234549760u, 0, &double_output_mantissa, &output_exp2));
190 
191   ASSERT_FALSE(__llvm_libc::internal::eisel_lemire<float>(
192       20040229, 0, &float_output_mantissa, &output_exp2));
193 }
194 
195 TEST_F(LlvmLibcStrToFloatTest, SimpleDecimalConversion64BasicWholeNumbers) {
196   simple_decimal_conversion_test<double>("123456789012345678900",
197                                          0x1AC53A7E04BCDA, 1089);
198   simple_decimal_conversion_test<double>("123", 0x1EC00000000000, 1029);
199   simple_decimal_conversion_test<double>("12345678901234549760",
200                                          0x156A95319D63D8, 1086);
201 }
202 
203 TEST_F(LlvmLibcStrToFloatTest, SimpleDecimalConversion64BasicDecimals) {
204   simple_decimal_conversion_test<double>("1.2345", 0x13c083126e978d, 1023);
205   simple_decimal_conversion_test<double>(".2345", 0x1e04189374bc6a, 1020);
206   simple_decimal_conversion_test<double>(".299792458", 0x132fccb4aca314, 1021);
207 }
208 
209 TEST_F(LlvmLibcStrToFloatTest, SimpleDecimalConversion64BasicExponents) {
210   simple_decimal_conversion_test<double>("1e10", 0x12a05f20000000, 1056);
211   simple_decimal_conversion_test<double>("1e-10", 0x1b7cdfd9d7bdbb, 989);
212   simple_decimal_conversion_test<double>("1e300", 0x17e43c8800759c, 2019);
213   simple_decimal_conversion_test<double>("1e-300", 0x156e1fc2f8f359, 26);
214 }
215 
216 TEST_F(LlvmLibcStrToFloatTest, SimpleDecimalConversion64BasicSubnormals) {
217   simple_decimal_conversion_test<double>("1e-320", 0x7e8, 0, ERANGE);
218   simple_decimal_conversion_test<double>("1e-308", 0x730d67819e8d2, 0, ERANGE);
219   simple_decimal_conversion_test<double>("2.9e-308", 0x14da6df5e4bcc8, 1);
220 }
221 
222 TEST_F(LlvmLibcStrToFloatTest, SimpleDecimalConversion64SubnormalRounding) {
223 
224   // Technically you can keep adding digits until you hit the truncation limit,
225   // but this is the shortest string that results in the maximum subnormal that
226   // I found.
227   simple_decimal_conversion_test<double>("2.225073858507201e-308",
228                                          0xfffffffffffff, 0, ERANGE);
229 
230   // Same here, if you were to extend the max subnormal out for another 800
231   // digits, incrementing any one of those digits would create a normal number.
232   simple_decimal_conversion_test<double>("2.2250738585072012e-308",
233                                          0x10000000000000, 1);
234 }
235 
236 TEST_F(LlvmLibcStrToFloatTest, SimpleDecimalConversion32SpecificFailures) {
237   simple_decimal_conversion_test<float>(
238       "1.4012984643248170709237295832899161312802619418765e-45", 0x1, 0,
239       ERANGE);
240 }
241 
242 TEST(LlvmLibcStrToFloatTest, SimpleDecimalConversionExtraTypes) {
243   uint32_t float_output_mantissa = 0;
244   uint32_t output_exp2 = 0;
245 
246   errno = 0;
247   __llvm_libc::internal::simple_decimal_conversion<float>(
248       "123456789012345678900", &float_output_mantissa, &output_exp2);
249   EXPECT_EQ(float_output_mantissa, uint32_t(0xd629d4));
250   EXPECT_EQ(output_exp2, uint32_t(193));
251   EXPECT_EQ(errno, 0);
252 
253   uint64_t double_output_mantissa = 0;
254   output_exp2 = 0;
255 
256   errno = 0;
257   __llvm_libc::internal::simple_decimal_conversion<double>(
258       "123456789012345678900", &double_output_mantissa, &output_exp2);
259   EXPECT_EQ(double_output_mantissa, uint64_t(0x1AC53A7E04BCDA));
260   EXPECT_EQ(output_exp2, uint32_t(1089));
261   EXPECT_EQ(errno, 0);
262 
263   // TODO(michaelrj): Get long double support working.
264 
265   // __uint128_t longDoubleOutputMantissa = 0;
266   // outputExp2 = 0;
267 
268   // errno = 0;
269   // __llvm_libc::internal::simple_decimal_conversion<long double>(
270   //     "123456789012345678900", &longDoubleOutputMantissa, &outputExp2);
271   // EXPECT_EQ(longDoubleOutputMantissa, __uint128_t(0x1AC53A7E04BCDA));
272   // EXPECT_EQ(outputExp2, uint32_t(1089));
273   // EXPECT_EQ(errno, 0);
274 }
275