On Tue, Nov 06, 2012 at 04:57:20PM -0430, Andres Perera wrote: > On Tue, Nov 6, 2012 at 3:27 PM, Otto Moerbeek <o...@drijf.net> wrote: > > Hi, > > > > And here's a diff to repair ^, whcih now produces correct results for > > things like > > > > (dc) 0.1 _1 ^p > > or > > (bc) 0.1 ^ -1 > > > > The diff is against very current, so beware. > > i've lightly tested it against gnu bc and it works > > i do have 2 small comments below
Fair enough. New diff. -Otto Index: bcode.c =================================================================== RCS file: /cvs/src/usr.bin/dc/bcode.c,v retrieving revision 1.44 diff -u -p -r1.44 bcode.c --- bcode.c 6 Nov 2012 16:00:05 -0000 1.44 +++ bcode.c 7 Nov 2012 06:45:52 -0000 @@ -257,6 +257,12 @@ init_bmachine(bool extended_registers) (void)signal(SIGINT, sighandler); } +u_int +bmachine_scale(void) +{ + return bmachine.scale; +} + /* Reset the things needed before processing a (new) file */ void reset_bmachine(struct source *src) @@ -991,7 +997,7 @@ bsub(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; @@ -1005,11 +1011,9 @@ bmul_number(struct number *r, struct num bn_check(BN_mul(r->number, a->number, b->number, ctx)); BN_CTX_free(ctx); - if (rscale > bmachine.scale && rscale > ascale && rscale > bscale) { - r->scale = rscale; - normalize(r, max(bmachine.scale, max(ascale, bscale))); - } else - r->scale = rscale; + r->scale = rscale; + if (rscale > bmachine.scale && rscale > ascale && rscale > bscale) + normalize(r, max(scale, max(ascale, bscale))); } static void @@ -1029,7 +1033,7 @@ bmul(void) } r = new_number(); - bmul_number(r, a, b); + bmul_number(r, a, b, bmachine.scale); push_number(r); free_number(a); @@ -1160,7 +1164,7 @@ bexp(void) struct number *a, *p; struct number *r; bool neg; - u_int scale; + u_int rscale; p = pop_number(); if (p == NULL) { @@ -1191,7 +1195,7 @@ bexp(void) if (BN_is_negative(p->number)) { neg = true; negate(p); - scale = bmachine.scale; + rscale = bmachine.scale; } else { /* Posix bc says min(a.scale * b, max(a.scale, scale) */ u_long b; @@ -1199,30 +1203,37 @@ bexp(void) b = BN_get_word(p->number); m = max(a->scale, bmachine.scale); - scale = a->scale * (u_int)b; - if (scale > m || (a->scale > 0 && (b == BN_MASK2 || + rscale = a->scale * (u_int)b; + if (rscale > m || (a->scale > 0 && (b == BN_MASK2 || b > UINT_MAX))) - scale = m; + rscale = m; } if (BN_is_zero(p->number)) { r = new_number(); bn_check(BN_one(r->number)); - normalize(r, scale); + normalize(r, rscale); } else { + u_int ascale, mscale; + + ascale = a->scale; 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)); } r = dup_number(a); - normalize(r, scale); bn_check(BN_rshift1(p->number, p->number)); + mscale = ascale; while (!BN_is_zero(p->number)) { - bmul_number(a, a, a); - if (BN_is_bit_set(p->number, 0)) - bmul_number(r, r, a); + ascale *= 2; + bmul_number(a, a, a, ascale); + if (BN_is_bit_set(p->number, 0)) { + mscale += ascale; + bmul_number(r, r, a, mscale); + } bn_check(BN_rshift1(p->number, p->number)); } @@ -1235,8 +1246,7 @@ bexp(void) bn_check(BN_one(one)); ctx = BN_CTX_new(); bn_checkp(ctx); - scale_number(one, r->scale + scale); - normalize(r, scale); + scale_number(one, r->scale + rscale); if (BN_is_zero(r->number)) warnx("divide by zero"); @@ -1245,8 +1255,9 @@ bexp(void) r->number, ctx)); BN_free(one); BN_CTX_free(ctx); + r->scale = rscale; } else - normalize(r, scale); + normalize(r, rscale); } push_number(r); free_number(a); Index: bcode.h =================================================================== RCS file: /cvs/src/usr.bin/dc/bcode.h,v retrieving revision 1.6 diff -u -p -r1.6 bcode.h --- bcode.h 6 Nov 2012 16:00:05 -0000 1.6 +++ bcode.h 7 Nov 2012 06:45:53 -0000 @@ -85,6 +85,7 @@ struct source { void init_bmachine(bool); void reset_bmachine(struct source *); +u_int bmachine_scale(void); void scale_number(BIGNUM *, int); void normalize(struct number *, u_int); void eval(void); @@ -93,4 +94,4 @@ void pbn(const char *, const BIGNUM *) void negate(struct number *); void split_number(const struct number *, BIGNUM *, BIGNUM *); void bmul_number(struct number *, struct number *, - struct number *); + struct number *, u_int scale); Index: inout.c =================================================================== RCS file: /cvs/src/usr.bin/dc/inout.c,v retrieving revision 1.16 diff -u -p -r1.16 inout.c --- inout.c 6 Nov 2012 16:00:05 -0000 1.16 +++ inout.c 7 Nov 2012 06:45:53 -0000 @@ -348,7 +348,8 @@ printnumber(FILE *f, const struct number putcharwrap(f, ' '); i = 1; - bmul_number(fract_part, fract_part, num_base); + bmul_number(fract_part, fract_part, num_base, + bmachine_scale()); split_number(fract_part, int_part->number, NULL); rem = BN_get_word(int_part->number); p = get_digit(rem, digits, base);