@@ -3908,19 +3908,29 @@ math_nextafter_impl(PyObject *module, double x, double y, PyObject *steps)
3908
3908
return NULL ;
3909
3909
}
3910
3910
3911
- uint64_t usteps = PyLong_AsUnsignedLongLong (steps );
3911
+ unsigned long long usteps_ull = PyLong_AsUnsignedLongLong (steps );
3912
3912
// Conveniently, uint64_t and double have the same number of bits
3913
3913
// on all the platforms we care about.
3914
3914
// So if an overflow occurs, we can just use UINT64_MAX.
3915
- if (usteps == (unsigned long long )-1 && PyErr_Occurred ()) {
3916
- if (!PyErr_ExceptionMatches (PyExc_OverflowError )) {
3917
- Py_DECREF (steps );
3918
- return NULL ;
3915
+ Py_DECREF (steps );
3916
+ if (usteps_ull >= UINT64_MAX ) {
3917
+ // This branch includes the case where an error occurred, since
3918
+ // (unsigned long long)(-1) = ULLONG_MAX >= UINT64_MAX. Note that
3919
+ // usteps_ull can be strictly larger than UINT64_MAX on a machine
3920
+ // where unsigned long long has width > 64 bits.
3921
+ if (PyErr_Occurred ()) {
3922
+ if (PyErr_ExceptionMatches (PyExc_OverflowError )) {
3923
+ PyErr_Clear ();
3924
+ }
3925
+ else {
3926
+ return NULL ;
3927
+ }
3919
3928
}
3920
- PyErr_Clear ();
3921
- usteps = UINT64_MAX ;
3929
+ usteps_ull = UINT64_MAX ;
3922
3930
}
3923
- Py_DECREF (steps );
3931
+ assert (usteps_ull <= UINT64_MAX );
3932
+ uint64_t usteps = (uint64_t )usteps_ull ;
3933
+
3924
3934
if (usteps == 0 ) {
3925
3935
return PyFloat_FromDouble (x );
3926
3936
}
@@ -3937,7 +3947,7 @@ math_nextafter_impl(PyObject *module, double x, double y, PyObject *steps)
3937
3947
// would be a "mixed-endian" double.)
3938
3948
union pun {double f ; uint64_t i ;};
3939
3949
union pun ux = {x }, uy = {y };
3940
- if (ux .i == uy .i ) {
3950
+ if (ux .i == uy .i ) {
3941
3951
return PyFloat_FromDouble (x );
3942
3952
}
3943
3953
0 commit comments