X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fround.c;h=b52bd35858a73a41761fa74e33190191afd80a5e;hb=fc5b3a7190a490a169f2d53a54b393a68fab9ec2;hp=5758fb7c79c571d9f9e7c9d137fe2aa1955cf9d9;hpb=980d2709cea1e46299cb5b4f74f7c7a95d07ef06;p=gnulib.git
diff --git a/lib/round.c b/lib/round.c
index 5758fb7c7..b52bd3585 100644
--- a/lib/round.c
+++ b/lib/round.c
@@ -1,5 +1,5 @@
/* Round toward nearest, breaking ties away from zero.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2010-2012 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
@@ -12,31 +12,38 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation,
- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+ with this program; if not, see . */
/* Written by Ben Pfaff , 2007.
Based heavily on code by Bruno Haible. */
-#include
+#if ! defined USE_LONG_DOUBLE
+# include
+#endif
-#include
+/* Specification. */
#include
+#include
+
+#undef MIN
+
#ifdef USE_LONG_DOUBLE
# define ROUND roundl
# define FLOOR floorl
# 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_DECL_FLOORL && HAVE_DECL_CEILL)
+# define HAVE_FLOOR_AND_CEIL HAVE_FLOORL_AND_CEILL
#elif ! defined USE_FLOAT
# define ROUND round
# define FLOOR floor
# 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,8 +52,22 @@
# 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_DECL_FLOORF && HAVE_DECL_CEILF)
+# 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
+
+/* MSVC with option -fp:strict refuses to compile constant initializers that
+ contain floating-point operations. Pacify this compiler. */
+#ifdef _MSC_VER
+# pragma fenv_access (off)
#endif
/* If we're being included from test-round2[f].c, it already defined names for
@@ -67,7 +88,7 @@
DOUBLE
FLOOR_BASED_ROUND (DOUBLE x)
{
- if (x >= L_(0.0))
+ if (x >= L_(0.0))
{
DOUBLE y = FLOOR (x);
if (x - y >= L_(0.5))
@@ -114,41 +135,40 @@ 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 = L_(0.0);
/* Avoid rounding errors for values near 2^k, where k >= MANT_DIG-1. */
else if (z < TWO_MANT_DIG)
- {
- /* Add 0.5 to the absolute value. */
- y = z += L_(0.5);
- /* Round to the next integer (nearest or up or down, doesn't
+ {
+ /* Add 0.5 to the absolute value. */
+ y = z += L_(0.5);
+ /* 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);
- }
+ z += TWO_MANT_DIG;
+ z -= TWO_MANT_DIG;
+ /* Enforce rounding down. */
+ if (z > y)
+ z -= L_(1.0);
+ }
}
else if (z < L_(0.0))
{
/* 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)
- {
- /* Add 0.5 to the absolute value. */
- y = z -= L_(0.5);
- /* Round to the next integer (nearest or up or down, doesn't
+ {
+ /* Add 0.5 to the absolute value. */
+ y = z -= L_(0.5);
+ /* 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);
- }
+ z -= TWO_MANT_DIG;
+ z += TWO_MANT_DIG;
+ /* Enforce rounding up. */
+ if (z < y)
+ z += L_(1.0);
+ }
}
return z;
}
#endif /* FLOOR_FREE_ROUND */
-