diff options
Diffstat (limited to 'libstdc++-v3/src/c++17/fast_float/fast_float.h')
-rw-r--r-- | libstdc++-v3/src/c++17/fast_float/fast_float.h | 173 |
1 files changed, 111 insertions, 62 deletions
diff --git a/libstdc++-v3/src/c++17/fast_float/fast_float.h b/libstdc++-v3/src/c++17/fast_float/fast_float.h index 31fb88b..5da55e2 100644 --- a/libstdc++-v3/src/c++17/fast_float/fast_float.h +++ b/libstdc++-v3/src/c++17/fast_float/fast_float.h @@ -74,7 +74,7 @@ struct parse_options { * Like the C++17 standard, the `fast_float::from_chars` functions take an optional last argument of * the type `fast_float::chars_format`. It is a bitset value: we check whether * `fmt & fast_float::chars_format::fixed` and `fmt & fast_float::chars_format::scientific` are set - * to determine whether we allowe the fixed point and scientific notation respectively. + * to determine whether we allow the fixed point and scientific notation respectively. * The default is `fast_float::chars_format::general` which allows both `fixed` and `scientific`. */ template<typename T> @@ -98,12 +98,11 @@ from_chars_result from_chars_advanced(const char *first, const char *last, || defined(__amd64) || defined(__aarch64__) || defined(_M_ARM64) \ || defined(__MINGW64__) \ || defined(__s390x__) \ - || (defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || defined(__PPC64LE__)) \ - || defined(__EMSCRIPTEN__)) + || (defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || defined(__PPC64LE__)) ) #define FASTFLOAT_64BIT #elif (defined(__i386) || defined(__i386__) || defined(_M_IX86) \ || defined(__arm__) || defined(_M_ARM) \ - || defined(__MINGW32__)) + || defined(__MINGW32__) || defined(__EMSCRIPTEN__)) #define FASTFLOAT_32BIT #else // Need to check incrementally, since SIZE_MAX is a size_t, avoid overflow. @@ -128,7 +127,7 @@ from_chars_result from_chars_advanced(const char *first, const char *last, #define FASTFLOAT_VISUAL_STUDIO 1 #endif -#ifdef __BYTE_ORDER__ +#if defined __BYTE_ORDER__ && defined __ORDER_BIG_ENDIAN__ #define FASTFLOAT_IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) #elif defined _WIN32 #define FASTFLOAT_IS_BIG_ENDIAN 0 @@ -271,8 +270,9 @@ fastfloat_really_inline uint64_t _umul128(uint64_t ab, uint64_t cd, fastfloat_really_inline value128 full_multiplication(uint64_t a, uint64_t b) { value128 answer; -#ifdef _M_ARM64 +#if defined(_M_ARM64) && !defined(__MINGW32__) // ARM64 has native support for 64-bit multiplications, no need to emulate + // But MinGW on ARM64 doesn't have native support for 64-bit multiplications answer.high = __umulh(a, b); answer.low = a * b; #elif defined(FASTFLOAT_32BIT) || (defined(_WIN64) && !defined(__clang__)) @@ -307,21 +307,69 @@ constexpr static double powers_of_ten_double[] = { 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22}; constexpr static float powers_of_ten_float[] = {1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 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 { + using equiv_uint = typename std::conditional<sizeof(T) == 4, uint32_t, uint64_t>::type; + static inline constexpr int mantissa_explicit_bits(); static inline constexpr int minimum_exponent(); static inline constexpr int infinite_power(); 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_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 smallest_power_of_ten(); static inline constexpr T exact_power_of_ten(int64_t power); static inline constexpr size_t max_digits(); + static inline constexpr equiv_uint exponent_mask(); + static inline constexpr equiv_uint mantissa_mask(); + static inline constexpr equiv_uint hidden_bit_mask(); }; template <> inline constexpr int binary_format<double>::mantissa_explicit_bits() { @@ -364,21 +412,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<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() { return 22; } @@ -386,11 +419,17 @@ template <> inline constexpr int binary_format<float>::max_exponent_fast_path() return 10; } -template <> inline constexpr uint64_t binary_format<double>::max_mantissa_fast_path() { - return uint64_t(2) << mantissa_explicit_bits(); +template <> inline constexpr uint64_t binary_format<double>::max_mantissa_fast_path(int64_t power) { + // 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() { - return uint64_t(2) << mantissa_explicit_bits(); +template <> inline constexpr uint64_t binary_format<float>::max_mantissa_fast_path(int64_t power) { + // caller is responsible to ensure that + // power >= 0 && power <= 10 + // + return max_mantissa_float[power]; } template <> @@ -429,6 +468,33 @@ template <> inline constexpr size_t binary_format<float>::max_digits() { return 114; } +template <> inline constexpr binary_format<float>::equiv_uint + binary_format<float>::exponent_mask() { + return 0x7F800000; +} +template <> inline constexpr binary_format<double>::equiv_uint + binary_format<double>::exponent_mask() { + return 0x7FF0000000000000; +} + +template <> inline constexpr binary_format<float>::equiv_uint + binary_format<float>::mantissa_mask() { + return 0x007FFFFF; +} +template <> inline constexpr binary_format<double>::equiv_uint + binary_format<double>::mantissa_mask() { + return 0x000FFFFFFFFFFFFF; +} + +template <> inline constexpr binary_format<float>::equiv_uint + binary_format<float>::hidden_bit_mask() { + return 0x00800000; +} +template <> inline constexpr binary_format<double>::equiv_uint + binary_format<double>::hidden_bit_mask() { + return 0x0010000000000000; +} + template<typename T> fastfloat_really_inline void to_float(bool negative, adjusted_mantissa am, T &value) { uint64_t word = am.mantissa; @@ -2410,40 +2476,24 @@ fastfloat_really_inline int32_t scientific_exponent(parsed_number_string& num) n // this converts a native floating-point number to an extended-precision float. template <typename T> fastfloat_really_inline adjusted_mantissa to_extended(T value) noexcept { + using equiv_uint = typename binary_format<T>::equiv_uint; + constexpr equiv_uint exponent_mask = binary_format<T>::exponent_mask(); + constexpr equiv_uint mantissa_mask = binary_format<T>::mantissa_mask(); + constexpr equiv_uint hidden_bit_mask = binary_format<T>::hidden_bit_mask(); + adjusted_mantissa am; int32_t bias = binary_format<T>::mantissa_explicit_bits() - binary_format<T>::minimum_exponent(); - if (std::is_same<T, float>::value) { - constexpr uint32_t exponent_mask = 0x7F800000; - constexpr uint32_t mantissa_mask = 0x007FFFFF; - constexpr uint64_t hidden_bit_mask = 0x00800000; - uint32_t bits; - ::memcpy(&bits, &value, sizeof(T)); - if ((bits & exponent_mask) == 0) { - // denormal - am.power2 = 1 - bias; - am.mantissa = bits & mantissa_mask; - } else { - // normal - am.power2 = int32_t((bits & exponent_mask) >> binary_format<T>::mantissa_explicit_bits()); - am.power2 -= bias; - am.mantissa = (bits & mantissa_mask) | hidden_bit_mask; - } + equiv_uint bits; + ::memcpy(&bits, &value, sizeof(T)); + if ((bits & exponent_mask) == 0) { + // denormal + am.power2 = 1 - bias; + am.mantissa = bits & mantissa_mask; } else { - constexpr uint64_t exponent_mask = 0x7FF0000000000000; - constexpr uint64_t mantissa_mask = 0x000FFFFFFFFFFFFF; - constexpr uint64_t hidden_bit_mask = 0x0010000000000000; - uint64_t bits; - ::memcpy(&bits, &value, sizeof(T)); - if ((bits & exponent_mask) == 0) { - // denormal - am.power2 = 1 - bias; - am.mantissa = bits & mantissa_mask; - } else { - // normal - am.power2 = int32_t((bits & exponent_mask) >> binary_format<T>::mantissa_explicit_bits()); - am.power2 -= bias; - am.mantissa = (bits & mantissa_mask) | hidden_bit_mask; - } + // normal + am.power2 = int32_t((bits & exponent_mask) >> binary_format<T>::mantissa_explicit_bits()); + am.power2 -= bias; + am.mantissa = (bits & mantissa_mask) | hidden_bit_mask; } return am; @@ -2869,11 +2919,10 @@ from_chars_result from_chars_advanced(const char *first, const char *last, } answer.ec = std::errc(); // be optimistic answer.ptr = pns.lastmatch; - // Next is Clinger's fast path. - 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) { + // Next is a modified Clinger's fast path, inspired by Jakub JelĂnek's proposal + 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); - if (pns.exponent < 0) { value = value / binary_format<T>::exact_power_of_ten(-pns.exponent); } - else { value = value * binary_format<T>::exact_power_of_ten(pns.exponent); } + value = value * binary_format<T>::exact_power_of_ten(pns.exponent); if (pns.negative) { value = -value; } return answer; } |