@@ -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