msvcrt: Support arbitrary buffer size in bnum.
Signed-off-by: Piotr Caban <piotr@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
413e34df58
commit
7495821974
|
@ -26,19 +26,26 @@ static const int p10s[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
|
||||||
|
|
||||||
#define LIMB_DIGITS 9 /* each DWORD stores up to 9 digits */
|
#define LIMB_DIGITS 9 /* each DWORD stores up to 9 digits */
|
||||||
#define LIMB_MAX 1000000000 /* 10^9 */
|
#define LIMB_MAX 1000000000 /* 10^9 */
|
||||||
#define BNUM_IDX(i) ((i) & 127)
|
|
||||||
|
#define BNUM_PREC64 128 /* data size needed to store 64-bit double */
|
||||||
/* bnum represents real number with fixed decimal point (after 2 limbs) */
|
/* bnum represents real number with fixed decimal point (after 2 limbs) */
|
||||||
struct bnum {
|
struct bnum {
|
||||||
DWORD data[128]; /* circular buffer, base 10 number */
|
|
||||||
int b; /* least significant digit position */
|
int b; /* least significant digit position */
|
||||||
int e; /* most significant digit position + 1 */
|
int e; /* most significant digit position + 1 */
|
||||||
|
int size; /* data buffer size in DWORDS (power of 2) */
|
||||||
|
DWORD data[1]; /* circular buffer, base 10 number */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline int bnum_idx(struct bnum *b, int idx)
|
||||||
|
{
|
||||||
|
return idx & (b->size - 1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Returns integral part of bnum */
|
/* Returns integral part of bnum */
|
||||||
static inline ULONGLONG bnum_to_mant(struct bnum *b)
|
static inline ULONGLONG bnum_to_mant(struct bnum *b)
|
||||||
{
|
{
|
||||||
ULONGLONG ret = (ULONGLONG)b->data[BNUM_IDX(b->e-1)] * LIMB_MAX;
|
ULONGLONG ret = (ULONGLONG)b->data[bnum_idx(b, b->e-1)] * LIMB_MAX;
|
||||||
if(b->b != b->e-1) ret += b->data[BNUM_IDX(b->e-2)];
|
if(b->b != b->e-1) ret += b->data[bnum_idx(b, b->e-2)];
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,20 +60,20 @@ static inline BOOL bnum_lshift(struct bnum *b, int shift)
|
||||||
assert(shift <= 29);
|
assert(shift <= 29);
|
||||||
|
|
||||||
for(i=b->b; i<b->e; i++) {
|
for(i=b->b; i<b->e; i++) {
|
||||||
tmp = ((ULONGLONG)b->data[BNUM_IDX(i)] << shift) + rest;
|
tmp = ((ULONGLONG)b->data[bnum_idx(b, i)] << shift) + rest;
|
||||||
rest = tmp / LIMB_MAX;
|
rest = tmp / LIMB_MAX;
|
||||||
b->data[BNUM_IDX(i)] = tmp % LIMB_MAX;
|
b->data[bnum_idx(b, i)] = tmp % LIMB_MAX;
|
||||||
|
|
||||||
if(i == b->b && !b->data[BNUM_IDX(i)])
|
if(i == b->b && !b->data[bnum_idx(b, i)])
|
||||||
b->b++;
|
b->b++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(rest) {
|
if(rest) {
|
||||||
b->data[BNUM_IDX(b->e)] = rest;
|
b->data[bnum_idx(b, b->e)] = rest;
|
||||||
b->e++;
|
b->e++;
|
||||||
|
|
||||||
if(BNUM_IDX(b->b) == BNUM_IDX(b->e)) {
|
if(bnum_idx(b, b->b) == bnum_idx(b, b->e)) {
|
||||||
if(b->data[BNUM_IDX(b->b)]) b->data[BNUM_IDX(b->b+1)] |= 1;
|
if(b->data[bnum_idx(b, b->b)]) b->data[bnum_idx(b, b->b+1)] |= 1;
|
||||||
b->b++;
|
b->b++;
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -85,21 +92,21 @@ static inline BOOL bnum_rshift(struct bnum *b, int shift)
|
||||||
assert(shift <= 9);
|
assert(shift <= 9);
|
||||||
|
|
||||||
for(i=b->e-1; i>=b->b; i--) {
|
for(i=b->e-1; i>=b->b; i--) {
|
||||||
tmp = b->data[BNUM_IDX(i)] & ((1<<shift)-1);
|
tmp = b->data[bnum_idx(b, i)] & ((1<<shift)-1);
|
||||||
b->data[BNUM_IDX(i)] = (b->data[BNUM_IDX(i)] >> shift) + rest;
|
b->data[bnum_idx(b, i)] = (b->data[bnum_idx(b, i)] >> shift) + rest;
|
||||||
rest = (LIMB_MAX >> shift) * tmp;
|
rest = (LIMB_MAX >> shift) * tmp;
|
||||||
if(i==b->e-1 && !b->data[BNUM_IDX(i)]) {
|
if(i==b->e-1 && !b->data[bnum_idx(b, i)]) {
|
||||||
b->e--;
|
b->e--;
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(rest) {
|
if(rest) {
|
||||||
if(BNUM_IDX(b->b-1) == BNUM_IDX(b->e)) {
|
if(bnum_idx(b, b->b-1) == bnum_idx(b, b->e)) {
|
||||||
if(rest) b->data[BNUM_IDX(b->b)] |= 1;
|
if(rest) b->data[bnum_idx(b, b->b)] |= 1;
|
||||||
} else {
|
} else {
|
||||||
b->b--;
|
b->b--;
|
||||||
b->data[BNUM_IDX(b->b)] = rest;
|
b->data[bnum_idx(b, b->b)] = rest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -114,20 +121,20 @@ static inline void bnum_mult(struct bnum *b, int mult)
|
||||||
assert(mult <= LIMB_MAX);
|
assert(mult <= LIMB_MAX);
|
||||||
|
|
||||||
for(i=b->b; i<b->e; i++) {
|
for(i=b->b; i<b->e; i++) {
|
||||||
tmp = ((ULONGLONG)b->data[BNUM_IDX(i)] * mult) + rest;
|
tmp = ((ULONGLONG)b->data[bnum_idx(b, i)] * mult) + rest;
|
||||||
rest = tmp / LIMB_MAX;
|
rest = tmp / LIMB_MAX;
|
||||||
b->data[BNUM_IDX(i)] = tmp % LIMB_MAX;
|
b->data[bnum_idx(b, i)] = tmp % LIMB_MAX;
|
||||||
|
|
||||||
if(i == b->b && !b->data[BNUM_IDX(i)])
|
if(i == b->b && !b->data[bnum_idx(b, i)])
|
||||||
b->b++;
|
b->b++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(rest) {
|
if(rest) {
|
||||||
b->data[BNUM_IDX(b->e)] = rest;
|
b->data[bnum_idx(b, b->e)] = rest;
|
||||||
b->e++;
|
b->e++;
|
||||||
|
|
||||||
if(BNUM_IDX(b->b) == BNUM_IDX(b->e)) {
|
if(bnum_idx(b, b->b) == bnum_idx(b, b->e)) {
|
||||||
if(b->data[BNUM_IDX(b->b)]) b->data[BNUM_IDX(b->b+1)] |= 1;
|
if(b->data[bnum_idx(b, b->b)]) b->data[bnum_idx(b, b->b+1)] |= 1;
|
||||||
b->b++;
|
b->b++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -577,11 +577,12 @@ static inline int FUNC_NAME(pf_output_fp)(FUNC_NAME(puts_clbk) pf_puts, void *pu
|
||||||
double v, pf_flags *flags, MSVCRT__locale_t locale, BOOL three_digit_exp)
|
double v, pf_flags *flags, MSVCRT__locale_t locale, BOOL three_digit_exp)
|
||||||
{
|
{
|
||||||
int e2, e10 = 0, round_pos, round_limb, radix_pos, first_limb_len, i, len, r, ret;
|
int e2, e10 = 0, round_pos, round_limb, radix_pos, first_limb_len, i, len, r, ret;
|
||||||
|
BYTE bnum_data[FIELD_OFFSET(struct bnum, data[BNUM_PREC64])];
|
||||||
|
struct bnum *b = (struct bnum*)bnum_data;
|
||||||
APICHAR buf[LIMB_DIGITS + 1];
|
APICHAR buf[LIMB_DIGITS + 1];
|
||||||
BOOL trim_tail = FALSE;
|
BOOL trim_tail = FALSE;
|
||||||
pf_flags f;
|
pf_flags f;
|
||||||
int limb_len, prec;
|
int limb_len, prec;
|
||||||
struct bnum b;
|
|
||||||
ULONGLONG m;
|
ULONGLONG m;
|
||||||
DWORD l;
|
DWORD l;
|
||||||
|
|
||||||
|
@ -594,33 +595,35 @@ static inline int FUNC_NAME(pf_output_fp)(FUNC_NAME(puts_clbk) pf_puts, void *pu
|
||||||
if(v) {
|
if(v) {
|
||||||
m = (ULONGLONG)1 << (MANT_BITS - 1);
|
m = (ULONGLONG)1 << (MANT_BITS - 1);
|
||||||
m |= (*(ULONGLONG*)&v & (((ULONGLONG)1 << (MANT_BITS - 1)) - 1));
|
m |= (*(ULONGLONG*)&v & (((ULONGLONG)1 << (MANT_BITS - 1)) - 1));
|
||||||
b.data[0] = m % LIMB_MAX;
|
b->b = 0;
|
||||||
b.data[1] = m / LIMB_MAX;
|
b->e = 2;
|
||||||
b.b = 0;
|
b->size = BNUM_PREC64;
|
||||||
b.e = 2;
|
b->data[0] = m % LIMB_MAX;
|
||||||
|
b->data[1] = m / LIMB_MAX;
|
||||||
e2 -= MANT_BITS;
|
e2 -= MANT_BITS;
|
||||||
|
|
||||||
while(e2 > 0) {
|
while(e2 > 0) {
|
||||||
int shift = e2 > 29 ? 29 : e2;
|
int shift = e2 > 29 ? 29 : e2;
|
||||||
if(bnum_lshift(&b, shift)) e10 += LIMB_DIGITS;
|
if(bnum_lshift(b, shift)) e10 += LIMB_DIGITS;
|
||||||
e2 -= shift;
|
e2 -= shift;
|
||||||
}
|
}
|
||||||
while(e2 < 0) {
|
while(e2 < 0) {
|
||||||
int shift = -e2 > 9 ? 9 : -e2;
|
int shift = -e2 > 9 ? 9 : -e2;
|
||||||
if(bnum_rshift(&b, shift)) e10 -= LIMB_DIGITS;
|
if(bnum_rshift(b, shift)) e10 -= LIMB_DIGITS;
|
||||||
e2 += shift;
|
e2 += shift;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
b.b = 0;
|
b->b = 0;
|
||||||
b.e = 1;
|
b->e = 1;
|
||||||
b.data[0] = 0;
|
b->size = BNUM_PREC64;
|
||||||
|
b->data[0] = 0;
|
||||||
e10 = -LIMB_DIGITS;
|
e10 = -LIMB_DIGITS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!b.data[BNUM_IDX(b.e-1)])
|
if(!b->data[bnum_idx(b, b->e-1)])
|
||||||
first_limb_len = 1;
|
first_limb_len = 1;
|
||||||
else
|
else
|
||||||
first_limb_len = floor(log10(b.data[BNUM_IDX(b.e - 1)])) + 1;
|
first_limb_len = floor(log10(b->data[bnum_idx(b, b->e - 1)])) + 1;
|
||||||
radix_pos = first_limb_len + LIMB_DIGITS + e10;
|
radix_pos = first_limb_len + LIMB_DIGITS + e10;
|
||||||
|
|
||||||
round_pos = flags->Precision;
|
round_pos = flags->Precision;
|
||||||
|
@ -629,11 +632,11 @@ static inline int FUNC_NAME(pf_output_fp)(FUNC_NAME(puts_clbk) pf_puts, void *pu
|
||||||
else if(!flags->Precision || flags->Format=='e' || flags->Format=='E')
|
else if(!flags->Precision || flags->Format=='e' || flags->Format=='E')
|
||||||
round_pos++;
|
round_pos++;
|
||||||
if (round_pos <= first_limb_len)
|
if (round_pos <= first_limb_len)
|
||||||
round_limb = b.e + (first_limb_len - round_pos) / LIMB_DIGITS - 1;
|
round_limb = b->e + (first_limb_len - round_pos) / LIMB_DIGITS - 1;
|
||||||
else
|
else
|
||||||
round_limb = b.e - (round_pos - first_limb_len - 1) / LIMB_DIGITS - 2;
|
round_limb = b->e - (round_pos - first_limb_len - 1) / LIMB_DIGITS - 2;
|
||||||
|
|
||||||
if (b.b<=round_limb && round_limb<b.e) {
|
if (b->b<=round_limb && round_limb<b->e) {
|
||||||
BOOL round_up = FALSE;
|
BOOL round_up = FALSE;
|
||||||
|
|
||||||
if (round_pos <= first_limb_len) {
|
if (round_pos <= first_limb_len) {
|
||||||
|
@ -644,43 +647,43 @@ static inline int FUNC_NAME(pf_output_fp)(FUNC_NAME(puts_clbk) pf_puts, void *pu
|
||||||
}
|
}
|
||||||
|
|
||||||
if (round_pos) {
|
if (round_pos) {
|
||||||
l = b.data[BNUM_IDX(round_limb)] % p10s[round_pos];
|
l = b->data[bnum_idx(b, round_limb)] % p10s[round_pos];
|
||||||
b.data[BNUM_IDX(round_limb)] -= l;
|
b->data[bnum_idx(b, round_limb)] -= l;
|
||||||
if(2*l >= p10s[round_pos]) round_up = TRUE;
|
if(2*l >= p10s[round_pos]) round_up = TRUE;
|
||||||
} else if(round_limb - 1 >= b.b) {
|
} else if(round_limb - 1 >= b->b) {
|
||||||
if(2*b.data[BNUM_IDX(round_limb-1)] >= LIMB_MAX) round_up = TRUE;
|
if(2*b->data[bnum_idx(b, round_limb-1)] >= LIMB_MAX) round_up = TRUE;
|
||||||
}
|
}
|
||||||
b.b = round_limb;
|
b->b = round_limb;
|
||||||
|
|
||||||
if(round_up) {
|
if(round_up) {
|
||||||
b.data[BNUM_IDX(b.b)] += p10s[round_pos];
|
b->data[bnum_idx(b, b->b)] += p10s[round_pos];
|
||||||
for(i = b.b; i < b.e; i++) {
|
for(i = b->b; i < b->e; i++) {
|
||||||
if(b.data[BNUM_IDX(i)] < LIMB_MAX) break;
|
if(b->data[bnum_idx(b, i)] < LIMB_MAX) break;
|
||||||
|
|
||||||
b.data[BNUM_IDX(i)] -= LIMB_MAX;
|
b->data[bnum_idx(b, i)] -= LIMB_MAX;
|
||||||
if(i+1 < b.e) b.data[BNUM_IDX(i+1)]++;
|
if(i+1 < b->e) b->data[bnum_idx(b, i+1)]++;
|
||||||
else b.data[BNUM_IDX(i+1)] = 1;
|
else b->data[bnum_idx(b, i+1)] = 1;
|
||||||
}
|
}
|
||||||
if(i == b.e-1) {
|
if(i == b->e-1) {
|
||||||
if(!b.data[BNUM_IDX(b.e-1)])
|
if(!b->data[bnum_idx(b, b->e-1)])
|
||||||
i = 1;
|
i = 1;
|
||||||
else
|
else
|
||||||
i = floor(log10(b.data[BNUM_IDX(b.e-1)])) + 1;
|
i = floor(log10(b->data[bnum_idx(b, b->e-1)])) + 1;
|
||||||
if(i != first_limb_len) {
|
if(i != first_limb_len) {
|
||||||
first_limb_len = i;
|
first_limb_len = i;
|
||||||
radix_pos++;
|
radix_pos++;
|
||||||
}
|
}
|
||||||
} else if(i == b.e) {
|
} else if(i == b->e) {
|
||||||
first_limb_len = 1;
|
first_limb_len = 1;
|
||||||
radix_pos++;
|
radix_pos++;
|
||||||
b.e++;
|
b->e++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(b.e <= round_limb) { /* got 0 or 1 after rounding */
|
else if(b->e <= round_limb) { /* got 0 or 1 after rounding */
|
||||||
b.data[BNUM_IDX(round_limb)] = b.e==round_limb && b.data[BNUM_IDX(b.e-1)]>=LIMB_MAX/2;
|
b->data[bnum_idx(b, round_limb)] = b->e==round_limb && b->data[bnum_idx(b, b->e-1)]>=LIMB_MAX/2;
|
||||||
b.b = round_limb;
|
b->b = round_limb;
|
||||||
b.e = b.b + 1;
|
b->e = b->b + 1;
|
||||||
first_limb_len = 1;
|
first_limb_len = 1;
|
||||||
radix_pos++;
|
radix_pos++;
|
||||||
}
|
}
|
||||||
|
@ -702,9 +705,9 @@ static inline int FUNC_NAME(pf_output_fp)(FUNC_NAME(puts_clbk) pf_puts, void *pu
|
||||||
}
|
}
|
||||||
|
|
||||||
if(trim_tail && !flags->Alternate) {
|
if(trim_tail && !flags->Alternate) {
|
||||||
for(i=round_limb; flags->Precision>0 && i<b.e; i++) {
|
for(i=round_limb; flags->Precision>0 && i<b->e; i++) {
|
||||||
if(i>=b.b)
|
if(i>=b->b)
|
||||||
l = b.data[BNUM_IDX(i)];
|
l = b->data[bnum_idx(b, i)];
|
||||||
else
|
else
|
||||||
l = 0;
|
l = 0;
|
||||||
|
|
||||||
|
@ -713,7 +716,7 @@ static inline int FUNC_NAME(pf_output_fp)(FUNC_NAME(puts_clbk) pf_puts, void *pu
|
||||||
r = radix_pos + flags->Precision;
|
r = radix_pos + flags->Precision;
|
||||||
else
|
else
|
||||||
r = flags->Precision + 1;
|
r = flags->Precision + 1;
|
||||||
r = first_limb_len + LIMB_DIGITS * (b.e-1 - b.b) - r;
|
r = first_limb_len + LIMB_DIGITS * (b->e-1 - b->b) - r;
|
||||||
r %= LIMB_DIGITS;
|
r %= LIMB_DIGITS;
|
||||||
if(r < 0) r += LIMB_DIGITS;
|
if(r < 0) r += LIMB_DIGITS;
|
||||||
l /= p10s[r];
|
l /= p10s[r];
|
||||||
|
@ -770,9 +773,9 @@ static inline int FUNC_NAME(pf_output_fp)(FUNC_NAME(puts_clbk) pf_puts, void *pu
|
||||||
}
|
}
|
||||||
|
|
||||||
limb_len = LIMB_DIGITS;
|
limb_len = LIMB_DIGITS;
|
||||||
for(i=b.e-1; radix_pos>0 && i>=b.b; i--) {
|
for(i=b->e-1; radix_pos>0 && i>=b->b; i--) {
|
||||||
limb_len = (i == b.e-1 ? first_limb_len : LIMB_DIGITS);
|
limb_len = (i == b->e-1 ? first_limb_len : LIMB_DIGITS);
|
||||||
l = b.data[BNUM_IDX(i)];
|
l = b->data[bnum_idx(b, i)];
|
||||||
if(limb_len > radix_pos) {
|
if(limb_len > radix_pos) {
|
||||||
f.Precision = radix_pos;
|
f.Precision = radix_pos;
|
||||||
l /= p10s[limb_len - radix_pos];
|
l /= p10s[limb_len - radix_pos];
|
||||||
|
@ -811,8 +814,8 @@ static inline int FUNC_NAME(pf_output_fp)(FUNC_NAME(puts_clbk) pf_puts, void *pu
|
||||||
ret += r;
|
ret += r;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(; prec>0 && i>=b.b; i--) {
|
for(; prec>0 && i>=b->b; i--) {
|
||||||
l = b.data[BNUM_IDX(i)];
|
l = b->data[bnum_idx(b, i)];
|
||||||
if(limb_len != LIMB_DIGITS)
|
if(limb_len != LIMB_DIGITS)
|
||||||
l %= p10s[limb_len];
|
l %= p10s[limb_len];
|
||||||
if(limb_len > prec) {
|
if(limb_len > prec) {
|
||||||
|
@ -837,7 +840,7 @@ static inline int FUNC_NAME(pf_output_fp)(FUNC_NAME(puts_clbk) pf_puts, void *pu
|
||||||
ret += r;
|
ret += r;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
l = b.data[BNUM_IDX(b.e - 1)];
|
l = b->data[bnum_idx(b, b->e - 1)];
|
||||||
l /= p10s[first_limb_len - 1];
|
l /= p10s[first_limb_len - 1];
|
||||||
|
|
||||||
buf[0] = '0' + l;
|
buf[0] = '0' + l;
|
||||||
|
@ -854,9 +857,9 @@ static inline int FUNC_NAME(pf_output_fp)(FUNC_NAME(puts_clbk) pf_puts, void *pu
|
||||||
|
|
||||||
prec = flags->Precision;
|
prec = flags->Precision;
|
||||||
limb_len = LIMB_DIGITS;
|
limb_len = LIMB_DIGITS;
|
||||||
for(i=b.e-1; prec>0 && i>=b.b; i--) {
|
for(i=b->e-1; prec>0 && i>=b->b; i--) {
|
||||||
l = b.data[BNUM_IDX(i)];
|
l = b->data[bnum_idx(b, i)];
|
||||||
if(i == b.e-1) {
|
if(i == b->e-1) {
|
||||||
limb_len = first_limb_len - 1;
|
limb_len = first_limb_len - 1;
|
||||||
l %= p10s[limb_len];
|
l %= p10s[limb_len];
|
||||||
}
|
}
|
||||||
|
|
|
@ -581,10 +581,11 @@ double parse_double(MSVCRT_wchar_t (*get)(void *ctx), void (*unget)(void *ctx),
|
||||||
int matched=0;
|
int matched=0;
|
||||||
#endif
|
#endif
|
||||||
BOOL found_digit = FALSE, found_dp = FALSE, found_sign = FALSE;
|
BOOL found_digit = FALSE, found_dp = FALSE, found_sign = FALSE;
|
||||||
|
BYTE bnum_data[FIELD_OFFSET(struct bnum, data[BNUM_PREC64])];
|
||||||
int e2 = 0, dp=0, sign=1, off, limb_digits = 0, i;
|
int e2 = 0, dp=0, sign=1, off, limb_digits = 0, i;
|
||||||
|
struct bnum *b = (struct bnum*)bnum_data;
|
||||||
enum round round = ROUND_ZERO;
|
enum round round = ROUND_ZERO;
|
||||||
MSVCRT_wchar_t nch;
|
MSVCRT_wchar_t nch;
|
||||||
struct bnum b;
|
|
||||||
|
|
||||||
nch = get(ctx);
|
nch = get(ctx);
|
||||||
if(nch == '-') {
|
if(nch == '-') {
|
||||||
|
@ -637,27 +638,28 @@ double parse_double(MSVCRT_wchar_t (*get)(void *ctx), void (*unget)(void *ctx),
|
||||||
nch = get(ctx);
|
nch = get(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
b.data[0] = 0;
|
b->b = 0;
|
||||||
b.b = 0;
|
b->e = 1;
|
||||||
b.e = 1;
|
b->size = BNUM_PREC64;
|
||||||
|
b->data[0] = 0;
|
||||||
while(nch>='0' && nch<='9') {
|
while(nch>='0' && nch<='9') {
|
||||||
found_digit = TRUE;
|
found_digit = TRUE;
|
||||||
if(limb_digits == LIMB_DIGITS) {
|
if(limb_digits == LIMB_DIGITS) {
|
||||||
if(BNUM_IDX(b.b-1) == BNUM_IDX(b.e)) break;
|
if(bnum_idx(b, b->b-1) == bnum_idx(b, b->e)) break;
|
||||||
else {
|
else {
|
||||||
b.b--;
|
b->b--;
|
||||||
b.data[BNUM_IDX(b.b)] = 0;
|
b->data[bnum_idx(b, b->b)] = 0;
|
||||||
limb_digits = 0;
|
limb_digits = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
b.data[BNUM_IDX(b.b)] = b.data[BNUM_IDX(b.b)] * 10 + nch - '0';
|
b->data[bnum_idx(b, b->b)] = b->data[bnum_idx(b, b->b)] * 10 + nch - '0';
|
||||||
limb_digits++;
|
limb_digits++;
|
||||||
nch = get(ctx);
|
nch = get(ctx);
|
||||||
dp++;
|
dp++;
|
||||||
}
|
}
|
||||||
while(nch>='0' && nch<='9') {
|
while(nch>='0' && nch<='9') {
|
||||||
if(nch != '0') b.data[BNUM_IDX(b.b)] |= 1;
|
if(nch != '0') b->data[bnum_idx(b, b->b)] |= 1;
|
||||||
nch = get(ctx);
|
nch = get(ctx);
|
||||||
dp++;
|
dp++;
|
||||||
}
|
}
|
||||||
|
@ -668,7 +670,7 @@ double parse_double(MSVCRT_wchar_t (*get)(void *ctx), void (*unget)(void *ctx),
|
||||||
}
|
}
|
||||||
|
|
||||||
/* skip leading '0' */
|
/* skip leading '0' */
|
||||||
if(nch=='0' && !limb_digits && !b.b) {
|
if(nch=='0' && !limb_digits && !b->b) {
|
||||||
found_digit = TRUE;
|
found_digit = TRUE;
|
||||||
while(nch == '0') {
|
while(nch == '0') {
|
||||||
nch = get(ctx);
|
nch = get(ctx);
|
||||||
|
@ -679,20 +681,20 @@ double parse_double(MSVCRT_wchar_t (*get)(void *ctx), void (*unget)(void *ctx),
|
||||||
while(nch>='0' && nch<='9') {
|
while(nch>='0' && nch<='9') {
|
||||||
found_digit = TRUE;
|
found_digit = TRUE;
|
||||||
if(limb_digits == LIMB_DIGITS) {
|
if(limb_digits == LIMB_DIGITS) {
|
||||||
if(BNUM_IDX(b.b-1) == BNUM_IDX(b.e)) break;
|
if(bnum_idx(b, b->b-1) == bnum_idx(b, b->e)) break;
|
||||||
else {
|
else {
|
||||||
b.b--;
|
b->b--;
|
||||||
b.data[BNUM_IDX(b.b)] = 0;
|
b->data[bnum_idx(b, b->b)] = 0;
|
||||||
limb_digits = 0;
|
limb_digits = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
b.data[BNUM_IDX(b.b)] = b.data[BNUM_IDX(b.b)] * 10 + nch - '0';
|
b->data[bnum_idx(b, b->b)] = b->data[bnum_idx(b, b->b)] * 10 + nch - '0';
|
||||||
limb_digits++;
|
limb_digits++;
|
||||||
nch = get(ctx);
|
nch = get(ctx);
|
||||||
}
|
}
|
||||||
while(nch>='0' && nch<='9') {
|
while(nch>='0' && nch<='9') {
|
||||||
if(nch != '0') b.data[BNUM_IDX(b.b)] |= 1;
|
if(nch != '0') b->data[bnum_idx(b, b->b)] |= 1;
|
||||||
nch = get(ctx);
|
nch = get(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -746,23 +748,23 @@ double parse_double(MSVCRT_wchar_t (*get)(void *ctx), void (*unget)(void *ctx),
|
||||||
unget(ctx);
|
unget(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!b.data[BNUM_IDX(b.e-1)]) return make_double(sign, 0, 0, ROUND_ZERO, err);
|
if(!b->data[bnum_idx(b, b->e-1)]) return make_double(sign, 0, 0, ROUND_ZERO, err);
|
||||||
|
|
||||||
/* Fill last limb with 0 if needed */
|
/* Fill last limb with 0 if needed */
|
||||||
if(b.b+1 != b.e) {
|
if(b->b+1 != b->e) {
|
||||||
for(; limb_digits != LIMB_DIGITS; limb_digits++)
|
for(; limb_digits != LIMB_DIGITS; limb_digits++)
|
||||||
b.data[BNUM_IDX(b.b)] *= 10;
|
b->data[bnum_idx(b, b->b)] *= 10;
|
||||||
}
|
}
|
||||||
for(; BNUM_IDX(b.b) < BNUM_IDX(b.e); b.b++) {
|
for(; bnum_idx(b, b->b) < bnum_idx(b, b->e); b->b++) {
|
||||||
if(b.data[BNUM_IDX(b.b)]) break;
|
if(b->data[bnum_idx(b, b->b)]) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* move decimal point to limb boundary */
|
/* move decimal point to limb boundary */
|
||||||
if(limb_digits==dp && b.b==b.e-1)
|
if(limb_digits==dp && b->b==b->e-1)
|
||||||
return make_double(sign, 0, b.data[BNUM_IDX(b.e-1)], ROUND_ZERO, err);
|
return make_double(sign, 0, b->data[bnum_idx(b, b->e-1)], ROUND_ZERO, err);
|
||||||
off = (dp - limb_digits) % LIMB_DIGITS;
|
off = (dp - limb_digits) % LIMB_DIGITS;
|
||||||
if(off < 0) off += LIMB_DIGITS;
|
if(off < 0) off += LIMB_DIGITS;
|
||||||
if(off) bnum_mult(&b, p10s[off]);
|
if(off) bnum_mult(b, p10s[off]);
|
||||||
|
|
||||||
if(dp-1 > MSVCRT_DBL_MAX_10_EXP)
|
if(dp-1 > MSVCRT_DBL_MAX_10_EXP)
|
||||||
return make_double(sign, INT_MAX, 1, ROUND_ZERO, err);
|
return make_double(sign, INT_MAX, 1, ROUND_ZERO, err);
|
||||||
|
@ -772,27 +774,27 @@ double parse_double(MSVCRT_wchar_t (*get)(void *ctx), void (*unget)(void *ctx),
|
||||||
return make_double(sign, INT_MIN, 1, ROUND_ZERO, err);
|
return make_double(sign, INT_MIN, 1, ROUND_ZERO, err);
|
||||||
|
|
||||||
while(dp > 2*LIMB_DIGITS) {
|
while(dp > 2*LIMB_DIGITS) {
|
||||||
if(bnum_rshift(&b, 9)) dp -= LIMB_DIGITS;
|
if(bnum_rshift(b, 9)) dp -= LIMB_DIGITS;
|
||||||
e2 += 9;
|
e2 += 9;
|
||||||
}
|
}
|
||||||
while(dp <= LIMB_DIGITS) {
|
while(dp <= LIMB_DIGITS) {
|
||||||
if(bnum_lshift(&b, 29)) dp += LIMB_DIGITS;
|
if(bnum_lshift(b, 29)) dp += LIMB_DIGITS;
|
||||||
e2 -= 29;
|
e2 -= 29;
|
||||||
}
|
}
|
||||||
while(b.data[BNUM_IDX(b.e-1)] < LIMB_MAX/10) {
|
while(b->data[bnum_idx(b, b->e-1)] < LIMB_MAX/10) {
|
||||||
bnum_lshift(&b, 1);
|
bnum_lshift(b, 1);
|
||||||
e2--;
|
e2--;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if fractional part is non-zero */
|
/* Check if fractional part is non-zero */
|
||||||
/* Caution: it's only correct because bnum_to_mant returns more than 53 bits */
|
/* Caution: it's only correct because bnum_to_mant returns more than 53 bits */
|
||||||
for(i=b.e-3; i>=b.b; i--) {
|
for(i=b->e-3; i>=b->b; i--) {
|
||||||
if (!b.data[BNUM_IDX(b.b)]) continue;
|
if (!b->data[bnum_idx(b, b->b)]) continue;
|
||||||
round = ROUND_DOWN;
|
round = ROUND_DOWN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return make_double(sign, e2, bnum_to_mant(&b), round, err);
|
return make_double(sign, e2, bnum_to_mant(b), round, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
static MSVCRT_wchar_t strtod_str_get(void *ctx)
|
static MSVCRT_wchar_t strtod_str_get(void *ctx)
|
||||||
|
|
Loading…
Reference in New Issue