mirror of https://github.com/python/cpython
bpo-44376 - reduce pow() overhead for small exponents (GH-26662)
Greatly reduce pow() overhead for small exponents.
This commit is contained in:
parent
be8b631b7a
commit
9d8dd8f08a
|
@ -0,0 +1 @@
|
||||||
|
Exact integer exponentiation (like ``i**2`` or ``pow(i, 2)``) with a small exponent is much faster, due to reducing overhead in such cases.
|
|
@ -4239,18 +4239,58 @@ long_pow(PyObject *v, PyObject *w, PyObject *x)
|
||||||
REDUCE(result); \
|
REDUCE(result); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
if (Py_SIZE(b) <= FIVEARY_CUTOFF) {
|
i = Py_SIZE(b);
|
||||||
|
digit bi = i ? b->ob_digit[i-1] : 0;
|
||||||
|
digit bit;
|
||||||
|
if (i <= 1 && bi <= 3) {
|
||||||
|
/* aim for minimal overhead */
|
||||||
|
if (bi >= 2) {
|
||||||
|
MULT(a, a, z);
|
||||||
|
if (bi == 3) {
|
||||||
|
MULT(z, a, z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (bi == 1) {
|
||||||
|
/* Multiplying by 1 serves two purposes: if `a` is of an int
|
||||||
|
* subclass, makes the result an int (e.g., pow(False, 1) returns
|
||||||
|
* 0 instead of False), and potentially reduces `a` by the modulus.
|
||||||
|
*/
|
||||||
|
MULT(a, z, z);
|
||||||
|
}
|
||||||
|
/* else bi is 0, and z==1 is correct */
|
||||||
|
}
|
||||||
|
else if (i <= FIVEARY_CUTOFF) {
|
||||||
/* Left-to-right binary exponentiation (HAC Algorithm 14.79) */
|
/* Left-to-right binary exponentiation (HAC Algorithm 14.79) */
|
||||||
/* http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf */
|
/* http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf */
|
||||||
for (i = Py_SIZE(b) - 1; i >= 0; --i) {
|
|
||||||
digit bi = b->ob_digit[i];
|
|
||||||
|
|
||||||
for (j = (digit)1 << (PyLong_SHIFT-1); j != 0; j >>= 1) {
|
/* Find the first significant exponent bit. Search right to left
|
||||||
MULT(z, z, z);
|
* because we're primarily trying to cut overhead for small powers.
|
||||||
if (bi & j)
|
*/
|
||||||
MULT(z, a, z);
|
assert(bi); /* else there is no significant bit */
|
||||||
|
Py_INCREF(a);
|
||||||
|
Py_DECREF(z);
|
||||||
|
z = a;
|
||||||
|
for (bit = 2; ; bit <<= 1) {
|
||||||
|
if (bit > bi) { /* found the first bit */
|
||||||
|
assert((bi & bit) == 0);
|
||||||
|
bit >>= 1;
|
||||||
|
assert(bi & bit);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (--i, bit >>= 1;;) {
|
||||||
|
for (; bit != 0; bit >>= 1) {
|
||||||
|
MULT(z, z, z);
|
||||||
|
if (bi & bit) {
|
||||||
|
MULT(z, a, z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (--i < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bi = b->ob_digit[i];
|
||||||
|
bit = (digit)1 << (PyLong_SHIFT-1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* Left-to-right 5-ary exponentiation (HAC Algorithm 14.82) */
|
/* Left-to-right 5-ary exponentiation (HAC Algorithm 14.82) */
|
||||||
|
|
Loading…
Reference in New Issue