Fix incorrect rounding of floor, floorf, floorl in some cases. Add new test.
authorBruno Haible <bruno@clisp.org>
Sat, 13 Oct 2007 00:51:46 +0000 (02:51 +0200)
committerBruno Haible <bruno@clisp.org>
Sat, 13 Oct 2007 00:51:46 +0000 (02:51 +0200)
ChangeLog
lib/floor.c
modules/floorf-tests

index 2886236767b0b3d7524d16cd0cf025e5280c4ecc..7857f6ed14fc0ced6c1d5d3bb91e9a1620eb0e69 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2007-10-12  Bruno Haible  <bruno@clisp.org>
 
+       * lib/floor.c (FUNC): Avoid rounding errors for values near a power
+       of 2.
+       * tests/test-floorf2.c: New file.
+       * modules/floorf-tests: (Files, Depends-on, Makefile.am): Add new test.
+
        * tests/test-floorf1.c: Renamed from tests/test-floorf.c.
        * modules/floorf-tests: Update.
 
index 7ee748601daeae96d4740eabcdbf1b845b1ab405..05a6591a4b40a183307ed04d9f4e04f22a4f64d1 100644 (file)
@@ -63,20 +63,31 @@ 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;
+      /* 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))
     {
-      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;
 }
index c8a97a8588ea2276115cfe0749ce5d73345a6888..02a5ca28c6d707d855c8c68ca000c28dd03dd66c 100644 (file)
@@ -1,14 +1,20 @@
 Files:
 tests/test-floorf1.c
+tests/test-floorf2.c
 
 Depends-on:
+float
+isnanf-nolibm
+stdbool
+stdint
 
 configure.ac:
 
 Makefile.am:
-TESTS += test-floorf1
-check_PROGRAMS += test-floorf1
+TESTS += test-floorf1 test-floorf2
+check_PROGRAMS += test-floorf1 test-floorf2
 test_floorf1_LDADD = $(LDADD) @FLOORF_LIBM@
+test_floorf2_LDADD = $(LDADD) @FLOORF_LIBM@
 
 License:
 LGPL