[PATCHv2,03/14] Begin refactor of libm-test.inc

Message ID 8365176381f9d8abd0c87bd7de3cbd7ae8032283.1463779745.git.murphyp@linux.vnet.ibm.com
State Superseded
Headers

Commit Message

Paul E. Murphy May 20, 2016, 9:37 p.m. UTC
  Attempt to creatively redefine the macros
to choose tests based on the format being
tested, not the type.

Note, TS 18661 does not define any printf
modifiers, so we need to be a little more
verbose about constructing strings to
output.

	* math/libm-test.inc:
	[__EXPAND]: New Macro.
	[_EXPAND]: New Macro.
	[TYPE_DECIMAL_DIG]: Redefine using type supplied PREFIX macro.
	[TYPE_MIN]: Likewise.
	[TYPE_TRUE_MIN]: Likewise.
	[TYPE_MAX]: Likewise.
	[MIN_EXP]: Likewise.
	[MAX_EXP]: Likewise.
	[MANT_DIG]: Likewise.

	[FSTR_MAX]: New macro.
	[TYPESTR]: Likewise.
	[TEST_COND_binary32]: Likewise.
	[TEST_COND_binary64]: Likewise.
	[TEST_COND_binary128]: Likewise.
	[TEST_COND_ibm128]: Likewise.
	[TEST_COND_intel96]: Likewise.
	[TEST_COND_m68k96]: Likewise.

	[TEST_COND_flt_32]: Redefine as equivalent format test macro.
	[TEST_COND_dbl_64]: Likewise.
	[TEST_COND_ldbl_96_intel]: Likewise.
	[TEST_COND_ldbl_96_m68k]: Likewise.
	[TEST_COND_ldbl_128]: Likewise.
	[TEST_COND_ldbl_128ibm]: Likewise.

	[plus_zero]: Redefine using LIT macro.
	[minus_zero]: Likewise.
	[plus_infty]: Redefine as (INF).
	[minux_infty]: Redefine as (-INF).
	[max_value]: Redefine as TYPE_MAX.
	[min_value]: Redefine as TYPE_MIN.
	[min_subnorm_value]: Redefine as TYPE_TRUE_MIN.

	(print_float): Refactor to use snprintf to convert FLOAT values
	to string. This enables dropin replacement of strtof for the
	TS 18661 defined types.
	(update_stats): Likewise.
	(print_complex_function_ulps): Likewise.
	(print_max_error): Likewise.
	(print_complex_max_error): Likewise.
	(check_float_internal): Likewise.

	* math/test-float.h [PREFIX]: New macro.
	[LIT]: Likewise.
	[TSTR]: Likewise.
	[FTOSTR]: Likewise.
	[INF]: Likewise.

	* math/test-double.h [PREFIX]: New macro.
	[LIT]: Likewise.
	[TSTR]: Likewise.
	[FTOSTR]: Likewise.
	[INF]: Likewise.

	* math/test-ldouble.h [PREFIX]: New macro.
	[LIT]: Likewise.
	[TSTR]: Likewise.
	[FTOSTR]: Likewise.
	[INF]: Likewise.
---
 math/libm-test.inc  | 211 +++++++++++++++++++++++++++++-----------------------
 math/test-double.h  |   5 ++
 math/test-float.h   |   5 ++
 math/test-ldouble.h |   5 ++
 4 files changed, 132 insertions(+), 94 deletions(-)
  

Comments

Joseph Myers May 23, 2016, 4:02 p.m. UTC | #1
On Fri, 20 May 2016, Paul E. Murphy wrote:

> +   INF A macro defining the positive infinite value of the type.  */

This should not be needed.  Just define plus_infty and minus_infty like 
qnan_value is defined, using FUNC (__builtin_inf) (), so reducing the 
numbers of definitions needed in the type-specific headers.  You can 
assume those built-in functions for all compilers supported for building 
glibc.

(Well, for float128 you may need to split FUNC into separate macros, since 
the public API will be *f128 but existing built-in functions are e.g. 
__builtin_infq.  But you could always name the functions __builtin_inff128 
etc. on powerpc from the start to avoid that issue and leave x86 to work 
around the different naming.  It looks like you should add built-in 
functions __builtin_nan<something>, __builtin_nans<something>, for use in 
tests, that are currently missing on x86 for TFmode; I've filed GCC bugs 
71241 and 71242 for the absence of such functions for x86 and ia64.)

>  /* Sufficient numbers of digits to represent any floating-point value
>     unambiguously (for any choice of the number of bits in the first
>     hex digit, in the case of TYPE_HEX_DIG).  When used with printf
>     formats where the precision counts only digits after the point, 1
>     is subtracted from these values. */
> -#define TYPE_DECIMAL_DIG CHOOSE (LDBL_DECIMAL_DIG,	\
> -				 DBL_DECIMAL_DIG,	\
> -				 FLT_DECIMAL_DIG,	\
> -				 LDBL_DECIMAL_DIG,	\
> -				 DBL_DECIMAL_DIG,	\
> -				 FLT_DECIMAL_DIG)
>  #define TYPE_HEX_DIG ((MANT_DIG + 6) / 4)

This comment is meant to apply to both TYPE_DECIMAL_DIG and TYPE_HEX_DIG.  
Thus, the new TYPE_DECIMAL_DIG definition should go here rather than 
elsewhere in the file.
  

Patch

diff --git a/math/libm-test.inc b/math/libm-test.inc
index 538f448..eb6218d 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -34,7 +34,14 @@ 
    the specifier, not the percent and width arguments,
    e.g. "f".
    PRINTF_XEXPR	   Like PRINTF_EXPR, but print in hexadecimal format.
-   PRINTF_NEXPR Like PRINTF_EXPR, but print nice.  */
+   PRINTF_NEXPR Like PRINTF_EXPR, but print nice.
+   PREFIX A macro which defines the prefix for common macros for the
+   type (i.e LDBL, DBL, or FLT).
+   LIT A function which appends the correct suffix to a literal.
+   TSTR A macro which defines a stringitized name of the type.
+   FTOSTR This macro defines a function similar in type to snprintf
+   which converts a FLOAT to a string.
+   INF A macro defining the positive infinite value of the type.  */
 
 /* This testsuite has currently tests for:
    acos, acosh, asin, asinh, atan, atan2, atanh,
@@ -183,31 +190,76 @@  struct ulp_data
 #define IGNORE_RESULT			0x20000
 #define NON_FINITE			0x40000
 
+#define __EXPAND(x,y) x ## y
+#define _EXPAND(x,y) __EXPAND (x,y)
+
+#define TYPE_DECIMAL_DIG _EXPAND (PREFIX, _DECIMAL_DIG)
+#define TYPE_MIN _EXPAND (PREFIX, _MIN)
+#define TYPE_TRUE_MIN _EXPAND (PREFIX, _TRUE_MIN)
+#define TYPE_MAX _EXPAND (PREFIX, _MAX)
+#define MIN_EXP _EXPAND (PREFIX, _MIN_EXP)
+#define MAX_EXP _EXPAND (PREFIX, _MAX_EXP)
+#define MANT_DIG _EXPAND (PREFIX, _MANT_DIG)
+
+/* Maximum character buffer to store a stringitized FLOAT value. */
+# define FSTR_MAX (128)
+
+#if TEST_INLINE
+# define TYPESTR "i" TSTR
+#else
+# define TYPESTR TSTR
+#endif
+
+/* Format specific test macros.  */
+#define TEST_COND_binary32 (MANT_DIG == 24	\
+			    && MIN_EXP == -125	\
+			    && MAX_EXP == 128)
+
+#define TEST_COND_binary64 (MANT_DIG == 53	\
+			    && MIN_EXP == -1021	\
+			    && MAX_EXP == 1024)
+
+#define TEST_COND_binary128 (MANT_DIG == 113		\
+			     && MIN_EXP == -16381	\
+			     && MAX_EXP == 16384)
+
+#define TEST_COND_ibm128 (MANT_DIG == 106)
+
+#define TEST_COND_intel96 (MANT_DIG == 64	\
+			   && MIN_EXP == -16381	\
+			   && MAX_EXP == 16384)
+
+#define TEST_COND_m68k96 (MANT_DIG == 64	\
+			  && MIN_EXP == -16382	\
+			  && MAX_EXP == 16384)
+
 /* Values underflowing only for float.  */
-#ifdef TEST_FLOAT
+#if TEST_COND_binary32
 # define UNDERFLOW_EXCEPTION_FLOAT	UNDERFLOW_EXCEPTION
 # define UNDERFLOW_EXCEPTION_OK_FLOAT	UNDERFLOW_EXCEPTION_OK
 #else
 # define UNDERFLOW_EXCEPTION_FLOAT	0
 # define UNDERFLOW_EXCEPTION_OK_FLOAT	0
 #endif
+
 /* Values underflowing only for double or types with a larger least
    positive normal value.  */
-#if defined TEST_FLOAT || defined TEST_DOUBLE \
-  || (defined TEST_LDOUBLE && LDBL_MIN_EXP >= DBL_MIN_EXP)
+#if TEST_COND_binary32 || TEST_COND_binary64 || TEST_COND_ibm128
 # define UNDERFLOW_EXCEPTION_DOUBLE	UNDERFLOW_EXCEPTION
 # define UNDERFLOW_EXCEPTION_OK_DOUBLE	UNDERFLOW_EXCEPTION_OK
 #else
 # define UNDERFLOW_EXCEPTION_DOUBLE	0
 # define UNDERFLOW_EXCEPTION_OK_DOUBLE	0
 #endif
+
 /* Values underflowing only for IBM long double or types with a larger least
    positive normal value.  */
-#if defined TEST_FLOAT || (defined TEST_LDOUBLE && LDBL_MIN_EXP > DBL_MIN_EXP)
+#if TEST_COND_binary32 || TEST_COND_ibm128
 # define UNDERFLOW_EXCEPTION_LDOUBLE_IBM	UNDERFLOW_EXCEPTION
 #else
 # define UNDERFLOW_EXCEPTION_LDOUBLE_IBM	0
 #endif
+
 /* Values underflowing on architectures detecting tininess before
    rounding, but not on those detecting tininess after rounding.  */
 #define UNDERFLOW_EXCEPTION_BEFORE_ROUNDING	(TININESS_AFTER_ROUNDING \
@@ -227,36 +279,13 @@  struct ulp_data
 #endif
 
 /* Conditions used by tests generated by gen-auto-libm-tests.c.  */
-#ifdef TEST_FLOAT
-# define TEST_COND_flt_32	1
-#else
-# define TEST_COND_flt_32	0
-#endif
-#if defined TEST_DOUBLE || (defined TEST_LDOUBLE && LDBL_MANT_DIG == 53)
-# define TEST_COND_dbl_64	1
-#else
-# define TEST_COND_dbl_64	0
-#endif
-#if defined TEST_LDOUBLE && LDBL_MANT_DIG == 64 && LDBL_MIN_EXP == -16381
-# define TEST_COND_ldbl_96_intel	1
-#else
-# define TEST_COND_ldbl_96_intel	0
-#endif
-#if defined TEST_LDOUBLE && LDBL_MANT_DIG == 64 && LDBL_MIN_EXP == -16382
-# define TEST_COND_ldbl_96_m68k	1
-#else
-# define TEST_COND_ldbl_96_m68k	0
-#endif
-#if defined TEST_LDOUBLE && LDBL_MANT_DIG == 113
-# define TEST_COND_ldbl_128	1
-#else
-# define TEST_COND_ldbl_128	0
-#endif
-#if defined TEST_LDOUBLE && LDBL_MANT_DIG == 106
-# define TEST_COND_ldbl_128ibm	1
-#else
-# define TEST_COND_ldbl_128ibm	0
-#endif
+#define TEST_COND_flt_32 TEST_COND_binary32
+#define TEST_COND_dbl_64 TEST_COND_binary64
+#define TEST_COND_ldbl_96_intel TEST_COND_intel96
+#define TEST_COND_ldbl_96_m68k  TEST_COND_m68k96
+#define TEST_COND_ldbl_128 TEST_COND_binary128
+#define TEST_COND_ldbl_128ibm TEST_COND_ibm128
+
 #if LONG_MAX == 0x7fffffff
 # define TEST_COND_long32	1
 # define TEST_COND_long64	0
@@ -302,25 +331,14 @@  static int output_max_error;	/* Should the maximal errors printed?  */
 static int output_points;	/* Should the single function results printed?  */
 static int ignore_max_ulp;	/* Should we ignore max_ulp?  */
 
-#define plus_zero	CHOOSE (0.0L, 0.0, 0.0f,	\
-				0.0L, 0.0, 0.0f)
-#define minus_zero	CHOOSE (-0.0L, -0.0, -0.0f,	\
-				-0.0L, -0.0, -0.0f)
-#define plus_infty	CHOOSE (HUGE_VALL, HUGE_VAL, HUGE_VALF, \
-				HUGE_VALL, HUGE_VAL, HUGE_VALF)
-#define minus_infty	CHOOSE (-HUGE_VALL, -HUGE_VAL, -HUGE_VALF,	\
-				-HUGE_VALL, -HUGE_VAL, -HUGE_VALF)
+#define plus_zero	LIT (0.0)
+#define minus_zero	LIT (-0.0)
+#define plus_infty	(INF)
+#define minus_infty	(-INF)
 #define qnan_value	FUNC (__builtin_nan) ("")
-#define max_value	CHOOSE (LDBL_MAX, DBL_MAX, FLT_MAX,	\
-				LDBL_MAX, DBL_MAX, FLT_MAX)
-#define min_value	CHOOSE (LDBL_MIN, DBL_MIN, FLT_MIN,	\
-				LDBL_MIN, DBL_MIN, FLT_MIN)
-#define min_subnorm_value	CHOOSE (LDBL_TRUE_MIN,	\
-					DBL_TRUE_MIN,	\
-					FLT_TRUE_MIN,	\
-					LDBL_TRUE_MIN,	\
-					DBL_TRUE_MIN,	\
-					FLT_TRUE_MIN)
+#define max_value	TYPE_MAX
+#define min_value	TYPE_MIN
+#define min_subnorm_value TYPE_TRUE_MIN
 
 static FLOAT max_error, real_max_error, imag_max_error;
 
@@ -328,23 +346,11 @@  static FLOAT prev_max_error, prev_real_max_error, prev_imag_max_error;
 
 static FLOAT max_valid_error;
 
-#define MANT_DIG CHOOSE (LDBL_MANT_DIG, DBL_MANT_DIG, FLT_MANT_DIG,  \
-			 LDBL_MANT_DIG, DBL_MANT_DIG, FLT_MANT_DIG)
-#define MIN_EXP CHOOSE (LDBL_MIN_EXP, DBL_MIN_EXP, FLT_MIN_EXP,	\
-			LDBL_MIN_EXP, DBL_MIN_EXP, FLT_MIN_EXP)
-#define MAX_EXP CHOOSE (LDBL_MAX_EXP, DBL_MAX_EXP, FLT_MAX_EXP, \
-			LDBL_MAX_EXP, DBL_MAX_EXP, FLT_MAX_EXP)
 /* Sufficient numbers of digits to represent any floating-point value
    unambiguously (for any choice of the number of bits in the first
    hex digit, in the case of TYPE_HEX_DIG).  When used with printf
    formats where the precision counts only digits after the point, 1
    is subtracted from these values. */
-#define TYPE_DECIMAL_DIG CHOOSE (LDBL_DECIMAL_DIG,	\
-				 DBL_DECIMAL_DIG,	\
-				 FLT_DECIMAL_DIG,	\
-				 LDBL_DECIMAL_DIG,	\
-				 DBL_DECIMAL_DIG,	\
-				 FLT_DECIMAL_DIG)
 #define TYPE_HEX_DIG ((MANT_DIG + 6) / 4)
 
 /* Compare KEY (a string, with the name of a function) with ULP (a
@@ -427,8 +433,12 @@  print_float (FLOAT f)
   else if (isnan (f))
     printf ("qNaN\n");
   else
-    printf ("% .*" PRINTF_EXPR "  % .*" PRINTF_XEXPR "\n",
-	    TYPE_DECIMAL_DIG - 1, f, TYPE_HEX_DIG - 1, f);
+    {
+      char fstrn[FSTR_MAX], fstrx[FSTR_MAX];
+      FTOSTR (fstrn, FSTR_MAX, "% .*" PRINTF_EXPR, TYPE_DECIMAL_DIG - 1, f);
+      FTOSTR (fstrx, FSTR_MAX, "% .*" PRINTF_XEXPR, TYPE_HEX_DIG - 1, f);
+      printf ("%s  %s\n", fstrn, fstrx);
+    }
 }
 
 /* Should the message print to screen?  This depends on the verbose flag,
@@ -470,11 +480,10 @@  print_function_ulps (const char *function_name, FLOAT ulp)
 {
   if (output_ulps)
     {
+      char ustrn[FSTR_MAX];
+      FTOSTR (ustrn, FSTR_MAX, "%.0" PRINTF_NEXPR, FUNC (ceil) (ulp));
       fprintf (ulps_file, "Function: \"%s\":\n", function_name);
-      fprintf (ulps_file, "%s: %.0" PRINTF_NEXPR "\n",
-	       CHOOSE("ldouble", "double", "float",
-		      "ildouble", "idouble", "ifloat"),
-	       FUNC(ceil) (ulp));
+      fprintf (ulps_file, TYPESTR ": %s\n", ustrn);
     }
 }
 
@@ -485,21 +494,20 @@  print_complex_function_ulps (const char *function_name, FLOAT real_ulp,
 {
   if (output_ulps)
     {
+      char fstrn[FSTR_MAX];
       if (real_ulp != 0.0)
 	{
+	  FTOSTR (fstrn, FSTR_MAX, "%.0" PRINTF_NEXPR,
+	            FUNC (ceil) (real_ulp));
 	  fprintf (ulps_file, "Function: Real part of \"%s\":\n", function_name);
-	  fprintf (ulps_file, "%s: %.0" PRINTF_NEXPR "\n",
-		   CHOOSE("ldouble", "double", "float",
-			  "ildouble", "idouble", "ifloat"),
-		   FUNC(ceil) (real_ulp));
+	  fprintf (ulps_file, TYPESTR ": %s\n", fstrn);
 	}
       if (imag_ulp != 0.0)
 	{
+	  FTOSTR (fstrn, FSTR_MAX, "%.0" PRINTF_NEXPR,
+	            FUNC (ceil) (imag_ulp));
 	  fprintf (ulps_file, "Function: Imaginary part of \"%s\":\n", function_name);
-	  fprintf (ulps_file, "%s: %.0" PRINTF_NEXPR "\n",
-		   CHOOSE("ldouble", "double", "float",
-			  "ildouble", "idouble", "ifloat"),
-		   FUNC(ceil) (imag_ulp));
+	  fprintf (ulps_file, TYPESTR ": %s\n", fstrn);
 	}
 
 
@@ -547,10 +555,12 @@  print_max_error (const char *func_name)
 
   if (print_screen_max_error (ok))
     {
+      char mestr[FSTR_MAX], pmestr[FSTR_MAX];
+      FTOSTR (mestr, FSTR_MAX, "%.0" PRINTF_NEXPR, FUNC (ceil) (max_error));
+      FTOSTR (pmestr, FSTR_MAX, "%.0" PRINTF_NEXPR, FUNC (ceil) (prev_max_error));
       printf ("Maximal error of `%s'\n", func_name);
-      printf (" is      : %.0" PRINTF_NEXPR " ulp\n", FUNC(ceil) (max_error));
-      printf (" accepted: %.0" PRINTF_NEXPR " ulp\n",
-	      FUNC(ceil) (prev_max_error));
+      printf (" is      : %s ulp\n", mestr);
+      printf (" accepted: %s ulp\n", pmestr);
     }
 
   update_stats (ok);
@@ -583,16 +593,22 @@  print_complex_max_error (const char *func_name)
 
   if (print_screen_max_error (ok))
     {
+      char rmestr[FSTR_MAX], prmestr[FSTR_MAX];
+      char imestr[FSTR_MAX], pimestr[FSTR_MAX];
+      FTOSTR (rmestr, FSTR_MAX, "%.0" PRINTF_NEXPR,
+		FUNC (ceil) (real_max_error));
+      FTOSTR (prmestr, FSTR_MAX, "%.0" PRINTF_NEXPR,
+		FUNC (ceil) (prev_real_max_error));
+      FTOSTR (imestr, FSTR_MAX, "%.0" PRINTF_NEXPR,
+		FUNC (ceil) (imag_max_error));
+      FTOSTR (pimestr, FSTR_MAX, "%.0" PRINTF_NEXPR,
+		FUNC (ceil) (prev_imag_max_error));
       printf ("Maximal error of real part of: %s\n", func_name);
-      printf (" is      : %.0" PRINTF_NEXPR " ulp\n",
-	      FUNC(ceil) (real_max_error));
-      printf (" accepted: %.0" PRINTF_NEXPR " ulp\n",
-	      FUNC(ceil) (prev_real_max_error));
+      printf (" is      : %s ulp\n", rmestr);
+      printf (" accepted: %s ulp\n", prmestr);
       printf ("Maximal error of imaginary part of: %s\n", func_name);
-      printf (" is      : %.0" PRINTF_NEXPR " ulp\n",
-	      FUNC(ceil) (imag_max_error));
-      printf (" accepted: %.0" PRINTF_NEXPR " ulp\n",
-	      FUNC(ceil) (prev_imag_max_error));
+      printf (" is      : %s ulp\n", imestr);
+      printf (" accepted: %s ulp\n", pimestr);
     }
 
   update_stats (ok);
@@ -850,10 +866,17 @@  check_float_internal (const char *test_name, FLOAT computed, FLOAT expected,
       print_float (expected);
       if (print_diff)
 	{
-	  printf (" difference: % .*" PRINTF_EXPR "  % .*" PRINTF_XEXPR
-		  "\n", TYPE_DECIMAL_DIG - 1, diff, TYPE_HEX_DIG - 1, diff);
-	  printf (" ulp       : % .4" PRINTF_NEXPR "\n", ulps);
-	  printf (" max.ulp   : % .4" PRINTF_NEXPR "\n", max_ulp);
+	  char dstrn[FSTR_MAX], dstrx[FSTR_MAX];
+	  char ustrn[FSTR_MAX], mustrn[FSTR_MAX];
+	  FTOSTR (dstrn, FSTR_MAX, "% .*" PRINTF_EXPR,
+		  TYPE_DECIMAL_DIG - 1, diff);
+	  FTOSTR (dstrx, FSTR_MAX, "% .*" PRINTF_XEXPR,
+		  TYPE_HEX_DIG - 1, diff);
+	  FTOSTR (ustrn, FSTR_MAX, "% .4" PRINTF_NEXPR, ulps);
+	  FTOSTR (mustrn, FSTR_MAX, "% .4" PRINTF_NEXPR, max_ulp);
+	  printf (" difference: %s  %s\n", dstrn, dstrx);
+	  printf (" ulp       : %s\n", ustrn);
+	  printf (" max.ulp   : %s\n", mustrn);
 	}
     }
   update_stats (ok);
diff --git a/math/test-double.h b/math/test-double.h
index 16b4ce8..0ece942 100644
--- a/math/test-double.h
+++ b/math/test-double.h
@@ -23,3 +23,8 @@ 
 #define PRINTF_NEXPR "f"
 #define TEST_DOUBLE 1
 #define BUILD_COMPLEX(real, imag) (CMPLX ((real), (imag)))
+#define PREFIX DBL
+#define LIT(x) (x)
+#define TSTR "double"
+#define FTOSTR snprintf
+#define INF HUGE_VAL
diff --git a/math/test-float.h b/math/test-float.h
index 629f6ee..d92612b 100644
--- a/math/test-float.h
+++ b/math/test-float.h
@@ -23,3 +23,8 @@ 
 #define PRINTF_NEXPR "f"
 #define TEST_FLOAT 1
 #define BUILD_COMPLEX(real, imag) (CMPLXF ((real), (imag)))
+#define PREFIX FLT
+#define TSTR "float"
+#define LIT(x) (x ## f)
+#define FTOSTR snprintf
+#define INF HUGE_VALF
diff --git a/math/test-ldouble.h b/math/test-ldouble.h
index 481561f..96a3dac 100644
--- a/math/test-ldouble.h
+++ b/math/test-ldouble.h
@@ -23,3 +23,8 @@ 
 #define PRINTF_NEXPR "Lf"
 #define TEST_LDOUBLE 1
 #define BUILD_COMPLEX(real, imag) (CMPLXL ((real), (imag)))
+#define PREFIX LDBL
+#define TSTR "ldouble"
+#define LIT(x) (x ## L)
+#define FTOSTR snprintf
+#define INF HUGE_VALL