Skip to content

Commit de65bbf

Browse files
committed
[libc] Update code.
1 parent 8e7d05d commit de65bbf

File tree

2 files changed

+56
-48
lines changed

2 files changed

+56
-48
lines changed

libc/src/math/generic/atanhf16.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ LLVM_LIBC_FUNCTION(float16, atanhf16, (float16 x)) {
9898
}
9999

100100
float xf = x;
101-
return fputil::cast<float16>(0.5 * log_eval((xf + 1.0f) / (xf - 1.0f)));
101+
return fputil::cast<float16>(0.5 * log_eval_f((xf + 1.0f) / (xf - 1.0f)));
102102
}
103103

104104
} // namespace LIBC_NAMESPACE_DECL

libc/src/math/generic/explogxf.h

Lines changed: 55 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -133,29 +133,6 @@ struct exp_b_reduc_t {
133133
double lo;
134134
};
135135

136-
// Coefficients for double (6th-degree minimax polynomial on [0, 2^-7]).
137-
// Minimax polynomial of log(1 + dx) generated by Sollya with:
138-
// > P = fpminimax(log(1 + x)/x, 6, [|D...|], [0, 2^-7]);
139-
static constexpr double LOG_COEFFS_DOUBLE[6] = {
140-
-0x1.ffffffffffffcp-2, 0x1.5555555552ddep-2, -0x1.ffffffefe562dp-3,
141-
0x1.9999817d3a50fp-3, -0x1.554317b3f67a5p-3, 0x1.1dc5c45e09c18p-3};
142-
143-
// Coefficients for float (6th-degree minimax polynomial on [0, 2^-7]).
144-
// Minimax polynomial of log(1 + dx) generated by Sollya with:
145-
// > P = fpminimax(log(1 + x)/x, 6, [|D...|], [0, 2^-7]);
146-
static constexpr float LOG_COEFFS_FLOAT[6] = {-0x1.fffffep-2f, 0x1.555556p-2f,
147-
-0x1.fffefep-3f, 0x1.99999ap-3f,
148-
-0x1.554318p-3f, 0x1.1dc5c4p-3f};
149-
150-
// log(2) in double precision.
151-
static constexpr double LOG2_DOUBLE = 0x1.62e42fefa39efp-1;
152-
153-
// log(2) in float precision.
154-
// Generated by Sollya with the following commands:
155-
// > display = hexadecimal;
156-
// > round(log(2), SG, RN);
157-
static constexpr float LOG2_FLOAT = 0x1.62e43p-1f;
158-
159136
// The function correctly calculates b^x value with at least float precision
160137
// in a limited range.
161138
// Range reduction:
@@ -321,12 +298,12 @@ LIBC_INLINE static double log2_eval(double x) {
321298
}
322299

323300
// x should be positive, normal finite value
324-
template <typename T> LIBC_INLINE static T log_eval(T x) {
301+
LIBC_INLINE static float log_eval_f(float x) {
325302
// For x = 2^ex * (1 + mx), logf(x) = ex * logf(2) + logf(1 + mx).
326-
using FPBits = fputil::FPBits<T>;
303+
using FPBits = fputil::FPBits<float>;
327304
FPBits xbits(x);
328305

329-
T ex = static_cast<T>(xbits.get_exponent());
306+
float ex = static_cast<float>(xbits.get_exponent());
330307
// p1 is the leading 7 bits of mx, i.e.
331308
// p1 * 2^(-7) <= m_x < (p1 + 1) * 2^(-7).
332309
int p1 = static_cast<int>(xbits.get_mantissa() >> (FPBits::FRACTION_LEN - 7));
@@ -335,32 +312,63 @@ template <typename T> LIBC_INLINE static T log_eval(T x) {
335312
xbits.set_uintval(xbits.uintval() & (FPBits::FRACTION_MASK >> 7));
336313
xbits.set_biased_exponent(FPBits::EXP_BIAS);
337314
// dx = (mx - p1*2^(-7)) / (1 + p1*2^(-7)).
338-
T dx = static_cast<T>(xbits.get_val() - 1.0) *
339-
(std::is_same<T, double>::value ? static_cast<T>(ONE_OVER_F[p1])
340-
: ONE_OVER_F_FLOAT[p1]);
315+
float dx = (xbits.get_val() - 1.0f) * ONE_OVER_F_FLOAT[p1];
341316

342-
T dx2 = dx * dx;
317+
// Minimax polynomial of log(1 + dx) generated by Sollya with:
318+
// > P = fpminimax(log(1 + x)/x, 6, [|D...|], [0, 2^-7]);
319+
const float COEFFS[6] = {-0x1.fffffep-2f, 0x1.555556p-2f, -0x1.fffefep-3f,
320+
0x1.99999ap-3f, -0x1.554318p-3f, 0x1.1dc5c4p-3f};
343321

344-
const T *coeffs = nullptr;
345-
T log2_val;
346-
if constexpr (std::is_same<T, double>::value) {
347-
coeffs = LOG_COEFFS_DOUBLE;
348-
log2_val = LOG2_DOUBLE;
349-
} else {
350-
coeffs = LOG_COEFFS_FLOAT;
351-
log2_val = LOG2_FLOAT;
352-
}
322+
float dx2 = dx * dx;
353323

354-
T c1 = fputil::multiply_add(dx, coeffs[1], coeffs[0]);
355-
T c2 = fputil::multiply_add(dx, coeffs[3], coeffs[2]);
356-
T c3 = fputil::multiply_add(dx, coeffs[5], coeffs[4]);
324+
float c1 = fputil::multiply_add(dx, COEFFS[1], COEFFS[0]);
325+
float c2 = fputil::multiply_add(dx, COEFFS[3], COEFFS[2]);
326+
float c3 = fputil::multiply_add(dx, COEFFS[5], COEFFS[4]);
357327

358-
T p = fputil::polyeval(dx2, dx, c1, c2, c3);
328+
float p = fputil::polyeval(dx2, dx, c1, c2, c3);
359329

360-
if constexpr (std::is_same<T, double>::value)
361-
return fputil::multiply_add(ex, log2_val, LOG_F[p1] + p);
362-
else
363-
return fputil::multiply_add(ex, log2_val, LOG_F_FLOAT[p1] + p);
330+
// Generated by Sollya with the following commands:
331+
// > display = hexadecimal;
332+
// > round(log(2), SG, RN);
333+
static constexpr float LOGF_2 = 0x1.62e43p-1f;
334+
335+
float result = fputil::multiply_add(ex, LOGF_2, LOG_F_FLOAT[p1] + p);
336+
return result;
337+
}
338+
339+
// x should be positive, normal finite value
340+
LIBC_INLINE static double log_eval(double x) {
341+
// For x = 2^ex * (1 + mx)
342+
// log(x) = ex * log(2) + log(1 + mx)
343+
using FPB = fputil::FPBits<double>;
344+
FPB bs(x);
345+
346+
double ex = static_cast<double>(bs.get_exponent());
347+
348+
// p1 is the leading 7 bits of mx, i.e.
349+
// p1 * 2^(-7) <= m_x < (p1 + 1) * 2^(-7).
350+
int p1 = static_cast<int>(bs.get_mantissa() >> (FPB::FRACTION_LEN - 7));
351+
352+
// Set bs to (1 + (mx - p1*2^(-7))
353+
bs.set_uintval(bs.uintval() & (FPB::FRACTION_MASK >> 7));
354+
bs.set_biased_exponent(FPB::EXP_BIAS);
355+
// dx = (mx - p1*2^(-7)) / (1 + p1*2^(-7)).
356+
double dx = (bs.get_val() - 1.0) * ONE_OVER_F[p1];
357+
358+
// Minimax polynomial of log(1 + dx) generated by Sollya with:
359+
// > P = fpminimax(log(1 + x)/x, 6, [|D...|], [0, 2^-7]);
360+
const double COEFFS[6] = {-0x1.ffffffffffffcp-2, 0x1.5555555552ddep-2,
361+
-0x1.ffffffefe562dp-3, 0x1.9999817d3a50fp-3,
362+
-0x1.554317b3f67a5p-3, 0x1.1dc5c45e09c18p-3};
363+
double dx2 = dx * dx;
364+
double c1 = fputil::multiply_add(dx, COEFFS[1], COEFFS[0]);
365+
double c2 = fputil::multiply_add(dx, COEFFS[3], COEFFS[2]);
366+
double c3 = fputil::multiply_add(dx, COEFFS[5], COEFFS[4]);
367+
368+
double p = fputil::polyeval(dx2, dx, c1, c2, c3);
369+
double result =
370+
fputil::multiply_add(ex, /*log(2)*/ 0x1.62e42fefa39efp-1, LOG_F[p1] + p);
371+
return result;
364372
}
365373

366374
// Rounding tests for 2^hi * (mid + lo) when the output might be denormal. We

0 commit comments

Comments
 (0)