mirror of
https://github.com/fastfloat/fast_float.git
synced 2026-02-09 11:16:45 +08:00
Final review for a more simple merge.
Feature FASTFLOAT_TABLE_HACK_CHAR_DIGIT_LUT_DISABLED is removed because hex and bin parsing isn't working properly. Properly use FASTFLOAT_SIMD_DISABLE_WARNINGS and FASTFLOAT_SIMD_RESTORE_WARNINGS only for instructions that allow unaligned loads.
This commit is contained in:
parent
cdabfe49af
commit
d07362c459
@ -84,10 +84,10 @@ fastfloat_really_inline uint64_t simd_read8_to_u64(__m128i const &data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fastfloat_really_inline uint64_t simd_read8_to_u64(char16_t const *chars) {
|
fastfloat_really_inline uint64_t simd_read8_to_u64(char16_t const *chars) {
|
||||||
return simd_read8_to_u64(_mm_loadu_si128(reinterpret_cast<__m128i const *>(
|
FASTFLOAT_SIMD_DISABLE_WARNINGS
|
||||||
chars))); // TODO: V1032 https://pvs-studio.com/en/docs/warnings/v1032/
|
return simd_read8_to_u64(
|
||||||
// The pointer 'chars' is cast to a more strictly aligned
|
_mm_loadu_si128(reinterpret_cast<__m128i const *>(chars)));
|
||||||
// pointer type.
|
FASTFLOAT_SIMD_RESTORE_WARNINGS
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(FASTFLOAT_NEON)
|
#elif defined(FASTFLOAT_NEON)
|
||||||
@ -98,8 +98,10 @@ fastfloat_really_inline uint64_t simd_read8_to_u64(uint16x8_t const &data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fastfloat_really_inline uint64_t simd_read8_to_u64(char16_t const *chars) {
|
fastfloat_really_inline uint64_t simd_read8_to_u64(char16_t const *chars) {
|
||||||
|
FASTFLOAT_SIMD_DISABLE_WARNINGS
|
||||||
return simd_read8_to_u64(
|
return simd_read8_to_u64(
|
||||||
vld1q_u16(reinterpret_cast<uint16_t const *>(chars)));
|
vld1q_u16(reinterpret_cast<uint16_t const *>(chars)));
|
||||||
|
FASTFLOAT_SIMD_RESTORE_WARNINGS
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -118,9 +120,9 @@ uint64_t simd_read8_to_u64(UC const *) {
|
|||||||
// credit @aqrit
|
// credit @aqrit
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint32_t
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint32_t
|
||||||
parse_eight_digits_unrolled(uint64_t val) noexcept {
|
parse_eight_digits_unrolled(uint64_t val) noexcept {
|
||||||
constexpr uint64_t mask = 0x000000FF000000FF;
|
uint64_t const mask = 0x000000FF000000FF;
|
||||||
constexpr uint64_t mul1 = 0x000F424000000064; // 100 + (1000000ULL << 32)
|
uint64_t const mul1 = 0x000F424000000064; // 100 + (1000000ULL << 32)
|
||||||
constexpr uint64_t mul2 = 0x0000271000000001; // 1 + (10000ULL << 32)
|
uint64_t const mul2 = 0x0000271000000001; // 1 + (10000ULL << 32)
|
||||||
val -= 0x3030303030303030;
|
val -= 0x3030303030303030;
|
||||||
val = (val * 10) + (val >> 8); // val = (val * 2561) >> 8;
|
val = (val * 10) + (val >> 8); // val = (val * 2561) >> 8;
|
||||||
val = (((val & mask) * mul1) + (((val >> 16) & mask) * mul2)) >> 32;
|
val = (((val & mask) * mul1) + (((val >> 16) & mask) * mul2)) >> 32;
|
||||||
@ -156,11 +158,11 @@ simd_parse_if_eight_digits_unrolled(char16_t const *chars,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#ifdef FASTFLOAT_SSE2
|
#ifdef FASTFLOAT_SSE2
|
||||||
|
FASTFLOAT_SIMD_DISABLE_WARNINGS
|
||||||
// Load 8 UTF-16 characters (16 bytes)
|
// Load 8 UTF-16 characters (16 bytes)
|
||||||
__m128i const data = _mm_loadu_si128(reinterpret_cast<__m128i const *>(
|
__m128i const data =
|
||||||
chars)); // TODO: V1032 https://pvs-studio.com/en/docs/warnings/v1032/ The
|
_mm_loadu_si128(reinterpret_cast<__m128i const *>(chars));
|
||||||
// pointer 'chars' is cast to a more strictly aligned pointer
|
FASTFLOAT_SIMD_RESTORE_WARNINGS
|
||||||
// type.
|
|
||||||
|
|
||||||
// Branchless "are all digits?" trick from Lemire:
|
// Branchless "are all digits?" trick from Lemire:
|
||||||
// (x - '0') <= 9 <=> (x + 32720) <= 32729
|
// (x - '0') <= 9 <=> (x + 32720) <= 32729
|
||||||
@ -175,7 +177,9 @@ simd_parse_if_eight_digits_unrolled(char16_t const *chars,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#elif defined(FASTFLOAT_NEON)
|
#elif defined(FASTFLOAT_NEON)
|
||||||
|
FASTFLOAT_SIMD_DISABLE_WARNINGS
|
||||||
uint16x8_t const data = vld1q_u16(reinterpret_cast<uint16_t const *>(chars));
|
uint16x8_t const data = vld1q_u16(reinterpret_cast<uint16_t const *>(chars));
|
||||||
|
FASTFLOAT_SIMD_RESTORE_WARNINGS
|
||||||
|
|
||||||
// (x - '0') <= 9
|
// (x - '0') <= 9
|
||||||
// http://0x80.pl/articles/simd-parsing-int-sequences.html
|
// http://0x80.pl/articles/simd-parsing-int-sequences.html
|
||||||
@ -286,7 +290,7 @@ report_parse_error(UC const *p, parse_error error) noexcept {
|
|||||||
template <bool basic_json_fmt, typename UC>
|
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
|
// Cyclomatic complexity https://en.wikipedia.org/wiki/Cyclomatic_complexity
|
||||||
// Consider refactoring the 'parse_number_string' function.
|
// Consider refactoring the 'parse_number_string' function.
|
||||||
// FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN fix this.
|
// FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN fix this.
|
||||||
@ -295,8 +299,8 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
FASTFLOAT_ASSUME(p < pend);
|
FASTFLOAT_ASSUME(p < pend);
|
||||||
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
||||||
answer.negative = (*p == UC('-'));
|
answer.negative = (*p == UC('-'));
|
||||||
|
// C++17 20.19.3.(7.1) explicitly forbids '+' sign here
|
||||||
if (answer.negative ||
|
if (answer.negative ||
|
||||||
// C++17 20.19.3.(7.1) explicitly forbids '+' sign here
|
|
||||||
((chars_format_t(options.format & chars_format::allow_leading_plus)) &&
|
((chars_format_t(options.format & chars_format::allow_leading_plus)) &&
|
||||||
(!basic_json_fmt && *p == UC('+')))) {
|
(!basic_json_fmt && *p == UC('+')))) {
|
||||||
++p;
|
++p;
|
||||||
@ -400,8 +404,11 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
#ifdef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
#ifdef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
||||||
++p;
|
++p;
|
||||||
#else
|
#else
|
||||||
if ((UC('e') == *p) || (UC('E') == *p) || (UC('d') == *p) ||
|
if ((UC('e') == *p) || (UC('E') == *p)
|
||||||
(UC('D') == *p)) {
|
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
||||||
|
|| (UC('d') == *p) || (UC('D') == *p)
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -483,8 +490,8 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
p = answer.integer.ptr;
|
p = answer.integer.ptr;
|
||||||
UC const *int_end = p + answer.integer.len();
|
UC const *int_end = p + answer.integer.len();
|
||||||
constexpr am_mant_t minimal_nineteen_digit_integer{1000000000000000000};
|
constexpr am_mant_t minimal_nineteen_digit_integer{1000000000000000000};
|
||||||
while ((answer.mantissa < minimal_nineteen_digit_integer) &&
|
while ((p != int_end) &&
|
||||||
(p != int_end)) {
|
(answer.mantissa < minimal_nineteen_digit_integer)) {
|
||||||
answer.mantissa = static_cast<am_mant_t>(
|
answer.mantissa = static_cast<am_mant_t>(
|
||||||
answer.mantissa * 10 + static_cast<am_mant_t>(*p - UC('0')));
|
answer.mantissa * 10 + static_cast<am_mant_t>(*p - UC('0')));
|
||||||
++p;
|
++p;
|
||||||
@ -496,8 +503,8 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
// We have a value with a significant fractional component.
|
// We have a value with a significant fractional component.
|
||||||
p = answer.fraction.ptr;
|
p = answer.fraction.ptr;
|
||||||
UC const *const frac_end = p + answer.fraction.len();
|
UC const *const frac_end = p + answer.fraction.len();
|
||||||
while ((answer.mantissa < minimal_nineteen_digit_integer) &&
|
while ((p != frac_end) &&
|
||||||
(p != frac_end)) {
|
(answer.mantissa < minimal_nineteen_digit_integer)) {
|
||||||
answer.mantissa = static_cast<am_mant_t>(
|
answer.mantissa = static_cast<am_mant_t>(
|
||||||
answer.mantissa * 10 + static_cast<am_mant_t>(*p - UC('0')));
|
answer.mantissa * 10 + static_cast<am_mant_t>(*p - UC('0')));
|
||||||
++p;
|
++p;
|
||||||
@ -514,7 +521,7 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
template <typename T, typename UC>
|
template <typename T, typename UC>
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||||
parse_int_string(UC const *p, UC const *pend, T &value,
|
parse_int_string(UC const *p, UC const *pend, T &value,
|
||||||
parse_options_t<UC> const &options) noexcept {
|
parse_options_t<UC> const options) noexcept {
|
||||||
|
|
||||||
from_chars_result_t<UC> answer;
|
from_chars_result_t<UC> answer;
|
||||||
|
|
||||||
@ -645,14 +652,7 @@ parse_int_string(UC const *p, UC const *pend, T &value,
|
|||||||
loop_parse_if_eight_digits(p, pend, i); // use SIMD if possible
|
loop_parse_if_eight_digits(p, pend, i); // use SIMD if possible
|
||||||
}
|
}
|
||||||
while (p != pend) {
|
while (p != pend) {
|
||||||
#ifdef FASTFLOAT_TABLE_HACK_CHAR_DIGIT_LUT_DISABLED
|
|
||||||
const auto digit = *p;
|
|
||||||
if (!is_integer(digit)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
auto const digit = ch_to_digit(*p);
|
auto const digit = ch_to_digit(*p);
|
||||||
#endif
|
|
||||||
if (digit >= options.base) {
|
if (digit >= options.base) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -281,7 +281,7 @@ template <limb_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 (limb_t index = 0; index++ != vec.len();) {
|
for (limb_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) {
|
||||||
@ -302,7 +302,7 @@ FASTFLOAT_CONSTEXPR20 bool large_add_from(stackvec<size> &x, limb_span y,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool carry = false;
|
bool carry = false;
|
||||||
for (limb_t index = 0; index++ != y.len();) {
|
for (limb_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;
|
||||||
@ -487,7 +487,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;) {
|
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) {
|
||||||
@ -514,7 +514,7 @@ struct bigint : pow5_tables<> {
|
|||||||
bigint_bits_t const shl = n;
|
bigint_bits_t const shl = n;
|
||||||
bigint_bits_t const shr = limb_bits - shl;
|
bigint_bits_t const shr = limb_bits - shl;
|
||||||
limb prev = 0;
|
limb prev = 0;
|
||||||
for (limb_t index = 0; index++ != vec.len();) {
|
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;
|
||||||
|
|||||||
@ -139,8 +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.
|
||||||
limb_t const upperbit = limb_t(product.high >> 63);
|
auto const upperbit = limb_t(product.high >> 63);
|
||||||
limb_t const shift =
|
auto const shift =
|
||||||
limb_t(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;
|
||||||
|
|||||||
@ -58,18 +58,18 @@ scientific_exponent(am_mant_t mantissa, am_pow_t exponent) noexcept {
|
|||||||
// this converts a native floating-point number to an extended-precision float.
|
// this converts a native floating-point number to an extended-precision float.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa
|
||||||
to_extended(T const &value) noexcept {
|
to_extended(T const value) noexcept {
|
||||||
using equiv_uint = equiv_uint_t<T>;
|
using equiv_uint = equiv_uint_t<T>;
|
||||||
constexpr equiv_uint exponent_mask = binary_format<T>::exponent_mask();
|
constexpr equiv_uint exponent_mask = binary_format<T>::exponent_mask();
|
||||||
constexpr equiv_uint mantissa_mask = binary_format<T>::mantissa_mask();
|
constexpr equiv_uint mantissa_mask = binary_format<T>::mantissa_mask();
|
||||||
constexpr equiv_uint hidden_bit_mask = binary_format<T>::hidden_bit_mask();
|
constexpr equiv_uint hidden_bit_mask = binary_format<T>::hidden_bit_mask();
|
||||||
|
|
||||||
|
adjusted_mantissa am;
|
||||||
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);
|
equiv_uint const bits = bit_cast<equiv_uint, T>(value);
|
||||||
|
|
||||||
adjusted_mantissa am;
|
|
||||||
if ((bits & exponent_mask) == 0) {
|
if ((bits & exponent_mask) == 0) {
|
||||||
// denormal
|
// denormal
|
||||||
am.power2 = 1 - bias;
|
am.power2 = 1 - bias;
|
||||||
@ -90,7 +90,7 @@ to_extended(T const &value) noexcept {
|
|||||||
// halfway between b and b+u.
|
// halfway between b and b+u.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa
|
||||||
to_extended_halfway(T const &value) noexcept {
|
to_extended_halfway(T const value) noexcept {
|
||||||
adjusted_mantissa am = to_extended(value);
|
adjusted_mantissa am = to_extended(value);
|
||||||
am.mantissa <<= 1;
|
am.mantissa <<= 1;
|
||||||
am.mantissa += 1;
|
am.mantissa += 1;
|
||||||
@ -253,7 +253,7 @@ round_up_bigint(bigint &big, am_digits &count) noexcept {
|
|||||||
|
|
||||||
// parse the significant digits into a big integer
|
// parse the significant digits into a big integer
|
||||||
template <typename T, typename UC>
|
template <typename T, typename UC>
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 am_digits
|
inline FASTFLOAT_CONSTEXPR20 am_digits
|
||||||
parse_mantissa(bigint &result, const parsed_number_string_t<UC> &num) noexcept {
|
parse_mantissa(bigint &result, const parsed_number_string_t<UC> &num) 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
|
||||||
@ -369,8 +369,7 @@ template <typename T>
|
|||||||
inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa
|
inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa
|
||||||
negative_digit_comp(bigint &real_digits, adjusted_mantissa am,
|
negative_digit_comp(bigint &real_digits, adjusted_mantissa am,
|
||||||
am_pow_t const real_exp) noexcept {
|
am_pow_t const real_exp) noexcept {
|
||||||
// get the value of `b`, rounded down, and get a bigint representation of
|
// get the value of `b`, rounded down, and get a bigint representation of b+h
|
||||||
// b+h
|
|
||||||
adjusted_mantissa am_b = am;
|
adjusted_mantissa am_b = am;
|
||||||
// gcc7 bug: use a lambda to remove the noexcept qualifier bug with
|
// gcc7 bug: use a lambda to remove the noexcept qualifier bug with
|
||||||
// -Wnoexcept-type.
|
// -Wnoexcept-type.
|
||||||
|
|||||||
@ -43,7 +43,7 @@ from_chars(UC const *first, UC const *last, T &value,
|
|||||||
template <typename T, typename UC = char>
|
template <typename T, typename UC = char>
|
||||||
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||||
from_chars_advanced(UC const *first, UC const *last, T &value,
|
from_chars_advanced(UC const *first, UC const *last, T &value,
|
||||||
parse_options_t<UC> const &options) noexcept;
|
parse_options_t<UC> const options) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function multiplies an integer number by a power of 10 and returns
|
* This function multiplies an integer number by a power of 10 and returns
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
#ifndef FASTFLOAT_FAST_TABLE_H
|
#ifndef FASTFLOAT_FAST_TABLE_H
|
||||||
#define FASTFLOAT_FAST_TABLE_H
|
#define FASTFLOAT_FAST_TABLE_H
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace fast_float {
|
namespace fast_float {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -205,6 +205,21 @@ FASTFLOAT_CONSTEXPR20 To bit_cast(const From &from) {
|
|||||||
#define FASTFLOAT_HAS_SIMD 1
|
#define FASTFLOAT_HAS_SIMD 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
// disable -Wcast-align=strict (GCC only)
|
||||||
|
#define FASTFLOAT_SIMD_DISABLE_WARNINGS \
|
||||||
|
_Pragma("GCC diagnostic push") \
|
||||||
|
_Pragma("GCC diagnostic ignored \"-Wcast-align\"")
|
||||||
|
#else
|
||||||
|
#define FASTFLOAT_SIMD_DISABLE_WARNINGS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#define FASTFLOAT_SIMD_RESTORE_WARNINGS _Pragma("GCC diagnostic pop")
|
||||||
|
#else
|
||||||
|
#define FASTFLOAT_SIMD_RESTORE_WARNINGS
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef FASTFLOAT_VISUAL_STUDIO
|
#ifdef FASTFLOAT_VISUAL_STUDIO
|
||||||
#define fastfloat_really_inline __forceinline
|
#define fastfloat_really_inline __forceinline
|
||||||
#else
|
#else
|
||||||
@ -288,7 +303,7 @@ template <typename UC>
|
|||||||
inline FASTFLOAT_CONSTEXPR14 bool
|
inline FASTFLOAT_CONSTEXPR14 bool
|
||||||
fastfloat_strncasecmp(UC const *actual_mixedcase, UC const *expected_lowercase,
|
fastfloat_strncasecmp(UC const *actual_mixedcase, UC const *expected_lowercase,
|
||||||
uint_fast8_t const length) noexcept {
|
uint_fast8_t const length) noexcept {
|
||||||
for (uint_fast8_t i = 0; i++ != length;) {
|
for (uint_fast8_t i = 0; i != length; ++i) {
|
||||||
UC const actual = actual_mixedcase[i];
|
UC const actual = actual_mixedcase[i];
|
||||||
if ((actual < 256 ? actual | 32 : actual) != expected_lowercase[i]) {
|
if ((actual < 256 ? actual | 32 : actual) != expected_lowercase[i]) {
|
||||||
return false;
|
return false;
|
||||||
@ -450,8 +465,10 @@ umul128_generic(uint64_t ab, uint64_t cd, uint64_t *hi) noexcept {
|
|||||||
|
|
||||||
// slow emulation routine for 32-bit
|
// slow emulation routine for 32-bit
|
||||||
#if !defined(__MINGW64__)
|
#if !defined(__MINGW64__)
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint64_t
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint64_t_umul128(uint64_t ab,
|
||||||
_umul128(uint64_t ab, uint64_t cd, uint64_t *hi) noexcept {
|
uint64_t cd,
|
||||||
|
uint64_t *hi)
|
||||||
|
noexcept {
|
||||||
return umul128_generic(ab, cd, hi);
|
return umul128_generic(ab, cd, hi);
|
||||||
}
|
}
|
||||||
#endif // !__MINGW64__
|
#endif // !__MINGW64__
|
||||||
@ -1186,7 +1203,6 @@ template <> constexpr char8_t const *str_const_inf<char8_t>() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename = void> struct int_luts {
|
template <typename = void> struct int_luts {
|
||||||
#ifndef FASTFLOAT_TABLE_HACK_CHAR_DIGIT_LUT_DISABLED
|
|
||||||
static constexpr uint8_t chdigit[] = {
|
static constexpr uint8_t chdigit[] = {
|
||||||
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, 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,
|
||||||
@ -1206,7 +1222,6 @@ 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, 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};
|
||||||
#endif
|
|
||||||
|
|
||||||
static constexpr uint_fast8_t maxdigits_u64[] = {
|
static constexpr uint_fast8_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,
|
||||||
@ -1237,7 +1252,6 @@ template <typename T> constexpr uint64_t int_luts<T>::min_safe_u64[];
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef FASTFLOAT_TABLE_HACK_CHAR_DIGIT_LUT_DISABLED
|
|
||||||
template <typename UC>
|
template <typename UC>
|
||||||
fastfloat_really_inline constexpr uint_fast8_t ch_to_digit(UC c) noexcept {
|
fastfloat_really_inline constexpr uint_fast8_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.
|
||||||
@ -1247,7 +1261,6 @@ fastfloat_really_inline constexpr uint_fast8_t ch_to_digit(UC c) noexcept {
|
|||||||
static_cast<UnsignedUC>(
|
static_cast<UnsignedUC>(
|
||||||
-((static_cast<UnsignedUC>(c) & ~0xFFull) == 0)))];
|
-((static_cast<UnsignedUC>(c) & ~0xFFull) == 0)))];
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
fastfloat_really_inline constexpr uint_fast8_t
|
fastfloat_really_inline constexpr uint_fast8_t
|
||||||
max_digits_u64(uint_fast8_t base) noexcept {
|
max_digits_u64(uint_fast8_t base) noexcept {
|
||||||
|
|||||||
@ -148,7 +148,7 @@ template <typename T> struct from_chars_caller {
|
|||||||
template <typename UC>
|
template <typename UC>
|
||||||
FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
|
FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
|
||||||
call(UC const *first, UC const *last, T &value,
|
call(UC const *first, UC const *last, T &value,
|
||||||
parse_options_t<UC> const &options) noexcept {
|
parse_options_t<UC> const options) noexcept {
|
||||||
return from_chars_advanced(first, last, value, options);
|
return from_chars_advanced(first, last, value, options);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -322,7 +322,7 @@ from_chars_advanced(parsed_number_string_t<UC> const &pns, T &value) noexcept {
|
|||||||
template <typename T, typename UC>
|
template <typename T, typename UC>
|
||||||
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||||
from_chars_float_advanced(UC const *first, UC const *last, T &value,
|
from_chars_float_advanced(UC const *first, UC const *last, T &value,
|
||||||
parse_options_t<UC> const &options) noexcept {
|
parse_options_t<UC> const options) noexcept {
|
||||||
|
|
||||||
static_assert(is_supported_float_type<T>::value,
|
static_assert(is_supported_float_type<T>::value,
|
||||||
"only some floating-point types are supported");
|
"only some floating-point types are supported");
|
||||||
@ -400,7 +400,7 @@ FASTFLOAT_CONSTEXPR20
|
|||||||
return value;
|
return value;
|
||||||
|
|
||||||
adjusted_mantissa am =
|
adjusted_mantissa am =
|
||||||
compute_float<binary_format<double>>(decimal_exponent, mantissa);
|
compute_float<binary_format<T>>(decimal_exponent, mantissa);
|
||||||
to_float(
|
to_float(
|
||||||
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
||||||
false,
|
false,
|
||||||
@ -415,7 +415,7 @@ FASTFLOAT_CONSTEXPR20
|
|||||||
integer_times_pow10(int64_t const mantissa,
|
integer_times_pow10(int64_t const mantissa,
|
||||||
int_fast16_t const decimal_exponent) noexcept {
|
int_fast16_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);
|
||||||
#else
|
#else
|
||||||
const bool is_negative = mantissa < 0;
|
const bool is_negative = mantissa < 0;
|
||||||
@ -493,7 +493,7 @@ integer_times_pow10(Int mantissa, int_fast16_t decimal_exponent) noexcept {
|
|||||||
template <typename T, typename UC>
|
template <typename T, typename UC>
|
||||||
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||||
from_chars_int_advanced(UC const *first, UC const *last, T &value,
|
from_chars_int_advanced(UC const *first, UC const *last, T &value,
|
||||||
parse_options_t<UC> const &options) noexcept {
|
parse_options_t<UC> const options) 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");
|
||||||
@ -533,7 +533,7 @@ template <> struct from_chars_advanced_caller<1> {
|
|||||||
template <typename T, typename UC>
|
template <typename T, typename UC>
|
||||||
FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
|
FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
|
||||||
call(UC const *first, UC const *last, T &value,
|
call(UC const *first, UC const *last, T &value,
|
||||||
parse_options_t<UC> const &options) noexcept {
|
parse_options_t<UC> const options) noexcept {
|
||||||
return from_chars_float_advanced(first, last, value, options);
|
return from_chars_float_advanced(first, last, value, options);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -542,7 +542,7 @@ template <> struct from_chars_advanced_caller<2> {
|
|||||||
template <typename T, typename UC>
|
template <typename T, typename UC>
|
||||||
FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
|
FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
|
||||||
call(UC const *first, UC const *last, T &value,
|
call(UC const *first, UC const *last, T &value,
|
||||||
parse_options_t<UC> const &options) noexcept {
|
parse_options_t<UC> const options) noexcept {
|
||||||
return from_chars_int_advanced(first, last, value, options);
|
return from_chars_int_advanced(first, last, value, options);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -550,7 +550,7 @@ template <> struct from_chars_advanced_caller<2> {
|
|||||||
template <typename T, typename UC>
|
template <typename T, typename UC>
|
||||||
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||||
from_chars_advanced(UC const *first, UC const *last, T &value,
|
from_chars_advanced(UC const *first, UC const *last, T &value,
|
||||||
parse_options_t<UC> const &options) noexcept {
|
parse_options_t<UC> const options) noexcept {
|
||||||
return from_chars_advanced_caller<
|
return from_chars_advanced_caller<
|
||||||
size_t(is_supported_float_type<T>::value) +
|
size_t(is_supported_float_type<T>::value) +
|
||||||
2 * size_t(is_supported_integer_type<T>::value)>::call(first, last, value,
|
2 * size_t(is_supported_integer_type<T>::value)>::call(first, last, value,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user