[PATCHv2] Refactor tst-strtod-round.c for type-generic-ness
diff mbox

Message ID 1464193929-21482-1-git-send-email-murphyp@linux.vnet.ibm.com
State New
Headers show

Commit Message

Paul E. Murphy May 25, 2016, 4:32 p.m. UTC
Tested on x86_64 and ppc64le (ldbl-96-intel and ldbl-128ibm).

---8<---
Reduce much of the redundancy in this file, and attempt
to coral the type specific stuff to ease adding an new type.

NOTE: reviewers, you will need to build gen-tst-strtod-round.c
and regenerate tst-strtod-round-data.h.  This keeps the patch
concise.

	* stdlib/gen-tst-strtod-round.c: Add backslash to
	compile command in comment.
	(printfp): Remove the literal suffix, and define an infinite
	value as INF to avoid expansion clash with INFINITY.
	(round_str): Remove the literal suffix.
	(round_for_all): Likewise, remove the now duplicate ldbl-64
	entry, and remove some magic constants.

	* stdlib/tst-strtod-round.c: (TEST): Redefine to reduce
	duplication.  Remove duplicate dbl-64 and ldbl-64 entries.
	(ROUNDING_TESTS_long_double): Define as 0 for ibm128.
	(_CONCAT): New macro.
	(CONCAT): Likewise.
	(CHOOSE_ld): Likewise.
	(CHOOSE_f): Likewise.
	(CHOOSE_d): Likewise.
	(FTYPE_MEMBER): Likewise.
	(BOOL_MEMBER): Likewise.
	(STRUCT_FOREACH_FLOAT_FTYPE): Likewise.
	(STRUCT_FOREACH_FLOAT_BOOL): Likewise.
	(_XNTRY): Likewise.
	(XNTRY): Likewise.
	(_ENTRY): Likewise.
	(ENTRY): Likewise.
	(test_exactness): Generate members via macro.
	(test_results): Likewise.
	(test): Update members.
	(TEST): Redefine using new macros.
	(INF): New macro.
	(fetestmodes): New structure.
	(do_test): Refactor to be type generic.
	(test_in_one_mode): Refactor duplicate code into
	(GEN_ONE_TEST): New macro.

	* stdlib/tst-strtod-round-data.h: Regenerate.

	* stdlib/tst-strtod.h (GEN_TEST_STRTOD_FOREACH):
	Extend to pass additional arbitrary parameters to
	generators.
---
 stdlib/gen-tst-strtod-round.c |  48 ++++---
 stdlib/tst-strtod-round.c     | 304 ++++++++++++++++++++----------------------
 stdlib/tst-strtod.h           |   8 +-
 3 files changed, 173 insertions(+), 187 deletions(-)

Comments

Joseph Myers May 25, 2016, 5:21 p.m. UTC | #1
On Wed, 25 May 2016, Paul E. Murphy wrote:

> +/* Define the long double choose (CHOOSE_ld) macro
> +   to select the appropriate generated long double
> +   value from the generated test data.  */
>  #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
> -# define TEST(s, fexact, fd, fn, fz, fu, dexact, dd, dn, dz, du,	\
> -	      ld53exact, ld53d, ld53n, ld53z, ld53u,			\
> -	      ld64iexact, ld64id, ld64in, ld64iz, ld64iu,		\
> -	      ld64mexact, ld64md, ld64mn, ld64mz, ld64mu,		\
> -	      ld106exact, ld106d, ld106n, ld106z, ld106u,		\
> -	      ld113exact, ld113d, ld113n, ld113z, ld113u)		\
> -  {									\
> -    s,									\
> -    { fexact, dexact, ld53exact },					\
> -    { fd, dd, ld53d },							\
> -    { fn, dn, ld53n },							\
> -    { fz, dz, ld53z },							\
> -    { fu, du, ld53u }							\
> -  }
> +/* This is for the long double == double format.  */
> +#define CHOOSE_ld(f,d,...) d

Preprocessor directives inside preprocessor conditionals should have 
appropriate indentation after the '#', so "# define CHOOSE_ld" for all the 
CHOOSE_ld definitions.

OK with that fixed.
Paul E. Murphy May 25, 2016, 6:43 p.m. UTC | #2
On 05/25/2016 12:21 PM, Joseph Myers wrote:
> On Wed, 25 May 2016, Paul E. Murphy wrote:
> 
>> +/* Define the long double choose (CHOOSE_ld) macro
>> +   to select the appropriate generated long double
>> +   value from the generated test data.  */
>>  #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
>> -# define TEST(s, fexact, fd, fn, fz, fu, dexact, dd, dn, dz, du,	\
>> -	      ld53exact, ld53d, ld53n, ld53z, ld53u,			\
>> -	      ld64iexact, ld64id, ld64in, ld64iz, ld64iu,		\
>> -	      ld64mexact, ld64md, ld64mn, ld64mz, ld64mu,		\
>> -	      ld106exact, ld106d, ld106n, ld106z, ld106u,		\
>> -	      ld113exact, ld113d, ld113n, ld113z, ld113u)		\
>> -  {									\
>> -    s,									\
>> -    { fexact, dexact, ld53exact },					\
>> -    { fd, dd, ld53d },							\
>> -    { fn, dn, ld53n },							\
>> -    { fz, dz, ld53z },							\
>> -    { fu, du, ld53u }							\
>> -  }
>> +/* This is for the long double == double format.  */
>> +#define CHOOSE_ld(f,d,...) d
> 
> Preprocessor directives inside preprocessor conditionals should have 
> appropriate indentation after the '#', so "# define CHOOSE_ld" for all the 
> CHOOSE_ld definitions.
> 
> OK with that fixed.

Spaces added, committed as 1ced34c.

Patch
diff mbox

diff --git a/stdlib/gen-tst-strtod-round.c b/stdlib/gen-tst-strtod-round.c
index fa5562e..1c2823f 100644
--- a/stdlib/gen-tst-strtod-round.c
+++ b/stdlib/gen-tst-strtod-round.c
@@ -19,7 +19,7 @@ 
 
 /* Compile this program as:
 
-   gcc -std=gnu11 -O2 -Wall -Wextra gen-tst-strtod-round.c -lmpfr
+   gcc -std=gnu11 -O2 -Wall -Wextra gen-tst-strtod-round.c -lmpfr \
      -o gen-tst-strtod-round
 
    (use of current MPFR version recommended) and run it as:
@@ -60,19 +60,18 @@  string_to_fp (mpfr_t f, const char *s, mpfr_rnd_t rnd)
 #endif
 }
 
-static void
-print_fp (FILE *fout, mpfr_t f, const char *suffix, const char *suffix2)
+void
+print_fp (FILE *fout, mpfr_t f, const char *suffix)
 {
   if (mpfr_inf_p (f))
-    mpfr_fprintf (fout, "\t%sINFINITY%s", mpfr_signbit (f) ? "-" : "",
-		  suffix2);
+    mpfr_fprintf (fout, "\t%sINF%s", mpfr_signbit (f) ? "-" : "", suffix);
   else
-    mpfr_fprintf (fout, "\t%Ra%s%s", f, suffix, suffix2);
+    mpfr_fprintf (fout, "\t%Ra%s", f, suffix);
 }
 
 static void
-round_str (FILE *fout, const char *s, const char *suffix,
-	   int prec, int emin, int emax, bool ibm_ld)
+round_str (FILE *fout, const char *s, int prec, int emin, int emax,
+	   bool ibm_ld)
 {
   mpfr_t f;
   mpfr_set_default_prec (prec);
@@ -94,13 +93,13 @@  round_str (FILE *fout, const char *s, const char *suffix,
       mpfr_clear (max_value);
     }
   mpfr_fprintf (fout, "\t%s,\n", r ? "false" : "true");
-  print_fp (fout, f, suffix, ",\n");
+  print_fp (fout, f, ",\n");
   string_to_fp (f, s, MPFR_RNDN);
-  print_fp (fout, f, suffix, ",\n");
+  print_fp (fout, f, ",\n");
   string_to_fp (f, s, MPFR_RNDZ);
-  print_fp (fout, f, suffix, ",\n");
+  print_fp (fout, f, ",\n");
   string_to_fp (f, s, MPFR_RNDU);
-  print_fp (fout, f, suffix, "");
+  print_fp (fout, f, "");
   mpfr_clear (f);
 }
 
@@ -108,21 +107,19 @@  static void
 round_for_all (FILE *fout, const char *s)
 {
   static const struct fmt {
-    const char *suffix;
     int prec;
     int emin;
     int emax;
     bool ibm_ld;
-  } formats[7] = {
-    { "f", 24, -148, 128, false },
-    { "", 53, -1073, 1024, false },
-    { "L", 53, -1073, 1024, false },
+  } formats[] = {
+    { 24, -148, 128, false },
+    { 53, -1073, 1024, false },
     /* This is the Intel extended float format.  */
-    { "L", 64, -16444, 16384, false },
+    { 64, -16444, 16384, false },
     /* This is the Motorola extended float format.  */
-    { "L", 64, -16445, 16384, false },
-    { "L", 106, -1073, 1024, true },
-    { "L", 113, -16493, 16384, false },
+    { 64, -16445, 16384, false },
+    { 106, -1073, 1024, true },
+    { 113, -16493, 16384, false },
   };
   mpfr_fprintf (fout, "  TEST (\"");
   const char *p;
@@ -134,11 +131,12 @@  round_for_all (FILE *fout, const char *s)
     }
   mpfr_fprintf (fout, "\",\n");
   int i;
-  for (i = 0; i < 7; i++)
+  int n_formats = sizeof (formats) / sizeof (formats[0]);
+  for (i = 0; i < n_formats; i++)
     {
-      round_str (fout, s, formats[i].suffix, formats[i].prec,
-		 formats[i].emin, formats[i].emax, formats[i].ibm_ld);
-      if (i < 6)
+      round_str (fout, s, formats[i].prec, formats[i].emin,
+		 formats[i].emax, formats[i].ibm_ld);
+      if (i < n_formats - 1)
 	mpfr_fprintf (fout, ",\n");
     }
   mpfr_fprintf (fout, "),\n");
diff --git a/stdlib/tst-strtod-round.c b/stdlib/tst-strtod-round.c
index a2cd2ab..487096c 100644
--- a/stdlib/tst-strtod-round.c
+++ b/stdlib/tst-strtod-round.c
@@ -29,152 +29,165 @@ 
 #include <string.h>
 #include <math-tests.h>
 
-struct exactness
-{
-  bool f;
-  bool d;
-  bool ld;
-};
+#include "tst-strtod.h"
 
-struct test_results {
-  float f;
-  double d;
-  long double ld;
-};
+#define _CONCAT(a, b) a ## b
+#define CONCAT(a, b) _CONCAT (a, b)
 
-struct test {
-  const char *s;
-  struct exactness exact;
-  struct test_results rd, rn, rz, ru;
-};
+#if LDBL_MANT_DIG == 106 && LDBL_MAX_EXP == 1024
+/* This is a stupid hack for IBM long double.  This test ignores
+   inexact values for long double due to the limitations of the
+   format.  This ensures rounding tests are ignored.  */
+# undef ROUNDING_TESTS_long_double
+# define ROUNDING_TESTS_long_double(x) 0
+#endif
 
+/* Generator to create an FTYPE member variabled named FSUF
+   used to populate struct member variables.  */
+#define FTYPE_MEMBER(FSUF, FTYPE, FTOSTR, FTOSTRM, LSUF, CSUF)  \
+       FTYPE FSUF;
+
+/* Likewise, but each member is of type bool.  */
+#define BOOL_MEMBER(FSUF, FTYPE, FTOSTR, FTOSTRM, LSUF, CSUF)  \
+       bool FSUF;
+
+#define STRUCT_FOREACH_FLOAT_FTYPE GEN_TEST_STRTOD_FOREACH (FTYPE_MEMBER)
+#define STRUCT_FOREACH_FLOAT_BOOL GEN_TEST_STRTOD_FOREACH (BOOL_MEMBER)
+
+/* Define the long double choose (CHOOSE_ld) macro
+   to select the appropriate generated long double
+   value from the generated test data.  */
 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
-# define TEST(s, fexact, fd, fn, fz, fu, dexact, dd, dn, dz, du,	\
-	      ld53exact, ld53d, ld53n, ld53z, ld53u,			\
-	      ld64iexact, ld64id, ld64in, ld64iz, ld64iu,		\
-	      ld64mexact, ld64md, ld64mn, ld64mz, ld64mu,		\
-	      ld106exact, ld106d, ld106n, ld106z, ld106u,		\
-	      ld113exact, ld113d, ld113n, ld113z, ld113u)		\
-  {									\
-    s,									\
-    { fexact, dexact, ld53exact },					\
-    { fd, dd, ld53d },							\
-    { fn, dn, ld53n },							\
-    { fz, dz, ld53z },							\
-    { fu, du, ld53u }							\
-  }
+/* This is for the long double == double format.  */
+#define CHOOSE_ld(f,d,...) d
 #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && LDBL_MIN_EXP == -16381
 /* This is for the Intel extended float format.  */
-# define TEST(s, fexact, fd, fn, fz, fu, dexact, dd, dn, dz, du,	\
-	      ld53exact, ld53d, ld53n, ld53z, ld53u,			\
-	      ld64iexact, ld64id, ld64in, ld64iz, ld64iu,		\
-	      ld64mexact, ld64md, ld64mn, ld64mz, ld64mu,		\
-	      ld106exact, ld106d, ld106n, ld106z, ld106u,		\
-	      ld113exact, ld113d, ld113n, ld113z, ld113u)		\
-  {									\
-    s,									\
-    { fexact, dexact, ld64iexact },					\
-    { fd, dd, ld64id },							\
-    { fn, dn, ld64in },							\
-    { fz, dz, ld64iz },							\
-    { fu, du, ld64iu }							\
-  }
+#define CHOOSE_ld(f,d,ld64i,...) ld64i
 #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && LDBL_MIN_EXP == -16382
 /* This is for the Motorola extended float format.  */
-# define TEST(s, fexact, fd, fn, fz, fu, dexact, dd, dn, dz, du,	\
-	      ld53exact, ld53d, ld53n, ld53z, ld53u,			\
-	      ld64iexact, ld64id, ld64in, ld64iz, ld64iu,		\
-	      ld64mexact, ld64md, ld64mn, ld64mz, ld64mu,		\
-	      ld106exact, ld106d, ld106n, ld106z, ld106u,		\
-	      ld113exact, ld113d, ld113n, ld113z, ld113u)		\
-  {									\
-    s,									\
-    { fexact, dexact, ld64mexact },					\
-    { fd, dd, ld64md },							\
-    { fn, dn, ld64mn },							\
-    { fz, dz, ld64mz },							\
-    { fu, du, ld64mu }							\
-  }
+#define CHOOSE_ld(f,d,ld64i,ld64m,...) ld64m
 #elif LDBL_MANT_DIG == 106 && LDBL_MAX_EXP == 1024
-# define TEST(s, fexact, fd, fn, fz, fu, dexact, dd, dn, dz, du,	\
-	      ld53exact, ld53d, ld53n, ld53z, ld53u,			\
-	      ld64iexact, ld64id, ld64in, ld64iz, ld64iu,		\
-	      ld64mexact, ld64md, ld64mn, ld64mz, ld64mu,		\
-	      ld106exact, ld106d, ld106n, ld106z, ld106u,		\
-	      ld113exact, ld113d, ld113n, ld113z, ld113u)		\
-  {									\
-    s,									\
-    { fexact, dexact, ld106exact },					\
-    { fd, dd, ld106d },							\
-    { fn, dn, ld106n },							\
-    { fz, dz, ld106z },							\
-    { fu, du, ld106u }							\
-  }
+/* This is for the IBM extended double format.  */
+#define CHOOSE_ld(f,d,ld64i,ld64m,ld106,...) ld106
 #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384
-# define TEST(s, fexact, fd, fn, fz, fu, dexact, dd, dn, dz, du,	\
-	      ld53exact, ld53d, ld53n, ld53z, ld53u,			\
-	      ld64iexact, ld64id, ld64in, ld64iz, ld64iu,		\
-	      ld64mexact, ld64md, ld64mn, ld64mz, ld64mu,		\
-	      ld106exact, ld106d, ld106n, ld106z, ld106u,		\
-	      ld113exact, ld113d, ld113n, ld113z, ld113u)		\
-  {									\
-    s,									\
-    { fexact, dexact, ld113exact },					\
-    { fd, dd, ld113d },							\
-    { fn, dn, ld113n },							\
-    { fz, dz, ld113z },							\
-    { fu, du, ld113u }							\
-  }
+/* This is for the IEEE binary128 format.  */
+#define CHOOSE_ld(f,d,ld64i,ld64m,ld106,ld113,...) ld113
 #else
 # error "unknown long double format"
 #endif
 
+/* Add type specific choosing macros below.  */
+#define CHOOSE_f(f,...) f
+#define CHOOSE_d(f,d,...) d
+/* long double is special, and handled above.  */
+
+/* Selector for expected result field of a given type.  */
+#define _ENTRY(FSUF, FTYPE, FTOSTR, FTOSTRM, LSUF, CSUF, ...)  \
+  CONCAT (CHOOSE_ ## FSUF (__VA_ARGS__), LSUF),
+#define ENTRY(...) \
+  GEN_TEST_STRTOD_FOREACH (_ENTRY, __VA_ARGS__)
+
+/* Selector for boolean exact tag of expected results.  */
+#define _XNTRY(FSUF, FTYPE, FTOSTR, FTOSTRM, LSUF, CSUF, ...)  \
+  CHOOSE_ ## FSUF (__VA_ARGS__),
+#define XNTRY(...) \
+  GEN_TEST_STRTOD_FOREACH (_XNTRY, __VA_ARGS__)
+
+/* This is hacky way around the seemingly unavoidable macro
+   expansion of the INFINITY or HUGE_VAL like macros in the
+   above.  It is assumed the compiler will implicitly convert
+   the infinity correctly.  */
+#define INF INFINITY + 0.0
+
+/* This macro is used in conjunction with the output from the
+   gen-tst-strtod-round utility to select the appropriately
+   rounded long double value for a given format.  */
+#define TEST(s,						\
+	     fx, fd, fn, fz, fu,			\
+	     dx, dd, dn, dz, du,			\
+	     ld64ix, ld64id, ld64in, ld64iz, ld64iu,	\
+	     ld64mx, ld64md, ld64mn, ld64mz, ld64mu,	\
+	     ld106x, ld106d, ld106n, ld106z, ld106u,	\
+	     ld113x, ld113d, ld113n, ld113z, ld113u)	\
+  {							\
+    s,							\
+    { XNTRY (fx, dx, ld64ix, ld64mx, ld106x, ld113x) },	\
+    {							\
+    { ENTRY (fn, dn, ld64in, ld64mn, ld106n, ld113n) },	\
+    { ENTRY (fd, dd, ld64id, ld64md, ld106d, ld113d) },	\
+    { ENTRY (fz, dz, ld64iz, ld64mz, ld106z, ld113z) },	\
+    { ENTRY (fu, du, ld64iu, ld64mu, ld106u, ld113u) }	\
+    }							\
+  }
+
+struct test_exactness
+  {
+  STRUCT_FOREACH_FLOAT_BOOL
+  };
+
+struct test_results
+  {
+  STRUCT_FOREACH_FLOAT_FTYPE
+  };
+
+struct test {
+  const char *s;
+  struct test_exactness exact;
+  struct test_results r[4];
+};
+
 /* Include the generated test data.  */
 #include "tst-strtod-round-data.h"
 
+#define GEN_ONE_TEST(FSUF, FTYPE, FTOSTR, FTOSTRM, LSUF, CSUF)	\
+{								\
+  FTYPE f = strto ## FSUF (s, NULL);				\
+  if (f != expected->FSUF					\
+      || (copysign ## CSUF) (1.0 ## LSUF, f)			\
+	 != (copysign ## CSUF) (1.0 ## LSUF, expected->FSUF))	\
+    {								\
+      char efstr[FSTRLENMAX];					\
+      char fstr[FSTRLENMAX];					\
+      FTOSTR (efstr, FSTRLENMAX, "%" FTOSTRM "a", expected->FSUF); \
+      FTOSTR (fstr, FSTRLENMAX, "%" FTOSTRM "a", f);		\
+      printf ("strto" #FSUF " (%s) returned %s not %s"		\
+	      " (%s)\n", s, fstr, efstr, mode_name);		\
+      if (ROUNDING_TESTS (FTYPE, rnd_mode) || exact->FSUF)	\
+	result = 1;						\
+      else							\
+	printf ("ignoring this inexact result\n");		\
+    }								\
+}
+
 static int
 test_in_one_mode (const char *s, const struct test_results *expected,
-		  const struct exactness *exact, const char *mode_name,
-		  bool float_round_ok, bool double_round_ok,
-		  bool long_double_round_ok)
+		  const struct test_exactness *exact, const char *mode_name,
+		  int rnd_mode)
 {
   int result = 0;
-  float f = strtof (s, NULL);
-  double d = strtod (s, NULL);
-  long double ld = strtold (s, NULL);
-  if (f != expected->f
-      || copysignf (1.0f, f) != copysignf (1.0f, expected->f))
-    {
-      printf ("strtof (%s) returned %a not %a (%s)\n", s, f,
-	      expected->f, mode_name);
-      if (float_round_ok || exact->f)
-	result = 1;
-      else
-	printf ("ignoring this inexact result\n");
-    }
-  if (d != expected->d
-      || copysign (1.0, d) != copysign (1.0, expected->d))
-    {
-      printf ("strtod (%s) returned %a not %a (%s)\n", s, d,
-	      expected->d, mode_name);
-      if (double_round_ok || exact->d)
-	result = 1;
-      else
-	printf ("ignoring this inexact result\n");
-    }
-  if (ld != expected->ld
-      || copysignl (1.0L, ld) != copysignl (1.0L, expected->ld))
-    {
-      printf ("strtold (%s) returned %La not %La (%s)\n", s, ld,
-	      expected->ld, mode_name);
-      if ((long_double_round_ok && LDBL_MANT_DIG != 106) || exact->ld)
-	result = 1;
-      else
-	printf ("ignoring this inexact result\n");
-    }
+  GEN_TEST_STRTOD_FOREACH (GEN_ONE_TEST)
   return result;
 }
 
+static const struct fetestmodes
+  {
+  const char *mode_name;
+  int rnd_mode;
+  int rnd_i; /* Corresponding index into r array of struct test.  */
+  } modes[] = {
+    { "default rounding mode", FE_TONEAREST, 0 },
+#ifdef FE_DOWNWARD
+    { "FE_DOWNWARD", FE_DOWNWARD, 1 },
+#endif
+#ifdef FE_TOWARDZERO
+    { "FE_TOWARDZERO", FE_TOWARDZERO, 2 },
+#endif
+#ifdef FE_UPWARD
+    { "FE_UPWARD", FE_UPWARD, 3 },
+#endif
+    {}
+};
+
 static int
 do_test (void)
 {
@@ -182,44 +195,19 @@  do_test (void)
   int result = 0;
   for (size_t i = 0; i < sizeof (tests) / sizeof (tests[0]); i++)
     {
-      result |= test_in_one_mode (tests[i].s, &tests[i].rn, &tests[i].exact,
-				  "default rounding mode",
-				  true, true, true);
-#ifdef FE_DOWNWARD
-      if (!fesetround (FE_DOWNWARD))
+      result |= test_in_one_mode (tests[i].s, &tests[i].r[modes[0].rnd_i],
+				  &tests[i].exact, modes[0].mode_name,
+				  modes[0].rnd_mode);
+      for (const struct fetestmodes *m = &modes[1]; m->mode_name != NULL; m++)
 	{
-	  result |= test_in_one_mode (tests[i].s, &tests[i].rd,
-				      &tests[i].exact, "FE_DOWNWARD",
-				      ROUNDING_TESTS (float, FE_DOWNWARD),
-				      ROUNDING_TESTS (double, FE_DOWNWARD),
-				      ROUNDING_TESTS (long double,
-						      FE_DOWNWARD));
-	  fesetround (save_round_mode);
+	  if (!fesetround (m->rnd_mode))
+	    {
+	      result |= test_in_one_mode (tests[i].s, &tests[i].r[m->rnd_i],
+					  &tests[i].exact, m->mode_name,
+					  m->rnd_mode);
+	      fesetround (save_round_mode);
+	    }
 	}
-#endif
-#ifdef FE_TOWARDZERO
-      if (!fesetround (FE_TOWARDZERO))
-	{
-	  result |= test_in_one_mode (tests[i].s, &tests[i].rz,
-				      &tests[i].exact, "FE_TOWARDZERO",
-				      ROUNDING_TESTS (float, FE_TOWARDZERO),
-				      ROUNDING_TESTS (double, FE_TOWARDZERO),
-				      ROUNDING_TESTS (long double,
-						      FE_TOWARDZERO));
-	  fesetround (save_round_mode);
-	}
-#endif
-#ifdef FE_UPWARD
-      if (!fesetround (FE_UPWARD))
-	{
-	  result |= test_in_one_mode (tests[i].s, &tests[i].ru,
-				      &tests[i].exact, "FE_UPWARD",
-				      ROUNDING_TESTS (float, FE_UPWARD),
-				      ROUNDING_TESTS (double, FE_UPWARD),
-				      ROUNDING_TESTS (long double, FE_UPWARD));
-	  fesetround (save_round_mode);
-	}
-#endif
     }
   return result;
 }
diff --git a/stdlib/tst-strtod.h b/stdlib/tst-strtod.h
index d53c1de..607cf39 100644
--- a/stdlib/tst-strtod.h
+++ b/stdlib/tst-strtod.h
@@ -22,10 +22,10 @@ 
 #define FSTRLENMAX 128
 
 /* Splat n variants of the same test for the various strtod functions.  */
-#define GEN_TEST_STRTOD_FOREACH(mfunc)		  \
-    mfunc (  f,       float, snprintf,  "", f, f) \
-    mfunc (  d,      double, snprintf,  "",  ,  ) \
-    mfunc ( ld, long double, snprintf, "L", L, l)
+#define GEN_TEST_STRTOD_FOREACH(mfunc, ...)			 \
+    mfunc (  f,       float, snprintf,  "", f, f, ##__VA_ARGS__) \
+    mfunc (  d,      double, snprintf,  "",  ,  , ##__VA_ARGS__) \
+    mfunc ( ld, long double, snprintf, "L", L, l, ##__VA_ARGS__)
 /* The arguments to the generated macros are:
    FSUF - Function suffix
    FTYPE - float type