xref: /llvm-project/libc/test/src/math/expf_test.cpp (revision f8f5b17564cb839101ba99390bcecc564de57e65)
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 
95748ad84Slntue #include "hdr/math_macros.h"
10c120edc7SMichael Jones #include "src/__support/FPUtil/FPBits.h"
1131c39439STue Ly #include "src/errno/libc_errno.h"
1296d85726SSiva Chandra Reddy #include "src/math/expf.h"
13af1315c2SSiva Chandra Reddy #include "test/UnitTest/FPMatcher.h"
14af1315c2SSiva Chandra Reddy #include "test/UnitTest/Test.h"
1596d85726SSiva Chandra Reddy #include "utils/MPFRWrapper/MPFRUtils.h"
1696d85726SSiva Chandra Reddy 
1796d85726SSiva Chandra Reddy #include <stdint.h>
1896d85726SSiva Chandra Reddy 
193fd5113cSlntue using LlvmLibcExpfTest = LIBC_NAMESPACE::testing::FPTest<float>;
203fd5113cSlntue 
21b6bc9d72SGuillaume Chatelet namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
2296d85726SSiva Chandra Reddy 
233fd5113cSlntue TEST_F(LlvmLibcExpfTest, SpecialNumbers) {
243eb1e6d8Smichaelrj-google   LIBC_NAMESPACE::libc_errno = 0;
2596d85726SSiva Chandra Reddy 
26b6bc9d72SGuillaume Chatelet   EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::expf(aNaN));
27ffb410d3STue Ly   EXPECT_MATH_ERRNO(0);
2896d85726SSiva Chandra Reddy 
29b6bc9d72SGuillaume Chatelet   EXPECT_FP_EQ(inf, LIBC_NAMESPACE::expf(inf));
30ffb410d3STue Ly   EXPECT_MATH_ERRNO(0);
3196d85726SSiva Chandra Reddy 
32b6bc9d72SGuillaume Chatelet   EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::expf(neg_inf));
33ffb410d3STue Ly   EXPECT_MATH_ERRNO(0);
3496d85726SSiva Chandra Reddy 
35b6bc9d72SGuillaume Chatelet   EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::expf(0.0f));
36ffb410d3STue Ly   EXPECT_MATH_ERRNO(0);
3796d85726SSiva Chandra Reddy 
38b6bc9d72SGuillaume Chatelet   EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::expf(-0.0f));
39ffb410d3STue Ly   EXPECT_MATH_ERRNO(0);
4096d85726SSiva Chandra Reddy }
4196d85726SSiva Chandra Reddy 
423fd5113cSlntue TEST_F(LlvmLibcExpfTest, Overflow) {
433eb1e6d8Smichaelrj-google   LIBC_NAMESPACE::libc_errno = 0;
440aa9593cSTue Ly   EXPECT_FP_EQ_WITH_EXCEPTION(
452856db0dSGuillaume Chatelet       inf, LIBC_NAMESPACE::expf(FPBits(0x7f7fffffU).get_val()), FE_OVERFLOW);
46ffb410d3STue Ly   EXPECT_MATH_ERRNO(ERANGE);
4796d85726SSiva Chandra Reddy 
480aa9593cSTue Ly   EXPECT_FP_EQ_WITH_EXCEPTION(
492856db0dSGuillaume Chatelet       inf, LIBC_NAMESPACE::expf(FPBits(0x42cffff8U).get_val()), FE_OVERFLOW);
50ffb410d3STue Ly   EXPECT_MATH_ERRNO(ERANGE);
5196d85726SSiva Chandra Reddy 
520aa9593cSTue Ly   EXPECT_FP_EQ_WITH_EXCEPTION(
532856db0dSGuillaume Chatelet       inf, LIBC_NAMESPACE::expf(FPBits(0x42d00008U).get_val()), FE_OVERFLOW);
54ffb410d3STue Ly   EXPECT_MATH_ERRNO(ERANGE);
5596d85726SSiva Chandra Reddy }
5696d85726SSiva Chandra Reddy 
573fd5113cSlntue TEST_F(LlvmLibcExpfTest, Underflow) {
583eb1e6d8Smichaelrj-google   LIBC_NAMESPACE::libc_errno = 0;
590aa9593cSTue Ly   EXPECT_FP_EQ_WITH_EXCEPTION(
602856db0dSGuillaume Chatelet       0.0f, LIBC_NAMESPACE::expf(FPBits(0xff7fffffU).get_val()), FE_UNDERFLOW);
61ffb410d3STue Ly   EXPECT_MATH_ERRNO(ERANGE);
6296d85726SSiva Chandra Reddy 
632856db0dSGuillaume Chatelet   float x = FPBits(0xc2cffff8U).get_val();
64b6bc9d72SGuillaume Chatelet   EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp, x,
65b6bc9d72SGuillaume Chatelet                                  LIBC_NAMESPACE::expf(x), 0.5);
66ffb410d3STue Ly   EXPECT_MATH_ERRNO(ERANGE);
6796d85726SSiva Chandra Reddy 
682856db0dSGuillaume Chatelet   x = FPBits(0xc2d00008U).get_val();
69b6bc9d72SGuillaume Chatelet   EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp, x,
70b6bc9d72SGuillaume Chatelet                                  LIBC_NAMESPACE::expf(x), 0.5);
71ffb410d3STue Ly   EXPECT_MATH_ERRNO(ERANGE);
7296d85726SSiva Chandra Reddy }
7396d85726SSiva Chandra Reddy 
7496d85726SSiva Chandra Reddy // Test with inputs which are the borders of underflow/overflow but still
7596d85726SSiva Chandra Reddy // produce valid results without setting errno.
763fd5113cSlntue TEST_F(LlvmLibcExpfTest, Borderline) {
7796d85726SSiva Chandra Reddy   float x;
7896d85726SSiva Chandra Reddy 
793eb1e6d8Smichaelrj-google   LIBC_NAMESPACE::libc_errno = 0;
802856db0dSGuillaume Chatelet   x = FPBits(0x42affff8U).get_val();
81b6bc9d72SGuillaume Chatelet   ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp, x,
82b6bc9d72SGuillaume Chatelet                                  LIBC_NAMESPACE::expf(x), 0.5);
83ffb410d3STue Ly   EXPECT_MATH_ERRNO(0);
8496d85726SSiva Chandra Reddy 
852856db0dSGuillaume Chatelet   x = FPBits(0x42b00008U).get_val();
86b6bc9d72SGuillaume Chatelet   ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp, x,
87b6bc9d72SGuillaume Chatelet                                  LIBC_NAMESPACE::expf(x), 0.5);
88ffb410d3STue Ly   EXPECT_MATH_ERRNO(0);
8996d85726SSiva Chandra Reddy 
902856db0dSGuillaume Chatelet   x = FPBits(0xc2affff8U).get_val();
91b6bc9d72SGuillaume Chatelet   ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp, x,
92b6bc9d72SGuillaume Chatelet                                  LIBC_NAMESPACE::expf(x), 0.5);
93ffb410d3STue Ly   EXPECT_MATH_ERRNO(0);
9496d85726SSiva Chandra Reddy 
952856db0dSGuillaume Chatelet   x = FPBits(0xc2b00008U).get_val();
96b6bc9d72SGuillaume Chatelet   ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp, x,
97b6bc9d72SGuillaume Chatelet                                  LIBC_NAMESPACE::expf(x), 0.5);
98ffb410d3STue Ly   EXPECT_MATH_ERRNO(0);
996168b422STue Ly 
1002856db0dSGuillaume Chatelet   x = FPBits(0xc236bd8cU).get_val();
101b6bc9d72SGuillaume Chatelet   EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp, x,
102b6bc9d72SGuillaume Chatelet                                  LIBC_NAMESPACE::expf(x), 0.5);
1036168b422STue Ly   EXPECT_MATH_ERRNO(0);
10496d85726SSiva Chandra Reddy }
10596d85726SSiva Chandra Reddy 
1063fd5113cSlntue TEST_F(LlvmLibcExpfTest, InFloatRange) {
107ae5c4724SGuillaume Chatelet   constexpr uint32_t COUNT = 100'000;
10825226f3eSMichael Jones   constexpr uint32_t STEP = UINT32_MAX / COUNT;
10925226f3eSMichael Jones   for (uint32_t i = 0, v = 0; i <= COUNT; ++i, v += STEP) {
1102856db0dSGuillaume Chatelet     float x = FPBits(v).get_val();
111*f8f5b175SNhat Nguyen     if (FPBits(v).is_nan() || FPBits(v).is_inf())
11296d85726SSiva Chandra Reddy       continue;
1133eb1e6d8Smichaelrj-google     LIBC_NAMESPACE::libc_errno = 0;
114b6bc9d72SGuillaume Chatelet     float result = LIBC_NAMESPACE::expf(x);
11596d85726SSiva Chandra Reddy 
11696d85726SSiva Chandra Reddy     // If the computation resulted in an error or did not produce valid result
11796d85726SSiva Chandra Reddy     // in the single-precision floating point range, then ignore comparing with
11896d85726SSiva Chandra Reddy     // MPFR result as MPFR can still produce valid results because of its
11996d85726SSiva Chandra Reddy     // wider precision.
120*f8f5b175SNhat Nguyen     if (FPBits(result).is_nan() || FPBits(result).is_inf() ||
121*f8f5b175SNhat Nguyen         LIBC_NAMESPACE::libc_errno != 0)
12296d85726SSiva Chandra Reddy       continue;
12338cadd90STue Ly     EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp, x,
124b6bc9d72SGuillaume Chatelet                                    LIBC_NAMESPACE::expf(x), 0.5);
12596d85726SSiva Chandra Reddy   }
12696d85726SSiva Chandra Reddy }
127