mirror of
https://github.com/python/cpython.git
synced 2025-08-02 08:02:56 +00:00
better power implementation
This commit is contained in:
parent
cf3d1087d1
commit
39739ea0ed
1 changed files with 54 additions and 18 deletions
|
@ -316,38 +316,74 @@ float_divmod(v, w)
|
||||||
return mkvalue("(dd)", div, mod);
|
return mkvalue("(dd)", div, mod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double powu(x, n)
|
||||||
|
double x;
|
||||||
|
long n;
|
||||||
|
{
|
||||||
|
double r = 1.;
|
||||||
|
double p = x;
|
||||||
|
long mask = 1;
|
||||||
|
while (mask > 0 && n >= mask) {
|
||||||
|
if (n & mask)
|
||||||
|
r *= p;
|
||||||
|
mask <<= 1;
|
||||||
|
p *= p;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
double powi(x, n)
|
||||||
|
double x;
|
||||||
|
long n;
|
||||||
|
{
|
||||||
|
if (n > 10000 || n < -10000)
|
||||||
|
return pow(x, (double) n);
|
||||||
|
else if (n > 0)
|
||||||
|
return powu(x, n);
|
||||||
|
else
|
||||||
|
return 1./powu(x, -n);
|
||||||
|
}
|
||||||
|
|
||||||
static object *
|
static object *
|
||||||
float_pow(v, w, z)
|
float_pow(v, w, z)
|
||||||
floatobject *v;
|
floatobject *v;
|
||||||
floatobject *w;
|
object *w;
|
||||||
floatobject *z;
|
floatobject *z;
|
||||||
{
|
{
|
||||||
double iv, iw, ix;
|
double iv, iw, ix;
|
||||||
iv = v->ob_fval;
|
long intw;
|
||||||
iw = w->ob_fval;
|
|
||||||
/* XXX Doesn't handle overflows if z!=None yet; it may never do so :(
|
/* XXX Doesn't handle overflows if z!=None yet; it may never do so :(
|
||||||
* The z parameter is really only going to be useful for integers and
|
* The z parameter is really only going to be useful for integers and
|
||||||
* long integers. Maybe something clever with logarithms could be done.
|
* long integers. Maybe something clever with logarithms could be done.
|
||||||
* [AMK]
|
* [AMK]
|
||||||
*/
|
*/
|
||||||
/* Sort out special cases here instead of relying on pow() */
|
iv = v->ob_fval;
|
||||||
if (iw == 0.0) { /* x**0 is 1, even 0**0 */
|
iw = ((floatobject *)w)->ob_fval;
|
||||||
if ((object *)z!=None) {
|
intw = (long)iw;
|
||||||
ix=fmod(1.0, z->ob_fval);
|
if (iw == intw) {
|
||||||
if (ix!=0 && z->ob_fval<0) ix+=z->ob_fval;
|
errno = 0;
|
||||||
}
|
ix = powi(iv, intw);
|
||||||
else ix=1.0;
|
|
||||||
return newfloatobject(ix);
|
|
||||||
}
|
}
|
||||||
if (iv == 0.0) {
|
else {
|
||||||
if (iw < 0.0) {
|
/* Sort out special cases here instead of relying on pow() */
|
||||||
err_setstr(ValueError, "0.0 to a negative power");
|
if (iw == 0.0) { /* x**0 is 1, even 0**0 */
|
||||||
return NULL;
|
if ((object *)z!=None) {
|
||||||
|
ix=fmod(1.0, z->ob_fval);
|
||||||
|
if (ix!=0 && z->ob_fval<0) ix+=z->ob_fval;
|
||||||
|
}
|
||||||
|
else ix=1.0;
|
||||||
|
return newfloatobject(ix);
|
||||||
}
|
}
|
||||||
return newfloatobject(0.0);
|
if (iv == 0.0) {
|
||||||
|
if (iw < 0.0) {
|
||||||
|
err_setstr(ValueError, "0.0 to a negative power");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return newfloatobject(0.0);
|
||||||
|
}
|
||||||
|
errno = 0;
|
||||||
|
ix = pow(iv, iw);
|
||||||
}
|
}
|
||||||
errno = 0;
|
|
||||||
ix = pow(iv, iw);
|
|
||||||
CHECK(ix);
|
CHECK(ix);
|
||||||
if (errno != 0) {
|
if (errno != 0) {
|
||||||
/* XXX could it be another type of error? */
|
/* XXX could it be another type of error? */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue