On Tue, Nov 6, 2012 at 3:27 PM, Otto Moerbeek <[email protected]> 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 -0000 1.44
> +++ bcode.c 6 Nov 2012 19:42:07 -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;
>
> @@ -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;
> bool neg;
> - 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