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