diff --git a/include/fast_float/ascii_number.h b/include/fast_float/ascii_number.h index d05b51b..a3ce62b 100644 --- a/include/fast_float/ascii_number.h +++ b/include/fast_float/ascii_number.h @@ -602,9 +602,9 @@ parse_int_string(UC const *p, UC const *pend, T &value, ((digits.as_int + 0x46464646u) | (digits.as_int - 0x30303030u)) & 0x80808080u; const auto tz = - static_cast(countr_zero_32(magic)); // 7, 15, 23, 31, or 32 - uint32_t nd = (tz == 32) ? 4 : (tz >> 3); - nd = std::min(static_cast(nd), len); + static_cast(countr_zero_32(magic)); // 7, 15, 23, 31, or 32 + am_digits nd = (tz == 32) ? 4 : (tz >> 3); + nd = std::min(nd, len); if (nd == 0) { if (has_leading_zeros) { value = 0; @@ -618,7 +618,7 @@ parse_int_string(UC const *p, UC const *pend, T &value, } if (nd > 3) { const UC *q = p + nd; - uint_fast8_t rem = len - nd; + am_digits rem = len - nd; while (rem) { if (*q < UC('0') || *q > UC('9')) break; diff --git a/include/fast_float/bigint.h b/include/fast_float/bigint.h index 5aa3faf..6f4856c 100644 --- a/include/fast_float/bigint.h +++ b/include/fast_float/bigint.h @@ -41,7 +41,7 @@ constexpr limb_t bigint_limbs = bigint_bits / limb_bits; template struct stackvec { limb data[size]; // we never need more than 150 limbs - uint_fast8_t length{0}; + limb_t length{0}; FASTFLOAT_CONSTEXPR20 stackvec() noexcept = default; stackvec(stackvec const &) = delete; @@ -100,7 +100,7 @@ template struct stackvec { FASTFLOAT_CONSTEXPR20 void extend_unchecked(limb_span s) noexcept { limb *ptr = data + length; std::copy_n(s.ptr, s.len(), ptr); - set_len(limb_t(len() + s.len())); + set_len(static_cast(len() + s.len())); } // try to add items to the vector, returning if items were added @@ -123,17 +123,20 @@ template struct stackvec { limb *first = data + len(); limb *last = first + count; ::std::fill(first, last, value); + set_len(new_len); + } else { + set_len(new_len); } - set_len(new_len); } // try to resize the vector, returning if the vector was resized. FASTFLOAT_CONSTEXPR20 bool try_resize(limb_t new_len, limb value) noexcept { if (new_len > capacity()) { return false; + } else { + resize_unchecked(new_len, value); + return true; } - resize_unchecked(new_len, value); - return true; } // check if any limbs are non-zero after the given index. @@ -259,9 +262,10 @@ inline FASTFLOAT_CONSTEXPR20 bool small_add_from(stackvec &vec, limb y, limb_t start) noexcept { limb carry = y; bool overflow; - while (carry != 0 && start++ != vec.len()) { + while (carry != 0 && start < vec.len()) { vec[start] = scalar_add(vec[start], carry, overflow); carry = limb(overflow); + ++start; } if (carry != 0) { FASTFLOAT_TRY(vec.try_push(carry)); @@ -297,8 +301,8 @@ FASTFLOAT_CONSTEXPR20 bool large_add_from(stackvec &x, limb_span y, limb_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() > limb_t(x.len() - start)) { - FASTFLOAT_TRY(x.try_resize(limb_t(y.len() + start), 0)); + if (x.len() < start || y.len() > static_cast(x.len() - start)) { + FASTFLOAT_TRY(x.try_resize(static_cast(y.len() + start), 0)); } bool carry = false; @@ -317,7 +321,7 @@ FASTFLOAT_CONSTEXPR20 bool large_add_from(stackvec &x, limb_span y, // handle overflow if (carry) { - FASTFLOAT_TRY(small_add_from(x, 1, limb_t(y.len() + start))); + FASTFLOAT_TRY(small_add_from(x, 1, static_cast(y.len() + start))); } return true; } @@ -369,7 +373,7 @@ FASTFLOAT_CONSTEXPR20 bool large_mul(stackvec &x, limb_span y) noexcept { } template struct pow5_tables { - static constexpr uint_fast8_t large_step = 135; + static constexpr limb_t large_step = 135; static constexpr uint64_t small_power_of_5[] = { 1UL, 5UL, @@ -413,7 +417,7 @@ template struct pow5_tables { #if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE -template constexpr uint_fast8_t pow5_tables::large_step; +template constexpr limb_t pow5_tables::large_step; template constexpr uint64_t pow5_tables::small_power_of_5[]; @@ -487,7 +491,7 @@ struct bigint : pow5_tables<> { } else if (vec.len() < other.vec.len()) { return -1; } else { - for (limb_t index = vec.len(); index != 0; --index) { + for (limb_t index = vec.len(); index > 0; --index) { limb xi = vec[index - 1]; limb yi = other.vec[index - 1]; if (xi > yi) { @@ -502,7 +506,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(bigint_bits_t n) noexcept { + FASTFLOAT_CONSTEXPR20 bool shl_bits(limb_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: @@ -511,10 +515,10 @@ struct bigint : pow5_tables<> { FASTFLOAT_DEBUG_ASSERT(n != 0); FASTFLOAT_DEBUG_ASSERT(n < sizeof(limb) * 8); - bigint_bits_t const shl = n; - bigint_bits_t const shr = limb_bits - shl; + limb_t const shl = n; + limb_t const shr = limb_bits - shl; limb prev = 0; - for (limb_t index = 0; index != vec.len(); ++index) { + for (limb_t index = 0; index < vec.len(); ++index) { limb xi = vec[index]; vec[index] = (xi << shl) | (prev >> shr); prev = xi; @@ -528,13 +532,12 @@ struct bigint : pow5_tables<> { } // move the limbs left by `n` limbs. - FASTFLOAT_CONSTEXPR20 bool shl_limbs(bigint_bits_t n) noexcept { + FASTFLOAT_CONSTEXPR20 bool shl_limbs(limb_t n) noexcept { FASTFLOAT_DEBUG_ASSERT(n != 0); if (n + vec.len() > vec.capacity()) { // we can't shift more than the capacity of the vector. return false; - } - if (!vec.is_empty()) { + } else if (!vec.is_empty()) { // move limbs limb *dst = vec.data + n; limb const *src = vec.data; @@ -543,15 +546,17 @@ struct bigint : pow5_tables<> { limb *first = vec.data; limb *last = first + n; ::std::fill(first, last, 0); - vec.set_len(limb_t(n + vec.len())); + vec.set_len(n + vec.len()); + return true; + } else { + return true; } - return true; } // move the limbs left by `n` bits. FASTFLOAT_CONSTEXPR20 bool shl(bigint_bits_t n) noexcept { - bigint_bits_t const rem = n % limb_bits; - bigint_bits_t const div = n / limb_bits; + auto const rem = static_cast(n % limb_bits); + auto const div = static_cast(n / limb_bits); if (rem != 0) { FASTFLOAT_TRY(shl_bits(rem)); } @@ -566,14 +571,15 @@ struct bigint : pow5_tables<> { if (vec.is_empty()) { // empty vector, no bits, no zeros. return 0; - } + } else { #ifdef FASTFLOAT_64BIT_LIMB - return leading_zeroes(vec.rindex(0)); + return leading_zeroes(vec.rindex(0)); #else - // no use defining a specialized leading_zeroes for a 32-bit type. - uint64_t r0 = vec.rindex(0); - return leading_zeroes(r0 << 32); + // no use defining a specialized leading_zeroes for a 32-bit type. + uint64_t r0 = vec.rindex(0); + return leading_zeroes(r0 << 32); #endif + } } // get the number of bits in the bigint. diff --git a/include/fast_float/decimal_to_binary.h b/include/fast_float/decimal_to_binary.h index 8d4b6a2..a10d3c8 100644 --- a/include/fast_float/decimal_to_binary.h +++ b/include/fast_float/decimal_to_binary.h @@ -72,7 +72,7 @@ constexpr fastfloat_really_inline am_pow_t power(am_pow_t q) noexcept { template fastfloat_really_inline FASTFLOAT_CONSTEXPR14 adjusted_mantissa compute_error_scaled(int64_t q, uint64_t w, limb_t lz) noexcept { - limb_t const hilz = static_cast((w >> 63) ^ 1); + auto const hilz = static_cast((w >> 63) ^ 1); adjusted_mantissa answer; answer.mantissa = w << hilz; constexpr am_pow_t bias = @@ -139,9 +139,8 @@ compute_float(int64_t q, uint64_t w) noexcept { // branchless approach: value128 product = compute_product(q, w); but in // practice, we can win big with the compute_product_approximation if its // additional branch is easily predicted. Which is best is data specific. - auto const upperbit = limb_t(product.high >> 63); - auto const shift = - limb_t(upperbit + 64 - binary::mantissa_explicit_bits() - 3); + limb_t const upperbit = static_cast(product.high >> 63); + limb_t const shift = upperbit + 64 - binary::mantissa_explicit_bits() - 3; answer.mantissa = product.high >> shift; diff --git a/include/fast_float/digit_comparison.h b/include/fast_float/digit_comparison.h index 22c8dd3..c7837e1 100644 --- a/include/fast_float/digit_comparison.h +++ b/include/fast_float/digit_comparison.h @@ -139,7 +139,7 @@ fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void round_nearest_tie_even(adjusted_mantissa &am, am_pow_t shift, callback cb) noexcept { am_mant_t const mask = - (shift == 64) ? UINT64_MAX : (am_mant_t(1) << shift) - 1; + (shift == 64) ? std::numeric_limits::max() : (am_mant_t(1) << shift) - 1; am_mant_t const halfway = (shift == 0) ? 0 : am_mant_t(1) << (shift - 1); am_mant_t truncated_bits = am.mantissa & mask; bool is_above = truncated_bits > halfway; diff --git a/include/fast_float/float_common.h b/include/fast_float/float_common.h index ad3e7dc..7d54548 100644 --- a/include/fast_float/float_common.h +++ b/include/fast_float/float_common.h @@ -41,6 +41,8 @@ typedef uint_fast8_t limb_t; typedef uint_fast8_t chars_format_t; +typedef uint_fast8_t base_t; + enum class chars_format : chars_format_t; #ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN @@ -82,7 +84,7 @@ using from_chars_result = from_chars_result_t; template struct parse_options_t { constexpr explicit parse_options_t( chars_format const fmt = chars_format::general, UC const dot = UC('.'), - uint_fast8_t const b = 10) noexcept + base_t const b = 10) noexcept : format(fmt), decimal_point(dot), base(b) {} /** Which number formats are accepted */ @@ -90,7 +92,7 @@ template struct parse_options_t { /** The character used as decimal point */ UC decimal_point; /** The base used for integers */ - uint_fast8_t base; /* only allowed from 2 to 36 */ + base_t base; /* only allowed from 2 to 36 */ }; using parse_options = parse_options_t; @@ -298,6 +300,10 @@ struct is_supported_char_type }; #ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN + +// TODO use SSE4.2 there when SSE2 compiler switch in MSVC +// or in other compiler SSE4.2 available. + // Compares two ASCII strings in a case insensitive manner. template inline FASTFLOAT_CONSTEXPR14 bool @@ -320,16 +326,17 @@ 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; - am_digits length; + uint_fast16_t length; - constexpr span(T const *_ptr, am_digits _length) noexcept + constexpr span(T const *_ptr, uint_fast16_t _length) noexcept : ptr(_ptr), length(_length) {} constexpr span() noexcept : ptr(nullptr), length(0) {} - constexpr am_digits len() const noexcept { return length; } + constexpr uint_fast16_t len() const noexcept { return length; } - FASTFLOAT_CONSTEXPR14 const T &operator[](am_digits index) const noexcept { + FASTFLOAT_CONSTEXPR14 const T & + operator[](uint_fast16_t index) const noexcept { FASTFLOAT_DEBUG_ASSERT(index < length); return ptr[index]; } @@ -345,7 +352,7 @@ struct alignas(16) value128 { constexpr value128() noexcept : low(0), high(0) {} }; -/* Helper C++14 constexpr generic implementation of leading_zeroes */ +/* Helper C++14 constexpr generic implementation of leading_zeroes for 64-bit */ fastfloat_really_inline FASTFLOAT_CONSTEXPR14 limb_t leading_zeroes_generic(uint64_t input_num, uint32_t last_bit = 0) noexcept { if (input_num & uint64_t(0xffffffff00000000)) { @@ -371,7 +378,7 @@ leading_zeroes_generic(uint64_t input_num, uint32_t last_bit = 0) noexcept { if (input_num & uint64_t(0x2)) { /* input_num >>= 1; */ last_bit |= 1; } - return 63 - (limb_t)last_bit; + return 63 - static_cast(last_bit); } /* result might be undefined when input_num is zero */ @@ -388,22 +395,22 @@ leading_zeroes(uint64_t input_num) noexcept { // Search the mask data from most significant bit (MSB) // to least significant bit (LSB) for a set bit (1). _BitScanReverse64(&leading_zero, input_num); - return (limb_t)(63 - leading_zero); + return static_cast(63 - leading_zero); #else - return (limb_t)leading_zeroes_generic(input_num); + return static_cast(leading_zeroes_generic(input_num)); #endif #else - return (limb_t)__builtin_clzll(input_num); + return static_cast(__builtin_clzll(input_num)); #endif } /* Helper C++14 constexpr generic implementation of countr_zero for 32-bit */ -fastfloat_really_inline FASTFLOAT_CONSTEXPR14 int +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint32_t countr_zero_generic_32(uint32_t input_num) { if (input_num == 0) { return 32; } - int last_bit = 0; + uint32_t last_bit = 0; if (!(input_num & 0x0000FFFF)) { input_num >>= 16; last_bit |= 16; @@ -1099,7 +1106,6 @@ binary_format::hidden_bit_mask() { return 0x0010000000000000; } -// Fix for C2672: Ensure bit_cast is called with explicit template arguments template fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void to_float( #ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN @@ -1120,7 +1126,7 @@ fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void to_float( #ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN template struct space_lut { - static constexpr uint_fast8_t value[] = { + static constexpr uint8_t value[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1136,12 +1142,12 @@ template struct space_lut { #if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE -template constexpr uint_fast8_t space_lut::value[]; +template constexpr uint8_t space_lut::value[]; #endif template constexpr bool is_space(UC c) { - return c < 256 && space_lut<>::value[uint_fast8_t(c)]; + return c < 256 && space_lut<>::value[uint8_t(c)]; } #endif @@ -1227,7 +1233,7 @@ template struct int_luts { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; - static constexpr uint_fast8_t maxdigits_u64[] = { + static constexpr limb_t maxdigits_u64[] = { 64, 41, 32, 28, 25, 23, 22, 21, 20, 19, 18, 18, 17, 17, 16, 16, 16, 16, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13}; @@ -1248,16 +1254,16 @@ template struct int_luts { #if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE -template constexpr uint_fast8_t int_luts::chdigit[]; +template constexpr uint8_t int_luts::chdigit[]; -template constexpr uint_fast8_t int_luts::maxdigits_u64[]; +template constexpr limb_t int_luts::maxdigits_u64[]; template constexpr uint64_t int_luts::min_safe_u64[]; #endif template -fastfloat_really_inline constexpr uint_fast8_t ch_to_digit(UC c) noexcept { +fastfloat_really_inline constexpr uint8_t ch_to_digit(UC c) noexcept { // wchar_t and char can be signed, so we need to be careful. using UnsignedUC = typename std::make_unsigned::type; return int_luts<>::chdigit[static_cast( @@ -1266,15 +1272,13 @@ fastfloat_really_inline constexpr uint_fast8_t ch_to_digit(UC c) noexcept { -((static_cast(c) & ~0xFFull) == 0)))]; } -fastfloat_really_inline constexpr uint_fast8_t -max_digits_u64(uint_fast8_t base) noexcept { +fastfloat_really_inline constexpr limb_t max_digits_u64(base_t base) noexcept { 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(uint_fast8_t base) noexcept { +fastfloat_really_inline constexpr uint64_t min_safe_u64(base_t base) noexcept { return int_luts<>::min_safe_u64[base - 2]; } diff --git a/include/fast_float/parse_number.h b/include/fast_float/parse_number.h index eb30818..97cbf04 100644 --- a/include/fast_float/parse_number.h +++ b/include/fast_float/parse_number.h @@ -27,12 +27,13 @@ from_chars_result_t const chars_format fmt) noexcept { from_chars_result_t answer{}; answer.ptr = first; - answer.ec = std::errc(); // be optimistic + answer.ec = std::errc(); // be optimistic + FASTFLOAT_ASSUME(first < last); // so dereference without checks bool const minusSign = (*first == UC('-')); // C++17 20.19.3.(7.1) explicitly forbids '+' sign here - if ((*first == UC('-')) || + if (minusSign || ((chars_format_t(fmt & chars_format::allow_leading_plus)) && (*first == UC('+')))) { ++first; @@ -375,7 +376,7 @@ from_chars_float_advanced(UC const *first, UC const *last, T &value, template FASTFLOAT_CONSTEXPR20 from_chars_result_t from_chars(UC const *first, UC const *last, T &value, - uint_fast8_t const base) noexcept { + base_t const base) noexcept { static_assert(is_supported_integer_type::value, "only integer types are supported"); @@ -389,8 +390,8 @@ from_chars(UC const *first, UC const *last, T &value, template FASTFLOAT_CONSTEXPR20 typename std::enable_if::value, T>::type - integer_times_pow10(uint64_t const mantissa, - int_fast16_t const decimal_exponent) noexcept { + integer_times_pow10(am_mant_t const mantissa, + am_pow_t const decimal_exponent) noexcept { T value; if (clinger_fast_path_impl(mantissa, decimal_exponent, #ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN @@ -412,8 +413,8 @@ FASTFLOAT_CONSTEXPR20 template FASTFLOAT_CONSTEXPR20 typename std::enable_if::value, T>::type - integer_times_pow10(int64_t const mantissa, - int_fast16_t const decimal_exponent) noexcept { + integer_times_pow10(am_sign_mant_t const mantissa, + am_pow_t const decimal_exponent) noexcept { #ifdef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN FASTFLOAT_ASSUME(mantissa >= 0); const am_mant_t m = static_cast(mantissa); @@ -441,14 +442,14 @@ FASTFLOAT_CONSTEXPR20 } FASTFLOAT_CONSTEXPR20 inline double -integer_times_pow10(uint64_t const mantissa, - int_fast16_t const decimal_exponent) noexcept { +integer_times_pow10(am_mant_t const mantissa, + am_pow_t const decimal_exponent) noexcept { return integer_times_pow10(mantissa, decimal_exponent); } FASTFLOAT_CONSTEXPR20 inline double -integer_times_pow10(int64_t const mantissa, - int_fast16_t const decimal_exponent) noexcept { +integer_times_pow10(am_sign_mant_t const mantissa, + am_pow_t const decimal_exponent) noexcept { return integer_times_pow10(mantissa, decimal_exponent); } @@ -460,8 +461,8 @@ FASTFLOAT_CONSTEXPR20 std::is_integral::value && !std::is_signed::value, T>::type - integer_times_pow10(Int mantissa, int_fast16_t decimal_exponent) noexcept { - return integer_times_pow10(static_cast(mantissa), + integer_times_pow10(Int mantissa, am_pow_t decimal_exponent) noexcept { + return integer_times_pow10(static_cast(mantissa), decimal_exponent); } @@ -471,23 +472,24 @@ FASTFLOAT_CONSTEXPR20 std::is_integral::value && std::is_signed::value, T>::type - integer_times_pow10(Int mantissa, int_fast16_t decimal_exponent) noexcept { - return integer_times_pow10(static_cast(mantissa), + integer_times_pow10(Int mantissa, am_pow_t decimal_exponent) noexcept { + return integer_times_pow10(static_cast(mantissa), decimal_exponent); } template FASTFLOAT_CONSTEXPR20 typename std::enable_if< std::is_integral::value && !std::is_signed::value, double>::type -integer_times_pow10(Int mantissa, int_fast16_t decimal_exponent) noexcept { - return integer_times_pow10(static_cast(mantissa), decimal_exponent); +integer_times_pow10(Int mantissa, am_pow_t decimal_exponent) noexcept { + return integer_times_pow10(static_cast(mantissa), decimal_exponent); } template FASTFLOAT_CONSTEXPR20 typename std::enable_if< std::is_integral::value && std::is_signed::value, double>::type -integer_times_pow10(Int mantissa, int_fast16_t decimal_exponent) noexcept { - return integer_times_pow10(static_cast(mantissa), decimal_exponent); +integer_times_pow10(Int mantissa, am_pow_t decimal_exponent) noexcept { + return integer_times_pow10(static_cast(mantissa), + decimal_exponent); } template