Compare commits

...

14 Commits

Author SHA1 Message Date
HedgehogInTheCPP
5c123e8614
Merge 9e1d063628e6db7d4495859f74db75f6573c6892 into 7b21183a93c4a8943a2d384f207537d7330547e1 2025-11-08 21:12:49 +00:00
IRainman
9e1d063628 # tests 2025-11-09 00:12:43 +03:00
IRainman
a92f025df7 * type usage fix 2025-11-08 23:59:52 +03:00
IRainman
3e498bb3b1 * try to fix precision error on x86 platform step9. 2025-11-08 22:28:40 +03:00
IRainman
97aa629922 * try to fix precision error on x86 platform step8. 2025-11-08 22:15:17 +03:00
IRainman
1ba0d482c1 * try to fix precision error on x86 platform step7. 2025-11-08 22:01:14 +03:00
IRainman
df6b574e40 * try to fix precision error on x86 platform step6. 2025-11-08 21:38:15 +03:00
IRainman
cd62aadb1b * try to fix precision error on x86 platform step5. 2025-11-08 21:26:31 +03:00
IRainman
578b1e9898 * try to fix precision error on x86 platform step4. 2025-11-08 21:19:23 +03:00
IRainman
77ef46838c * try to fix precision error on x86 platform step3. 2025-11-08 19:40:24 +03:00
IRainman
e96afe608e * try to fix precision error on x86 platform step2. 2025-11-08 19:25:53 +03:00
IRainman
e6f2bf13b4 # test failed. 2025-11-08 19:09:45 +03:00
IRainman
62b60e0040 # Disable FASTFLOAT_HAS_BYTESWAP: step to try to fix precision error on x86 platform 2025-11-08 18:29:14 +03:00
IRainman
56d423399d * Improving in code generation -> speedup.
* fix warning in 32 bit build.
2025-11-08 18:14:39 +03:00
7 changed files with 42 additions and 40 deletions

View File

@ -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);

View File

@ -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));

View File

@ -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;

View File

@ -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

View File

@ -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.

View File

@ -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);
}

View File

@ -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