On Sun, Nov 04, 2012 at 03:06:14PM -0430, Andres Perera wrote:
> On Sun, Nov 4, 2012 at 1:41 PM, Otto Moerbeek <[email protected]> wrote:
> >
> > It's easy to create a trunc function. Yes it will needs scale setting
> > en resetting, but I do not see that as a problem.
> >
> > On the other hand, being reminded that ^ does not do fractional exponents
> > is very important.
>
> is it important because there is no root operator or because scale
> itself is a side effect in other currently present operators?
>
> if it's the first, what about a patch that checks (scale &&
> fractional_part != 0) before issuing the warning?
Like teh diff below.
BTW I was looking into the case 0.1^-1. Single Unix is pretty
confusing about it, talking about an absolute value being negaitive.
To quote:
expression^expression
The result shall be the first expression raised to the power of the
second expression. If the second expression is not an integer, the
behavior is undefined. If a is the scale of the left expression and b
is the absolute value of the right expression, the scale of the result
shall be:
if b >= 0 min(a * b, max(scale, a)) if b < 0 scale
-Otto
Index: bcode.c
===================================================================
RCS file: /cvs/src/usr.bin/dc/bcode.c,v
retrieving revision 1.42
diff -u -p -r1.42 bcode.c
--- bcode.c 8 Mar 2012 08:15:37 -0000 1.42
+++ bcode.c 5 Nov 2012 19:35:41 -0000
@@ -1176,12 +1176,23 @@ bexp(void)
return;
}
- if (p->scale != 0)
- warnx("Runtime warning: non-zero scale in exponent");
+ if (p->scale != 0) {
+ BIGNUM *i, *f;
+ i = BN_new();
+ bn_checkp(i);
+ f = BN_new();
+ bn_checkp(f);
+ split_number(p, i, f);
+ if (!BN_is_zero(f))
+ warnx("Runtime warning: non-zero fractional part in
exponent");
+ BN_free(i);
+ BN_free(f);
+ }
+
normalize(p, 0);
neg = false;
- if (BN_cmp(p->number, &zero) < 0) {
+ if (BN_is_negative(p->number)) {
neg = true;
negate(p);
scale = bmachine.scale;
@@ -1230,7 +1241,12 @@ bexp(void)
bn_checkp(ctx);
scale_number(one, r->scale + scale);
normalize(r, scale);
- bn_check(BN_div(r->number, NULL, one, r->number, ctx));
+
+ if (BN_is_zero(r->number))
+ warnx("divide by zero");
+ else
+ bn_check(BN_div(r->number, NULL, one,
+ r->number, ctx));
BN_free(one);
BN_CTX_free(ctx);
} else