mirror of
https://github.com/fastfloat/fast_float.git
synced 2026-02-08 10:46:52 +08:00
code cleanup and type usage fixes.
This commit is contained in:
parent
22605807b8
commit
fb1e92c0e2
@ -602,9 +602,9 @@ parse_int_string(UC const *p, UC const *pend, T &value,
|
|||||||
((digits.as_int + 0x46464646u) | (digits.as_int - 0x30303030u)) &
|
((digits.as_int + 0x46464646u) | (digits.as_int - 0x30303030u)) &
|
||||||
0x80808080u;
|
0x80808080u;
|
||||||
const auto tz =
|
const auto tz =
|
||||||
static_cast<uint32_t>(countr_zero_32(magic)); // 7, 15, 23, 31, or 32
|
static_cast<am_digits>(countr_zero_32(magic)); // 7, 15, 23, 31, or 32
|
||||||
uint32_t nd = (tz == 32) ? 4 : (tz >> 3);
|
am_digits nd = (tz == 32) ? 4 : (tz >> 3);
|
||||||
nd = std::min(static_cast<uint32_t>(nd), len);
|
nd = std::min(nd, len);
|
||||||
if (nd == 0) {
|
if (nd == 0) {
|
||||||
if (has_leading_zeros) {
|
if (has_leading_zeros) {
|
||||||
value = 0;
|
value = 0;
|
||||||
@ -618,7 +618,7 @@ parse_int_string(UC const *p, UC const *pend, T &value,
|
|||||||
}
|
}
|
||||||
if (nd > 3) {
|
if (nd > 3) {
|
||||||
const UC *q = p + nd;
|
const UC *q = p + nd;
|
||||||
uint_fast8_t rem = len - nd;
|
am_digits rem = len - nd;
|
||||||
while (rem) {
|
while (rem) {
|
||||||
if (*q < UC('0') || *q > UC('9'))
|
if (*q < UC('0') || *q > UC('9'))
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -41,7 +41,7 @@ constexpr limb_t bigint_limbs = bigint_bits / limb_bits;
|
|||||||
template <limb_t size> struct stackvec {
|
template <limb_t size> struct stackvec {
|
||||||
limb data[size];
|
limb data[size];
|
||||||
// we never need more than 150 limbs
|
// we never need more than 150 limbs
|
||||||
uint_fast8_t length{0};
|
limb_t length{0};
|
||||||
|
|
||||||
FASTFLOAT_CONSTEXPR20 stackvec() noexcept = default;
|
FASTFLOAT_CONSTEXPR20 stackvec() noexcept = default;
|
||||||
stackvec(stackvec const &) = delete;
|
stackvec(stackvec const &) = delete;
|
||||||
@ -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(limb_t(len() + s.len()));
|
set_len(static_cast<limb_t>(len() + 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
|
||||||
@ -123,17 +123,20 @@ template <limb_t size> struct stackvec {
|
|||||||
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);
|
||||||
|
set_len(new_len);
|
||||||
|
} else {
|
||||||
|
set_len(new_len);
|
||||||
}
|
}
|
||||||
set_len(new_len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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(limb_t new_len, limb value) noexcept {
|
FASTFLOAT_CONSTEXPR20 bool try_resize(limb_t new_len, limb value) noexcept {
|
||||||
if (new_len > capacity()) {
|
if (new_len > capacity()) {
|
||||||
return false;
|
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.
|
// check if any limbs are non-zero after the given index.
|
||||||
@ -259,9 +262,10 @@ inline FASTFLOAT_CONSTEXPR20 bool small_add_from(stackvec<size> &vec, limb y,
|
|||||||
limb_t start) noexcept {
|
limb_t start) noexcept {
|
||||||
limb carry = y;
|
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);
|
||||||
carry = limb(overflow);
|
carry = limb(overflow);
|
||||||
|
++start;
|
||||||
}
|
}
|
||||||
if (carry != 0) {
|
if (carry != 0) {
|
||||||
FASTFLOAT_TRY(vec.try_push(carry));
|
FASTFLOAT_TRY(vec.try_push(carry));
|
||||||
@ -297,8 +301,8 @@ 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() > limb_t(x.len() - start)) {
|
if (x.len() < start || y.len() > static_cast<limb_t>(x.len() - start)) {
|
||||||
FASTFLOAT_TRY(x.try_resize(limb_t(y.len() + start), 0));
|
FASTFLOAT_TRY(x.try_resize(static_cast<limb_t>(y.len() + start), 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool carry = false;
|
bool carry = false;
|
||||||
@ -317,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, limb_t(y.len() + start)));
|
FASTFLOAT_TRY(small_add_from(x, 1, static_cast<limb_t>(y.len() + start)));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -369,7 +373,7 @@ FASTFLOAT_CONSTEXPR20 bool large_mul(stackvec<size> &x, limb_span y) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename = void> struct pow5_tables {
|
template <typename = void> 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[] = {
|
static constexpr uint64_t small_power_of_5[] = {
|
||||||
1UL,
|
1UL,
|
||||||
5UL,
|
5UL,
|
||||||
@ -413,7 +417,7 @@ template <typename = void> struct pow5_tables {
|
|||||||
|
|
||||||
#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE
|
#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE
|
||||||
|
|
||||||
template <typename T> constexpr uint_fast8_t pow5_tables<T>::large_step;
|
template <typename T> constexpr limb_t pow5_tables<T>::large_step;
|
||||||
|
|
||||||
template <typename T> constexpr uint64_t pow5_tables<T>::small_power_of_5[];
|
template <typename T> constexpr uint64_t pow5_tables<T>::small_power_of_5[];
|
||||||
|
|
||||||
@ -487,7 +491,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 (limb_t index = vec.len(); index != 0; --index) {
|
for (limb_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) {
|
||||||
@ -502,7 +506,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(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
|
// 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:
|
||||||
@ -511,10 +515,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);
|
||||||
|
|
||||||
bigint_bits_t const shl = n;
|
limb_t const shl = n;
|
||||||
bigint_bits_t const shr = limb_bits - shl;
|
limb_t const shr = limb_bits - shl;
|
||||||
limb prev = 0;
|
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];
|
limb xi = vec[index];
|
||||||
vec[index] = (xi << shl) | (prev >> shr);
|
vec[index] = (xi << shl) | (prev >> shr);
|
||||||
prev = xi;
|
prev = xi;
|
||||||
@ -528,13 +532,12 @@ struct bigint : pow5_tables<> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// move the limbs left by `n` limbs.
|
// 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);
|
FASTFLOAT_DEBUG_ASSERT(n != 0);
|
||||||
if (n + vec.len() > vec.capacity()) {
|
if (n + vec.len() > vec.capacity()) {
|
||||||
// we can't shift more than the capacity of the vector.
|
// we can't shift more than the capacity of the vector.
|
||||||
return false;
|
return false;
|
||||||
}
|
} else if (!vec.is_empty()) {
|
||||||
if (!vec.is_empty()) {
|
|
||||||
// move limbs
|
// move limbs
|
||||||
limb *dst = vec.data + n;
|
limb *dst = vec.data + n;
|
||||||
limb const *src = vec.data;
|
limb const *src = vec.data;
|
||||||
@ -543,15 +546,17 @@ struct bigint : pow5_tables<> {
|
|||||||
limb *first = vec.data;
|
limb *first = vec.data;
|
||||||
limb *last = first + n;
|
limb *last = first + n;
|
||||||
::std::fill(first, last, 0);
|
::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.
|
// move the limbs left by `n` bits.
|
||||||
FASTFLOAT_CONSTEXPR20 bool shl(bigint_bits_t n) noexcept {
|
FASTFLOAT_CONSTEXPR20 bool shl(bigint_bits_t n) noexcept {
|
||||||
bigint_bits_t const rem = n % limb_bits;
|
auto const rem = static_cast<limb_t>(n % limb_bits);
|
||||||
bigint_bits_t const div = n / limb_bits;
|
auto const div = static_cast<limb_t>(n / limb_bits);
|
||||||
if (rem != 0) {
|
if (rem != 0) {
|
||||||
FASTFLOAT_TRY(shl_bits(rem));
|
FASTFLOAT_TRY(shl_bits(rem));
|
||||||
}
|
}
|
||||||
@ -566,14 +571,15 @@ struct bigint : pow5_tables<> {
|
|||||||
if (vec.is_empty()) {
|
if (vec.is_empty()) {
|
||||||
// empty vector, no bits, no zeros.
|
// empty vector, no bits, no zeros.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
} else {
|
||||||
#ifdef FASTFLOAT_64BIT_LIMB
|
#ifdef FASTFLOAT_64BIT_LIMB
|
||||||
return leading_zeroes(vec.rindex(0));
|
return leading_zeroes(vec.rindex(0));
|
||||||
#else
|
#else
|
||||||
// no use defining a specialized leading_zeroes for a 32-bit type.
|
// no use defining a specialized leading_zeroes for a 32-bit type.
|
||||||
uint64_t r0 = vec.rindex(0);
|
uint64_t r0 = vec.rindex(0);
|
||||||
return leading_zeroes(r0 << 32);
|
return leading_zeroes(r0 << 32);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the number of bits in the bigint.
|
// get the number of bits in the bigint.
|
||||||
|
|||||||
@ -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(int64_t q, uint64_t w, limb_t lz) noexcept {
|
compute_error_scaled(int64_t q, uint64_t w, limb_t lz) noexcept {
|
||||||
limb_t const hilz = static_cast<limb_t>((w >> 63) ^ 1);
|
auto const hilz = static_cast<limb_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 =
|
||||||
@ -139,9 +139,8 @@ compute_float(int64_t q, uint64_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 = limb_t(product.high >> 63);
|
limb_t const upperbit = static_cast<limb_t>(product.high >> 63);
|
||||||
auto const shift =
|
limb_t const shift = upperbit + 64 - binary::mantissa_explicit_bits() - 3;
|
||||||
limb_t(upperbit + 64 - binary::mantissa_explicit_bits() - 3);
|
|
||||||
|
|
||||||
answer.mantissa = product.high >> shift;
|
answer.mantissa = product.high >> shift;
|
||||||
|
|
||||||
|
|||||||
@ -139,7 +139,7 @@ fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void
|
|||||||
round_nearest_tie_even(adjusted_mantissa &am, am_pow_t shift,
|
round_nearest_tie_even(adjusted_mantissa &am, am_pow_t shift,
|
||||||
callback cb) noexcept {
|
callback cb) noexcept {
|
||||||
am_mant_t const mask =
|
am_mant_t const mask =
|
||||||
(shift == 64) ? UINT64_MAX : (am_mant_t(1) << shift) - 1;
|
(shift == 64) ? std::numeric_limits<am_mant_t>::max() : (am_mant_t(1) << shift) - 1;
|
||||||
am_mant_t const halfway = (shift == 0) ? 0 : 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;
|
am_mant_t truncated_bits = am.mantissa & mask;
|
||||||
bool is_above = truncated_bits > halfway;
|
bool is_above = truncated_bits > halfway;
|
||||||
|
|||||||
@ -41,6 +41,8 @@ typedef uint_fast8_t limb_t;
|
|||||||
|
|
||||||
typedef uint_fast8_t chars_format_t;
|
typedef uint_fast8_t chars_format_t;
|
||||||
|
|
||||||
|
typedef uint_fast8_t base_t;
|
||||||
|
|
||||||
enum class chars_format : chars_format_t;
|
enum class chars_format : chars_format_t;
|
||||||
|
|
||||||
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
||||||
@ -82,7 +84,7 @@ using from_chars_result = from_chars_result_t<char>;
|
|||||||
template <typename UC> struct parse_options_t {
|
template <typename UC> struct parse_options_t {
|
||||||
constexpr explicit parse_options_t(
|
constexpr explicit parse_options_t(
|
||||||
chars_format const fmt = chars_format::general, UC const dot = UC('.'),
|
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) {}
|
: format(fmt), decimal_point(dot), base(b) {}
|
||||||
|
|
||||||
/** Which number formats are accepted */
|
/** Which number formats are accepted */
|
||||||
@ -90,7 +92,7 @@ template <typename UC> struct parse_options_t {
|
|||||||
/** 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 */
|
||||||
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<char>;
|
using parse_options = parse_options_t<char>;
|
||||||
@ -298,6 +300,10 @@ struct is_supported_char_type
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
#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.
|
// Compares two ASCII strings in a case insensitive manner.
|
||||||
template <typename UC>
|
template <typename UC>
|
||||||
inline FASTFLOAT_CONSTEXPR14 bool
|
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
|
// 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;
|
||||||
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) {}
|
: ptr(_ptr), length(_length) {}
|
||||||
|
|
||||||
constexpr span() noexcept : ptr(nullptr), length(0) {}
|
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);
|
FASTFLOAT_DEBUG_ASSERT(index < length);
|
||||||
return ptr[index];
|
return ptr[index];
|
||||||
}
|
}
|
||||||
@ -345,7 +352,7 @@ struct alignas(16) value128 {
|
|||||||
constexpr value128() noexcept : low(0), high(0) {}
|
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
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 limb_t
|
||||||
leading_zeroes_generic(uint64_t input_num, uint32_t last_bit = 0) noexcept {
|
leading_zeroes_generic(uint64_t input_num, uint32_t last_bit = 0) noexcept {
|
||||||
if (input_num & uint64_t(0xffffffff00000000)) {
|
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; */
|
if (input_num & uint64_t(0x2)) { /* input_num >>= 1; */
|
||||||
last_bit |= 1;
|
last_bit |= 1;
|
||||||
}
|
}
|
||||||
return 63 - (limb_t)last_bit;
|
return 63 - static_cast<limb_t>(last_bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* result might be undefined when input_num is zero */
|
/* 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)
|
// Search the mask data from most significant bit (MSB)
|
||||||
// to least significant bit (LSB) for a set bit (1).
|
// to least significant bit (LSB) for a set bit (1).
|
||||||
_BitScanReverse64(&leading_zero, input_num);
|
_BitScanReverse64(&leading_zero, input_num);
|
||||||
return (limb_t)(63 - leading_zero);
|
return static_cast<limb_t>(63 - leading_zero);
|
||||||
#else
|
#else
|
||||||
return (limb_t)leading_zeroes_generic(input_num);
|
return static_cast<limb_t>(leading_zeroes_generic(input_num));
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
return (limb_t)__builtin_clzll(input_num);
|
return static_cast<limb_t>(__builtin_clzll(input_num));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper C++14 constexpr generic implementation of countr_zero for 32-bit */
|
/* 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) {
|
countr_zero_generic_32(uint32_t input_num) {
|
||||||
if (input_num == 0) {
|
if (input_num == 0) {
|
||||||
return 32;
|
return 32;
|
||||||
}
|
}
|
||||||
int last_bit = 0;
|
uint32_t last_bit = 0;
|
||||||
if (!(input_num & 0x0000FFFF)) {
|
if (!(input_num & 0x0000FFFF)) {
|
||||||
input_num >>= 16;
|
input_num >>= 16;
|
||||||
last_bit |= 16;
|
last_bit |= 16;
|
||||||
@ -1099,7 +1106,6 @@ binary_format<double>::hidden_bit_mask() {
|
|||||||
return 0x0010000000000000;
|
return 0x0010000000000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix for C2672: Ensure bit_cast is called with explicit template arguments
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void to_float(
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void to_float(
|
||||||
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
#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
|
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
||||||
|
|
||||||
template <typename = void> struct space_lut {
|
template <typename = void> 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, 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, 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,
|
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 <typename = void> struct space_lut {
|
|||||||
|
|
||||||
#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE
|
#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE
|
||||||
|
|
||||||
template <typename T> constexpr uint_fast8_t space_lut<T>::value[];
|
template <typename T> constexpr uint8_t space_lut<T>::value[];
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename UC> constexpr bool is_space(UC c) {
|
template <typename UC> 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
|
#endif
|
||||||
@ -1227,7 +1233,7 @@ template <typename = void> struct int_luts {
|
|||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
255, 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,
|
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};
|
15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13};
|
||||||
|
|
||||||
@ -1248,16 +1254,16 @@ template <typename = void> struct int_luts {
|
|||||||
|
|
||||||
#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE
|
#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE
|
||||||
|
|
||||||
template <typename T> constexpr uint_fast8_t int_luts<T>::chdigit[];
|
template <typename T> constexpr uint8_t int_luts<T>::chdigit[];
|
||||||
|
|
||||||
template <typename T> constexpr uint_fast8_t int_luts<T>::maxdigits_u64[];
|
template <typename T> constexpr limb_t int_luts<T>::maxdigits_u64[];
|
||||||
|
|
||||||
template <typename T> constexpr uint64_t int_luts<T>::min_safe_u64[];
|
template <typename T> constexpr uint64_t int_luts<T>::min_safe_u64[];
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename UC>
|
template <typename UC>
|
||||||
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.
|
// wchar_t and char can be signed, so we need to be careful.
|
||||||
using UnsignedUC = typename std::make_unsigned<UC>::type;
|
using UnsignedUC = typename std::make_unsigned<UC>::type;
|
||||||
return int_luts<>::chdigit[static_cast<unsigned char>(
|
return int_luts<>::chdigit[static_cast<unsigned char>(
|
||||||
@ -1266,15 +1272,13 @@ fastfloat_really_inline constexpr uint_fast8_t ch_to_digit(UC c) noexcept {
|
|||||||
-((static_cast<UnsignedUC>(c) & ~0xFFull) == 0)))];
|
-((static_cast<UnsignedUC>(c) & ~0xFFull) == 0)))];
|
||||||
}
|
}
|
||||||
|
|
||||||
fastfloat_really_inline constexpr uint_fast8_t
|
fastfloat_really_inline constexpr limb_t max_digits_u64(base_t base) noexcept {
|
||||||
max_digits_u64(uint_fast8_t base) noexcept {
|
|
||||||
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
|
fastfloat_really_inline constexpr uint64_t min_safe_u64(base_t base) noexcept {
|
||||||
min_safe_u64(uint_fast8_t base) noexcept {
|
|
||||||
return int_luts<>::min_safe_u64[base - 2];
|
return int_luts<>::min_safe_u64[base - 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -27,12 +27,13 @@ from_chars_result_t<UC>
|
|||||||
const chars_format fmt) noexcept {
|
const chars_format fmt) noexcept {
|
||||||
from_chars_result_t<UC> answer{};
|
from_chars_result_t<UC> answer{};
|
||||||
answer.ptr = first;
|
answer.ptr = first;
|
||||||
answer.ec = std::errc(); // be optimistic
|
answer.ec = std::errc(); // be optimistic
|
||||||
|
|
||||||
FASTFLOAT_ASSUME(first < last); // so dereference without checks
|
FASTFLOAT_ASSUME(first < last); // so dereference without checks
|
||||||
|
|
||||||
bool const minusSign = (*first == UC('-'));
|
bool const minusSign = (*first == UC('-'));
|
||||||
// C++17 20.19.3.(7.1) explicitly forbids '+' sign here
|
// 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)) &&
|
((chars_format_t(fmt & chars_format::allow_leading_plus)) &&
|
||||||
(*first == UC('+')))) {
|
(*first == UC('+')))) {
|
||||||
++first;
|
++first;
|
||||||
@ -375,7 +376,7 @@ from_chars_float_advanced(UC const *first, UC const *last, T &value,
|
|||||||
template <typename T, typename UC, typename>
|
template <typename T, typename UC, typename>
|
||||||
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||||
from_chars(UC const *first, UC const *last, T &value,
|
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<T>::value,
|
static_assert(is_supported_integer_type<T>::value,
|
||||||
"only integer types are supported");
|
"only integer types are supported");
|
||||||
@ -389,8 +390,8 @@ from_chars(UC const *first, UC const *last, T &value,
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
FASTFLOAT_CONSTEXPR20
|
FASTFLOAT_CONSTEXPR20
|
||||||
typename std::enable_if<is_supported_float_type<T>::value, T>::type
|
typename std::enable_if<is_supported_float_type<T>::value, T>::type
|
||||||
integer_times_pow10(uint64_t const mantissa,
|
integer_times_pow10(am_mant_t const mantissa,
|
||||||
int_fast16_t const decimal_exponent) noexcept {
|
am_pow_t const decimal_exponent) noexcept {
|
||||||
T value;
|
T value;
|
||||||
if (clinger_fast_path_impl(mantissa, decimal_exponent,
|
if (clinger_fast_path_impl(mantissa, decimal_exponent,
|
||||||
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
||||||
@ -412,8 +413,8 @@ FASTFLOAT_CONSTEXPR20
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
FASTFLOAT_CONSTEXPR20
|
FASTFLOAT_CONSTEXPR20
|
||||||
typename std::enable_if<is_supported_float_type<T>::value, T>::type
|
typename std::enable_if<is_supported_float_type<T>::value, T>::type
|
||||||
integer_times_pow10(int64_t const mantissa,
|
integer_times_pow10(am_sign_mant_t const mantissa,
|
||||||
int_fast16_t const decimal_exponent) noexcept {
|
am_pow_t const decimal_exponent) noexcept {
|
||||||
#ifdef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
#ifdef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
||||||
FASTFLOAT_ASSUME(mantissa >= 0);
|
FASTFLOAT_ASSUME(mantissa >= 0);
|
||||||
const am_mant_t m = static_cast<am_mant_t>(mantissa);
|
const am_mant_t m = static_cast<am_mant_t>(mantissa);
|
||||||
@ -441,14 +442,14 @@ FASTFLOAT_CONSTEXPR20
|
|||||||
}
|
}
|
||||||
|
|
||||||
FASTFLOAT_CONSTEXPR20 inline double
|
FASTFLOAT_CONSTEXPR20 inline double
|
||||||
integer_times_pow10(uint64_t const mantissa,
|
integer_times_pow10(am_mant_t const mantissa,
|
||||||
int_fast16_t const decimal_exponent) noexcept {
|
am_pow_t const decimal_exponent) noexcept {
|
||||||
return integer_times_pow10<double>(mantissa, decimal_exponent);
|
return integer_times_pow10<double>(mantissa, decimal_exponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
FASTFLOAT_CONSTEXPR20 inline double
|
FASTFLOAT_CONSTEXPR20 inline double
|
||||||
integer_times_pow10(int64_t const mantissa,
|
integer_times_pow10(am_sign_mant_t const mantissa,
|
||||||
int_fast16_t const decimal_exponent) noexcept {
|
am_pow_t const decimal_exponent) noexcept {
|
||||||
return integer_times_pow10<double>(mantissa, decimal_exponent);
|
return integer_times_pow10<double>(mantissa, decimal_exponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -460,8 +461,8 @@ FASTFLOAT_CONSTEXPR20
|
|||||||
std::is_integral<Int>::value &&
|
std::is_integral<Int>::value &&
|
||||||
!std::is_signed<Int>::value,
|
!std::is_signed<Int>::value,
|
||||||
T>::type
|
T>::type
|
||||||
integer_times_pow10(Int mantissa, int_fast16_t decimal_exponent) noexcept {
|
integer_times_pow10(Int mantissa, am_pow_t decimal_exponent) noexcept {
|
||||||
return integer_times_pow10<T>(static_cast<uint64_t>(mantissa),
|
return integer_times_pow10<T>(static_cast<am_mant_t>(mantissa),
|
||||||
decimal_exponent);
|
decimal_exponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -471,23 +472,24 @@ FASTFLOAT_CONSTEXPR20
|
|||||||
std::is_integral<Int>::value &&
|
std::is_integral<Int>::value &&
|
||||||
std::is_signed<Int>::value,
|
std::is_signed<Int>::value,
|
||||||
T>::type
|
T>::type
|
||||||
integer_times_pow10(Int mantissa, int_fast16_t decimal_exponent) noexcept {
|
integer_times_pow10(Int mantissa, am_pow_t decimal_exponent) noexcept {
|
||||||
return integer_times_pow10<T>(static_cast<int64_t>(mantissa),
|
return integer_times_pow10<T>(static_cast<am_sign_mant_t>(mantissa),
|
||||||
decimal_exponent);
|
decimal_exponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Int>
|
template <typename Int>
|
||||||
FASTFLOAT_CONSTEXPR20 typename std::enable_if<
|
FASTFLOAT_CONSTEXPR20 typename std::enable_if<
|
||||||
std::is_integral<Int>::value && !std::is_signed<Int>::value, double>::type
|
std::is_integral<Int>::value && !std::is_signed<Int>::value, double>::type
|
||||||
integer_times_pow10(Int mantissa, int_fast16_t decimal_exponent) noexcept {
|
integer_times_pow10(Int mantissa, am_pow_t decimal_exponent) noexcept {
|
||||||
return integer_times_pow10(static_cast<uint64_t>(mantissa), decimal_exponent);
|
return integer_times_pow10(static_cast<am_mant_t>(mantissa), decimal_exponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Int>
|
template <typename Int>
|
||||||
FASTFLOAT_CONSTEXPR20 typename std::enable_if<
|
FASTFLOAT_CONSTEXPR20 typename std::enable_if<
|
||||||
std::is_integral<Int>::value && std::is_signed<Int>::value, double>::type
|
std::is_integral<Int>::value && std::is_signed<Int>::value, double>::type
|
||||||
integer_times_pow10(Int mantissa, int_fast16_t decimal_exponent) noexcept {
|
integer_times_pow10(Int mantissa, am_pow_t decimal_exponent) noexcept {
|
||||||
return integer_times_pow10(static_cast<int64_t>(mantissa), decimal_exponent);
|
return integer_times_pow10(static_cast<am_sign_mant_t>(mantissa),
|
||||||
|
decimal_exponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename UC>
|
template <typename T, typename UC>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user