xref: /aosp_15_r20/external/llvm-libc/test/src/math/smoke/LogbTest.h (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
1 //===-- Utility class to test logb[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/CPP/algorithm.h"
10 #include "src/__support/FPUtil/ManipulationFunctions.h"
11 #include "test/UnitTest/FEnvSafeTest.h"
12 #include "test/UnitTest/FPMatcher.h"
13 #include "test/UnitTest/Test.h"
14 
15 template <typename T>
16 class LogbTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
17 
18   DECLARE_SPECIAL_CONSTANTS(T)
19 
20   static constexpr StorageType HIDDEN_BIT =
21       StorageType(1) << LIBC_NAMESPACE::fputil::FPBits<T>::FRACTION_LEN;
22 
23 public:
24   typedef T (*LogbFunc)(T);
25 
testSpecialNumbers(LogbFunc func)26   void testSpecialNumbers(LogbFunc func) {
27     ASSERT_FP_EQ(aNaN, func(aNaN));
28     ASSERT_FP_EQ(inf, func(inf));
29     ASSERT_FP_EQ(inf, func(neg_inf));
30     ASSERT_FP_EQ(neg_inf, func(zero));
31     ASSERT_FP_EQ(neg_inf, func(neg_zero));
32   }
33 
testPowersOfTwo(LogbFunc func)34   void testPowersOfTwo(LogbFunc func) {
35     EXPECT_FP_EQ(T(0.0), func(T(1.0)));
36     EXPECT_FP_EQ(T(0.0), func(T(-1.0)));
37 
38     EXPECT_FP_EQ(T(1.0), func(T(2.0)));
39     EXPECT_FP_EQ(T(1.0), func(T(-2.0)));
40 
41     EXPECT_FP_EQ(T(2.0), func(T(4.0)));
42     EXPECT_FP_EQ(T(2.0), func(T(-4.0)));
43 
44     EXPECT_FP_EQ(T(3.0), func(T(8.0)));
45     EXPECT_FP_EQ(T(3.0), func(T(-8.0)));
46 
47     EXPECT_FP_EQ(T(4.0), func(T(16.0)));
48     EXPECT_FP_EQ(T(4.0), func(T(-16.0)));
49 
50     EXPECT_FP_EQ(T(5.0), func(T(32.0)));
51     EXPECT_FP_EQ(T(5.0), func(T(-32.0)));
52   }
53 
testSomeIntegers(LogbFunc func)54   void testSomeIntegers(LogbFunc func) {
55     EXPECT_FP_EQ(T(1.0), func(T(3.0)));
56     EXPECT_FP_EQ(T(1.0), func(T(-3.0)));
57 
58     EXPECT_FP_EQ(T(2.0), func(T(7.0)));
59     EXPECT_FP_EQ(T(2.0), func(T(-7.0)));
60 
61     EXPECT_FP_EQ(T(3.0), func(T(10.0)));
62     EXPECT_FP_EQ(T(3.0), func(T(-10.0)));
63 
64     EXPECT_FP_EQ(T(4.0), func(T(31.0)));
65     EXPECT_FP_EQ(T(4.0), func(T(-31.0)));
66 
67     EXPECT_FP_EQ(T(5.0), func(T(55.0)));
68     EXPECT_FP_EQ(T(5.0), func(T(-55.0)));
69   }
70 
testRange(LogbFunc func)71   void testRange(LogbFunc func) {
72     using StorageType = typename FPBits::StorageType;
73     constexpr int COUNT = 100'000;
74     constexpr StorageType STEP = LIBC_NAMESPACE::cpp::max(
75         static_cast<StorageType>(STORAGE_MAX / COUNT), StorageType(1));
76     StorageType v = 0;
77     for (int i = 0; i <= COUNT; ++i, v += STEP) {
78       FPBits x_bits(v);
79       if (x_bits.is_zero() || x_bits.is_inf_or_nan())
80         continue;
81 
82       T x = x_bits.get_val();
83 
84       int exponent;
85       LIBC_NAMESPACE::fputil::frexp(x, exponent);
86       ASSERT_FP_EQ(T(exponent), func(x) + T(1.0));
87     }
88   }
89 };
90 
91 #define LIST_LOGB_TESTS(T, func)                                               \
92   using LlvmLibcLogbTest = LogbTest<T>;                                        \
93   TEST_F(LlvmLibcLogbTest, SpecialNumbers) { testSpecialNumbers(&func); }      \
94   TEST_F(LlvmLibcLogbTest, PowersOfTwo) { testPowersOfTwo(&func); }            \
95   TEST_F(LlvmLibcLogbTest, SomeIntegers) { testSomeIntegers(&func); }          \
96   TEST_F(LlvmLibcLogbTest, InRange) { testRange(&func); }
97