gh-111139: Optimize math.gcd(int, int) (#113887)

Add a fast-path for the common case.

Benchmark:

    python -m pyperf timeit \
        -s 'import math; gcd=math.gcd; x=2*3; y=3*5' \
        'gcd(x,y)'

Result: 1.07x faster (-3.4 ns)

    Mean +- std dev: 52.6 ns +- 4.0 ns -> 49.2 ns +- 0.4 ns: 1.07x faster
This commit is contained in:
Victor Stinner 2024-01-10 16:38:56 +01:00 committed by GitHub
parent 66363b9a7b
commit 93930eaf0a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -759,13 +759,17 @@ m_log10(double x)
static PyObject *
math_gcd(PyObject *module, PyObject * const *args, Py_ssize_t nargs)
{
PyObject *res, *x;
Py_ssize_t i;
// Fast-path for the common case: gcd(int, int)
if (nargs == 2 && PyLong_CheckExact(args[0]) && PyLong_CheckExact(args[1]))
{
return _PyLong_GCD(args[0], args[1]);
}
if (nargs == 0) {
return PyLong_FromLong(0);
}
res = PyNumber_Index(args[0]);
PyObject *res = PyNumber_Index(args[0]);
if (res == NULL) {
return NULL;
}
@ -775,8 +779,8 @@ math_gcd(PyObject *module, PyObject * const *args, Py_ssize_t nargs)
}
PyObject *one = _PyLong_GetOne(); // borrowed ref
for (i = 1; i < nargs; i++) {
x = _PyNumber_Index(args[i]);
for (Py_ssize_t i = 1; i < nargs; i++) {
PyObject *x = _PyNumber_Index(args[i]);
if (x == NULL) {
Py_DECREF(res);
return NULL;