196d85726SSiva Chandra Reddy //===-- Unittests for expf ------------------------------------------------===//
296d85726SSiva Chandra Reddy //
396d85726SSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
496d85726SSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information.
596d85726SSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
696d85726SSiva Chandra Reddy //
796d85726SSiva Chandra Reddy //===----------------------------------------------------------------------===//
896d85726SSiva Chandra Reddy 
9c120edc7SMichael Jones #include "src/__support/FPUtil/FPBits.h"
1096d85726SSiva Chandra Reddy #include "src/math/expf.h"
1196d85726SSiva Chandra Reddy #include "utils/MPFRWrapper/MPFRUtils.h"
126c3f53c7SSiva Chandra Reddy #include "utils/UnitTest/FPMatcher.h"
1396d85726SSiva Chandra Reddy #include "utils/UnitTest/Test.h"
143e18fb33SMichael Jones #include <math.h>
1596d85726SSiva Chandra Reddy 
1635e2e448SSiva Chandra Reddy #include <errno.h>
1796d85726SSiva Chandra Reddy #include <stdint.h>
1896d85726SSiva Chandra Reddy 
1996d85726SSiva Chandra Reddy namespace mpfr = __llvm_libc::testing::mpfr;
2096d85726SSiva Chandra Reddy 
21e7e71e94SSiva Chandra Reddy DECLARE_SPECIAL_CONSTANTS(float)
22e7e71e94SSiva Chandra Reddy 
TEST(LlvmLibcExpfTest,SpecialNumbers)231df0dbfcSMichael Jones TEST(LlvmLibcExpfTest, SpecialNumbers) {
2435e2e448SSiva Chandra Reddy   errno = 0;
2596d85726SSiva Chandra Reddy 
26e7e71e94SSiva Chandra Reddy   EXPECT_FP_EQ(aNaN, __llvm_libc::expf(aNaN));
27ffb410d3STue Ly   EXPECT_MATH_ERRNO(0);
2896d85726SSiva Chandra Reddy 
29e7e71e94SSiva Chandra Reddy   EXPECT_FP_EQ(inf, __llvm_libc::expf(inf));
30ffb410d3STue Ly   EXPECT_MATH_ERRNO(0);
3196d85726SSiva Chandra Reddy 
321c92911eSMichael Jones   EXPECT_FP_EQ(0.0f, __llvm_libc::expf(neg_inf));
33ffb410d3STue Ly   EXPECT_MATH_ERRNO(0);
3496d85726SSiva Chandra Reddy 
35e7e71e94SSiva Chandra Reddy   EXPECT_FP_EQ(1.0f, __llvm_libc::expf(0.0f));
36ffb410d3STue Ly   EXPECT_MATH_ERRNO(0);
3796d85726SSiva Chandra Reddy 
38e7e71e94SSiva Chandra Reddy   EXPECT_FP_EQ(1.0f, __llvm_libc::expf(-0.0f));
39ffb410d3STue Ly   EXPECT_MATH_ERRNO(0);
4096d85726SSiva Chandra Reddy }
4196d85726SSiva Chandra Reddy 
TEST(LlvmLibcExpfTest,Overflow)421df0dbfcSMichael Jones TEST(LlvmLibcExpfTest, Overflow) {
4335e2e448SSiva Chandra Reddy   errno = 0;
44e7e71e94SSiva Chandra Reddy   EXPECT_FP_EQ(inf, __llvm_libc::expf(float(FPBits(0x7f7fffffU))));
45ffb410d3STue Ly   EXPECT_MATH_ERRNO(ERANGE);
4696d85726SSiva Chandra Reddy 
47e7e71e94SSiva Chandra Reddy   EXPECT_FP_EQ(inf, __llvm_libc::expf(float(FPBits(0x42cffff8U))));
48ffb410d3STue Ly   EXPECT_MATH_ERRNO(ERANGE);
4996d85726SSiva Chandra Reddy 
50e7e71e94SSiva Chandra Reddy   EXPECT_FP_EQ(inf, __llvm_libc::expf(float(FPBits(0x42d00008U))));
51ffb410d3STue Ly   EXPECT_MATH_ERRNO(ERANGE);
5296d85726SSiva Chandra Reddy }
5396d85726SSiva Chandra Reddy 
TEST(LlvmLibcExpfTest,Underflow)541df0dbfcSMichael Jones TEST(LlvmLibcExpfTest, Underflow) {
5535e2e448SSiva Chandra Reddy   errno = 0;
56e7e71e94SSiva Chandra Reddy   EXPECT_FP_EQ(0.0f, __llvm_libc::expf(float(FPBits(0xff7fffffU))));
57ffb410d3STue Ly   EXPECT_MATH_ERRNO(ERANGE);
5896d85726SSiva Chandra Reddy 
59e7e71e94SSiva Chandra Reddy   float x = float(FPBits(0xc2cffff8U));
6038cadd90STue Ly   EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp, x, __llvm_libc::expf(x),
6138cadd90STue Ly                                  0.5);
62ffb410d3STue Ly   EXPECT_MATH_ERRNO(ERANGE);
6396d85726SSiva Chandra Reddy 
64e7e71e94SSiva Chandra Reddy   x = float(FPBits(0xc2d00008U));
6538cadd90STue Ly   EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp, x, __llvm_libc::expf(x),
6638cadd90STue Ly                                  0.5);
67ffb410d3STue Ly   EXPECT_MATH_ERRNO(ERANGE);
6896d85726SSiva Chandra Reddy }
6996d85726SSiva Chandra Reddy 
7096d85726SSiva Chandra Reddy // Test with inputs which are the borders of underflow/overflow but still
7196d85726SSiva Chandra Reddy // produce valid results without setting errno.
TEST(LlvmLibcExpfTest,Borderline)721df0dbfcSMichael Jones TEST(LlvmLibcExpfTest, Borderline) {
7396d85726SSiva Chandra Reddy   float x;
7496d85726SSiva Chandra Reddy 
7535e2e448SSiva Chandra Reddy   errno = 0;
76e7e71e94SSiva Chandra Reddy   x = float(FPBits(0x42affff8U));
7738cadd90STue Ly   ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp, x, __llvm_libc::expf(x),
7838cadd90STue Ly                                  0.5);
79ffb410d3STue Ly   EXPECT_MATH_ERRNO(0);
8096d85726SSiva Chandra Reddy 
81e7e71e94SSiva Chandra Reddy   x = float(FPBits(0x42b00008U));
8238cadd90STue Ly   ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp, x, __llvm_libc::expf(x),
8338cadd90STue Ly                                  0.5);
84ffb410d3STue Ly   EXPECT_MATH_ERRNO(0);
8596d85726SSiva Chandra Reddy 
86e7e71e94SSiva Chandra Reddy   x = float(FPBits(0xc2affff8U));
8738cadd90STue Ly   ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp, x, __llvm_libc::expf(x),
8838cadd90STue Ly                                  0.5);
89ffb410d3STue Ly   EXPECT_MATH_ERRNO(0);
9096d85726SSiva Chandra Reddy 
91e7e71e94SSiva Chandra Reddy   x = float(FPBits(0xc2b00008U));
9238cadd90STue Ly   ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp, x, __llvm_libc::expf(x),
9338cadd90STue Ly                                  0.5);
94ffb410d3STue Ly   EXPECT_MATH_ERRNO(0);
95*6168b422STue Ly 
96*6168b422STue Ly   x = float(FPBits(0xc236bd8cU));
97*6168b422STue Ly   EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp, x, __llvm_libc::expf(x),
98*6168b422STue Ly                                  0.5);
99*6168b422STue Ly   EXPECT_MATH_ERRNO(0);
10096d85726SSiva Chandra Reddy }
10196d85726SSiva Chandra Reddy 
TEST(LlvmLibcExpfTest,InFloatRange)1021df0dbfcSMichael Jones TEST(LlvmLibcExpfTest, InFloatRange) {
10325226f3eSMichael Jones   constexpr uint32_t COUNT = 1000000;
10425226f3eSMichael Jones   constexpr uint32_t STEP = UINT32_MAX / COUNT;
10525226f3eSMichael Jones   for (uint32_t i = 0, v = 0; i <= COUNT; ++i, v += STEP) {
106e7e71e94SSiva Chandra Reddy     float x = float(FPBits(v));
10796d85726SSiva Chandra Reddy     if (isnan(x) || isinf(x))
10896d85726SSiva Chandra Reddy       continue;
10935e2e448SSiva Chandra Reddy     errno = 0;
11096d85726SSiva Chandra Reddy     float result = __llvm_libc::expf(x);
11196d85726SSiva Chandra Reddy 
11296d85726SSiva Chandra Reddy     // If the computation resulted in an error or did not produce valid result
11396d85726SSiva Chandra Reddy     // in the single-precision floating point range, then ignore comparing with
11496d85726SSiva Chandra Reddy     // MPFR result as MPFR can still produce valid results because of its
11596d85726SSiva Chandra Reddy     // wider precision.
11635e2e448SSiva Chandra Reddy     if (isnan(result) || isinf(result) || errno != 0)
11796d85726SSiva Chandra Reddy       continue;
11838cadd90STue Ly     EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp, x,
11938cadd90STue Ly                                    __llvm_libc::expf(x), 0.5);
12096d85726SSiva Chandra Reddy   }
12196d85726SSiva Chandra Reddy }
122