svn commit: r292800 - stable/9/tools/regression/lib/msun

Garrett Cooper ngie at FreeBSD.org
Sun Dec 27 21:16:00 UTC 2015


Author: ngie
Date: Sun Dec 27 21:15:58 2015
New Revision: 292800
URL: https://svnweb.freebsd.org/changeset/base/292800

Log:
  MFstable/10 r226377,r292799:
  
  r226377 (by das):
  
  Add some tests for double-rounding bugs in fma().
  
  r292799:
  
  MFC r292492,r292495,r292647:
  
  r292492:
  
  - Use nitems instead of handrolling the macro
  - Use a separate variable for tracking the testcase count instead
    of hardcoding the offset for the testcases
  
  Sponsored by: EMC / Isilon Storage Division
  
  r292495:
  
  Initialize j so it doesn't print out a garbage index
  
  Use it consistently instead of i in the first loop
  
  Sponsored by: EMC / Isilon Storage Division
  
  r292647:
  
  Use j instead of a hardcoded index (9) and increment it after
  running the NaNs testcases
  
  Pointyhat to: ngie
  Sponsored by: EMC / Isilon Storage Division

Modified:
  stable/9/tools/regression/lib/msun/test-fma.c
Directory Properties:
  stable/9/   (props changed)
  stable/9/tools/   (props changed)
  stable/9/tools/regression/   (props changed)

Modified: stable/9/tools/regression/lib/msun/test-fma.c
==============================================================================
--- stable/9/tools/regression/lib/msun/test-fma.c	Sun Dec 27 21:08:46 2015	(r292799)
+++ stable/9/tools/regression/lib/msun/test-fma.c	Sun Dec 27 21:15:58 2015	(r292800)
@@ -31,6 +31,7 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include <sys/param.h>
 #include <assert.h>
 #include <fenv.h>
 #include <float.h>
@@ -364,45 +365,107 @@ test_accuracy(void)
 #endif
 }
 
+static void
+test_double_rounding(void)
+{
+
+	/*
+	 *     a =  0x1.8000000000001p0
+	 *     b =  0x1.8000000000001p0
+	 *     c = -0x0.0000000000000000000000000080...1p+1
+	 * a * b =  0x1.2000000000001800000000000080p+1
+	 *
+	 * The correct behavior is to round DOWN to 0x1.2000000000001p+1 in
+	 * round-to-nearest mode.  An implementation that computes a*b+c in
+	 * double+double precision, however, will get 0x1.20000000000018p+1,
+	 * and then round UP.
+	 */
+	fesetround(FE_TONEAREST);
+	test(fma, 0x1.8000000000001p0, 0x1.8000000000001p0,
+	     -0x1.0000000000001p-104, 0x1.2000000000001p+1,
+	     ALL_STD_EXCEPT, FE_INEXACT);
+	fesetround(FE_DOWNWARD);
+	test(fma, 0x1.8000000000001p0, 0x1.8000000000001p0,
+	     -0x1.0000000000001p-104, 0x1.2000000000001p+1,
+	     ALL_STD_EXCEPT, FE_INEXACT);
+	fesetround(FE_UPWARD);
+	test(fma, 0x1.8000000000001p0, 0x1.8000000000001p0,
+	     -0x1.0000000000001p-104, 0x1.2000000000002p+1,
+	     ALL_STD_EXCEPT, FE_INEXACT);
+
+	fesetround(FE_TONEAREST);
+	test(fmaf, 0x1.800002p+0, 0x1.800002p+0, -0x1.000002p-46, 0x1.200002p+1,
+	     ALL_STD_EXCEPT, FE_INEXACT);
+	fesetround(FE_DOWNWARD);
+	test(fmaf, 0x1.800002p+0, 0x1.800002p+0, -0x1.000002p-46, 0x1.200002p+1,
+	     ALL_STD_EXCEPT, FE_INEXACT);
+	fesetround(FE_UPWARD);
+	test(fmaf, 0x1.800002p+0, 0x1.800002p+0, -0x1.000002p-46, 0x1.200004p+1,
+	     ALL_STD_EXCEPT, FE_INEXACT);
+
+	fesetround(FE_TONEAREST);
+#if LDBL_MANT_DIG == 64
+	test(fmal, 0x1.4p+0L, 0x1.0000000000000004p+0L, 0x1p-128L,
+	     0x1.4000000000000006p+0L, ALL_STD_EXCEPT, FE_INEXACT);
+#elif LDBL_MANT_DIG == 113
+	/* XXX untested test */
+	test(fmal, 0x1.4p+0L, 0x1.0000000000000000000000000002p+0L, 0x1p-224L,
+	     0x1.4000000000000000000000000003p+0L, ALL_STD_EXCEPT, FE_INEXACT);
+#endif
+
+}
+
 int
 main(int argc, char *argv[])
 {
 	int rmodes[] = { FE_TONEAREST, FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO };
-	int i;
+	int i, j;
 
-	printf("1..18\n");
+	j = 1;
 
-	for (i = 0; i < 4; i++) {
+	printf("1..19\n");
+
+	for (i = 0; i < nitems(rmodes); i++, j++) {
+		printf("rmode = %d\n", rmodes[i]);
 		fesetround(rmodes[i]);
 		test_zeroes();
-		printf("ok %d - fma zeroes\n", i + 1);
+		printf("ok %d - fma zeroes\n", j);
 	}
 
-	for (i = 0; i < 4; i++) {
+	for (i = 0; i < nitems(rmodes); i++, j++) {
+		printf("rmode = %d\n", rmodes[i]);
 		fesetround(rmodes[i]);
 		test_infinities();
-		printf("ok %d - fma infinities\n", i + 5);
+		printf("ok %d - fma infinities\n", j);
 	}
 
 	fesetround(FE_TONEAREST);
 	test_nans();
-	printf("ok 9 - fma NaNs\n");
+	printf("ok %d - fma NaNs\n", j);
+	j++;
 
-	for (i = 0; i < 4; i++) {
+	for (i = 0; i < nitems(rmodes); i++, j++) {
+		printf("rmode = %d\n", rmodes[i]);
 		fesetround(rmodes[i]);
 		test_small_z();
-		printf("ok %d - fma small z\n", i + 10);
+		printf("ok %d - fma small z\n", j);
 	}
 
-	for (i = 0; i < 4; i++) {
+	for (i = 0; i < nitems(rmodes); i++, j++) {
+		printf("rmode = %d\n", rmodes[i]);
 		fesetround(rmodes[i]);
 		test_big_z();
-		printf("ok %d - fma big z\n", i + 14);
+		printf("ok %d - fma big z\n", j);
 	}
 
 	fesetround(FE_TONEAREST);
 	test_accuracy();
-	printf("ok 18 - fma accuracy\n");
+	printf("ok %d - fma accuracy\n", j);
+	j++;
+
+	test_double_rounding();
+	printf("ok %d - fma double rounding\n", j);
+	j++;
 
 	/*
 	 * TODO:


More information about the svn-src-all mailing list