1b91e78daSTue Ly //===-- Unittests for log1p -----------------------------------------------===// 2b91e78daSTue Ly // 3b91e78daSTue Ly // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4b91e78daSTue Ly // See https://llvm.org/LICENSE.txt for license information. 5b91e78daSTue Ly // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6b91e78daSTue Ly // 7b91e78daSTue Ly //===----------------------------------------------------------------------===// 8b91e78daSTue Ly 95748ad84Slntue #include "hdr/math_macros.h" 10b91e78daSTue Ly #include "src/__support/FPUtil/FPBits.h" 11b91e78daSTue Ly #include "src/errno/libc_errno.h" 12b91e78daSTue Ly #include "src/math/log1p.h" 13b91e78daSTue Ly #include "test/UnitTest/FPMatcher.h" 14b91e78daSTue Ly #include "test/UnitTest/Test.h" 15b91e78daSTue Ly #include "utils/MPFRWrapper/MPFRUtils.h" 16b91e78daSTue Ly 17b91e78daSTue Ly #include <stdint.h> 18b91e78daSTue Ly 193fd5113cSlntue using LlvmLibcLog1pTest = LIBC_NAMESPACE::testing::FPTest<double>; 203fd5113cSlntue 21b6bc9d72SGuillaume Chatelet namespace mpfr = LIBC_NAMESPACE::testing::mpfr; 22b6bc9d72SGuillaume Chatelet using LIBC_NAMESPACE::testing::tlog; 23b91e78daSTue Ly 243fd5113cSlntue TEST_F(LlvmLibcLog1pTest, SpecialNumbers) { 25b6bc9d72SGuillaume Chatelet EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::log1p(aNaN)); 26b6bc9d72SGuillaume Chatelet EXPECT_FP_EQ(inf, LIBC_NAMESPACE::log1p(inf)); 27b6bc9d72SGuillaume Chatelet EXPECT_FP_IS_NAN_WITH_EXCEPTION(LIBC_NAMESPACE::log1p(neg_inf), FE_INVALID); 28b6bc9d72SGuillaume Chatelet EXPECT_FP_IS_NAN_WITH_EXCEPTION(LIBC_NAMESPACE::log1p(-2.0), FE_INVALID); 29b6bc9d72SGuillaume Chatelet EXPECT_FP_EQ(zero, LIBC_NAMESPACE::log1p(0.0)); 30b6bc9d72SGuillaume Chatelet EXPECT_FP_EQ(neg_zero, LIBC_NAMESPACE::log1p(-0.0)); 31b6bc9d72SGuillaume Chatelet EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, LIBC_NAMESPACE::log1p(-1.0), 32b6bc9d72SGuillaume Chatelet FE_DIVBYZERO); 33b91e78daSTue Ly } 34b91e78daSTue Ly 353fd5113cSlntue TEST_F(LlvmLibcLog1pTest, TrickyInputs) { 365f7b133eSlntue constexpr int N = 42; 37b91e78daSTue Ly constexpr uint64_t INPUTS[N] = { 38b91e78daSTue Ly 0x3ff0000000000000, // x = 1.0 39b91e78daSTue Ly 0x4024000000000000, // x = 10.0 40b91e78daSTue Ly 0x4059000000000000, // x = 10^2 41b91e78daSTue Ly 0x408f400000000000, // x = 10^3 42b91e78daSTue Ly 0x40c3880000000000, // x = 10^4 43b91e78daSTue Ly 0x40f86a0000000000, // x = 10^5 44b91e78daSTue Ly 0x412e848000000000, // x = 10^6 45b91e78daSTue Ly 0x416312d000000000, // x = 10^7 46b91e78daSTue Ly 0x4197d78400000000, // x = 10^8 47b91e78daSTue Ly 0x41cdcd6500000000, // x = 10^9 48b91e78daSTue Ly 0x4202a05f20000000, // x = 10^10 49b91e78daSTue Ly 0x42374876e8000000, // x = 10^11 50b91e78daSTue Ly 0x426d1a94a2000000, // x = 10^12 51b91e78daSTue Ly 0x42a2309ce5400000, // x = 10^13 52b91e78daSTue Ly 0x42d6bcc41e900000, // x = 10^14 53b91e78daSTue Ly 0x430c6bf526340000, // x = 10^15 54b91e78daSTue Ly 0x4341c37937e08000, // x = 10^16 55b91e78daSTue Ly 0x4376345785d8a000, // x = 10^17 56b91e78daSTue Ly 0x43abc16d674ec800, // x = 10^18 57b91e78daSTue Ly 0x43e158e460913d00, // x = 10^19 58b91e78daSTue Ly 0x4415af1d78b58c40, // x = 10^20 59b91e78daSTue Ly 0x444b1ae4d6e2ef50, // x = 10^21 60b91e78daSTue Ly 0x4480f0cf064dd592, // x = 10^22 61b91e78daSTue Ly 0x3fefffffffef06ad, 0x3fefde0f22c7d0eb, 0x225e7812faadb32f, 62b91e78daSTue Ly 0x3fee1076964c2903, 0x3fdfe93fff7fceb0, 0x3ff012631ad8df10, 63b91e78daSTue Ly 0x3fefbfdaa448ed98, 0x3fd00a8cefe9a5f8, 0x3fd0b4d870eb22f8, 64b91e78daSTue Ly 0x3c90c40cef04efb5, 0x449d2ccad399848e, 0x4aa12ccdffd9d2ec, 65b91e78daSTue Ly 0x5656f070b92d36ce, 0x6db06dcb74f76bcc, 0x7f1954e72ffd4596, 66b91e78daSTue Ly 0x5671e2f1628093e4, 0x73dac56e2bf1a951, 0x8001bc6879ea14c5, 675f7b133eSlntue 0x45ca5f497ec291df, // x = 0x1.a5f497ec291dfp+93 68b91e78daSTue Ly }; 69b91e78daSTue Ly for (int i = 0; i < N; ++i) { 702856db0dSGuillaume Chatelet double x = FPBits(INPUTS[i]).get_val(); 71b91e78daSTue Ly EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log1p, x, 72b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::log1p(x), 0.5); 73b91e78daSTue Ly } 74b91e78daSTue Ly } 75b91e78daSTue Ly 763fd5113cSlntue TEST_F(LlvmLibcLog1pTest, AllExponents) { 77b91e78daSTue Ly double x = 0x1.0p-1074; 78b91e78daSTue Ly for (int i = -1074; i < 1024; ++i, x *= 2.0) { 79b91e78daSTue Ly ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log1p, x, 80b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::log1p(x), 0.5); 81b91e78daSTue Ly } 82b91e78daSTue Ly } 83b91e78daSTue Ly 843fd5113cSlntue TEST_F(LlvmLibcLog1pTest, InDoubleRange) { 852697ffd0SGuillaume Chatelet constexpr uint64_t COUNT = 4501; 86b91e78daSTue Ly 87b91e78daSTue Ly auto test = [&](uint64_t start, uint64_t stop, 88b91e78daSTue Ly mpfr::RoundingMode rounding_mode) { 89b91e78daSTue Ly mpfr::ForceRoundingMode __r(rounding_mode); 90055be3c3STue Ly if (!__r.success) 91055be3c3STue Ly return; 92055be3c3STue Ly 93b91e78daSTue Ly uint64_t fails = 0; 94b91e78daSTue Ly uint64_t count = 0; 95b91e78daSTue Ly uint64_t cc = 0; 96b91e78daSTue Ly double mx, mr = 0.0; 97b91e78daSTue Ly double tol = 0.5; 98b91e78daSTue Ly 99b91e78daSTue Ly uint64_t step = (stop - start) / COUNT; 100b91e78daSTue Ly 101b91e78daSTue Ly for (uint64_t i = 0, v = start; i <= COUNT; ++i, v += step) { 102b91e78daSTue Ly double x = FPBits(v).get_val(); 103*f8f5b175SNhat Nguyen if (FPBits(v).is_nan() || FPBits(v).is_inf() || x < 0.0) 104b91e78daSTue Ly continue; 1053eb1e6d8Smichaelrj-google LIBC_NAMESPACE::libc_errno = 0; 106b6bc9d72SGuillaume Chatelet double result = LIBC_NAMESPACE::log1p(x); 107b91e78daSTue Ly ++cc; 108*f8f5b175SNhat Nguyen if (FPBits(result).is_nan() || FPBits(result).is_inf()) 109b91e78daSTue Ly continue; 110b91e78daSTue Ly 111b91e78daSTue Ly ++count; 112b91e78daSTue Ly // ASSERT_MPFR_MATCH(mpfr::Operation::Log1p, x, result, 0.5); 1139902fc8dSGuillaume Chatelet if (!TEST_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Log1p, x, result, 1149902fc8dSGuillaume Chatelet 0.5, rounding_mode)) { 115b91e78daSTue Ly ++fails; 1169902fc8dSGuillaume Chatelet while (!TEST_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Log1p, x, 1179902fc8dSGuillaume Chatelet result, tol, rounding_mode)) { 118b91e78daSTue Ly mx = x; 119b91e78daSTue Ly mr = result; 120b91e78daSTue Ly tol *= 2.0; 121b91e78daSTue Ly } 122b91e78daSTue Ly } 123b91e78daSTue Ly } 124b91e78daSTue Ly tlog << " Log1p failed: " << fails << "/" << count << "/" << cc 125b91e78daSTue Ly << " tests.\n"; 126b91e78daSTue Ly tlog << " Max ULPs is at most: " << static_cast<uint64_t>(tol) << ".\n"; 127b91e78daSTue Ly if (fails) { 128b91e78daSTue Ly EXPECT_MPFR_MATCH(mpfr::Operation::Log1p, mx, mr, 0.5, rounding_mode); 129b91e78daSTue Ly } 130b91e78daSTue Ly }; 131b91e78daSTue Ly 132b91e78daSTue Ly auto test_all_rounding = [&](uint64_t start, uint64_t stop, 133b91e78daSTue Ly const char *start_str, const char *stop_str) { 134b91e78daSTue Ly tlog << "\n=== Test in range [" << start_str << ", " << stop_str 135b91e78daSTue Ly << "] ===\n"; 136b91e78daSTue Ly 137b91e78daSTue Ly tlog << "\n Test Rounding To Nearest...\n"; 138b91e78daSTue Ly test(start, stop, mpfr::RoundingMode::Nearest); 139b91e78daSTue Ly 140b91e78daSTue Ly tlog << "\n Test Rounding Downward...\n"; 141b91e78daSTue Ly test(start, stop, mpfr::RoundingMode::Downward); 142b91e78daSTue Ly 143b91e78daSTue Ly tlog << "\n Test Rounding Upward...\n"; 144b91e78daSTue Ly test(start, stop, mpfr::RoundingMode::Upward); 145b91e78daSTue Ly 146b91e78daSTue Ly tlog << "\n Test Rounding Toward Zero...\n"; 147b91e78daSTue Ly test(start, stop, mpfr::RoundingMode::TowardZero); 148b91e78daSTue Ly }; 149b91e78daSTue Ly 150b91e78daSTue Ly test_all_rounding(0x0000'0000'0000'0001ULL, 0x0010'0000'0000'0000ULL, 151b91e78daSTue Ly "2^-1074", "2^-1022"); 152b91e78daSTue Ly 153b91e78daSTue Ly test_all_rounding(0x39B0'0000'0000'0000ULL, 0x3A50'0000'0000'0000ULL, 154b91e78daSTue Ly "2^-100", "2^-90"); 155b91e78daSTue Ly 156b91e78daSTue Ly test_all_rounding(0x3CD0'0000'0000'0000ULL, 0x3D20'0000'0000'0000ULL, "2^-50", 157b91e78daSTue Ly "2^-45"); 158b91e78daSTue Ly 159b91e78daSTue Ly test_all_rounding(0x3E10'0000'0000'0000ULL, 0x3E40'0000'0000'0000ULL, "2^-30", 160b91e78daSTue Ly "2^-27"); 161b91e78daSTue Ly 162b91e78daSTue Ly test_all_rounding(0x3FD0'0000'0000'0000ULL, 0x4010'0000'0000'0000ULL, "0.25", 163b91e78daSTue Ly "4.0"); 164b91e78daSTue Ly 165b91e78daSTue Ly test_all_rounding(0x4630'0000'0000'0000ULL, 0x4670'0000'0000'0000ULL, "2^100", 166b91e78daSTue Ly "2^104"); 167b91e78daSTue Ly 168b91e78daSTue Ly test_all_rounding(0x7FD0'0000'0000'0000ULL, 0x7FF0'0000'0000'0000ULL, 169b91e78daSTue Ly "2^1022", "2^1024"); 170b91e78daSTue Ly } 171