Mercurial > hg > octave-nkf > gnulib-hg
diff lib/floor.c @ 9332:b72a5920bf45
Fix incorrect rounding of floor, floorf, floorl in some cases. Add new test.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Sat, 13 Oct 2007 02:51:46 +0200 |
parents | 59fc463c9868 |
children | e8d2c6fc33ad |
line wrap: on
line diff
--- a/lib/floor.c +++ b/lib/floor.c @@ -63,20 +63,31 @@ volatile DOUBLE y = x; volatile DOUBLE z = y; - /* Round to the next integer (nearest or up or down, doesn't matter). */ if (z > L_(0.0)) { - z += TWO_MANT_DIG; - z -= TWO_MANT_DIG; + /* Avoid rounding errors for values near 2^k, where k >= MANT_DIG-1. */ + if (z < TWO_MANT_DIG) + { + /* Round to the next integer (nearest or up or down, doesn't matter). */ + z += TWO_MANT_DIG; + z -= TWO_MANT_DIG; + /* Enforce rounding down. */ + if (z > y) + z -= L_(1.0); + } } else if (z < L_(0.0)) { - z -= TWO_MANT_DIG; - z += TWO_MANT_DIG; + /* Avoid rounding errors for values near -2^k, where k >= MANT_DIG-1. */ + if (z > - TWO_MANT_DIG) + { + /* Round to the next integer (nearest or up or down, doesn't matter). */ + z -= TWO_MANT_DIG; + z += TWO_MANT_DIG; + /* Enforce rounding down. */ + if (z > y) + z -= L_(1.0); + } } - /* Enforce rounding down. */ - if (z > y) - z -= L_(1.0); - return z; }