@@ -2937,31 +2937,32 @@ math_sumprod_impl(PyObject *module, PyObject *p, PyObject *q)
29372937
29382938 if (!finished ) {
29392939 double flt_p , flt_q ;
2940-
2941- if (PyFloat_CheckExact (p_i )) {
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 ) {
29422943 flt_p = PyFloat_AS_DOUBLE (p_i );
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 ()) {
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. */
2950+ flt_p = PyFloat_AS_DOUBLE (p_i );
2951+ flt_q = PyLong_AsDouble (q_i );
2952+ if (flt_q == -1.0 && PyErr_Occurred ()) {
29462953 PyErr_Clear ();
29472954 goto finalize_flt_path ;
29482955 }
2949- } else {
2950- goto finalize_flt_path ;
2951- }
2952-
2953- if (PyFloat_CheckExact (q_i )) {
2956+ } else if (q_type_float && (PyLong_CheckExact (p_i ) || PyBool_Check (p_i ))) {
29542957 flt_q = PyFloat_AS_DOUBLE (q_i );
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 ()) {
2958+ flt_p = PyLong_AsDouble (p_i );
2959+ if (flt_p == -1.0 && PyErr_Occurred ()) {
29582960 PyErr_Clear ();
29592961 goto finalize_flt_path ;
29602962 }
29612963 } else {
29622964 goto finalize_flt_path ;
29632965 }
2964-
29652966 TripleLength new_flt_total = tl_fma (flt_p , flt_q , flt_total );
29662967 if (isfinite (new_flt_total .hi )) {
29672968 flt_total = new_flt_total ;
0 commit comments