@@ -2937,31 +2937,32 @@ math_sumprod_impl(PyObject *module, PyObject *p, PyObject *q)
2937
2937
2938
2938
if (!finished ) {
2939
2939
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 ) {
2942
2943
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 ()) {
2946
2953
PyErr_Clear ();
2947
2954
goto finalize_flt_path ;
2948
2955
}
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 ))) {
2954
2957
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 ()) {
2958
2960
PyErr_Clear ();
2959
2961
goto finalize_flt_path ;
2960
2962
}
2961
2963
} else {
2962
2964
goto finalize_flt_path ;
2963
2965
}
2964
-
2965
2966
TripleLength new_flt_total = tl_fma (flt_p , flt_q , flt_total );
2966
2967
if (isfinite (new_flt_total .hi )) {
2967
2968
flt_total = new_flt_total ;
0 commit comments