1 //===-- Utility class to test frexp[f|l] ------------------------*- C++ -*-===// 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/BasicOperations.h" 10 #include "test/UnitTest/FEnvSafeTest.h" 11 #include "test/UnitTest/FPMatcher.h" 12 #include "test/UnitTest/Test.h" 13 #include "utils/MPFRWrapper/MPFRUtils.h" 14 15 #include "hdr/math_macros.h" 16 17 namespace mpfr = LIBC_NAMESPACE::testing::mpfr; 18 19 template <typename T> 20 class FrexpTest : public LIBC_NAMESPACE::testing::FEnvSafeTest { 21 22 DECLARE_SPECIAL_CONSTANTS(T) 23 24 static constexpr StorageType HIDDEN_BIT = 25 StorageType(1) << LIBC_NAMESPACE::fputil::FPBits<T>::FRACTION_LEN; 26 27 public: 28 typedef T (*FrexpFunc)(T, int *); 29 testSpecialNumbers(FrexpFunc func)30 void testSpecialNumbers(FrexpFunc func) { 31 int exponent; 32 ASSERT_FP_EQ(aNaN, func(aNaN, &exponent)); 33 ASSERT_FP_EQ(inf, func(inf, &exponent)); 34 ASSERT_FP_EQ(neg_inf, func(neg_inf, &exponent)); 35 36 ASSERT_FP_EQ(0.0, func(0.0, &exponent)); 37 ASSERT_EQ(exponent, 0); 38 39 ASSERT_FP_EQ(-0.0, func(-0.0, &exponent)); 40 ASSERT_EQ(exponent, 0); 41 } 42 testPowersOfTwo(FrexpFunc func)43 void testPowersOfTwo(FrexpFunc func) { 44 int exponent; 45 46 EXPECT_FP_EQ(T(0.5), func(T(1.0), &exponent)); 47 EXPECT_EQ(exponent, 1); 48 EXPECT_FP_EQ(T(-0.5), func(T(-1.0), &exponent)); 49 EXPECT_EQ(exponent, 1); 50 51 EXPECT_FP_EQ(T(0.5), func(T(2.0), &exponent)); 52 EXPECT_EQ(exponent, 2); 53 EXPECT_FP_EQ(T(-0.5), func(T(-2.0), &exponent)); 54 EXPECT_EQ(exponent, 2); 55 56 EXPECT_FP_EQ(T(0.5), func(T(4.0), &exponent)); 57 EXPECT_EQ(exponent, 3); 58 EXPECT_FP_EQ(T(-0.5), func(T(-4.0), &exponent)); 59 EXPECT_EQ(exponent, 3); 60 61 EXPECT_FP_EQ(T(0.5), func(T(8.0), &exponent)); 62 EXPECT_EQ(exponent, 4); 63 EXPECT_FP_EQ(T(-0.5), func(T(-8.0), &exponent)); 64 EXPECT_EQ(exponent, 4); 65 66 EXPECT_FP_EQ(T(0.5), func(T(16.0), &exponent)); 67 EXPECT_EQ(exponent, 5); 68 EXPECT_FP_EQ(T(-0.5), func(T(-16.0), &exponent)); 69 EXPECT_EQ(exponent, 5); 70 71 EXPECT_FP_EQ(T(0.5), func(T(32.0), &exponent)); 72 EXPECT_EQ(exponent, 6); 73 EXPECT_FP_EQ(T(-0.5), func(T(-32.0), &exponent)); 74 EXPECT_EQ(exponent, 6); 75 } 76 testSomeIntegers(FrexpFunc func)77 void testSomeIntegers(FrexpFunc func) { 78 int exponent; 79 80 EXPECT_FP_EQ(T(0.75), func(T(24.0), &exponent)); 81 EXPECT_EQ(exponent, 5); 82 EXPECT_FP_EQ(T(-0.75), func(T(-24.0), &exponent)); 83 EXPECT_EQ(exponent, 5); 84 85 EXPECT_FP_EQ(T(0.625), func(T(40.0), &exponent)); 86 EXPECT_EQ(exponent, 6); 87 EXPECT_FP_EQ(T(-0.625), func(T(-40.0), &exponent)); 88 EXPECT_EQ(exponent, 6); 89 90 EXPECT_FP_EQ(T(0.78125), func(T(800.0), &exponent)); 91 EXPECT_EQ(exponent, 10); 92 EXPECT_FP_EQ(T(-0.78125), func(T(-800.0), &exponent)); 93 EXPECT_EQ(exponent, 10); 94 } 95 testRange(FrexpFunc func)96 void testRange(FrexpFunc func) { 97 using StorageType = typename FPBits::StorageType; 98 constexpr StorageType COUNT = 100'000; 99 constexpr StorageType STEP = STORAGE_MAX / COUNT; 100 for (StorageType i = 0, v = 0; i <= COUNT; ++i, v += STEP) { 101 T x = FPBits(v).get_val(); 102 if (FPBits(v).is_nan() || FPBits(v).is_inf() || x == 0.0l) 103 continue; 104 105 mpfr::BinaryOutput<T> result; 106 result.f = func(x, &result.i); 107 108 ASSERT_TRUE(LIBC_NAMESPACE::fputil::abs(result.f) < 1.0); 109 ASSERT_TRUE(LIBC_NAMESPACE::fputil::abs(result.f) >= 0.5); 110 ASSERT_MPFR_MATCH(mpfr::Operation::Frexp, x, result, 0.0); 111 } 112 } 113 }; 114 115 #define LIST_FREXP_TESTS(T, func) \ 116 using LlvmLibcFrexpTest = FrexpTest<T>; \ 117 TEST_F(LlvmLibcFrexpTest, SpecialNumbers) { testSpecialNumbers(&func); } \ 118 TEST_F(LlvmLibcFrexpTest, PowersOfTwo) { testPowersOfTwo(&func); } \ 119 TEST_F(LlvmLibcFrexpTest, SomeIntegers) { testSomeIntegers(&func); } \ 120 TEST_F(LlvmLibcFrexpTest, InRange) { testRange(&func); } 121