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