| //===-- Unittests for the DyadicFloat class -------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "src/__support/FPUtil/dyadic_float.h" |
| #include "src/__support/big_int.h" |
| #include "test/UnitTest/FPMatcher.h" |
| #include "test/UnitTest/Test.h" |
| #include "utils/MPFRWrapper/MPFRUtils.h" |
| |
| using Float128 = LIBC_NAMESPACE::fputil::DyadicFloat<128>; |
| using Float192 = LIBC_NAMESPACE::fputil::DyadicFloat<192>; |
| using Float256 = LIBC_NAMESPACE::fputil::DyadicFloat<256>; |
| |
| TEST(LlvmLibcDyadicFloatTest, BasicConversions) { |
| Float128 x(Sign::POS, /*exponent*/ 0, |
| /*mantissa*/ Float128::MantissaType(1)); |
| ASSERT_FP_EQ(1.0f, float(x)); |
| ASSERT_FP_EQ(1.0, double(x)); |
| |
| Float128 y(0x1.0p-53); |
| ASSERT_FP_EQ(0x1.0p-53f, float(y)); |
| ASSERT_FP_EQ(0x1.0p-53, double(y)); |
| |
| Float128 z = quick_add(x, y); |
| |
| EXPECT_FP_EQ_ALL_ROUNDING(float(x) + float(y), float(z)); |
| EXPECT_FP_EQ_ALL_ROUNDING(double(x) + double(y), double(z)); |
| } |
| |
| TEST(LlvmLibcDyadicFloatTest, QuickAdd) { |
| Float192 x(Sign::POS, /*exponent*/ 0, |
| /*mantissa*/ Float192::MantissaType(0x123456)); |
| ASSERT_FP_EQ(0x1.23456p20, double(x)); |
| |
| Float192 y(0x1.abcdefp-20); |
| ASSERT_FP_EQ(0x1.abcdefp-20, double(y)); |
| |
| Float192 z = quick_add(x, y); |
| EXPECT_FP_EQ_ALL_ROUNDING(double(x) + double(y), double(z)); |
| } |
| |
| TEST(LlvmLibcDyadicFloatTest, QuickMul) { |
| Float256 x(Sign::POS, /*exponent*/ 0, |
| /*mantissa*/ Float256::MantissaType(0x123456)); |
| ASSERT_FP_EQ(0x1.23456p20, double(x)); |
| |
| Float256 y(0x1.abcdefp-25); |
| ASSERT_FP_EQ(0x1.abcdefp-25, double(y)); |
| |
| Float256 z = quick_mul(x, y); |
| EXPECT_FP_EQ_ALL_ROUNDING(double(x) * double(y), double(z)); |
| } |
| |
| #define TEST_EDGE_RANGES(Name, Type) \ |
| TEST(LlvmLibcDyadicFloatTest, EdgeRanges##Name) { \ |
| using Bits = LIBC_NAMESPACE::fputil::FPBits<Type>; \ |
| using DFType = LIBC_NAMESPACE::fputil::DyadicFloat<Bits::STORAGE_LEN>; \ |
| Type max_normal = Bits::max_normal().get_val(); \ |
| Type min_normal = Bits::min_normal().get_val(); \ |
| Type min_subnormal = Bits::min_subnormal().get_val(); \ |
| Type two(2); \ |
| \ |
| DFType x(min_normal); \ |
| EXPECT_FP_EQ_ALL_ROUNDING(min_normal, static_cast<Type>(x)); \ |
| --x.exponent; \ |
| EXPECT_FP_EQ(min_normal / two, static_cast<Type>(x)); \ |
| \ |
| DFType y(two *min_normal - min_subnormal); \ |
| --y.exponent; \ |
| EXPECT_FP_EQ(min_normal, static_cast<Type>(y)); \ |
| \ |
| DFType z(min_subnormal); \ |
| EXPECT_FP_EQ_ALL_ROUNDING(min_subnormal, static_cast<Type>(z)); \ |
| --z.exponent; \ |
| EXPECT_FP_EQ(Bits::zero().get_val(), static_cast<Type>(z)); \ |
| \ |
| DFType t(max_normal); \ |
| EXPECT_FP_EQ_ALL_ROUNDING(max_normal, static_cast<Type>(t)); \ |
| ++t.exponent; \ |
| EXPECT_FP_EQ(Bits::inf().get_val(), static_cast<Type>(t)); \ |
| } \ |
| static_assert(true, "Require semicolon.") |
| |
| TEST_EDGE_RANGES(Float, float); |
| TEST_EDGE_RANGES(Double, double); |
| TEST_EDGE_RANGES(LongDouble, long double); |