Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[libc][math] Implement double precision log2 function correctly round…
…ed to all rounding modes. Implement double precision log2 function correctly rounded to all rounding modes. See https://reviews.llvm.org/D150014 for a more detail description of the algorithm. **Performance** - For `0.5 <= x <= 2`, the fast pass hitting rate is about 99.91%. - Reciprocal throughput from CORE-MATH's perf tool on Ryzen 5900X: ``` $ ./perf.sh log2 GNU libc version: 2.35 GNU libc release: stable -- CORE-MATH reciprocal throughput -- with FMA [####################] 100 % Ntrial = 20 ; Min = 15.458 + 0.204 clc/call; Median-Min = 0.224 clc/call; Max = 15.867 clc/call; -- CORE-MATH reciprocal throughput -- without FMA (-march=x86-64-v2) [####################] 100 % Ntrial = 20 ; Min = 23.711 + 0.524 clc/call; Median-Min = 0.443 clc/call; Max = 25.307 clc/call; -- System LIBC reciprocal throughput -- [####################] 100 % Ntrial = 20 ; Min = 14.807 + 0.199 clc/call; Median-Min = 0.211 clc/call; Max = 15.137 clc/call; -- LIBC reciprocal throughput -- with FMA [####################] 100 % Ntrial = 20 ; Min = 17.666 + 0.274 clc/call; Median-Min = 0.298 clc/call; Max = 18.531 clc/call; -- LIBC reciprocal throughput -- without FMA [####################] 100 % Ntrial = 20 ; Min = 26.534 + 0.418 clc/call; Median-Min = 0.462 clc/call; Max = 27.327 clc/call; ``` - Latency from CORE-MATH's perf tool on Ryzen 5900X: ``` $ ./perf.sh log2 --latency GNU libc version: 2.35 GNU libc release: stable -- CORE-MATH latency -- with FMA [####################] 100 % Ntrial = 20 ; Min = 46.048 + 1.643 clc/call; Median-Min = 1.694 clc/call; Max = 48.018 clc/call; -- CORE-MATH latency -- without FMA (-march=x86-64-v2) [####################] 100 % Ntrial = 20 ; Min = 62.333 + 0.138 clc/call; Median-Min = 0.119 clc/call; Max = 62.583 clc/call; -- System LIBC latency -- [####################] 100 % Ntrial = 20 ; Min = 45.206 + 1.503 clc/call; Median-Min = 1.467 clc/call; Max = 47.229 clc/call; -- LIBC latency -- with FMA [####################] 100 % Ntrial = 20 ; Min = 43.042 + 0.454 clc/call; Median-Min = 0.484 clc/call; Max = 43.912 clc/call; -- LIBC latency -- without FMA [####################] 100 % Ntrial = 20 ; Min = 57.016 + 1.636 clc/call; Median-Min = 1.655 clc/call; Max = 58.816 clc/call; ``` - Accurate pass latency: ``` $ ./perf.sh log2 --latency --simple_stat GNU libc version: 2.35 GNU libc release: stable -- CORE-MATH latency -- with FMA 177.632 -- CORE-MATH latency -- without FMA (-march=x86-64-v2) 231.332 -- LIBC latency -- with FMA 459.751 -- LIBC latency -- without FMA 463.850 ``` Reviewed By: zimmermann6 Differential Revision: https://reviews.llvm.org/D150374
- Loading branch information
Showing
13 changed files
with
1,158 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
//===-- Implementation header for log2 --------------------------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_LIBC_SRC_MATH_LOG2_H | ||
#define LLVM_LIBC_SRC_MATH_LOG2_H | ||
|
||
namespace __llvm_libc { | ||
|
||
double log2(double x); | ||
|
||
} // namespace __llvm_libc | ||
|
||
#endif // LLVM_LIBC_SRC_MATH_LOG2_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
//===-- Unittests for log2 ------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "src/__support/FPUtil/FPBits.h" | ||
#include "src/errno/libc_errno.h" | ||
#include "src/math/log2.h" | ||
#include "test/UnitTest/FPMatcher.h" | ||
#include "test/UnitTest/Test.h" | ||
#include "utils/MPFRWrapper/MPFRUtils.h" | ||
#include <math.h> | ||
|
||
#include <errno.h> | ||
#include <stdint.h> | ||
|
||
namespace mpfr = __llvm_libc::testing::mpfr; | ||
using __llvm_libc::testing::tlog; | ||
|
||
DECLARE_SPECIAL_CONSTANTS(double) | ||
|
||
TEST(LlvmLibcLog2Test, SpecialNumbers) { | ||
EXPECT_FP_EQ(aNaN, __llvm_libc::log2(aNaN)); | ||
EXPECT_FP_EQ(inf, __llvm_libc::log2(inf)); | ||
EXPECT_FP_IS_NAN_WITH_EXCEPTION(__llvm_libc::log2(neg_inf), FE_INVALID); | ||
EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, __llvm_libc::log2(0.0), FE_DIVBYZERO); | ||
EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, __llvm_libc::log2(-0.0), FE_DIVBYZERO); | ||
EXPECT_FP_IS_NAN_WITH_EXCEPTION(__llvm_libc::log2(-1.0), FE_INVALID); | ||
EXPECT_FP_EQ_ALL_ROUNDING(zero, __llvm_libc::log2(1.0)); | ||
} | ||
|
||
TEST(LlvmLibcLog2Test, TrickyInputs) { | ||
constexpr int N = 30; | ||
constexpr uint64_t INPUTS[N] = { | ||
0x3ff0000000000000, // x = 1.0 | ||
0x4024000000000000, // x = 10.0 | ||
0x4059000000000000, // x = 10^2 | ||
0x408f400000000000, // x = 10^3 | ||
0x40c3880000000000, // x = 10^4 | ||
0x40f86a0000000000, // x = 10^5 | ||
0x412e848000000000, // x = 10^6 | ||
0x416312d000000000, // x = 10^7 | ||
0x4197d78400000000, // x = 10^8 | ||
0x41cdcd6500000000, // x = 10^9 | ||
0x4202a05f20000000, // x = 10^10 | ||
0x42374876e8000000, // x = 10^11 | ||
0x426d1a94a2000000, // x = 10^12 | ||
0x42a2309ce5400000, // x = 10^13 | ||
0x42d6bcc41e900000, // x = 10^14 | ||
0x430c6bf526340000, // x = 10^15 | ||
0x4341c37937e08000, // x = 10^16 | ||
0x4376345785d8a000, // x = 10^17 | ||
0x43abc16d674ec800, // x = 10^18 | ||
0x43e158e460913d00, // x = 10^19 | ||
0x4415af1d78b58c40, // x = 10^20 | ||
0x444b1ae4d6e2ef50, // x = 10^21 | ||
0x4480f0cf064dd592, // x = 10^22 | ||
0x3fefffffffef06ad, 0x3fefde0f22c7d0eb, 0x225e7812faadb32f, | ||
0x3fee1076964c2903, 0x3fdfe93fff7fceb0, 0x3ff012631ad8df10, | ||
0x3fefbfdaa448ed98, | ||
}; | ||
for (int i = 0; i < N; ++i) { | ||
double x = double(FPBits(INPUTS[i])); | ||
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log2, x, | ||
__llvm_libc::log2(x), 0.5); | ||
} | ||
} | ||
|
||
TEST(LlvmLibcLog2Test, AllExponents) { | ||
double x = 0x1.0p-1074; | ||
for (int i = -1074; i < 1024; ++i, x *= 2.0) { | ||
ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log2, x, | ||
__llvm_libc::log2(x), 0.5); | ||
} | ||
} | ||
|
||
TEST(LlvmLibcLog2Test, InDoubleRange) { | ||
constexpr uint64_t COUNT = 1234561; | ||
constexpr uint64_t START = 0x3FD0'0000'0000'0000ULL; // 0.25 | ||
constexpr uint64_t STOP = 0x4010'0000'0000'0000ULL; // 4.0 | ||
// constexpr uint64_t START = 0x3FF0'0000'0000'0000ULL; // 1.0 | ||
// constexpr uint64_t STOP = 0x4000'0000'0000'0000ULL; // 2.0 | ||
constexpr uint64_t STEP = (STOP - START) / COUNT; | ||
|
||
auto test = [&](mpfr::RoundingMode rounding_mode) { | ||
mpfr::ForceRoundingMode __r(rounding_mode); | ||
uint64_t fails = 0; | ||
uint64_t count = 0; | ||
uint64_t cc = 0; | ||
double mx, mr = 0.0; | ||
double tol = 0.5; | ||
|
||
for (uint64_t i = 0, v = START; i <= COUNT; ++i, v += STEP) { | ||
double x = FPBits(v).get_val(); | ||
if (isnan(x) || isinf(x) || x < 0.0) | ||
continue; | ||
libc_errno = 0; | ||
double result = __llvm_libc::log2(x); | ||
++cc; | ||
if (isnan(result) || isinf(result)) | ||
continue; | ||
|
||
++count; | ||
// ASSERT_MPFR_MATCH(mpfr::Operation::Log2, x, result, 0.5); | ||
if (!EXPECT_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Log2, x, result, | ||
0.5, rounding_mode)) { | ||
++fails; | ||
while (!EXPECT_MPFR_MATCH_ROUNDING_SILENTLY( | ||
mpfr::Operation::Log2, x, result, tol, rounding_mode)) { | ||
mx = x; | ||
mr = result; | ||
tol *= 2.0; | ||
} | ||
} | ||
} | ||
tlog << " Log2 failed: " << fails << "/" << count << "/" << cc | ||
<< " tests.\n"; | ||
tlog << " Max ULPs is at most: " << static_cast<uint64_t>(tol) << ".\n"; | ||
if (fails) { | ||
EXPECT_MPFR_MATCH(mpfr::Operation::Log2, mx, mr, 0.5, rounding_mode); | ||
} | ||
}; | ||
|
||
tlog << " Test Rounding To Nearest...\n"; | ||
test(mpfr::RoundingMode::Nearest); | ||
|
||
tlog << " Test Rounding Downward...\n"; | ||
test(mpfr::RoundingMode::Downward); | ||
|
||
tlog << " Test Rounding Upward...\n"; | ||
test(mpfr::RoundingMode::Upward); | ||
|
||
tlog << " Test Rounding Toward Zero...\n"; | ||
test(mpfr::RoundingMode::TowardZero); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters