mirror of
https://github.com/fastfloat/fast_float.git
synced 2025-12-06 16:56:57 +08:00
Merge pull request #150 from fastfloat/dlemire/simplified_clinger
Simplified Clinger's fast path for increased portability
This commit is contained in:
commit
662497742f
@ -220,6 +220,50 @@ constexpr static double powers_of_ten_double[] = {
|
|||||||
1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};
|
1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};
|
||||||
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};
|
||||||
|
// used for max_mantissa_double and max_mantissa_float
|
||||||
|
constexpr uint64_t constant_55555 = 5 * 5 * 5 * 5 * 5;
|
||||||
|
// 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 / (constant_55555),
|
||||||
|
0x10000000000000 / (constant_55555 * 5),
|
||||||
|
0x10000000000000 / (constant_55555 * 5 * 5),
|
||||||
|
0x10000000000000 / (constant_55555 * 5 * 5 * 5),
|
||||||
|
0x10000000000000 / (constant_55555 * 5 * 5 * 5 * 5),
|
||||||
|
0x10000000000000 / (constant_55555 * constant_55555),
|
||||||
|
0x10000000000000 / (constant_55555 * constant_55555 * 5),
|
||||||
|
0x10000000000000 / (constant_55555 * constant_55555 * 5 * 5),
|
||||||
|
0x10000000000000 / (constant_55555 * constant_55555 * 5 * 5 * 5),
|
||||||
|
0x10000000000000 / (constant_55555 * constant_55555 * constant_55555),
|
||||||
|
0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * 5),
|
||||||
|
0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * 5 * 5),
|
||||||
|
0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * 5 * 5 * 5),
|
||||||
|
0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * 5 * 5 * 5 * 5),
|
||||||
|
0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * constant_55555),
|
||||||
|
0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * 5),
|
||||||
|
0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * 5 * 5),
|
||||||
|
0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * 5 * 5 * 5),
|
||||||
|
0x10000000000000 / (constant_55555 * constant_55555 * constant_55555 * constant_55555 * 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 / (constant_55555),
|
||||||
|
0x1000000 / (constant_55555 * 5),
|
||||||
|
0x1000000 / (constant_55555 * 5 * 5),
|
||||||
|
0x1000000 / (constant_55555 * 5 * 5 * 5),
|
||||||
|
0x1000000 / (constant_55555 * 5 * 5 * 5 * 5),
|
||||||
|
0x1000000 / (constant_55555 * constant_55555),
|
||||||
|
0x1000000 / (constant_55555 * constant_55555 * 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 +272,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 +325,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 +332,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 <>
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user