Commit 9263e78f authored by Guido van Rossum's avatar Guido van Rossum

Tim Peters writes:

1. Fixes float divmod so that the quotient it returns is always an integral
value.

2. Fixes float % and float divmod so that the remainder always gets the
right sign (the current code uses a "are the signs different?" test that
doesn't work half the time <wink> when the product of the divisor and the
remainder underflows to 0).
parent 8e40759d
......@@ -359,7 +359,7 @@ float_rem(v, w)
PyFloatObject *w;
{
double vx, wx;
double /* div, */ mod;
double mod;
wx = w->ob_fval;
if (wx == 0.0) {
PyErr_SetString(PyExc_ZeroDivisionError, "float modulo");
......@@ -368,10 +368,10 @@ float_rem(v, w)
PyFPE_START_PROTECT("modulo", return 0)
vx = v->ob_fval;
mod = fmod(vx, wx);
/* div = (vx - mod) / wx; */
if (wx*mod < 0) {
/* note: checking mod*wx < 0 is incorrect -- underflows to
0 if wx < sqrt(smallest nonzero double) */
if (mod && ((wx < 0) != (mod < 0))) {
mod += wx;
/* div -= 1.0; */
}
PyFPE_END_PROTECT(mod)
return PyFloat_FromDouble(mod);
......@@ -383,7 +383,7 @@ float_divmod(v, w)
PyFloatObject *w;
{
double vx, wx;
double div, mod;
double div, mod, floordiv;
wx = w->ob_fval;
if (wx == 0.0) {
PyErr_SetString(PyExc_ZeroDivisionError, "float divmod()");
......@@ -392,13 +392,25 @@ float_divmod(v, w)
PyFPE_START_PROTECT("divmod", return 0)
vx = v->ob_fval;
mod = fmod(vx, wx);
/* fmod is typically exact, so vx-mod is *mathemtically* 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 (wx*mod < 0) {
/* note: checking mod*wx < 0 is incorrect -- underflows to
0 if wx < sqrt(smallest nonzero double) */
if (mod && ((wx < 0) != (mod < 0))) {
mod += wx;
div -= 1.0;
}
/* snap quotient to nearest integral value */
floordiv = floor(div);
if (div - floordiv > 0.5)
floordiv += 1.0;
PyFPE_END_PROTECT(div)
return Py_BuildValue("(dd)", div, mod);
return Py_BuildValue("(dd)", floordiv, mod);
}
static double powu(x, n)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment