1a68bbf42STue Ly //===-- Unittests for log -------------------------------------------------===// 2a68bbf42STue Ly // 3a68bbf42STue Ly // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a68bbf42STue Ly // See https://llvm.org/LICENSE.txt for license information. 5a68bbf42STue Ly // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a68bbf42STue Ly // 7a68bbf42STue Ly //===----------------------------------------------------------------------===// 8a68bbf42STue Ly 95748ad84Slntue #include "hdr/math_macros.h" 10a68bbf42STue Ly #include "src/__support/FPUtil/FPBits.h" 11a68bbf42STue Ly #include "src/errno/libc_errno.h" 12a68bbf42STue Ly #include "src/math/log.h" 13a68bbf42STue Ly #include "test/UnitTest/FPMatcher.h" 14a68bbf42STue Ly #include "test/UnitTest/Test.h" 15a68bbf42STue Ly #include "utils/MPFRWrapper/MPFRUtils.h" 16a68bbf42STue Ly 17a68bbf42STue Ly #include <stdint.h> 18a68bbf42STue Ly 193fd5113cSlntue using LlvmLibcLogTest = LIBC_NAMESPACE::testing::FPTest<double>; 203fd5113cSlntue 21b6bc9d72SGuillaume Chatelet namespace mpfr = LIBC_NAMESPACE::testing::mpfr; 22b6bc9d72SGuillaume Chatelet using LIBC_NAMESPACE::testing::tlog; 23a68bbf42STue Ly 243fd5113cSlntue TEST_F(LlvmLibcLogTest, SpecialNumbers) { 25b6bc9d72SGuillaume Chatelet EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::log(aNaN)); 26b6bc9d72SGuillaume Chatelet EXPECT_FP_EQ(inf, LIBC_NAMESPACE::log(inf)); 27b6bc9d72SGuillaume Chatelet EXPECT_FP_IS_NAN_WITH_EXCEPTION(LIBC_NAMESPACE::log(neg_inf), FE_INVALID); 28b6bc9d72SGuillaume Chatelet EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, LIBC_NAMESPACE::log(0.0), FE_DIVBYZERO); 29b6bc9d72SGuillaume Chatelet EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, LIBC_NAMESPACE::log(-0.0), FE_DIVBYZERO); 30b6bc9d72SGuillaume Chatelet EXPECT_FP_IS_NAN_WITH_EXCEPTION(LIBC_NAMESPACE::log(-1.0), FE_INVALID); 31b6bc9d72SGuillaume Chatelet EXPECT_FP_EQ_ALL_ROUNDING(zero, LIBC_NAMESPACE::log(1.0)); 32a68bbf42STue Ly } 33a68bbf42STue Ly 343fd5113cSlntue TEST_F(LlvmLibcLogTest, TrickyInputs) { 35a68bbf42STue Ly constexpr int N = 30; 36a68bbf42STue Ly constexpr uint64_t INPUTS[N] = { 37a68bbf42STue Ly 0x3ff0000000000000, // x = 1.0 38a68bbf42STue Ly 0x4024000000000000, // x = 10.0 39a68bbf42STue Ly 0x4059000000000000, // x = 10^2 40a68bbf42STue Ly 0x408f400000000000, // x = 10^3 41a68bbf42STue Ly 0x40c3880000000000, // x = 10^4 42a68bbf42STue Ly 0x40f86a0000000000, // x = 10^5 43a68bbf42STue Ly 0x412e848000000000, // x = 10^6 44a68bbf42STue Ly 0x416312d000000000, // x = 10^7 45a68bbf42STue Ly 0x4197d78400000000, // x = 10^8 46a68bbf42STue Ly 0x41cdcd6500000000, // x = 10^9 47a68bbf42STue Ly 0x4202a05f20000000, // x = 10^10 48a68bbf42STue Ly 0x42374876e8000000, // x = 10^11 49a68bbf42STue Ly 0x426d1a94a2000000, // x = 10^12 50a68bbf42STue Ly 0x42a2309ce5400000, // x = 10^13 51a68bbf42STue Ly 0x42d6bcc41e900000, // x = 10^14 52a68bbf42STue Ly 0x430c6bf526340000, // x = 10^15 53a68bbf42STue Ly 0x4341c37937e08000, // x = 10^16 54a68bbf42STue Ly 0x4376345785d8a000, // x = 10^17 55a68bbf42STue Ly 0x43abc16d674ec800, // x = 10^18 56a68bbf42STue Ly 0x43e158e460913d00, // x = 10^19 57a68bbf42STue Ly 0x4415af1d78b58c40, // x = 10^20 58a68bbf42STue Ly 0x444b1ae4d6e2ef50, // x = 10^21 59a68bbf42STue Ly 0x4480f0cf064dd592, // x = 10^22 60a68bbf42STue Ly 0x3fefffffffef06ad, 0x3fefde0f22c7d0eb, 0x225e7812faadb32f, 61a68bbf42STue Ly 0x3fee1076964c2903, 0x3fdfe93fff7fceb0, 0x3ff012631ad8df10, 62a68bbf42STue Ly 0x3fefbfdaa448ed98, 63a68bbf42STue Ly }; 64a68bbf42STue Ly for (int i = 0; i < N; ++i) { 652856db0dSGuillaume Chatelet double x = FPBits(INPUTS[i]).get_val(); 66b6bc9d72SGuillaume Chatelet EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log, x, 67b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::log(x), 0.5); 68a68bbf42STue Ly } 69a68bbf42STue Ly } 70a68bbf42STue Ly 713fd5113cSlntue TEST_F(LlvmLibcLogTest, AllExponents) { 72a68bbf42STue Ly double x = 0x1.0p-1074; 73a68bbf42STue Ly for (int i = -1074; i < 1024; ++i, x *= 2.0) { 74b6bc9d72SGuillaume Chatelet ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log, x, 75b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::log(x), 0.5); 76a68bbf42STue Ly } 77a68bbf42STue Ly } 78a68bbf42STue Ly 793fd5113cSlntue TEST_F(LlvmLibcLogTest, InDoubleRange) { 808c6b83dcSTue Ly constexpr uint64_t COUNT = 234561; 81a68bbf42STue Ly constexpr uint64_t START = 0x3FD0'0000'0000'0000ULL; // 0.25 82a68bbf42STue Ly constexpr uint64_t STOP = 0x4010'0000'0000'0000ULL; // 4.0 83a68bbf42STue Ly // constexpr uint64_t START = 0x3FF0'0000'0000'0000ULL; // 1.0 84a68bbf42STue Ly // constexpr uint64_t STOP = 0x4000'0000'0000'0000ULL; // 2.0 85a68bbf42STue Ly constexpr uint64_t STEP = (STOP - START) / COUNT; 86a68bbf42STue Ly 87a68bbf42STue Ly auto test = [&](mpfr::RoundingMode rounding_mode) { 88a68bbf42STue Ly mpfr::ForceRoundingMode __r(rounding_mode); 89055be3c3STue Ly if (!__r.success) 90055be3c3STue Ly return; 91055be3c3STue Ly 92a68bbf42STue Ly uint64_t fails = 0; 93a68bbf42STue Ly uint64_t count = 0; 94a68bbf42STue Ly uint64_t cc = 0; 95a68bbf42STue Ly double mx, mr = 0.0; 96a68bbf42STue Ly double tol = 0.5; 97a68bbf42STue Ly 98a68bbf42STue Ly for (uint64_t i = 0, v = START; i <= COUNT; ++i, v += STEP) { 99a68bbf42STue Ly double x = FPBits(v).get_val(); 100*f8f5b175SNhat Nguyen if (FPBits(v).is_nan() || FPBits(v).is_inf() || x < 0.0) 101a68bbf42STue Ly continue; 1023eb1e6d8Smichaelrj-google LIBC_NAMESPACE::libc_errno = 0; 103b6bc9d72SGuillaume Chatelet double result = LIBC_NAMESPACE::log(x); 104a68bbf42STue Ly ++cc; 105*f8f5b175SNhat Nguyen if (FPBits(result).is_nan() || FPBits(result).is_inf()) 106a68bbf42STue Ly continue; 107a68bbf42STue Ly 108a68bbf42STue Ly ++count; 109a68bbf42STue Ly // ASSERT_MPFR_MATCH(mpfr::Operation::Log, x, result, 0.5); 1109902fc8dSGuillaume Chatelet if (!TEST_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Log, x, result, 111a68bbf42STue Ly 0.5, rounding_mode)) { 112a68bbf42STue Ly ++fails; 1139902fc8dSGuillaume Chatelet while (!TEST_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Log, x, 1149902fc8dSGuillaume Chatelet result, tol, rounding_mode)) { 115a68bbf42STue Ly mx = x; 116a68bbf42STue Ly mr = result; 117a68bbf42STue Ly tol *= 2.0; 118a68bbf42STue Ly } 119a68bbf42STue Ly } 120a68bbf42STue Ly } 121a68bbf42STue Ly tlog << " Log failed: " << fails << "/" << count << "/" << cc 122a68bbf42STue Ly << " tests.\n"; 123a68bbf42STue Ly tlog << " Max ULPs is at most: " << static_cast<uint64_t>(tol) << ".\n"; 124a68bbf42STue Ly if (fails) { 125a68bbf42STue Ly EXPECT_MPFR_MATCH(mpfr::Operation::Log, mx, mr, 0.5, rounding_mode); 126a68bbf42STue Ly } 127a68bbf42STue Ly }; 128a68bbf42STue Ly 129a68bbf42STue Ly tlog << " Test Rounding To Nearest...\n"; 130a68bbf42STue Ly test(mpfr::RoundingMode::Nearest); 131a68bbf42STue Ly 132a68bbf42STue Ly tlog << " Test Rounding Downward...\n"; 133a68bbf42STue Ly test(mpfr::RoundingMode::Downward); 134a68bbf42STue Ly 135a68bbf42STue Ly tlog << " Test Rounding Upward...\n"; 136a68bbf42STue Ly test(mpfr::RoundingMode::Upward); 137a68bbf42STue Ly 138a68bbf42STue Ly tlog << " Test Rounding Toward Zero...\n"; 139a68bbf42STue Ly test(mpfr::RoundingMode::TowardZero); 140a68bbf42STue Ly } 141