Skip to content

Commit e69c39c

Browse files
gh-102221: Optimize math.lcm() for multiple arguments
1 parent 667a86e commit e69c39c

File tree

1 file changed

+37
-27
lines changed

1 file changed

+37
-27
lines changed

Modules/mathmodule.c

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,39 @@ long_lcm(PyObject *a, PyObject *b)
788788
return ab;
789789
}
790790

791+
static PyObject *
792+
long_array_lcm(PyObject * const *args, Py_ssize_t args_length)
793+
{
794+
if (args_length == 1) {
795+
return PyNumber_Index(args[0]);
796+
}
797+
798+
PyObject *left, *right;
799+
if (args_length == 2) {
800+
left = PyNumber_Index(args[0]);
801+
if (left == NULL) {
802+
return NULL;
803+
}
804+
right = PyNumber_Index(args[1]);
805+
}
806+
else {
807+
Py_ssize_t half = args_length / 2;
808+
left = long_array_lcm(args, half);
809+
if (left == NULL) {
810+
return NULL;
811+
}
812+
right = long_array_lcm(args + half, args_length - half);
813+
}
814+
if (right == NULL) {
815+
Py_DECREF(left);
816+
return NULL;
817+
}
818+
PyObject *res = long_lcm(left, right);
819+
Py_DECREF(left);
820+
Py_DECREF(right);
821+
return res;
822+
}
823+
791824

792825
/*[clinic input]
793826
math.lcm
@@ -802,41 +835,18 @@ math_lcm_impl(PyObject *module, PyObject * const *args,
802835
Py_ssize_t args_length)
803836
/*[clinic end generated code: output=c8a59a5c2e55c816 input=3e4f4b7cdf948a98]*/
804837
{
805-
PyObject *res, *x;
806-
Py_ssize_t i;
807-
808838
if (args_length == 0) {
809839
return PyLong_FromLong(1);
810840
}
811-
res = PyNumber_Index(args[0]);
812-
if (res == NULL) {
813-
return NULL;
814-
}
815841
if (args_length == 1) {
816-
Py_SETREF(res, PyNumber_Absolute(res));
817-
return res;
818-
}
819-
820-
PyObject *zero = _PyLong_GetZero(); // borrowed ref
821-
for (i = 1; i < args_length; i++) {
822-
x = PyNumber_Index(args[i]);
823-
if (x == NULL) {
824-
Py_DECREF(res);
825-
return NULL;
826-
}
827-
if (res == zero) {
828-
/* Fast path: just check arguments.
829-
It is okay to use identity comparison here. */
830-
Py_DECREF(x);
831-
continue;
832-
}
833-
Py_SETREF(res, long_lcm(res, x));
834-
Py_DECREF(x);
842+
PyObject *res = PyNumber_Index(args[0]);
835843
if (res == NULL) {
836844
return NULL;
837845
}
846+
Py_SETREF(res, PyNumber_Absolute(res));
847+
return res;
838848
}
839-
return res;
849+
return long_array_lcm(args, args_length);
840850
}
841851

842852

0 commit comments

Comments
 (0)