diff options
author | Bruno Haible <bruno@clisp.org> | 2007-10-13 02:51:46 +0200 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2007-10-13 02:51:46 +0200 |
commit | 33d6a0e5ca06c6d0a8b0fddba8c7f41bbd6794ae (patch) | |
tree | f5465ba662e635ac6c9a761d9d4a6876e8e6cc5d /lib/floor.c | |
parent | 7a9376508b5cf731a98a66e4021aa9d0167ef723 (diff) | |
download | gnulib-33d6a0e5ca06c6d0a8b0fddba8c7f41bbd6794ae.tar.gz |
Fix incorrect rounding of floor, floorf, floorl in some cases. Add new test.
Diffstat (limited to 'lib/floor.c')
-rw-r--r-- | lib/floor.c | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/lib/floor.c b/lib/floor.c index 7ee748601d..05a6591a4b 100644 --- a/lib/floor.c +++ b/lib/floor.c @@ -63,20 +63,31 @@ FUNC (DOUBLE x) 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; } |