@@ -2757,8 +2757,7 @@ and sums are computed with extended precision.
27572757[clinic start generated code]*/ 
27582758
27592759static  PyObject  * 
2760- math_sumprod_impl (PyObject  * module , PyObject  * p , PyObject  * q )
2761- /*[clinic end generated code: output=6722dbfe60664554 input=a2880317828c61d2]*/ 
2760+ math_sumprod_impl (PyObject  * module , PyObject  * p , PyObject  * q , PyObject  * start )
27622761{
27632762    PyObject  * p_i  =  NULL , * q_i  =  NULL , * term_i  =  NULL , * new_total  =  NULL ;
27642763    PyObject  * p_it , * q_it , * total ;
@@ -2778,44 +2777,34 @@ math_sumprod_impl(PyObject *module, PyObject *p, PyObject *q)
27782777        Py_DECREF (p_it );
27792778        return  NULL ;
27802779    }
2781-     total  =  PyLong_FromLong (0 );
2780+ 
2781+     // Use start instead of initializing with 0 
2782+     total  =  start  ? Py_NewRef (start ) : PyLong_FromLong (0 );
27822783    if  (total  ==  NULL ) {
27832784        Py_DECREF (p_it );
27842785        Py_DECREF (q_it );
27852786        return  NULL ;
27862787    }
2788+ 
27872789    p_next  =  * Py_TYPE (p_it )-> tp_iternext ;
27882790    q_next  =  * Py_TYPE (q_it )-> tp_iternext ;
27892791    while  (1 ) {
27902792        bool  finished ;
27912793
2792-         assert  (p_i  ==  NULL );
2793-         assert  (q_i  ==  NULL );
2794-         assert  (term_i  ==  NULL );
2795-         assert  (new_total  ==  NULL );
2796- 
2797-         assert  (p_it  !=  NULL );
2798-         assert  (q_it  !=  NULL );
2799-         assert  (total  !=  NULL );
2800- 
28012794        p_i  =  p_next (p_it );
28022795        if  (p_i  ==  NULL ) {
2803-             if  (PyErr_Occurred ()) {
2804-                 if  (!PyErr_ExceptionMatches (PyExc_StopIteration )) {
2805-                     goto err_exit ;
2806-                 }
2807-                 PyErr_Clear ();
2796+             if  (PyErr_Occurred () &&  !PyErr_ExceptionMatches (PyExc_StopIteration )) {
2797+                 goto err_exit ;
28082798            }
2799+             PyErr_Clear ();
28092800            p_stopped  =  true;
28102801        }
28112802        q_i  =  q_next (q_it );
28122803        if  (q_i  ==  NULL ) {
2813-             if  (PyErr_Occurred ()) {
2814-                 if  (!PyErr_ExceptionMatches (PyExc_StopIteration )) {
2815-                     goto err_exit ;
2816-                 }
2817-                 PyErr_Clear ();
2804+             if  (PyErr_Occurred () &&  !PyErr_ExceptionMatches (PyExc_StopIteration )) {
2805+                 goto err_exit ;
28182806            }
2807+             PyErr_Clear ();
28192808            q_stopped  =  true;
28202809        }
28212810        if  (p_stopped  !=  q_stopped ) {
@@ -2824,119 +2813,10 @@ math_sumprod_impl(PyObject *module, PyObject *p, PyObject *q)
28242813        }
28252814        finished  =  p_stopped  &  q_stopped ;
28262815
2827-         if  (int_path_enabled ) {
2828- 
2829-             if  (!finished  &&  PyLong_CheckExact (p_i ) &  PyLong_CheckExact (q_i )) {
2830-                 int  overflow ;
2831-                 long  int_p , int_q , int_prod ;
2832- 
2833-                 int_p  =  PyLong_AsLongAndOverflow (p_i , & overflow );
2834-                 if  (overflow ) {
2835-                     goto finalize_int_path ;
2836-                 }
2837-                 int_q  =  PyLong_AsLongAndOverflow (q_i , & overflow );
2838-                 if  (overflow ) {
2839-                     goto finalize_int_path ;
2840-                 }
2841-                 if  (_check_long_mult_overflow (int_p , int_q )) {
2842-                     goto finalize_int_path ;
2843-                 }
2844-                 int_prod  =  int_p  *  int_q ;
2845-                 if  (long_add_would_overflow (int_total , int_prod )) {
2846-                     goto finalize_int_path ;
2847-                 }
2848-                 int_total  +=  int_prod ;
2849-                 int_total_in_use  =  true;
2850-                 Py_CLEAR (p_i );
2851-                 Py_CLEAR (q_i );
2852-                 continue ;
2853-             }
2854- 
2855-           finalize_int_path :
2856-             // We're finished, overflowed, or have a non-int 
2857-             int_path_enabled  =  false;
2858-             if  (int_total_in_use ) {
2859-                 term_i  =  PyLong_FromLong (int_total );
2860-                 if  (term_i  ==  NULL ) {
2861-                     goto err_exit ;
2862-                 }
2863-                 new_total  =  PyNumber_Add (total , term_i );
2864-                 if  (new_total  ==  NULL ) {
2865-                     goto err_exit ;
2866-                 }
2867-                 Py_SETREF (total , new_total );
2868-                 new_total  =  NULL ;
2869-                 Py_CLEAR (term_i );
2870-                 int_total  =  0 ;   // An ounce of prevention, ... 
2871-                 int_total_in_use  =  false;
2872-             }
2873-         }
2874- 
2875-         if  (flt_path_enabled ) {
2876- 
2877-             if  (!finished ) {
2878-                 double  flt_p , flt_q ;
2879-                 bool  p_type_float  =  PyFloat_CheckExact (p_i );
2880-                 bool  q_type_float  =  PyFloat_CheckExact (q_i );
2881-                 if  (p_type_float  &&  q_type_float ) {
2882-                     flt_p  =  PyFloat_AS_DOUBLE (p_i );
2883-                     flt_q  =  PyFloat_AS_DOUBLE (q_i );
2884-                 } else  if  (p_type_float  &&  (PyLong_CheckExact (q_i ) ||  PyBool_Check (q_i ))) {
2885-                     /* We care about float/int pairs and int/float pairs because 
2886-                        they arise naturally in several use cases such as price 
2887-                        times quantity, measurements with integer weights, or 
2888-                        data selected by a vector of bools. */ 
2889-                     flt_p  =  PyFloat_AS_DOUBLE (p_i );
2890-                     flt_q  =  PyLong_AsDouble (q_i );
2891-                     if  (flt_q  ==  -1.0  &&  PyErr_Occurred ()) {
2892-                         PyErr_Clear ();
2893-                         goto finalize_flt_path ;
2894-                     }
2895-                 } else  if  (q_type_float  &&  (PyLong_CheckExact (p_i ) ||  PyBool_Check (p_i ))) {
2896-                     flt_q  =  PyFloat_AS_DOUBLE (q_i );
2897-                     flt_p  =  PyLong_AsDouble (p_i );
2898-                     if  (flt_p  ==  -1.0  &&  PyErr_Occurred ()) {
2899-                         PyErr_Clear ();
2900-                         goto finalize_flt_path ;
2901-                     }
2902-                 } else  {
2903-                     goto finalize_flt_path ;
2904-                 }
2905-                 TripleLength  new_flt_total  =  tl_fma (flt_p , flt_q , flt_total );
2906-                 if  (isfinite (new_flt_total .hi )) {
2907-                     flt_total  =  new_flt_total ;
2908-                     flt_total_in_use  =  true;
2909-                     Py_CLEAR (p_i );
2910-                     Py_CLEAR (q_i );
2911-                     continue ;
2912-                 }
2913-             }
2914- 
2915-           finalize_flt_path :
2916-             // We're finished, overflowed, have a non-float, or got a non-finite value 
2917-             flt_path_enabled  =  false;
2918-             if  (flt_total_in_use ) {
2919-                 term_i  =  PyFloat_FromDouble (tl_to_d (flt_total ));
2920-                 if  (term_i  ==  NULL ) {
2921-                     goto err_exit ;
2922-                 }
2923-                 new_total  =  PyNumber_Add (total , term_i );
2924-                 if  (new_total  ==  NULL ) {
2925-                     goto err_exit ;
2926-                 }
2927-                 Py_SETREF (total , new_total );
2928-                 new_total  =  NULL ;
2929-                 Py_CLEAR (term_i );
2930-                 flt_total  =  tl_zero ;
2931-                 flt_total_in_use  =  false;
2932-             }
2933-         }
2934- 
2935-         assert (!int_total_in_use );
2936-         assert (!flt_total_in_use );
29372816        if  (finished ) {
2938-             goto  normal_exit ;
2817+             break ;
29392818        }
2819+ 
29402820        term_i  =  PyNumber_Multiply (p_i , q_i );
29412821        if  (term_i  ==  NULL ) {
29422822            goto err_exit ;
@@ -2946,18 +2826,16 @@ math_sumprod_impl(PyObject *module, PyObject *p, PyObject *q)
29462826            goto err_exit ;
29472827        }
29482828        Py_SETREF (total , new_total );
2949-         new_total  =  NULL ;
29502829        Py_CLEAR (p_i );
29512830        Py_CLEAR (q_i );
29522831        Py_CLEAR (term_i );
29532832    }
29542833
2955-  normal_exit :
29562834    Py_DECREF (p_it );
29572835    Py_DECREF (q_it );
29582836    return  total ;
29592837
2960-   err_exit :
2838+ err_exit :
29612839    Py_DECREF (p_it );
29622840    Py_DECREF (q_it );
29632841    Py_DECREF (total );
@@ -2969,6 +2847,7 @@ math_sumprod_impl(PyObject *module, PyObject *p, PyObject *q)
29692847}
29702848
29712849
2850+ 
29722851/* pow can't use math_2, but needs its own wrapper: the problem is 
29732852   that an infinite result can arise either as a result of overflow 
29742853   (in which case OverflowError should be raised) or as a result of 
0 commit comments