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 EiselLemireTest(
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::eiselLemire<T>(
27         inputMantissa, inputExp10, &actualOutputMantissa, &actualOutputExp2));
28     EXPECT_EQ(actualOutputMantissa, expectedOutputMantissa);
29     EXPECT_EQ(actualOutputExp2, expectedOutputExp2);
30   }
31 
32   template <class T>
33   void SimpleDecimalConversionTest(
34       const char *__restrict numStart,
35       const typename __llvm_libc::fputil::FPBits<T>::UIntType
36           expectedOutputMantissa,
37       const uint32_t expectedOutputExp2, const int expectedErrno = 0) {
38     typename __llvm_libc::fputil::FPBits<T>::UIntType actualOutputMantissa = 0;
39     uint32_t actualOutputExp2 = 0;
40     errno = 0;
41 
42     __llvm_libc::internal::simpleDecimalConversion<T>(
43         numStart, &actualOutputMantissa, &actualOutputExp2);
44     EXPECT_EQ(actualOutputMantissa, expectedOutputMantissa);
45     EXPECT_EQ(actualOutputExp2, expectedOutputExp2);
46     EXPECT_EQ(errno, expectedErrno);
47   }
48 };
49 
50 TEST(LlvmLibcStrToFloatTest, LeadingZeroes) {
51   uint64_t testNum64 = 1;
52   uint32_t numOfZeroes = 63;
53   EXPECT_EQ(__llvm_libc::internal::leadingZeroes<uint64_t>(0), 64u);
54   for (; numOfZeroes < 64; testNum64 <<= 1, numOfZeroes--) {
55     EXPECT_EQ(__llvm_libc::internal::leadingZeroes<uint64_t>(testNum64),
56               numOfZeroes);
57   }
58 
59   testNum64 = 3;
60   numOfZeroes = 62;
61   for (; numOfZeroes > 63; testNum64 <<= 1, numOfZeroes--) {
62     EXPECT_EQ(__llvm_libc::internal::leadingZeroes<uint64_t>(testNum64),
63               numOfZeroes);
64   }
65 
66   EXPECT_EQ(__llvm_libc::internal::leadingZeroes<uint64_t>(0xffffffffffffffff),
67             0u);
68 
69   testNum64 = 1;
70   numOfZeroes = 63;
71   for (; numOfZeroes > 63; testNum64 = (testNum64 << 1) + 1, numOfZeroes--) {
72     EXPECT_EQ(__llvm_libc::internal::leadingZeroes<uint64_t>(testNum64),
73               numOfZeroes);
74   }
75 
76   uint64_t testNum32 = 1;
77   numOfZeroes = 31;
78   EXPECT_EQ(__llvm_libc::internal::leadingZeroes<uint32_t>(0), 32u);
79   for (; numOfZeroes < 32; testNum32 <<= 1, numOfZeroes--) {
80     EXPECT_EQ(__llvm_libc::internal::leadingZeroes<uint32_t>(testNum32),
81               numOfZeroes);
82   }
83 
84   EXPECT_EQ(__llvm_libc::internal::leadingZeroes<uint32_t>(0xffffffff), 0u);
85 }
86 
87 TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat64Simple) {
88   EiselLemireTest<double>(12345678901234567890u, 1, 0x1AC53A7E04BCDA, 1089);
89   EiselLemireTest<double>(123, 0, 0x1EC00000000000, 1029);
90   EiselLemireTest<double>(12345678901234568192u, 0, 0x156A95319D63E2, 1086);
91 }
92 
93 TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat64SpecificFailures) {
94   // These test cases have caused failures in the past.
95   EiselLemireTest<double>(358416272, -33, 0x1BBB2A68C9D0B9, 941);
96   EiselLemireTest<double>(2166568064000000238u, -9, 0x10246690000000, 1054);
97   EiselLemireTest<double>(2794967654709307187u, 1, 0x183e132bc608c8, 1087);
98   EiselLemireTest<double>(2794967654709307188u, 1, 0x183e132bc608c9, 1087);
99 }
100 
101 TEST_F(LlvmLibcStrToFloatTest, EiselLemireFallbackStates) {
102   // Check the fallback states for the algorithm:
103   uint32_t floatOutputMantissa = 0;
104   uint64_t doubleOutputMantissa = 0;
105   __uint128_t tooLongMantissa = 0;
106   uint32_t outputExp2 = 0;
107 
108   // This Eisel-Lemire implementation doesn't support long doubles yet.
109   ASSERT_FALSE(__llvm_libc::internal::eiselLemire<long double>(
110       tooLongMantissa, 0, &tooLongMantissa, &outputExp2));
111 
112   // This number can't be evaluated by Eisel-Lemire since it's exactly 1024 away
113   // from both of its closest floating point approximations
114   // (12345678901234548736 and 12345678901234550784)
115   ASSERT_FALSE(__llvm_libc::internal::eiselLemire<double>(
116       12345678901234549760u, 0, &doubleOutputMantissa, &outputExp2));
117 
118   ASSERT_FALSE(__llvm_libc::internal::eiselLemire<float>(
119       20040229, 0, &floatOutputMantissa, &outputExp2));
120 }
121 
122 TEST_F(LlvmLibcStrToFloatTest, SimpleDecimalConversion64BasicWholeNumbers) {
123   SimpleDecimalConversionTest<double>("123456789012345678900", 0x1AC53A7E04BCDA,
124                                       1089);
125   SimpleDecimalConversionTest<double>("123", 0x1EC00000000000, 1029);
126   SimpleDecimalConversionTest<double>("12345678901234549760", 0x156A95319D63D8,
127                                       1086);
128 }
129 
130 TEST_F(LlvmLibcStrToFloatTest, SimpleDecimalConversion64BasicDecimals) {
131   SimpleDecimalConversionTest<double>("1.2345", 0x13c083126e978d, 1023);
132   SimpleDecimalConversionTest<double>(".2345", 0x1e04189374bc6a, 1020);
133   SimpleDecimalConversionTest<double>(".299792458", 0x132fccb4aca314, 1021);
134 }
135 
136 TEST_F(LlvmLibcStrToFloatTest, SimpleDecimalConversion64BasicExponents) {
137   SimpleDecimalConversionTest<double>("1e10", 0x12a05f20000000, 1056);
138   SimpleDecimalConversionTest<double>("1e-10", 0x1b7cdfd9d7bdbb, 989);
139   SimpleDecimalConversionTest<double>("1e300", 0x17e43c8800759c, 2019);
140   SimpleDecimalConversionTest<double>("1e-300", 0x156e1fc2f8f359, 26);
141 }
142 
143 TEST_F(LlvmLibcStrToFloatTest, SimpleDecimalConversion64BasicSubnormals) {
144   SimpleDecimalConversionTest<double>("1e-320", 0x7e8, 0);
145   SimpleDecimalConversionTest<double>("1e-308", 0x730d67819e8d2, 0);
146   SimpleDecimalConversionTest<double>("2.9e-308", 0x14da6df5e4bcc8, 1);
147 }
148 
149 TEST_F(LlvmLibcStrToFloatTest, SimpleDecimalConversion64SubnormalRounding) {
150 
151   // Technically you can keep adding digits until you hit the truncation limit,
152   // but this is the shortest string that results in the maximum subnormal that
153   // I found.
154   SimpleDecimalConversionTest<double>("2.225073858507201e-308", 0xfffffffffffff,
155                                       0);
156 
157   // Same here, if you were to extend the max subnormal out for another 800
158   // digits, incrementing any one of those digits would create a normal number.
159   SimpleDecimalConversionTest<double>("2.2250738585072012e-308",
160                                       0x10000000000000, 1);
161 }
162 
163 TEST_F(LlvmLibcStrToFloatTest, SimpleDecimalConversion32SpecificFailures) {
164   SimpleDecimalConversionTest<float>(
165       "1.4012984643248170709237295832899161312802619418765e-45", 0x1, 0);
166 }
167 
168 TEST(LlvmLibcStrToFloatTest, SimpleDecimalConversionExtraTypes) {
169   uint32_t floatOutputMantissa = 0;
170   uint32_t outputExp2 = 0;
171 
172   errno = 0;
173   __llvm_libc::internal::simpleDecimalConversion<float>(
174       "123456789012345678900", &floatOutputMantissa, &outputExp2);
175   EXPECT_EQ(floatOutputMantissa, uint32_t(0xd629d4));
176   EXPECT_EQ(outputExp2, uint32_t(193));
177   EXPECT_EQ(errno, 0);
178 
179   uint64_t doubleOutputMantissa = 0;
180   outputExp2 = 0;
181 
182   errno = 0;
183   __llvm_libc::internal::simpleDecimalConversion<double>(
184       "123456789012345678900", &doubleOutputMantissa, &outputExp2);
185   EXPECT_EQ(doubleOutputMantissa, uint64_t(0x1AC53A7E04BCDA));
186   EXPECT_EQ(outputExp2, uint32_t(1089));
187   EXPECT_EQ(errno, 0);
188 
189   // TODO(michaelrj): Get long double support working.
190 
191   // __uint128_t longDoubleOutputMantissa = 0;
192   // outputExp2 = 0;
193 
194   // errno = 0;
195   // __llvm_libc::internal::simpleDecimalConversion<long double>(
196   //     "123456789012345678900", &longDoubleOutputMantissa, &outputExp2);
197   // EXPECT_EQ(longDoubleOutputMantissa, __uint128_t(0x1AC53A7E04BCDA));
198   // EXPECT_EQ(outputExp2, uint32_t(1089));
199   // EXPECT_EQ(errno, 0);
200 }
201