From: Bruno Haible Date: Wed, 22 Dec 2010 15:05:29 +0000 (+0100) Subject: floor: Implement result sign according to IEEE 754. X-Git-Tag: v0.1~3496 X-Git-Url: http://erislabs.net/gitweb/?a=commitdiff_plain;h=9ca8092d849ed03418229af9a2aefdf784fd4db9;p=gnulib.git floor: Implement result sign according to IEEE 754. * lib/floor.c (FUNC): Return +0.0 for 0 < x < 1. * tests/test-floor2.c (floor_reference): Keep in sync with lib/floor.c. * tests/test-floorf2.c (floorf_reference): Likewise. * tests/test-floorf-ieee.c (main): Test also values between -1 and 1. * tests/test-floor-ieee.c (main): Likewise. * tests/test-floorl-ieee.c (main): Likewise. --- diff --git a/ChangeLog b/ChangeLog index 298bae1b5..de2decf06 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,15 @@ 2010-12-22 Bruno Haible + floor: Implement result sign according to IEEE 754. + * lib/floor.c (FUNC): Return +0.0 for 0 < x < 1. + * tests/test-floor2.c (floor_reference): Keep in sync with lib/floor.c. + * tests/test-floorf2.c (floorf_reference): Likewise. + * tests/test-floorf-ieee.c (main): Test also values between -1 and 1. + * tests/test-floor-ieee.c (main): Likewise. + * tests/test-floorl-ieee.c (main): Likewise. + +2010-12-22 Bruno Haible + getaddrinfo: Update doc. * doc/posix-functions/gai_strerror.texi: Return type is also different on AIX and HP-UX. diff --git a/lib/floor.c b/lib/floor.c index 593b52682..73a7e1eb0 100644 --- a/lib/floor.c +++ b/lib/floor.c @@ -1,5 +1,5 @@ /* Round towards negative infinity. - Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2007, 2010 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 @@ -65,8 +65,12 @@ FUNC (DOUBLE x) if (z > L_(0.0)) { + /* 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. */ - if (z < TWO_MANT_DIG) + else if (z < TWO_MANT_DIG) { /* Round to the next integer (nearest or up or down, doesn't matter). */ z += TWO_MANT_DIG; diff --git a/tests/test-floor-ieee.c b/tests/test-floor-ieee.c index 0051d67f2..4446e8b14 100644 --- a/tests/test-floor-ieee.c +++ b/tests/test-floor-ieee.c @@ -24,9 +24,20 @@ int main () { + /* See IEEE 754, section 6.3: + "the sign of the result of the round floating-point number to + integral value operation is the sign of the operand. These rules + shall apply even when operands or results are zero or infinite." */ + /* Zero. */ ASSERT (!signbit (floor (0.0))); ASSERT (!!signbit (floor (minus_zerod)) == !!signbit (minus_zerod)); + /* Positive numbers. */ + ASSERT (!signbit (floor (0.3))); + ASSERT (!signbit (floor (0.7))); + /* Negative numbers. */ + ASSERT (!!signbit (floor (-0.3)) == !!signbit (minus_zerod)); + ASSERT (!!signbit (floor (-0.7)) == !!signbit (minus_zerod)); return 0; } diff --git a/tests/test-floor2.c b/tests/test-floor2.c index 1aca8ab5f..e2391993b 100644 --- a/tests/test-floor2.c +++ b/tests/test-floor2.c @@ -63,8 +63,12 @@ floor_reference (DOUBLE x) if (z > L_(0.0)) { + /* 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. */ - if (z < TWO_MANT_DIG) + else if (z < TWO_MANT_DIG) { /* Round to the next integer (nearest or up or down, doesn't matter). */ z += TWO_MANT_DIG; diff --git a/tests/test-floorf-ieee.c b/tests/test-floorf-ieee.c index da1384873..c4925d2b1 100644 --- a/tests/test-floorf-ieee.c +++ b/tests/test-floorf-ieee.c @@ -37,9 +37,20 @@ main (int argc, char **argv _GL_UNUSED) { float (*my_floorf) (float) = argc ? floorf : dummy; + /* See IEEE 754, section 6.3: + "the sign of the result of the round floating-point number to + integral value operation is the sign of the operand. These rules + shall apply even when operands or results are zero or infinite." */ + /* Zero. */ ASSERT (!signbit (my_floorf (0.0f))); ASSERT (!!signbit (my_floorf (minus_zerof)) == !!signbit (minus_zerof)); + /* Positive numbers. */ + ASSERT (!signbit (my_floorf (0.3f))); + ASSERT (!signbit (my_floorf (0.7f))); + /* Negative numbers. */ + ASSERT (!!signbit (my_floorf (-0.3f)) == !!signbit (minus_zerof)); + ASSERT (!!signbit (my_floorf (-0.7f)) == !!signbit (minus_zerof)); return 0; } diff --git a/tests/test-floorf2.c b/tests/test-floorf2.c index 6811728cc..b7f18a84f 100644 --- a/tests/test-floorf2.c +++ b/tests/test-floorf2.c @@ -63,8 +63,12 @@ floorf_reference (DOUBLE x) if (z > L_(0.0)) { + /* 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. */ - if (z < TWO_MANT_DIG) + else if (z < TWO_MANT_DIG) { /* Round to the next integer (nearest or up or down, doesn't matter). */ z += TWO_MANT_DIG; diff --git a/tests/test-floorl-ieee.c b/tests/test-floorl-ieee.c index 05e836e51..ec4b4e18c 100644 --- a/tests/test-floorl-ieee.c +++ b/tests/test-floorl-ieee.c @@ -29,9 +29,20 @@ main () BEGIN_LONG_DOUBLE_ROUNDING (); + /* See IEEE 754, section 6.3: + "the sign of the result of the round floating-point number to + integral value operation is the sign of the operand. These rules + shall apply even when operands or results are zero or infinite." */ + /* Zero. */ ASSERT (!signbit (floorl (0.0L))); ASSERT (!!signbit (floorl (minus_zerol)) == !!signbit (minus_zerol)); + /* Positive numbers. */ + ASSERT (!signbit (floorl (0.3L))); + ASSERT (!signbit (floorl (0.7L))); + /* Negative numbers. */ + ASSERT (!!signbit (floorl (-0.3L)) == !!signbit (minus_zerol)); + ASSERT (!!signbit (floorl (-0.7L)) == !!signbit (minus_zerol)); return 0; }