Blame math/libm-test-support.c

Packit 6c4009
/* Support code for testing libm functions (compiled once per type).
Packit 6c4009
   Copyright (C) 1997-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
/* Part of testsuite for libm.
Packit 6c4009
Packit 6c4009
   libm-test-support.c contains functions shared by tests of different
Packit 6c4009
   libm functions and types; it is compiled once per type.
Packit 6c4009
   libm-test-driver.c defines the main function, and various variables
Packit 6c4009
   that are used to configure the code in libm-test-support.c for
Packit 6c4009
   different types and for variants such as testing inline functions.
Packit 6c4009
Packit 6c4009
   The tests of individual functions are in .inc files processed by
Packit 6c4009
   gen-libm-test.pl, with the resulting files included together with
Packit 6c4009
   libm-test-driver.c.
Packit 6c4009
Packit 6c4009
   The per-type headers included both before libm-test-support.c and
Packit 6c4009
   for the tests of individual functions must define the following
Packit 6c4009
   macros:
Packit 6c4009
Packit 6c4009
   FUNC(function): Convert general function name (like cos) to name
Packit 6c4009
   with correct suffix (e.g. cosl or cosf).
Packit 6c4009
Packit 6c4009
   FLOAT: Floating-point type to test.
Packit 6c4009
Packit 6c4009
   BUILD_COMPLEX(real, imag): Create a complex number by calling a
Packit 6c4009
   macro such as CMPLX.
Packit 6c4009
Packit 6c4009
   PREFIX: The prefix for <float.h> macros for the type (e.g. LDBL,
Packit 6c4009
   DBL, or FLT).
Packit 6c4009
Packit 6c4009
   TYPE_STR: The name of the type as used in ulps files, as a string.
Packit 6c4009
Packit 6c4009
   ULP_IDX, ULP_I_IDX: The array indexes for ulps values for this
Packit 6c4009
   function.
Packit 6c4009
Packit 6c4009
   LIT: Append the correct suffix to a literal.
Packit 6c4009
Packit 6c4009
   LITM: Append the correct suffix to an M_* macro name.
Packit 6c4009
Packit 6c4009
   FTOSTR: A function similar in type to strfromf which converts a
Packit 6c4009
   FLOAT to a string.
Packit 6c4009
Packit 6c4009
   snan_value_MACRO: The macro such as SNAN for a signaling NaN for
Packit 6c4009
   the type.
Packit 6c4009
Packit 6c4009
*/
Packit 6c4009
Packit 6c4009
/* Parameter handling is primitive in the moment:
Packit 6c4009
   --verbose=[0..3] for different levels of output:
Packit 6c4009
   0: only error count
Packit 6c4009
   1: basic report on failed tests (default)
Packit 6c4009
   2: full report on all tests
Packit 6c4009
   -v for full output (equals --verbose=3)
Packit 6c4009
   -u for generation of an ULPs file
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
/* "Philosophy":
Packit 6c4009
Packit 6c4009
   This suite tests some aspects of the correct implementation of
Packit 6c4009
   mathematical functions in libm.  Some simple, specific parameters
Packit 6c4009
   are tested for correctness but there's no exhaustive
Packit 6c4009
   testing.  Handling of specific inputs (e.g. infinity, not-a-number)
Packit 6c4009
   is also tested.  Correct handling of exceptions is checked
Packit 6c4009
   against.  These implemented tests should check all cases that are
Packit 6c4009
   specified in ISO C99.
Packit 6c4009
Packit 6c4009
   NaN values: The payload of NaNs is set in inputs for functions
Packit 6c4009
   where it is significant, and is examined in the outputs of some
Packit 6c4009
   functions.
Packit 6c4009
Packit 6c4009
   Inline functions: Inlining functions should give an improvement in
Packit 6c4009
   speed - but not in precission.  The inlined functions return
Packit 6c4009
   reasonable values for a reasonable range of input values.  The
Packit 6c4009
   result is not necessarily correct for all values and exceptions are
Packit 6c4009
   not correctly raised in all cases.  Problematic input and return
Packit 6c4009
   values are infinity, not-a-number and minus zero.  This suite
Packit 6c4009
   therefore does not check these specific inputs and the exception
Packit 6c4009
   handling for inlined mathematical functions - just the "reasonable"
Packit 6c4009
   values are checked.
Packit 6c4009
Packit 6c4009
   Beware: The tests might fail for any of the following reasons:
Packit 6c4009
   - Tests are wrong
Packit 6c4009
   - Functions are wrong
Packit 6c4009
   - Floating Point Unit not working properly
Packit 6c4009
   - Compiler has errors
Packit 6c4009
Packit 6c4009
   With e.g. gcc 2.7.2.2 the test for cexp fails because of a compiler error.
Packit 6c4009
Packit 6c4009
Packit 6c4009
   To Do: All parameter should be numbers that can be represented as
Packit 6c4009
   exact floating point values.  Currently some values cannot be
Packit 6c4009
   represented exactly and therefore the result is not the expected
Packit 6c4009
   result.  For this we will use 36 digits so that numbers can be
Packit 6c4009
   represented exactly.  */
Packit 6c4009
Packit 6c4009
#include "libm-test-support.h"
Packit 6c4009
Packit 6c4009
#include <argp.h>
Packit 6c4009
#include <errno.h>
Packit 6c4009
#include <string.h>
Packit 6c4009
Packit 6c4009
/* This header defines func_ulps, func_real_ulps and func_imag_ulps
Packit 6c4009
   arrays.  */
Packit 6c4009
#include "libm-test-ulps.h"
Packit 6c4009
Packit 6c4009
/* Maximum character buffer to store a stringitized FLOAT value.  */
Packit 6c4009
#define FSTR_MAX (128)
Packit 6c4009
Packit 6c4009
#define ulps_file_name "ULPs"	/* Name of the ULPs file.  */
Packit 6c4009
static FILE *ulps_file;		/* File to document difference.  */
Packit 6c4009
static int output_ulps;		/* Should ulps printed?  */
Packit 6c4009
static char *output_dir;	/* Directory where generated files will be written.  */
Packit 6c4009
Packit 6c4009
static int noErrors;	/* number of errors */
Packit 6c4009
static int noTests;	/* number of tests (without testing exceptions) */
Packit 6c4009
static int noExcTests;	/* number of tests for exception flags */
Packit 6c4009
static int noErrnoTests;/* number of tests for errno values */
Packit 6c4009
Packit 6c4009
static int verbose;
Packit 6c4009
static int output_max_error;	/* Should the maximal errors printed?  */
Packit 6c4009
static int output_points;	/* Should the single function results printed?  */
Packit 6c4009
static int ignore_max_ulp;	/* Should we ignore max_ulp?  */
Packit 6c4009
static int test_ibm128;		/* Is argument or result IBM long double?  */
Packit 6c4009
Packit 6c4009
static FLOAT max_error, real_max_error, imag_max_error;
Packit 6c4009
Packit 6c4009
static FLOAT prev_max_error, prev_real_max_error, prev_imag_max_error;
Packit 6c4009
Packit 6c4009
static FLOAT max_valid_error;
Packit 6c4009
Packit 6c4009
/* Sufficient numbers of digits to represent any floating-point value
Packit 6c4009
   unambiguously (for any choice of the number of bits in the first
Packit 6c4009
   hex digit, in the case of TYPE_HEX_DIG).  When used with printf
Packit 6c4009
   formats where the precision counts only digits after the point, 1
Packit 6c4009
   is subtracted from these values. */
Packit 6c4009
#define TYPE_DECIMAL_DIG __CONCATX (PREFIX, _DECIMAL_DIG)
Packit 6c4009
#define TYPE_HEX_DIG ((MANT_DIG + 6) / 4)
Packit 6c4009
Packit 6c4009
/* Converts VALUE (a floating-point number) to string and writes it to DEST.
Packit 6c4009
   PRECISION specifies the number of fractional digits that should be printed.
Packit 6c4009
   CONVERSION is the conversion specifier, such as in printf, e.g. 'f' or 'a'.
Packit 6c4009
   The output is prepended with an empty space if VALUE is non-negative.  */
Packit 6c4009
static void
Packit 6c4009
fmt_ftostr (char *dest, size_t size, int precision, const char *conversion,
Packit 6c4009
	    FLOAT value)
Packit 6c4009
{
Packit 6c4009
  char format[64];
Packit 6c4009
  char *ptr_format;
Packit 6c4009
  int ret;
Packit 6c4009
Packit 6c4009
  /* Generate the format string.  */
Packit 6c4009
  ptr_format = stpcpy (format, "%.");
Packit 6c4009
  ret = sprintf (ptr_format, "%d", precision);
Packit 6c4009
  ptr_format += ret;
Packit 6c4009
  ptr_format = stpcpy (ptr_format, conversion);
Packit 6c4009
Packit 6c4009
  /* Add a space to the beginning of the output string, if the floating-point
Packit 6c4009
     number is non-negative.  This mimics the behavior of the space (' ') flag
Packit 6c4009
     in snprintf, which is not available on strfrom.  */
Packit 6c4009
  if (! signbit (value))
Packit 6c4009
    {
Packit 6c4009
      *dest = ' ';
Packit 6c4009
      dest++;
Packit 6c4009
      size--;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Call the float to string conversion function, e.g.: strfromd.  */
Packit 6c4009
  FTOSTR (dest, size, format, value);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Compare KEY (a string, with the name of a function) with ULP (a
Packit 6c4009
   pointer to a struct ulp_data structure), returning a value less
Packit 6c4009
   than, equal to or greater than zero for use in bsearch.  */
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
compare_ulp_data (const void *key, const void *ulp)
Packit 6c4009
{
Packit 6c4009
  const char *keystr = key;
Packit 6c4009
  const struct ulp_data *ulpdat = ulp;
Packit 6c4009
  return strcmp (keystr, ulpdat->name);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static const int ulp_i_idx = ULP_I_IDX;
Packit 6c4009
static const int ulp_idx = ULP_IDX;
Packit 6c4009
Packit 6c4009
/* Return the ulps for NAME in array DATA with NMEMB elements, or 0 if
Packit 6c4009
   no ulps listed.  */
Packit 6c4009
Packit 6c4009
static FLOAT
Packit 6c4009
find_ulps (const char *name, const struct ulp_data *data, size_t nmemb)
Packit 6c4009
{
Packit 6c4009
  const struct ulp_data *entry = bsearch (name, data, nmemb, sizeof (*data),
Packit 6c4009
					  compare_ulp_data);
Packit 6c4009
  if (entry == NULL)
Packit 6c4009
    return 0;
Packit 6c4009
  else
Packit 6c4009
    return entry->max_ulp[(flag_test_inline ? ulp_i_idx : ulp_idx)];
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
init_max_error (const char *name, int exact, int testing_ibm128)
Packit 6c4009
{
Packit 6c4009
  max_error = 0;
Packit 6c4009
  real_max_error = 0;
Packit 6c4009
  imag_max_error = 0;
Packit 6c4009
  test_ibm128 = testing_ibm128;
Packit 6c4009
  prev_max_error = find_ulps (name, func_ulps,
Packit 6c4009
			      sizeof (func_ulps) / sizeof (func_ulps[0]));
Packit 6c4009
  prev_real_max_error = find_ulps (name, func_real_ulps,
Packit 6c4009
				   (sizeof (func_real_ulps)
Packit 6c4009
				    / sizeof (func_real_ulps[0])));
Packit 6c4009
  prev_imag_max_error = find_ulps (name, func_imag_ulps,
Packit 6c4009
				   (sizeof (func_imag_ulps)
Packit 6c4009
				    / sizeof (func_imag_ulps[0])));
Packit 6c4009
  if (testing_ibm128)
Packit 6c4009
    /* The documented accuracy of IBM long double division is 3ulp
Packit 6c4009
       (see libgcc/config/rs6000/ibm-ldouble-format), so do not
Packit 6c4009
       require better accuracy for libm functions that are exactly
Packit 6c4009
       defined for other formats.  */
Packit 6c4009
    max_valid_error = exact ? 3 : 16;
Packit 6c4009
  else
Packit 6c4009
    max_valid_error = exact ? 0 : 9;
Packit 6c4009
  prev_max_error = (prev_max_error <= max_valid_error
Packit 6c4009
		    ? prev_max_error
Packit 6c4009
		    : max_valid_error);
Packit 6c4009
  prev_real_max_error = (prev_real_max_error <= max_valid_error
Packit 6c4009
			 ? prev_real_max_error
Packit 6c4009
			 : max_valid_error);
Packit 6c4009
  prev_imag_max_error = (prev_imag_max_error <= max_valid_error
Packit 6c4009
			 ? prev_imag_max_error
Packit 6c4009
			 : max_valid_error);
Packit 6c4009
  feclearexcept (FE_ALL_EXCEPT);
Packit 6c4009
  errno = 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
set_max_error (FLOAT current, FLOAT *curr_max_error)
Packit 6c4009
{
Packit 6c4009
  if (current > *curr_max_error && current <= max_valid_error)
Packit 6c4009
    *curr_max_error = current;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Print a FLOAT.  */
Packit 6c4009
static void
Packit 6c4009
print_float (FLOAT f)
Packit 6c4009
{
Packit 6c4009
  /* As printf doesn't differ between a sNaN and a qNaN, do this manually.  */
Packit 6c4009
  if (issignaling (f))
Packit 6c4009
    printf ("sNaN\n");
Packit 6c4009
  else if (isnan (f))
Packit 6c4009
    printf ("qNaN\n");
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      char fstrn[FSTR_MAX], fstrx[FSTR_MAX];
Packit 6c4009
      fmt_ftostr (fstrn, FSTR_MAX, TYPE_DECIMAL_DIG - 1, "e", f);
Packit 6c4009
      fmt_ftostr (fstrx, FSTR_MAX, TYPE_HEX_DIG - 1, "a", f);
Packit 6c4009
      printf ("%s  %s\n", fstrn, fstrx);
Packit 6c4009
    }
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Should the message print to screen?  This depends on the verbose flag,
Packit 6c4009
   and the test status.  */
Packit 6c4009
static int
Packit 6c4009
print_screen (int ok)
Packit 6c4009
{
Packit 6c4009
  if (output_points
Packit 6c4009
      && (verbose > 1
Packit 6c4009
	  || (verbose == 1 && ok == 0)))
Packit 6c4009
    return 1;
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Should the message print to screen?  This depends on the verbose flag,
Packit 6c4009
   and the test status.  */
Packit 6c4009
static int
Packit 6c4009
print_screen_max_error (int ok)
Packit 6c4009
{
Packit 6c4009
  if (output_max_error
Packit 6c4009
      && (verbose > 1
Packit 6c4009
	  || ((verbose == 1) && (ok == 0))))
Packit 6c4009
    return 1;
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Update statistic counters.  */
Packit 6c4009
static void
Packit 6c4009
update_stats (int ok)
Packit 6c4009
{
Packit 6c4009
  ++noTests;
Packit 6c4009
  if (!ok)
Packit 6c4009
    ++noErrors;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
print_function_ulps (const char *function_name, FLOAT ulp)
Packit 6c4009
{
Packit 6c4009
  if (output_ulps)
Packit 6c4009
    {
Packit 6c4009
      char ustrn[FSTR_MAX];
Packit 6c4009
      FTOSTR (ustrn, FSTR_MAX, "%.0f", FUNC (ceil) (ulp));
Packit 6c4009
      fprintf (ulps_file, "Function: \"%s\":\n", function_name);
Packit 6c4009
      fprintf (ulps_file, "%s: %s\n", qtype_str, ustrn);
Packit 6c4009
    }
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
print_complex_function_ulps (const char *function_name, FLOAT real_ulp,
Packit 6c4009
			     FLOAT imag_ulp)
Packit 6c4009
{
Packit 6c4009
  if (output_ulps)
Packit 6c4009
    {
Packit 6c4009
      char fstrn[FSTR_MAX];
Packit 6c4009
      if (real_ulp != 0.0)
Packit 6c4009
	{
Packit 6c4009
	  FTOSTR (fstrn, FSTR_MAX, "%.0f", FUNC (ceil) (real_ulp));
Packit 6c4009
	  fprintf (ulps_file, "Function: Real part of \"%s\":\n", function_name);
Packit 6c4009
	  fprintf (ulps_file, "%s: %s\n", qtype_str, fstrn);
Packit 6c4009
	}
Packit 6c4009
      if (imag_ulp != 0.0)
Packit 6c4009
	{
Packit 6c4009
	  FTOSTR (fstrn, FSTR_MAX, "%.0f", FUNC (ceil) (imag_ulp));
Packit 6c4009
	  fprintf (ulps_file, "Function: Imaginary part of \"%s\":\n", function_name);
Packit 6c4009
	  fprintf (ulps_file, "%s: %s\n", qtype_str, fstrn);
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
Packit 6c4009
    }
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Test if Floating-Point stack hasn't changed */
Packit 6c4009
static void
Packit 6c4009
fpstack_test (const char *test_name)
Packit 6c4009
{
Packit 6c4009
#if defined (__i386__) || defined (__x86_64__)
Packit 6c4009
  static int old_stack;
Packit 6c4009
  int sw;
Packit 6c4009
Packit 6c4009
  asm ("fnstsw" : "=a" (sw));
Packit 6c4009
  sw >>= 11;
Packit 6c4009
  sw &= 7;
Packit 6c4009
Packit 6c4009
  if (sw != old_stack)
Packit 6c4009
    {
Packit 6c4009
      printf ("FP-Stack wrong after test %s (%d, should be %d)\n",
Packit 6c4009
	      test_name, sw, old_stack);
Packit 6c4009
      ++noErrors;
Packit 6c4009
      old_stack = sw;
Packit 6c4009
    }
Packit 6c4009
#endif
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
print_max_error (const char *func_name)
Packit 6c4009
{
Packit 6c4009
  int ok = 0;
Packit 6c4009
Packit 6c4009
  if (max_error == 0.0 || (max_error <= prev_max_error && !ignore_max_ulp))
Packit 6c4009
    {
Packit 6c4009
      ok = 1;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (!ok)
Packit 6c4009
    print_function_ulps (func_name, max_error);
Packit 6c4009
Packit 6c4009
Packit 6c4009
  if (print_screen_max_error (ok))
Packit 6c4009
    {
Packit 6c4009
      char mestr[FSTR_MAX], pmestr[FSTR_MAX];
Packit 6c4009
      FTOSTR (mestr, FSTR_MAX, "%.0f", FUNC (ceil) (max_error));
Packit 6c4009
      FTOSTR (pmestr, FSTR_MAX, "%.0f", FUNC (ceil) (prev_max_error));
Packit 6c4009
      printf ("Maximal error of `%s'\n", func_name);
Packit 6c4009
      printf (" is      : %s ulp\n", mestr);
Packit 6c4009
      printf (" accepted: %s ulp\n", pmestr);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  update_stats (ok);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
print_complex_max_error (const char *func_name)
Packit 6c4009
{
Packit 6c4009
  int real_ok = 0, imag_ok = 0, ok;
Packit 6c4009
Packit 6c4009
  if (real_max_error == 0
Packit 6c4009
      || (real_max_error <= prev_real_max_error && !ignore_max_ulp))
Packit 6c4009
    {
Packit 6c4009
      real_ok = 1;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (imag_max_error == 0
Packit 6c4009
      || (imag_max_error <= prev_imag_max_error && !ignore_max_ulp))
Packit 6c4009
    {
Packit 6c4009
      imag_ok = 1;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  ok = real_ok && imag_ok;
Packit 6c4009
Packit 6c4009
  if (!ok)
Packit 6c4009
    print_complex_function_ulps (func_name,
Packit 6c4009
				 real_ok ? 0 : real_max_error,
Packit 6c4009
				 imag_ok ? 0 : imag_max_error);
Packit 6c4009
Packit 6c4009
  if (print_screen_max_error (ok))
Packit 6c4009
    {
Packit 6c4009
      char rmestr[FSTR_MAX], prmestr[FSTR_MAX];
Packit 6c4009
      char imestr[FSTR_MAX], pimestr[FSTR_MAX];
Packit 6c4009
      FTOSTR (rmestr, FSTR_MAX, "%.0f", FUNC (ceil) (real_max_error));
Packit 6c4009
      FTOSTR (prmestr, FSTR_MAX, "%.0f", FUNC (ceil) (prev_real_max_error));
Packit 6c4009
      FTOSTR (imestr, FSTR_MAX, "%.0f", FUNC (ceil) (imag_max_error));
Packit 6c4009
      FTOSTR (pimestr, FSTR_MAX, "%.0f", FUNC (ceil) (prev_imag_max_error));
Packit 6c4009
      printf ("Maximal error of real part of: %s\n", func_name);
Packit 6c4009
      printf (" is      : %s ulp\n", rmestr);
Packit 6c4009
      printf (" accepted: %s ulp\n", prmestr);
Packit 6c4009
      printf ("Maximal error of imaginary part of: %s\n", func_name);
Packit 6c4009
      printf (" is      : %s ulp\n", imestr);
Packit 6c4009
      printf (" accepted: %s ulp\n", pimestr);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  update_stats (ok);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
#if FE_ALL_EXCEPT
Packit 6c4009
/* Test whether a given exception was raised.  */
Packit 6c4009
static void
Packit 6c4009
test_single_exception (const char *test_name,
Packit 6c4009
		       int exception,
Packit 6c4009
		       int exc_flag,
Packit 6c4009
		       int fe_flag,
Packit 6c4009
		       const char *flag_name)
Packit 6c4009
{
Packit 6c4009
  int ok = 1;
Packit 6c4009
  if (exception & exc_flag)
Packit 6c4009
    {
Packit 6c4009
      if (fetestexcept (fe_flag))
Packit 6c4009
	{
Packit 6c4009
	  if (print_screen (1))
Packit 6c4009
	    printf ("Pass: %s: Exception \"%s\" set\n", test_name, flag_name);
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	{
Packit 6c4009
	  ok = 0;
Packit 6c4009
	  if (print_screen (0))
Packit 6c4009
	    printf ("Failure: %s: Exception \"%s\" not set\n",
Packit 6c4009
		    test_name, flag_name);
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      if (fetestexcept (fe_flag))
Packit 6c4009
	{
Packit 6c4009
	  ok = 0;
Packit 6c4009
	  if (print_screen (0))
Packit 6c4009
	    printf ("Failure: %s: Exception \"%s\" set\n",
Packit 6c4009
		    test_name, flag_name);
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	{
Packit 6c4009
	  if (print_screen (1))
Packit 6c4009
	    printf ("%s: Exception \"%s\" not set\n", test_name,
Packit 6c4009
		    flag_name);
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
  if (!ok)
Packit 6c4009
    ++noErrors;
Packit 6c4009
}
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* Test whether exceptions given by EXCEPTION are raised.  Ignore thereby
Packit 6c4009
   allowed but not required exceptions.
Packit 6c4009
*/
Packit 6c4009
static void
Packit 6c4009
test_exceptions (const char *test_name, int exception)
Packit 6c4009
{
Packit 6c4009
  if (flag_test_exceptions && EXCEPTION_TESTS (FLOAT))
Packit 6c4009
    {
Packit 6c4009
      ++noExcTests;
Packit 6c4009
#ifdef FE_DIVBYZERO
Packit 6c4009
      if ((exception & DIVIDE_BY_ZERO_EXCEPTION_OK) == 0)
Packit 6c4009
	test_single_exception (test_name, exception,
Packit 6c4009
			       DIVIDE_BY_ZERO_EXCEPTION, FE_DIVBYZERO,
Packit 6c4009
			       "Divide by zero");
Packit 6c4009
#endif
Packit 6c4009
#ifdef FE_INVALID
Packit 6c4009
      if ((exception & INVALID_EXCEPTION_OK) == 0)
Packit 6c4009
	test_single_exception (test_name, exception,
Packit 6c4009
			       INVALID_EXCEPTION, FE_INVALID,
Packit 6c4009
			       "Invalid operation");
Packit 6c4009
#endif
Packit 6c4009
#ifdef FE_OVERFLOW
Packit 6c4009
      if ((exception & OVERFLOW_EXCEPTION_OK) == 0)
Packit 6c4009
	test_single_exception (test_name, exception, OVERFLOW_EXCEPTION,
Packit 6c4009
			       FE_OVERFLOW, "Overflow");
Packit 6c4009
#endif
Packit 6c4009
      /* Spurious "underflow" and "inexact" exceptions are always
Packit 6c4009
	 allowed for IBM long double, in line with the underlying
Packit 6c4009
	 arithmetic.  */
Packit 6c4009
#ifdef FE_UNDERFLOW
Packit 6c4009
      if ((exception & UNDERFLOW_EXCEPTION_OK) == 0
Packit 6c4009
	  && !(test_ibm128
Packit 6c4009
	       && (exception & UNDERFLOW_EXCEPTION) == 0))
Packit 6c4009
	test_single_exception (test_name, exception, UNDERFLOW_EXCEPTION,
Packit 6c4009
			       FE_UNDERFLOW, "Underflow");
Packit 6c4009
#endif
Packit 6c4009
#ifdef FE_INEXACT
Packit 6c4009
      if ((exception & (INEXACT_EXCEPTION | NO_INEXACT_EXCEPTION)) != 0
Packit 6c4009
	  && !(test_ibm128
Packit 6c4009
	       && (exception & NO_INEXACT_EXCEPTION) != 0))
Packit 6c4009
	test_single_exception (test_name, exception, INEXACT_EXCEPTION,
Packit 6c4009
			       FE_INEXACT, "Inexact");
Packit 6c4009
#endif
Packit 6c4009
    }
Packit 6c4009
  feclearexcept (FE_ALL_EXCEPT);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Test whether errno for TEST_NAME, set to ERRNO_VALUE, has value
Packit 6c4009
   EXPECTED_VALUE (description EXPECTED_NAME).  */
Packit 6c4009
static void
Packit 6c4009
test_single_errno (const char *test_name, int errno_value,
Packit 6c4009
		   int expected_value, const char *expected_name)
Packit 6c4009
{
Packit 6c4009
  if (errno_value == expected_value)
Packit 6c4009
    {
Packit 6c4009
      if (print_screen (1))
Packit 6c4009
	printf ("Pass: %s: errno set to %d (%s)\n", test_name, errno_value,
Packit 6c4009
		expected_name);
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      ++noErrors;
Packit 6c4009
      if (print_screen (0))
Packit 6c4009
	printf ("Failure: %s: errno set to %d, expected %d (%s)\n",
Packit 6c4009
		test_name, errno_value, expected_value, expected_name);
Packit 6c4009
    }
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Test whether errno (value ERRNO_VALUE) has been for TEST_NAME set
Packit 6c4009
   as required by EXCEPTIONS.  */
Packit 6c4009
static void
Packit 6c4009
test_errno (const char *test_name, int errno_value, int exceptions)
Packit 6c4009
{
Packit 6c4009
  if (flag_test_errno)
Packit 6c4009
    {
Packit 6c4009
      ++noErrnoTests;
Packit 6c4009
      if (exceptions & ERRNO_UNCHANGED)
Packit 6c4009
	test_single_errno (test_name, errno_value, 0, "unchanged");
Packit 6c4009
      if (exceptions & ERRNO_EDOM)
Packit 6c4009
	test_single_errno (test_name, errno_value, EDOM, "EDOM");
Packit 6c4009
      if (exceptions & ERRNO_ERANGE)
Packit 6c4009
	test_single_errno (test_name, errno_value, ERANGE, "ERANGE");
Packit 6c4009
    }
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Returns the number of ulps that GIVEN is away from EXPECTED.  */
Packit 6c4009
#define ULPDIFF(given, expected) \
Packit 6c4009
	(FUNC(fabs) ((given) - (expected)) / ulp (expected))
Packit 6c4009
Packit 6c4009
/* Returns the size of an ulp for VALUE.  */
Packit 6c4009
static FLOAT
Packit 6c4009
ulp (FLOAT value)
Packit 6c4009
{
Packit 6c4009
  FLOAT ulp;
Packit 6c4009
Packit 6c4009
  switch (fpclassify (value))
Packit 6c4009
    {
Packit 6c4009
      case FP_ZERO:
Packit 6c4009
	/* We compute the distance to the next FP which is the same as the
Packit 6c4009
	   value of the smallest subnormal number. Previously we used
Packit 6c4009
	   2^-(MANT_DIG - 1) which is too large a value to be useful. Note that we
Packit 6c4009
	   can't use ilogb(0), since that isn't a valid thing to do. As a point
Packit 6c4009
	   of comparison Java's ulp returns the next normal value e.g.
Packit 6c4009
	   2^(1 - MAX_EXP) for ulp(0), but that is not what we want for
Packit 6c4009
	   glibc.  */
Packit 6c4009
	/* Fall through...  */
Packit 6c4009
      case FP_SUBNORMAL:
Packit 6c4009
        /* The next closest subnormal value is a constant distance away.  */
Packit 6c4009
	ulp = FUNC(ldexp) (1.0, MIN_EXP - MANT_DIG);
Packit 6c4009
	break;
Packit 6c4009
Packit 6c4009
      case FP_NORMAL:
Packit 6c4009
	ulp = FUNC(ldexp) (1.0, FUNC(ilogb) (value) - MANT_DIG + 1);
Packit 6c4009
	break;
Packit 6c4009
Packit 6c4009
      default:
Packit 6c4009
	/* It should never happen. */
Packit 6c4009
	abort ();
Packit 6c4009
	break;
Packit 6c4009
    }
Packit 6c4009
  return ulp;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
check_float_internal (const char *test_name, FLOAT computed, FLOAT expected,
Packit 6c4009
		      int exceptions,
Packit 6c4009
		      FLOAT *curr_max_error, FLOAT max_ulp)
Packit 6c4009
{
Packit 6c4009
  int ok = 0;
Packit 6c4009
  int print_diff = 0;
Packit 6c4009
  FLOAT diff = 0;
Packit 6c4009
  FLOAT ulps = 0;
Packit 6c4009
  int errno_value = errno;
Packit 6c4009
Packit 6c4009
  test_exceptions (test_name, exceptions);
Packit 6c4009
  test_errno (test_name, errno_value, exceptions);
Packit 6c4009
  if (exceptions & IGNORE_RESULT)
Packit 6c4009
    goto out;
Packit 6c4009
  if (issignaling (computed) && issignaling (expected))
Packit 6c4009
    {
Packit 6c4009
      if ((exceptions & TEST_NAN_SIGN) != 0
Packit 6c4009
	  && signbit (computed) != signbit (expected))
Packit 6c4009
	{
Packit 6c4009
	  ok = 0;
Packit 6c4009
	  printf ("signaling NaN has wrong sign.\n");
Packit 6c4009
	}
Packit 6c4009
      else if ((exceptions & TEST_NAN_PAYLOAD) != 0
Packit 6c4009
	       && (FUNC (getpayload) (&computed)
Packit 6c4009
		   != FUNC (getpayload) (&expected)))
Packit 6c4009
	{
Packit 6c4009
	  ok = 0;
Packit 6c4009
	  printf ("signaling NaN has wrong payload.\n");
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	ok = 1;
Packit 6c4009
    }
Packit 6c4009
  else if (issignaling (computed) || issignaling (expected))
Packit 6c4009
    ok = 0;
Packit 6c4009
  else if (isnan (computed) && isnan (expected))
Packit 6c4009
    {
Packit 6c4009
      if ((exceptions & TEST_NAN_SIGN) != 0
Packit 6c4009
	  && signbit (computed) != signbit (expected))
Packit 6c4009
	{
Packit 6c4009
	  ok = 0;
Packit 6c4009
	  printf ("quiet NaN has wrong sign.\n");
Packit 6c4009
	}
Packit 6c4009
      else if ((exceptions & TEST_NAN_PAYLOAD) != 0
Packit 6c4009
	       && (FUNC (getpayload) (&computed)
Packit 6c4009
		   != FUNC (getpayload) (&expected)))
Packit 6c4009
	{
Packit 6c4009
	  ok = 0;
Packit 6c4009
	  printf ("quiet NaN has wrong payload.\n");
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	ok = 1;
Packit 6c4009
    }
Packit 6c4009
  else if (isinf (computed) && isinf (expected))
Packit 6c4009
    {
Packit 6c4009
      /* Test for sign of infinities.  */
Packit 6c4009
      if ((exceptions & IGNORE_ZERO_INF_SIGN) == 0
Packit 6c4009
	  && signbit (computed) != signbit (expected))
Packit 6c4009
	{
Packit 6c4009
	  ok = 0;
Packit 6c4009
	  printf ("infinity has wrong sign.\n");
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	ok = 1;
Packit 6c4009
    }
Packit 6c4009
  /* Don't calculate ULPs for infinities or any kind of NaNs.  */
Packit 6c4009
  else if (isinf (computed) || isnan (computed)
Packit 6c4009
	   || isinf (expected) || isnan (expected))
Packit 6c4009
    ok = 0;
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      diff = FUNC(fabs) (computed - expected);
Packit 6c4009
      ulps = ULPDIFF (computed, expected);
Packit 6c4009
      set_max_error (ulps, curr_max_error);
Packit 6c4009
      print_diff = 1;
Packit 6c4009
      if ((exceptions & IGNORE_ZERO_INF_SIGN) == 0
Packit 6c4009
	  && computed == 0.0 && expected == 0.0
Packit 6c4009
	  && signbit(computed) != signbit (expected))
Packit 6c4009
	ok = 0;
Packit 6c4009
      else if (ulps <= max_ulp && !ignore_max_ulp)
Packit 6c4009
	ok = 1;
Packit 6c4009
      else
Packit 6c4009
	ok = 0;
Packit 6c4009
    }
Packit 6c4009
  if (print_screen (ok))
Packit 6c4009
    {
Packit 6c4009
      if (!ok)
Packit 6c4009
	printf ("Failure: ");
Packit 6c4009
      printf ("Test: %s\n", test_name);
Packit 6c4009
      printf ("Result:\n");
Packit 6c4009
      printf (" is:         ");
Packit 6c4009
      print_float (computed);
Packit 6c4009
      printf (" should be:  ");
Packit 6c4009
      print_float (expected);
Packit 6c4009
      if (print_diff)
Packit 6c4009
	{
Packit 6c4009
	  char dstrn[FSTR_MAX], dstrx[FSTR_MAX];
Packit 6c4009
	  char ustrn[FSTR_MAX], mustrn[FSTR_MAX];
Packit 6c4009
	  fmt_ftostr (dstrn, FSTR_MAX, TYPE_DECIMAL_DIG - 1, "e", diff);
Packit 6c4009
	  fmt_ftostr (dstrx, FSTR_MAX, TYPE_HEX_DIG - 1, "a", diff);
Packit 6c4009
	  fmt_ftostr (ustrn, FSTR_MAX, 4, "f", ulps);
Packit 6c4009
	  fmt_ftostr (mustrn, FSTR_MAX, 4, "f", max_ulp);
Packit 6c4009
	  printf (" difference: %s  %s\n", dstrn, dstrx);
Packit 6c4009
	  printf (" ulp       : %s\n", ustrn);
Packit 6c4009
	  printf (" max.ulp   : %s\n", mustrn);
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
  update_stats (ok);
Packit 6c4009
Packit 6c4009
 out:
Packit 6c4009
  fpstack_test (test_name);
Packit 6c4009
  feclearexcept (FE_ALL_EXCEPT);
Packit 6c4009
  errno = 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
check_float (const char *test_name, FLOAT computed, FLOAT expected,
Packit 6c4009
	     int exceptions)
Packit 6c4009
{
Packit 6c4009
  check_float_internal (test_name, computed, expected,
Packit 6c4009
			exceptions, &max_error, prev_max_error);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
check_complex (const char *test_name, CFLOAT computed,
Packit 6c4009
	       CFLOAT expected,
Packit 6c4009
	       int exception)
Packit 6c4009
{
Packit 6c4009
  FLOAT part_comp, part_exp;
Packit 6c4009
  char *str;
Packit 6c4009
Packit 6c4009
  if (asprintf (&str, "Real part of: %s", test_name) == -1)
Packit 6c4009
    abort ();
Packit 6c4009
Packit 6c4009
  part_comp = __real__ computed;
Packit 6c4009
  part_exp = __real__ expected;
Packit 6c4009
Packit 6c4009
  check_float_internal (str, part_comp, part_exp,
Packit 6c4009
			exception, &real_max_error, prev_real_max_error);
Packit 6c4009
  free (str);
Packit 6c4009
Packit 6c4009
  if (asprintf (&str, "Imaginary part of: %s", test_name) == -1)
Packit 6c4009
    abort ();
Packit 6c4009
Packit 6c4009
  part_comp = __imag__ computed;
Packit 6c4009
  part_exp = __imag__ expected;
Packit 6c4009
Packit 6c4009
  /* Don't check again for exceptions or errno, just pass through the
Packit 6c4009
     other relevant flags.  */
Packit 6c4009
  check_float_internal (str, part_comp, part_exp,
Packit 6c4009
			exception & (IGNORE_ZERO_INF_SIGN
Packit 6c4009
				     | TEST_NAN_SIGN
Packit 6c4009
				     | IGNORE_RESULT),
Packit 6c4009
			&imag_max_error, prev_imag_max_error);
Packit 6c4009
  free (str);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Check that computed and expected values are equal (int values).  */
Packit 6c4009
void
Packit 6c4009
check_int (const char *test_name, int computed, int expected,
Packit 6c4009
	   int exceptions)
Packit 6c4009
{
Packit 6c4009
  int ok = 0;
Packit 6c4009
  int errno_value = errno;
Packit 6c4009
Packit 6c4009
  test_exceptions (test_name, exceptions);
Packit 6c4009
  test_errno (test_name, errno_value, exceptions);
Packit 6c4009
  if (exceptions & IGNORE_RESULT)
Packit 6c4009
    goto out;
Packit 6c4009
  noTests++;
Packit 6c4009
  if (computed == expected)
Packit 6c4009
    ok = 1;
Packit 6c4009
Packit 6c4009
  if (print_screen (ok))
Packit 6c4009
    {
Packit 6c4009
      if (!ok)
Packit 6c4009
	printf ("Failure: ");
Packit 6c4009
      printf ("Test: %s\n", test_name);
Packit 6c4009
      printf ("Result:\n");
Packit 6c4009
      printf (" is:         %d\n", computed);
Packit 6c4009
      printf (" should be:  %d\n", expected);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  update_stats (ok);
Packit 6c4009
 out:
Packit 6c4009
  fpstack_test (test_name);
Packit 6c4009
  feclearexcept (FE_ALL_EXCEPT);
Packit 6c4009
  errno = 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Check that computed and expected values are equal (long int values).  */
Packit 6c4009
void
Packit 6c4009
check_long (const char *test_name, long int computed, long int expected,
Packit 6c4009
	    int exceptions)
Packit 6c4009
{
Packit 6c4009
  int ok = 0;
Packit 6c4009
  int errno_value = errno;
Packit 6c4009
Packit 6c4009
  test_exceptions (test_name, exceptions);
Packit 6c4009
  test_errno (test_name, errno_value, exceptions);
Packit 6c4009
  if (exceptions & IGNORE_RESULT)
Packit 6c4009
    goto out;
Packit 6c4009
  noTests++;
Packit 6c4009
  if (computed == expected)
Packit 6c4009
    ok = 1;
Packit 6c4009
Packit 6c4009
  if (print_screen (ok))
Packit 6c4009
    {
Packit 6c4009
      if (!ok)
Packit 6c4009
	printf ("Failure: ");
Packit 6c4009
      printf ("Test: %s\n", test_name);
Packit 6c4009
      printf ("Result:\n");
Packit 6c4009
      printf (" is:         %ld\n", computed);
Packit 6c4009
      printf (" should be:  %ld\n", expected);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  update_stats (ok);
Packit 6c4009
 out:
Packit 6c4009
  fpstack_test (test_name);
Packit 6c4009
  feclearexcept (FE_ALL_EXCEPT);
Packit 6c4009
  errno = 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Check that computed value is true/false.  */
Packit 6c4009
void
Packit 6c4009
check_bool (const char *test_name, int computed, int expected,
Packit 6c4009
	    int exceptions)
Packit 6c4009
{
Packit 6c4009
  int ok = 0;
Packit 6c4009
  int errno_value = errno;
Packit 6c4009
Packit 6c4009
  test_exceptions (test_name, exceptions);
Packit 6c4009
  test_errno (test_name, errno_value, exceptions);
Packit 6c4009
  if (exceptions & IGNORE_RESULT)
Packit 6c4009
    goto out;
Packit 6c4009
  noTests++;
Packit 6c4009
  if ((computed == 0) == (expected == 0))
Packit 6c4009
    ok = 1;
Packit 6c4009
Packit 6c4009
  if (print_screen (ok))
Packit 6c4009
    {
Packit 6c4009
      if (!ok)
Packit 6c4009
	printf ("Failure: ");
Packit 6c4009
      printf ("Test: %s\n", test_name);
Packit 6c4009
      printf ("Result:\n");
Packit 6c4009
      printf (" is:         %d\n", computed);
Packit 6c4009
      printf (" should be:  %d\n", expected);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  update_stats (ok);
Packit 6c4009
 out:
Packit 6c4009
  fpstack_test (test_name);
Packit 6c4009
  feclearexcept (FE_ALL_EXCEPT);
Packit 6c4009
  errno = 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* check that computed and expected values are equal (long int values) */
Packit 6c4009
void
Packit 6c4009
check_longlong (const char *test_name, long long int computed,
Packit 6c4009
		long long int expected,
Packit 6c4009
		int exceptions)
Packit 6c4009
{
Packit 6c4009
  int ok = 0;
Packit 6c4009
  int errno_value = errno;
Packit 6c4009
Packit 6c4009
  test_exceptions (test_name, exceptions);
Packit 6c4009
  test_errno (test_name, errno_value, exceptions);
Packit 6c4009
  if (exceptions & IGNORE_RESULT)
Packit 6c4009
    goto out;
Packit 6c4009
  noTests++;
Packit 6c4009
  if (computed == expected)
Packit 6c4009
    ok = 1;
Packit 6c4009
Packit 6c4009
  if (print_screen (ok))
Packit 6c4009
    {
Packit 6c4009
      if (!ok)
Packit 6c4009
	printf ("Failure:");
Packit 6c4009
      printf ("Test: %s\n", test_name);
Packit 6c4009
      printf ("Result:\n");
Packit 6c4009
      printf (" is:         %lld\n", computed);
Packit 6c4009
      printf (" should be:  %lld\n", expected);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  update_stats (ok);
Packit 6c4009
 out:
Packit 6c4009
  fpstack_test (test_name);
Packit 6c4009
  feclearexcept (FE_ALL_EXCEPT);
Packit 6c4009
  errno = 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Check that computed and expected values are equal (intmax_t values).  */
Packit 6c4009
void
Packit 6c4009
check_intmax_t (const char *test_name, intmax_t computed,
Packit 6c4009
		intmax_t expected, int exceptions)
Packit 6c4009
{
Packit 6c4009
  int ok = 0;
Packit 6c4009
  int errno_value = errno;
Packit 6c4009
Packit 6c4009
  test_exceptions (test_name, exceptions);
Packit 6c4009
  test_errno (test_name, errno_value, exceptions);
Packit 6c4009
  if (exceptions & IGNORE_RESULT)
Packit 6c4009
    goto out;
Packit 6c4009
  noTests++;
Packit 6c4009
  if (computed == expected)
Packit 6c4009
    ok = 1;
Packit 6c4009
Packit 6c4009
  if (print_screen (ok))
Packit 6c4009
    {
Packit 6c4009
      if (!ok)
Packit 6c4009
	printf ("Failure:");
Packit 6c4009
      printf ("Test: %s\n", test_name);
Packit 6c4009
      printf ("Result:\n");
Packit 6c4009
      printf (" is:         %jd\n", computed);
Packit 6c4009
      printf (" should be:  %jd\n", expected);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  update_stats (ok);
Packit 6c4009
 out:
Packit 6c4009
  fpstack_test (test_name);
Packit 6c4009
  feclearexcept (FE_ALL_EXCEPT);
Packit 6c4009
  errno = 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Check that computed and expected values are equal (uintmax_t values).  */
Packit 6c4009
void
Packit 6c4009
check_uintmax_t (const char *test_name, uintmax_t computed,
Packit 6c4009
		 uintmax_t expected, int exceptions)
Packit 6c4009
{
Packit 6c4009
  int ok = 0;
Packit 6c4009
  int errno_value = errno;
Packit 6c4009
Packit 6c4009
  test_exceptions (test_name, exceptions);
Packit 6c4009
  test_errno (test_name, errno_value, exceptions);
Packit 6c4009
  if (exceptions & IGNORE_RESULT)
Packit 6c4009
    goto out;
Packit 6c4009
  noTests++;
Packit 6c4009
  if (computed == expected)
Packit 6c4009
    ok = 1;
Packit 6c4009
Packit 6c4009
  if (print_screen (ok))
Packit 6c4009
    {
Packit 6c4009
      if (!ok)
Packit 6c4009
	printf ("Failure:");
Packit 6c4009
      printf ("Test: %s\n", test_name);
Packit 6c4009
      printf ("Result:\n");
Packit 6c4009
      printf (" is:         %ju\n", computed);
Packit 6c4009
      printf (" should be:  %ju\n", expected);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  update_stats (ok);
Packit 6c4009
 out:
Packit 6c4009
  fpstack_test (test_name);
Packit 6c4009
  feclearexcept (FE_ALL_EXCEPT);
Packit 6c4009
  errno = 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Return whether a test with flags EXCEPTIONS should be run.  */
Packit 6c4009
int
Packit 6c4009
enable_test (int exceptions)
Packit 6c4009
{
Packit 6c4009
  if (exceptions & XFAIL_TEST)
Packit 6c4009
    return 0;
Packit 6c4009
  if (flag_test_inline && (exceptions & NO_TEST_INLINE))
Packit 6c4009
    return 0;
Packit 6c4009
  if (flag_test_finite && (exceptions & NON_FINITE) != 0)
Packit 6c4009
    return 0;
Packit 6c4009
  if ((!SNAN_TESTS (FLOAT) || !snan_tests_arg)
Packit 6c4009
      && (exceptions & TEST_SNAN) != 0)
Packit 6c4009
    return 0;
Packit 6c4009
  if (flag_test_mathvec && (exceptions & NO_TEST_MATHVEC) != 0)
Packit 6c4009
    return 0;
Packit 6c4009
Packit 6c4009
  return 1;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
initialize (void)
Packit 6c4009
{
Packit 6c4009
  fpstack_test ("start *init*");
Packit 6c4009
Packit 6c4009
  /* Clear all exceptions.  From now on we must not get random exceptions.  */
Packit 6c4009
  feclearexcept (FE_ALL_EXCEPT);
Packit 6c4009
  errno = 0;
Packit 6c4009
Packit 6c4009
  /* Test to make sure we start correctly.  */
Packit 6c4009
  fpstack_test ("end *init*");
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Definitions of arguments for argp functions.  */
Packit 6c4009
static const struct argp_option options[] =
Packit 6c4009
{
Packit 6c4009
  { "verbose", 'v', "NUMBER", 0, "Level of verbosity (0..3)"},
Packit 6c4009
  { "ulps-file", 'u', NULL, 0, "Output ulps to file ULPs"},
Packit 6c4009
  { "no-max-error", 'f', NULL, 0,
Packit 6c4009
    "Don't output maximal errors of functions"},
Packit 6c4009
  { "no-points", 'p', NULL, 0,
Packit 6c4009
    "Don't output results of functions invocations"},
Packit 6c4009
  { "ignore-max-ulp", 'i', "yes/no", 0,
Packit 6c4009
    "Ignore given maximal errors"},
Packit 6c4009
  { "output-dir", 'o', "DIR", 0,
Packit 6c4009
    "Directory where generated files will be placed"},
Packit 6c4009
  { NULL, 0, NULL, 0, NULL }
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
/* Prototype for option handler.  */
Packit 6c4009
static error_t parse_opt (int key, char *arg, struct argp_state *state);
Packit 6c4009
Packit 6c4009
/* Data structure to communicate with argp functions.  */
Packit 6c4009
static struct argp argp =
Packit 6c4009
{
Packit 6c4009
  options, parse_opt, NULL, doc,
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Handle program arguments.  */
Packit 6c4009
static error_t
Packit 6c4009
parse_opt (int key, char *arg, struct argp_state *state)
Packit 6c4009
{
Packit 6c4009
  switch (key)
Packit 6c4009
    {
Packit 6c4009
    case 'f':
Packit 6c4009
      output_max_error = 0;
Packit 6c4009
      break;
Packit 6c4009
    case 'i':
Packit 6c4009
      if (strcmp (arg, "yes") == 0)
Packit 6c4009
	ignore_max_ulp = 1;
Packit 6c4009
      else if (strcmp (arg, "no") == 0)
Packit 6c4009
	ignore_max_ulp = 0;
Packit 6c4009
      break;
Packit 6c4009
    case 'o':
Packit 6c4009
      output_dir = (char *) malloc (strlen (arg) + 1);
Packit 6c4009
      if (output_dir != NULL)
Packit 6c4009
	strcpy (output_dir, arg);
Packit 6c4009
      else
Packit 6c4009
        return errno;
Packit 6c4009
      break;
Packit 6c4009
    case 'p':
Packit 6c4009
      output_points = 0;
Packit 6c4009
      break;
Packit 6c4009
    case 'u':
Packit 6c4009
      output_ulps = 1;
Packit 6c4009
      break;
Packit 6c4009
    case 'v':
Packit 6c4009
      if (optarg)
Packit 6c4009
	verbose = (unsigned int) strtoul (optarg, NULL, 0);
Packit 6c4009
      else
Packit 6c4009
	verbose = 3;
Packit 6c4009
      break;
Packit 6c4009
    default:
Packit 6c4009
      return ARGP_ERR_UNKNOWN;
Packit 6c4009
    }
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Verify that our ulp () implementation is behaving as expected
Packit 6c4009
   or abort.  */
Packit 6c4009
static void
Packit 6c4009
check_ulp (void)
Packit 6c4009
{
Packit 6c4009
   FLOAT ulps, ulpx, value;
Packit 6c4009
   int i;
Packit 6c4009
   /* Check ulp of zero is a subnormal value...  */
Packit 6c4009
   ulps = ulp (0x0.0p0);
Packit 6c4009
   if (fpclassify (ulps) != FP_SUBNORMAL)
Packit 6c4009
     {
Packit 6c4009
       fprintf (stderr, "ulp (0x0.0p0) is not FP_SUBNORMAL!\n");
Packit 6c4009
       exit (EXIT_FAILURE);
Packit 6c4009
     }
Packit 6c4009
   /* Check that the ulp of one is a normal value... */
Packit 6c4009
   ulps = ulp (LIT(1.0));
Packit 6c4009
   if (fpclassify (ulps) != FP_NORMAL)
Packit 6c4009
     {
Packit 6c4009
       fprintf (stderr, "ulp (1.0L) is not FP_NORMAL\n");
Packit 6c4009
       exit (EXIT_FAILURE);
Packit 6c4009
     }
Packit 6c4009
Packit 6c4009
   /* Compute the next subnormal value using nextafter to validate ulp.
Packit 6c4009
      We allow +/- 1 ulp around the represented value.  */
Packit 6c4009
   value = FUNC(nextafter) (0, 1);
Packit 6c4009
   ulps = ULPDIFF (value, 0);
Packit 6c4009
   ulpx = ulp (LIT(1.0));
Packit 6c4009
   if (ulps < (LIT(1.0) - ulpx) || ulps > (LIT(1.0) + ulpx))
Packit 6c4009
     {
Packit 6c4009
       fprintf (stderr, "Value outside of 1 +/- 1ulp.\n");
Packit 6c4009
       exit (EXIT_FAILURE);
Packit 6c4009
     }
Packit 6c4009
   /* Compute the nearest representable number from 10 towards 20.
Packit 6c4009
      The result is 10 + 1ulp.  We use this to check the ulp function.
Packit 6c4009
      We allow +/- 1 ulp around the represented value.  */
Packit 6c4009
   value = FUNC(nextafter) (10, 20);
Packit 6c4009
   ulps = ULPDIFF (value, 10);
Packit 6c4009
   ulpx = ulp (LIT(1.0));
Packit 6c4009
   if (ulps < (LIT(1.0) - ulpx) || ulps > (LIT(1.0) + ulpx))
Packit 6c4009
     {
Packit 6c4009
       fprintf (stderr, "Value outside of 1 +/- 1ulp.\n");
Packit 6c4009
       exit (EXIT_FAILURE);
Packit 6c4009
     }
Packit 6c4009
   /* This gives one more ulp.  */
Packit 6c4009
   value = FUNC(nextafter) (value, 20);
Packit 6c4009
   ulps = ULPDIFF (value, 10);
Packit 6c4009
   ulpx = ulp (LIT(2.0));
Packit 6c4009
   if (ulps < (LIT(2.0) - ulpx) || ulps > (LIT(2.0) + ulpx))
Packit 6c4009
     {
Packit 6c4009
       fprintf (stderr, "Value outside of 2 +/- 1ulp.\n");
Packit 6c4009
       exit (EXIT_FAILURE);
Packit 6c4009
     }
Packit 6c4009
   /* And now calculate 100 ulp.  */
Packit 6c4009
   for (i = 2; i < 100; i++)
Packit 6c4009
     value = FUNC(nextafter) (value, 20);
Packit 6c4009
   ulps = ULPDIFF (value, 10);
Packit 6c4009
   ulpx = ulp (LIT(100.0));
Packit 6c4009
   if (ulps < (LIT(100.0) - ulpx) || ulps > (LIT(100.0) + ulpx))
Packit 6c4009
     {
Packit 6c4009
       fprintf (stderr, "Value outside of 100 +/- 1ulp.\n");
Packit 6c4009
       exit (EXIT_FAILURE);
Packit 6c4009
     }
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Do all initialization for a test run with arguments given by ARGC
Packit 6c4009
   and ARGV.  */
Packit 6c4009
void
Packit 6c4009
libm_test_init (int argc, char **argv)
Packit 6c4009
{
Packit 6c4009
  int remaining;
Packit 6c4009
  char *ulps_file_path;
Packit 6c4009
  size_t dir_len = 0;
Packit 6c4009
Packit 6c4009
  verbose = 1;
Packit 6c4009
  output_ulps = 0;
Packit 6c4009
  output_max_error = 1;
Packit 6c4009
  output_points = 1;
Packit 6c4009
  output_dir = NULL;
Packit 6c4009
  /* XXX set to 0 for releases.  */
Packit 6c4009
  ignore_max_ulp = 0;
Packit 6c4009
Packit 6c4009
  /* Parse and process arguments.  */
Packit 6c4009
  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
Packit 6c4009
Packit 6c4009
  if (remaining != argc)
Packit 6c4009
    {
Packit 6c4009
      fprintf (stderr, "wrong number of arguments");
Packit 6c4009
      argp_help (&argp, stdout, ARGP_HELP_SEE, program_invocation_short_name);
Packit 6c4009
      exit (EXIT_FAILURE);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (output_ulps)
Packit 6c4009
    {
Packit 6c4009
      if (output_dir != NULL)
Packit 6c4009
	dir_len = strlen (output_dir);
Packit 6c4009
      ulps_file_path = (char *) malloc (dir_len + strlen (ulps_file_name) + 1);
Packit 6c4009
      if (ulps_file_path == NULL)
Packit 6c4009
        {
Packit 6c4009
	  perror ("can't allocate path for `ULPs' file: ");
Packit 6c4009
	  exit (1);
Packit 6c4009
        }
Packit 6c4009
      sprintf (ulps_file_path, "%s%s", output_dir == NULL ? "" : output_dir, ulps_file_name);
Packit 6c4009
      ulps_file = fopen (ulps_file_path, "a");
Packit 6c4009
      if (ulps_file == NULL)
Packit 6c4009
	{
Packit 6c4009
	  perror ("can't open file `ULPs' for writing: ");
Packit 6c4009
	  exit (1);
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
Packit 6c4009
  initialize ();
Packit 6c4009
  fputs (test_msg, stdout);
Packit 6c4009
Packit 6c4009
  check_ulp ();
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Process the test results, returning the exit status.  */
Packit 6c4009
int
Packit 6c4009
libm_test_finish (void)
Packit 6c4009
{
Packit 6c4009
  if (output_ulps)
Packit 6c4009
    fclose (ulps_file);
Packit 6c4009
Packit 6c4009
  printf ("\nTest suite completed:\n");
Packit 6c4009
  printf ("  %d test cases plus %d tests for exception flags and\n"
Packit 6c4009
	  "    %d tests for errno executed.\n",
Packit 6c4009
	  noTests, noExcTests, noErrnoTests);
Packit 6c4009
  if (noErrors)
Packit 6c4009
    {
Packit 6c4009
      printf ("  %d errors occurred.\n", noErrors);
Packit 6c4009
      return 1;
Packit 6c4009
    }
Packit 6c4009
  printf ("  All tests passed successfully.\n");
Packit 6c4009
Packit 6c4009
  return 0;
Packit 6c4009
}