On Tue, Nov 06, 2012 at 04:57:20PM -0430, Andres Perera wrote:
> 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
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);