mirror of
https://github.com/fastfloat/fast_float.git
synced 2025-12-06 16:56:57 +08:00
Compare commits
13 Commits
97045b1d14
...
9e1d063628
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e1d063628 | ||
|
|
a92f025df7 | ||
|
|
3e498bb3b1 | ||
|
|
97aa629922 | ||
|
|
1ba0d482c1 | ||
|
|
df6b574e40 | ||
|
|
cd62aadb1b | ||
|
|
578b1e9898 | ||
|
|
77ef46838c | ||
|
|
e96afe608e | ||
|
|
e6f2bf13b4 | ||
|
|
62b60e0040 | ||
|
|
56d423399d |
@ -122,7 +122,7 @@ uint64_t simd_read8_to_u64(UC const *) {
|
||||
}
|
||||
|
||||
// credit @aqrit
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint64_t
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint32_t
|
||||
parse_eight_digits_unrolled(uint64_t val) noexcept {
|
||||
constexpr uint64_t mask = 0x000000FF000000FF;
|
||||
constexpr uint64_t mul1 = 0x000F424000000064; // 100 + (1000000ULL << 32)
|
||||
@ -130,12 +130,12 @@ parse_eight_digits_unrolled(uint64_t val) noexcept {
|
||||
val -= 0x3030303030303030;
|
||||
val = (val * 10) + (val >> 8); // val = (val * 2561) >> 8;
|
||||
val = (((val & mask) * mul1) + (((val >> 16) & mask) * mul2)) >> 32;
|
||||
return val;
|
||||
return uint32_t(val);
|
||||
}
|
||||
|
||||
// Call this if chars are definitely 8 digits.
|
||||
template <typename UC>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint32_t
|
||||
parse_eight_digits_unrolled(UC const *chars) noexcept {
|
||||
if (cpp20_and_in_constexpr() || !has_simd_opt<UC>()) {
|
||||
return parse_eight_digits_unrolled(read8_to_u64(chars)); // truncation okay
|
||||
@ -439,7 +439,7 @@ parse_number_string(UC const *p, UC const *pend,
|
||||
} else {
|
||||
// Now let's parse the explicit exponent.
|
||||
while ((p != pend) && is_integer(*p)) {
|
||||
if (exp_number < 0x1000) {
|
||||
if (exp_number < 0x10000) {
|
||||
// check for exponent overflow if we have too many digits.
|
||||
UC const digit = UC(*p - UC('0'));
|
||||
exp_number = 10 * exp_number + static_cast<am_pow_t>(digit);
|
||||
|
||||
@ -39,7 +39,7 @@ constexpr limb_t bigint_limbs = bigint_bits / limb_bits;
|
||||
// vector-like type that is allocated on the stack. the entire
|
||||
// buffer is pre-allocated, and only the length changes.
|
||||
template <limb_t size> struct stackvec {
|
||||
limb data[size] = {0};
|
||||
limb data[size];
|
||||
// we never need more than 150 limbs
|
||||
uint_fast8_t length{0};
|
||||
|
||||
@ -604,11 +604,11 @@ struct bigint : pow5_tables<> {
|
||||
exp -= large_step;
|
||||
}
|
||||
#ifdef FASTFLOAT_64BIT_LIMB
|
||||
limb_t const small_step = 27;
|
||||
limb const max_native = 7450580596923828125UL;
|
||||
limb_t constexpr small_step = 27;
|
||||
limb constexpr max_native = 7450580596923828125UL;
|
||||
#else
|
||||
limb_t const small_step = 13;
|
||||
limb const max_native = 1220703125U;
|
||||
limb_t constexpr small_step = 13;
|
||||
limb constexpr max_native = 1220703125U;
|
||||
#endif
|
||||
while (exp >= small_step) {
|
||||
FASTFLOAT_TRY(small_mul(vec, max_native));
|
||||
|
||||
@ -20,14 +20,14 @@ namespace fast_float {
|
||||
template <limb_t bit_precision>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 value128
|
||||
compute_product_approximation(int64_t q, uint64_t w) noexcept {
|
||||
int const index = 2 * int(q - powers::smallest_power_of_five);
|
||||
am_pow_t const index = 2 * am_pow_t(q - powers::smallest_power_of_five);
|
||||
// For small values of q, e.g., q in [0,27], the answer is always exact
|
||||
// because The line value128 firstproduct = full_multiplication(w,
|
||||
// power_of_five_128[index]); gives the exact answer.
|
||||
value128 firstproduct =
|
||||
full_multiplication(w, powers::power_of_five_128[index]);
|
||||
static_assert((bit_precision >= 0) && (bit_precision <= 64),
|
||||
" precision should be in (0,64]");
|
||||
" precision should be in [0,64]");
|
||||
constexpr uint64_t precision_mask =
|
||||
(bit_precision < 64) ? (uint64_t(0xFFFFFFFFFFFFFFFF) >> bit_precision)
|
||||
: uint64_t(0xFFFFFFFFFFFFFFFF);
|
||||
@ -40,7 +40,7 @@ compute_product_approximation(int64_t q, uint64_t w) noexcept {
|
||||
full_multiplication(w, powers::power_of_five_128[index + 1]);
|
||||
firstproduct.low += secondproduct.high;
|
||||
if (secondproduct.high > firstproduct.low) {
|
||||
firstproduct.high++;
|
||||
++firstproduct.high;
|
||||
}
|
||||
}
|
||||
return firstproduct;
|
||||
@ -71,8 +71,8 @@ constexpr fastfloat_really_inline am_pow_t power(am_pow_t q) noexcept {
|
||||
// for significant digits already multiplied by 10 ** q.
|
||||
template <typename binary>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 adjusted_mantissa
|
||||
compute_error_scaled(int64_t q, uint64_t w, int32_t lz) noexcept {
|
||||
am_pow_t hilz = static_cast<am_pow_t>(uint64_t(w >> 63) ^ 1);
|
||||
compute_error_scaled(int64_t q, uint64_t w, limb_t lz) noexcept {
|
||||
limb_t const hilz = static_cast<limb_t>((w >> 63) ^ 1);
|
||||
adjusted_mantissa answer;
|
||||
answer.mantissa = w << hilz;
|
||||
constexpr am_pow_t bias =
|
||||
@ -87,7 +87,7 @@ compute_error_scaled(int64_t q, uint64_t w, int32_t lz) noexcept {
|
||||
template <typename binary>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa
|
||||
compute_error(int64_t q, uint64_t w) noexcept {
|
||||
limb_t lz = leading_zeroes(w);
|
||||
limb_t const lz = leading_zeroes(w);
|
||||
w <<= lz;
|
||||
value128 product =
|
||||
compute_product_approximation<binary::mantissa_explicit_bits() + 3>(q, w);
|
||||
@ -119,7 +119,7 @@ compute_float(int64_t q, uint64_t w) noexcept {
|
||||
// powers::largest_power_of_five].
|
||||
|
||||
// We want the most significant bit of i to be 1. Shift if needed.
|
||||
limb_t lz = leading_zeroes(w);
|
||||
limb_t const lz = leading_zeroes(w);
|
||||
w <<= lz;
|
||||
|
||||
// The required precision is binary::mantissa_explicit_bits() + 3 because
|
||||
@ -139,8 +139,9 @@ compute_float(int64_t q, uint64_t w) noexcept {
|
||||
// branchless approach: value128 product = compute_product(q, w); but in
|
||||
// practice, we can win big with the compute_product_approximation if its
|
||||
// additional branch is easily predicted. Which is best is data specific.
|
||||
limb_t upperbit = limb_t(product.high >> 63);
|
||||
limb_t shift = limb_t(upperbit + 64 - binary::mantissa_explicit_bits() - 3);
|
||||
limb_t const upperbit = limb_t(product.high >> 63);
|
||||
limb_t const shift =
|
||||
limb_t(upperbit + 64 - binary::mantissa_explicit_bits() - 3);
|
||||
|
||||
answer.mantissa = product.high >> shift;
|
||||
|
||||
|
||||
@ -260,7 +260,7 @@ round_up_bigint(bigint &big, am_digits &count) noexcept {
|
||||
|
||||
// parse the significant digits into a big integer
|
||||
template <typename T, typename UC>
|
||||
inline FASTFLOAT_CONSTEXPR20 am_digits
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 am_digits
|
||||
parse_mantissa(bigint &result, const parsed_number_string_t<UC> &num) noexcept {
|
||||
// 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
|
||||
|
||||
@ -60,10 +60,10 @@ from_chars_advanced(UC const *first, UC const *last, T &value,
|
||||
*/
|
||||
FASTFLOAT_CONSTEXPR20 inline double
|
||||
integer_times_pow10(uint64_t const mantissa,
|
||||
int const decimal_exponent) noexcept;
|
||||
int16_t const decimal_exponent) noexcept;
|
||||
FASTFLOAT_CONSTEXPR20 inline double
|
||||
integer_times_pow10(int64_t const mantissa,
|
||||
int const decimal_exponent) noexcept;
|
||||
int16_t const decimal_exponent) noexcept;
|
||||
|
||||
/**
|
||||
* This function is a template overload of `integer_times_pow10()`
|
||||
@ -74,12 +74,12 @@ template <typename T>
|
||||
FASTFLOAT_CONSTEXPR20
|
||||
typename std::enable_if<is_supported_float_type<T>::value, T>::type
|
||||
integer_times_pow10(uint64_t const mantissa,
|
||||
int const decimal_exponent) noexcept;
|
||||
int16_t const decimal_exponent) noexcept;
|
||||
template <typename T>
|
||||
FASTFLOAT_CONSTEXPR20
|
||||
typename std::enable_if<is_supported_float_type<T>::value, T>::type
|
||||
integer_times_pow10(int64_t const mantissa,
|
||||
int const decimal_exponent) noexcept;
|
||||
int16_t const decimal_exponent) noexcept;
|
||||
|
||||
/**
|
||||
* from_chars for integer types.
|
||||
|
||||
@ -388,7 +388,7 @@ template <typename T>
|
||||
FASTFLOAT_CONSTEXPR20
|
||||
typename std::enable_if<is_supported_float_type<T>::value, T>::type
|
||||
integer_times_pow10(uint64_t const mantissa,
|
||||
int const decimal_exponent) noexcept {
|
||||
int16_t const decimal_exponent) noexcept {
|
||||
T value;
|
||||
if (clinger_fast_path_impl(mantissa, decimal_exponent,
|
||||
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
||||
@ -411,7 +411,7 @@ template <typename T>
|
||||
FASTFLOAT_CONSTEXPR20
|
||||
typename std::enable_if<is_supported_float_type<T>::value, T>::type
|
||||
integer_times_pow10(int64_t const mantissa,
|
||||
int const decimal_exponent) noexcept {
|
||||
int16_t const decimal_exponent) noexcept {
|
||||
#ifdef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
||||
FASTFLOAT_ASSUME(mantissa > 0);
|
||||
const am_mant_t m = static_cast<am_mant_t>(mantissa);
|
||||
@ -440,13 +440,13 @@ FASTFLOAT_CONSTEXPR20
|
||||
|
||||
FASTFLOAT_CONSTEXPR20 inline double
|
||||
integer_times_pow10(uint64_t const mantissa,
|
||||
int const decimal_exponent) noexcept {
|
||||
int16_t const decimal_exponent) noexcept {
|
||||
return integer_times_pow10<double>(mantissa, decimal_exponent);
|
||||
}
|
||||
|
||||
FASTFLOAT_CONSTEXPR20 inline double
|
||||
integer_times_pow10(int64_t const mantissa,
|
||||
int const decimal_exponent) noexcept {
|
||||
int16_t const decimal_exponent) noexcept {
|
||||
return integer_times_pow10<double>(mantissa, decimal_exponent);
|
||||
}
|
||||
|
||||
@ -458,7 +458,7 @@ FASTFLOAT_CONSTEXPR20
|
||||
std::is_integral<Int>::value &&
|
||||
!std::is_signed<Int>::value,
|
||||
T>::type
|
||||
integer_times_pow10(Int mantissa, int decimal_exponent) noexcept {
|
||||
integer_times_pow10(Int mantissa, int16_t decimal_exponent) noexcept {
|
||||
return integer_times_pow10<T>(static_cast<uint64_t>(mantissa),
|
||||
decimal_exponent);
|
||||
}
|
||||
@ -469,7 +469,7 @@ FASTFLOAT_CONSTEXPR20
|
||||
std::is_integral<Int>::value &&
|
||||
std::is_signed<Int>::value,
|
||||
T>::type
|
||||
integer_times_pow10(Int mantissa, int decimal_exponent) noexcept {
|
||||
integer_times_pow10(Int mantissa, int16_t decimal_exponent) noexcept {
|
||||
return integer_times_pow10<T>(static_cast<int64_t>(mantissa),
|
||||
decimal_exponent);
|
||||
}
|
||||
@ -477,14 +477,14 @@ FASTFLOAT_CONSTEXPR20
|
||||
template <typename Int>
|
||||
FASTFLOAT_CONSTEXPR20 typename std::enable_if<
|
||||
std::is_integral<Int>::value && !std::is_signed<Int>::value, double>::type
|
||||
integer_times_pow10(Int mantissa, int decimal_exponent) noexcept {
|
||||
integer_times_pow10(Int mantissa, int16_t decimal_exponent) noexcept {
|
||||
return integer_times_pow10(static_cast<uint64_t>(mantissa), decimal_exponent);
|
||||
}
|
||||
|
||||
template <typename Int>
|
||||
FASTFLOAT_CONSTEXPR20 typename std::enable_if<
|
||||
std::is_integral<Int>::value && std::is_signed<Int>::value, double>::type
|
||||
integer_times_pow10(Int mantissa, int decimal_exponent) noexcept {
|
||||
integer_times_pow10(Int mantissa, int16_t decimal_exponent) noexcept {
|
||||
return integer_times_pow10(static_cast<int64_t>(mantissa), decimal_exponent);
|
||||
}
|
||||
|
||||
|
||||
@ -69,7 +69,7 @@ template <typename T> std::string fHexAndDec(T v) {
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
const std::string_view round_name(int const d) {
|
||||
const std::string round_name(int const d) {
|
||||
switch (d) {
|
||||
case FE_UPWARD:
|
||||
return "FE_UPWARD";
|
||||
@ -2127,7 +2127,7 @@ TEST_CASE("bfloat16.general") {
|
||||
|
||||
template <typename Int, typename T, typename U>
|
||||
void verify_integer_times_pow10_result(Int const mantissa,
|
||||
int const decimal_exponent,
|
||||
int16_t const decimal_exponent,
|
||||
T const actual, U const expected) {
|
||||
static_assert(std::is_same<T, U>::value,
|
||||
"expected and actual types must match");
|
||||
@ -2145,8 +2145,8 @@ void verify_integer_times_pow10_result(Int const mantissa,
|
||||
}
|
||||
|
||||
template <typename T, typename Int>
|
||||
T calculate_integer_times_pow10_expected_result(Int const mantissa,
|
||||
int const decimal_exponent) {
|
||||
T calculate_integer_times_pow10_expected_result(
|
||||
Int const mantissa, int16_t const decimal_exponent) {
|
||||
std::string constructed_string =
|
||||
std::to_string(mantissa) + "e" + std::to_string(decimal_exponent);
|
||||
T expected_result;
|
||||
@ -2160,7 +2160,7 @@ T calculate_integer_times_pow10_expected_result(Int const mantissa,
|
||||
|
||||
template <typename Int>
|
||||
void verify_integer_times_pow10_dflt(Int const mantissa,
|
||||
int const decimal_exponent,
|
||||
int16_t const decimal_exponent,
|
||||
double const expected) {
|
||||
static_assert(std::is_integral<Int>::value);
|
||||
|
||||
@ -2174,7 +2174,7 @@ void verify_integer_times_pow10_dflt(Int const mantissa,
|
||||
|
||||
template <typename Int>
|
||||
void verify_integer_times_pow10_dflt(Int const mantissa,
|
||||
int const decimal_exponent) {
|
||||
int16_t const decimal_exponent) {
|
||||
static_assert(std::is_integral<Int>::value);
|
||||
|
||||
const auto expected_result =
|
||||
@ -2185,7 +2185,8 @@ void verify_integer_times_pow10_dflt(Int const mantissa,
|
||||
}
|
||||
|
||||
template <typename T, typename Int>
|
||||
void verify_integer_times_pow10(Int const mantissa, int const decimal_exponent,
|
||||
void verify_integer_times_pow10(Int const mantissa,
|
||||
int16_t const decimal_exponent,
|
||||
T const expected) {
|
||||
static_assert(std::is_floating_point<T>::value);
|
||||
static_assert(std::is_integral<Int>::value);
|
||||
@ -2200,7 +2201,7 @@ void verify_integer_times_pow10(Int const mantissa, int const decimal_exponent,
|
||||
|
||||
template <typename T, typename Int>
|
||||
void verify_integer_times_pow10(Int const mantissa,
|
||||
int const decimal_exponent) {
|
||||
int16_t const decimal_exponent) {
|
||||
static_assert(std::is_floating_point<T>::value);
|
||||
static_assert(std::is_integral<Int>::value);
|
||||
|
||||
@ -2213,7 +2214,7 @@ void verify_integer_times_pow10(Int const mantissa,
|
||||
namespace all_supported_types {
|
||||
template <typename Int>
|
||||
void verify_integer_times_pow10(Int const mantissa,
|
||||
int const decimal_exponent) {
|
||||
int16_t const decimal_exponent) {
|
||||
static_assert(std::is_integral<Int>::value);
|
||||
|
||||
// verify the "default" overload
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user