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 uint32_t output_exp2 = 0; 179 180 // This number can't be evaluated by Eisel-Lemire since it's exactly 1024 away 181 // from both of its closest floating point approximations 182 // (12345678901234548736 and 12345678901234550784) 183 ASSERT_FALSE(__llvm_libc::internal::eisel_lemire<double>( 184 12345678901234549760u, 0, &double_output_mantissa, &output_exp2)); 185 186 ASSERT_FALSE(__llvm_libc::internal::eisel_lemire<float>( 187 20040229, 0, &float_output_mantissa, &output_exp2)); 188 } 189 190 TEST_F(LlvmLibcStrToFloatTest, SimpleDecimalConversion64BasicWholeNumbers) { 191 simple_decimal_conversion_test<double>("123456789012345678900", 192 0x1AC53A7E04BCDA, 1089); 193 simple_decimal_conversion_test<double>("123", 0x1EC00000000000, 1029); 194 simple_decimal_conversion_test<double>("12345678901234549760", 195 0x156A95319D63D8, 1086); 196 } 197 198 TEST_F(LlvmLibcStrToFloatTest, SimpleDecimalConversion64BasicDecimals) { 199 simple_decimal_conversion_test<double>("1.2345", 0x13c083126e978d, 1023); 200 simple_decimal_conversion_test<double>(".2345", 0x1e04189374bc6a, 1020); 201 simple_decimal_conversion_test<double>(".299792458", 0x132fccb4aca314, 1021); 202 } 203 204 TEST_F(LlvmLibcStrToFloatTest, SimpleDecimalConversion64BasicExponents) { 205 simple_decimal_conversion_test<double>("1e10", 0x12a05f20000000, 1056); 206 simple_decimal_conversion_test<double>("1e-10", 0x1b7cdfd9d7bdbb, 989); 207 simple_decimal_conversion_test<double>("1e300", 0x17e43c8800759c, 2019); 208 simple_decimal_conversion_test<double>("1e-300", 0x156e1fc2f8f359, 26); 209 } 210 211 TEST_F(LlvmLibcStrToFloatTest, SimpleDecimalConversion64BasicSubnormals) { 212 simple_decimal_conversion_test<double>("1e-320", 0x7e8, 0, ERANGE); 213 simple_decimal_conversion_test<double>("1e-308", 0x730d67819e8d2, 0, ERANGE); 214 simple_decimal_conversion_test<double>("2.9e-308", 0x14da6df5e4bcc8, 1); 215 } 216 217 TEST_F(LlvmLibcStrToFloatTest, SimpleDecimalConversion64SubnormalRounding) { 218 219 // Technically you can keep adding digits until you hit the truncation limit, 220 // but this is the shortest string that results in the maximum subnormal that 221 // I found. 222 simple_decimal_conversion_test<double>("2.225073858507201e-308", 223 0xfffffffffffff, 0, ERANGE); 224 225 // Same here, if you were to extend the max subnormal out for another 800 226 // digits, incrementing any one of those digits would create a normal number. 227 simple_decimal_conversion_test<double>("2.2250738585072012e-308", 228 0x10000000000000, 1); 229 } 230 231 TEST_F(LlvmLibcStrToFloatTest, SimpleDecimalConversion32SpecificFailures) { 232 simple_decimal_conversion_test<float>( 233 "1.4012984643248170709237295832899161312802619418765e-45", 0x1, 0, 234 ERANGE); 235 simple_decimal_conversion_test<float>( 236 "7." 237 "006492321624085354618647916449580656401309709382578858785341419448955413" 238 "42930300743319094181060791015625e-46", 239 0x0, 0, 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 264 #if defined(LONG_DOUBLE_IS_DOUBLE) 265 TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat64AsLongDouble) { 266 eisel_lemire_test<long double>(123, 0, 0x1EC00000000000, 1029); 267 } 268 #elif defined(SPECIAL_X86_LONG_DOUBLE) 269 TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat80Simple) { 270 eisel_lemire_test<long double>(123, 0, 0xf600000000000000, 16389); 271 eisel_lemire_test<long double>(12345678901234568192u, 0, 0xab54a98ceb1f0c00, 272 16446); 273 } 274 275 TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat80LongerMantissa) { 276 eisel_lemire_test<long double>((__uint128_t(0x1234567812345678) << 64) + 277 __uint128_t(0x1234567812345678), 278 0, 0x91a2b3c091a2b3c1, 16507); 279 eisel_lemire_test<long double>((__uint128_t(0x1234567812345678) << 64) + 280 __uint128_t(0x1234567812345678), 281 300, 0xd97757de56adb65c, 17503); 282 eisel_lemire_test<long double>((__uint128_t(0x1234567812345678) << 64) + 283 __uint128_t(0x1234567812345678), 284 -300, 0xc30feb9a7618457d, 15510); 285 } 286 287 // These tests check numbers at the edge of the DETAILED_POWERS_OF_TEN table. 288 // This doesn't reach very far into the range for long doubles, since it's sized 289 // for doubles and their 11 exponent bits, and not for long doubles and their 290 // 15 exponent bits. This is a known tradeoff, and was made because a proper 291 // long double table would be approximately 16 times longer (specifically the 292 // maximum exponent would need to be about 5000, leading to a 10,000 entry 293 // table). This would have significant memory and storage costs all the time to 294 // speed up a relatively uncommon path. 295 TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat80TableLimits) { 296 eisel_lemire_test<long double>(1, 347, 0xd13eb46469447567, 17535); 297 eisel_lemire_test<long double>(1, -348, 0xfa8fd5a0081c0288, 15226); 298 } 299 300 TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat80Fallback) { 301 uint32_t outputExp2 = 0; 302 __uint128_t quadOutputMantissa = 0; 303 304 // This number is halfway between two possible results, and the algorithm 305 // can't determine which is correct. 306 ASSERT_FALSE(__llvm_libc::internal::eisel_lemire<long double>( 307 12345678901234567890u, 1, &quadOutputMantissa, &outputExp2)); 308 309 // These numbers' exponents are out of range for the current powers of ten 310 // table. 311 ASSERT_FALSE(__llvm_libc::internal::eisel_lemire<long double>( 312 1, 1000, &quadOutputMantissa, &outputExp2)); 313 ASSERT_FALSE(__llvm_libc::internal::eisel_lemire<long double>( 314 1, -1000, &quadOutputMantissa, &outputExp2)); 315 } 316 #elif defined(__SIZEOF_INT128__) 317 TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat128Simple) { 318 eisel_lemire_test<long double>(123, 0, (__uint128_t(0x1ec0000000000) << 64), 319 16389); 320 eisel_lemire_test<long double>(12345678901234568192u, 0, 321 (__uint128_t(0x156a95319d63e) << 64) + 322 __uint128_t(0x1800000000000000), 323 16446); 324 } 325 326 TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat128LongerMantissa) { 327 eisel_lemire_test<long double>( 328 (__uint128_t(0x1234567812345678) << 64) + __uint128_t(0x1234567812345678), 329 0, (__uint128_t(0x1234567812345) << 64) + __uint128_t(0x6781234567812345), 330 16507); 331 eisel_lemire_test<long double>( 332 (__uint128_t(0x1234567812345678) << 64) + __uint128_t(0x1234567812345678), 333 300, 334 (__uint128_t(0x1b2eeafbcad5b) << 64) + __uint128_t(0x6cb8b4451dfcde19), 335 17503); 336 eisel_lemire_test<long double>( 337 (__uint128_t(0x1234567812345678) << 64) + __uint128_t(0x1234567812345678), 338 -300, 339 (__uint128_t(0x1861fd734ec30) << 64) + __uint128_t(0x8afa7189f0f7595f), 340 15510); 341 } 342 343 TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat128Fallback) { 344 uint32_t outputExp2 = 0; 345 __uint128_t quadOutputMantissa = 0; 346 347 ASSERT_FALSE(__llvm_libc::internal::eisel_lemire<long double>( 348 (__uint128_t(0x5ce0e9a56015fec5) << 64) + __uint128_t(0xaadfa328ae39b333), 349 1, &quadOutputMantissa, &outputExp2)); 350 } 351 #endif 352