mirror of
https://github.com/fastfloat/fast_float.git
synced 2025-12-06 16:56:57 +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;
|
return answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace fast_float
|
} // namespace fast_float
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -126,7 +126,11 @@ 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;
|
||||||
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 {
|
struct decimal {
|
||||||
@ -135,6 +139,36 @@ struct decimal {
|
|||||||
bool negative;
|
bool negative;
|
||||||
bool truncated;
|
bool truncated;
|
||||||
uint8_t digits[max_digits];
|
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[] = {
|
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
|
} // 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
|
#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) {
|
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>
|
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);
|
||||||
|
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);
|
return compute_float<binary>(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace fast_float
|
} // namespace fast_float
|
||||||
#endif
|
#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