The python grammar definition (from which the parser is generated using pgen), look for 'power': Gramar/Gramar
The python ast, look for 'ast_for_power': Python/ast.c
The python eval loop, look for 'BINARY_POWER': Python/ceval.c
Which calls PyNumber_Power (implemented in Objects/abstract.c):
PyObject *
PyNumber_Power(PyObject *v, PyObject *w, PyObject *z)
{
return ternary_op(v, w, z, NB_SLOT(nb_power), "** or pow()");
}
Essentially, invoke the pow slot. For long objects (the only default integer type in 3.0) this is implemented in the long_pow function Objects/longobject.c, for int objects (in the 2.x branches) it is implemented in the int_pow function Object/intobject.c
If you dig into long_pow, you can see that after vetting the arguments and doing a bit of set up, the heart of the exponentiation can be see here:
if (Py_SIZE(b) <= FIVEARY_CUTOFF) {
/* Left-to-right binary exponentiation (HAC Algorithm 14.79) */
/* 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 = 1 << (PyLong_SHIFT-1); j != 0; j >>= 1) {
MULT(z, z, z)
if (bi & j)
MULT(z, a, z)
}
}
}
else {
/* Left-to-right 5-ary exponentiation (HAC Algorithm 14.82) */
Py_INCREF(z); /* still holds 1L */
table[0] = z;
for (i = 1; i < 32; ++i)
MULT(table[i-1], a, table[i])
for (i = Py_SIZE(b) - 1; i >= 0; --i) {
const digit bi = b->ob_digit[i];
for (j = PyLong_SHIFT - 5; j >= 0; j -= 5) {
const int index = (bi >> j) & 0x1f;
for (k = 0; k < 5; ++k)
MULT(z, z, z)
if (index)
MULT(z, table[index], z)
}
}
}
Which uses algorithms discussed in Chapter 14.6 of the Handbook of Applied Cryptography which describes efficient exponentiation algorithms for arbitrary precision arithmetic.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…