@@ -45,7 +45,7 @@ static constexpr fputil::ExceptValues<float, N_EXCEPTS_LO> EXP2M1F_EXCEPTS_LO =
45
45
{0xbcf3'a937U , 0xbca7'29efU , 0U , 1U , 1U },
46
46
}};
47
47
48
- static constexpr size_t N_EXCEPTS_HI = 2 ;
48
+ static constexpr size_t N_EXCEPTS_HI = 3 ;
49
49
50
50
static constexpr fputil::ExceptValues<float , N_EXCEPTS_HI> EXP2M1F_EXCEPTS_HI =
51
51
{{
@@ -54,6 +54,8 @@ static constexpr fputil::ExceptValues<float, N_EXCEPTS_HI> EXP2M1F_EXCEPTS_HI =
54
54
{0x3f0b'54b9U , 0x3eea'a2d9U , 1U , 0U , 0U },
55
55
// x = -0x1.9f12acp-5, exp2m1f(x) = -0x1.1ab68cp-5 (RZ)
56
56
{0xbd4f'8956U , 0xbd0d'5b46U , 0U , 1U , 0U },
57
+ // x = -0x1.de7b9cp-5, exp2m1f(x) = -0x1.4508f4p-5 (RZ)
58
+ {0xbd6f'3dceU , 0xbd22'847aU , 0U , 1U , 1U },
57
59
}};
58
60
59
61
LLVM_LIBC_FUNCTION (float , exp2m1f, (float x)) {
@@ -66,7 +68,7 @@ LLVM_LIBC_FUNCTION(float, exp2m1f, (float x)) {
66
68
// When |x| >= 128, or x is nan, or |x| <= 2^-5
67
69
if (LIBC_UNLIKELY (x_abs >= 0x4300'0000U || x_abs <= 0x3d00'0000U )) {
68
70
// |x| <= 2^-5
69
- if (x_abs <= 0x3d00'0000 ) {
71
+ if (x_abs <= 0x3d00'0000U ) {
70
72
if (auto r = EXP2M1F_EXCEPTS_LO.lookup (x_u); LIBC_UNLIKELY (r.has_value ()))
71
73
return r.value ();
72
74
@@ -147,17 +149,17 @@ LLVM_LIBC_FUNCTION(float, exp2m1f, (float x)) {
147
149
kf = static_cast<float>(k);
148
150
#endif // LIBC_TARGET_CPU_HAS_NEAREST_INT
149
151
150
- // dx = lo = x - (hi + mid) = x - kf * 2^(-5)
151
- double dx = fputil::multiply_add(-0x1.0p-5f, kf, x);
152
+ // lo = x - (hi + mid) = x - kf * 2^(-5)
153
+ double lo = fputil::multiply_add(-0x1.0p-5f, kf, x);
152
154
153
155
// hi = floor(kf * 2^(-4))
154
- // exp_hi = shift hi to the exponent field of double precision.
155
- int64_t exp_hi =
156
+ // exp2_hi = shift hi to the exponent field of double precision.
157
+ int64_t exp2_hi =
156
158
static_cast<int64_t>(static_cast<uint64_t>(k >> ExpBase::MID_BITS)
157
159
<< fputil::FPBits<double>::FRACTION_LEN);
158
160
// mh = 2^hi * 2^mid
159
161
// mh_bits = bit field of mh
160
- int64_t mh_bits = ExpBase::EXP_2_MID[k & ExpBase::MID_MASK] + exp_hi ;
162
+ int64_t mh_bits = ExpBase::EXP_2_MID[k & ExpBase::MID_MASK] + exp2_hi ;
161
163
double mh = fputil::FPBits<double>(static_cast<uint64_t>(mh_bits)).get_val();
162
164
163
165
// Degree-4 polynomial approximating (2^x - 1)/x generated by Sollya with:
@@ -166,16 +168,15 @@ LLVM_LIBC_FUNCTION(float, exp2m1f, (float x)) {
166
168
constexpr double COEFFS[5] = {0x1.62e42fefa39efp-1, 0x1.ebfbdff8131c4p-3,
167
169
0x1.c6b08d7061695p-5, 0x1.3b2b1bee74b2ap-7,
168
170
0x1.5d88091198529p-10};
169
- double dx_sq = dx * dx;
170
- double c1 = fputil::multiply_add(dx, COEFFS[0], 1.0);
171
- double c2 = fputil::multiply_add(dx, COEFFS[2], COEFFS[1]);
172
- double c3 = fputil::multiply_add(dx, COEFFS[4], COEFFS[3]);
173
- double p = fputil::multiply_add(dx_sq, c3, c2);
174
- // 2^x = 2^(hi + mid + lo)
175
- // = 2^(hi + mid) * 2^lo
176
- // ~ mh * (1 + lo * P(lo))
177
- // = mh + (mh*lo) * P(lo)
178
- double exp2_lo = fputil::multiply_add(p, dx_sq, c1);
171
+ double lo_sq = lo * lo;
172
+ double c1 = fputil::multiply_add(lo, COEFFS[0], 1.0);
173
+ double c2 = fputil::multiply_add(lo, COEFFS[2], COEFFS[1]);
174
+ double c3 = fputil::multiply_add(lo, COEFFS[4], COEFFS[3]);
175
+ double exp2_lo = fputil::polyeval(lo_sq, c1, c2, c3);
176
+ // 2^x - 1 = 2^(hi + mid + lo) - 1
177
+ // = 2^(hi + mid) * 2^lo - 1
178
+ // ~ mh * (1 + lo * P(lo)) - 1
179
+ // = mh * exp2_lo - 1
179
180
return static_cast<float>(fputil::multiply_add(exp2_lo, mh, -1.0));
180
181
}
181
182
0 commit comments