reduce register pressure.

This commit is contained in:
IRainman 2025-04-08 01:22:14 +03:00
parent 8212e9e919
commit b261492ae7
3 changed files with 33 additions and 36 deletions

View File

@ -40,7 +40,7 @@ constexpr static uint64_t powers_of_ten_uint64[] = {1UL,
// 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 int16_t
scientific_exponent(const parsed_number_string_t<UC> &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; int16_t exponent = num.exponent;
while (mantissa >= 10000) { while (mantissa >= 10000) {
@ -61,7 +61,7 @@ scientific_exponent(const parsed_number_string_t<UC> &num) 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 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();
@ -96,7 +96,7 @@ to_extended(T 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 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;
@ -341,17 +341,17 @@ parse_mantissa(bigint &result, const parsed_number_string_t<UC> &num,
} }
template <typename T> template <typename T>
inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa inline FASTFLOAT_CONSTEXPR20 void
positive_digit_comp(bigint &bigmant, int32_t exponent) noexcept { positive_digit_comp(bigint &bigmant, adjusted_mantissa &am,
int32_t const exponent) noexcept {
FASTFLOAT_ASSERT(bigmant.pow10(uint32_t(exponent))); FASTFLOAT_ASSERT(bigmant.pow10(uint32_t(exponent)));
adjusted_mantissa answer;
bool truncated; bool truncated;
answer.mantissa = bigmant.hi64(truncated); am.mantissa = bigmant.hi64(truncated);
int bias = binary_format<T>::mantissa_explicit_bits() - int32_t bias = binary_format<T>::mantissa_explicit_bits() -
binary_format<T>::minimum_exponent(); binary_format<T>::minimum_exponent();
answer.power2 = bigmant.bit_length() - 64 + bias; am.power2 = bigmant.bit_length() - 64 + bias;
round<T>(answer, [truncated](adjusted_mantissa &a, int32_t shift) { round<T>(am, [truncated](adjusted_mantissa &a, int32_t shift) {
round_nearest_tie_even( round_nearest_tie_even(
a, shift, a, shift,
[truncated](bool is_odd, bool is_halfway, bool is_above) -> bool { [truncated](bool is_odd, bool is_halfway, bool is_above) -> bool {
@ -359,8 +359,6 @@ positive_digit_comp(bigint &bigmant, int32_t exponent) noexcept {
(is_odd && is_halfway); (is_odd && is_halfway);
}); });
}); });
return answer;
} }
// the scaling here is quite simple: we have, for the real digits `m * 10^e`, // the scaling here is quite simple: we have, for the real digits `m * 10^e`,
@ -369,24 +367,26 @@ positive_digit_comp(bigint &bigmant, int32_t exponent) noexcept {
// we then need to scale by `2^(f- e)`, and then the two significant digits // we then need to scale by `2^(f- e)`, and then the two significant digits
// are of the same magnitude. // are of the same magnitude.
template <typename T> template <typename T>
inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa inline FASTFLOAT_CONSTEXPR20 void
negative_digit_comp(bigint &bigmant, const adjusted_mantissa am, negative_digit_comp(bigint &bigmant, adjusted_mantissa &am,
const int32_t exponent) noexcept { int32_t const exponent) noexcept {
bigint &real_digits = bigmant; bigint &real_digits = bigmant;
const int32_t &real_exp = exponent; const int32_t &real_exp = exponent;
// get the value of `b`, rounded down, and get a bigint representation of b+h
adjusted_mantissa am_b = am;
// gcc7 buf: use a lambda to remove the noexcept qualifier bug with
// -Wnoexcept-type.
round<T>(am_b,
[](adjusted_mantissa &a, int32_t shift) { round_down(a, shift); });
T b; T b;
to_float( {
// get the value of `b`, rounded down, and get a bigint representation of b+h
adjusted_mantissa am_b = am;
// gcc7 bug: use a lambda to remove the noexcept qualifier bug with
// -Wnoexcept-type.
round<T>(am_b,
[](adjusted_mantissa &a, int32_t shift) { round_down(a, shift); });
to_float(
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN #ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
false, false,
#endif #endif
am_b, b); am_b, b);
}
adjusted_mantissa theor = to_extended_halfway(b); adjusted_mantissa theor = to_extended_halfway(b);
bigint theor_digits(theor.mantissa); bigint theor_digits(theor.mantissa);
int32_t theor_exp = theor.power2; int32_t theor_exp = theor.power2;
@ -405,8 +405,7 @@ negative_digit_comp(bigint &bigmant, const adjusted_mantissa am,
// compare digits, and use it to director rounding // compare digits, and use it to director rounding
int ord = real_digits.compare(theor_digits); int ord = real_digits.compare(theor_digits);
adjusted_mantissa answer = am; round<T>(am, [ord](adjusted_mantissa &a, int32_t shift) {
round<T>(answer, [ord](adjusted_mantissa &a, int32_t shift) {
round_nearest_tie_even( round_nearest_tie_even(
a, shift, [ord](bool is_odd, bool _, bool __) -> bool { a, shift, [ord](bool is_odd, bool _, bool __) -> bool {
(void)_; // not needed, since we've done our comparison (void)_; // not needed, since we've done our comparison
@ -420,8 +419,6 @@ negative_digit_comp(bigint &bigmant, const adjusted_mantissa am,
} }
}); });
}); });
return answer;
} }
// parse the significant digits as a big integer to unambiguously round the // parse the significant digits as a big integer to unambiguously round the
@ -438,8 +435,8 @@ negative_digit_comp(bigint &bigmant, const adjusted_mantissa am,
// the actual digits. we then compare the big integer representations // the actual digits. we then compare the big integer representations
// of both, and use that to direct rounding. // of both, and use that to direct rounding.
template <typename T, typename UC> template <typename T, typename UC>
inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa digit_comp( inline FASTFLOAT_CONSTEXPR20 void digit_comp(
const parsed_number_string_t<UC> &num, adjusted_mantissa &am) noexcept { parsed_number_string_t<UC> const &num, adjusted_mantissa &am) noexcept {
// remove the invalid exponent bias // remove the invalid exponent bias
am.power2 -= invalid_am_bias; am.power2 -= invalid_am_bias;
@ -451,9 +448,9 @@ inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa digit_comp(
// 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; int16_t exponent = sci_exp + 1 - digits;
if (exponent >= 0) { if (exponent >= 0) {
return positive_digit_comp<T>(bigmant, exponent); positive_digit_comp<T>(bigmant, am, exponent);
} else { } else {
return negative_digit_comp<T>(bigmant, am, exponent); negative_digit_comp<T>(bigmant, am, exponent);
} }
} }

View File

@ -772,7 +772,7 @@ inline constexpr int binary_format<std::float16_t>::smallest_power_of_ten() {
} }
template <> template <>
inline constexpr unsigned int binary_format<std::float16_t>::max_digits() { inline constexpr size_t binary_format<std::float16_t>::max_digits() {
return 22; return 22;
} }
#endif // __STDCPP_FLOAT16_T__ #endif // __STDCPP_FLOAT16_T__
@ -899,7 +899,7 @@ inline constexpr int binary_format<std::bfloat16_t>::smallest_power_of_ten() {
} }
template <> template <>
inline constexpr unsigned int binary_format<std::bfloat16_t>::max_digits() { inline constexpr size_t binary_format<std::bfloat16_t>::max_digits() {
return 98; return 98;
} }
#endif // __STDCPP_BFLOAT16_T__ #endif // __STDCPP_BFLOAT16_T__
@ -1009,7 +1009,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
bool const negative, bool const negative,
#endif #endif
adjusted_mantissa const am, T &value) noexcept { adjusted_mantissa const &am, T &value) noexcept {
using equiv_uint = equiv_uint_t<T>; using equiv_uint = equiv_uint_t<T>;
equiv_uint word = equiv_uint(am.mantissa); equiv_uint word = equiv_uint(am.mantissa);
word = equiv_uint(word | equiv_uint(am.power2) word = equiv_uint(word | equiv_uint(am.power2)

View File

@ -283,7 +283,7 @@ from_chars_advanced(parsed_number_string_t<UC> const &pns, T &value) noexcept {
// and we have an invalid power (am.power2 < 0), then we need to go the long // and we have an invalid power (am.power2 < 0), then we need to go the long
// way around again. This is very uncommon. // way around again. This is very uncommon.
if (am.power2 < 0) { if (am.power2 < 0) {
am = digit_comp<T>(pns, am); digit_comp<T>(pns, am);
} }
to_float( to_float(
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN #ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN