diff mbox

[v3] Replace use of snprintf with strfrom in libm tests

Message ID 1482182728-12524-1-git-send-email-gftg@linux.vnet.ibm.com
State New
Headers show

Commit Message

Gabriel F. T. Gomes Dec. 19, 2016, 9:25 p.m. UTC
Changes since v2:
  - Replace the use of totalorder with signbit on fmt_ftostr.

---8<---
In order to support float128 tests, the calls to snprintf, which does
not support the type __float128, are replaced with calls to
strfrom{f,d,l}.

Tested for powerpc64le, s390, and x64_64.

2016-11-08  Gabriel F. T. Gomes  <gftg@linux.vnet.ibm.com>

	* math/libm-test.inc (fmt_ftostr): New function.
	(print_float, check_float_internal): Replace some uses of
	FTOSTR with uses of fmt_ftostr.
	(print_max_error, print_complex_max_error, print_function_ulps)
	(print_complex_function_ulps): Remove uses of the macros
	PRINTF_EXPR, PRINTF_NEXPR, and PRINTF_XEXPR.
	* math/test-double.h (FTOSTR): Define to strfromd.
	(PRINTF_EXPR): Delete.
	(PRINTF_XEXPR): Likewise.
	(PRINTF_NEXPR): Likewise.
	* math/test-float.h (FTOSTR): Define to strfromf.
	(PRINTF_EXPR): Delete.
	(PRINTF_XEXPR): Likewise.
	(PRINTF_NEXPR): Likewise.
	* math/test-ldouble.h (FTOSTR): Define to strfroml.
	(PRINTF_EXPR): Delete.
	(PRINTF_XEXPR): Likewise.
	(PRINTF_NEXPR): Likewise.
---
 math/libm-test.inc  | 79 +++++++++++++++++++++++++++++++++--------------------
 math/test-double.h  |  5 +---
 math/test-float.h   |  5 +---
 math/test-ldouble.h |  5 +---
 4 files changed, 52 insertions(+), 42 deletions(-)

Comments

Joseph Myers Dec. 19, 2016, 10:52 p.m. UTC | #1
On Mon, 19 Dec 2016, Gabriel F. T. Gomes wrote:

> +/* Converts VALUE (a floating-point number) to string and writes it to DEST.
> +   PRECISION specifies the number of fractional digits that should be printed.
> +   CONVERSION is the conversion specifier, such as in printf, e.g. 'f' or 'a'.
> +   The output is prepended with an empty space if VALUE is non-negative and if
> +   SPACE is true.  The function fmt_ftostr calls one of the strfrom functions
> +   and returns the same code.  */
> +static int
> +fmt_ftostr (char *dest, size_t size, bool space, int precision,
> +	    const char *conversion, FLOAT value)

As far as I can see, all calls to this function have the following 
properties:

* The return value is not used.

* The "space" argument is always 1.

So make the function return void and always have the "space" semantics 
rather than having that argument at all.  This avoids at least three 
problems: (a) if you're returning a value indicating the number of 
characters output, it needs to account for the added space, which this 
implementation does not; (b) by using bool you're relying on implicit 
inclusion of <stdbool.h> by include/fenv.h (that is, you'd need to add an 
include of <stdbool.h> to avoid the test breaking if we stop tests using 
internal headers as much as possible); (c) when using bool you should use 
"true" instead of 1.
diff mbox

Patch

diff --git a/math/libm-test.inc b/math/libm-test.inc
index 110b421..ee0dd78 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -28,17 +28,11 @@ 
    - TEST_MSG:	   informal message to be displayed
    chooses one of the parameters as delta for testing
    equality
-   PRINTF_EXPR	   Floating point conversion specification to print a variable
-   of type FLOAT with printf.  PRINTF_EXPR just contains
-   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.
    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.
    TYPE_STR A macro which defines a stringitized name of the type.
-   FTOSTR This macro defines a function similar in type to snprintf
+   FTOSTR This macro defines a function similar in type to strfromf
    which converts a FLOAT to a string.  */
 
 /* This testsuite has currently tests for:
@@ -355,6 +349,39 @@  static FLOAT max_valid_error;
 #define TYPE_DECIMAL_DIG __CONCATX (PREFIX, _DECIMAL_DIG)
 #define TYPE_HEX_DIG ((MANT_DIG + 6) / 4)
 
+/* Converts VALUE (a floating-point number) to string and writes it to DEST.
+   PRECISION specifies the number of fractional digits that should be printed.
+   CONVERSION is the conversion specifier, such as in printf, e.g. 'f' or 'a'.
+   The output is prepended with an empty space if VALUE is non-negative and if
+   SPACE is true.  The function fmt_ftostr calls one of the strfrom functions
+   and returns the same code.  */
+static int
+fmt_ftostr (char *dest, size_t size, bool space, int precision,
+	    const char *conversion, FLOAT value)
+{
+  char format[64];
+  char *ptr_format;
+  int ret;
+
+  /* Generate the format string.  */
+  ptr_format = stpcpy (format, "%.");
+  ret = sprintf (ptr_format, "%d", precision);
+  ptr_format += ret;
+  ptr_format = stpcpy (ptr_format, conversion);
+
+  /* Add a space to the beginning of the output string, if the floating-point
+     number is non-negative.  This mimics the behavior of the space (' ') flag
+     in snprintf, which is not available on strfrom.  */
+  if (space && ! signbit (value))
+    {
+      *dest = ' ';
+      dest++;
+    }
+
+  /* Call the float to string conversion function, e.g.: strfromd.  */
+  return FTOSTR (dest, size, format, value);
+}
+
 /* Compare KEY (a string, with the name of a function) with ULP (a
    pointer to a struct ulp_data structure), returning a value less
    than, equal to or greater than zero for use in bsearch.  */
@@ -437,8 +464,8 @@  print_float (FLOAT f)
   else
     {
       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);
+      fmt_ftostr (fstrn, FSTR_MAX, 1, TYPE_DECIMAL_DIG - 1, "e", f);
+      fmt_ftostr (fstrx, FSTR_MAX, 1, TYPE_HEX_DIG - 1, "a", f);
       printf ("%s  %s\n", fstrn, fstrx);
     }
 }
@@ -483,7 +510,7 @@  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));
+      FTOSTR (ustrn, FSTR_MAX, "%.0f", FUNC (ceil) (ulp));
       fprintf (ulps_file, "Function: \"%s\":\n", function_name);
       fprintf (ulps_file, QTYPE_STR ": %s\n", ustrn);
     }
@@ -499,15 +526,13 @@  print_complex_function_ulps (const char *function_name, FLOAT real_ulp,
       char fstrn[FSTR_MAX];
       if (real_ulp != 0.0)
 	{
-	  FTOSTR (fstrn, FSTR_MAX, "%.0" PRINTF_NEXPR,
-	            FUNC (ceil) (real_ulp));
+	  FTOSTR (fstrn, FSTR_MAX, "%.0f", FUNC (ceil) (real_ulp));
 	  fprintf (ulps_file, "Function: Real part of \"%s\":\n", function_name);
 	  fprintf (ulps_file, QTYPE_STR ": %s\n", fstrn);
 	}
       if (imag_ulp != 0.0)
 	{
-	  FTOSTR (fstrn, FSTR_MAX, "%.0" PRINTF_NEXPR,
-	            FUNC (ceil) (imag_ulp));
+	  FTOSTR (fstrn, FSTR_MAX, "%.0f", FUNC (ceil) (imag_ulp));
 	  fprintf (ulps_file, "Function: Imaginary part of \"%s\":\n", function_name);
 	  fprintf (ulps_file, QTYPE_STR ": %s\n", fstrn);
 	}
@@ -558,8 +583,8 @@  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));
+      FTOSTR (mestr, FSTR_MAX, "%.0f", FUNC (ceil) (max_error));
+      FTOSTR (pmestr, FSTR_MAX, "%.0f", FUNC (ceil) (prev_max_error));
       printf ("Maximal error of `%s'\n", func_name);
       printf (" is      : %s ulp\n", mestr);
       printf (" accepted: %s ulp\n", pmestr);
@@ -597,14 +622,10 @@  print_complex_max_error (const char *func_name)
     {
       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));
+      FTOSTR (rmestr, FSTR_MAX, "%.0f", FUNC (ceil) (real_max_error));
+      FTOSTR (prmestr, FSTR_MAX, "%.0f", FUNC (ceil) (prev_real_max_error));
+      FTOSTR (imestr, FSTR_MAX, "%.0f", FUNC (ceil) (imag_max_error));
+      FTOSTR (pimestr, FSTR_MAX, "%.0f", FUNC (ceil) (prev_imag_max_error));
       printf ("Maximal error of real part of: %s\n", func_name);
       printf (" is      : %s ulp\n", rmestr);
       printf (" accepted: %s ulp\n", prmestr);
@@ -884,12 +905,10 @@  check_float_internal (const char *test_name, FLOAT computed, FLOAT expected,
 	{
 	  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);
+	  fmt_ftostr (dstrn, FSTR_MAX, 1, TYPE_DECIMAL_DIG - 1, "e", diff);
+	  fmt_ftostr (dstrx, FSTR_MAX, 1, TYPE_HEX_DIG - 1, "a", diff);
+	  fmt_ftostr (ustrn, FSTR_MAX, 1, 4, "f", ulps);
+	  fmt_ftostr (mustrn, FSTR_MAX, 1, 4, "f", max_ulp);
 	  printf (" difference: %s  %s\n", dstrn, dstrx);
 	  printf (" ulp       : %s\n", ustrn);
 	  printf (" max.ulp   : %s\n", mustrn);
diff --git a/math/test-double.h b/math/test-double.h
index e172b8f..170f03c 100644
--- a/math/test-double.h
+++ b/math/test-double.h
@@ -18,13 +18,10 @@ 
 
 #define FUNC(function) function
 #define FLOAT double
-#define PRINTF_EXPR "e"
-#define PRINTF_XEXPR "a"
-#define PRINTF_NEXPR "f"
 #define BUILD_COMPLEX(real, imag) (CMPLX ((real), (imag)))
 #define PREFIX DBL
 #define LIT(x) (x)
 #define TYPE_STR "double"
 #define LITM(x) x
-#define FTOSTR snprintf
+#define FTOSTR strfromd
 #define snan_value_MACRO SNAN
diff --git a/math/test-float.h b/math/test-float.h
index ea096c8..84d0bd1 100644
--- a/math/test-float.h
+++ b/math/test-float.h
@@ -18,14 +18,11 @@ 
 
 #define FUNC(function) function ## f
 #define FLOAT float
-#define PRINTF_EXPR "e"
-#define PRINTF_XEXPR "a"
-#define PRINTF_NEXPR "f"
 #define BUILD_COMPLEX(real, imag) (CMPLXF ((real), (imag)))
 #define PREFIX FLT
 #define TYPE_STR "float"
 #define LIT(x) (x ## f)
 /* Use the double variants of macro constants.  */
 #define LITM(x) x
-#define FTOSTR snprintf
+#define FTOSTR strfromf
 #define snan_value_MACRO SNANF
diff --git a/math/test-ldouble.h b/math/test-ldouble.h
index 62c9eb8..a18938a 100644
--- a/math/test-ldouble.h
+++ b/math/test-ldouble.h
@@ -18,13 +18,10 @@ 
 
 #define FUNC(function) function##l
 #define FLOAT long double
-#define PRINTF_EXPR "Le"
-#define PRINTF_XEXPR "La"
-#define PRINTF_NEXPR "Lf"
 #define BUILD_COMPLEX(real, imag) (CMPLXL ((real), (imag)))
 #define PREFIX LDBL
 #define TYPE_STR "ldouble"
 #define LIT(x) (x ## L)
 #define LITM(x) x ## l
-#define FTOSTR snprintf
+#define FTOSTR strfroml
 #define snan_value_MACRO SNANL