# HG changeset patch # User Paul Eggert # Date 854427105 0 # Node ID d6cd00b2e214b22624a8580dc636bebd3847aa43 # Parent 54108c7f46e6d063185edca373a3cfbf28e704b5 (isnan): Define even if LISP_FLOAT_TYPE is not defined, since fmod might need it. (fmod): Ensure that the magnitude of the result does not exceed that of the divisor, and that the sign of the result does not disagree with that of the dividend. This does not yield a particularly accurate result, but at least it will be in the range promised by fmod. diff -r 54108c7f46e6 -r d6cd00b2e214 src/data.c --- a/src/data.c Mon Jan 27 22:55:04 1997 +0000 +++ b/src/data.c Tue Jan 28 04:51:45 1997 +0000 @@ -2007,11 +2007,11 @@ return val; } -#ifdef LISP_FLOAT_TYPE - #undef isnan #define isnan(x) ((x) != (x)) +#ifdef LISP_FLOAT_TYPE + Lisp_Object float_arith_driver (accum, argnum, code, nargs, args) double accum; @@ -2141,9 +2141,21 @@ fmod (f1, f2) double f1, f2; { + double r = f1; + if (f2 < 0.0) f2 = -f2; - return (f1 - f2 * floor (f1/f2)); + + /* If the magnitude of the result exceeds that of the divisor, or + the sign of the result does not agree with that of the dividend, + iterate with the reduced value. This does not yield a + particularly accurate result, but at least it will be in the + range promised by fmod. */ + do + r -= f2 * floor (r / f2); + while (f2 <= (r < 0 ? -r : r) || ((r < 0) != (f1 < 0) && ! isnan (r))); + + return r; } #endif /* ! HAVE_FMOD */