xref: /llvm-project/libc/test/src/__support/FPUtil/dyadic_float_test.cpp (revision f6b2a222beed734df1d91bd5c165a5233c19fddb)
1 //===-- Unittests for the DyadicFloat class -------------------------------===//
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/dyadic_float.h"
10 #include "src/__support/big_int.h"
11 #include "src/__support/macros/properties/types.h"
12 #include "test/UnitTest/FPMatcher.h"
13 #include "test/UnitTest/Test.h"
14 #include "utils/MPFRWrapper/MPFRUtils.h"
15 
16 using Float128 = LIBC_NAMESPACE::fputil::DyadicFloat<128>;
17 using Float192 = LIBC_NAMESPACE::fputil::DyadicFloat<192>;
18 using Float256 = LIBC_NAMESPACE::fputil::DyadicFloat<256>;
19 using LIBC_NAMESPACE::Sign;
20 
21 TEST(LlvmLibcDyadicFloatTest, BasicConversions) {
22   Float128 x(Sign::POS, /*exponent*/ 0,
23              /*mantissa*/ Float128::MantissaType(1));
24   ASSERT_FP_EQ(1.0f, float(x));
25   ASSERT_FP_EQ(1.0, double(x));
26 
27   Float128 y(0x1.0p-53);
28   ASSERT_FP_EQ(0x1.0p-53f, float(y));
29   ASSERT_FP_EQ(0x1.0p-53, double(y));
30 
31   Float128 z = quick_add(x, y);
32 
33   EXPECT_FP_EQ_ALL_ROUNDING(float(x) + float(y), float(z));
34   EXPECT_FP_EQ_ALL_ROUNDING(double(x) + double(y), double(z));
35 }
36 
37 TEST(LlvmLibcDyadicFloatTest, QuickAdd) {
38   Float192 x(Sign::POS, /*exponent*/ 0,
39              /*mantissa*/ Float192::MantissaType(0x123456));
40   ASSERT_FP_EQ(0x1.23456p20, double(x));
41 
42   Float192 y(0x1.abcdefp-20);
43   ASSERT_FP_EQ(0x1.abcdefp-20, double(y));
44 
45   Float192 z = quick_add(x, y);
46   EXPECT_FP_EQ_ALL_ROUNDING(double(x) + double(y), double(z));
47 }
48 
49 TEST(LlvmLibcDyadicFloatTest, QuickMul) {
50   Float256 x(Sign::POS, /*exponent*/ 0,
51              /*mantissa*/ Float256::MantissaType(0x123456));
52   ASSERT_FP_EQ(0x1.23456p20, double(x));
53 
54   Float256 y(0x1.abcdefp-25);
55   ASSERT_FP_EQ(0x1.abcdefp-25, double(y));
56 
57   Float256 z = quick_mul(x, y);
58   EXPECT_FP_EQ_ALL_ROUNDING(double(x) * double(y), double(z));
59 }
60 
61 #define TEST_EDGE_RANGES(Name, Type)                                           \
62   TEST(LlvmLibcDyadicFloatTest, EdgeRanges##Name) {                            \
63     using Bits = LIBC_NAMESPACE::fputil::FPBits<Type>;                         \
64     using DFType = LIBC_NAMESPACE::fputil::DyadicFloat<Bits::STORAGE_LEN>;     \
65     Type max_normal = Bits::max_normal().get_val();                            \
66     Type min_normal = Bits::min_normal().get_val();                            \
67     Type min_subnormal = Bits::min_subnormal().get_val();                      \
68     Type two(2);                                                               \
69                                                                                \
70     DFType x(min_normal);                                                      \
71     EXPECT_FP_EQ_ALL_ROUNDING(min_normal, static_cast<Type>(x));               \
72     --x.exponent;                                                              \
73     EXPECT_FP_EQ(min_normal / two, static_cast<Type>(x));                      \
74                                                                                \
75     DFType y(two *min_normal - min_subnormal);                                 \
76     --y.exponent;                                                              \
77     EXPECT_FP_EQ(min_normal, static_cast<Type>(y));                            \
78                                                                                \
79     DFType z(min_subnormal);                                                   \
80     EXPECT_FP_EQ_ALL_ROUNDING(min_subnormal, static_cast<Type>(z));            \
81     --z.exponent;                                                              \
82     EXPECT_FP_EQ(Bits::zero().get_val(), static_cast<Type>(z));                \
83                                                                                \
84     DFType t(max_normal);                                                      \
85     EXPECT_FP_EQ_ALL_ROUNDING(max_normal, static_cast<Type>(t));               \
86     ++t.exponent;                                                              \
87     EXPECT_FP_EQ(Bits::inf().get_val(), static_cast<Type>(t));                 \
88   }                                                                            \
89   static_assert(true, "Require semicolon.")
90 
91 TEST_EDGE_RANGES(Float, float);
92 TEST_EDGE_RANGES(Double, double);
93 TEST_EDGE_RANGES(LongDouble, long double);
94 #ifdef LIBC_TYPES_HAS_FLOAT16
95 TEST_EDGE_RANGES(Float16, float16);
96 #endif
97