From: Bruno Haible Date: Wed, 22 Dec 2010 15:10:58 +0000 (+0100) Subject: round: Implement result sign according to IEEE 754. X-Git-Tag: v0.1~3493 X-Git-Url: http://erislabs.org.uk/gitweb/?a=commitdiff_plain;h=2adbc9c81f9a8b3681f44c3103d2ab617506f6f2;p=gnulib.git round: Implement result sign according to IEEE 754. * lib/round.c (MIN, MINUS_ZERO): New macros. (FUNC): Return -0.0 for -0.5 < x < 0. * tests/test-roundf-ieee.c (main): Test also values between -1 and 1. * tests/test-round-ieee.c (main): Likewise. * tests/test-roundl-ieee.c (main): Likewise. --- diff --git a/ChangeLog b/ChangeLog index b8af66437..be3b0fa4c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2010-12-22 Bruno Haible + round: Implement result sign according to IEEE 754. + * lib/round.c (MIN, MINUS_ZERO): New macros. + (FUNC): Return -0.0 for -0.5 < x < 0. + * tests/test-roundf-ieee.c (main): Test also values between -1 and 1. + * tests/test-round-ieee.c (main): Likewise. + * tests/test-roundl-ieee.c (main): Likewise. + trunc: Implement result sign according to IEEE 754. * lib/trunc.c (MIN, MINUS_ZERO): New macros. (FUNC): Return +0.0 for 0 < x < 1 and -0.0 for -1 < x < 0. diff --git a/lib/round.c b/lib/round.c index c935ddc10..07ec4cdf8 100644 --- a/lib/round.c +++ b/lib/round.c @@ -1,5 +1,5 @@ /* Round toward nearest, breaking ties away from zero. - 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 @@ -29,6 +29,7 @@ # define CEIL ceill # define DOUBLE long double # define MANT_DIG LDBL_MANT_DIG +# define MIN LDBL_MIN # define L_(literal) literal##L # define HAVE_FLOOR_AND_CEIL HAVE_FLOORL_AND_CEILL #elif ! defined USE_FLOAT @@ -37,6 +38,7 @@ # define CEIL ceil # define DOUBLE double # define MANT_DIG DBL_MANT_DIG +# define MIN DBL_MIN # define L_(literal) literal # define HAVE_FLOOR_AND_CEIL 1 #else /* defined USE_FLOAT */ @@ -45,10 +47,18 @@ # define CEIL ceilf # define DOUBLE float # define MANT_DIG FLT_MANT_DIG +# define MIN FLT_MIN # define L_(literal) literal##f # define HAVE_FLOOR_AND_CEIL HAVE_FLOORF_AND_CEILF #endif +/* -0.0. See minus-zero.h. */ +#if defined __hpux || defined __sgi || defined __ICC +# define MINUS_ZERO (-MIN * MIN) +#else +# define MINUS_ZERO L_(-0.0) +#endif + /* If we're being included from test-round2[f].c, it already defined names for our round implementations. Otherwise, pick the preferred implementation for this machine. */ @@ -133,7 +143,7 @@ FLOOR_FREE_ROUND (DOUBLE x) { /* Avoid rounding error for x = -(0.5 - 2^(-MANT_DIG-1)). */ if (z > - L_(0.5)) - z = L_(0.0); + z = MINUS_ZERO; /* Avoid rounding errors for values near -2^k, where k >= MANT_DIG-1. */ else if (z > -TWO_MANT_DIG) { diff --git a/tests/test-round-ieee.c b/tests/test-round-ieee.c index 0d5ad86df..817acd12a 100644 --- a/tests/test-round-ieee.c +++ b/tests/test-round-ieee.c @@ -25,9 +25,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 (round (0.0))); ASSERT (!!signbit (round (minus_zerod)) == !!signbit (minus_zerod)); + /* Positive numbers. */ + ASSERT (!signbit (round (0.3))); + ASSERT (!signbit (round (0.7))); + /* Negative numbers. */ + ASSERT (!!signbit (round (-0.3)) == !!signbit (minus_zerod)); + ASSERT (!!signbit (round (-0.7)) == !!signbit (minus_zerod)); return 0; } diff --git a/tests/test-roundf-ieee.c b/tests/test-roundf-ieee.c index 3948401a2..e7d9001cb 100644 --- a/tests/test-roundf-ieee.c +++ b/tests/test-roundf-ieee.c @@ -25,9 +25,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 (roundf (0.0f))); ASSERT (!!signbit (roundf (minus_zerof)) == !!signbit (minus_zerof)); + /* Positive numbers. */ + ASSERT (!signbit (roundf (0.3f))); + ASSERT (!signbit (roundf (0.7f))); + /* Negative numbers. */ + ASSERT (!!signbit (roundf (-0.3f)) == !!signbit (minus_zerof)); + ASSERT (!!signbit (roundf (-0.7f)) == !!signbit (minus_zerof)); return 0; } diff --git a/tests/test-roundl-ieee.c b/tests/test-roundl-ieee.c index ca4ac9ed7..431005bae 100644 --- a/tests/test-roundl-ieee.c +++ b/tests/test-roundl-ieee.c @@ -30,9 +30,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 (roundl (0.0L))); ASSERT (!!signbit (roundl (minus_zerol)) == !!signbit (minus_zerol)); + /* Positive numbers. */ + ASSERT (!signbit (roundl (0.3L))); + ASSERT (!signbit (roundl (0.7L))); + /* Negative numbers. */ + ASSERT (!!signbit (roundl (-0.3L)) == !!signbit (minus_zerol)); + ASSERT (!!signbit (roundl (-0.7L)) == !!signbit (minus_zerol)); return 0; }