1 //===-- Unittests for log10 -----------------------------------------------===// 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/errno/libc_errno.h" 12 #include "src/math/log10.h" 13 #include "test/UnitTest/FPMatcher.h" 14 #include "test/UnitTest/Test.h" 15 #include "utils/MPFRWrapper/MPFRUtils.h" 16 17 #include <stdint.h> 18 19 using LlvmLibcLog10Test = LIBC_NAMESPACE::testing::FPTest<double>; 20 21 namespace mpfr = LIBC_NAMESPACE::testing::mpfr; 22 using LIBC_NAMESPACE::testing::tlog; 23 24 TEST_F(LlvmLibcLog10Test, SpecialNumbers) { 25 EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::log10(aNaN)); 26 EXPECT_FP_EQ(inf, LIBC_NAMESPACE::log10(inf)); 27 EXPECT_FP_IS_NAN_WITH_EXCEPTION(LIBC_NAMESPACE::log10(neg_inf), FE_INVALID); 28 EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, LIBC_NAMESPACE::log10(0.0), 29 FE_DIVBYZERO); 30 EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, LIBC_NAMESPACE::log10(-0.0), 31 FE_DIVBYZERO); 32 EXPECT_FP_IS_NAN_WITH_EXCEPTION(LIBC_NAMESPACE::log10(-1.0), FE_INVALID); 33 EXPECT_FP_EQ_ALL_ROUNDING(zero, LIBC_NAMESPACE::log10(1.0)); 34 } 35 36 TEST_F(LlvmLibcLog10Test, TrickyInputs) { 37 constexpr int N = 36; 38 constexpr uint64_t INPUTS[N] = { 39 0x3ff0000000000000, // x = 1.0 40 0x4024000000000000, // x = 10.0 41 0x4059000000000000, // x = 10^2 42 0x408f400000000000, // x = 10^3 43 0x40c3880000000000, // x = 10^4 44 0x40f86a0000000000, // x = 10^5 45 0x412e848000000000, // x = 10^6 46 0x416312d000000000, // x = 10^7 47 0x4197d78400000000, // x = 10^8 48 0x41cdcd6500000000, // x = 10^9 49 0x4202a05f20000000, // x = 10^10 50 0x42374876e8000000, // x = 10^11 51 0x426d1a94a2000000, // x = 10^12 52 0x42a2309ce5400000, // x = 10^13 53 0x42d6bcc41e900000, // x = 10^14 54 0x430c6bf526340000, // x = 10^15 55 0x4341c37937e08000, // x = 10^16 56 0x4376345785d8a000, // x = 10^17 57 0x43abc16d674ec800, // x = 10^18 58 0x43e158e460913d00, // x = 10^19 59 0x4415af1d78b58c40, // x = 10^20 60 0x444b1ae4d6e2ef50, // x = 10^21 61 0x4480f0cf064dd592, // x = 10^22 62 0x3fefffffffef06ad, 0x3fefde0f22c7d0eb, 0x225e7812faadb32f, 63 0x3fee1076964c2903, 0x3fdfe93fff7fceb0, 0x3ff012631ad8df10, 64 0x3fefbfdaa448ed98, 0x44b0c9705a25ce02, 0x2c88d301065c7f9b, 65 0x30160580e7268a99, 0x5ca04103b7eaa345, 0x19ad77dc4a40093f, 66 0x0000449fb5c8a96e}; 67 for (int i = 0; i < N; ++i) { 68 double x = FPBits(INPUTS[i]).get_val(); 69 EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log10, x, 70 LIBC_NAMESPACE::log10(x), 0.5); 71 } 72 } 73 74 TEST_F(LlvmLibcLog10Test, AllExponents) { 75 double x = 0x1.0p-1074; 76 for (int i = -1074; i < 1024; ++i, x *= 2.0) { 77 ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log10, x, 78 LIBC_NAMESPACE::log10(x), 0.5); 79 } 80 } 81 82 TEST_F(LlvmLibcLog10Test, InDoubleRange) { 83 constexpr uint64_t COUNT = 1'001; 84 constexpr uint64_t START = 0x3FD0'0000'0000'0000ULL; // 0.25 85 constexpr uint64_t STOP = 0x4010'0000'0000'0000ULL; // 4.0 86 // constexpr uint64_t START = 0x3FF0'0000'0000'0000ULL; // 1.0 87 // constexpr uint64_t STOP = 0x4000'0000'0000'0000ULL; // 2.0 88 constexpr uint64_t STEP = (STOP - START) / COUNT; 89 90 auto test = [&](mpfr::RoundingMode rounding_mode) { 91 mpfr::ForceRoundingMode __r(rounding_mode); 92 if (!__r.success) 93 return; 94 uint64_t fails = 0; 95 uint64_t count = 0; 96 uint64_t cc = 0; 97 double mx, mr = 0.0; 98 double tol = 0.5; 99 100 for (uint64_t i = 0, v = START; i <= COUNT; ++i, v += STEP) { 101 double x = FPBits(v).get_val(); 102 if (FPBits(v).is_nan() || FPBits(v).is_inf() || x < 0.0) 103 continue; 104 LIBC_NAMESPACE::libc_errno = 0; 105 double result = LIBC_NAMESPACE::log10(x); 106 ++cc; 107 if (FPBits(result).is_nan() || FPBits(result).is_inf()) 108 continue; 109 110 ++count; 111 // ASSERT_MPFR_MATCH(mpfr::Operation::Log10, x, result, 0.5); 112 if (!TEST_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Log10, x, result, 113 0.5, rounding_mode)) { 114 ++fails; 115 while (!TEST_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Log10, x, 116 result, tol, rounding_mode)) { 117 mx = x; 118 mr = result; 119 tol *= 2.0; 120 } 121 } 122 } 123 tlog << " Log10 failed: " << fails << "/" << count << "/" << cc 124 << " tests.\n"; 125 tlog << " Max ULPs is at most: " << static_cast<uint64_t>(tol) << ".\n"; 126 if (fails) { 127 EXPECT_MPFR_MATCH(mpfr::Operation::Log10, mx, mr, 0.5, rounding_mode); 128 } 129 }; 130 131 tlog << " Test Rounding To Nearest...\n"; 132 test(mpfr::RoundingMode::Nearest); 133 134 tlog << " Test Rounding Downward...\n"; 135 test(mpfr::RoundingMode::Downward); 136 137 tlog << " Test Rounding Upward...\n"; 138 test(mpfr::RoundingMode::Upward); 139 140 tlog << " Test Rounding Toward Zero...\n"; 141 test(mpfr::RoundingMode::TowardZero); 142 } 143