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