diff --git a/Objects/longobject.c b/Objects/longobject.c index 985b1ec83c6..6383507a5c6 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -3868,10 +3868,16 @@ long_pow(PyObject *v, PyObject *w, PyObject *x) goto Done; } - /* if base < 0: - base = base % modulus - Having the base positive just makes things easier. */ - if (Py_SIZE(a) < 0) { + /* Reduce base by modulus in some cases: + 1. If base < 0. Forcing the base non-negative makes things easier. + 2. If base is obviously larger than the modulus. The "small + exponent" case later can multiply directly by base repeatedly, + while the "large exponent" case multiplies directly by base 31 + times. It can be unboundedly faster to multiply by + base % modulus instead. + We could _always_ do this reduction, but l_divmod() isn't cheap, + so we only do it when it buys something. */ + if (Py_SIZE(a) < 0 || Py_SIZE(a) > Py_SIZE(c)) { if (l_divmod(a, c, NULL, &temp) < 0) goto Error; Py_DECREF(a);