mirror of
https://github.com/fastfloat/fast_float.git
synced 2025-12-06 16:56:57 +08:00
Minor fix.
This commit is contained in:
parent
5c50a4c5d5
commit
47d3d443d8
@ -168,7 +168,10 @@ parsed_number_string parse_number_string(const char *p, const char *pend, chars_
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// This should always succeed since it follows a call to parse_number_string.
|
// This should always succeed since it follows a call to parse_number_string
|
||||||
|
// This function could be optimized. In particular, we could stop after 19 digits
|
||||||
|
// and try to bail out. Furthermore, we should be able to recover the computed
|
||||||
|
// exponent from the pass in parse_number_string.
|
||||||
decimal parse_decimal(const char *p, const char *pend) noexcept {
|
decimal parse_decimal(const char *p, const char *pend) noexcept {
|
||||||
decimal answer;
|
decimal answer;
|
||||||
answer.num_digits = 0;
|
answer.num_digits = 0;
|
||||||
@ -203,10 +206,13 @@ decimal parse_decimal(const char *p, const char *pend) noexcept {
|
|||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// We expect that this loop will often take the bulk of the running time
|
||||||
|
// because when a value has lots of digits, these digits often
|
||||||
while ((p + 8 <= pend) && (answer.num_digits + 8 < max_digits)) {
|
while ((p + 8 <= pend) && (answer.num_digits + 8 < max_digits)) {
|
||||||
uint64_t val;
|
uint64_t val;
|
||||||
::memcpy(&val, p, sizeof(uint64_t));
|
::memcpy(&val, p, sizeof(uint64_t));
|
||||||
if(! is_made_of_eight_digits_fast(val)) break;
|
if(! is_made_of_eight_digits_fast(val)) { break; }
|
||||||
|
// We have eight digits, process them in one go!
|
||||||
val -= 0x3030303030303030;
|
val -= 0x3030303030303030;
|
||||||
::memcpy(answer.digits + answer.num_digits, &val, sizeof(uint64_t));
|
::memcpy(answer.digits + answer.num_digits, &val, sizeof(uint64_t));
|
||||||
answer.num_digits += 8;
|
answer.num_digits += 8;
|
||||||
|
|||||||
@ -94,7 +94,7 @@ adjusted_mantissa compute_float(int64_t q, uint64_t w) noexcept {
|
|||||||
if(product.low == 0xFFFFFFFFFFFFFFFF) { // could guard it further
|
if(product.low == 0xFFFFFFFFFFFFFFFF) { // could guard it further
|
||||||
// In some very rare cases, this could happen, in which case we might need a more accurate
|
// In some very rare cases, this could happen, in which case we might need a more accurate
|
||||||
// computation that what we can provide cheaply. This is very, very unlikely.
|
// computation that what we can provide cheaply. This is very, very unlikely.
|
||||||
answer.power2 = -1;
|
answer.power2 = -1; // This (a negative value) indicates an error condition.
|
||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
// The "compute_product_approximation" function can be slightly slower than a branchless approach:
|
// The "compute_product_approximation" function can be slightly slower than a branchless approach:
|
||||||
|
|||||||
@ -125,7 +125,7 @@ value128 full_multiplication(uint64_t value1, uint64_t value2) {
|
|||||||
|
|
||||||
struct adjusted_mantissa {
|
struct adjusted_mantissa {
|
||||||
uint64_t mantissa;
|
uint64_t mantissa;
|
||||||
int power2;
|
int power2;// a negative value indicate an invalid result
|
||||||
adjusted_mantissa() = default;
|
adjusted_mantissa() = default;
|
||||||
//bool operator==(const adjusted_mantissa &o) const = default;
|
//bool operator==(const adjusted_mantissa &o) const = default;
|
||||||
bool operator==(const adjusted_mantissa &o) const {
|
bool operator==(const adjusted_mantissa &o) const {
|
||||||
|
|||||||
@ -100,9 +100,9 @@ from_chars_result from_chars(const char *first, const char *last,
|
|||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
adjusted_mantissa am = pns.too_many_digits ? parse_long_mantissa<binary_format<T>>(first,last) : compute_float<binary_format<T>>(pns.exponent, pns.mantissa);
|
adjusted_mantissa am = pns.too_many_digits ? parse_long_mantissa<binary_format<T>>(first,last) : compute_float<binary_format<T>>(pns.exponent, pns.mantissa);
|
||||||
if(am.power2 < 0) {
|
// If we called compute_float<binary_format<T>>(pns.exponent, pns.mantissa) and we have an invalid power (am.power2 < 0),
|
||||||
am = parse_long_mantissa<binary_format<T>>(first,last);
|
// then we need to go the long way around again. This is very uncommon.
|
||||||
}
|
if(am.power2 < 0) { am = parse_long_mantissa<binary_format<T>>(first,last); }
|
||||||
uint64_t word = am.mantissa;
|
uint64_t word = am.mantissa;
|
||||||
word |= uint64_t(am.power2) << binary_format<T>::mantissa_explicit_bits();
|
word |= uint64_t(am.power2) << binary_format<T>::mantissa_explicit_bits();
|
||||||
word = pns.negative
|
word = pns.negative
|
||||||
|
|||||||
@ -354,6 +354,8 @@ adjusted_mantissa compute_float(decimal &d) {
|
|||||||
template <typename binary>
|
template <typename binary>
|
||||||
adjusted_mantissa parse_long_mantissa(const char *first, const char* last) {
|
adjusted_mantissa parse_long_mantissa(const char *first, const char* last) {
|
||||||
decimal d = parse_decimal(first, last);
|
decimal d = parse_decimal(first, last);
|
||||||
|
// In some cases we can get lucky and looking at only the first 19 digits is enough.
|
||||||
|
// Let us try that.
|
||||||
const uint64_t mantissa = d.to_truncated_mantissa();
|
const uint64_t mantissa = d.to_truncated_mantissa();
|
||||||
const int64_t exponent = d.to_truncated_exponent();
|
const int64_t exponent = d.to_truncated_exponent();
|
||||||
// credit: Nigel Tao who first implemented this fast path (to my knowledge).
|
// credit: Nigel Tao who first implemented this fast path (to my knowledge).
|
||||||
@ -361,7 +363,8 @@ adjusted_mantissa parse_long_mantissa(const char *first, const char* last) {
|
|||||||
// long streams of digits are determined after 19 digits.
|
// long streams of digits are determined after 19 digits.
|
||||||
adjusted_mantissa am1 = compute_float<binary>(exponent, mantissa);
|
adjusted_mantissa am1 = compute_float<binary>(exponent, mantissa);
|
||||||
adjusted_mantissa am2 = compute_float<binary>(exponent, mantissa+1);
|
adjusted_mantissa am2 = compute_float<binary>(exponent, mantissa+1);
|
||||||
if( am1 == am2 ) { return am1; }
|
// They must both agree and be both a successful result.
|
||||||
|
if(( am1 == am2 ) && (am1.power2 >= 0)) { return am1; }
|
||||||
return compute_float<binary>(d);
|
return compute_float<binary>(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user