1 //===-- Unittests for exp2f -----------------------------------------------===//
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/FPBits.h"
10 #include "src/math/exp2f.h"
11 #include "utils/MPFRWrapper/MPFRUtils.h"
12 #include "utils/UnitTest/FPMatcher.h"
13 #include "utils/UnitTest/Test.h"
14 #include <math.h>
15 
16 #include <errno.h>
17 #include <stdint.h>
18 
19 namespace mpfr = __llvm_libc::testing::mpfr;
20 
21 DECLARE_SPECIAL_CONSTANTS(float)
22 
23 TEST(LlvmLibcExp2fTest, SpecialNumbers) {
24   errno = 0;
25 
26   EXPECT_FP_EQ(aNaN, __llvm_libc::exp2f(aNaN));
27   EXPECT_MATH_ERRNO(0);
28 
29   EXPECT_FP_EQ(inf, __llvm_libc::exp2f(inf));
30   EXPECT_MATH_ERRNO(0);
31 
32   EXPECT_FP_EQ(0.0f, __llvm_libc::exp2f(neg_inf));
33   EXPECT_MATH_ERRNO(0);
34 
35   EXPECT_FP_EQ(1.0f, __llvm_libc::exp2f(0.0f));
36   EXPECT_MATH_ERRNO(0);
37 
38   EXPECT_FP_EQ(1.0f, __llvm_libc::exp2f(-0.0f));
39   EXPECT_MATH_ERRNO(0);
40 }
41 
42 TEST(LlvmLibcExp2fTest, Overflow) {
43   errno = 0;
44   EXPECT_FP_EQ(inf, __llvm_libc::exp2f(float(FPBits(0x7f7fffffU))));
45   EXPECT_MATH_ERRNO(ERANGE);
46 
47   EXPECT_FP_EQ(inf, __llvm_libc::exp2f(float(FPBits(0x43000000U))));
48   EXPECT_MATH_ERRNO(ERANGE);
49 
50   EXPECT_FP_EQ(inf, __llvm_libc::exp2f(float(FPBits(0x43000001U))));
51   EXPECT_MATH_ERRNO(ERANGE);
52 }
53 
54 // Test with inputs which are the borders of underflow/overflow but still
55 // produce valid results without setting errno.
56 TEST(LlvmLibcExp2fTest, Borderline) {
57   float x;
58 
59   errno = 0;
60   x = float(FPBits(0x42fa0001U));
61   EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp2, x,
62                                  __llvm_libc::exp2f(x), 0.5);
63   EXPECT_MATH_ERRNO(0);
64 
65   x = float(FPBits(0x42ffffffU));
66   EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp2, x,
67                                  __llvm_libc::exp2f(x), 0.5);
68   EXPECT_MATH_ERRNO(0);
69 
70   x = float(FPBits(0xc2fa0001U));
71   EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp2, x,
72                                  __llvm_libc::exp2f(x), 0.5);
73   EXPECT_MATH_ERRNO(0);
74 
75   x = float(FPBits(0xc2fc0000U));
76   EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp2, x,
77                                  __llvm_libc::exp2f(x), 0.5);
78   EXPECT_MATH_ERRNO(0);
79 
80   x = float(FPBits(0xc2fc0001U));
81   EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp2, x,
82                                  __llvm_libc::exp2f(x), 0.5);
83   EXPECT_MATH_ERRNO(0);
84 
85   x = float(FPBits(0xc3150000U));
86   EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp2, x,
87                                  __llvm_libc::exp2f(x), 0.5);
88   EXPECT_MATH_ERRNO(0);
89 
90   x = float(FPBits(0x3b42'9d37U));
91   EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp2, x,
92                                  __llvm_libc::exp2f(x), 0.5);
93   EXPECT_MATH_ERRNO(0);
94 
95   x = float(FPBits(0xbcf3'a937U));
96   EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp2, x,
97                                  __llvm_libc::exp2f(x), 0.5);
98   EXPECT_MATH_ERRNO(0);
99 }
100 
101 TEST(LlvmLibcExp2fTest, Underflow) {
102   errno = 0;
103   EXPECT_FP_EQ(0.0f, __llvm_libc::exp2f(float(FPBits(0xff7fffffU))));
104   EXPECT_MATH_ERRNO(ERANGE);
105 
106   float x = float(FPBits(0xc3158000U));
107   EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp2, x,
108                                  __llvm_libc::exp2f(x), 0.5);
109   EXPECT_MATH_ERRNO(0);
110 
111   x = float(FPBits(0xc3160000U));
112   EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp2, x,
113                                  __llvm_libc::exp2f(x), 0.5);
114   EXPECT_MATH_ERRNO(ERANGE);
115 
116   x = float(FPBits(0xc3165432U));
117   EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp2, x,
118                                  __llvm_libc::exp2f(x), 0.5);
119   EXPECT_MATH_ERRNO(ERANGE);
120 }
121 
122 TEST(LlvmLibcExp2fTest, InFloatRange) {
123   constexpr uint32_t COUNT = 1000000;
124   constexpr uint32_t STEP = UINT32_MAX / COUNT;
125   for (uint32_t i = 0, v = 0; i <= COUNT; ++i, v += STEP) {
126     float x = float(FPBits(v));
127     if (isnan(x) || isinf(x))
128       continue;
129     errno = 0;
130     float result = __llvm_libc::exp2f(x);
131 
132     // If the computation resulted in an error or did not produce valid result
133     // in the single-precision floating point range, then ignore comparing with
134     // MPFR result as MPFR can still produce valid results because of its
135     // wider precision.
136     if (isnan(result) || isinf(result) || errno != 0)
137       continue;
138     ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp2, x,
139                                    __llvm_libc::exp2f(x), 0.5);
140   }
141 }
142