mirror of
https://github.com/fastfloat/fast_float.git
synced 2025-12-06 16:56:57 +08:00
Merge branch 'main' of github.com:lemire/fast_float into main
This commit is contained in:
commit
dcc883cde8
@ -35,22 +35,6 @@ fastfloat_really_inline bool is_made_of_eight_digits_fast(const char *chars) no
|
||||
return is_made_of_eight_digits_fast(val);
|
||||
}
|
||||
|
||||
|
||||
fastfloat_really_inline uint32_t parse_four_digits_unrolled(const char *chars) noexcept {
|
||||
uint32_t val;
|
||||
::memcpy(&val, chars, sizeof(uint32_t));
|
||||
val = (val & 0x0F0F0F0F) * 2561 >> 8;
|
||||
return (val & 0x00FF00FF) * 6553601 >> 16;
|
||||
}
|
||||
|
||||
fastfloat_really_inline bool is_made_of_four_digits_fast(const char *chars) noexcept {
|
||||
uint32_t val;
|
||||
::memcpy(&val, chars, 4);
|
||||
return (((val & 0xF0F0F0F0) |
|
||||
(((val + 0x06060606) & 0xF0F0F0F0) >> 4)) ==
|
||||
0x33333333);
|
||||
}
|
||||
|
||||
struct parsed_number_string {
|
||||
int64_t exponent;
|
||||
uint64_t mantissa;
|
||||
@ -115,8 +99,8 @@ parsed_number_string parse_number_string(const char *p, const char *pend, chars_
|
||||
int32_t digit_count =
|
||||
int32_t(p - start_digits - 1); // used later to guard against overflows
|
||||
|
||||
if ((p != pend) && (('e' == *p) || ('E' == *p))) {
|
||||
if((fmt & chars_format::fixed) && !(fmt & chars_format::scientific)) { return answer; }
|
||||
if ((fmt & chars_format::scientific) && (p != pend) && (('e' == *p) || ('E' == *p))) {
|
||||
const char * location_of_e = p;
|
||||
int64_t exp_number = 0; // exponential part
|
||||
++p;
|
||||
bool neg_exp = false;
|
||||
@ -127,8 +111,12 @@ parsed_number_string parse_number_string(const char *p, const char *pend, chars_
|
||||
++p;
|
||||
}
|
||||
if ((p == pend) || !is_integer(*p)) {
|
||||
if(!(fmt & chars_format::fixed)) {
|
||||
// We are in error.
|
||||
return answer;
|
||||
}
|
||||
// Otherwise, we will be ignoring the 'e'.
|
||||
} else {
|
||||
while ((p != pend) && is_integer(*p)) {
|
||||
uint8_t digit = uint8_t(*p - '0');
|
||||
if (exp_number < 0x10000) {
|
||||
@ -137,7 +125,9 @@ parsed_number_string parse_number_string(const char *p, const char *pend, chars_
|
||||
++p;
|
||||
}
|
||||
exponent += (neg_exp ? -exp_number : exp_number);
|
||||
}
|
||||
} else {
|
||||
// If it scientific and not fixed, we have to bail out.
|
||||
if((fmt & chars_format::scientific) && !(fmt & chars_format::fixed)) { return answer; }
|
||||
}
|
||||
answer.lastmatch = p;
|
||||
@ -176,7 +166,6 @@ decimal parse_decimal(const char *p, const char *pend) noexcept {
|
||||
decimal answer;
|
||||
answer.num_digits = 0;
|
||||
answer.decimal_point = 0;
|
||||
answer.negative = false;
|
||||
answer.truncated = false;
|
||||
// any whitespace has been skipped.
|
||||
answer.negative = (*p == '-');
|
||||
@ -194,10 +183,9 @@ decimal parse_decimal(const char *p, const char *pend) noexcept {
|
||||
answer.num_digits++;
|
||||
++p;
|
||||
}
|
||||
const char *first_after_period{};
|
||||
if ((p != pend) && (*p == '.')) {
|
||||
++p;
|
||||
first_after_period = p;
|
||||
const char *first_after_period = p;
|
||||
// if we have not yet encountered a zero, we have to skip it as well
|
||||
if(answer.num_digits == 0) {
|
||||
// skip zeros
|
||||
|
||||
@ -63,6 +63,7 @@ from_chars_result parse_infnan(const char *first, const char *last, T &value) n
|
||||
}
|
||||
}
|
||||
answer.ec = std::errc::invalid_argument;
|
||||
answer.ptr = first;
|
||||
return answer;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@ -30,7 +30,7 @@ inline void trim(decimal &h) {
|
||||
|
||||
|
||||
|
||||
uint32_t number_of_digits_decimal_left_shift(decimal &h, uint32_t shift) {
|
||||
uint32_t number_of_digits_decimal_left_shift(const decimal &h, uint32_t shift) {
|
||||
shift &= 63;
|
||||
const static uint16_t number_of_digits_decimal_left_shift_table[65] = {
|
||||
0x0000, 0x0800, 0x0801, 0x0803, 0x1006, 0x1009, 0x100D, 0x1812, 0x1817,
|
||||
|
||||
@ -147,9 +147,42 @@ bool issue8() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool check_behavior() {
|
||||
const std::string input = "abc";
|
||||
double result;
|
||||
auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result);
|
||||
if(answer.ec != std::errc()) {
|
||||
std::cerr << "parsing failure as expected\n";
|
||||
// specification says ptr should point at first
|
||||
if(answer.ptr != input.data()) {
|
||||
std::cerr << "If there is no pattern match, we should have ptr equals first\n";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
std::cout << "parsed the number " << result << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool issue19() {
|
||||
const std::string input = "3.14e";
|
||||
double result;
|
||||
auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result);
|
||||
if(answer.ec != std::errc()) {
|
||||
std::cerr << "We want to parse up to 3.14\n";
|
||||
return false;
|
||||
}
|
||||
std::cout << "parsed the number " << result << std::endl;
|
||||
if(answer.ptr != input.data() + 4) {
|
||||
std::cout << "Parsed the number and stopped at the right character." << result << std::endl;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
|
||||
Assert(issue19());
|
||||
Assert(check_behavior());
|
||||
std::cout << "======= 64 bits " << std::endl;
|
||||
Assert(basic_test_64bit("INF",std::numeric_limits<double>::infinity()));
|
||||
Assert(basic_test_64bit("-INF",-std::numeric_limits<double>::infinity()));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user