version 1.44, 2012/11/06 16:00:05 |
version 1.45, 2012/11/07 11:06:14 |
|
|
(void)signal(SIGINT, sighandler); |
(void)signal(SIGINT, sighandler); |
} |
} |
|
|
|
u_int |
|
bmachine_scale(void) |
|
{ |
|
return bmachine.scale; |
|
} |
|
|
/* Reset the things needed before processing a (new) file */ |
/* Reset the things needed before processing a (new) file */ |
void |
void |
reset_bmachine(struct source *src) |
reset_bmachine(struct source *src) |
|
|
} |
} |
|
|
void |
void |
bmul_number(struct number *r, struct number *a, struct number *b) |
bmul_number(struct number *r, struct number *a, struct number *b, u_int scale) |
{ |
{ |
BN_CTX *ctx; |
BN_CTX *ctx; |
|
|
|
|
bn_check(BN_mul(r->number, a->number, b->number, ctx)); |
bn_check(BN_mul(r->number, a->number, b->number, ctx)); |
BN_CTX_free(ctx); |
BN_CTX_free(ctx); |
|
|
if (rscale > bmachine.scale && rscale > ascale && rscale > bscale) { |
r->scale = rscale; |
r->scale = rscale; |
if (rscale > bmachine.scale && rscale > ascale && rscale > bscale) |
normalize(r, max(bmachine.scale, max(ascale, bscale))); |
normalize(r, max(scale, max(ascale, bscale))); |
} else |
|
r->scale = rscale; |
|
} |
} |
|
|
static void |
static void |
|
|
} |
} |
|
|
r = new_number(); |
r = new_number(); |
bmul_number(r, a, b); |
bmul_number(r, a, b, bmachine.scale); |
|
|
push_number(r); |
push_number(r); |
free_number(a); |
free_number(a); |
|
|
struct number *a, *p; |
struct number *a, *p; |
struct number *r; |
struct number *r; |
bool neg; |
bool neg; |
u_int scale; |
u_int rscale; |
|
|
p = pop_number(); |
p = pop_number(); |
if (p == NULL) { |
if (p == NULL) { |
|
|
if (BN_is_negative(p->number)) { |
if (BN_is_negative(p->number)) { |
neg = true; |
neg = true; |
negate(p); |
negate(p); |
scale = bmachine.scale; |
rscale = bmachine.scale; |
} else { |
} else { |
/* Posix bc says min(a.scale * b, max(a.scale, scale) */ |
/* Posix bc says min(a.scale * b, max(a.scale, scale) */ |
u_long b; |
u_long b; |
|
|
|
|
b = BN_get_word(p->number); |
b = BN_get_word(p->number); |
m = max(a->scale, bmachine.scale); |
m = max(a->scale, bmachine.scale); |
scale = a->scale * (u_int)b; |
rscale = a->scale * (u_int)b; |
if (scale > m || (a->scale > 0 && (b == BN_MASK2 || |
if (rscale > m || (a->scale > 0 && (b == BN_MASK2 || |
b > UINT_MAX))) |
b > UINT_MAX))) |
scale = m; |
rscale = m; |
} |
} |
|
|
if (BN_is_zero(p->number)) { |
if (BN_is_zero(p->number)) { |
r = new_number(); |
r = new_number(); |
bn_check(BN_one(r->number)); |
bn_check(BN_one(r->number)); |
normalize(r, scale); |
normalize(r, rscale); |
} else { |
} else { |
|
u_int ascale, mscale; |
|
|
|
ascale = a->scale; |
while (!BN_is_bit_set(p->number, 0)) { |
while (!BN_is_bit_set(p->number, 0)) { |
bmul_number(a, a, a); |
ascale *= 2; |
|
bmul_number(a, a, a, ascale); |
bn_check(BN_rshift1(p->number, p->number)); |
bn_check(BN_rshift1(p->number, p->number)); |
} |
} |
|
|
r = dup_number(a); |
r = dup_number(a); |
normalize(r, scale); |
|
bn_check(BN_rshift1(p->number, p->number)); |
bn_check(BN_rshift1(p->number, p->number)); |
|
|
|
mscale = ascale; |
while (!BN_is_zero(p->number)) { |
while (!BN_is_zero(p->number)) { |
bmul_number(a, a, a); |
ascale *= 2; |
if (BN_is_bit_set(p->number, 0)) |
bmul_number(a, a, a, ascale); |
bmul_number(r, r, a); |
if (BN_is_bit_set(p->number, 0)) { |
|
mscale += ascale; |
|
bmul_number(r, r, a, mscale); |
|
} |
bn_check(BN_rshift1(p->number, p->number)); |
bn_check(BN_rshift1(p->number, p->number)); |
} |
} |
|
|
|
|
bn_check(BN_one(one)); |
bn_check(BN_one(one)); |
ctx = BN_CTX_new(); |
ctx = BN_CTX_new(); |
bn_checkp(ctx); |
bn_checkp(ctx); |
scale_number(one, r->scale + scale); |
scale_number(one, r->scale + rscale); |
normalize(r, scale); |
|
|
|
if (BN_is_zero(r->number)) |
if (BN_is_zero(r->number)) |
warnx("divide by zero"); |
warnx("divide by zero"); |
|
|
r->number, ctx)); |
r->number, ctx)); |
BN_free(one); |
BN_free(one); |
BN_CTX_free(ctx); |
BN_CTX_free(ctx); |
|
r->scale = rscale; |
} else |
} else |
normalize(r, scale); |
normalize(r, rscale); |
} |
} |
push_number(r); |
push_number(r); |
free_number(a); |
free_number(a); |