X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Ffloor.c;h=df5e6ddcc946e96f398fdbfa41535e4ce203a20f;hb=4b6dad7e35019625bd5eb30796beebac099a7422;hp=7ee748601daeae96d4740eabcdbf1b845b1ab405;hpb=d9cd580560f5ba3bd4c669d78321eb9947f4d568;p=gnulib.git diff --git a/lib/floor.c b/lib/floor.c index 7ee748601..df5e6ddcc 100644 --- a/lib/floor.c +++ b/lib/floor.c @@ -1,5 +1,5 @@ /* Round towards negative infinity. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2010-2011 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -63,20 +63,35 @@ 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; + /* For 0 < x < 1, return +0.0 even if the current rounding mode is + FE_DOWNWARD. */ + if (z < L_(1.0)) + z = L_(0.0); + /* Avoid rounding errors for values near 2^k, where k >= MANT_DIG-1. */ + else 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; }