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/FPUtil/ManipulationFunctions.h"
10 #include "utils/MPFRWrapper/MPFRUtils.h"
11 #include "utils/UnitTest/FPMatcher.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 LogbTest : public __llvm_libc::testing::Test {
19 
20   DECLARE_SPECIAL_CONSTANTS(T)
21 
22   static constexpr UIntType HIDDEN_BIT =
23       UIntType(1) << __llvm_libc::fputil::MantissaWidth<T>::VALUE;
24 
25 public:
26   typedef T (*LogbFunc)(T);
27 
testSpecialNumbers(LogbFunc func)28   void testSpecialNumbers(LogbFunc func) {
29     ASSERT_FP_EQ(aNaN, func(aNaN));
30     ASSERT_FP_EQ(inf, func(inf));
31     ASSERT_FP_EQ(inf, func(neg_inf));
32     ASSERT_FP_EQ(neg_inf, func(0.0));
33     ASSERT_FP_EQ(neg_inf, func(-0.0));
34   }
35 
testPowersOfTwo(LogbFunc func)36   void testPowersOfTwo(LogbFunc func) {
37     EXPECT_FP_EQ(T(0.0), func(T(1.0)));
38     EXPECT_FP_EQ(T(0.0), func(T(-1.0)));
39 
40     EXPECT_FP_EQ(T(1.0), func(T(2.0)));
41     EXPECT_FP_EQ(T(1.0), func(T(-2.0)));
42 
43     EXPECT_FP_EQ(T(2.0), func(T(4.0)));
44     EXPECT_FP_EQ(T(2.0), func(T(-4.0)));
45 
46     EXPECT_FP_EQ(T(3.0), func(T(8.0)));
47     EXPECT_FP_EQ(T(3.0), func(T(-8.0)));
48 
49     EXPECT_FP_EQ(T(4.0), func(T(16.0)));
50     EXPECT_FP_EQ(T(4.0), func(T(-16.0)));
51 
52     EXPECT_FP_EQ(T(5.0), func(T(32.0)));
53     EXPECT_FP_EQ(T(5.0), func(T(-32.0)));
54   }
55 
testSomeIntegers(LogbFunc func)56   void testSomeIntegers(LogbFunc func) {
57     EXPECT_FP_EQ(T(1.0), func(T(3.0)));
58     EXPECT_FP_EQ(T(1.0), func(T(-3.0)));
59 
60     EXPECT_FP_EQ(T(2.0), func(T(7.0)));
61     EXPECT_FP_EQ(T(2.0), func(T(-7.0)));
62 
63     EXPECT_FP_EQ(T(3.0), func(T(10.0)));
64     EXPECT_FP_EQ(T(3.0), func(T(-10.0)));
65 
66     EXPECT_FP_EQ(T(4.0), func(T(31.0)));
67     EXPECT_FP_EQ(T(4.0), func(T(-31.0)));
68 
69     EXPECT_FP_EQ(T(5.0), func(T(55.0)));
70     EXPECT_FP_EQ(T(5.0), func(T(-55.0)));
71   }
72 
testRange(LogbFunc func)73   void testRange(LogbFunc func) {
74     using UIntType = typename FPBits::UIntType;
75     constexpr UIntType COUNT = 10000000;
76     constexpr UIntType STEP = UIntType(-1) / COUNT;
77     for (UIntType i = 0, v = 0; i <= COUNT; ++i, v += STEP) {
78       T x = static_cast<T>(FPBits(v));
79       if (isnan(x) || isinf(x) || x == 0.0l)
80         continue;
81 
82       int exponent;
83       __llvm_libc::fputil::frexp(x, exponent);
84       ASSERT_FP_EQ(T(exponent), func(x) + T(1.0));
85     }
86   }
87 };
88 
89 #define LIST_LOGB_TESTS(T, func)                                               \
90   using LlvmLibcLogbTest = LogbTest<T>;                                        \
91   TEST_F(LlvmLibcLogbTest, SpecialNumbers) { testSpecialNumbers(&func); }      \
92   TEST_F(LlvmLibcLogbTest, PowersOfTwo) { testPowersOfTwo(&func); }            \
93   TEST_F(LlvmLibcLogbTest, SomeIntegers) { testSomeIntegers(&func); }          \
94   TEST_F(LlvmLibcLogbTest, InRange) { testRange(&func); }
95