version 1.58, 2017/12/02 12:43:18 |
version 1.59, 2017/12/05 14:05:22 |
|
|
volatile sig_atomic_t interrupted; |
volatile sig_atomic_t interrupted; |
struct source *readstack; |
struct source *readstack; |
size_t readstack_sz; |
size_t readstack_sz; |
|
BN_CTX *ctx; |
}; |
}; |
|
|
static struct bmachine bmachine; |
static struct bmachine bmachine; |
|
|
opcode_function f; |
opcode_function f; |
}; |
}; |
|
|
|
|
static opcode_function jump_table[UCHAR_MAX + 1]; |
static opcode_function jump_table[UCHAR_MAX + 1]; |
|
|
static const struct jump_entry jump_table_data[] = { |
static const struct jump_entry jump_table_data[] = { |
|
|
{ |
{ |
int i; |
int i; |
|
|
|
bmachine.ctx = BN_CTX_new(); |
|
bn_checkp(bmachine.ctx); |
|
|
bmachine.extended_regs = extended_registers; |
bmachine.extended_regs = extended_registers; |
bmachine.reg_array_size = bmachine.extended_regs ? |
bmachine.reg_array_size = bmachine.extended_regs ? |
REG_ARRAY_SIZE_BIG : REG_ARRAY_SIZE_SMALL; |
REG_ARRAY_SIZE_BIG : REG_ARRAY_SIZE_SMALL; |
|
|
(void)BN_div_word(n, factors[abs_scale]); |
(void)BN_div_word(n, factors[abs_scale]); |
} else { |
} else { |
BIGNUM *a, *p; |
BIGNUM *a, *p; |
BN_CTX *ctx; |
|
|
|
a = BN_new(); |
a = BN_new(); |
bn_checkp(a); |
bn_checkp(a); |
p = BN_new(); |
p = BN_new(); |
bn_checkp(p); |
bn_checkp(p); |
ctx = BN_CTX_new(); |
|
bn_checkp(ctx); |
|
|
|
bn_check(BN_set_word(a, 10)); |
bn_check(BN_set_word(a, 10)); |
bn_check(BN_set_word(p, abs_scale)); |
bn_check(BN_set_word(p, abs_scale)); |
bn_check(BN_exp(a, a, p, ctx)); |
bn_check(BN_exp(a, a, p, bmachine.ctx)); |
if (s > 0) |
if (s > 0) |
bn_check(BN_mul(n, n, a, ctx)); |
bn_check(BN_mul(n, n, a, bmachine.ctx)); |
else |
else |
bn_check(BN_div(n, NULL, n, a, ctx)); |
bn_check(BN_div(n, NULL, n, a, bmachine.ctx)); |
BN_CTX_free(ctx); |
|
BN_free(a); |
BN_free(a); |
BN_free(p); |
BN_free(p); |
} |
} |
|
|
bn_check(BN_set_word(f, rem)); |
bn_check(BN_set_word(f, rem)); |
} else { |
} else { |
BIGNUM *a, *p; |
BIGNUM *a, *p; |
BN_CTX *ctx; |
|
|
|
a = BN_new(); |
a = BN_new(); |
bn_checkp(a); |
bn_checkp(a); |
p = BN_new(); |
p = BN_new(); |
bn_checkp(p); |
bn_checkp(p); |
ctx = BN_CTX_new(); |
|
bn_checkp(ctx); |
|
|
|
bn_check(BN_set_word(a, 10)); |
bn_check(BN_set_word(a, 10)); |
bn_check(BN_set_word(p, n->scale)); |
bn_check(BN_set_word(p, n->scale)); |
bn_check(BN_exp(a, a, p, ctx)); |
bn_check(BN_exp(a, a, p, bmachine.ctx)); |
bn_check(BN_div(i, f, n->number, a, ctx)); |
bn_check(BN_div(i, f, n->number, a, bmachine.ctx)); |
BN_CTX_free(ctx); |
|
BN_free(a); |
BN_free(a); |
BN_free(p); |
BN_free(p); |
} |
} |
|
|
count_digits(const struct number *n) |
count_digits(const struct number *n) |
{ |
{ |
BIGNUM *int_part, *a, *p; |
BIGNUM *int_part, *a, *p; |
BN_CTX *ctx; |
|
uint d; |
uint d; |
const uint64_t c = 1292913986; /* floor(2^32 * log_10(2)) */ |
const uint64_t c = 1292913986; /* floor(2^32 * log_10(2)) */ |
int bits; |
int bits; |
|
|
|
|
/* If close to a possible rounding error fix if needed */ |
/* If close to a possible rounding error fix if needed */ |
if (d != (c * (bits - 1)) >> 32) { |
if (d != (c * (bits - 1)) >> 32) { |
ctx = BN_CTX_new(); |
|
bn_checkp(ctx); |
|
a = BN_new(); |
a = BN_new(); |
bn_checkp(a); |
bn_checkp(a); |
p = BN_new(); |
p = BN_new(); |
|
|
|
|
bn_check(BN_set_word(a, 10)); |
bn_check(BN_set_word(a, 10)); |
bn_check(BN_set_word(p, d)); |
bn_check(BN_set_word(p, d)); |
bn_check(BN_exp(a, a, p, ctx)); |
bn_check(BN_exp(a, a, p, bmachine.ctx)); |
|
|
if (BN_ucmp(int_part, a) >= 0) |
if (BN_ucmp(int_part, a) >= 0) |
d++; |
d++; |
|
|
BN_CTX_free(ctx); |
|
BN_free(a); |
BN_free(a); |
BN_free(p); |
BN_free(p); |
} else |
} else |
|
|
void |
void |
bmul_number(struct number *r, struct number *a, struct number *b, u_int scale) |
bmul_number(struct number *r, struct number *a, struct number *b, u_int scale) |
{ |
{ |
BN_CTX *ctx; |
|
|
|
/* Create copies of the scales, since r might be equal to a or b */ |
/* Create copies of the scales, since r might be equal to a or b */ |
u_int ascale = a->scale; |
u_int ascale = a->scale; |
u_int bscale = b->scale; |
u_int bscale = b->scale; |
u_int rscale = ascale + bscale; |
u_int rscale = ascale + bscale; |
|
|
ctx = BN_CTX_new(); |
bn_check(BN_mul(r->number, a->number, b->number, bmachine.ctx)); |
bn_checkp(ctx); |
|
bn_check(BN_mul(r->number, a->number, b->number, ctx)); |
|
BN_CTX_free(ctx); |
|
|
|
r->scale = rscale; |
r->scale = rscale; |
if (rscale > bmachine.scale && rscale > ascale && rscale > bscale) |
if (rscale > bmachine.scale && rscale > ascale && rscale > bscale) |
|
|
struct number *a, *b; |
struct number *a, *b; |
struct number *r; |
struct number *r; |
u_int scale; |
u_int scale; |
BN_CTX *ctx; |
|
|
|
a = pop_number(); |
a = pop_number(); |
if (a == NULL) |
if (a == NULL) |
|
|
normalize(a, scale); |
normalize(a, scale); |
normalize(b, scale + r->scale); |
normalize(b, scale + r->scale); |
|
|
ctx = BN_CTX_new(); |
bn_check(BN_div(r->number, NULL, b->number, a->number, bmachine.ctx)); |
bn_checkp(ctx); |
|
bn_check(BN_div(r->number, NULL, b->number, a->number, ctx)); |
|
BN_CTX_free(ctx); |
|
} |
} |
push_number(r); |
push_number(r); |
free_number(a); |
free_number(a); |
|
|
struct number *a, *b; |
struct number *a, *b; |
struct number *r; |
struct number *r; |
u_int scale; |
u_int scale; |
BN_CTX *ctx; |
|
|
|
a = pop_number(); |
a = pop_number(); |
if (a == NULL) |
if (a == NULL) |
|
|
normalize(a, scale); |
normalize(a, scale); |
normalize(b, scale + bmachine.scale); |
normalize(b, scale + bmachine.scale); |
|
|
ctx = BN_CTX_new(); |
bn_check(BN_mod(r->number, b->number, a->number, bmachine.ctx)); |
bn_checkp(ctx); |
|
bn_check(BN_mod(r->number, b->number, a->number, ctx)); |
|
BN_CTX_free(ctx); |
|
} |
} |
push_number(r); |
push_number(r); |
free_number(a); |
free_number(a); |
|
|
struct number *a, *b; |
struct number *a, *b; |
struct number *rdiv, *rmod; |
struct number *rdiv, *rmod; |
u_int scale; |
u_int scale; |
BN_CTX *ctx; |
|
|
|
a = pop_number(); |
a = pop_number(); |
if (a == NULL) |
if (a == NULL) |
|
|
normalize(a, scale); |
normalize(a, scale); |
normalize(b, scale + bmachine.scale); |
normalize(b, scale + bmachine.scale); |
|
|
ctx = BN_CTX_new(); |
|
bn_checkp(ctx); |
|
bn_check(BN_div(rdiv->number, rmod->number, |
bn_check(BN_div(rdiv->number, rmod->number, |
b->number, a->number, ctx)); |
b->number, a->number, bmachine.ctx)); |
BN_CTX_free(ctx); |
|
} |
} |
push_number(rdiv); |
push_number(rdiv); |
push_number(rmod); |
push_number(rmod); |
|
|
} |
} |
|
|
if (neg) { |
if (neg) { |
BN_CTX *ctx; |
|
BIGNUM *one; |
BIGNUM *one; |
|
|
one = BN_new(); |
one = BN_new(); |
bn_checkp(one); |
bn_checkp(one); |
bn_check(BN_one(one)); |
bn_check(BN_one(one)); |
ctx = BN_CTX_new(); |
|
bn_checkp(ctx); |
|
scale_number(one, r->scale + rscale); |
scale_number(one, r->scale + rscale); |
|
|
if (BN_is_zero(r->number)) |
if (BN_is_zero(r->number)) |
warnx("divide by zero"); |
warnx("divide by zero"); |
else |
else |
bn_check(BN_div(r->number, NULL, one, |
bn_check(BN_div(r->number, NULL, one, |
r->number, ctx)); |
r->number, bmachine.ctx)); |
BN_free(one); |
BN_free(one); |
BN_CTX_free(ctx); |
|
r->scale = rscale; |
r->scale = rscale; |
} else |
} else |
normalize(r, rscale); |
normalize(r, rscale); |
|
|
struct number *r; |
struct number *r; |
BIGNUM *x, *y, *t; |
BIGNUM *x, *y, *t; |
u_int scale, onecount; |
u_int scale, onecount; |
BN_CTX *ctx; |
|
|
|
onecount = 0; |
onecount = 0; |
n = pop_number(); |
n = pop_number(); |
|
|
bn_check(BN_rshift(x, x, BN_num_bits(x)/2)); |
bn_check(BN_rshift(x, x, BN_num_bits(x)/2)); |
y = BN_new(); |
y = BN_new(); |
bn_checkp(y); |
bn_checkp(y); |
ctx = BN_CTX_new(); |
|
bn_checkp(ctx); |
|
do { |
do { |
bn_check(BN_div(y, NULL, n->number, x, ctx)); |
bn_check(BN_div(y, NULL, n->number, x, bmachine.ctx)); |
bn_check(BN_add(y, x, y)); |
bn_check(BN_add(y, x, y)); |
bn_check(BN_rshift1(y, y)); |
bn_check(BN_rshift1(y, y)); |
bn_check(BN_sub(x, y, x)); |
bn_check(BN_sub(x, y, x)); |
|
|
r->scale = scale; |
r->scale = scale; |
r->number = y; |
r->number = y; |
BN_free(x); |
BN_free(x); |
BN_CTX_free(ctx); |
|
push_number(r); |
push_number(r); |
} |
} |
|
|