Skip to content

Commit b485e50

Browse files
authored
gh-139074: Fix missing high precision case in sumprod() (gh-139075)
1 parent 5a15e73 commit b485e50

File tree

3 files changed

+19
-16
lines changed

3 files changed

+19
-16
lines changed

Lib/test/test_math.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1485,7 +1485,9 @@ def __rmul__(self, other):
14851485

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

14901492
@requires_IEEE_754
14911493
@unittest.skipIf(HAVE_DOUBLE_ROUNDING,
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fixed a missing case in :func:`math.sumprod` where a low precision path was
2+
taken when an int/int input pair followed a float input.

Modules/mathmodule.c

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2937,32 +2937,31 @@ math_sumprod_impl(PyObject *module, PyObject *p, PyObject *q)
29372937

29382938
if (!finished) {
29392939
double flt_p, flt_q;
2940-
bool p_type_float = PyFloat_CheckExact(p_i);
2941-
bool q_type_float = PyFloat_CheckExact(q_i);
2942-
if (p_type_float && q_type_float) {
2943-
flt_p = PyFloat_AS_DOUBLE(p_i);
2944-
flt_q = PyFloat_AS_DOUBLE(q_i);
2945-
} else if (p_type_float && (PyLong_CheckExact(q_i) || PyBool_Check(q_i))) {
2946-
/* We care about float/int pairs and int/float pairs because
2947-
they arise naturally in several use cases such as price
2948-
times quantity, measurements with integer weights, or
2949-
data selected by a vector of bools. */
2940+
2941+
if (PyFloat_CheckExact(p_i)) {
29502942
flt_p = PyFloat_AS_DOUBLE(p_i);
2951-
flt_q = PyLong_AsDouble(q_i);
2952-
if (flt_q == -1.0 && PyErr_Occurred()) {
2943+
} else if (PyLong_CheckExact(p_i) || PyBool_Check(p_i)) {
2944+
flt_p = PyLong_AsDouble(p_i);
2945+
if (flt_p == -1.0 && PyErr_Occurred()) {
29532946
PyErr_Clear();
29542947
goto finalize_flt_path;
29552948
}
2956-
} else if (q_type_float && (PyLong_CheckExact(p_i) || PyBool_Check(p_i))) {
2949+
} else {
2950+
goto finalize_flt_path;
2951+
}
2952+
2953+
if (PyFloat_CheckExact(q_i)) {
29572954
flt_q = PyFloat_AS_DOUBLE(q_i);
2958-
flt_p = PyLong_AsDouble(p_i);
2959-
if (flt_p == -1.0 && PyErr_Occurred()) {
2955+
} else if (PyLong_CheckExact(q_i) || PyBool_Check(q_i)) {
2956+
flt_q = PyLong_AsDouble(q_i);
2957+
if (flt_q == -1.0 && PyErr_Occurred()) {
29602958
PyErr_Clear();
29612959
goto finalize_flt_path;
29622960
}
29632961
} else {
29642962
goto finalize_flt_path;
29652963
}
2964+
29662965
TripleLength new_flt_total = tl_fma(flt_p, flt_q, flt_total);
29672966
if (isfinite(new_flt_total.hi)) {
29682967
flt_total = new_flt_total;

0 commit comments

Comments
 (0)