bug-gnu-utils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: gawk bug


From: Andrew J. Schorr
Subject: Re: gawk bug
Date: Tue, 14 Jun 2005 08:43:46 -0400
User-agent: Mutt/1.4.1i

On Mon, Jun 13, 2005 at 03:21:11PM -0700, John H. DuBois III wrote:
> $ time gawk 'BEGIN{j=1; j^=-1; print j}'
> 1
> 
> user    0m9.60s
> 
> $ time gawk 'BEGIN{j=1; j=j^-1; print j}'
> 1
> 
> user    0m0.00s

Interesting.  The difference is in the Node_assign_exp vs. Node_exp
code in eval.c.

For Node_exp, it says:

        case Node_exp:
                if ((lx = x2) == x2 && lx >= 0) {       /* integer exponent */
                        if (lx == 0)
                                x = 1;
                        else if (lx == 1)
                                x = x1;
                        else {
                                /* doing it this way should be more precise */
                                for (x = x1; --lx; )
                                        x *= x1;
                        }
                } else
                        x = pow((double) x1, (double) x2);
                return tmp_number(x);

Whereas for Node_assign_exp, it says:

                if ((ltemp = rval) == rval) {   /* integer exponent */
                        if (ltemp == 0)
                                *lhs = make_number((AWKNUM) 1);
                        else if (ltemp == 1)
                                *lhs = make_number(lval);
                        else {
                                /* doing it this way should be more precise */
                                for (t1 = t2 = lval; --ltemp; )
                                        t1 *= t2;
                                *lhs = make_number(t1);
                        }
                } else
                        *lhs = make_number((AWKNUM) pow((double) lval, (double) 
rval));


The difference is that Node_exp checks for a non-negative exponent, whereas
Node_assign_exp omits that check.  So the 'for' loop takes quite some time
to run.

Note that using a large integer exponent also takes a lot of time:

bash-2.05b$ time gawk 'BEGIN{j=1; j=j^2000000000; print j}'                   
1

real    0m4.120s
bash-2.05b$ time gawk 'BEGIN{j=1; j^=2000000000; print j}'
1

real    0m4.133s

A quick patch for the original problem would be to change the Node_assign_exp
code to check for a non-negative exponent.

But beyond that, I think there are 2 issues here: 1. the same function should
be used in both places; and 2. the exponentiation algorithm is not very good,
instead exponentiation by squaring should be used:

   http://en.wikipedia.org/wiki/Exponentiation_by_squaring

Regards,
Andy




reply via email to

[Prev in Thread] Current Thread [Next in Thread]