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