mirror of
https://github.com/fastfloat/fast_float.git
synced 2025-12-06 08:46:49 +08:00
Let us try the long path.
This commit is contained in:
parent
644b05989d
commit
05ad45dfb5
@ -160,6 +160,7 @@ adjusted_mantissa compute_float(int64_t q, uint64_t w) noexcept {
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
||||
} // namespace fast_float
|
||||
|
||||
#endif
|
||||
|
||||
@ -126,7 +126,11 @@ value128 full_multiplication(uint64_t value1, uint64_t value2) {
|
||||
struct adjusted_mantissa {
|
||||
uint64_t mantissa;
|
||||
int power2;
|
||||
adjusted_mantissa() : mantissa(0), power2(0) {}
|
||||
adjusted_mantissa() = default;
|
||||
//bool operator==(const adjusted_mantissa &o) const = default;
|
||||
bool operator==(const adjusted_mantissa &o) const {
|
||||
return mantissa == o.mantissa && power2 == o.power2;
|
||||
}
|
||||
};
|
||||
|
||||
struct decimal {
|
||||
@ -135,6 +139,36 @@ struct decimal {
|
||||
bool negative;
|
||||
bool truncated;
|
||||
uint8_t digits[max_digits];
|
||||
|
||||
// generate a mantissa by truncating to 19 digits, this assumes
|
||||
// that num_digits >= 19 (caller should check).
|
||||
inline uint64_t to_truncated_mantissa() {
|
||||
const int64_t max_digit_with_overflow = 19;
|
||||
static_assert(9999999999999999999U < 0xffffffffffffffff, "cannot fit 19 digits in an uint64_t");
|
||||
static_assert(max_digit_with_overflow < max_digits, "too few max_digits");
|
||||
uint64_t val;
|
||||
// 8 first digits
|
||||
::memcpy(&val, digits, sizeof(uint64_t));
|
||||
val = val * 2561 >> 8;
|
||||
val = (val & 0x00FF00FF00FF00FF) * 6553601 >> 16;
|
||||
uint64_t mantissa = uint32_t((val & 0x0000FFFF0000FFFF) * 42949672960001 >> 32);
|
||||
// 8 more digits for a total of 16
|
||||
::memcpy(&val, digits + sizeof(uint64_t), sizeof(uint64_t));
|
||||
val = val * 2561 >> 8;
|
||||
val = (val & 0x00FF00FF00FF00FF) * 6553601 >> 16;
|
||||
uint32_t eight_digits_value = uint32_t((val & 0x0000FFFF0000FFFF) * 42949672960001 >> 32);
|
||||
mantissa = 100000000 * mantissa + eight_digits_value;
|
||||
for(size_t i = 2*sizeof(uint64_t); i < max_digit_with_overflow; i++) {
|
||||
mantissa = mantissa * 10 + digits[i]; // can be accelerated
|
||||
}
|
||||
return mantissa;
|
||||
}
|
||||
// generate an exponent matching to_truncated_mantissa()
|
||||
inline int64_t to_truncated_exponent() {
|
||||
const int64_t max_digit_with_overflow = 19;
|
||||
return decimal_point - max_digit_with_overflow;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
constexpr static double powers_of_ten_double[] = {
|
||||
@ -265,4 +299,13 @@ constexpr float binary_format<float>::exact_power_of_ten(int64_t power) {
|
||||
|
||||
} // namespace fast_float
|
||||
|
||||
// for convenience:
|
||||
#include <ostream>
|
||||
std::ostream& operator<<(std::ostream& out, const fast_float::decimal& d) {
|
||||
out << "0.";
|
||||
for(size_t i = 0; i < d.num_digits; i++) { out << int32_t(d.digits[i]); }
|
||||
out << " * 10 ** " << d.decimal_point;
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -28,20 +28,6 @@ inline void trim(decimal &h) {
|
||||
}
|
||||
}
|
||||
|
||||
/** If you ever want to see what is going on, the following function might prove handy:
|
||||
* **/
|
||||
void print(const decimal d, int32_t exp2 = 0) {
|
||||
printf("0.");
|
||||
for(size_t i = 0; i < d.num_digits; i++) {
|
||||
printf("%d", int(d.digits[i]));
|
||||
}
|
||||
printf(" * 10 **%d ", d.decimal_point);
|
||||
printf(" * 2 **%d ", exp2);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
uint32_t number_of_digits_decimal_left_shift(decimal &h, uint32_t shift) {
|
||||
@ -368,8 +354,20 @@ adjusted_mantissa compute_float(decimal &d) {
|
||||
template <typename binary>
|
||||
adjusted_mantissa parse_long_mantissa(const char *first, const char* last) {
|
||||
decimal d = parse_decimal(first, last);
|
||||
const uint64_t mantissa = d.to_truncated_mantissa();
|
||||
const int64_t exponent = d.to_truncated_exponent();
|
||||
adjusted_mantissa am1 = compute_float<binary>(exponent, mantissa);
|
||||
adjusted_mantissa am2 = compute_float<binary>(exponent, mantissa+1);
|
||||
if( am1 == am2 ) { return am1; }
|
||||
return compute_float<binary>(d);
|
||||
}
|
||||
|
||||
} // namespace fast_float
|
||||
#endif
|
||||
|
||||
/*
|
||||
uint32_t num_digits;
|
||||
int32_t decimal_point;
|
||||
bool negative;
|
||||
bool truncated;
|
||||
uint8_t digits[max_digits];*/
|
||||
Loading…
x
Reference in New Issue
Block a user