Skip to content

Commit 26d961e

Browse files
gh-102221: Optimize math.lcm() for multiple arguments
1 parent 654b8d9 commit 26d961e

File tree

1 file changed

+32
-26
lines changed

1 file changed

+32
-26
lines changed

Modules/mathmodule.c

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -802,41 +802,47 @@ math_lcm_impl(PyObject *module, PyObject * const *args,
802802
Py_ssize_t args_length)
803803
/*[clinic end generated code: output=c8a59a5c2e55c816 input=3e4f4b7cdf948a98]*/
804804
{
805-
PyObject *res, *x;
806-
Py_ssize_t i;
807-
808805
if (args_length == 0) {
809806
return PyLong_FromLong(1);
810807
}
811-
res = PyNumber_Index(args[0]);
812-
if (res == NULL) {
813-
return NULL;
808+
PyObject *res;
809+
PyObject *stack[8 * sizeof(Py_ssize_t)];
810+
int top = 0;
811+
Py_ssize_t i = 0;
812+
while (1) {
813+
size_t j = i;
814+
res = PyNumber_Index(args[i++]);
815+
if (res == NULL) {
816+
goto error;
817+
}
818+
if (i >= args_length) {
819+
j = ((size_t)1 << top) - 1;
820+
}
821+
while (j & 1) {
822+
j >>= 1;
823+
Py_SETREF(res, long_lcm(res, stack[top-1]));
824+
if (res == NULL) {
825+
goto error;
826+
}
827+
top--;
828+
Py_DECREF(stack[top]);
829+
}
830+
if (i >= args_length) {
831+
break;
832+
}
833+
stack[top++] = res;
814834
}
815835
if (args_length == 1) {
816836
Py_SETREF(res, PyNumber_Absolute(res));
817-
return res;
818837
}
838+
return res;
819839

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);
835-
if (res == NULL) {
836-
return NULL;
837-
}
840+
error:
841+
while (top > 0) {
842+
top--;
843+
Py_DECREF(stack[top]);
838844
}
839-
return res;
845+
return NULL;
840846
}
841847

842848

0 commit comments

Comments
 (0)