From f1b7f493aaaf866dc24597ecc860c61789586e1a Mon Sep 17 00:00:00 2001 From: IRainman Date: Tue, 8 Apr 2025 18:23:27 +0300 Subject: [PATCH] after all sized checks is done I return the minimum registers size possible for the counter. Because the library only support 32 and 64 bit platform we only need 32 bit as a small counter. --- include/fast_float/ascii_number.h | 20 +++--- include/fast_float/bigint.h | 96 +++++++++++++------------- include/fast_float/decimal_to_binary.h | 2 +- include/fast_float/digit_comparison.h | 30 ++++---- include/fast_float/float_common.h | 17 ++--- 5 files changed, 83 insertions(+), 82 deletions(-) diff --git a/include/fast_float/ascii_number.h b/include/fast_float/ascii_number.h index 04a9e01..fcbbfe9 100644 --- a/include/fast_float/ascii_number.h +++ b/include/fast_float/ascii_number.h @@ -261,7 +261,7 @@ enum class parse_error { template struct parsed_number_string_t { uint64_t mantissa{0}; - int16_t exponent{0}; + int32_t exponent{0}; #ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN bool negative{false}; #endif @@ -338,8 +338,8 @@ parse_number_string(UC const *p, UC const *pend, ++p; } UC const *const end_of_integer_part = p; - uint16_t digit_count = uint16_t(end_of_integer_part - start_digits); - answer.integer = span(start_digits, size_t(digit_count)); + uint32_t digit_count = uint32_t(end_of_integer_part - start_digits); + answer.integer = span(start_digits, digit_count); #ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN FASTFLOAT_IF_CONSTEXPR17(basic_json_fmt) { // at least 1 digit in integer part, without leading zeros @@ -353,7 +353,7 @@ parse_number_string(UC const *p, UC const *pend, } #endif - int16_t exponent = 0; + int32_t exponent = 0; bool const has_decimal_point = (p != pend) && (*p == options.decimal_point); if (has_decimal_point) { ++p; @@ -367,8 +367,8 @@ parse_number_string(UC const *p, UC const *pend, i = i * 10 + digit; // in rare cases, this will overflow, but that's ok ++p; } - exponent = int16_t(before - p); - answer.fraction = span(before, size_t(p - before)); + exponent = int32_t(before - p); + answer.fraction = span(before, uint32_t(p - before)); digit_count -= exponent; } #ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN @@ -383,7 +383,7 @@ parse_number_string(UC const *p, UC const *pend, else if (digit_count == 0) { // we must have encountered at least one integer! return report_parse_error(p, parse_error::no_digits_in_mantissa); } - int16_t exp_number = 0; // explicit exponential part + int32_t exp_number = 0; // explicit exponential part if (p != pend && (uint64_t(options.format & chars_format::scientific) && ((UC('e') == *p) || (UC('E') == *p))) @@ -468,7 +468,7 @@ parse_number_string(UC const *p, UC const *pend, ++p; } if (i >= minimal_nineteen_digit_integer) { // We have a big integers - exponent = uint16_t(end_of_integer_part - p) + exp_number; + exponent = uint32_t(end_of_integer_part - p) + exp_number; } else { // We have a value with a fractional component. p = answer.fraction.ptr; UC const *frac_end = p + answer.fraction.len(); @@ -476,7 +476,7 @@ parse_number_string(UC const *p, UC const *pend, i = i * 10 + uint64_t(*p - UC('0')); ++p; } - exponent = uint16_t(answer.fraction.ptr - p) + exp_number; + exponent = uint32_t(answer.fraction.ptr - p) + exp_number; } // We have now corrected both exponent and i, to a truncated value } @@ -541,7 +541,7 @@ parse_int_string(UC const *p, UC const *pend, T &value, p++; } - uint8_t const digit_count = uint8_t(p - start_digits); + uint32_t const digit_count = uint32_t(p - start_digits); if (digit_count == 0) { if (has_leading_zeros) { diff --git a/include/fast_float/bigint.h b/include/fast_float/bigint.h index 4e3e06c..7a481b4 100644 --- a/include/fast_float/bigint.h +++ b/include/fast_float/bigint.h @@ -19,11 +19,11 @@ namespace fast_float { #if defined(FASTFLOAT_64BIT) && !defined(__sparc) #define FASTFLOAT_64BIT_LIMB 1 typedef uint64_t limb; -constexpr size_t limb_bits = 64; +constexpr uint32_t limb_bits = 64; #else #define FASTFLOAT_32BIT_LIMB typedef uint32_t limb; -constexpr size_t limb_bits = 32; +constexpr uint32_t limb_bits = 32; #endif typedef span limb_span; @@ -32,15 +32,15 @@ typedef span limb_span; // of bits required to store the largest bigint, which is // `log2(10**(digits + max_exp))`, or `log2(10**(767 + 342))`, or // ~3600 bits, so we round to 4000. -constexpr size_t bigint_bits = 4000; -constexpr size_t bigint_limbs = bigint_bits / limb_bits; +constexpr uint32_t bigint_bits = 4000; +constexpr uint32_t bigint_limbs = bigint_bits / limb_bits; // vector-like type that is allocated on the stack. the entire // buffer is pre-allocated, and only the length changes. -template struct stackvec { +template struct stackvec { limb data[size]; // we never need more than 150 limbs - uint8_t length{0}; + uint32_t length{0}; FASTFLOAT_CONSTEXPR20 stackvec() noexcept = default; stackvec(stackvec const &) = delete; @@ -53,38 +53,38 @@ template struct stackvec { FASTFLOAT_ASSERT(try_extend(s)); } - FASTFLOAT_CONSTEXPR14 limb &operator[](size_t index) noexcept { + FASTFLOAT_CONSTEXPR14 limb &operator[](uint32_t index) noexcept { FASTFLOAT_DEBUG_ASSERT(index < length); return data[index]; } - FASTFLOAT_CONSTEXPR14 const limb &operator[](size_t index) const noexcept { + FASTFLOAT_CONSTEXPR14 const limb &operator[](uint32_t index) const noexcept { FASTFLOAT_DEBUG_ASSERT(index < length); return data[index]; } // index from the end of the container - FASTFLOAT_CONSTEXPR14 const limb &rindex(size_t index) const noexcept { + FASTFLOAT_CONSTEXPR14 const limb &rindex(uint32_t index) const noexcept { FASTFLOAT_DEBUG_ASSERT(index < length); - size_t rindex = length - index - 1; + uint32_t rindex = length - index - 1; return data[rindex]; } // set the length, without bounds checking. - FASTFLOAT_CONSTEXPR14 void set_len(size_t len) noexcept { - length = uint8_t(len); + FASTFLOAT_CONSTEXPR14 void set_len(uint32_t len) noexcept { + length = len; } - constexpr uint8_t len() const noexcept { return length; } + constexpr uint32_t len() const noexcept { return length; } constexpr bool is_empty() const noexcept { return length == 0; } - constexpr uint8_t capacity() const noexcept { return size; } + constexpr uint32_t capacity() const noexcept { return size; } // append item to vector, without bounds checking FASTFLOAT_CONSTEXPR14 void push_unchecked(limb value) noexcept { data[length] = value; - length++; + ++length; } // append item to vector, returning if item was added @@ -118,9 +118,9 @@ template struct stackvec { // if the new size is longer than the vector, assign value to each // appended item. FASTFLOAT_CONSTEXPR20 - void resize_unchecked(size_t new_len, limb value) noexcept { + void resize_unchecked(uint32_t new_len, limb value) noexcept { if (new_len > len()) { - size_t count = new_len - len(); + uint32_t count = new_len - len(); limb *first = data + len(); limb *last = first + count; ::std::fill(first, last, value); @@ -131,7 +131,7 @@ template struct stackvec { } // try to resize the vector, returning if the vector was resized. - FASTFLOAT_CONSTEXPR20 bool try_resize(size_t new_len, limb value) noexcept { + FASTFLOAT_CONSTEXPR20 bool try_resize(uint32_t new_len, limb value) noexcept { if (new_len > capacity()) { return false; } else { @@ -143,12 +143,12 @@ template struct stackvec { // check if any limbs are non-zero after the given index. // this needs to be done in reverse order, since the index // is relative to the most significant limbs. - FASTFLOAT_CONSTEXPR14 bool nonzero(size_t index) const noexcept { + FASTFLOAT_CONSTEXPR14 bool nonzero(uint32_t index) const noexcept { while (index < len()) { if (rindex(index) != 0) { return true; } - index++; + ++index; } return false; } @@ -156,7 +156,7 @@ template struct stackvec { // normalize the big integer, so most-significant zero limbs are removed. FASTFLOAT_CONSTEXPR14 void normalize() noexcept { while (len() > 0 && rindex(0) == 0) { - length--; + --length; } } }; @@ -258,16 +258,16 @@ scalar_mul(limb x, limb y, limb &carry) noexcept { // add scalar value to bigint starting from offset. // used in grade school multiplication -template +template inline FASTFLOAT_CONSTEXPR20 bool small_add_from(stackvec &vec, limb y, - size_t start) noexcept { - size_t index = start; + uint32_t start) noexcept { + uint32_t index = start; limb carry = y; bool overflow; while (carry != 0 && index < vec.len()) { vec[index] = scalar_add(vec[index], carry, overflow); carry = limb(overflow); - index += 1; + ++index; } if (carry != 0) { FASTFLOAT_TRY(vec.try_push(carry)); @@ -276,18 +276,18 @@ inline FASTFLOAT_CONSTEXPR20 bool small_add_from(stackvec &vec, limb y, } // add scalar value to bigint. -template +template fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool small_add(stackvec &vec, limb y) noexcept { return small_add_from(vec, y, 0); } // multiply bigint by scalar value. -template +template inline FASTFLOAT_CONSTEXPR20 bool small_mul(stackvec &vec, limb y) noexcept { limb carry = 0; - for (size_t index = 0; index < vec.len(); index++) { + for (uint32_t index = 0; index != vec.len(); ++index) { vec[index] = scalar_mul(vec[index], y, carry); } if (carry != 0) { @@ -298,9 +298,9 @@ inline FASTFLOAT_CONSTEXPR20 bool small_mul(stackvec &vec, // add bigint to bigint starting from index. // used in grade school multiplication -template +template FASTFLOAT_CONSTEXPR20 bool large_add_from(stackvec &x, limb_span y, - size_t start) noexcept { + uint32_t start) noexcept { // the effective x buffer is from `xstart..x.len()`, so exit early // if we can't get that current range. if (x.len() < start || y.len() > x.len() - start) { @@ -308,7 +308,7 @@ FASTFLOAT_CONSTEXPR20 bool large_add_from(stackvec &x, limb_span y, } bool carry = false; - for (size_t index = 0; index < y.len(); index++) { + for (uint32_t index = 0; index < y.len(); ++index) { limb xi = x[index + start]; limb yi = y[index]; bool c1 = false; @@ -329,14 +329,14 @@ FASTFLOAT_CONSTEXPR20 bool large_add_from(stackvec &x, limb_span y, } // add bigint to bigint. -template +template fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool large_add_from(stackvec &x, limb_span y) noexcept { return large_add_from(x, y, 0); } // grade-school multiplication algorithm -template +template FASTFLOAT_CONSTEXPR20 bool long_mul(stackvec &x, limb_span y) noexcept { limb_span xs = limb_span(x.data, x.len()); stackvec z(xs); @@ -345,7 +345,7 @@ FASTFLOAT_CONSTEXPR20 bool long_mul(stackvec &x, limb_span y) noexcept { if (y.len() != 0) { limb y0 = y[0]; FASTFLOAT_TRY(small_mul(x, y0)); - for (size_t index = 1; index < y.len(); index++) { + for (uint32_t index = 1; index != y.len(); ++index) { limb yi = y[index]; stackvec zi; if (yi != 0) { @@ -364,7 +364,7 @@ FASTFLOAT_CONSTEXPR20 bool long_mul(stackvec &x, limb_span y) noexcept { } // grade-school multiplication algorithm -template +template FASTFLOAT_CONSTEXPR20 bool large_mul(stackvec &x, limb_span y) noexcept { if (y.len() == 1) { FASTFLOAT_TRY(small_mul(x, y[0])); @@ -493,7 +493,7 @@ struct bigint : pow5_tables<> { } else if (vec.len() < other.vec.len()) { return -1; } else { - for (size_t index = vec.len(); index > 0; index--) { + for (uint32_t index = vec.len(); index > 0; --index) { limb xi = vec[index - 1]; limb yi = other.vec[index - 1]; if (xi > yi) { @@ -508,7 +508,7 @@ struct bigint : pow5_tables<> { // shift left each limb n bits, carrying over to the new limb // returns true if we were able to shift all the digits. - FASTFLOAT_CONSTEXPR20 bool shl_bits(size_t n) noexcept { + FASTFLOAT_CONSTEXPR20 bool shl_bits(uint32_t n) noexcept { // Internally, for each item, we shift left by n, and add the previous // right shifted limb-bits. // For example, we transform (for u8) shifted left 2, to: @@ -517,10 +517,10 @@ struct bigint : pow5_tables<> { FASTFLOAT_DEBUG_ASSERT(n != 0); FASTFLOAT_DEBUG_ASSERT(n < sizeof(limb) * 8); - size_t const shl = n; - size_t const shr = limb_bits - shl; + uint32_t const shl = n; + uint32_t const shr = limb_bits - shl; limb prev = 0; - for (size_t index = 0; index < vec.len(); index++) { + for (uint32_t index = 0; index != vec.len(); ++index) { limb xi = vec[index]; vec[index] = (xi << shl) | (prev >> shr); prev = xi; @@ -534,7 +534,7 @@ struct bigint : pow5_tables<> { } // move the limbs left by `n` limbs. - FASTFLOAT_CONSTEXPR20 bool shl_limbs(size_t n) noexcept { + FASTFLOAT_CONSTEXPR20 bool shl_limbs(uint32_t n) noexcept { FASTFLOAT_DEBUG_ASSERT(n != 0); if (n + vec.len() > vec.capacity()) { return false; @@ -555,9 +555,9 @@ struct bigint : pow5_tables<> { } // move the limbs left by `n` bits. - FASTFLOAT_CONSTEXPR20 bool shl(size_t n) noexcept { - size_t const rem = n % limb_bits; - size_t const div = n / limb_bits; + FASTFLOAT_CONSTEXPR20 bool shl(uint32_t n) noexcept { + uint32_t const rem = n % limb_bits; + uint32_t const div = n / limb_bits; if (rem != 0) { FASTFLOAT_TRY(shl_bits(rem)); } @@ -605,11 +605,11 @@ struct bigint : pow5_tables<> { exp -= large_step; } #ifdef FASTFLOAT_64BIT_LIMB - uint8_t small_step = 27; - limb max_native = 7450580596923828125UL; + uint32_t const small_step = 27; + limb const max_native = 7450580596923828125UL; #else - uint8_t small_step = 13; - limb max_native = 1220703125U; + uint32_t const small_step = 13; + limb const max_native = 1220703125U; #endif while (exp >= small_step) { FASTFLOAT_TRY(small_mul(vec, max_native)); diff --git a/include/fast_float/decimal_to_binary.h b/include/fast_float/decimal_to_binary.h index cdff846..2255716 100644 --- a/include/fast_float/decimal_to_binary.h +++ b/include/fast_float/decimal_to_binary.h @@ -17,7 +17,7 @@ namespace fast_float { // most significant bits and the low part corresponding to the least significant // bits. // -template +template fastfloat_really_inline FASTFLOAT_CONSTEXPR20 value128 compute_product_approximation(int64_t q, uint64_t w) noexcept { int const index = 2 * int(q - powers::smallest_power_of_five); diff --git a/include/fast_float/digit_comparison.h b/include/fast_float/digit_comparison.h index 6229653..ad62f73 100644 --- a/include/fast_float/digit_comparison.h +++ b/include/fast_float/digit_comparison.h @@ -39,10 +39,10 @@ constexpr static uint64_t powers_of_ten_uint64[] = {1UL, // effect on performance: in order to have a faster algorithm, we'd need // to slow down performance for faster algorithms, and this is still fast. template -fastfloat_really_inline FASTFLOAT_CONSTEXPR14 int16_t +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 int32_t scientific_exponent(parsed_number_string_t const &num) noexcept { uint64_t mantissa = num.mantissa; - int16_t exponent = num.exponent; + int32_t exponent = num.exponent; while (mantissa >= 10000) { mantissa /= 10000; exponent += 4; @@ -223,8 +223,8 @@ is_truncated(span s) noexcept { template fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void -parse_eight_digits(UC const *&p, limb &value, uint16_t &counter, - uint16_t &count) noexcept { +parse_eight_digits(UC const *&p, limb &value, uint32_t &counter, + uint32_t &count) noexcept { value = value * 100000000 + parse_eight_digits_unrolled(p); p += 8; counter += 8; @@ -233,8 +233,8 @@ parse_eight_digits(UC const *&p, limb &value, uint16_t &counter, template fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void -parse_one_digit(UC const *&p, limb &value, uint16_t &counter, - uint16_t &count) noexcept { +parse_one_digit(UC const *&p, limb &value, uint32_t &counter, + uint32_t &count) noexcept { value = value * 10 + limb(*p - UC('0')); p++; counter++; @@ -248,7 +248,7 @@ add_native(bigint &big, limb power, limb value) noexcept { } fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void -round_up_bigint(bigint &big, uint16_t &count) noexcept { +round_up_bigint(bigint &big, uint32_t &count) noexcept { // need to round-up the digits, but need to avoid rounding // ....9999 to ...10000, which could cause a false halfway point. add_native(big, 10, 1); @@ -259,17 +259,17 @@ round_up_bigint(bigint &big, uint16_t &count) noexcept { template inline FASTFLOAT_CONSTEXPR20 void parse_mantissa(bigint &result, const parsed_number_string_t &num, - uint16_t const max_digits, uint16_t &digits) noexcept { + uint32_t const max_digits, uint32_t &digits) noexcept { // try to minimize the number of big integer and scalar multiplication. // therefore, try to parse 8 digits at a time, and multiply by the largest // scalar value (9 or 19 digits) for each step. - uint16_t counter = 0; + uint32_t counter = 0; digits = 0; limb value = 0; #ifdef FASTFLOAT_64BIT_LIMB - uint16_t const step = 19; + uint32_t const step = 19; #else - uint16_t const step = 9; + uint32_t const step = 9; #endif // process all integer digits. @@ -440,13 +440,13 @@ inline FASTFLOAT_CONSTEXPR20 void digit_comp( // remove the invalid exponent bias am.power2 -= invalid_am_bias; - int16_t sci_exp = scientific_exponent(num); - uint16_t const max_digits = static_cast(binary_format::max_digits()); - uint16_t digits = 0; + int32_t sci_exp = scientific_exponent(num); + uint32_t const max_digits = uint32_t(binary_format::max_digits()); + uint32_t digits = 0; bigint bigmant; parse_mantissa(bigmant, num, max_digits, digits); // can't underflow, since digits is at most max_digits. - int16_t exponent = sci_exp + 1 - digits; + int32_t exponent = sci_exp + 1 - digits; if (exponent >= 0) { positive_digit_comp(bigmant, am, exponent); } else { diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index 143df1b..1b4362d 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -70,14 +70,15 @@ template struct parse_options_t { FASTFLOAT_CONSTEXPR20 explicit parse_options_t( chars_format fmt = chars_format::general, UC dot = UC('.'), int const b = 10) noexcept - : format(fmt), decimal_point(dot), base(static_cast(b)) {} + : format(fmt), decimal_point(dot), base(b) {} /** Which number formats are accepted */ chars_format format; /** The character used as decimal point */ UC decimal_point; /** The base used for integers */ - uint8_t base; /* only allowed from 2 to 36 */ + uint32_t base; /* only allowed from 2 to 36 */ + FASTFLOAT_ASSUME(base >= 2 && base <= 36); }; using parse_options = parse_options_t; @@ -288,15 +289,15 @@ fastfloat_strncasecmp(UC const *actual_mixedcase, UC const *expected_lowercase, // a pointer and a length to a contiguous block of memory template struct span { T const *ptr; - size_t length; + uint32_t length; - constexpr span(T const *_ptr, size_t _length) : ptr(_ptr), length(_length) {} + constexpr span(T const *_ptr, uint32_t _length) : ptr(_ptr), length(_length) {} constexpr span() : ptr(nullptr), length(0) {} - constexpr size_t len() const noexcept { return length; } + constexpr uint32_t len() const noexcept { return length; } - FASTFLOAT_CONSTEXPR14 const T &operator[](size_t index) const noexcept { + FASTFLOAT_CONSTEXPR14 const T &operator[](uint32_t index) const noexcept { FASTFLOAT_DEBUG_ASSERT(index < length); return ptr[index]; } @@ -1169,13 +1170,13 @@ fastfloat_really_inline constexpr uint8_t ch_to_digit(UC c) { return int_luts<>::chdigit[static_cast(c)]; } -fastfloat_really_inline constexpr uint8_t max_digits_u64(uint8_t base) { +fastfloat_really_inline constexpr uint8_t max_digits_u64(uint32_t base) { return int_luts<>::maxdigits_u64[base - 2]; } // If a u64 is exactly max_digits_u64() in length, this is // the value below which it has definitely overflowed. -fastfloat_really_inline constexpr uint64_t min_safe_u64(uint8_t base) { +fastfloat_really_inline constexpr uint64_t min_safe_u64(uint32_t base) { return int_luts<>::min_safe_u64[base - 2]; }