xref: /aosp_15_r20/external/llvm-libc/test/src/math/FrexpTest.h (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
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