Commit 74958219 authored by Piotr Caban's avatar Piotr Caban Committed by Alexandre Julliard

msvcrt: Support arbitrary buffer size in bnum.

parent 413e34df
...@@ -26,19 +26,26 @@ static const int p10s[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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), ...@@ -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), ...@@ -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), ...@@ -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), ...@@ -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), ...@@ -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), ...@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment