Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions Modules/clinic/mathmodule.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

151 changes: 15 additions & 136 deletions Modules/mathmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@
static const TripleLength tl_zero = {0.0, 0.0, 0.0};

static TripleLength
tl_fma(double x, double y, TripleLength total)

Check warning on line 184 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Ubuntu (free-threading) / build and test (ubuntu-24.04)

‘tl_fma’ defined but not used [-Wunused-function]

Check warning on line 184 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Hypothesis tests on Ubuntu

‘tl_fma’ defined but not used [-Wunused-function]

Check warning on line 184 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Cross build Linux

‘tl_fma’ defined but not used [-Wunused-function]

Check warning on line 184 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Address sanitizer (ubuntu-24.04)

‘tl_fma’ defined but not used [-Wunused-function]
{
/* Algorithm 5.10 with SumKVert for K=3 */
DoubleLength pr = dl_mul(x, y);
Expand All @@ -192,7 +192,7 @@
}

static double
tl_to_d(TripleLength total)

Check warning on line 195 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Ubuntu (free-threading) / build and test (ubuntu-24.04)

‘tl_to_d’ defined but not used [-Wunused-function]

Check warning on line 195 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Hypothesis tests on Ubuntu

‘tl_to_d’ defined but not used [-Wunused-function]

Check warning on line 195 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Cross build Linux

‘tl_to_d’ defined but not used [-Wunused-function]

Check warning on line 195 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Address sanitizer (ubuntu-24.04)

‘tl_to_d’ defined but not used [-Wunused-function]
{
DoubleLength last = dl_sum(total.lo, total.hi);
return total.tiny + last.lo + last.hi;
Expand Down Expand Up @@ -2757,17 +2757,16 @@
[clinic start generated code]*/

static PyObject *
math_sumprod_impl(PyObject *module, PyObject *p, PyObject *q)
/*[clinic end generated code: output=6722dbfe60664554 input=a2880317828c61d2]*/
math_sumprod_impl(PyObject *module, PyObject *p, PyObject *q, PyObject *start)

Check failure on line 2760 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Ubuntu (free-threading) / build and test (ubuntu-24.04)

conflicting types for ‘math_sumprod_impl’; have ‘PyObject *(PyObject *, PyObject *, PyObject *, PyObject *)’ {aka ‘struct _object *(struct _object *, struct _object *, struct _object *, struct _object *)’}

Check warning on line 2760 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Ubuntu (free-threading) / build and test (ubuntu-24.04)

‘math_sumprod_impl’ defined but not used [-Wunused-function]

Check failure on line 2760 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Hypothesis tests on Ubuntu

conflicting types for ‘math_sumprod_impl’; have ‘PyObject *(PyObject *, PyObject *, PyObject *, PyObject *)’ {aka ‘struct _object *(struct _object *, struct _object *, struct _object *, struct _object *)’}

Check warning on line 2760 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Hypothesis tests on Ubuntu

‘math_sumprod_impl’ defined but not used [-Wunused-function]

Check failure on line 2760 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Windows / build and test (x64)

'math_sumprod_impl': 'PyObject *(PyObject *,PyObject *,PyObject *,PyObject *)' differs in levels of indirection from 'int ()' [D:\a\cpython\cpython\PCbuild\pythoncore.vcxproj]

Check failure on line 2760 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Cross build Linux

conflicting types for ‘math_sumprod_impl’; have ‘PyObject *(PyObject *, PyObject *, PyObject *, PyObject *)’ {aka ‘struct _object *(struct _object *, struct _object *, struct _object *, struct _object *)’}

Check warning on line 2760 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Cross build Linux

‘math_sumprod_impl’ defined but not used [-Wunused-function]

Check failure on line 2760 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Address sanitizer (ubuntu-24.04)

conflicting types for ‘math_sumprod_impl’

Check warning on line 2760 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Address sanitizer (ubuntu-24.04)

‘math_sumprod_impl’ defined but not used [-Wunused-function]

Check failure on line 2760 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Windows (free-threading) / build (arm64)

'math_sumprod_impl': 'PyObject *(PyObject *,PyObject *,PyObject *,PyObject *)' differs in levels of indirection from 'int ()' [D:\a\cpython\cpython\PCbuild\pythoncore.vcxproj]

Check failure on line 2760 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Windows / build (arm64)

'math_sumprod_impl': 'PyObject *(PyObject *,PyObject *,PyObject *,PyObject *)' differs in levels of indirection from 'int ()' [D:\a\cpython\cpython\PCbuild\pythoncore.vcxproj]

Check failure on line 2760 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Windows (free-threading) / build and test (x64)

'math_sumprod_impl': 'PyObject *(PyObject *,PyObject *,PyObject *,PyObject *)' differs in levels of indirection from 'int ()' [D:\a\cpython\cpython\PCbuild\pythoncore.vcxproj]
{
PyObject *p_i = NULL, *q_i = NULL, *term_i = NULL, *new_total = NULL;
PyObject *p_it, *q_it, *total;
iternextfunc p_next, q_next;
bool p_stopped = false, q_stopped = false;
bool int_path_enabled = true, int_total_in_use = false;

Check warning on line 2766 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Ubuntu (free-threading) / build and test (ubuntu-24.04)

unused variable ‘int_total_in_use’ [-Wunused-variable]

Check warning on line 2766 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Ubuntu (free-threading) / build and test (ubuntu-24.04)

unused variable ‘int_path_enabled’ [-Wunused-variable]

Check warning on line 2766 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Hypothesis tests on Ubuntu

unused variable ‘int_total_in_use’ [-Wunused-variable]

Check warning on line 2766 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Hypothesis tests on Ubuntu

unused variable ‘int_path_enabled’ [-Wunused-variable]

Check warning on line 2766 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Cross build Linux

unused variable ‘int_total_in_use’ [-Wunused-variable]

Check warning on line 2766 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Cross build Linux

unused variable ‘int_path_enabled’ [-Wunused-variable]

Check warning on line 2766 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Address sanitizer (ubuntu-24.04)

unused variable ‘int_total_in_use’ [-Wunused-variable]

Check warning on line 2766 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Address sanitizer (ubuntu-24.04)

unused variable ‘int_path_enabled’ [-Wunused-variable]
bool flt_path_enabled = true, flt_total_in_use = false;

Check warning on line 2767 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Ubuntu (free-threading) / build and test (ubuntu-24.04)

unused variable ‘flt_total_in_use’ [-Wunused-variable]

Check warning on line 2767 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Ubuntu (free-threading) / build and test (ubuntu-24.04)

unused variable ‘flt_path_enabled’ [-Wunused-variable]

Check warning on line 2767 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Hypothesis tests on Ubuntu

unused variable ‘flt_total_in_use’ [-Wunused-variable]

Check warning on line 2767 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Hypothesis tests on Ubuntu

unused variable ‘flt_path_enabled’ [-Wunused-variable]

Check warning on line 2767 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Cross build Linux

unused variable ‘flt_total_in_use’ [-Wunused-variable]

Check warning on line 2767 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Cross build Linux

unused variable ‘flt_path_enabled’ [-Wunused-variable]

Check warning on line 2767 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Address sanitizer (ubuntu-24.04)

unused variable ‘flt_total_in_use’ [-Wunused-variable]

Check warning on line 2767 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Address sanitizer (ubuntu-24.04)

unused variable ‘flt_path_enabled’ [-Wunused-variable]
long int_total = 0;

Check warning on line 2768 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Ubuntu (free-threading) / build and test (ubuntu-24.04)

unused variable ‘int_total’ [-Wunused-variable]

Check warning on line 2768 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Hypothesis tests on Ubuntu

unused variable ‘int_total’ [-Wunused-variable]

Check warning on line 2768 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Cross build Linux

unused variable ‘int_total’ [-Wunused-variable]

Check warning on line 2768 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Address sanitizer (ubuntu-24.04)

unused variable ‘int_total’ [-Wunused-variable]
TripleLength flt_total = tl_zero;

Check warning on line 2769 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Ubuntu (free-threading) / build and test (ubuntu-24.04)

unused variable ‘flt_total’ [-Wunused-variable]

Check warning on line 2769 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Hypothesis tests on Ubuntu

unused variable ‘flt_total’ [-Wunused-variable]

Check warning on line 2769 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Cross build Linux

unused variable ‘flt_total’ [-Wunused-variable]

Check warning on line 2769 in Modules/mathmodule.c

View workflow job for this annotation

GitHub Actions / Address sanitizer (ubuntu-24.04)

unused variable ‘flt_total’ [-Wunused-variable]

p_it = PyObject_GetIter(p);
if (p_it == NULL) {
Expand All @@ -2778,44 +2777,34 @@
Py_DECREF(p_it);
return NULL;
}
total = PyLong_FromLong(0);

// Use start instead of initializing with 0
total = start ? Py_NewRef(start) : PyLong_FromLong(0);
if (total == NULL) {
Py_DECREF(p_it);
Py_DECREF(q_it);
return NULL;
}

p_next = *Py_TYPE(p_it)->tp_iternext;
q_next = *Py_TYPE(q_it)->tp_iternext;
while (1) {
bool finished;

assert (p_i == NULL);
assert (q_i == NULL);
assert (term_i == NULL);
assert (new_total == NULL);

assert (p_it != NULL);
assert (q_it != NULL);
assert (total != NULL);

p_i = p_next(p_it);
if (p_i == NULL) {
if (PyErr_Occurred()) {
if (!PyErr_ExceptionMatches(PyExc_StopIteration)) {
goto err_exit;
}
PyErr_Clear();
if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_StopIteration)) {
goto err_exit;
}
PyErr_Clear();
p_stopped = true;
}
q_i = q_next(q_it);
if (q_i == NULL) {
if (PyErr_Occurred()) {
if (!PyErr_ExceptionMatches(PyExc_StopIteration)) {
goto err_exit;
}
PyErr_Clear();
if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_StopIteration)) {
goto err_exit;
}
PyErr_Clear();
q_stopped = true;
}
if (p_stopped != q_stopped) {
Expand All @@ -2824,119 +2813,10 @@
}
finished = p_stopped & q_stopped;

if (int_path_enabled) {

if (!finished && PyLong_CheckExact(p_i) & PyLong_CheckExact(q_i)) {
int overflow;
long int_p, int_q, int_prod;

int_p = PyLong_AsLongAndOverflow(p_i, &overflow);
if (overflow) {
goto finalize_int_path;
}
int_q = PyLong_AsLongAndOverflow(q_i, &overflow);
if (overflow) {
goto finalize_int_path;
}
if (_check_long_mult_overflow(int_p, int_q)) {
goto finalize_int_path;
}
int_prod = int_p * int_q;
if (long_add_would_overflow(int_total, int_prod)) {
goto finalize_int_path;
}
int_total += int_prod;
int_total_in_use = true;
Py_CLEAR(p_i);
Py_CLEAR(q_i);
continue;
}

finalize_int_path:
// We're finished, overflowed, or have a non-int
int_path_enabled = false;
if (int_total_in_use) {
term_i = PyLong_FromLong(int_total);
if (term_i == NULL) {
goto err_exit;
}
new_total = PyNumber_Add(total, term_i);
if (new_total == NULL) {
goto err_exit;
}
Py_SETREF(total, new_total);
new_total = NULL;
Py_CLEAR(term_i);
int_total = 0; // An ounce of prevention, ...
int_total_in_use = false;
}
}

if (flt_path_enabled) {

if (!finished) {
double flt_p, flt_q;
bool p_type_float = PyFloat_CheckExact(p_i);
bool q_type_float = PyFloat_CheckExact(q_i);
if (p_type_float && q_type_float) {
flt_p = PyFloat_AS_DOUBLE(p_i);
flt_q = PyFloat_AS_DOUBLE(q_i);
} else if (p_type_float && (PyLong_CheckExact(q_i) || PyBool_Check(q_i))) {
/* We care about float/int pairs and int/float pairs because
they arise naturally in several use cases such as price
times quantity, measurements with integer weights, or
data selected by a vector of bools. */
flt_p = PyFloat_AS_DOUBLE(p_i);
flt_q = PyLong_AsDouble(q_i);
if (flt_q == -1.0 && PyErr_Occurred()) {
PyErr_Clear();
goto finalize_flt_path;
}
} else if (q_type_float && (PyLong_CheckExact(p_i) || PyBool_Check(p_i))) {
flt_q = PyFloat_AS_DOUBLE(q_i);
flt_p = PyLong_AsDouble(p_i);
if (flt_p == -1.0 && PyErr_Occurred()) {
PyErr_Clear();
goto finalize_flt_path;
}
} else {
goto finalize_flt_path;
}
TripleLength new_flt_total = tl_fma(flt_p, flt_q, flt_total);
if (isfinite(new_flt_total.hi)) {
flt_total = new_flt_total;
flt_total_in_use = true;
Py_CLEAR(p_i);
Py_CLEAR(q_i);
continue;
}
}

finalize_flt_path:
// We're finished, overflowed, have a non-float, or got a non-finite value
flt_path_enabled = false;
if (flt_total_in_use) {
term_i = PyFloat_FromDouble(tl_to_d(flt_total));
if (term_i == NULL) {
goto err_exit;
}
new_total = PyNumber_Add(total, term_i);
if (new_total == NULL) {
goto err_exit;
}
Py_SETREF(total, new_total);
new_total = NULL;
Py_CLEAR(term_i);
flt_total = tl_zero;
flt_total_in_use = false;
}
}

assert(!int_total_in_use);
assert(!flt_total_in_use);
if (finished) {
goto normal_exit;
break;
}

term_i = PyNumber_Multiply(p_i, q_i);
if (term_i == NULL) {
goto err_exit;
Expand All @@ -2946,18 +2826,16 @@
goto err_exit;
}
Py_SETREF(total, new_total);
new_total = NULL;
Py_CLEAR(p_i);
Py_CLEAR(q_i);
Py_CLEAR(term_i);
}

normal_exit:
Py_DECREF(p_it);
Py_DECREF(q_it);
return total;

err_exit:
err_exit:
Py_DECREF(p_it);
Py_DECREF(q_it);
Py_DECREF(total);
Expand All @@ -2969,6 +2847,7 @@
}



/* pow can't use math_2, but needs its own wrapper: the problem is
that an infinite result can arise either as a result of overflow
(in which case OverflowError should be raised) or as a result of
Expand Down
Loading