summaryrefslogtreecommitdiff
path: root/pp.c
diff options
context:
space:
mode:
authorPiotr Fusik <pfusik@op.pl>2005-06-24 14:47:40 +0200
committerDave Mitchell <davem@fdisolutions.com>2005-07-19 01:16:09 +0000
commit900658e3894003c933933cc814fc7c95f6f6a2dd (patch)
treee3444c9c05cbf2e11b6bd0736134488ea120e434 /pp.c
parent2fc04a10ca47a4a5713a39beb29dd8beb9d0f653 (diff)
downloadperl-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.c108
1 files changed, 52 insertions, 56 deletions
diff --git a/pp.c b/pp.c
index cb48bb86a4..be055a0309 100644
--- a/pp.c
+++ b/pp.c
@@ -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--;