1111d2748STue Ly //===-- Unittests for log2 ------------------------------------------------===// 2111d2748STue Ly // 3111d2748STue Ly // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4111d2748STue Ly // See https://llvm.org/LICENSE.txt for license information. 5111d2748STue Ly // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6111d2748STue Ly // 7111d2748STue Ly //===----------------------------------------------------------------------===// 8111d2748STue Ly 95748ad84Slntue #include "hdr/math_macros.h" 10111d2748STue Ly #include "src/__support/FPUtil/FPBits.h" 11111d2748STue Ly #include "src/errno/libc_errno.h" 12111d2748STue Ly #include "src/math/log2.h" 13111d2748STue Ly #include "test/UnitTest/FPMatcher.h" 14111d2748STue Ly #include "test/UnitTest/Test.h" 15111d2748STue Ly #include "utils/MPFRWrapper/MPFRUtils.h" 16111d2748STue Ly 17111d2748STue Ly #include <stdint.h> 18111d2748STue Ly 193fd5113cSlntue using LlvmLibcLog2Test = LIBC_NAMESPACE::testing::FPTest<double>; 203fd5113cSlntue 21b6bc9d72SGuillaume Chatelet namespace mpfr = LIBC_NAMESPACE::testing::mpfr; 22b6bc9d72SGuillaume Chatelet using LIBC_NAMESPACE::testing::tlog; 23111d2748STue Ly 243fd5113cSlntue TEST_F(LlvmLibcLog2Test, SpecialNumbers) { 25b6bc9d72SGuillaume Chatelet EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::log2(aNaN)); 26b6bc9d72SGuillaume Chatelet EXPECT_FP_EQ(inf, LIBC_NAMESPACE::log2(inf)); 27b6bc9d72SGuillaume Chatelet EXPECT_FP_IS_NAN_WITH_EXCEPTION(LIBC_NAMESPACE::log2(neg_inf), FE_INVALID); 28b6bc9d72SGuillaume Chatelet EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, LIBC_NAMESPACE::log2(0.0), FE_DIVBYZERO); 29b6bc9d72SGuillaume Chatelet EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, LIBC_NAMESPACE::log2(-0.0), 30b6bc9d72SGuillaume Chatelet FE_DIVBYZERO); 31b6bc9d72SGuillaume Chatelet EXPECT_FP_IS_NAN_WITH_EXCEPTION(LIBC_NAMESPACE::log2(-1.0), FE_INVALID); 32b6bc9d72SGuillaume Chatelet EXPECT_FP_EQ_ALL_ROUNDING(zero, LIBC_NAMESPACE::log2(1.0)); 33111d2748STue Ly } 34111d2748STue Ly 353fd5113cSlntue TEST_F(LlvmLibcLog2Test, TrickyInputs) { 36111d2748STue Ly constexpr int N = 30; 37111d2748STue Ly constexpr uint64_t INPUTS[N] = { 38111d2748STue Ly 0x3ff0000000000000, // x = 1.0 39111d2748STue Ly 0x4024000000000000, // x = 10.0 40111d2748STue Ly 0x4059000000000000, // x = 10^2 41111d2748STue Ly 0x408f400000000000, // x = 10^3 42111d2748STue Ly 0x40c3880000000000, // x = 10^4 43111d2748STue Ly 0x40f86a0000000000, // x = 10^5 44111d2748STue Ly 0x412e848000000000, // x = 10^6 45111d2748STue Ly 0x416312d000000000, // x = 10^7 46111d2748STue Ly 0x4197d78400000000, // x = 10^8 47111d2748STue Ly 0x41cdcd6500000000, // x = 10^9 48111d2748STue Ly 0x4202a05f20000000, // x = 10^10 49111d2748STue Ly 0x42374876e8000000, // x = 10^11 50111d2748STue Ly 0x426d1a94a2000000, // x = 10^12 51111d2748STue Ly 0x42a2309ce5400000, // x = 10^13 52111d2748STue Ly 0x42d6bcc41e900000, // x = 10^14 53111d2748STue Ly 0x430c6bf526340000, // x = 10^15 54111d2748STue Ly 0x4341c37937e08000, // x = 10^16 55111d2748STue Ly 0x4376345785d8a000, // x = 10^17 56111d2748STue Ly 0x43abc16d674ec800, // x = 10^18 57111d2748STue Ly 0x43e158e460913d00, // x = 10^19 58111d2748STue Ly 0x4415af1d78b58c40, // x = 10^20 59111d2748STue Ly 0x444b1ae4d6e2ef50, // x = 10^21 60111d2748STue Ly 0x4480f0cf064dd592, // x = 10^22 61111d2748STue Ly 0x3fefffffffef06ad, 0x3fefde0f22c7d0eb, 0x225e7812faadb32f, 62111d2748STue Ly 0x3fee1076964c2903, 0x3fdfe93fff7fceb0, 0x3ff012631ad8df10, 63111d2748STue Ly 0x3fefbfdaa448ed98, 64111d2748STue Ly }; 65111d2748STue Ly for (int i = 0; i < N; ++i) { 662856db0dSGuillaume Chatelet double x = FPBits(INPUTS[i]).get_val(); 67111d2748STue Ly EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log2, x, 68b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::log2(x), 0.5); 69111d2748STue Ly } 70111d2748STue Ly } 71111d2748STue Ly 723fd5113cSlntue TEST_F(LlvmLibcLog2Test, AllExponents) { 73111d2748STue Ly double x = 0x1.0p-1074; 74111d2748STue Ly for (int i = -1074; i < 1024; ++i, x *= 2.0) { 75111d2748STue Ly ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log2, x, 76b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::log2(x), 0.5); 77111d2748STue Ly } 78111d2748STue Ly } 79111d2748STue Ly 803fd5113cSlntue TEST_F(LlvmLibcLog2Test, InDoubleRange) { 812697ffd0SGuillaume Chatelet constexpr uint64_t COUNT = 1'001; 82111d2748STue Ly constexpr uint64_t START = 0x3FD0'0000'0000'0000ULL; // 0.25 83111d2748STue Ly constexpr uint64_t STOP = 0x4010'0000'0000'0000ULL; // 4.0 84111d2748STue Ly // constexpr uint64_t START = 0x3FF0'0000'0000'0000ULL; // 1.0 85111d2748STue Ly // constexpr uint64_t STOP = 0x4000'0000'0000'0000ULL; // 2.0 86111d2748STue Ly constexpr uint64_t STEP = (STOP - START) / COUNT; 87111d2748STue Ly 88111d2748STue Ly auto test = [&](mpfr::RoundingMode rounding_mode) { 89111d2748STue Ly mpfr::ForceRoundingMode __r(rounding_mode); 90055be3c3STue Ly if (!__r.success) 91055be3c3STue Ly return; 92055be3c3STue Ly 93111d2748STue Ly uint64_t fails = 0; 94111d2748STue Ly uint64_t count = 0; 95111d2748STue Ly uint64_t cc = 0; 96111d2748STue Ly double mx, mr = 0.0; 97111d2748STue Ly double tol = 0.5; 98111d2748STue Ly 99111d2748STue Ly for (uint64_t i = 0, v = START; i <= COUNT; ++i, v += STEP) { 100111d2748STue Ly double x = FPBits(v).get_val(); 101*f8f5b175SNhat Nguyen if (FPBits(v).is_nan() || FPBits(v).is_inf() || x < 0.0) 102111d2748STue Ly continue; 1033eb1e6d8Smichaelrj-google LIBC_NAMESPACE::libc_errno = 0; 104b6bc9d72SGuillaume Chatelet double result = LIBC_NAMESPACE::log2(x); 105111d2748STue Ly ++cc; 106*f8f5b175SNhat Nguyen if (FPBits(result).is_nan() || FPBits(result).is_inf()) 107111d2748STue Ly continue; 108111d2748STue Ly 109111d2748STue Ly ++count; 110111d2748STue Ly // ASSERT_MPFR_MATCH(mpfr::Operation::Log2, x, result, 0.5); 1119902fc8dSGuillaume Chatelet if (!TEST_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Log2, x, result, 112111d2748STue Ly 0.5, rounding_mode)) { 113111d2748STue Ly ++fails; 1149902fc8dSGuillaume Chatelet while (!TEST_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Log2, x, 1159902fc8dSGuillaume Chatelet result, tol, rounding_mode)) { 116111d2748STue Ly mx = x; 117111d2748STue Ly mr = result; 118111d2748STue Ly tol *= 2.0; 119111d2748STue Ly } 120111d2748STue Ly } 121111d2748STue Ly } 122111d2748STue Ly tlog << " Log2 failed: " << fails << "/" << count << "/" << cc 123111d2748STue Ly << " tests.\n"; 124111d2748STue Ly tlog << " Max ULPs is at most: " << static_cast<uint64_t>(tol) << ".\n"; 125111d2748STue Ly if (fails) { 126111d2748STue Ly EXPECT_MPFR_MATCH(mpfr::Operation::Log2, mx, mr, 0.5, rounding_mode); 127111d2748STue Ly } 128111d2748STue Ly }; 129111d2748STue Ly 130111d2748STue Ly tlog << " Test Rounding To Nearest...\n"; 131111d2748STue Ly test(mpfr::RoundingMode::Nearest); 132111d2748STue Ly 133111d2748STue Ly tlog << " Test Rounding Downward...\n"; 134111d2748STue Ly test(mpfr::RoundingMode::Downward); 135111d2748STue Ly 136111d2748STue Ly tlog << " Test Rounding Upward...\n"; 137111d2748STue Ly test(mpfr::RoundingMode::Upward); 138111d2748STue Ly 139111d2748STue Ly tlog << " Test Rounding Toward Zero...\n"; 140111d2748STue Ly test(mpfr::RoundingMode::TowardZero); 141111d2748STue Ly } 142