mirror of
https://github.com/fastfloat/fast_float.git
synced 2026-02-16 07:09:55 +08:00
cleanup and type usage fixes.
This commit is contained in:
parent
37152ead57
commit
054004f779
@ -291,9 +291,6 @@ template <bool basic_json_fmt, typename UC>
|
|||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 parsed_number_string_t<UC>
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 parsed_number_string_t<UC>
|
||||||
parse_number_string(UC const *p, UC const *pend,
|
parse_number_string(UC const *p, UC const *pend,
|
||||||
parse_options_t<UC> const options) noexcept {
|
parse_options_t<UC> const options) noexcept {
|
||||||
// Cyclomatic complexity https://en.wikipedia.org/wiki/Cyclomatic_complexity
|
|
||||||
// Consider refactoring the 'parse_number_string' function.
|
|
||||||
// FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN fix this.
|
|
||||||
parsed_number_string_t<UC> answer;
|
parsed_number_string_t<UC> answer;
|
||||||
// so dereference without checks
|
// so dereference without checks
|
||||||
FASTFLOAT_ASSUME(p < pend);
|
FASTFLOAT_ASSUME(p < pend);
|
||||||
@ -460,12 +457,12 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
|
|
||||||
// Now we can check for errors.
|
// Now we can check for errors.
|
||||||
|
|
||||||
// TODO: If we frequently had to deal with long strings of digits,
|
// If we frequently had to deal with long strings of digits,
|
||||||
// we could extend our code by using a 128-bit integer instead
|
// we could extend our code by using a 128-bit integer instead
|
||||||
// of a 64-bit integer. However, this is uncommon.
|
// of a 64-bit integer. However, this is uncommon.
|
||||||
|
//
|
||||||
// We can deal with up to 19 digits.
|
// We can deal with up to 19 digits.
|
||||||
if (digit_count > 19) {
|
if (digit_count > 19) { // this is uncommon
|
||||||
// It is possible that the integer had an overflow.
|
// It is possible that the integer had an overflow.
|
||||||
// We have to handle the case where we have 0.0000somenumber.
|
// We have to handle the case where we have 0.0000somenumber.
|
||||||
// We need to be mindful of the case where we only have zeroes...
|
// We need to be mindful of the case where we only have zeroes...
|
||||||
@ -479,8 +476,7 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
++start;
|
++start;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have to check if we have a number with more than 19 significant
|
// We have to check if number has more than 19 significant digits.
|
||||||
// digits.
|
|
||||||
if (digit_count > 19) {
|
if (digit_count > 19) {
|
||||||
answer.too_many_digits = true;
|
answer.too_many_digits = true;
|
||||||
// Let us start again, this time, avoiding overflows.
|
// Let us start again, this time, avoiding overflows.
|
||||||
@ -492,8 +488,8 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
constexpr am_mant_t minimal_nineteen_digit_integer{1000000000000000000};
|
constexpr am_mant_t minimal_nineteen_digit_integer{1000000000000000000};
|
||||||
while ((p != int_end) &&
|
while ((p != int_end) &&
|
||||||
(answer.mantissa < minimal_nineteen_digit_integer)) {
|
(answer.mantissa < minimal_nineteen_digit_integer)) {
|
||||||
answer.mantissa = static_cast<am_mant_t>(
|
answer.mantissa =
|
||||||
answer.mantissa * 10 + static_cast<am_mant_t>(*p - UC('0')));
|
answer.mantissa * 10 + static_cast<am_mant_t>(*p - UC('0'));
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
if (answer.mantissa >= minimal_nineteen_digit_integer) {
|
if (answer.mantissa >= minimal_nineteen_digit_integer) {
|
||||||
|
|||||||
@ -67,7 +67,7 @@ template <limb_t size> struct stackvec {
|
|||||||
// index from the end of the container
|
// index from the end of the container
|
||||||
FASTFLOAT_CONSTEXPR14 const limb &rindex(limb_t index) const noexcept {
|
FASTFLOAT_CONSTEXPR14 const limb &rindex(limb_t index) const noexcept {
|
||||||
FASTFLOAT_DEBUG_ASSERT(index < length);
|
FASTFLOAT_DEBUG_ASSERT(index < length);
|
||||||
limb_t rindex = static_cast<limb_t>(length - index - 1);
|
auto rindex = length - index - 1;
|
||||||
return data[rindex];
|
return data[rindex];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ template <limb_t size> struct stackvec {
|
|||||||
FASTFLOAT_CONSTEXPR20 void extend_unchecked(limb_span s) noexcept {
|
FASTFLOAT_CONSTEXPR20 void extend_unchecked(limb_span s) noexcept {
|
||||||
limb *ptr = data + length;
|
limb *ptr = data + length;
|
||||||
std::copy_n(s.ptr, s.len(), ptr);
|
std::copy_n(s.ptr, s.len(), ptr);
|
||||||
set_len(static_cast<limb_t>(len() + s.len()));
|
set_len(len() + static_cast<limb_t>(s.len()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to add items to the vector, returning if items were added
|
// try to add items to the vector, returning if items were added
|
||||||
@ -119,7 +119,7 @@ template <limb_t size> struct stackvec {
|
|||||||
FASTFLOAT_CONSTEXPR20
|
FASTFLOAT_CONSTEXPR20
|
||||||
void resize_unchecked(limb_t new_len, limb value) noexcept {
|
void resize_unchecked(limb_t new_len, limb value) noexcept {
|
||||||
if (new_len > len()) {
|
if (new_len > len()) {
|
||||||
limb_t count = new_len - len();
|
auto count = new_len - len();
|
||||||
limb *first = data + len();
|
limb *first = data + len();
|
||||||
limb *last = first + count;
|
limb *last = first + count;
|
||||||
::std::fill(first, last, value);
|
::std::fill(first, last, value);
|
||||||
@ -258,9 +258,8 @@ scalar_mul(limb x, limb y, limb &carry) noexcept {
|
|||||||
// add scalar value to bigint starting from offset.
|
// add scalar value to bigint starting from offset.
|
||||||
// used in grade school multiplication
|
// used in grade school multiplication
|
||||||
template <limb_t size>
|
template <limb_t size>
|
||||||
inline FASTFLOAT_CONSTEXPR20 bool small_add_from(stackvec<size> &vec, limb y,
|
inline FASTFLOAT_CONSTEXPR20 bool
|
||||||
limb_t start) noexcept {
|
small_add_from(stackvec<size> &vec, limb carry, limb_t start) noexcept {
|
||||||
limb carry = y;
|
|
||||||
bool overflow;
|
bool overflow;
|
||||||
while (carry != 0 && start < vec.len()) {
|
while (carry != 0 && start < vec.len()) {
|
||||||
vec[start] = scalar_add(vec[start], carry, overflow);
|
vec[start] = scalar_add(vec[start], carry, overflow);
|
||||||
@ -301,8 +300,9 @@ FASTFLOAT_CONSTEXPR20 bool large_add_from(stackvec<size> &x, limb_span y,
|
|||||||
limb_t start) noexcept {
|
limb_t start) noexcept {
|
||||||
// the effective x buffer is from `xstart..x.len()`, so exit early
|
// the effective x buffer is from `xstart..x.len()`, so exit early
|
||||||
// if we can't get that current range.
|
// if we can't get that current range.
|
||||||
if (x.len() < start || y.len() > static_cast<limb_t>(x.len() - start)) {
|
if (x.len() < start ||
|
||||||
FASTFLOAT_TRY(x.try_resize(static_cast<limb_t>(y.len() + start), 0));
|
y.len() > static_cast<uint_fast16_t>(x.len() - start)) {
|
||||||
|
FASTFLOAT_TRY(x.try_resize(static_cast<limb_t>(y.len()) + start, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool carry = false;
|
bool carry = false;
|
||||||
@ -321,7 +321,7 @@ FASTFLOAT_CONSTEXPR20 bool large_add_from(stackvec<size> &x, limb_span y,
|
|||||||
|
|
||||||
// handle overflow
|
// handle overflow
|
||||||
if (carry) {
|
if (carry) {
|
||||||
FASTFLOAT_TRY(small_add_from(x, 1, static_cast<limb_t>(y.len() + start)));
|
FASTFLOAT_TRY(small_add_from(x, 1, static_cast<limb_t>(y.len()) + start));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -343,7 +343,7 @@ FASTFLOAT_CONSTEXPR20 bool long_mul(stackvec<size> &x, limb_span y) noexcept {
|
|||||||
if (y.len() != 0) {
|
if (y.len() != 0) {
|
||||||
limb y0 = y[0];
|
limb y0 = y[0];
|
||||||
FASTFLOAT_TRY(small_mul(x, y0));
|
FASTFLOAT_TRY(small_mul(x, y0));
|
||||||
for (limb_t index = 1; index != y.len(); ++index) {
|
for (limb_t index = 1; index < y.len(); ++index) {
|
||||||
limb yi = y[index];
|
limb yi = y[index];
|
||||||
stackvec<size> zi;
|
stackvec<size> zi;
|
||||||
if (yi != 0) {
|
if (yi != 0) {
|
||||||
@ -584,8 +584,8 @@ struct bigint : pow5_tables<> {
|
|||||||
|
|
||||||
// get the number of bits in the bigint.
|
// get the number of bits in the bigint.
|
||||||
FASTFLOAT_CONSTEXPR20 bigint_bits_t bit_length() const noexcept {
|
FASTFLOAT_CONSTEXPR20 bigint_bits_t bit_length() const noexcept {
|
||||||
bigint_bits_t lz = ctlz();
|
auto lz = ctlz();
|
||||||
return static_cast<fast_float::bigint_bits_t>(limb_bits * vec.len() - lz);
|
return limb_bits * vec.len() - lz;
|
||||||
}
|
}
|
||||||
|
|
||||||
FASTFLOAT_CONSTEXPR20 bool mul(limb y) noexcept { return small_mul(vec, y); }
|
FASTFLOAT_CONSTEXPR20 bool mul(limb y) noexcept { return small_mul(vec, y); }
|
||||||
|
|||||||
@ -76,15 +76,6 @@
|
|||||||
#define FASTFLOAT_INLINE_VARIABLE static constexpr
|
#define FASTFLOAT_INLINE_VARIABLE static constexpr
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__cpp_lib_is_constant_evaluated) && \
|
|
||||||
__cpp_lib_is_constant_evaluated >= 201811L
|
|
||||||
#define FASTFLOAT_HAS_IS_CONSTANT_EVALUATED 1
|
|
||||||
#define FASTFLOAT_CONSTEVAL consteval
|
|
||||||
#else
|
|
||||||
#define FASTFLOAT_HAS_IS_CONSTANT_EVALUATED 0
|
|
||||||
#define FASTFLOAT_CONSTEVAL FASTFLOAT_CONSTEXPR14
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Testing for relevant C++20 constexpr library features
|
// Testing for relevant C++20 constexpr library features
|
||||||
#if FASTFLOAT_HAS_IS_CONSTANT_EVALUATED && FASTFLOAT_HAS_BIT_CAST && \
|
#if FASTFLOAT_HAS_IS_CONSTANT_EVALUATED && FASTFLOAT_HAS_BIT_CAST && \
|
||||||
defined(__cpp_lib_constexpr_algorithms) && \
|
defined(__cpp_lib_constexpr_algorithms) && \
|
||||||
|
|||||||
@ -72,7 +72,7 @@ constexpr fastfloat_really_inline am_pow_t power(am_pow_t q) noexcept {
|
|||||||
template <typename binary>
|
template <typename binary>
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 adjusted_mantissa
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 adjusted_mantissa
|
||||||
compute_error_scaled(am_pow_t q, am_mant_t w, am_bits_t lz) noexcept {
|
compute_error_scaled(am_pow_t q, am_mant_t w, am_bits_t lz) noexcept {
|
||||||
auto const hilz = static_cast<am_pow_t>((w >> 63) ^ 1);
|
auto const hilz = static_cast<am_bits_t>((w >> 63) ^ 1);
|
||||||
adjusted_mantissa answer;
|
adjusted_mantissa answer;
|
||||||
answer.mantissa = w << hilz;
|
answer.mantissa = w << hilz;
|
||||||
constexpr am_pow_t bias =
|
constexpr am_pow_t bias =
|
||||||
@ -138,8 +138,8 @@ compute_float(am_pow_t q, am_mant_t w) noexcept {
|
|||||||
// branchless approach: value128 product = compute_product(q, w); but in
|
// branchless approach: value128 product = compute_product(q, w); but in
|
||||||
// practice, we can win big with the compute_product_approximation if its
|
// practice, we can win big with the compute_product_approximation if its
|
||||||
// additional branch is easily predicted. Which is best is data specific.
|
// additional branch is easily predicted. Which is best is data specific.
|
||||||
auto const upperbit = static_cast<limb_t>(product.high >> 63);
|
auto const upperbit = static_cast<am_bits_t>(product.high >> 63);
|
||||||
limb_t const shift = upperbit + 64 - binary::mantissa_explicit_bits() - 3;
|
am_bits_t const shift = upperbit + 64 - binary::mantissa_explicit_bits() - 3;
|
||||||
|
|
||||||
answer.mantissa = product.high >> shift;
|
answer.mantissa = product.high >> shift;
|
||||||
|
|
||||||
|
|||||||
@ -68,7 +68,7 @@ to_extended(T const value) noexcept {
|
|||||||
constexpr am_pow_t bias = binary_format<T>::mantissa_explicit_bits() -
|
constexpr am_pow_t bias = binary_format<T>::mantissa_explicit_bits() -
|
||||||
binary_format<T>::minimum_exponent();
|
binary_format<T>::minimum_exponent();
|
||||||
|
|
||||||
equiv_uint const bits = bit_cast<equiv_uint, T>(value);
|
auto const bits = bit_cast<equiv_uint, T>(value);
|
||||||
|
|
||||||
if ((bits & exponent_mask) == 0) {
|
if ((bits & exponent_mask) == 0) {
|
||||||
// denormal
|
// denormal
|
||||||
|
|||||||
@ -49,19 +49,19 @@ typedef uint_fast8_t limb_t;
|
|||||||
typedef int_fast8_t am_bits_t;
|
typedef int_fast8_t am_bits_t;
|
||||||
|
|
||||||
// 16 bit signed integer is used for power to cover all double exponents.
|
// 16 bit signed integer is used for power to cover all double exponents.
|
||||||
typedef int16_t am_pow_t;
|
typedef int_fast16_t am_pow_t;
|
||||||
// Power bias is signed for handling a denormal float
|
// Power bias is signed for handling a denormal float
|
||||||
// or an invalid mantissa.
|
// or an invalid mantissa.
|
||||||
// Bias so we can get the real exponent with an invalid adjusted_mantissa.
|
// Bias so we can get the real exponent with an invalid adjusted_mantissa.
|
||||||
constexpr static am_pow_t invalid_am_bias =
|
constexpr static am_pow_t invalid_am_bias =
|
||||||
std::numeric_limits<am_pow_t>::min() + 1;
|
std::numeric_limits<int16_t>::min() + 1;
|
||||||
constexpr static am_pow_t am_bias_limit =
|
constexpr static am_pow_t am_bias_limit =
|
||||||
(std::numeric_limits<am_pow_t>::max() / 8) - 1;
|
(std::numeric_limits<int16_t>::max() / 16) - 1;
|
||||||
|
|
||||||
// Type for enum chars_format.
|
// Type for enum chars_format.
|
||||||
typedef uint_fast8_t chars_format_t;
|
typedef uint_fast8_t chars_format_t;
|
||||||
|
|
||||||
// Type for base.
|
// Type for base, only allowed from 2 to 36.
|
||||||
typedef uint_fast8_t base_t;
|
typedef uint_fast8_t base_t;
|
||||||
|
|
||||||
enum class chars_format : chars_format_t;
|
enum class chars_format : chars_format_t;
|
||||||
@ -110,10 +110,10 @@ template <typename UC> struct parse_options_t {
|
|||||||
|
|
||||||
/** Which number formats are accepted */
|
/** Which number formats are accepted */
|
||||||
chars_format format;
|
chars_format format;
|
||||||
/** The character used as decimal point */
|
/** The character used as decimal point for floats */
|
||||||
UC decimal_point;
|
UC decimal_point;
|
||||||
/** The base used for integers */
|
/** The base used for integers */
|
||||||
base_t base; /* only allowed from 2 to 36 */
|
base_t base;
|
||||||
};
|
};
|
||||||
|
|
||||||
using parse_options = parse_options_t<char>;
|
using parse_options = parse_options_t<char>;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user