bpo-37986: Improve perfomance of PyLong_FromDouble() (GH-15611)

* bpo-37986: Improve perfomance of PyLong_FromDouble()

* Use strict bound check for safety and symmetry

* Remove possibly outdated performance claims

Co-authored-by: Mark Dickinson <dickinsm@gmail.com>
This commit is contained in:
Sergey Fedoseev 2020-05-10 14:15:57 +05:00 committed by GitHub
parent 1c2fa78156
commit 86a93fddf7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 19 additions and 23 deletions

View file

@ -862,27 +862,7 @@ static PyObject *
float___trunc___impl(PyObject *self)
/*[clinic end generated code: output=dd3e289dd4c6b538 input=591b9ba0d650fdff]*/
{
double x = PyFloat_AsDouble(self);
double wholepart; /* integral portion of x, rounded toward 0 */
(void)modf(x, &wholepart);
/* Try to get out cheap if this fits in a Python int. The attempt
* to cast to long must be protected, as C doesn't define what
* happens if the double is too big to fit in a long. Some rare
* systems raise an exception then (RISCOS was mentioned as one,
* and someone using a non-default option on Sun also bumped into
* that). Note that checking for >= and <= LONG_{MIN,MAX} would
* still be vulnerable: if a long has more bits of precision than
* a double, casting MIN/MAX to double may yield an approximation,
* and if that's rounded up, then, e.g., wholepart=LONG_MAX+1 would
* yield true from the C expression wholepart<=LONG_MAX, despite
* that wholepart is actually greater than LONG_MAX.
*/
if (LONG_MIN < wholepart && wholepart < LONG_MAX) {
const long aslong = (long)wholepart;
return PyLong_FromLong(aslong);
}
return PyLong_FromDouble(wholepart);
return PyLong_FromDouble(PyFloat_AS_DOUBLE(self));
}
/*[clinic input]