From dad07cc054bcb48f416a3db45364d0faac4a66da Mon Sep 17 00:00:00 2001 From: IRainman Date: Mon, 29 Dec 2025 16:17:44 +0300 Subject: [PATCH] initialization cleanup and improve caches usage. --- include/fast_float/ascii_number.h | 13 ++++++++----- include/fast_float/decimal_to_binary.h | 14 ++++++++++---- include/fast_float/float_common.h | 10 +++++----- include/fast_float/parse_number.h | 5 +++-- 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/include/fast_float/ascii_number.h b/include/fast_float/ascii_number.h index 4fe726b..e999bcb 100644 --- a/include/fast_float/ascii_number.h +++ b/include/fast_float/ascii_number.h @@ -259,17 +259,20 @@ enum class parse_error : uint_fast8_t { template struct parsed_number_string_t { am_mant_t mantissa{0}; - am_pow_t exponent{0}; - // contains the range of the significant digits - span integer{}; // non-nullable - span fraction{}; // nullable - UC const *lastmatch{nullptr}; + #ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN bool negative{false}; #endif bool invalid{false}; // be optimistic bool too_many_digits{false}; // be optimistic parse_error error{parse_error::no_error}; // be optimistic + + am_pow_t exponent{0}; + + // contains the range of the significant digits + span integer; // non-nullable + span fraction; // nullable + UC const *lastmatch; }; using byte_span = span; diff --git a/include/fast_float/decimal_to_binary.h b/include/fast_float/decimal_to_binary.h index a2a1481..1db1055 100644 --- a/include/fast_float/decimal_to_binary.h +++ b/include/fast_float/decimal_to_binary.h @@ -31,14 +31,16 @@ compute_product_approximation(am_pow_t q, am_mant_t w) noexcept { constexpr uint64_t precision_mask = (bit_precision < 64) ? (uint64_t(0xFFFFFFFFFFFFFFFF) >> bit_precision) : uint64_t(0xFFFFFFFFFFFFFFFF); + if ((firstproduct.high & precision_mask) == precision_mask) { // could further guard with (lower + w < lower) // regarding the second product, we only need secondproduct.high, but our // expectation is that the compiler will optimize this extra work away if // needed. - value128 secondproduct = + value128 const secondproduct = full_multiplication(w, powers::power_of_five_128[index + 1]); firstproduct.low += secondproduct.high; + if (secondproduct.high > firstproduct.low) { ++firstproduct.high; } @@ -62,7 +64,7 @@ namespace detail { * where * p = log(5**-q)/log(2) = -q * log(5)/log(2) */ -constexpr fastfloat_really_inline am_pow_t power(am_pow_t q) noexcept { +constexpr fastfloat_really_inline am_pow_t power(am_pow_t const q) noexcept { return (((152170 + 65536) * q) >> 16) + 63; } } // namespace detail @@ -103,9 +105,9 @@ fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa compute_float(am_pow_t q, am_mant_t w) noexcept { adjusted_mantissa answer; if ((w == 0) || (q < binary::smallest_power_of_ten())) { + // we want to get zero: answer.power2 = 0; answer.mantissa = 0; - // result should be zero return answer; } if (q > binary::largest_power_of_ten()) { @@ -114,6 +116,7 @@ compute_float(am_pow_t q, am_mant_t w) noexcept { answer.mantissa = 0; return answer; } + // At this point in time q is in [powers::smallest_power_of_five, // powers::largest_power_of_five]. @@ -127,7 +130,7 @@ compute_float(am_pow_t q, am_mant_t w) noexcept { // 3. We might lose a bit due to the "upperbit" routine (result too small, // requiring a shift) - value128 product = + value128 const product = compute_product_approximation(q, w); // The computed 'product' is always sufficient. // Mathematical proof: @@ -141,6 +144,7 @@ compute_float(am_pow_t q, am_mant_t w) noexcept { auto const upperbit = static_cast(product.high >> 63); am_bits_t const shift = upperbit + 64 - binary::mantissa_explicit_bits() - 3; + // Shift right the mantissa to the correct position answer.mantissa = product.high >> shift; answer.power2 = detail::power(q) + upperbit - lz - binary::minimum_exponent(); @@ -192,6 +196,7 @@ compute_float(am_pow_t q, am_mant_t w) noexcept { } } + // Normal rounding answer.mantissa += (answer.mantissa & 1); // round up answer.mantissa >>= 1; if (answer.mantissa >= (am_mant_t(2) << binary::mantissa_explicit_bits())) { @@ -199,6 +204,7 @@ compute_float(am_pow_t q, am_mant_t w) noexcept { ++answer.power2; // undo previous addition } + // Check if we have infinity after computation answer.mantissa &= ~(am_mant_t(1) << binary::mantissa_explicit_bits()); if (answer.power2 >= binary::infinite_power()) { // infinity answer.power2 = binary::infinite_power(); diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index b23edc5..bbd2d71 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -110,10 +110,10 @@ template struct parse_options_t { /** Which number formats are accepted */ chars_format format; - /** The character used as decimal point for floats */ - UC decimal_point; /** The base used for integers */ base_t base; + /** The character used as decimal point for floats */ + UC decimal_point; }; using parse_options = parse_options_t; @@ -370,7 +370,7 @@ struct alignas(16) value128 { constexpr value128(uint64_t _low, uint64_t _high) noexcept : low(_low), high(_high) {} - constexpr value128() noexcept : low(0), high(0) {} + constexpr value128() noexcept {} }; /* Helper C++14 constexpr generic implementation of leading_zeroes for 64-bit */ @@ -415,7 +415,7 @@ leading_zeroes(uint64_t input_num) noexcept { } #ifdef FASTFLOAT_VISUAL_STUDIO #if defined(_M_X64) || defined(_M_ARM64) - unsigned long leading_zero = 0; + unsigned long leading_zero; // Search the mask data from most significant bit (MSB) // to least significant bit (LSB) for a set bit (1). _BitScanReverse64(&leading_zero, input_num); @@ -533,7 +533,7 @@ full_multiplication(uint64_t a, uint64_t b) noexcept { struct alignas(16) adjusted_mantissa { am_mant_t mantissa; am_pow_t power2; - adjusted_mantissa() noexcept = default; + adjusted_mantissa() noexcept {}; constexpr bool operator==(adjusted_mantissa const &o) const noexcept { return mantissa == o.mantissa && power2 == o.power2; diff --git a/include/fast_float/parse_number.h b/include/fast_float/parse_number.h index 913fc08..2c7e9d4 100644 --- a/include/fast_float/parse_number.h +++ b/include/fast_float/parse_number.h @@ -417,7 +417,7 @@ FASTFLOAT_CONSTEXPR20 integer_times_pow10(am_sign_mant_t const mantissa, am_pow_t const decimal_exponent) noexcept { #ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN - const bool is_negative = mantissa < 0; + const auto is_negative = mantissa < 0; const auto m = static_cast(is_negative ? -mantissa : mantissa); #else FASTFLOAT_ASSUME(mantissa >= 0); @@ -431,8 +431,9 @@ FASTFLOAT_CONSTEXPR20 value)) return value; - adjusted_mantissa am = + adjusted_mantissa const am = compute_float>(decimal_exponent, m); + to_float( #ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN is_negative,