@@ -133,29 +133,6 @@ struct exp_b_reduc_t {
133
133
double lo;
134
134
};
135
135
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
-
159
136
// The function correctly calculates b^x value with at least float precision
160
137
// in a limited range.
161
138
// Range reduction:
@@ -321,12 +298,12 @@ LIBC_INLINE static double log2_eval(double x) {
321
298
}
322
299
323
300
// 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) {
325
302
// 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 >;
327
304
FPBits xbits (x);
328
305
329
- T ex = static_cast <T >(xbits.get_exponent ());
306
+ float ex = static_cast <float >(xbits.get_exponent ());
330
307
// p1 is the leading 7 bits of mx, i.e.
331
308
// p1 * 2^(-7) <= m_x < (p1 + 1) * 2^(-7).
332
309
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) {
335
312
xbits.set_uintval (xbits.uintval () & (FPBits::FRACTION_MASK >> 7 ));
336
313
xbits.set_biased_exponent (FPBits::EXP_BIAS);
337
314
// 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];
341
316
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 };
343
321
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;
353
323
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 ]);
357
327
358
- T p = fputil::polyeval (dx2, dx, c1, c2, c3);
328
+ float p = fputil::polyeval (dx2, dx, c1, c2, c3);
359
329
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;
364
372
}
365
373
366
374
// Rounding tests for 2^hi * (mid + lo) when the output might be denormal. We
0 commit comments