@@ -76,6 +76,29 @@ static const double logpi = 1.144729885849400174143427351353058711647;
76
76
static const double sqrtpi = 1.772453850905516027298167483341145182798 ;
77
77
#endif /* !defined(HAVE_ERF) || !defined(HAVE_ERFC) */
78
78
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
+
79
102
static double
80
103
sinpi (double x )
81
104
{
@@ -1323,10 +1346,8 @@ math_fsum(PyObject *module, PyObject *seq)
1323
1346
goto _fsum_error ;
1324
1347
break ;
1325
1348
}
1326
- x = PyFloat_AsDouble ( item );
1349
+ ASSIGN_DOUBLE ( x , item , error_with_item );
1327
1350
Py_DECREF (item );
1328
- if (PyErr_Occurred ())
1329
- goto _fsum_error ;
1330
1351
1331
1352
xsave = x ;
1332
1353
for (i = j = 0 ; j < n ; j ++ ) { /* for y in partials */
@@ -1407,12 +1428,16 @@ math_fsum(PyObject *module, PyObject *seq)
1407
1428
}
1408
1429
sum = PyFloat_FromDouble (hi );
1409
1430
1410
- _fsum_error :
1431
+ _fsum_error :
1411
1432
PyFPE_END_PROTECT (hi )
1412
1433
Py_DECREF (iter );
1413
1434
if (p != ps )
1414
1435
PyMem_Free (p );
1415
1436
return sum ;
1437
+
1438
+ error_with_item :
1439
+ Py_DECREF (item );
1440
+ goto _fsum_error ;
1416
1441
}
1417
1442
1418
1443
#undef NUM_PARTIALS
@@ -2142,37 +2167,9 @@ math_dist_impl(PyObject *module, PyObject *p, PyObject *q)
2142
2167
}
2143
2168
for (i = 0 ; i < n ; i ++ ) {
2144
2169
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 );
2160
2171
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 );
2176
2173
x = fabs (px - qx );
2177
2174
diffs [i ] = x ;
2178
2175
found_nan |= Py_IS_NAN (x );
@@ -2213,21 +2210,7 @@ math_hypot(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
2213
2210
}
2214
2211
for (i = 0 ; i < nargs ; i ++ ) {
2215
2212
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 );
2231
2214
x = fabs (x );
2232
2215
coordinates [i ] = x ;
2233
2216
found_nan |= Py_IS_NAN (x );
0 commit comments