mirror of
https://github.com/ii64/sonic.git
synced 2026-06-21 00:46:43 +08:00
fix: check prefix in native float parsing (#86)
This commit is contained in:
parent
fa5f5026d9
commit
365da9c1a8
8 changed files with 629 additions and 635 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -19,16 +19,16 @@ var (
|
|||
_subr__lspace = **(**uintptr)(unsafe.Pointer(&_func__base)) + 238
|
||||
_subr__lzero = **(**uintptr)(unsafe.Pointer(&_func__base)) + 0
|
||||
_subr__quote = **(**uintptr)(unsafe.Pointer(&_func__base)) + 4854
|
||||
_subr__skip_array = **(**uintptr)(unsafe.Pointer(&_func__base)) + 15938
|
||||
_subr__skip_object = **(**uintptr)(unsafe.Pointer(&_func__base)) + 15973
|
||||
_subr__skip_one = **(**uintptr)(unsafe.Pointer(&_func__base)) + 13616
|
||||
_subr__skip_array = **(**uintptr)(unsafe.Pointer(&_func__base)) + 15888
|
||||
_subr__skip_object = **(**uintptr)(unsafe.Pointer(&_func__base)) + 15923
|
||||
_subr__skip_one = **(**uintptr)(unsafe.Pointer(&_func__base)) + 13566
|
||||
_subr__u64toa = **(**uintptr)(unsafe.Pointer(&_func__base)) + 3634
|
||||
_subr__unquote = **(**uintptr)(unsafe.Pointer(&_func__base)) + 5875
|
||||
_subr__value = **(**uintptr)(unsafe.Pointer(&_func__base)) + 9329
|
||||
_subr__vnumber = **(**uintptr)(unsafe.Pointer(&_func__base)) + 11904
|
||||
_subr__vsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 13066
|
||||
_subr__vstring = **(**uintptr)(unsafe.Pointer(&_func__base)) + 10935
|
||||
_subr__vunsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 13343
|
||||
_subr__value = **(**uintptr)(unsafe.Pointer(&_func__base)) + 9279
|
||||
_subr__vnumber = **(**uintptr)(unsafe.Pointer(&_func__base)) + 11854
|
||||
_subr__vsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 13016
|
||||
_subr__vstring = **(**uintptr)(unsafe.Pointer(&_func__base)) + 10885
|
||||
_subr__vunsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 13293
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -19,16 +19,16 @@ var (
|
|||
_subr__lspace = **(**uintptr)(unsafe.Pointer(&_func__base)) + 366
|
||||
_subr__lzero = **(**uintptr)(unsafe.Pointer(&_func__base)) + 0
|
||||
_subr__quote = **(**uintptr)(unsafe.Pointer(&_func__base)) + 5202
|
||||
_subr__skip_array = **(**uintptr)(unsafe.Pointer(&_func__base)) + 18358
|
||||
_subr__skip_object = **(**uintptr)(unsafe.Pointer(&_func__base)) + 18393
|
||||
_subr__skip_one = **(**uintptr)(unsafe.Pointer(&_func__base)) + 15558
|
||||
_subr__skip_array = **(**uintptr)(unsafe.Pointer(&_func__base)) + 18308
|
||||
_subr__skip_object = **(**uintptr)(unsafe.Pointer(&_func__base)) + 18343
|
||||
_subr__skip_one = **(**uintptr)(unsafe.Pointer(&_func__base)) + 15508
|
||||
_subr__u64toa = **(**uintptr)(unsafe.Pointer(&_func__base)) + 3882
|
||||
_subr__unquote = **(**uintptr)(unsafe.Pointer(&_func__base)) + 7039
|
||||
_subr__value = **(**uintptr)(unsafe.Pointer(&_func__base)) + 11282
|
||||
_subr__vnumber = **(**uintptr)(unsafe.Pointer(&_func__base)) + 13846
|
||||
_subr__vsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 15008
|
||||
_subr__vstring = **(**uintptr)(unsafe.Pointer(&_func__base)) + 12993
|
||||
_subr__vunsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 15285
|
||||
_subr__value = **(**uintptr)(unsafe.Pointer(&_func__base)) + 11232
|
||||
_subr__vnumber = **(**uintptr)(unsafe.Pointer(&_func__base)) + 13796
|
||||
_subr__vsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 14958
|
||||
_subr__vstring = **(**uintptr)(unsafe.Pointer(&_func__base)) + 12943
|
||||
_subr__vunsigned = **(**uintptr)(unsafe.Pointer(&_func__base)) + 15235
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
|||
|
|
@ -54,9 +54,9 @@ static inline u128_output mul_u64(uint64_t x, uint64_t y) {
|
|||
/* This is Eisel Lemire ParseFloat algorithm implemented in C.
|
||||
* reference: https://nigeltao.github.io/blog/2020/eisel-lemire.html
|
||||
*/
|
||||
int atof_eisel_lemire64(uint64_t mant, int exp10, int sgn, double *val) {
|
||||
bool atof_eisel_lemire64(uint64_t mant, int exp10, int sgn, double *val) {
|
||||
if (exp10 < -348 || exp10 > 347) {
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Calculate the 2-base exponent of float */
|
||||
|
|
@ -78,7 +78,7 @@ int atof_eisel_lemire64(uint64_t mant, int exp10, int sgn, double *val) {
|
|||
*/
|
||||
if ((x_hi & 0x1FF) == 0x1FF && (x_lo + mant) < mant) {
|
||||
/* lower 64 bits of POW10 mantissa */
|
||||
u128_output y = mul_u64(mant, POW10_M128_TAB[exp10 + 347][0]);
|
||||
u128_output y = mul_u64(mant, POW10_M128_TAB[exp10 + 348][0]);
|
||||
uint64_t merged_hi = x_hi;
|
||||
uint64_t merged_lo = x_lo + y.hi;
|
||||
|
||||
|
|
@ -89,7 +89,7 @@ int atof_eisel_lemire64(uint64_t mant, int exp10, int sgn, double *val) {
|
|||
|
||||
/* Still ambigunous */
|
||||
if ((merged_hi & 0x1FF) == 0x1FF && (merged_lo + 1) == 0 && (y.lo + mant) < mant) {
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
x_hi = merged_hi;
|
||||
|
|
@ -103,7 +103,7 @@ int atof_eisel_lemire64(uint64_t mant, int exp10, int sgn, double *val) {
|
|||
|
||||
/* Half-way Ambiguity */
|
||||
if ((x_lo == 0) && ((x_hi & 0x1FF) == 0) && ((ret_man & 3) == 1)) {
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If not half-way, then it's rounding to-nearest
|
||||
|
|
@ -121,17 +121,17 @@ int atof_eisel_lemire64(uint64_t mant, int exp10, int sgn, double *val) {
|
|||
* ret_exp2 >= 0x7FF means INF/inf.
|
||||
*/
|
||||
if ((ret_exp2 - 1) >= (0x7FF - 1)) {
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Get the lower 52 bits as finnal mantissa */
|
||||
uint64_t bits = (ret_exp2 << 52) | (ret_man & 0x000FFFFFFFFFFFFF);
|
||||
if (sgn == -1) {
|
||||
bits |= ((uint64_t)1) << 63;
|
||||
bits |= 1ull << 63;
|
||||
}
|
||||
*(int64_t*)val = bits;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -70,10 +70,7 @@ static inline void decimal_set(Decimal *d, const char *s, int len) {
|
|||
int i = 0;
|
||||
|
||||
decimal_init(d);
|
||||
if (s[i] == '+') {
|
||||
i++;
|
||||
}
|
||||
else if (s[i] == '-') {
|
||||
if (s[i] == '-') {
|
||||
i++;
|
||||
d->neg = 1;
|
||||
}
|
||||
|
|
@ -144,14 +141,14 @@ static inline void right_shift(Decimal *d, uint32_t k) {
|
|||
uint64_t n = 0;
|
||||
|
||||
/* Pick up enough leading digits to cover first shift */
|
||||
for (; n>>k == 0; r++) {
|
||||
for (; n >> k == 0; r++) {
|
||||
if (r >= d->nd) {
|
||||
if (n == 0) {
|
||||
d->nd = 0; // no digits for this num
|
||||
return;
|
||||
}
|
||||
/* until n has enough bits for right shift */
|
||||
while (n>>k == 0) {
|
||||
while (n >> k == 0) {
|
||||
n *= 10;
|
||||
r++;
|
||||
}
|
||||
|
|
@ -161,7 +158,7 @@ static inline void right_shift(Decimal *d, uint32_t k) {
|
|||
}
|
||||
d->dp -= r - 1; // point shift left
|
||||
|
||||
uint64_t mask = (((uint64_t)1) << k) - 1;
|
||||
uint64_t mask = (1ull << k) - 1;
|
||||
uint64_t dig = 0;
|
||||
|
||||
/* Pick up a digit, put down a digit */
|
||||
|
|
@ -191,44 +188,41 @@ static inline void right_shift(Decimal *d, uint32_t k) {
|
|||
}
|
||||
|
||||
/* Compare the leading prefix, if b is lexicographically less, return 0 */
|
||||
static inline int prefix_cmp(const char *b, const char *s, uint64_t len) {
|
||||
static inline bool prefix_is_less(const char *b, const char *s, uint64_t bn) {
|
||||
int i = 0;
|
||||
|
||||
for (; i < len; i++) {
|
||||
for (; i < bn; i++) {
|
||||
if (s[i] == '\0') {
|
||||
return false;
|
||||
}
|
||||
if (b[i] != s[i]) {
|
||||
return b[i] > s[i];
|
||||
return b[i] < s[i];
|
||||
}
|
||||
}
|
||||
/* when b is substr of s */
|
||||
if (i < DECIMAL_MAX_DNUM && s[i] >= '0' && s[i] <= '9') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return s[i] != '\0';
|
||||
}
|
||||
|
||||
/* Binary shift left (* 2) by k bits. k <= maxShift to avoid overflow */
|
||||
static inline void left_shift(Decimal *d, uint32_t k) {
|
||||
int delta = LSHIFT_TAB[k].delta;
|
||||
|
||||
if (prefix_cmp(d->d, LSHIFT_TAB[k].cutoff, d->nd) == 0){
|
||||
if (prefix_is_less(d->d, LSHIFT_TAB[k].cutoff, d->nd)){
|
||||
delta--;
|
||||
}
|
||||
|
||||
int r = d->nd - 1; // read index
|
||||
int w = d->nd + delta - 1; // write index
|
||||
int r = d->nd; // read index
|
||||
int w = d->nd + delta; // write index
|
||||
uint64_t n = 0;
|
||||
uint64_t quo = 0;
|
||||
uint64_t rem = 0;
|
||||
|
||||
/* Pick up a digit, put down a digit */
|
||||
for (; r >= 0; r--) {
|
||||
for (r--; r >= 0; r--) {
|
||||
n += (uint64_t)(d->d[r] - '0') << k;
|
||||
quo = n / 10;
|
||||
rem = n - 10 * quo;
|
||||
w--;
|
||||
if (w < DECIMAL_MAX_DNUM) {
|
||||
d->d[w] = (char)(rem + '0');
|
||||
w--;
|
||||
} else if (rem != 0) {
|
||||
/* truncated */
|
||||
d->trunc = 1;
|
||||
|
|
@ -240,9 +234,9 @@ static inline void left_shift(Decimal *d, uint32_t k) {
|
|||
while (n > 0) {
|
||||
quo = n / 10;
|
||||
rem = n - 10 * quo;
|
||||
w--;
|
||||
if (w < DECIMAL_MAX_DNUM) {
|
||||
d->d[w] = (char)(rem + '0');
|
||||
w--;
|
||||
} else if (rem != 0) {
|
||||
/* truncated */
|
||||
d->trunc = 1;
|
||||
|
|
@ -356,7 +350,7 @@ int decimal_to_f64(Decimal *d, double *val) {
|
|||
decimal_shift(d, -n); // shift right
|
||||
exp2 += n;
|
||||
}
|
||||
while ((d->dp < 0) || (d->dp == 0) && (d->d[0] < '5')) { // d < 0.5
|
||||
while ((d->dp < 0) || ((d->dp == 0) && (d->d[0] < '5'))) { // d < 0.5
|
||||
if (-d->dp >= 9) {
|
||||
n = 27;
|
||||
} else {
|
||||
|
|
@ -389,7 +383,7 @@ int decimal_to_f64(Decimal *d, double *val) {
|
|||
mant = rounded_integer(d);
|
||||
|
||||
/* Rounding might have added a bit; shift down. */
|
||||
if (mant == (((uint64_t)2) << 52)) { // mant has 54 bits
|
||||
if (mant == (2ull << 52)) { // mant has 54 bits
|
||||
mant >>= 1;
|
||||
exp2 ++;
|
||||
if ((exp2 + 1023) >= 0x7FF) {
|
||||
|
|
@ -398,7 +392,7 @@ int decimal_to_f64(Decimal *d, double *val) {
|
|||
}
|
||||
|
||||
/* Denormalized? */
|
||||
if ((mant & (((uint64_t)1) << 52)) == 0) {
|
||||
if ((mant & (1ull << 52)) == 0) {
|
||||
exp2 = -1023;
|
||||
}
|
||||
goto out;
|
||||
|
|
@ -413,7 +407,7 @@ out:
|
|||
bits = mant & 0x000FFFFFFFFFFFFF;
|
||||
bits |= (uint64_t)((exp2 + 1023) & 0x7FF) << 52;
|
||||
if (d->neg) {
|
||||
bits |= ((uint64_t)1) << 63;
|
||||
bits |= 1ull << 63;
|
||||
}
|
||||
*(uint64_t*)val = bits;
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ long skip_string(const GoString *src, long *p);
|
|||
long skip_negative(const GoString *src, long *p);
|
||||
long skip_positive(const GoString *src, long *p);
|
||||
|
||||
int atof_eisel_lemire64(uint64_t mant, int exp10, int sgn, double *val);
|
||||
bool atof_eisel_lemire64(uint64_t mant, int exp10, int sgn, double *val);
|
||||
double atof_native_decimal(const char *buf, int len);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -483,11 +483,11 @@ void vstring(const GoString *src, long *p, JsonState *ret) {
|
|||
ret->iv = val;
|
||||
|
||||
/** check whether float can represent the val exactly **/
|
||||
static inline int is_atof_exact(uint64_t man, int exp, int sgn, double *val) {
|
||||
static inline bool is_atof_exact(uint64_t man, int exp, int sgn, double *val) {
|
||||
double f = (double)man;
|
||||
|
||||
if (man >> 52 != 0) {
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sgn == -1) {
|
||||
|
|
@ -497,7 +497,7 @@ static inline int is_atof_exact(uint64_t man, int exp, int sgn, double *val) {
|
|||
|
||||
if (exp == 0 || man == 0) {
|
||||
*val = f;
|
||||
return 1;
|
||||
return true;
|
||||
} else if (exp > 0 && exp <= 15+22) {
|
||||
/* uint64 integers: accurate range <= 10^15 *
|
||||
* Powers of 10: accurate range <= 10^22, as P10_TAB *
|
||||
|
|
@ -509,17 +509,17 @@ static inline int is_atof_exact(uint64_t man, int exp, int sgn, double *val) {
|
|||
|
||||
/* f is not accurate when too larger */
|
||||
if (f > 1e15 || f < -1e15) {
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
*val = f * P10_TAB[exp];
|
||||
return 1;
|
||||
return true;
|
||||
} else if (exp < 0 && exp >= -22) {
|
||||
*val = f / P10_TAB[-exp];
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline double parse_float64(uint64_t man, int exp, int sgn, int trunc, const GoString *src, long idx) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue