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_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) */
|
||||
struct bnum {
|
||||
DWORD data[128]; /* circular buffer, base 10 number */
|
||||
int b; /* least significant digit position */
|
||||
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 */
|
||||
static inline ULONGLONG bnum_to_mant(struct bnum *b)
|
||||
{
|
||||
ULONGLONG ret = (ULONGLONG)b->data[BNUM_IDX(b->e-1)] * LIMB_MAX;
|
||||
if(b->b != b->e-1) ret += b->data[BNUM_IDX(b->e-2)];
|
||||
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, b->e-2)];
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -53,20 +60,20 @@ static inline BOOL bnum_lshift(struct bnum *b, int shift)
|
|||
assert(shift <= 29);
|
||||
|
||||
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;
|
||||
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++;
|
||||
}
|
||||
|
||||
if(rest) {
|
||||
b->data[BNUM_IDX(b->e)] = rest;
|
||||
b->data[bnum_idx(b, b->e)] = rest;
|
||||
b->e++;
|
||||
|
||||
if(BNUM_IDX(b->b) == BNUM_IDX(b->e)) {
|
||||
if(b->data[BNUM_IDX(b->b)]) b->data[BNUM_IDX(b->b+1)] |= 1;
|
||||
if(bnum_idx(b, b->b) == bnum_idx(b, b->e)) {
|
||||
if(b->data[bnum_idx(b, b->b)]) b->data[bnum_idx(b, b->b+1)] |= 1;
|
||||
b->b++;
|
||||
}
|
||||
return TRUE;
|
||||
|
@ -85,21 +92,21 @@ static inline BOOL bnum_rshift(struct bnum *b, int shift)
|
|||
assert(shift <= 9);
|
||||
|
||||
for(i=b->e-1; i>=b->b; i--) {
|
||||
tmp = b->data[BNUM_IDX(i)] & ((1<<shift)-1);
|
||||
b->data[BNUM_IDX(i)] = (b->data[BNUM_IDX(i)] >> shift) + rest;
|
||||
tmp = b->data[bnum_idx(b, i)] & ((1<<shift)-1);
|
||||
b->data[bnum_idx(b, i)] = (b->data[bnum_idx(b, i)] >> shift) + rest;
|
||||
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--;
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if(rest) {
|
||||
if(BNUM_IDX(b->b-1) == BNUM_IDX(b->e)) {
|
||||
if(rest) b->data[BNUM_IDX(b->b)] |= 1;
|
||||
if(bnum_idx(b, b->b-1) == bnum_idx(b, b->e)) {
|
||||
if(rest) b->data[bnum_idx(b, b->b)] |= 1;
|
||||
} else {
|
||||
b->b--;
|
||||
b->data[BNUM_IDX(b->b)] = rest;
|
||||
b->data[bnum_idx(b, b->b)] = rest;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
@ -114,20 +121,20 @@ static inline void bnum_mult(struct bnum *b, int mult)
|
|||
assert(mult <= LIMB_MAX);
|
||||
|
||||
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;
|
||||
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++;
|
||||
}
|
||||
|
||||
if(rest) {
|
||||
b->data[BNUM_IDX(b->e)] = rest;
|
||||
b->data[bnum_idx(b, b->e)] = rest;
|
||||
b->e++;
|
||||
|
||||
if(BNUM_IDX(b->b) == BNUM_IDX(b->e)) {
|
||||
if(b->data[BNUM_IDX(b->b)]) b->data[BNUM_IDX(b->b+1)] |= 1;
|
||||
if(bnum_idx(b, b->b) == bnum_idx(b, b->e)) {
|
||||
if(b->data[bnum_idx(b, b->b)]) b->data[bnum_idx(b, b->b+1)] |= 1;
|
||||
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)
|
||||
{
|
||||
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];
|
||||
BOOL trim_tail = FALSE;
|
||||
pf_flags f;
|
||||
int limb_len, prec;
|
||||
struct bnum b;
|
||||
ULONGLONG m;
|
||||
DWORD l;
|
||||
|
||||
|
@ -594,33 +595,35 @@ static inline int FUNC_NAME(pf_output_fp)(FUNC_NAME(puts_clbk) pf_puts, void *pu
|
|||
if(v) {
|
||||
m = (ULONGLONG)1 << (MANT_BITS - 1);
|
||||
m |= (*(ULONGLONG*)&v & (((ULONGLONG)1 << (MANT_BITS - 1)) - 1));
|
||||
b.data[0] = m % LIMB_MAX;
|
||||
b.data[1] = m / LIMB_MAX;
|
||||
b.b = 0;
|
||||
b.e = 2;
|
||||
b->b = 0;
|
||||
b->e = 2;
|
||||
b->size = BNUM_PREC64;
|
||||
b->data[0] = m % LIMB_MAX;
|
||||
b->data[1] = m / LIMB_MAX;
|
||||
e2 -= MANT_BITS;
|
||||
|
||||
while(e2 > 0) {
|
||||
int shift = e2 > 29 ? 29 : e2;
|
||||
if(bnum_lshift(&b, shift)) e10 += LIMB_DIGITS;
|
||||
if(bnum_lshift(b, shift)) e10 += LIMB_DIGITS;
|
||||
e2 -= shift;
|
||||
}
|
||||
while(e2 < 0) {
|
||||
int shift = -e2 > 9 ? 9 : -e2;
|
||||
if(bnum_rshift(&b, shift)) e10 -= LIMB_DIGITS;
|
||||
if(bnum_rshift(b, shift)) e10 -= LIMB_DIGITS;
|
||||
e2 += shift;
|
||||
}
|
||||
} else {
|
||||
b.b = 0;
|
||||
b.e = 1;
|
||||
b.data[0] = 0;
|
||||
b->b = 0;
|
||||
b->e = 1;
|
||||
b->size = BNUM_PREC64;
|
||||
b->data[0] = 0;
|
||||
e10 = -LIMB_DIGITS;
|
||||
}
|
||||
|
||||
if(!b.data[BNUM_IDX(b.e-1)])
|
||||
if(!b->data[bnum_idx(b, b->e-1)])
|
||||
first_limb_len = 1;
|
||||
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;
|
||||
|
||||
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')
|
||||
round_pos++;
|
||||
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
|
||||
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;
|
||||
|
||||
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) {
|
||||
l = b.data[BNUM_IDX(round_limb)] % p10s[round_pos];
|
||||
b.data[BNUM_IDX(round_limb)] -= l;
|
||||
l = b->data[bnum_idx(b, round_limb)] % p10s[round_pos];
|
||||
b->data[bnum_idx(b, round_limb)] -= l;
|
||||
if(2*l >= p10s[round_pos]) round_up = TRUE;
|
||||
} else if(round_limb - 1 >= b.b) {
|
||||
if(2*b.data[BNUM_IDX(round_limb-1)] >= LIMB_MAX) round_up = TRUE;
|
||||
} else if(round_limb - 1 >= b->b) {
|
||||
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) {
|
||||
b.data[BNUM_IDX(b.b)] += p10s[round_pos];
|
||||
for(i = b.b; i < b.e; i++) {
|
||||
if(b.data[BNUM_IDX(i)] < LIMB_MAX) break;
|
||||
b->data[bnum_idx(b, b->b)] += p10s[round_pos];
|
||||
for(i = b->b; i < b->e; i++) {
|
||||
if(b->data[bnum_idx(b, i)] < LIMB_MAX) break;
|
||||
|
||||
b.data[BNUM_IDX(i)] -= LIMB_MAX;
|
||||
if(i+1 < b.e) b.data[BNUM_IDX(i+1)]++;
|
||||
else b.data[BNUM_IDX(i+1)] = 1;
|
||||
b->data[bnum_idx(b, i)] -= LIMB_MAX;
|
||||
if(i+1 < b->e) b->data[bnum_idx(b, i+1)]++;
|
||||
else b->data[bnum_idx(b, i+1)] = 1;
|
||||
}
|
||||
if(i == b.e-1) {
|
||||
if(!b.data[BNUM_IDX(b.e-1)])
|
||||
if(i == b->e-1) {
|
||||
if(!b->data[bnum_idx(b, b->e-1)])
|
||||
i = 1;
|
||||
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) {
|
||||
first_limb_len = i;
|
||||
radix_pos++;
|
||||
}
|
||||
} else if(i == b.e) {
|
||||
} else if(i == b->e) {
|
||||
first_limb_len = 1;
|
||||
radix_pos++;
|
||||
b.e++;
|
||||
b->e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
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.b = round_limb;
|
||||
b.e = b.b + 1;
|
||||
else if(b->e <= round_limb) { /* got 0 or 1 after rounding */
|
||||
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->e = b->b + 1;
|
||||
first_limb_len = 1;
|
||||
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) {
|
||||
for(i=round_limb; flags->Precision>0 && i<b.e; i++) {
|
||||
if(i>=b.b)
|
||||
l = b.data[BNUM_IDX(i)];
|
||||
for(i=round_limb; flags->Precision>0 && i<b->e; i++) {
|
||||
if(i>=b->b)
|
||||
l = b->data[bnum_idx(b, i)];
|
||||
else
|
||||
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;
|
||||
else
|
||||
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;
|
||||
if(r < 0) r += LIMB_DIGITS;
|
||||
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;
|
||||
for(i=b.e-1; radix_pos>0 && i>=b.b; i--) {
|
||||
limb_len = (i == b.e-1 ? first_limb_len : LIMB_DIGITS);
|
||||
l = b.data[BNUM_IDX(i)];
|
||||
for(i=b->e-1; radix_pos>0 && i>=b->b; i--) {
|
||||
limb_len = (i == b->e-1 ? first_limb_len : LIMB_DIGITS);
|
||||
l = b->data[bnum_idx(b, i)];
|
||||
if(limb_len > radix_pos) {
|
||||
f.Precision = 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;
|
||||
}
|
||||
|
||||
for(; prec>0 && i>=b.b; i--) {
|
||||
l = b.data[BNUM_IDX(i)];
|
||||
for(; prec>0 && i>=b->b; i--) {
|
||||
l = b->data[bnum_idx(b, i)];
|
||||
if(limb_len != LIMB_DIGITS)
|
||||
l %= p10s[limb_len];
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
l = b.data[BNUM_IDX(b.e - 1)];
|
||||
l = b->data[bnum_idx(b, b->e - 1)];
|
||||
l /= p10s[first_limb_len - 1];
|
||||
|
||||
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;
|
||||
limb_len = LIMB_DIGITS;
|
||||
for(i=b.e-1; prec>0 && i>=b.b; i--) {
|
||||
l = b.data[BNUM_IDX(i)];
|
||||
if(i == b.e-1) {
|
||||
for(i=b->e-1; prec>0 && i>=b->b; i--) {
|
||||
l = b->data[bnum_idx(b, i)];
|
||||
if(i == b->e-1) {
|
||||
limb_len = first_limb_len - 1;
|
||||
l %= p10s[limb_len];
|
||||
}
|
||||
|
|
|
@ -581,10 +581,11 @@ double parse_double(MSVCRT_wchar_t (*get)(void *ctx), void (*unget)(void *ctx),
|
|||
int matched=0;
|
||||
#endif
|
||||
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;
|
||||
struct bnum *b = (struct bnum*)bnum_data;
|
||||
enum round round = ROUND_ZERO;
|
||||
MSVCRT_wchar_t nch;
|
||||
struct bnum b;
|
||||
|
||||
nch = get(ctx);
|
||||
if(nch == '-') {
|
||||
|
@ -637,27 +638,28 @@ double parse_double(MSVCRT_wchar_t (*get)(void *ctx), void (*unget)(void *ctx),
|
|||
nch = get(ctx);
|
||||
}
|
||||
|
||||
b.data[0] = 0;
|
||||
b.b = 0;
|
||||
b.e = 1;
|
||||
b->b = 0;
|
||||
b->e = 1;
|
||||
b->size = BNUM_PREC64;
|
||||
b->data[0] = 0;
|
||||
while(nch>='0' && nch<='9') {
|
||||
found_digit = TRUE;
|
||||
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 {
|
||||
b.b--;
|
||||
b.data[BNUM_IDX(b.b)] = 0;
|
||||
b->b--;
|
||||
b->data[bnum_idx(b, b->b)] = 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++;
|
||||
nch = get(ctx);
|
||||
dp++;
|
||||
}
|
||||
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);
|
||||
dp++;
|
||||
}
|
||||
|
@ -668,7 +670,7 @@ double parse_double(MSVCRT_wchar_t (*get)(void *ctx), void (*unget)(void *ctx),
|
|||
}
|
||||
|
||||
/* skip leading '0' */
|
||||
if(nch=='0' && !limb_digits && !b.b) {
|
||||
if(nch=='0' && !limb_digits && !b->b) {
|
||||
found_digit = TRUE;
|
||||
while(nch == '0') {
|
||||
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') {
|
||||
found_digit = TRUE;
|
||||
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 {
|
||||
b.b--;
|
||||
b.data[BNUM_IDX(b.b)] = 0;
|
||||
b->b--;
|
||||
b->data[bnum_idx(b, b->b)] = 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++;
|
||||
nch = get(ctx);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -746,23 +748,23 @@ double parse_double(MSVCRT_wchar_t (*get)(void *ctx), void (*unget)(void *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 */
|
||||
if(b.b+1 != b.e) {
|
||||
if(b->b+1 != b->e) {
|
||||
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++) {
|
||||
if(b.data[BNUM_IDX(b.b)]) break;
|
||||
for(; bnum_idx(b, b->b) < bnum_idx(b, b->e); b->b++) {
|
||||
if(b->data[bnum_idx(b, b->b)]) break;
|
||||
}
|
||||
|
||||
/* move decimal point to limb boundary */
|
||||
if(limb_digits==dp && b.b==b.e-1)
|
||||
return make_double(sign, 0, b.data[BNUM_IDX(b.e-1)], ROUND_ZERO, err);
|
||||
if(limb_digits==dp && b->b==b->e-1)
|
||||
return make_double(sign, 0, b->data[bnum_idx(b, b->e-1)], ROUND_ZERO, err);
|
||||
off = (dp - limb_digits) % 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)
|
||||
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);
|
||||
|
||||
while(dp > 2*LIMB_DIGITS) {
|
||||
if(bnum_rshift(&b, 9)) dp -= LIMB_DIGITS;
|
||||
if(bnum_rshift(b, 9)) dp -= LIMB_DIGITS;
|
||||
e2 += 9;
|
||||
}
|
||||
while(dp <= LIMB_DIGITS) {
|
||||
if(bnum_lshift(&b, 29)) dp += LIMB_DIGITS;
|
||||
if(bnum_lshift(b, 29)) dp += LIMB_DIGITS;
|
||||
e2 -= 29;
|
||||
}
|
||||
while(b.data[BNUM_IDX(b.e-1)] < LIMB_MAX/10) {
|
||||
bnum_lshift(&b, 1);
|
||||
while(b->data[bnum_idx(b, b->e-1)] < LIMB_MAX/10) {
|
||||
bnum_lshift(b, 1);
|
||||
e2--;
|
||||
}
|
||||
|
||||
/* Check if fractional part is non-zero */
|
||||
/* Caution: it's only correct because bnum_to_mant returns more than 53 bits */
|
||||
for(i=b.e-3; i>=b.b; i--) {
|
||||
if (!b.data[BNUM_IDX(b.b)]) continue;
|
||||
for(i=b->e-3; i>=b->b; i--) {
|
||||
if (!b->data[bnum_idx(b, b->b)]) continue;
|
||||
round = ROUND_DOWN;
|
||||
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)
|
||||
|
|
Loading…
Reference in New Issue