bc: shrink zbc_num_ulong()
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
ec74a9c145
commit
1557b76edd
@ -1442,20 +1442,21 @@ static void bc_num_copy(BcNum *d, BcNum *s)
|
|||||||
static BC_STATUS zbc_num_ulong(BcNum *n, unsigned long *result_p)
|
static BC_STATUS zbc_num_ulong(BcNum *n, unsigned long *result_p)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
unsigned long pow, result;
|
unsigned long result;
|
||||||
|
|
||||||
if (n->neg) RETURN_STATUS(bc_error("negative number"));
|
if (n->neg) RETURN_STATUS(bc_error("negative number"));
|
||||||
|
|
||||||
for (result = 0, pow = 1, i = n->rdx; i < n->len; ++i) {
|
result = 0;
|
||||||
unsigned long prev = result, powprev = pow;
|
i = n->len;
|
||||||
|
while (i > n->rdx) {
|
||||||
result += ((unsigned long) n->num[i]) * pow;
|
unsigned long prev = result;
|
||||||
pow *= 10;
|
result = result * 10 + n->num[--i];
|
||||||
|
// Even overflowed N*10 can still satisfy N*10>=N. For example,
|
||||||
if (result < prev || pow < powprev)
|
// 0x1ff00000 * 10 is 0x13f600000,
|
||||||
|
// or 0x3f600000 truncated to 32 bits. Which is larger.
|
||||||
|
// However, (N*10)/8 < N check is always correct.
|
||||||
|
if ((result / 8) < prev)
|
||||||
RETURN_STATUS(bc_error("overflow"));
|
RETURN_STATUS(bc_error("overflow"));
|
||||||
prev = result;
|
|
||||||
powprev = pow;
|
|
||||||
}
|
}
|
||||||
*result_p = result;
|
*result_p = result;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user