@@ -76,6 +76,29 @@ static const double logpi = 1.144729885849400174143427351353058711647;
7676static const double sqrtpi = 1.772453850905516027298167483341145182798 ;
7777#endif /* !defined(HAVE_ERF) || !defined(HAVE_ERFC) */
7878
79+
80+ /* Version of PyFloat_AsDouble() with in-line fast paths
81+ for exact floats and integers. Gives a substantial
82+ speed improvement for extracting float arguments.
83+ */
84+
85+ #define ASSIGN_DOUBLE (target_var , obj , error_label ) \
86+ if (PyFloat_CheckExact(obj)) { \
87+ target_var = PyFloat_AS_DOUBLE(obj); \
88+ } \
89+ else if (PyLong_CheckExact(obj)) { \
90+ target_var = PyLong_AsDouble(obj); \
91+ if (target_var == -1.0 && PyErr_Occurred()) { \
92+ goto error_label; \
93+ } \
94+ } \
95+ else { \
96+ target_var = PyFloat_AsDouble(obj); \
97+ if (target_var == -1.0 && PyErr_Occurred()) { \
98+ goto error_label; \
99+ } \
100+ }
101+
79102static double
80103sinpi (double x )
81104{
@@ -1323,10 +1346,8 @@ math_fsum(PyObject *module, PyObject *seq)
13231346 goto _fsum_error ;
13241347 break ;
13251348 }
1326- x = PyFloat_AsDouble ( item );
1349+ ASSIGN_DOUBLE ( x , item , error_with_item );
13271350 Py_DECREF (item );
1328- if (PyErr_Occurred ())
1329- goto _fsum_error ;
13301351
13311352 xsave = x ;
13321353 for (i = j = 0 ; j < n ; j ++ ) { /* for y in partials */
@@ -1407,12 +1428,16 @@ math_fsum(PyObject *module, PyObject *seq)
14071428 }
14081429 sum = PyFloat_FromDouble (hi );
14091430
1410- _fsum_error :
1431+ _fsum_error :
14111432 PyFPE_END_PROTECT (hi )
14121433 Py_DECREF (iter );
14131434 if (p != ps )
14141435 PyMem_Free (p );
14151436 return sum ;
1437+
1438+ error_with_item :
1439+ Py_DECREF (item );
1440+ goto _fsum_error ;
14161441}
14171442
14181443#undef NUM_PARTIALS
@@ -2142,37 +2167,9 @@ math_dist_impl(PyObject *module, PyObject *p, PyObject *q)
21422167 }
21432168 for (i = 0 ; i < n ; i ++ ) {
21442169 item = PyTuple_GET_ITEM (p , i );
2145- if (PyFloat_CheckExact (item )) {
2146- px = PyFloat_AS_DOUBLE (item );
2147- }
2148- else if (PyLong_CheckExact (item )) {
2149- px = PyLong_AsDouble (item );
2150- if (px == -1.0 && PyErr_Occurred ()) {
2151- goto error_exit ;
2152- }
2153- }
2154- else {
2155- px = PyFloat_AsDouble (item );
2156- if (px == -1.0 && PyErr_Occurred ()) {
2157- goto error_exit ;
2158- }
2159- }
2170+ ASSIGN_DOUBLE (px , item , error_exit );
21602171 item = PyTuple_GET_ITEM (q , i );
2161- if (PyFloat_CheckExact (item )) {
2162- qx = PyFloat_AS_DOUBLE (item );
2163- }
2164- else if (PyLong_CheckExact (item )) {
2165- qx = PyLong_AsDouble (item );
2166- if (qx == -1.0 && PyErr_Occurred ()) {
2167- goto error_exit ;
2168- }
2169- }
2170- else {
2171- qx = PyFloat_AsDouble (item );
2172- if (qx == -1.0 && PyErr_Occurred ()) {
2173- goto error_exit ;
2174- }
2175- }
2172+ ASSIGN_DOUBLE (qx , item , error_exit );
21762173 x = fabs (px - qx );
21772174 diffs [i ] = x ;
21782175 found_nan |= Py_IS_NAN (x );
@@ -2213,21 +2210,7 @@ math_hypot(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
22132210 }
22142211 for (i = 0 ; i < nargs ; i ++ ) {
22152212 item = args [i ];
2216- if (PyFloat_CheckExact (item )) {
2217- x = PyFloat_AS_DOUBLE (item );
2218- }
2219- else if (PyLong_CheckExact (item )) {
2220- x = PyLong_AsDouble (item );
2221- if (x == -1.0 && PyErr_Occurred ()) {
2222- goto error_exit ;
2223- }
2224- }
2225- else {
2226- x = PyFloat_AsDouble (item );
2227- if (x == -1.0 && PyErr_Occurred ()) {
2228- goto error_exit ;
2229- }
2230- }
2213+ ASSIGN_DOUBLE (x , item , error_exit );
22312214 x = fabs (x );
22322215 coordinates [i ] = x ;
22332216 found_nan |= Py_IS_NAN (x );
0 commit comments