diff options
author | Piotr Fusik <pfusik@op.pl> | 2005-06-24 14:47:40 +0200 |
---|---|---|
committer | Dave Mitchell <davem@fdisolutions.com> | 2005-07-19 01:16:09 +0000 |
commit | 900658e3894003c933933cc814fc7c95f6f6a2dd (patch) | |
tree | e3444c9c05cbf2e11b6bd0736134488ea120e434 /pp.c | |
parent | 2fc04a10ca47a4a5713a39beb29dd8beb9d0f653 (diff) | |
download | perl-900658e3894003c933933cc814fc7c95f6f6a2dd.tar.gz |
Re: [PATCH] Faster **
From: "Piotr Fusik" <pfusik@op.pl>
Message-Id: <00b201c578af$7ad02b40$17d24dd5@piec>
p4raw-id: //depot/perl@25177
Diffstat (limited to 'pp.c')
-rw-r--r-- | pp.c | 108 |
1 files changed, 52 insertions, 56 deletions
@@ -900,36 +900,37 @@ PP(pp_pow) we're sure it is safe; otherwise we call pow() and try to convert to integer afterwards. */ { - SvIV_please(TOPm1s); - if (SvIOK(TOPm1s)) { - bool baseuok = SvUOK(TOPm1s); - UV baseuv; + SvIV_please(TOPs); + if (SvIOK(TOPs)) { + SvIV_please(TOPm1s); + if (SvIOK(TOPm1s)) { + UV power; + bool baseuok; + UV baseuv; - if (baseuok) { - baseuv = SvUVX(TOPm1s); - } else { - const IV iv = SvIVX(TOPm1s); - if (iv >= 0) { - baseuv = iv; - baseuok = TRUE; /* effectively it's a UV now */ - } else { - baseuv = -iv; /* abs, baseuok == false records sign */ - } - } - SvIV_please(TOPs); - if (SvIOK(TOPs)) { - UV power; + if (SvUOK(TOPs)) { + power = SvUVX(TOPs); + } else { + const IV iv = SvIVX(TOPs); + if (iv >= 0) { + power = iv; + } else { + goto float_it; /* Can't do negative powers this way. */ + } + } - if (SvUOK(TOPs)) { - power = SvUVX(TOPs); - } else { - IV iv = SvIVX(TOPs); - if (iv >= 0) { - power = iv; - } else { - goto float_it; /* Can't do negative powers this way. */ - } - } + baseuok = SvUOK(TOPm1s); + if (baseuok) { + baseuv = SvUVX(TOPm1s); + } else { + const IV iv = SvIVX(TOPm1s); + if (iv >= 0) { + baseuv = iv; + baseuok = TRUE; /* effectively it's a UV now */ + } else { + baseuv = -iv; /* abs, baseuok == false records sign */ + } + } /* now we have integer ** positive integer. */ is_int = 1; @@ -945,34 +946,28 @@ PP(pp_pow) programmers to notice ** not doing what they mean. */ NV result = 1.0; NV base = baseuok ? baseuv : -(NV)baseuv; - int n = 0; - - for (; power; base *= base, n++) { - /* Do I look like I trust gcc with long longs here? - Do I hell. */ - const UV bit = (UV)1 << (UV)n; - if (power & bit) { - result *= base; - /* Only bother to clear the bit if it is set. */ - power -= bit; - /* Avoid squaring base again if we're done. */ - if (power == 0) break; - } - } + + if (power & 1) { + result *= base; + } + while (power >>= 1) { + base *= base; + if (power & 1) { + result *= base; + } + } SP--; SETn( result ); SvIV_please(TOPs); RETURN; } else { register unsigned int highbit = 8 * sizeof(UV); - register unsigned int lowbit = 0; - register unsigned int diff; - bool odd_power = (bool)(power & 1); - while ((diff = (highbit - lowbit) >> 1)) { - if (baseuv & ~((1 << (lowbit + diff)) - 1)) - lowbit += diff; - else - highbit -= diff; + register unsigned int diff = 8 * sizeof(UV); + while (diff >>= 1) { + highbit -= diff; + if (baseuv >> highbit) { + highbit += diff; + } } /* we now have baseuv < 2 ** highbit */ if (power * highbit <= 8 * sizeof(UV)) { @@ -980,13 +975,14 @@ PP(pp_pow) on same algorithm as above */ register UV result = 1; register UV base = baseuv; - register int n = 0; - for (; power; base *= base, n++) { - register const UV bit = (UV)1 << (UV)n; - if (power & bit) { + const bool odd_power = (bool)(power & 1); + if (odd_power) { + result *= base; + } + while (power >>= 1) { + base *= base; + if (power & 1) { result *= base; - power -= bit; - if (power == 0) break; } } SP--; |