dc(1) exp improvements
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. Please test. I have some regress test updates for dc as well. t9 turns out to be a wrong test (computation of 2.1 ^ 500). That is fixed with this diff as well. -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 - 1.44 +++ bcode.c 6 Nov 2012 19:42:07 - @@ -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; @@ -1007,7 +1013,7 @@ bmul_number(struct number *r, struct num if (rscale bmachine.scale rscale ascale rscale bscale) { r-scale = rscale; - normalize(r, max(bmachine.scale, max(ascale, bscale))); + normalize(r, max(scale, max(ascale, bscale))); } else r-scale = rscale; } @@ -1029,7 +1035,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 +1166,7 @@ bexp(void) struct number *a, *p; struct number *r; boolneg; - u_int scale; + u_int rscale; p = pop_number(); if (p == NULL) { @@ -1191,7 +1197,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 +1205,35 @@ 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 scale, 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)); + scale = 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)) { + scale += ascale; + bmul_number(r, r, a, scale); + } 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
Re: dc(1) exp improvements
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 Please test. I have some regress test updates for dc as well. t9 turns out to be a wrong test (computation of 2.1 ^ 500). That is fixed with this diff as well. -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 - 1.44 +++ bcode.c 6 Nov 2012 19:42:07 - @@ -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; @@ -1007,7 +1013,7 @@ bmul_number(struct number *r, struct num if (rscale bmachine.scale rscale ascale rscale bscale) { r-scale = rscale; - normalize(r, max(bmachine.scale, max(ascale, bscale))); + normalize(r, max(scale, max(ascale, bscale))); } else r-scale = rscale; the function unconditionally sets r-scale to rscale, but the operation is duplicated across `if' bodies. interpreting a diff for the function is difficult because the intent is unclear } @@ -1029,7 +1035,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 +1166,7 @@ bexp(void) struct number *a, *p; struct number *r; boolneg; - u_int scale; + u_int rscale; p = pop_number(); if (p == NULL) { @@ -1191,7 +1197,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 +1205,35 @@ 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 scale, ascale = a-scale; `scale' should be renamed for clarity to signify that it's an accumulator for `ascale'. at its current state, not being prefixed by a letter that is, `scale' looks more important than it is
Re: dc(1) exp improvements
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 - 1.44 +++ bcode.c 7 Nov 2012 06:45:52 - @@ -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; boolneg; - 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 -