X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Ftrunc.c;h=a10184e352a59c1a3e90825f97887f62c0a96061;hb=a3984e06bca84a7654624dd754a7c4c7a5a39a59;hp=385e2d139cdf03cc4b4cd94c50be9ea534f425e1;hpb=57fdfd3f8ec62b105c53bcdf6f127c35c7fe7391;p=gnulib.git diff --git a/lib/trunc.c b/lib/trunc.c index 385e2d139..a10184e35 100644 --- a/lib/trunc.c +++ b/lib/trunc.c @@ -41,7 +41,7 @@ #endif /* 2^(MANT_DIG-1). */ -static const double TWO_MANT_DIG = +static const DOUBLE TWO_MANT_DIG = /* Assume MANT_DIG <= 5 * 31. Use the identity n = floor(n/5) + floor((n+1)/5) + ... + floor((n+4)/5). */ @@ -65,21 +65,29 @@ FUNC (DOUBLE x) if (z > L_(0.0)) { - /* 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); + /* 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)) { - /* Round to the next integer (nearest or up or down, doesn't matter). */ - z -= TWO_MANT_DIG; - z += TWO_MANT_DIG; - /* Enforce rounding up. */ - if (z < y) - z += L_(1.0); + /* 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 up. */ + if (z < y) + z += L_(1.0); + } } return z; }