Skip to content

Commit a3b6177

Browse files
committed
[libc][math] Fix log1p SEGV with large inputs when FTZ/DAZ flags are set.
1 parent bbcd352 commit a3b6177

File tree

2 files changed

+12
-9
lines changed

2 files changed

+12
-9
lines changed

libc/src/math/generic/log1p.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -822,7 +822,7 @@ constexpr Float128 BIG_COEFFS[4]{
822822
{Sign::NEG, -128, 0x80000000'00000000'00000000'00000000_u128},
823823
};
824824

825-
LIBC_INLINE double log1p_accurate(int e_x, int index,
825+
[[maybe_unused]] LIBC_INLINE double log1p_accurate(int e_x, int index,
826826
fputil::DoubleDouble m_x) {
827827
Float128 e_x_f128(static_cast<float>(e_x));
828828
Float128 sum = fputil::quick_mul(LOG_2, e_x_f128);
@@ -975,16 +975,16 @@ LLVM_LIBC_FUNCTION(double, log1p, (double x)) {
975975
double err_hi = ERR_HI[hi == 0.0];
976976

977977
// Scaling factior = 2^(-xh_bits.get_exponent())
978-
uint64_t s_u = (static_cast<uint64_t>(EXP_BIAS) << (FRACTION_LEN + 1)) -
979-
(x_u & FPBits_t::EXP_MASK);
980-
// When the exponent of x is 2^1023, its inverse, 2^(-1023), is subnormal.
981-
const double EXPONENT_CORRECTION[2] = {0.0, 0x1.0p-1023};
982-
double scaling = FPBits_t(s_u).get_val() + EXPONENT_CORRECTION[s_u == 0];
978+
int64_t s_u = static_cast<int64_t>(x_u & FPBits_t::EXP_MASK) -
979+
(static_cast<int64_t>(EXP_BIAS) << FRACTION_LEN);
983980
// Normalize arguments:
984981
// 1 <= m_dd.hi < 2
985982
// |m_dd.lo| < 2^-52.
986983
// This is exact.
987-
fputil::DoubleDouble m_dd{scaling * x_dd.lo, scaling * x_dd.hi};
984+
uint64_t m_hi = static_cast<uint64_t>(static_cast<int64_t>(x_u) - s_u);
985+
uint64_t m_lo = (x_dd.lo != 0.0) ? FPBits_t(x_dd.lo).uintval() :
986+
static_cast<uint64_t>(cpp::bit_cast<int64_t>(x_dd.lo) - s_u);
987+
fputil::DoubleDouble m_dd{FPBits_t(m_lo).get_val(), FPBits_t(m_hi).get_val()};
988988

989989
// Perform range reduction:
990990
// r * m - 1 = r * (m_dd.hi + m_dd.lo) - 1

libc/test/src/math/smoke/log1p_test.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
#include "test/UnitTest/FPMatcher.h"
1414
#include "test/UnitTest/Test.h"
1515

16-
#include <stdint.h>
17-
1816
using LlvmLibcLog1pTest = LIBC_NAMESPACE::testing::FPTest<double>;
1917

2018
TEST_F(LlvmLibcLog1pTest, SpecialNumbers) {
@@ -26,6 +24,8 @@ TEST_F(LlvmLibcLog1pTest, SpecialNumbers) {
2624
EXPECT_FP_EQ(neg_zero, LIBC_NAMESPACE::log1p(-0.0));
2725
EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, LIBC_NAMESPACE::log1p(-1.0),
2826
FE_DIVBYZERO);
27+
28+
EXPECT_FP_EQ(0x1.62c829bf8fd9dp9, LIBC_NAMESPACE::log1p(0x1.9b536cac3a09dp1023));
2929
}
3030

3131
#ifdef LIBC_TEST_FTZ_DAZ
@@ -36,18 +36,21 @@ TEST_F(LlvmLibcLog1pTest, FTZMode) {
3636
ModifyMXCSR mxcsr(FTZ);
3737

3838
EXPECT_FP_EQ(0.0, LIBC_NAMESPACE::log1p(min_denormal));
39+
EXPECT_FP_EQ(0x1.62c829bf8fd9dp9, LIBC_NAMESPACE::log1p(0x1.9b536cac3a09dp1023));
3940
}
4041

4142
TEST_F(LlvmLibcLog1pTest, DAZMode) {
4243
ModifyMXCSR mxcsr(DAZ);
4344

4445
EXPECT_FP_EQ(0.0, LIBC_NAMESPACE::log1p(min_denormal));
46+
EXPECT_FP_EQ(0x1.62c829bf8fd9dp9, LIBC_NAMESPACE::log1p(0x1.9b536cac3a09dp1023));
4547
}
4648

4749
TEST_F(LlvmLibcLog1pTest, FTZDAZMode) {
4850
ModifyMXCSR mxcsr(FTZ | DAZ);
4951

5052
EXPECT_FP_EQ(0.0, LIBC_NAMESPACE::log1p(min_denormal));
53+
EXPECT_FP_EQ(0x1.62c829bf8fd9dp9, LIBC_NAMESPACE::log1p(0x1.9b536cac3a09dp1023));
5154
}
5255

5356
#endif

0 commit comments

Comments
 (0)