version 1.56, 2017/11/29 19:13:31 |
version 1.57, 2017/12/01 19:04:15 |
|
|
|
|
abs_scale = s > 0 ? s : -s; |
abs_scale = s > 0 ? s : -s; |
|
|
if (abs_scale < sizeof(factors)/sizeof(factors[0])) { |
if (abs_scale < nitems(factors)) { |
if (s > 0) |
if (s > 0) |
bn_check(BN_mul_word(n, factors[abs_scale])); |
bn_check(BN_mul_word(n, factors[abs_scale])); |
else |
else |
|
|
|
|
bn_checkp(BN_copy(i, n->number)); |
bn_checkp(BN_copy(i, n->number)); |
|
|
if (n->scale == 0 && f != NULL) |
if (n->scale == 0) { |
bn_check(BN_set_word(f, 0)); |
if (f != NULL) |
else if (n->scale < sizeof(factors)/sizeof(factors[0])) { |
bn_check(BN_set_word(f, 0)); |
|
} else if (n->scale < nitems(factors)) { |
rem = BN_div_word(i, factors[n->scale]); |
rem = BN_div_word(i, factors[n->scale]); |
if (f != NULL) |
if (f != NULL) |
bn_check(BN_set_word(f, rem)); |
bn_check(BN_set_word(f, rem)); |
|
|
static u_int |
static u_int |
count_digits(const struct number *n) |
count_digits(const struct number *n) |
{ |
{ |
struct number *int_part, *fract_part; |
BIGNUM *int_part, *a, *p; |
u_int i; |
BN_CTX *ctx; |
|
uint d; |
|
const uint64_t c = 1292913986; /* floor(2^32 * log_10(2)) */ |
|
int bits; |
|
|
if (BN_is_zero(n->number)) |
if (BN_is_zero(n->number)) |
return n->scale ? n->scale : 1; |
return n->scale ? n->scale : 1; |
|
|
int_part = new_number(); |
int_part = BN_new(); |
fract_part = new_number(); |
bn_checkp(int_part); |
fract_part->scale = n->scale; |
|
split_number(n, int_part->number, fract_part->number); |
|
|
|
i = 0; |
split_number(n, int_part, NULL); |
while (!BN_is_zero(int_part->number)) { |
bits = BN_num_bits(int_part); |
(void)BN_div_word(int_part->number, 10); |
|
i++; |
if (bits == 0) |
|
d = 0; |
|
else { |
|
/* |
|
* Estimate number of decimal digits based on number of bits. |
|
* Divide 2^32 factor out by shifting |
|
*/ |
|
d = (c * bits) >> 32; |
|
|
|
/* If close to a possible rounding error fix if needed */ |
|
if (d != (c * (bits - 1)) >> 32) { |
|
ctx = BN_CTX_new(); |
|
bn_checkp(ctx); |
|
a = BN_new(); |
|
bn_checkp(a); |
|
p = BN_new(); |
|
bn_checkp(p); |
|
|
|
bn_check(BN_set_word(a, 10)); |
|
bn_check(BN_set_word(p, d)); |
|
bn_check(BN_exp(a, a, p, ctx)); |
|
|
|
if (BN_ucmp(int_part, a) >= 0) |
|
d++; |
|
|
|
BN_CTX_free(ctx); |
|
BN_free(a); |
|
BN_free(p); |
|
} else |
|
d++; |
} |
} |
free_number(int_part); |
|
free_number(fract_part); |
BN_free(int_part); |
return i + n->scale; |
|
|
return d + n->scale; |
} |
} |
|
|
static void |
static void |