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