1 //===-- Unittests for the DyadicFloat class -------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
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
;
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
));
27 Float128
y(0x1.0p
-53);
28 ASSERT_FP_EQ(0x1.0p
-53f
, float(y
));
29 ASSERT_FP_EQ(0x1.0p
-53, double(y
));
31 Float128 z
= quick_add(x
, y
);
33 EXPECT_FP_EQ_ALL_ROUNDING(float(x
) + float(y
), float(z
));
34 EXPECT_FP_EQ_ALL_ROUNDING(double(x
) + double(y
), double(z
));
37 TEST(LlvmLibcDyadicFloatTest
, QuickAdd
) {
38 Float192
x(Sign::POS
, /*exponent*/ 0,
39 /*mantissa*/ Float192::MantissaType(0x123456));
40 ASSERT_FP_EQ(0x1.23456p20
, double(x
));
42 Float192
y(0x1.abcdefp
-20);
43 ASSERT_FP_EQ(0x1.abcdefp
-20, double(y
));
45 Float192 z
= quick_add(x
, y
);
46 EXPECT_FP_EQ_ALL_ROUNDING(double(x
) + double(y
), double(z
));
49 TEST(LlvmLibcDyadicFloatTest
, QuickMul
) {
50 Float256
x(Sign::POS
, /*exponent*/ 0,
51 /*mantissa*/ Float256::MantissaType(0x123456));
52 ASSERT_FP_EQ(0x1.23456p20
, double(x
));
54 Float256
y(0x1.abcdefp
-25);
55 ASSERT_FP_EQ(0x1.abcdefp
-25, double(y
));
57 Float256 z
= quick_mul(x
, y
);
58 EXPECT_FP_EQ_ALL_ROUNDING(double(x
) * double(y
), double(z
));
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(); \
70 DFType x(min_normal); \
71 EXPECT_FP_EQ_ALL_ROUNDING(min_normal, static_cast<Type>(x)); \
73 EXPECT_FP_EQ(min_normal / two, static_cast<Type>(x)); \
75 DFType y(two *min_normal - min_subnormal); \
77 EXPECT_FP_EQ(min_normal, static_cast<Type>(y)); \
79 DFType z(min_subnormal); \
80 EXPECT_FP_EQ_ALL_ROUNDING(min_subnormal, static_cast<Type>(z)); \
82 EXPECT_FP_EQ(Bits::zero().get_val(), static_cast<Type>(z)); \
84 DFType t(max_normal); \
85 EXPECT_FP_EQ_ALL_ROUNDING(max_normal, static_cast<Type>(t)); \
87 EXPECT_FP_EQ(Bits::inf().get_val(), static_cast<Type>(t)); \
89 static_assert(true, "Require semicolon.")
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
);