Simplified clinger.

This commit is contained in:
Daniel Lemire 2022-11-03 18:51:37 -04:00
parent c56e595438
commit e958ff4269
4 changed files with 67 additions and 27 deletions

View File

@ -221,6 +221,55 @@ constexpr static double powers_of_ten_double[] = {
constexpr static float powers_of_ten_float[] = {1e0, 1e1, 1e2, 1e3, 1e4, 1e5, constexpr static float powers_of_ten_float[] = {1e0, 1e1, 1e2, 1e3, 1e4, 1e5,
1e6, 1e7, 1e8, 1e9, 1e10}; 1e6, 1e7, 1e8, 1e9, 1e10};
// Largest integer value v so that (5**index * v) <= 1<<53.
// 0x10000000000000 == 1 << 53
constexpr static uint64_t max_mantissa_double[] = {
0x10000000000000,
0x10000000000000 / 5,
0x10000000000000 / (5 * 5),
0x10000000000000 / (5 * 5 * 5),
0x10000000000000 / (5 * 5 * 5 * 5),
0x10000000000000 / (5 * 5 * 5 * 5 * 5),
0x10000000000000 / (5 * 5 * 5 * 5 * 5 * 5),
0x10000000000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5),
0x10000000000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5),
0x10000000000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5),
0x10000000000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5),
0x10000000000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5),
0x10000000000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5),
0x10000000000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5),
0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5),
0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5),
0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5),
0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5),
0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 *
5),
0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 *
5 * 5),
0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 *
5 * 5 * 5),
0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 *
5 * 5 * 5 * 5),
0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 *
5 * 5 * 5 * 5 * 5),
0x10000000000000 / (uint64_t(5) * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 *
5 * 5 * 5 * 5 * 5 * 5)};
// Largest integer value v so that (5**index * v) <= 1<<24.
// 0x1000000 == 1<<24
constexpr static uint64_t max_mantissa_float[] = {
0x1000000,
0x1000000 / 5,
0x1000000 / (5 * 5),
0x1000000 / (5 * 5 * 5),
0x1000000 / (5 * 5 * 5 * 5),
0x1000000 / (5 * 5 * 5 * 5 * 5),
0x1000000 / (5 * 5 * 5 * 5 * 5 * 5),
0x1000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5),
0x1000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5),
0x1000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5),
0x1000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5),
0x1000000 / (5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5)};
template <typename T> struct binary_format { template <typename T> struct binary_format {
using equiv_uint = typename std::conditional<sizeof(T) == 4, uint32_t, uint64_t>::type; using equiv_uint = typename std::conditional<sizeof(T) == 4, uint32_t, uint64_t>::type;
@ -228,11 +277,10 @@ template <typename T> struct binary_format {
static inline constexpr int minimum_exponent(); static inline constexpr int minimum_exponent();
static inline constexpr int infinite_power(); static inline constexpr int infinite_power();
static inline constexpr int sign_index(); static inline constexpr int sign_index();
static inline constexpr int min_exponent_fast_path();
static inline constexpr int max_exponent_fast_path(); static inline constexpr int max_exponent_fast_path();
static inline constexpr int max_exponent_round_to_even(); static inline constexpr int max_exponent_round_to_even();
static inline constexpr int min_exponent_round_to_even(); static inline constexpr int min_exponent_round_to_even();
static inline constexpr uint64_t max_mantissa_fast_path(); static inline constexpr uint64_t max_mantissa_fast_path(int64_t power);
static inline constexpr int largest_power_of_ten(); static inline constexpr int largest_power_of_ten();
static inline constexpr int smallest_power_of_ten(); static inline constexpr int smallest_power_of_ten();
static inline constexpr T exact_power_of_ten(int64_t power); static inline constexpr T exact_power_of_ten(int64_t power);
@ -282,21 +330,6 @@ template <> inline constexpr int binary_format<float>::infinite_power() {
template <> inline constexpr int binary_format<double>::sign_index() { return 63; } template <> inline constexpr int binary_format<double>::sign_index() { return 63; }
template <> inline constexpr int binary_format<float>::sign_index() { return 31; } template <> inline constexpr int binary_format<float>::sign_index() { return 31; }
template <> inline constexpr int binary_format<double>::min_exponent_fast_path() {
#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
return 0;
#else
return -22;
#endif
}
template <> inline constexpr int binary_format<float>::min_exponent_fast_path() {
#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
return 0;
#else
return -10;
#endif
}
template <> inline constexpr int binary_format<double>::max_exponent_fast_path() { template <> inline constexpr int binary_format<double>::max_exponent_fast_path() {
return 22; return 22;
} }
@ -304,11 +337,17 @@ template <> inline constexpr int binary_format<float>::max_exponent_fast_path()
return 10; return 10;
} }
template <> inline constexpr uint64_t binary_format<double>::max_mantissa_fast_path() { template <> inline constexpr uint64_t binary_format<double>::max_mantissa_fast_path(int64_t power) {
return uint64_t(2) << mantissa_explicit_bits(); // caller is responsible to ensure that
// power >= 0 && power <= 22
//
return max_mantissa_double[power];
} }
template <> inline constexpr uint64_t binary_format<float>::max_mantissa_fast_path() { template <> inline constexpr uint64_t binary_format<float>::max_mantissa_fast_path(int64_t power) {
return uint64_t(2) << mantissa_explicit_bits(); // caller is responsible to ensure that
// power >= 0 && power <= 10
//
return max_mantissa_float[power];
} }
template <> template <>

View File

@ -87,11 +87,10 @@ from_chars_result from_chars_advanced(const char *first, const char *last,
} }
answer.ec = std::errc(); // be optimistic answer.ec = std::errc(); // be optimistic
answer.ptr = pns.lastmatch; answer.ptr = pns.lastmatch;
// Next is Clinger's fast path. // Next is a modified Clinger's fast path, inspired by Jakub Jelínek's proposal
if (binary_format<T>::min_exponent_fast_path() <= pns.exponent && pns.exponent <= binary_format<T>::max_exponent_fast_path() && pns.mantissa <=binary_format<T>::max_mantissa_fast_path() && !pns.too_many_digits) { if (pns.exponent >= 0 && pns.exponent <= binary_format<T>::max_exponent_fast_path() && pns.mantissa <=binary_format<T>::max_mantissa_fast_path(pns.exponent) && !pns.too_many_digits) {
value = T(pns.mantissa); value = T(pns.mantissa);
if (pns.exponent < 0) { value = value / binary_format<T>::exact_power_of_ten(-pns.exponent); } value = value * binary_format<T>::exact_power_of_ten(pns.exponent);
else { value = value * binary_format<T>::exact_power_of_ten(pns.exponent); }
if (pns.negative) { value = -value; } if (pns.negative) { value = -value; }
return answer; return answer;
} }

View File

@ -56,6 +56,8 @@ endfunction(fast_float_add_cpp_test)
fast_float_add_cpp_test(example_test) fast_float_add_cpp_test(example_test)
fast_float_add_cpp_test(example_comma_test) fast_float_add_cpp_test(example_comma_test)
fast_float_add_cpp_test(basictest) fast_float_add_cpp_test(basictest)
target_compile_features(basictest PRIVATE cxx_std_17)
fast_float_add_cpp_test(long_test) fast_float_add_cpp_test(long_test)
fast_float_add_cpp_test(powersoffive_hardround) fast_float_add_cpp_test(powersoffive_hardround)
fast_float_add_cpp_test(string_test) fast_float_add_cpp_test(string_test)