1 //===-- Unittests for expf ------------------------------------------------===// 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/math/expf.h" 10 #include "utils/FPUtil/BitPatterns.h" 11 #include "utils/FPUtil/ClassificationFunctions.h" 12 #include "utils/FPUtil/FloatOperations.h" 13 #include "utils/FPUtil/FloatProperties.h" 14 #include "utils/MPFRWrapper/MPFRUtils.h" 15 #include "utils/UnitTest/Test.h" 16 #include <math.h> 17 18 #include <errno.h> 19 #include <stdint.h> 20 21 using __llvm_libc::fputil::isNegativeQuietNaN; 22 using __llvm_libc::fputil::isQuietNaN; 23 using __llvm_libc::fputil::valueAsBits; 24 using __llvm_libc::fputil::valueFromBits; 25 26 using BitPatterns = __llvm_libc::fputil::BitPatterns<float>; 27 28 namespace mpfr = __llvm_libc::testing::mpfr; 29 30 TEST(LlvmLibcExpfTest, SpecialNumbers) { 31 errno = 0; 32 33 EXPECT_TRUE( 34 isQuietNaN(__llvm_libc::expf(valueFromBits(BitPatterns::aQuietNaN)))); 35 EXPECT_EQ(errno, 0); 36 37 EXPECT_TRUE(isNegativeQuietNaN( 38 __llvm_libc::expf(valueFromBits(BitPatterns::aNegativeQuietNaN)))); 39 EXPECT_EQ(errno, 0); 40 41 EXPECT_TRUE(isQuietNaN( 42 __llvm_libc::expf(valueFromBits(BitPatterns::aSignallingNaN)))); 43 EXPECT_EQ(errno, 0); 44 45 EXPECT_TRUE(isNegativeQuietNaN( 46 __llvm_libc::expf(valueFromBits(BitPatterns::aNegativeSignallingNaN)))); 47 EXPECT_EQ(errno, 0); 48 49 EXPECT_EQ(BitPatterns::inf, 50 valueAsBits(__llvm_libc::expf(valueFromBits(BitPatterns::inf)))); 51 EXPECT_EQ(errno, 0); 52 53 EXPECT_EQ(BitPatterns::zero, 54 valueAsBits(__llvm_libc::expf(valueFromBits(BitPatterns::negInf)))); 55 EXPECT_EQ(errno, 0); 56 57 EXPECT_EQ(BitPatterns::one, 58 valueAsBits(__llvm_libc::expf(valueFromBits(BitPatterns::zero)))); 59 EXPECT_EQ(errno, 0); 60 61 EXPECT_EQ(BitPatterns::one, valueAsBits(__llvm_libc::expf( 62 valueFromBits(BitPatterns::negZero)))); 63 EXPECT_EQ(errno, 0); 64 } 65 66 TEST(LlvmLibcExpfTest, Overflow) { 67 errno = 0; 68 EXPECT_EQ(BitPatterns::inf, 69 valueAsBits(__llvm_libc::expf(valueFromBits(0x7f7fffffU)))); 70 EXPECT_EQ(errno, ERANGE); 71 72 errno = 0; 73 EXPECT_EQ(BitPatterns::inf, 74 valueAsBits(__llvm_libc::expf(valueFromBits(0x42cffff8U)))); 75 EXPECT_EQ(errno, ERANGE); 76 77 errno = 0; 78 EXPECT_EQ(BitPatterns::inf, 79 valueAsBits(__llvm_libc::expf(valueFromBits(0x42d00008U)))); 80 EXPECT_EQ(errno, ERANGE); 81 } 82 83 TEST(LlvmLibcExpfTest, Underflow) { 84 errno = 0; 85 EXPECT_EQ(BitPatterns::zero, 86 valueAsBits(__llvm_libc::expf(valueFromBits(0xff7fffffU)))); 87 EXPECT_EQ(errno, ERANGE); 88 89 errno = 0; 90 EXPECT_EQ(BitPatterns::zero, 91 valueAsBits(__llvm_libc::expf(valueFromBits(0xc2cffff8U)))); 92 EXPECT_EQ(errno, ERANGE); 93 94 errno = 0; 95 EXPECT_EQ(BitPatterns::zero, 96 valueAsBits(__llvm_libc::expf(valueFromBits(0xc2d00008U)))); 97 EXPECT_EQ(errno, ERANGE); 98 } 99 100 // Test with inputs which are the borders of underflow/overflow but still 101 // produce valid results without setting errno. 102 TEST(LlvmLibcExpfTest, Borderline) { 103 float x; 104 105 errno = 0; 106 x = valueFromBits(0x42affff8U); 107 ASSERT_MPFR_MATCH(mpfr::Operation::Exp, x, __llvm_libc::expf(x), 1.0); 108 EXPECT_EQ(errno, 0); 109 110 x = valueFromBits(0x42b00008U); 111 ASSERT_MPFR_MATCH(mpfr::Operation::Exp, x, __llvm_libc::expf(x), 1.0); 112 EXPECT_EQ(errno, 0); 113 114 x = valueFromBits(0xc2affff8U); 115 ASSERT_MPFR_MATCH(mpfr::Operation::Exp, x, __llvm_libc::expf(x), 1.0); 116 EXPECT_EQ(errno, 0); 117 118 x = valueFromBits(0xc2b00008U); 119 ASSERT_MPFR_MATCH(mpfr::Operation::Exp, x, __llvm_libc::expf(x), 1.0); 120 EXPECT_EQ(errno, 0); 121 } 122 123 TEST(LlvmLibcExpfTest, InFloatRange) { 124 constexpr uint32_t count = 1000000; 125 constexpr uint32_t step = UINT32_MAX / count; 126 for (uint32_t i = 0, v = 0; i <= count; ++i, v += step) { 127 float x = valueFromBits(v); 128 if (isnan(x) || isinf(x)) 129 continue; 130 errno = 0; 131 float result = __llvm_libc::expf(x); 132 133 // If the computation resulted in an error or did not produce valid result 134 // in the single-precision floating point range, then ignore comparing with 135 // MPFR result as MPFR can still produce valid results because of its 136 // wider precision. 137 if (isnan(result) || isinf(result) || errno != 0) 138 continue; 139 ASSERT_MPFR_MATCH(mpfr::Operation::Exp, x, __llvm_libc::expf(x), 1.0); 140 } 141 } 142