xref: /llvm-project/libc/test/src/__support/str_to_long_double_test.cpp (revision 7302c8dbe71b7c03b73a35a21fa4b415fa1f4505)
1 //===-- Unittests for str_to_float<long double> ---------------------------===//
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/macros/config.h"
10 #include "str_to_fp_test.h"
11 
12 #include "src/__support/integer_literals.h"
13 
14 namespace LIBC_NAMESPACE_DECL {
15 
16 using LlvmLibcStrToLongDblTest = LlvmLibcStrToFloatTest<long double>;
17 using LIBC_NAMESPACE::operator""_u128;
18 
19 #if defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
20 
21 TEST_F(LlvmLibcStrToLongDblTest, EiselLemireFloat64AsLongDouble) {
22   eisel_lemire_test(123, 0, 0x1EC00000000000, 1029);
23 }
24 
25 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
26 
27 TEST_F(LlvmLibcStrToLongDblTest, EiselLemireFloat80Simple) {
28   eisel_lemire_test(123, 0, 0xf600000000000000, 16389);
29   eisel_lemire_test(12345678901234568192u, 0, 0xab54a98ceb1f0c00, 16446);
30 }
31 
32 TEST_F(LlvmLibcStrToLongDblTest, EiselLemireFloat80LongerMantissa) {
33 #if __SIZEOF_LONG_DOUBLE__ == 16
34   eisel_lemire_test(0x12345678'12345678'12345678'12345678_u128, 0,
35                     0x91a2b3c091a2b3c1, 16507);
36   eisel_lemire_test(0x12345678'12345678'12345678'12345678_u128, 300,
37                     0xd97757de56adb65c, 17503);
38   eisel_lemire_test(0x12345678'12345678'12345678'12345678_u128, -300,
39                     0xc30feb9a7618457d, 15510);
40 #elif __SIZEOF_LONG_DOUBLE__ == 12
41   eisel_lemire_test(0x12345678'12345678'12345678_u96, 0, 0x91a2b3c091a2b3c1,
42                     16475);
43   eisel_lemire_test(0x12345678'12345678'12345678_u96, 300, 0xd97757de56adb65c,
44                     17471);
45   eisel_lemire_test(0x12345678'12345678'12345678_u96, -300, 0xc30feb9a7618457d,
46                     15478);
47 #else
48 #error "unhandled long double type"
49 #endif
50 }
51 
52 // These tests check numbers at the edge of the DETAILED_POWERS_OF_TEN table.
53 // This doesn't reach very far into the range for long doubles, since it's sized
54 // for doubles and their 11 exponent bits, and not for long doubles and their
55 // 15 exponent bits. This is a known tradeoff, and was made because a proper
56 // long double table would be approximately 16 times longer (specifically the
57 // maximum exponent would need to be about 5000, leading to a 10,000 entry
58 // table). This would have significant memory and storage costs all the time to
59 // speed up a relatively uncommon path.
60 TEST_F(LlvmLibcStrToLongDblTest, EiselLemireFloat80TableLimits) {
61   eisel_lemire_test(1, 347, 0xd13eb46469447567, 17535);
62   eisel_lemire_test(1, -348, 0xfa8fd5a0081c0288, 15226);
63 }
64 
65 TEST_F(LlvmLibcStrToLongDblTest, EiselLemireFloat80Fallback) {
66   // This number is halfway between two possible results, and the algorithm
67   // can't determine which is correct.
68   ASSERT_FALSE(internal::eisel_lemire<long double>({12345678901234567890u, 1})
69                    .has_value());
70 
71   // These numbers' exponents are out of range for the current powers of ten
72   // table.
73   ASSERT_FALSE(internal::eisel_lemire<long double>({1, 1000}).has_value());
74   ASSERT_FALSE(internal::eisel_lemire<long double>({1, -1000}).has_value());
75 }
76 
77 TEST_F(LlvmLibcStrToLongDblTest, ClingerFastPathFloat80Simple) {
78   clinger_fast_path_test(123, 0, 0xf600000000000000, 16389);
79   clinger_fast_path_test(1234567, 1, 0xbc61460000000000, 16406);
80   clinger_fast_path_test(12345, -5, 0xfcd35a858793dd98, 16379);
81 }
82 
83 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
84 
85 TEST_F(LlvmLibcStrToLongDblTest, EiselLemireFloat128Simple) {
86   eisel_lemire_test(123, 0, 0x1ec00'00000000'00000000'00000000_u128, 16389);
87   eisel_lemire_test(12345678901234568192u, 0,
88                     0x156a9'5319d63e'18000000'00000000_u128, 16446);
89 }
90 
91 TEST_F(LlvmLibcStrToLongDblTest, EiselLemireFloat128LongerMantissa) {
92   eisel_lemire_test(0x12345678'12345678'12345678'12345678_u128, 0,
93                     0x12345'67812345'67812345'67812345_u128, 16507);
94   eisel_lemire_test(0x12345678'12345678'12345678'12345678_u128, 300,
95                     0x1b2ee'afbcad5b'6cb8b445'1dfcde19_u128, 17503);
96   eisel_lemire_test(0x12345678'12345678'12345678'12345678_u128, -300,
97                     0x1861f'd734ec30'8afa7189'f0f7595f_u128, 15510);
98 }
99 
100 TEST_F(LlvmLibcStrToLongDblTest, EiselLemireFloat128Fallback) {
101   ASSERT_FALSE(internal::eisel_lemire<long double>(
102                    {0x5ce0e9a5'6015fec5'aadfa328'ae39b333_u128, 1})
103                    .has_value());
104 }
105 
106 TEST_F(LlvmLibcStrToLongDblTest, ClingerFastPathFloat128Simple) {
107   clinger_fast_path_test(123, 0, 0x1ec00'00000000'00000000'00000000_u128,
108                          16389);
109   clinger_fast_path_test(1234567, 1, 0x178c2'8c000000'00000000'00000000_u128,
110                          16406);
111   clinger_fast_path_test(12345, -5, 0x1f9a6'b50b0f27'bb2fec56'd5cfaace_u128,
112                          16379);
113 }
114 
115 #else
116 #error "Unknown long double type"
117 #endif
118 
119 } // namespace LIBC_NAMESPACE_DECL
120