summaryrefslogtreecommitdiffstats
path: root/Objects/floatobject.c
diff options
context:
space:
mode:
authorDong-hee Na <donghee.na92@gmail.com>2020-01-30 13:23:15 (GMT)
committerGitHub <noreply@github.com>2020-01-30 13:23:15 (GMT)
commit8d49f7ceb4f961770ae61fe6a4033c4e61cc3288 (patch)
treebf3e0f674c1d714ebe98486bad2a46ecaeeffe0e /Objects/floatobject.c
parent2a4903fcce54c25807d362dbbbcfb32d0b494f9f (diff)
downloadcpython-8d49f7ceb4f961770ae61fe6a4033c4e61cc3288.zip
cpython-8d49f7ceb4f961770ae61fe6a4033c4e61cc3288.tar.gz
cpython-8d49f7ceb4f961770ae61fe6a4033c4e61cc3288.tar.bz2
bpo-39434: Improve float __floordiv__ performance and error message (GH-18147)
Diffstat (limited to 'Objects/floatobject.c')
-rw-r--r--Objects/floatobject.c70
1 files changed, 39 insertions, 31 deletions
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index d67f17a..89f60b6 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -611,29 +611,22 @@ float_rem(PyObject *v, PyObject *w)
return PyFloat_FromDouble(mod);
}
-static PyObject *
-float_divmod(PyObject *v, PyObject *w)
+static void
+_float_div_mod(double vx, double wx, double *floordiv, double *mod)
{
- double vx, wx;
- double div, mod, floordiv;
- CONVERT_TO_DOUBLE(v, vx);
- CONVERT_TO_DOUBLE(w, wx);
- if (wx == 0.0) {
- PyErr_SetString(PyExc_ZeroDivisionError, "float divmod()");
- return NULL;
- }
- mod = fmod(vx, wx);
+ double div;
+ *mod = fmod(vx, wx);
/* fmod is typically exact, so vx-mod is *mathematically* an
exact multiple of wx. But this is fp arithmetic, and fp
vx - mod is an approximation; the result is that div may
not be an exact integral value after the division, although
it will always be very close to one.
*/
- div = (vx - mod) / wx;
- if (mod) {
+ div = (vx - *mod) / wx;
+ if (*mod) {
/* ensure the remainder has the same sign as the denominator */
- if ((wx < 0) != (mod < 0)) {
- mod += wx;
+ if ((wx < 0) != (*mod < 0)) {
+ *mod += wx;
div -= 1.0;
}
}
@@ -641,34 +634,49 @@ float_divmod(PyObject *v, PyObject *w)
/* the remainder is zero, and in the presence of signed zeroes
fmod returns different results across platforms; ensure
it has the same sign as the denominator. */
- mod = copysign(0.0, wx);
+ *mod = copysign(0.0, wx);
}
/* snap quotient to nearest integral value */
if (div) {
- floordiv = floor(div);
- if (div - floordiv > 0.5)
- floordiv += 1.0;
+ *floordiv = floor(div);
+ if (div - *floordiv > 0.5) {
+ *floordiv += 1.0;
+ }
}
else {
/* div is zero - get the same sign as the true quotient */
- floordiv = copysign(0.0, vx / wx); /* zero w/ sign of vx/wx */
+ *floordiv = copysign(0.0, vx / wx); /* zero w/ sign of vx/wx */
}
- return Py_BuildValue("(dd)", floordiv, mod);
+}
+
+static PyObject *
+float_divmod(PyObject *v, PyObject *w)
+{
+ double vx, wx;
+ double mod, floordiv;
+ CONVERT_TO_DOUBLE(v, vx);
+ CONVERT_TO_DOUBLE(w, wx);
+ if (wx == 0.0) {
+ PyErr_SetString(PyExc_ZeroDivisionError, "float divmod()");
+ return NULL;
+ }
+ _float_div_mod(vx, wx, &floordiv, &mod);
+ return Py_BuildValue("(dd)", floordiv, mod);
}
static PyObject *
float_floor_div(PyObject *v, PyObject *w)
{
- PyObject *t, *r;
-
- t = float_divmod(v, w);
- if (t == NULL || t == Py_NotImplemented)
- return t;
- assert(PyTuple_CheckExact(t));
- r = PyTuple_GET_ITEM(t, 0);
- Py_INCREF(r);
- Py_DECREF(t);
- return r;
+ double vx, wx;
+ double mod, floordiv;
+ CONVERT_TO_DOUBLE(v, vx);
+ CONVERT_TO_DOUBLE(w, wx);
+ if (wx == 0.0) {
+ PyErr_SetString(PyExc_ZeroDivisionError, "float floor division by zero");
+ return NULL;
+ }
+ _float_div_mod(vx, wx, &floordiv, &mod);
+ return PyFloat_FromDouble(floordiv);
}
/* determine whether x is an odd integer or not; assumes that