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