mirror of
https://github.com/fastfloat/fast_float.git
synced 2025-12-06 16:56:57 +08:00
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.
This commit is contained in:
parent
97bfec6ea3
commit
f1b7f493aa
@ -261,7 +261,7 @@ enum class parse_error {
|
|||||||
|
|
||||||
template <typename UC> struct parsed_number_string_t {
|
template <typename UC> struct parsed_number_string_t {
|
||||||
uint64_t mantissa{0};
|
uint64_t mantissa{0};
|
||||||
int16_t exponent{0};
|
int32_t exponent{0};
|
||||||
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
||||||
bool negative{false};
|
bool negative{false};
|
||||||
#endif
|
#endif
|
||||||
@ -338,8 +338,8 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
UC const *const end_of_integer_part = p;
|
UC const *const end_of_integer_part = p;
|
||||||
uint16_t digit_count = uint16_t(end_of_integer_part - start_digits);
|
uint32_t digit_count = uint32_t(end_of_integer_part - start_digits);
|
||||||
answer.integer = span<UC const>(start_digits, size_t(digit_count));
|
answer.integer = span<UC const>(start_digits, digit_count);
|
||||||
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
||||||
FASTFLOAT_IF_CONSTEXPR17(basic_json_fmt) {
|
FASTFLOAT_IF_CONSTEXPR17(basic_json_fmt) {
|
||||||
// at least 1 digit in integer part, without leading zeros
|
// at least 1 digit in integer part, without leading zeros
|
||||||
@ -353,7 +353,7 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int16_t exponent = 0;
|
int32_t exponent = 0;
|
||||||
bool const has_decimal_point = (p != pend) && (*p == options.decimal_point);
|
bool const has_decimal_point = (p != pend) && (*p == options.decimal_point);
|
||||||
if (has_decimal_point) {
|
if (has_decimal_point) {
|
||||||
++p;
|
++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
|
i = i * 10 + digit; // in rare cases, this will overflow, but that's ok
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
exponent = int16_t(before - p);
|
exponent = int32_t(before - p);
|
||||||
answer.fraction = span<UC const>(before, size_t(p - before));
|
answer.fraction = span<UC const>(before, uint32_t(p - before));
|
||||||
digit_count -= exponent;
|
digit_count -= exponent;
|
||||||
}
|
}
|
||||||
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
#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!
|
else if (digit_count == 0) { // we must have encountered at least one integer!
|
||||||
return report_parse_error<UC>(p, parse_error::no_digits_in_mantissa);
|
return report_parse_error<UC>(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 &&
|
if (p != pend &&
|
||||||
(uint64_t(options.format & chars_format::scientific) &&
|
(uint64_t(options.format & chars_format::scientific) &&
|
||||||
((UC('e') == *p) || (UC('E') == *p)))
|
((UC('e') == *p) || (UC('E') == *p)))
|
||||||
@ -468,7 +468,7 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
if (i >= minimal_nineteen_digit_integer) { // We have a big integers
|
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.
|
} else { // We have a value with a fractional component.
|
||||||
p = answer.fraction.ptr;
|
p = answer.fraction.ptr;
|
||||||
UC const *frac_end = p + answer.fraction.len();
|
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'));
|
i = i * 10 + uint64_t(*p - UC('0'));
|
||||||
++p;
|
++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
|
// 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++;
|
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 (digit_count == 0) {
|
||||||
if (has_leading_zeros) {
|
if (has_leading_zeros) {
|
||||||
|
|||||||
@ -19,11 +19,11 @@ namespace fast_float {
|
|||||||
#if defined(FASTFLOAT_64BIT) && !defined(__sparc)
|
#if defined(FASTFLOAT_64BIT) && !defined(__sparc)
|
||||||
#define FASTFLOAT_64BIT_LIMB 1
|
#define FASTFLOAT_64BIT_LIMB 1
|
||||||
typedef uint64_t limb;
|
typedef uint64_t limb;
|
||||||
constexpr size_t limb_bits = 64;
|
constexpr uint32_t limb_bits = 64;
|
||||||
#else
|
#else
|
||||||
#define FASTFLOAT_32BIT_LIMB
|
#define FASTFLOAT_32BIT_LIMB
|
||||||
typedef uint32_t limb;
|
typedef uint32_t limb;
|
||||||
constexpr size_t limb_bits = 32;
|
constexpr uint32_t limb_bits = 32;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef span<limb> limb_span;
|
typedef span<limb> limb_span;
|
||||||
@ -32,15 +32,15 @@ typedef span<limb> limb_span;
|
|||||||
// of bits required to store the largest bigint, which is
|
// of bits required to store the largest bigint, which is
|
||||||
// `log2(10**(digits + max_exp))`, or `log2(10**(767 + 342))`, or
|
// `log2(10**(digits + max_exp))`, or `log2(10**(767 + 342))`, or
|
||||||
// ~3600 bits, so we round to 4000.
|
// ~3600 bits, so we round to 4000.
|
||||||
constexpr size_t bigint_bits = 4000;
|
constexpr uint32_t bigint_bits = 4000;
|
||||||
constexpr size_t bigint_limbs = bigint_bits / limb_bits;
|
constexpr uint32_t bigint_limbs = bigint_bits / limb_bits;
|
||||||
|
|
||||||
// vector-like type that is allocated on the stack. the entire
|
// vector-like type that is allocated on the stack. the entire
|
||||||
// buffer is pre-allocated, and only the length changes.
|
// buffer is pre-allocated, and only the length changes.
|
||||||
template <uint8_t size> struct stackvec {
|
template <uint32_t size> struct stackvec {
|
||||||
limb data[size];
|
limb data[size];
|
||||||
// we never need more than 150 limbs
|
// we never need more than 150 limbs
|
||||||
uint8_t length{0};
|
uint32_t length{0};
|
||||||
|
|
||||||
FASTFLOAT_CONSTEXPR20 stackvec() noexcept = default;
|
FASTFLOAT_CONSTEXPR20 stackvec() noexcept = default;
|
||||||
stackvec(stackvec const &) = delete;
|
stackvec(stackvec const &) = delete;
|
||||||
@ -53,38 +53,38 @@ template <uint8_t size> struct stackvec {
|
|||||||
FASTFLOAT_ASSERT(try_extend(s));
|
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);
|
FASTFLOAT_DEBUG_ASSERT(index < length);
|
||||||
return data[index];
|
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);
|
FASTFLOAT_DEBUG_ASSERT(index < length);
|
||||||
return data[index];
|
return data[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
// index from the end of the container
|
// 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);
|
FASTFLOAT_DEBUG_ASSERT(index < length);
|
||||||
size_t rindex = length - index - 1;
|
uint32_t rindex = length - index - 1;
|
||||||
return data[rindex];
|
return data[rindex];
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the length, without bounds checking.
|
// set the length, without bounds checking.
|
||||||
FASTFLOAT_CONSTEXPR14 void set_len(size_t len) noexcept {
|
FASTFLOAT_CONSTEXPR14 void set_len(uint32_t len) noexcept {
|
||||||
length = uint8_t(len);
|
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 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
|
// append item to vector, without bounds checking
|
||||||
FASTFLOAT_CONSTEXPR14 void push_unchecked(limb value) noexcept {
|
FASTFLOAT_CONSTEXPR14 void push_unchecked(limb value) noexcept {
|
||||||
data[length] = value;
|
data[length] = value;
|
||||||
length++;
|
++length;
|
||||||
}
|
}
|
||||||
|
|
||||||
// append item to vector, returning if item was added
|
// append item to vector, returning if item was added
|
||||||
@ -118,9 +118,9 @@ template <uint8_t size> struct stackvec {
|
|||||||
// if the new size is longer than the vector, assign value to each
|
// if the new size is longer than the vector, assign value to each
|
||||||
// appended item.
|
// appended item.
|
||||||
FASTFLOAT_CONSTEXPR20
|
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()) {
|
if (new_len > len()) {
|
||||||
size_t count = new_len - len();
|
uint32_t 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);
|
||||||
@ -131,7 +131,7 @@ template <uint8_t size> struct stackvec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// try to resize the vector, returning if the vector was resized.
|
// 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()) {
|
if (new_len > capacity()) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
@ -143,12 +143,12 @@ template <uint8_t size> struct stackvec {
|
|||||||
// check if any limbs are non-zero after the given index.
|
// check if any limbs are non-zero after the given index.
|
||||||
// this needs to be done in reverse order, since the index
|
// this needs to be done in reverse order, since the index
|
||||||
// is relative to the most significant limbs.
|
// 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()) {
|
while (index < len()) {
|
||||||
if (rindex(index) != 0) {
|
if (rindex(index) != 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
index++;
|
++index;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -156,7 +156,7 @@ template <uint8_t size> struct stackvec {
|
|||||||
// normalize the big integer, so most-significant zero limbs are removed.
|
// normalize the big integer, so most-significant zero limbs are removed.
|
||||||
FASTFLOAT_CONSTEXPR14 void normalize() noexcept {
|
FASTFLOAT_CONSTEXPR14 void normalize() noexcept {
|
||||||
while (len() > 0 && rindex(0) == 0) {
|
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.
|
// add scalar value to bigint starting from offset.
|
||||||
// used in grade school multiplication
|
// used in grade school multiplication
|
||||||
template <uint16_t size>
|
template <uint32_t size>
|
||||||
inline FASTFLOAT_CONSTEXPR20 bool small_add_from(stackvec<size> &vec, limb y,
|
inline FASTFLOAT_CONSTEXPR20 bool small_add_from(stackvec<size> &vec, limb y,
|
||||||
size_t start) noexcept {
|
uint32_t start) noexcept {
|
||||||
size_t index = start;
|
uint32_t index = start;
|
||||||
limb carry = y;
|
limb carry = y;
|
||||||
bool overflow;
|
bool overflow;
|
||||||
while (carry != 0 && index < vec.len()) {
|
while (carry != 0 && index < vec.len()) {
|
||||||
vec[index] = scalar_add(vec[index], carry, overflow);
|
vec[index] = scalar_add(vec[index], carry, overflow);
|
||||||
carry = limb(overflow);
|
carry = limb(overflow);
|
||||||
index += 1;
|
++index;
|
||||||
}
|
}
|
||||||
if (carry != 0) {
|
if (carry != 0) {
|
||||||
FASTFLOAT_TRY(vec.try_push(carry));
|
FASTFLOAT_TRY(vec.try_push(carry));
|
||||||
@ -276,18 +276,18 @@ inline FASTFLOAT_CONSTEXPR20 bool small_add_from(stackvec<size> &vec, limb y,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add scalar value to bigint.
|
// add scalar value to bigint.
|
||||||
template <uint16_t size>
|
template <uint32_t size>
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool
|
||||||
small_add(stackvec<size> &vec, limb y) noexcept {
|
small_add(stackvec<size> &vec, limb y) noexcept {
|
||||||
return small_add_from(vec, y, 0);
|
return small_add_from(vec, y, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// multiply bigint by scalar value.
|
// multiply bigint by scalar value.
|
||||||
template <uint16_t size>
|
template <uint32_t size>
|
||||||
inline FASTFLOAT_CONSTEXPR20 bool small_mul(stackvec<size> &vec,
|
inline FASTFLOAT_CONSTEXPR20 bool small_mul(stackvec<size> &vec,
|
||||||
limb y) noexcept {
|
limb y) noexcept {
|
||||||
limb carry = 0;
|
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);
|
vec[index] = scalar_mul(vec[index], y, carry);
|
||||||
}
|
}
|
||||||
if (carry != 0) {
|
if (carry != 0) {
|
||||||
@ -298,9 +298,9 @@ inline FASTFLOAT_CONSTEXPR20 bool small_mul(stackvec<size> &vec,
|
|||||||
|
|
||||||
// add bigint to bigint starting from index.
|
// add bigint to bigint starting from index.
|
||||||
// used in grade school multiplication
|
// used in grade school multiplication
|
||||||
template <uint16_t size>
|
template <uint32_t size>
|
||||||
FASTFLOAT_CONSTEXPR20 bool large_add_from(stackvec<size> &x, limb_span y,
|
FASTFLOAT_CONSTEXPR20 bool large_add_from(stackvec<size> &x, limb_span y,
|
||||||
size_t start) noexcept {
|
uint32_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() > x.len() - start) {
|
if (x.len() < start || y.len() > x.len() - start) {
|
||||||
@ -308,7 +308,7 @@ FASTFLOAT_CONSTEXPR20 bool large_add_from(stackvec<size> &x, limb_span y,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool carry = false;
|
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 xi = x[index + start];
|
||||||
limb yi = y[index];
|
limb yi = y[index];
|
||||||
bool c1 = false;
|
bool c1 = false;
|
||||||
@ -329,14 +329,14 @@ FASTFLOAT_CONSTEXPR20 bool large_add_from(stackvec<size> &x, limb_span y,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add bigint to bigint.
|
// add bigint to bigint.
|
||||||
template <uint16_t size>
|
template <uint32_t size>
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool
|
||||||
large_add_from(stackvec<size> &x, limb_span y) noexcept {
|
large_add_from(stackvec<size> &x, limb_span y) noexcept {
|
||||||
return large_add_from(x, y, 0);
|
return large_add_from(x, y, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// grade-school multiplication algorithm
|
// grade-school multiplication algorithm
|
||||||
template <uint16_t size>
|
template <uint32_t size>
|
||||||
FASTFLOAT_CONSTEXPR20 bool long_mul(stackvec<size> &x, limb_span y) noexcept {
|
FASTFLOAT_CONSTEXPR20 bool long_mul(stackvec<size> &x, limb_span y) noexcept {
|
||||||
limb_span xs = limb_span(x.data, x.len());
|
limb_span xs = limb_span(x.data, x.len());
|
||||||
stackvec<size> z(xs);
|
stackvec<size> z(xs);
|
||||||
@ -345,7 +345,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 (size_t index = 1; index < y.len(); index++) {
|
for (uint32_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) {
|
||||||
@ -364,7 +364,7 @@ FASTFLOAT_CONSTEXPR20 bool long_mul(stackvec<size> &x, limb_span y) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// grade-school multiplication algorithm
|
// grade-school multiplication algorithm
|
||||||
template <uint16_t size>
|
template <uint32_t size>
|
||||||
FASTFLOAT_CONSTEXPR20 bool large_mul(stackvec<size> &x, limb_span y) noexcept {
|
FASTFLOAT_CONSTEXPR20 bool large_mul(stackvec<size> &x, limb_span y) noexcept {
|
||||||
if (y.len() == 1) {
|
if (y.len() == 1) {
|
||||||
FASTFLOAT_TRY(small_mul(x, y[0]));
|
FASTFLOAT_TRY(small_mul(x, y[0]));
|
||||||
@ -493,7 +493,7 @@ struct bigint : pow5_tables<> {
|
|||||||
} else if (vec.len() < other.vec.len()) {
|
} else if (vec.len() < other.vec.len()) {
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} 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 xi = vec[index - 1];
|
||||||
limb yi = other.vec[index - 1];
|
limb yi = other.vec[index - 1];
|
||||||
if (xi > yi) {
|
if (xi > yi) {
|
||||||
@ -508,7 +508,7 @@ struct bigint : pow5_tables<> {
|
|||||||
|
|
||||||
// shift left each limb n bits, carrying over to the new limb
|
// shift left each limb n bits, carrying over to the new limb
|
||||||
// returns true if we were able to shift all the digits.
|
// 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
|
// Internally, for each item, we shift left by n, and add the previous
|
||||||
// right shifted limb-bits.
|
// right shifted limb-bits.
|
||||||
// For example, we transform (for u8) shifted left 2, to:
|
// 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 != 0);
|
||||||
FASTFLOAT_DEBUG_ASSERT(n < sizeof(limb) * 8);
|
FASTFLOAT_DEBUG_ASSERT(n < sizeof(limb) * 8);
|
||||||
|
|
||||||
size_t const shl = n;
|
uint32_t const shl = n;
|
||||||
size_t const shr = limb_bits - shl;
|
uint32_t const shr = limb_bits - shl;
|
||||||
limb prev = 0;
|
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];
|
limb xi = vec[index];
|
||||||
vec[index] = (xi << shl) | (prev >> shr);
|
vec[index] = (xi << shl) | (prev >> shr);
|
||||||
prev = xi;
|
prev = xi;
|
||||||
@ -534,7 +534,7 @@ struct bigint : pow5_tables<> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// move the limbs left by `n` limbs.
|
// 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);
|
FASTFLOAT_DEBUG_ASSERT(n != 0);
|
||||||
if (n + vec.len() > vec.capacity()) {
|
if (n + vec.len() > vec.capacity()) {
|
||||||
return false;
|
return false;
|
||||||
@ -555,9 +555,9 @@ struct bigint : pow5_tables<> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// move the limbs left by `n` bits.
|
// move the limbs left by `n` bits.
|
||||||
FASTFLOAT_CONSTEXPR20 bool shl(size_t n) noexcept {
|
FASTFLOAT_CONSTEXPR20 bool shl(uint32_t n) noexcept {
|
||||||
size_t const rem = n % limb_bits;
|
uint32_t const rem = n % limb_bits;
|
||||||
size_t const div = n / limb_bits;
|
uint32_t const div = n / limb_bits;
|
||||||
if (rem != 0) {
|
if (rem != 0) {
|
||||||
FASTFLOAT_TRY(shl_bits(rem));
|
FASTFLOAT_TRY(shl_bits(rem));
|
||||||
}
|
}
|
||||||
@ -605,11 +605,11 @@ struct bigint : pow5_tables<> {
|
|||||||
exp -= large_step;
|
exp -= large_step;
|
||||||
}
|
}
|
||||||
#ifdef FASTFLOAT_64BIT_LIMB
|
#ifdef FASTFLOAT_64BIT_LIMB
|
||||||
uint8_t small_step = 27;
|
uint32_t const small_step = 27;
|
||||||
limb max_native = 7450580596923828125UL;
|
limb const max_native = 7450580596923828125UL;
|
||||||
#else
|
#else
|
||||||
uint8_t small_step = 13;
|
uint32_t const small_step = 13;
|
||||||
limb max_native = 1220703125U;
|
limb const max_native = 1220703125U;
|
||||||
#endif
|
#endif
|
||||||
while (exp >= small_step) {
|
while (exp >= small_step) {
|
||||||
FASTFLOAT_TRY(small_mul(vec, max_native));
|
FASTFLOAT_TRY(small_mul(vec, max_native));
|
||||||
|
|||||||
@ -17,7 +17,7 @@ namespace fast_float {
|
|||||||
// most significant bits and the low part corresponding to the least significant
|
// most significant bits and the low part corresponding to the least significant
|
||||||
// bits.
|
// bits.
|
||||||
//
|
//
|
||||||
template <uint8_t bit_precision>
|
template <uint32_t bit_precision>
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 value128
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 value128
|
||||||
compute_product_approximation(int64_t q, uint64_t w) noexcept {
|
compute_product_approximation(int64_t q, uint64_t w) noexcept {
|
||||||
int const index = 2 * int(q - powers::smallest_power_of_five);
|
int const index = 2 * int(q - powers::smallest_power_of_five);
|
||||||
|
|||||||
@ -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
|
// 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.
|
// to slow down performance for faster algorithms, and this is still fast.
|
||||||
template <typename UC>
|
template <typename UC>
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 int16_t
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 int32_t
|
||||||
scientific_exponent(parsed_number_string_t<UC> const &num) noexcept {
|
scientific_exponent(parsed_number_string_t<UC> const &num) noexcept {
|
||||||
uint64_t mantissa = num.mantissa;
|
uint64_t mantissa = num.mantissa;
|
||||||
int16_t exponent = num.exponent;
|
int32_t exponent = num.exponent;
|
||||||
while (mantissa >= 10000) {
|
while (mantissa >= 10000) {
|
||||||
mantissa /= 10000;
|
mantissa /= 10000;
|
||||||
exponent += 4;
|
exponent += 4;
|
||||||
@ -223,8 +223,8 @@ is_truncated(span<UC const> s) noexcept {
|
|||||||
|
|
||||||
template <typename UC>
|
template <typename UC>
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void
|
||||||
parse_eight_digits(UC const *&p, limb &value, uint16_t &counter,
|
parse_eight_digits(UC const *&p, limb &value, uint32_t &counter,
|
||||||
uint16_t &count) noexcept {
|
uint32_t &count) noexcept {
|
||||||
value = value * 100000000 + parse_eight_digits_unrolled(p);
|
value = value * 100000000 + parse_eight_digits_unrolled(p);
|
||||||
p += 8;
|
p += 8;
|
||||||
counter += 8;
|
counter += 8;
|
||||||
@ -233,8 +233,8 @@ parse_eight_digits(UC const *&p, limb &value, uint16_t &counter,
|
|||||||
|
|
||||||
template <typename UC>
|
template <typename UC>
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void
|
||||||
parse_one_digit(UC const *&p, limb &value, uint16_t &counter,
|
parse_one_digit(UC const *&p, limb &value, uint32_t &counter,
|
||||||
uint16_t &count) noexcept {
|
uint32_t &count) noexcept {
|
||||||
value = value * 10 + limb(*p - UC('0'));
|
value = value * 10 + limb(*p - UC('0'));
|
||||||
p++;
|
p++;
|
||||||
counter++;
|
counter++;
|
||||||
@ -248,7 +248,7 @@ add_native(bigint &big, limb power, limb value) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void
|
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
|
// need to round-up the digits, but need to avoid rounding
|
||||||
// ....9999 to ...10000, which could cause a false halfway point.
|
// ....9999 to ...10000, which could cause a false halfway point.
|
||||||
add_native(big, 10, 1);
|
add_native(big, 10, 1);
|
||||||
@ -259,17 +259,17 @@ round_up_bigint(bigint &big, uint16_t &count) noexcept {
|
|||||||
template <typename UC>
|
template <typename UC>
|
||||||
inline FASTFLOAT_CONSTEXPR20 void
|
inline FASTFLOAT_CONSTEXPR20 void
|
||||||
parse_mantissa(bigint &result, const parsed_number_string_t<UC> &num,
|
parse_mantissa(bigint &result, const parsed_number_string_t<UC> &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.
|
// 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
|
// therefore, try to parse 8 digits at a time, and multiply by the largest
|
||||||
// scalar value (9 or 19 digits) for each step.
|
// scalar value (9 or 19 digits) for each step.
|
||||||
uint16_t counter = 0;
|
uint32_t counter = 0;
|
||||||
digits = 0;
|
digits = 0;
|
||||||
limb value = 0;
|
limb value = 0;
|
||||||
#ifdef FASTFLOAT_64BIT_LIMB
|
#ifdef FASTFLOAT_64BIT_LIMB
|
||||||
uint16_t const step = 19;
|
uint32_t const step = 19;
|
||||||
#else
|
#else
|
||||||
uint16_t const step = 9;
|
uint32_t const step = 9;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// process all integer digits.
|
// process all integer digits.
|
||||||
@ -440,13 +440,13 @@ inline FASTFLOAT_CONSTEXPR20 void digit_comp(
|
|||||||
// remove the invalid exponent bias
|
// remove the invalid exponent bias
|
||||||
am.power2 -= invalid_am_bias;
|
am.power2 -= invalid_am_bias;
|
||||||
|
|
||||||
int16_t sci_exp = scientific_exponent(num);
|
int32_t sci_exp = scientific_exponent(num);
|
||||||
uint16_t const max_digits = static_cast<uint16_t>(binary_format<T>::max_digits());
|
uint32_t const max_digits = uint32_t(binary_format<T>::max_digits());
|
||||||
uint16_t digits = 0;
|
uint32_t digits = 0;
|
||||||
bigint bigmant;
|
bigint bigmant;
|
||||||
parse_mantissa(bigmant, num, max_digits, digits);
|
parse_mantissa(bigmant, num, max_digits, digits);
|
||||||
// can't underflow, since digits is at most max_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) {
|
if (exponent >= 0) {
|
||||||
positive_digit_comp<T>(bigmant, am, exponent);
|
positive_digit_comp<T>(bigmant, am, exponent);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -70,14 +70,15 @@ template <typename UC> struct parse_options_t {
|
|||||||
FASTFLOAT_CONSTEXPR20 explicit parse_options_t(
|
FASTFLOAT_CONSTEXPR20 explicit parse_options_t(
|
||||||
chars_format fmt = chars_format::general, UC dot = UC('.'),
|
chars_format fmt = chars_format::general, UC dot = UC('.'),
|
||||||
int const b = 10) noexcept
|
int const b = 10) noexcept
|
||||||
: format(fmt), decimal_point(dot), base(static_cast<uint8_t>(b)) {}
|
: format(fmt), decimal_point(dot), base(b) {}
|
||||||
|
|
||||||
/** 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 */
|
||||||
UC decimal_point;
|
UC decimal_point;
|
||||||
/** The base used for integers */
|
/** 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<char>;
|
using parse_options = parse_options_t<char>;
|
||||||
@ -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
|
// a pointer and a length to a contiguous block of memory
|
||||||
template <typename T> struct span {
|
template <typename T> struct span {
|
||||||
T const *ptr;
|
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 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);
|
FASTFLOAT_DEBUG_ASSERT(index < length);
|
||||||
return ptr[index];
|
return ptr[index];
|
||||||
}
|
}
|
||||||
@ -1169,13 +1170,13 @@ fastfloat_really_inline constexpr uint8_t ch_to_digit(UC c) {
|
|||||||
return int_luts<>::chdigit[static_cast<unsigned char>(c)];
|
return int_luts<>::chdigit[static_cast<unsigned char>(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];
|
return int_luts<>::maxdigits_u64[base - 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a u64 is exactly max_digits_u64() in length, this is
|
// If a u64 is exactly max_digits_u64() in length, this is
|
||||||
// the value below which it has definitely overflowed.
|
// 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];
|
return int_luts<>::min_safe_u64[base - 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user