1 //===-- Unittests for erff ------------------------------------------------===// 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 "hdr/math_macros.h" 10 #include "src/__support/FPUtil/FPBits.h" 11 #include "src/math/erff.h" 12 #include "test/UnitTest/FPMatcher.h" 13 #include "test/UnitTest/Test.h" 14 #include "utils/MPFRWrapper/MPFRUtils.h" 15 16 #include <stdint.h> 17 18 using LlvmLibcErffTest = LIBC_NAMESPACE::testing::FPTest<float>; 19 20 namespace mpfr = LIBC_NAMESPACE::testing::mpfr; 21 using LIBC_NAMESPACE::testing::tlog; 22 23 TEST_F(LlvmLibcErffTest, SpecialNumbers) { 24 EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::erff(aNaN)); 25 EXPECT_FP_EQ_ALL_ROUNDING(1.0f, LIBC_NAMESPACE::erff(inf)); 26 EXPECT_FP_EQ_ALL_ROUNDING(-1.0f, LIBC_NAMESPACE::erff(neg_inf)); 27 EXPECT_FP_EQ_ALL_ROUNDING(zero, LIBC_NAMESPACE::erff(zero)); 28 EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, LIBC_NAMESPACE::erff(neg_zero)); 29 } 30 31 TEST_F(LlvmLibcErffTest, TrickyInputs) { 32 constexpr int N = 2; 33 constexpr uint32_t INPUTS[N] = { 34 0x3f65'9229U, // |x| = 0x1.cb2452p-1f 35 0x4004'1e6aU, // |x| = 0x1.083cd4p+1f 36 }; 37 for (int i = 0; i < N; ++i) { 38 float x = FPBits(INPUTS[i]).get_val(); 39 EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Erf, x, 40 LIBC_NAMESPACE::erff(x), 0.5); 41 EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Erf, -x, 42 LIBC_NAMESPACE::erff(-x), 0.5); 43 } 44 } 45 46 TEST_F(LlvmLibcErffTest, InFloatRange) { 47 constexpr uint32_t COUNT = 234561; 48 constexpr uint32_t START = 0; // 0 49 constexpr uint32_t STOP = 0x4080'0000U; // 4.0f 50 51 constexpr uint64_t STEP = (STOP - START) / COUNT; 52 53 auto test = [&](mpfr::RoundingMode rounding_mode) { 54 mpfr::ForceRoundingMode __r(rounding_mode); 55 if (!__r.success) 56 return; 57 58 uint32_t fails = 0; 59 uint32_t count = 0; 60 uint32_t cc = 0; 61 float mx, mr = 0.0; 62 double tol = 0.5; 63 64 for (uint32_t i = 0, v = START; i <= COUNT; ++i, v += STEP) { 65 float x = FPBits(v).get_val(); 66 if (FPBits(v).is_nan()) 67 continue; 68 69 float result = LIBC_NAMESPACE::erff(x); 70 ++cc; 71 if (FPBits(result).is_nan()) 72 continue; 73 74 ++count; 75 if (!TEST_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Erf, x, result, 76 0.5, rounding_mode)) { 77 ++fails; 78 while (!TEST_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Erf, x, 79 result, tol, rounding_mode)) { 80 mx = x; 81 mr = result; 82 tol *= 2.0; 83 } 84 } 85 } 86 tlog << " Log failed: " << fails << "/" << count << "/" << cc 87 << " tests.\n"; 88 tlog << " Max ULPs is at most: " << static_cast<uint64_t>(tol) << ".\n"; 89 if (fails) { 90 EXPECT_MPFR_MATCH(mpfr::Operation::Erf, mx, mr, 0.5, rounding_mode); 91 } 92 }; 93 94 tlog << " Test Rounding To Nearest...\n"; 95 test(mpfr::RoundingMode::Nearest); 96 97 tlog << " Test Rounding Downward...\n"; 98 test(mpfr::RoundingMode::Downward); 99 100 tlog << " Test Rounding Upward...\n"; 101 test(mpfr::RoundingMode::Upward); 102 103 tlog << " Test Rounding Toward Zero...\n"; 104 test(mpfr::RoundingMode::TowardZero); 105 } 106