Skip to content
Merged
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
4 changes: 3 additions & 1 deletion Lib/test/test_math.py
Original file line number Diff line number Diff line change
Expand Up @@ -1485,7 +1485,9 @@ def __rmul__(self, other):

# Error cases that arose during development
args = ((-5, -5, 10), (1.5, 4611686018427387904, 2305843009213693952))
self.assertEqual(sumprod(*args), 0.0)
self.assertEqual(sumprod(*args), -7.5)
self.assertEqual(sumprod([-0.01, 1, -1, 0.01], [1, 1, 1, 1]), 0.0)
self.assertEqual(sumprod([1, 1, 1, 1], [-0.01, 1, -1, 0.01], ), 0.0)

@requires_IEEE_754
@unittest.skipIf(HAVE_DOUBLE_ROUNDING,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fixed a missing case in :func:`math.sumprod` where a low precision path was
taken when an int/int input pair followed a float input.
29 changes: 14 additions & 15 deletions Modules/mathmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2937,32 +2937,31 @@ math_sumprod_impl(PyObject *module, PyObject *p, PyObject *q)

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. */

if (PyFloat_CheckExact(p_i)) {
flt_p = PyFloat_AS_DOUBLE(p_i);
flt_q = PyLong_AsDouble(q_i);
if (flt_q == -1.0 && PyErr_Occurred()) {
} else if (PyLong_CheckExact(p_i) || PyBool_Check(p_i)) {
flt_p = PyLong_AsDouble(p_i);
if (flt_p == -1.0 && PyErr_Occurred()) {
PyErr_Clear();
goto finalize_flt_path;
}
} else if (q_type_float && (PyLong_CheckExact(p_i) || PyBool_Check(p_i))) {
} else {
goto finalize_flt_path;
}

if (PyFloat_CheckExact(q_i)) {
flt_q = PyFloat_AS_DOUBLE(q_i);
flt_p = PyLong_AsDouble(p_i);
if (flt_p == -1.0 && PyErr_Occurred()) {
} else if (PyLong_CheckExact(q_i) || PyBool_Check(q_i)) {
flt_q = PyLong_AsDouble(q_i);
if (flt_q == -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;
Expand Down
Loading