diff --git a/Misc/NEWS.d/next/Library/2023-10-29-15-35-57.gh-issue-102221.fQnOaT.rst b/Misc/NEWS.d/next/Library/2023-10-29-15-35-57.gh-issue-102221.fQnOaT.rst new file mode 100644 index 00000000000000..136a3e2bc4ca6c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-10-29-15-35-57.gh-issue-102221.fQnOaT.rst @@ -0,0 +1 @@ +Speed up :func:`math.lcm` for larger number of arguments. diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index bbbb49115681de..529050c62782a9 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -769,7 +769,15 @@ long_lcm(PyObject *a, PyObject *b) if (_PyLong_IsZero((PyLongObject *)a) || _PyLong_IsZero((PyLongObject *)b)) { return PyLong_FromLong(0); } - g = _PyLong_GCD(a, b); + + /* Make sure a_size <= b_size to speed up (a // g) * b; see gh-102221 for details. */ + if (_PyLong_DigitCount((PyLongObject *)b) < _PyLong_DigitCount((PyLongObject *)a)) { + g = a; + a = b; + b = g; + } + + g = _PyLong_GCD(b, a); if (g == NULL) { return NULL; } @@ -830,7 +838,7 @@ math_lcm_impl(PyObject *module, PyObject * const *args, Py_DECREF(x); continue; } - Py_SETREF(res, long_lcm(res, x)); + Py_SETREF(res, long_lcm(x, res)); Py_DECREF(x); if (res == NULL) { return NULL;