diff --git a/dlls/msvcrt/bnum.h b/dlls/msvcrt/bnum.h index b66ebf04ecb..5cc71c1e686 100644 --- a/dlls/msvcrt/bnum.h +++ b/dlls/msvcrt/bnum.h @@ -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; ie; 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<data[BNUM_IDX(i)] = (b->data[BNUM_IDX(i)] >> shift) + rest; + tmp = b->data[bnum_idx(b, i)] & ((1<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; ie; 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++; } } diff --git a/dlls/msvcrt/printf.h b/dlls/msvcrt/printf.h index de0e6523adc..4fe9f6106ac 100644 --- a/dlls/msvcrt/printf.h +++ b/dlls/msvcrt/printf.h @@ -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_limbb<=round_limb && round_limbe) { 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.b) - l = b.data[BNUM_IDX(i)]; + for(i=round_limb; flags->Precision>0 && ie; 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]; } diff --git a/dlls/msvcrt/string.c b/dlls/msvcrt/string.c index 806dace0409..460d0730f65 100644 --- a/dlls/msvcrt/string.c +++ b/dlls/msvcrt/string.c @@ -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)