Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 39739ea

Browse files
committed
better power implementation
1 parent cf3d108 commit 39739ea

1 file changed

Lines changed: 54 additions & 18 deletions

File tree

Objects/floatobject.c

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -316,38 +316,74 @@ float_divmod(v, w)
316316
return mkvalue("(dd)", div, mod);
317317
}
318318

319+
double powu(x, n)
320+
double x;
321+
long n;
322+
{
323+
double r = 1.;
324+
double p = x;
325+
long mask = 1;
326+
while (mask > 0 && n >= mask) {
327+
if (n & mask)
328+
r *= p;
329+
mask <<= 1;
330+
p *= p;
331+
}
332+
return r;
333+
}
334+
335+
double powi(x, n)
336+
double x;
337+
long n;
338+
{
339+
if (n > 10000 || n < -10000)
340+
return pow(x, (double) n);
341+
else if (n > 0)
342+
return powu(x, n);
343+
else
344+
return 1./powu(x, -n);
345+
}
346+
319347
static object *
320348
float_pow(v, w, z)
321349
floatobject *v;
322-
floatobject *w;
350+
object *w;
323351
floatobject *z;
324352
{
325353
double iv, iw, ix;
326-
iv = v->ob_fval;
327-
iw = w->ob_fval;
354+
long intw;
328355
/* XXX Doesn't handle overflows if z!=None yet; it may never do so :(
329356
* The z parameter is really only going to be useful for integers and
330357
* long integers. Maybe something clever with logarithms could be done.
331358
* [AMK]
332359
*/
333-
/* Sort out special cases here instead of relying on pow() */
334-
if (iw == 0.0) { /* x**0 is 1, even 0**0 */
335-
if ((object *)z!=None) {
336-
ix=fmod(1.0, z->ob_fval);
337-
if (ix!=0 && z->ob_fval<0) ix+=z->ob_fval;
338-
}
339-
else ix=1.0;
340-
return newfloatobject(ix);
360+
iv = v->ob_fval;
361+
iw = ((floatobject *)w)->ob_fval;
362+
intw = (long)iw;
363+
if (iw == intw) {
364+
errno = 0;
365+
ix = powi(iv, intw);
341366
}
342-
if (iv == 0.0) {
343-
if (iw < 0.0) {
344-
err_setstr(ValueError, "0.0 to a negative power");
345-
return NULL;
367+
else {
368+
/* Sort out special cases here instead of relying on pow() */
369+
if (iw == 0.0) { /* x**0 is 1, even 0**0 */
370+
if ((object *)z!=None) {
371+
ix=fmod(1.0, z->ob_fval);
372+
if (ix!=0 && z->ob_fval<0) ix+=z->ob_fval;
373+
}
374+
else ix=1.0;
375+
return newfloatobject(ix);
376+
}
377+
if (iv == 0.0) {
378+
if (iw < 0.0) {
379+
err_setstr(ValueError, "0.0 to a negative power");
380+
return NULL;
381+
}
382+
return newfloatobject(0.0);
346383
}
347-
return newfloatobject(0.0);
384+
errno = 0;
385+
ix = pow(iv, iw);
348386
}
349-
errno = 0;
350-
ix = pow(iv, iw);
351387
CHECK(ix);
352388
if (errno != 0) {
353389
/* XXX could it be another type of error? */

0 commit comments

Comments
 (0)