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