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