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(LlvmLibcExpfTest, 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(LlvmLibcExpfTest, Borderline) {
57   float x;
58 
59   errno = 0;
60   x = float(FPBits(0x42fa0001U));
61   EXPECT_MPFR_MATCH(mpfr::Operation::Exp2, x, __llvm_libc::exp2f(x), 1.0);
62   EXPECT_MATH_ERRNO(0);
63 
64   x = float(FPBits(0x42ffffffU));
65   EXPECT_MPFR_MATCH(mpfr::Operation::Exp2, x, __llvm_libc::exp2f(x), 1.0);
66   EXPECT_MATH_ERRNO(0);
67 
68   x = float(FPBits(0xc2fa0001U));
69   EXPECT_MPFR_MATCH(mpfr::Operation::Exp2, x, __llvm_libc::exp2f(x), 1.0);
70   EXPECT_MATH_ERRNO(0);
71 
72   x = float(FPBits(0xc2fc0000U));
73   EXPECT_MPFR_MATCH(mpfr::Operation::Exp2, x, __llvm_libc::exp2f(x), 1.0);
74   EXPECT_MATH_ERRNO(0);
75 
76   x = float(FPBits(0xc2fc0001U));
77   EXPECT_MPFR_MATCH(mpfr::Operation::Exp2, x, __llvm_libc::exp2f(x), 1.0);
78   EXPECT_MATH_ERRNO(0);
79 
80   x = float(FPBits(0xc3150000U));
81   EXPECT_MPFR_MATCH(mpfr::Operation::Exp2, x, __llvm_libc::exp2f(x), 1.0);
82   EXPECT_MATH_ERRNO(0);
83 }
84 
85 TEST(LlvmLibcExpfTest, Underflow) {
86   errno = 0;
87   EXPECT_FP_EQ(0.0f, __llvm_libc::exp2f(float(FPBits(0xff7fffffU))));
88   EXPECT_MATH_ERRNO(ERANGE);
89 
90   float x = float(FPBits(0xc3158000U));
91   EXPECT_MPFR_MATCH(mpfr::Operation::Exp2, x, __llvm_libc::exp2f(x), 1.0);
92   EXPECT_MATH_ERRNO(ERANGE);
93 
94   x = float(FPBits(0xc3165432U));
95   EXPECT_MPFR_MATCH(mpfr::Operation::Exp2, x, __llvm_libc::exp2f(x), 1.0);
96   EXPECT_MATH_ERRNO(ERANGE);
97 }
98 
99 TEST(LlvmLibcexp2fTest, InFloatRange) {
100   constexpr uint32_t COUNT = 1000000;
101   constexpr uint32_t STEP = UINT32_MAX / COUNT;
102   for (uint32_t i = 0, v = 0; i <= COUNT; ++i, v += STEP) {
103     float x = float(FPBits(v));
104     if (isnan(x) || isinf(x))
105       continue;
106     errno = 0;
107     float result = __llvm_libc::exp2f(x);
108 
109     // If the computation resulted in an error or did not produce valid result
110     // in the single-precision floating point range, then ignore comparing with
111     // MPFR result as MPFR can still produce valid results because of its
112     // wider precision.
113     if (isnan(result) || isinf(result) || errno != 0)
114       continue;
115     ASSERT_MPFR_MATCH(mpfr::Operation::Exp2, x, __llvm_libc::exp2f(x), 1.0);
116   }
117 }
118