176bb278eSTue Ly //===-- Unittests for 10^x ------------------------------------------------===// 276bb278eSTue Ly // 376bb278eSTue Ly // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 476bb278eSTue Ly // See https://llvm.org/LICENSE.txt for license information. 576bb278eSTue Ly // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 676bb278eSTue Ly // 776bb278eSTue Ly //===----------------------------------------------------------------------===// 876bb278eSTue Ly 95748ad84Slntue #include "hdr/math_macros.h" 1076bb278eSTue Ly #include "src/__support/FPUtil/FPBits.h" 1176bb278eSTue Ly #include "src/errno/libc_errno.h" 1276bb278eSTue Ly #include "src/math/exp10.h" 1376bb278eSTue Ly #include "test/UnitTest/FPMatcher.h" 1476bb278eSTue Ly #include "test/UnitTest/Test.h" 1576bb278eSTue Ly #include "utils/MPFRWrapper/MPFRUtils.h" 1676bb278eSTue Ly 1776bb278eSTue Ly #include <stdint.h> 1876bb278eSTue Ly 193fd5113cSlntue using LlvmLibcExp10Test = LIBC_NAMESPACE::testing::FPTest<double>; 203fd5113cSlntue 21b6bc9d72SGuillaume Chatelet namespace mpfr = LIBC_NAMESPACE::testing::mpfr; 22b6bc9d72SGuillaume Chatelet using LIBC_NAMESPACE::testing::tlog; 2376bb278eSTue Ly 243fd5113cSlntue TEST_F(LlvmLibcExp10Test, SpecialNumbers) { 25b6bc9d72SGuillaume Chatelet EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::exp10(aNaN)); 26b6bc9d72SGuillaume Chatelet EXPECT_FP_EQ(inf, LIBC_NAMESPACE::exp10(inf)); 27b6bc9d72SGuillaume Chatelet EXPECT_FP_EQ_ALL_ROUNDING(zero, LIBC_NAMESPACE::exp10(neg_inf)); 28b6bc9d72SGuillaume Chatelet EXPECT_FP_EQ_WITH_EXCEPTION(zero, LIBC_NAMESPACE::exp10(-0x1.0p20), 2976bb278eSTue Ly FE_UNDERFLOW); 30b6bc9d72SGuillaume Chatelet EXPECT_FP_EQ_WITH_EXCEPTION(inf, LIBC_NAMESPACE::exp10(0x1.0p20), 31b6bc9d72SGuillaume Chatelet FE_OVERFLOW); 32b6bc9d72SGuillaume Chatelet EXPECT_FP_EQ_ALL_ROUNDING(1.0, LIBC_NAMESPACE::exp10(0.0)); 33b6bc9d72SGuillaume Chatelet EXPECT_FP_EQ_ALL_ROUNDING(1.0, LIBC_NAMESPACE::exp10(-0.0)); 3476bb278eSTue Ly } 3576bb278eSTue Ly 363fd5113cSlntue TEST_F(LlvmLibcExp10Test, TrickyInputs) { 3776bb278eSTue Ly constexpr int N = 41; 3876bb278eSTue Ly constexpr uint64_t INPUTS[N] = { 3976bb278eSTue Ly 0x40033093317082F8, 0x3FD79289C6E6A5C0, 4076bb278eSTue Ly 0x3FD05DE80A173EA0, // 0x1.05de80a173eap-2 4176bb278eSTue Ly 0xbf1eb7a4cb841fcc, // -0x1.eb7a4cb841fccp-14 4276bb278eSTue Ly 0xbf19a61fb925970d, 4376bb278eSTue Ly 0x3fda7b764e2cf47a, // 0x1.a7b764e2cf47ap-2 4476bb278eSTue Ly 0xc04757852a4b93aa, // -0x1.757852a4b93aap+5 4576bb278eSTue Ly 0x4044c19e5712e377, // x=0x1.4c19e5712e377p+5 4676bb278eSTue Ly 0xbf19a61fb925970d, // x=-0x1.9a61fb925970dp-14 4776bb278eSTue Ly 0xc039a74cdab36c28, // x=-0x1.9a74cdab36c28p+4 4876bb278eSTue Ly 0xc085b3e4e2e3bba9, // x=-0x1.5b3e4e2e3bba9p+9 4976bb278eSTue Ly 0xc086960d591aec34, // x=-0x1.6960d591aec34p+9 5076bb278eSTue Ly 0xc086232c09d58d91, // x=-0x1.6232c09d58d91p+9 5176bb278eSTue Ly 0xc0874910d52d3051, // x=-0x1.74910d52d3051p9 5276bb278eSTue Ly 0xc0867a172ceb0990, // x=-0x1.67a172ceb099p+9 5376bb278eSTue Ly 0xc08ff80000000000, // x=-0x1.ff8p+9 5476bb278eSTue Ly 0xbc971547652b82fe, // x=-0x1.71547652b82fep-54 5576bb278eSTue Ly 0x0000000000000000, // x = 0 5676bb278eSTue Ly 0x3ff0000000000000, // x = 1 5776bb278eSTue Ly 0x4000000000000000, // x = 2 5876bb278eSTue Ly 0x4008000000000000, // x = 3 5976bb278eSTue Ly 0x4010000000000000, // x = 4 6076bb278eSTue Ly 0x4014000000000000, // x = 5 6176bb278eSTue Ly 0x4018000000000000, // x = 6 6276bb278eSTue Ly 0x401c000000000000, // x = 7 6376bb278eSTue Ly 0x4020000000000000, // x = 8 6476bb278eSTue Ly 0x4022000000000000, // x = 9 6576bb278eSTue Ly 0x4024000000000000, // x = 10 6676bb278eSTue Ly 0x4026000000000000, // x = 11 6776bb278eSTue Ly 0x4028000000000000, // x = 12 6876bb278eSTue Ly 0x402a000000000000, // x = 13 6976bb278eSTue Ly 0x402c000000000000, // x = 14 7076bb278eSTue Ly 0x402e000000000000, // x = 15 7176bb278eSTue Ly 0x4030000000000000, // x = 16 7276bb278eSTue Ly 0x4031000000000000, // x = 17 7376bb278eSTue Ly 0x4032000000000000, // x = 18 7476bb278eSTue Ly 0x4033000000000000, // x = 19 7576bb278eSTue Ly 0x4034000000000000, // x = 20 7676bb278eSTue Ly 0x4035000000000000, // x = 21 7776bb278eSTue Ly 0x4036000000000000, // x = 22 7876bb278eSTue Ly 0x4037000000000000, // x = 23 7976bb278eSTue Ly }; 8076bb278eSTue Ly for (int i = 0; i < N; ++i) { 812856db0dSGuillaume Chatelet double x = FPBits(INPUTS[i]).get_val(); 8276bb278eSTue Ly EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Exp10, x, 83b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::exp10(x), 0.5); 8476bb278eSTue Ly } 8576bb278eSTue Ly } 8676bb278eSTue Ly 873fd5113cSlntue TEST_F(LlvmLibcExp10Test, InDoubleRange) { 8876bb278eSTue Ly constexpr uint64_t COUNT = 1'231; 89b6bc9d72SGuillaume Chatelet uint64_t START = LIBC_NAMESPACE::fputil::FPBits<double>(0.25).uintval(); 90b6bc9d72SGuillaume Chatelet uint64_t STOP = LIBC_NAMESPACE::fputil::FPBits<double>(4.0).uintval(); 9176bb278eSTue Ly uint64_t STEP = (STOP - START) / COUNT; 9276bb278eSTue Ly 9376bb278eSTue Ly auto test = [&](mpfr::RoundingMode rounding_mode) { 9476bb278eSTue Ly mpfr::ForceRoundingMode __r(rounding_mode); 9576bb278eSTue Ly if (!__r.success) 9676bb278eSTue Ly return; 9776bb278eSTue Ly 9876bb278eSTue Ly uint64_t fails = 0; 9976bb278eSTue Ly uint64_t count = 0; 10076bb278eSTue Ly uint64_t cc = 0; 10176bb278eSTue Ly double mx, mr = 0.0; 10276bb278eSTue Ly double tol = 0.5; 10376bb278eSTue Ly 10476bb278eSTue Ly for (uint64_t i = 0, v = START; i <= COUNT; ++i, v += STEP) { 10576bb278eSTue Ly double x = FPBits(v).get_val(); 106*f8f5b175SNhat Nguyen if (FPBits(v).is_nan() || FPBits(v).is_inf() || x < 0.0) 10776bb278eSTue Ly continue; 1083eb1e6d8Smichaelrj-google LIBC_NAMESPACE::libc_errno = 0; 109b6bc9d72SGuillaume Chatelet double result = LIBC_NAMESPACE::exp10(x); 11076bb278eSTue Ly ++cc; 111*f8f5b175SNhat Nguyen if (FPBits(result).is_nan() || FPBits(result).is_inf()) 11276bb278eSTue Ly continue; 11376bb278eSTue Ly 11476bb278eSTue Ly ++count; 11576bb278eSTue Ly 11676bb278eSTue Ly if (!TEST_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Exp10, x, result, 11776bb278eSTue Ly 0.5, rounding_mode)) { 11876bb278eSTue Ly ++fails; 11976bb278eSTue Ly while (!TEST_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Exp10, x, 12076bb278eSTue Ly result, tol, rounding_mode)) { 12176bb278eSTue Ly mx = x; 12276bb278eSTue Ly mr = result; 12376bb278eSTue Ly 12476bb278eSTue Ly if (tol > 1000.0) 12576bb278eSTue Ly break; 12676bb278eSTue Ly 12776bb278eSTue Ly tol *= 2.0; 12876bb278eSTue Ly } 12976bb278eSTue Ly } 13076bb278eSTue Ly } 13176bb278eSTue Ly tlog << " Exp10 failed: " << fails << "/" << count << "/" << cc 13276bb278eSTue Ly << " tests.\n"; 13376bb278eSTue Ly tlog << " Max ULPs is at most: " << static_cast<uint64_t>(tol) << ".\n"; 13476bb278eSTue Ly if (fails) { 13576bb278eSTue Ly EXPECT_MPFR_MATCH(mpfr::Operation::Exp10, mx, mr, 0.5, rounding_mode); 13676bb278eSTue Ly } 13776bb278eSTue Ly }; 13876bb278eSTue Ly 13976bb278eSTue Ly tlog << " Test Rounding To Nearest...\n"; 14076bb278eSTue Ly test(mpfr::RoundingMode::Nearest); 14176bb278eSTue Ly 14276bb278eSTue Ly tlog << " Test Rounding Downward...\n"; 14376bb278eSTue Ly test(mpfr::RoundingMode::Downward); 14476bb278eSTue Ly 14576bb278eSTue Ly tlog << " Test Rounding Upward...\n"; 14676bb278eSTue Ly test(mpfr::RoundingMode::Upward); 14776bb278eSTue Ly 14876bb278eSTue Ly tlog << " Test Rounding Toward Zero...\n"; 14976bb278eSTue Ly test(mpfr::RoundingMode::TowardZero); 15076bb278eSTue Ly } 151