Changeset View
Changeset View
Standalone View
Standalone View
head/usr.bin/dc/bcode.c
Show First 20 Lines • Show All 1,090 Lines • ▼ Show 20 Lines | bmod(void) | ||||
b = pop_number(); | b = pop_number(); | ||||
if (b == NULL) { | if (b == NULL) { | ||||
push_number(a); | push_number(a); | ||||
return; | return; | ||||
} | } | ||||
r = new_number(); | r = new_number(); | ||||
scale = max(a->scale, b->scale); | scale = max(a->scale, b->scale); | ||||
r->scale = max(b->scale, a->scale + bmachine.scale); | r->scale = scale; | ||||
if (BN_is_zero(a->number)) | if (BN_is_zero(a->number)) | ||||
warnx("remainder by zero"); | warnx("remainder by zero"); | ||||
else { | else { | ||||
normalize(a, scale); | normalize(a, scale); | ||||
normalize(b, scale + bmachine.scale); | normalize(b, scale); | ||||
ctx = BN_CTX_new(); | ctx = BN_CTX_new(); | ||||
bn_checkp(ctx); | bn_checkp(ctx); | ||||
bn_check(BN_mod(r->number, b->number, a->number, ctx)); | bn_check(BN_mod(r->number, b->number, a->number, ctx)); | ||||
BN_CTX_free(ctx); | BN_CTX_free(ctx); | ||||
} | } | ||||
push_number(r); | push_number(r); | ||||
free_number(a); | free_number(a); | ||||
free_number(b); | free_number(b); | ||||
} | } | ||||
static void | static void | ||||
bdivmod(void) | bdivmod(void) | ||||
{ | { | ||||
struct number *a, *b, *rdiv, *rmod; | struct number *a, *b, *frac, *quotient, *rdiv, *remainder; | ||||
BN_CTX *ctx; | BN_CTX *ctx; | ||||
u_int scale; | u_int scale; | ||||
a = pop_number(); | a = pop_number(); | ||||
if (a == NULL) | if (a == NULL) | ||||
return; | return; | ||||
b = pop_number(); | b = pop_number(); | ||||
if (b == NULL) { | if (b == NULL) { | ||||
push_number(a); | push_number(a); | ||||
return; | return; | ||||
} | } | ||||
rdiv = new_number(); | rdiv = new_number(); | ||||
rmod = new_number(); | quotient = new_number(); | ||||
rdiv->scale = bmachine.scale; | remainder = new_number(); | ||||
rmod->scale = max(b->scale, a->scale + bmachine.scale); | |||||
scale = max(a->scale, b->scale); | scale = max(a->scale, b->scale); | ||||
rdiv->scale = 0; | |||||
remainder->scale = scale; | |||||
quotient->scale = bmachine.scale; | |||||
scale = max(a->scale, b->scale); | |||||
if (BN_is_zero(a->number)) | if (BN_is_zero(a->number)) | ||||
warnx("divide by zero"); | warnx("divide by zero"); | ||||
else { | else { | ||||
normalize(a, scale); | normalize(a, scale); | ||||
normalize(b, scale + bmachine.scale); | normalize(b, scale); | ||||
ctx = BN_CTX_new(); | ctx = BN_CTX_new(); | ||||
bn_checkp(ctx); | bn_checkp(ctx); | ||||
bn_check(BN_div(rdiv->number, rmod->number, | /* | ||||
* Unlike other languages' divmod operations, dc is specified | |||||
* to return the remainder and the full quotient, rather than | |||||
* the remainder and the floored quotient. bn(3) has no | |||||
* function to calculate both. So we'll use BN_div to get the | |||||
* remainder and floored quotient, then calculate the full | |||||
* quotient from those. | |||||
* | |||||
* quotient = rdiv + remainder / divisor | |||||
*/ | |||||
bn_check(BN_div(rdiv->number, remainder->number, | |||||
b->number, a->number, ctx)); | b->number, a->number, ctx)); | ||||
frac = div_number(remainder, a, bmachine.scale); | |||||
normalize(rdiv, bmachine.scale); | |||||
normalize(remainder, scale); | |||||
bn_check(BN_add(quotient->number, rdiv->number, frac->number)); | |||||
free_number(frac); | |||||
BN_CTX_free(ctx); | BN_CTX_free(ctx); | ||||
} | } | ||||
push_number(rdiv); | push_number(quotient); | ||||
push_number(rmod); | push_number(remainder); | ||||
free_number(rdiv); | |||||
free_number(a); | free_number(a); | ||||
free_number(b); | free_number(b); | ||||
} | } | ||||
static void | static void | ||||
bexp(void) | bexp(void) | ||||
{ | { | ||||
struct number *a, *p; | struct number *a, *p; | ||||
▲ Show 20 Lines • Show All 596 Lines • Show Last 20 Lines |