Make libm-test look up ulps by name at runtime.

This commit is contained in:
Joseph Myers 2013-05-18 12:10:59 +00:00
parent bb38759d6d
commit 3779b5b64a
3 changed files with 316 additions and 229 deletions

View File

@ -1,3 +1,93 @@
2013-05-18 Joseph Myers <joseph@codesourcery.com>
* math/gen-libm-test.pl (@tests): Remove variable.
($count): Likewise.
(new_test): Remove function.
(show_exceptions): New function.
(special_functions): Use show_exceptions instead of new_test.
(parse_args): Likewise.
(generate_testfile): Pass only function name in generated call to
print_max_error or print_complex_max_error.
(get_ulps): Do not handle complex tests specially.
(output_test): Rename to ...
(get_all_ulps_for_test): ... this. Return a string rather than
printing to a file. Require ulps to be present.
(output_ulps): Generate arrays rather than #defines.
* math/libm-test.inc: Move down #include of "libm-test-ulps.h".
(struct ulp_data): New type.
(BUILD_COMPLEX_ULP): Remove macro.
(compare_ulp_data): New function.
(find_ulps): Likewise.
(find_test_ulps): Likewise.
(find_function_ulps): Likewise.
(find_complex_function_ulps): Likewise.
(print_max_error): Determine allowed ulps using
find_function_ulps.
(print_complex_max_error): Determine allowed ulps using
find_complex_function_ulps.
(check_float_internal): Determine max ulps using find_test_ulps.
(check_float): Do not take max_ulp parameter. Update call to
check_float_internal.
(check_complex): Likewise.
(check_int): Do not take max_ulp parameter.
(check_long): Likewise.
(check_bool): Likewise.
(check_longlong): Likewise.
(struct test_f_f_data): Remove max_ulp field.
(struct test_ff_f_data): Likewise.
(struct test_ff_f_data_nexttoward): Likewise.
(struct test_fi_f_data): Likewise.
(struct test_fl_f_data): Likewise.
(struct test_if_f_data): Likewise.
(struct test_fff_f_data): Likewise.
(struct test_c_f_data): Likewise.
(struct test_f_f1_data): Remove max_ulp and extra_ulp fields.
(struct test_fF_f1_data): Likewise.
(struct test_ffI_f1_data): Likewise.
(struct test_c_c_data): Remove max_ulp field.
(struct test_cc_c_data): Likewise.
(struct test_f_i_data): Likewise.
(struct test_ff_i_data): Likewise.
(struct test_f_l_data): Likewise.
(struct test_f_L_data): Likewise.
(struct test_sincos_data): Likewise.
(RUN_TEST_f_f): Do not handle ulps.
(RUN_TEST_LOOP_f_f): Likewise.
(RUN_TEST_2_f): Likewise.
(RUN_TEST_LOOP_2_f): Likewise.
(RUN_TEST_fff_f): Likewise.
(RUN_TEST_LOOP_fff_f): Likewise.
(RUN_TEST_c_f): Likewise.
(RUN_TEST_LOOP_c_f): Likewise.
(RUN_TEST_f_f1): Likewise.
(RUN_TEST_LOOP_f_f1): Likewise.
(RUN_TEST_fF_f1): Likewise.
(RUN_TEST_LOOP_fF_f1): Likewise.
(RUN_TEST_fI_f1): Likewise.
(RUN_TEST_LOOP_fI_f1): Likewise.
(RUN_TEST_ffI_f1): Likewise.
(RUN_TEST_LOOP_ffI_f1): Likewise.
(RUN_TEST_c_c): Likewise.
(RUN_TEST_LOOP_c_c): Likewise.
(RUN_TEST_cc_c): Likewise.
(RUN_TEST_LOOP_cc_c): Likewise.
(RUN_TEST_f_i): Likewise.
(RUN_TEST_LOOP_f_i): Likewise.
(RUN_TEST_f_i_tg): Likewise.
(RUN_TEST_LOOP_f_i_tg): Likewise.
(RUN_TEST_ff_i_tg): Likewise.
(RUN_TEST_LOOP_ff_i_tg): Likewise.
(RUN_TEST_f_b): Likewise.
(RUN_TEST_LOOP_f_b): Likewise.
(RUN_TEST_f_b_tg): Likewise.
(RUN_TEST_LOOP_f_b_tg): Likewise.
(RUN_TEST_f_l): Likewise.
(RUN_TEST_LOOP_f_l): Likewise.
(RUN_TEST_f_L): Likewise.
(RUN_TEST_LOOP_f_L): Likewise.
(RUN_TEST_sincos): Likewise.
(RUN_TEST_LOOP_sincos): Likewise.
2013-05-17 Joseph Myers <joseph@codesourcery.com> 2013-05-17 Joseph Myers <joseph@codesourcery.com>
[BZ #15480] [BZ #15480]

View File

@ -41,8 +41,7 @@ use strict;
use vars qw ($input $output); use vars qw ($input $output);
use vars qw (%results); use vars qw (%results);
use vars qw (@tests @functions); use vars qw (@functions);
use vars qw ($count);
use vars qw (%beautify @all_floats); use vars qw (%beautify @all_floats);
use vars qw ($output_dir $ulps_file); use vars qw ($output_dir $ulps_file);
@ -103,8 +102,6 @@ $output_dir = $opt_o if ($opt_o);
$input = "libm-test.inc"; $input = "libm-test.inc";
$output = "${output_dir}libm-test.c"; $output = "${output_dir}libm-test.c";
$count = 0;
&parse_ulps ($ulps_file); &parse_ulps ($ulps_file);
&generate_testfile ($input, $output) unless ($opt_n); &generate_testfile ($input, $output) unless ($opt_n);
&output_ulps ("${output_dir}libm-test-ulps.h", $ulps_file) unless ($opt_n); &output_ulps ("${output_dir}libm-test-ulps.h", $ulps_file) unless ($opt_n);
@ -160,29 +157,15 @@ sub get_variable {
return "x$number"; return "x$number";
} }
# Add a new test to internal data structures and fill in the # Return the text to put in an initializer for a test's exception
# ulps and exception information for the C line. # information.
sub new_test { sub show_exceptions {
my ($test, $exception, $show_exception) = @_; my ($exception) = @_;
my $rest;
# Add ulp.
if (exists $results{$test}{'has_ulps'}) {
$rest = ", DELTA$count";
} else {
$rest = ', 0';
}
if ($show_exception) {
if (defined $exception) { if (defined $exception) {
$rest .= ", $exception"; return ", $exception";
} else { } else {
$rest .= ', 0'; return ', 0';
} }
}
# We must increment here to keep @tests and count in sync
push @tests, $test;
++$count;
return $rest;
} }
# Treat some functions especially. # Treat some functions especially.
@ -203,12 +186,11 @@ sub special_functions {
$test = $str . ' puts ' . &beautify ($args[2]) . ' in sin_res'; $test = $str . ' puts ' . &beautify ($args[2]) . ' in sin_res';
$cline .= ", \"$test\", $args[2]"; $cline .= ", \"$test\", $args[2]";
$cline .= &new_test ($test, $args[4], 0);
# handle cos # handle cos
$test = $str . ' puts ' . &beautify ($args[3]) . ' in cos_res'; $test = $str . ' puts ' . &beautify ($args[3]) . ' in cos_res';
$cline .= ", \"$test\", $args[3]"; $cline .= ", \"$test\", $args[3]";
$cline .= &new_test ($test, $args[4], 1); $cline .= show_exceptions ($args[4]);
$cline .= " },\n"; $cline .= " },\n";
print $file $cline; print $file $cline;
} }
@ -332,8 +314,10 @@ sub parse_args {
++$current_arg; ++$current_arg;
} }
} }
# Add ulp. # Add exceptions.
$cline .= &new_test ($str, ($current_arg <= $#args) ? $args[$current_arg] : undef, 1); $cline .= show_exceptions (($current_arg <= $#args)
? $args[$current_arg]
: undef);
# special treatment for some functions # special treatment for some functions
if ($args[0] eq 'frexp') { if ($args[0] eq 'frexp') {
@ -346,11 +330,6 @@ sub parse_args {
$extra_expected = "0"; $extra_expected = "0";
} }
$cline .= ", \"$str\", $run_extra, $extra_expected"; $cline .= ", \"$str\", $run_extra, $extra_expected";
if ($run_extra) {
$cline .= &new_test ($str, undef, 0);
} else {
$cline .= ", 0";
}
} }
} elsif ($args[0] eq 'gamma' || $args[0] eq 'lgamma') { } elsif ($args[0] eq 'gamma' || $args[0] eq 'lgamma') {
if (defined $special[0]) { if (defined $special[0]) {
@ -362,11 +341,6 @@ sub parse_args {
$extra_expected = "0"; $extra_expected = "0";
} }
$cline .= ", \"$str\", $run_extra, $extra_expected"; $cline .= ", \"$str\", $run_extra, $extra_expected";
if ($run_extra) {
$cline .= &new_test ($str, undef, 0);
} else {
$cline .= ", 0";
}
} }
} elsif ($args[0] eq 'modf') { } elsif ($args[0] eq 'modf') {
if (defined $special[0]) { if (defined $special[0]) {
@ -378,11 +352,6 @@ sub parse_args {
$extra_expected = "0"; $extra_expected = "0";
} }
$cline .= ", \"$str\", $run_extra, $extra_expected"; $cline .= ", \"$str\", $run_extra, $extra_expected";
if ($run_extra) {
$cline .= &new_test ($str, undef, 0);
} else {
$cline .= ", 0";
}
} }
} elsif ($args[0] eq 'remquo') { } elsif ($args[0] eq 'remquo') {
if (defined $special[0]) { if (defined $special[0]) {
@ -394,11 +363,6 @@ sub parse_args {
$extra_expected = "0"; $extra_expected = "0";
} }
$cline .= ", \"$str\", $run_extra, $extra_expected"; $cline .= ", \"$str\", $run_extra, $extra_expected";
if ($run_extra) {
$cline .= &new_test ($str, undef, 0);
} else {
$cline .= ", 0";
}
} }
} }
print $file " $cline },\n"; print $file " $cline },\n";
@ -450,16 +414,10 @@ sub generate_testfile {
} }
($fct) = ($_ =~ /END\s*\((.*)\)/); ($fct) = ($_ =~ /END\s*\((.*)\)/);
if ($type eq 'complex') { if ($type eq 'complex') {
$line = " print_complex_max_error (\"$fct\", "; $line = " print_complex_max_error (\"$fct\");\n";
} else { } else {
$line = " print_max_error (\"$fct\", "; $line = " print_max_error (\"$fct\");\n";
} }
if (exists $results{$fct}{'has_ulps'}) {
$line .= "DELTA$fct";
} else {
$line .= '0';
}
$line .= ");\n";
print OUTPUT $line; print OUTPUT $line;
push @functions, $fct; push @functions, $fct;
next; next;
@ -620,37 +578,15 @@ sub print_ulps_file {
sub get_ulps { sub get_ulps {
my ($test, $type, $float) = @_; my ($test, $type, $float) = @_;
if ($type eq 'complex') { return (exists $results{$test}{$type}{'ulp'}{$float}
my ($res); ? $results{$test}{$type}{'ulp'}{$float} : "0");
# Return 0 instead of BUILD_COMPLEX_ULP (0,0)
if (!exists $results{$test}{'real'}{'ulp'}{$float} &&
!exists $results{$test}{'imag'}{'ulp'}{$float}) {
return "0";
}
$res = 'BUILD_COMPLEX_ULP (';
$res .= (exists $results{$test}{'real'}{'ulp'}{$float}
? $results{$test}{'real'}{'ulp'}{$float} : "0");
$res .= ', ';
$res .= (exists $results{$test}{'imag'}{'ulp'}{$float}
? $results{$test}{'imag'}{'ulp'}{$float} : "0");
$res .= ')';
return $res;
}
return (exists $results{$test}{'normal'}{'ulp'}{$float}
? $results{$test}{'normal'}{'ulp'}{$float} : "0");
} }
# Output the defines for a single test # Return the ulps value for a single test.
sub output_test { sub get_all_ulps_for_test {
my ($file, $test, $name) = @_; my ($test, $type) = @_;
my ($ldouble, $double, $float, $ildouble, $idouble, $ifloat); my ($ldouble, $double, $float, $ildouble, $idouble, $ifloat);
my ($type);
# Do we have ulps?
if (!exists $results{$test}{'type'}) {
return;
}
$type = $results{$test}{'type'};
if (exists $results{$test}{'has_ulps'}) { if (exists $results{$test}{'has_ulps'}) {
# XXX use all_floats (change order!) # XXX use all_floats (change order!)
$ldouble = &get_ulps ($test, $type, "ldouble"); $ldouble = &get_ulps ($test, $type, "ldouble");
@ -659,14 +595,17 @@ sub output_test {
$ildouble = &get_ulps ($test, $type, "ildouble"); $ildouble = &get_ulps ($test, $type, "ildouble");
$idouble = &get_ulps ($test, $type, "idouble"); $idouble = &get_ulps ($test, $type, "idouble");
$ifloat = &get_ulps ($test, $type, "ifloat"); $ifloat = &get_ulps ($test, $type, "ifloat");
print $file "#define DELTA$name CHOOSE($ldouble, $double, $float, $ildouble, $idouble, $ifloat)\t/* $test */\n"; return "CHOOSE ($ldouble, $double, $float, $ildouble, $idouble, $ifloat)";
} else {
die "get_all_ulps_for_test called for \"$test\" with no ulps\n";
} }
} }
# Print include file # Print include file
sub output_ulps { sub output_ulps {
my ($file, $ulps_filename) = @_; my ($file, $ulps_filename) = @_;
my ($i, $fct); my ($i, $fct, $type, $ulp, $ulp_real, $ulp_imag);
my (%test_ulps, %func_ulps, %func_real_ulps, %func_imag_ulps);
open ULP, ">$file" or die ("Can't open $file: $!"); open ULP, ">$file" or die ("Can't open $file: $!");
@ -674,14 +613,56 @@ sub output_ulps {
print ULP " from $ulps_filename with gen-libm-test.pl.\n"; print ULP " from $ulps_filename with gen-libm-test.pl.\n";
print ULP " Don't change it - change instead the master files. */\n\n"; print ULP " Don't change it - change instead the master files. */\n\n";
print ULP "\n/* Maximal error of functions. */\n"; foreach $fct (keys %results) {
foreach $fct (@functions) { $type = $results{$fct}{'type'};
output_test (\*ULP, $fct, $fct); if ($type eq 'normal') {
$ulp = get_all_ulps_for_test ($fct, 'normal');
} elsif ($type eq 'complex') {
$ulp_real = get_all_ulps_for_test ($fct, 'real');
$ulp_imag = get_all_ulps_for_test ($fct, 'imag');
} else {
die "unknown results ($fct) type $type\n";
} }
if ($results{$fct}{'kind'} eq 'fct') {
if ($type eq 'normal') {
$func_ulps{$fct} = $ulp;
} else {
$func_real_ulps{$fct} = $ulp_real;
$func_imag_ulps{$fct} = $ulp_imag;
}
} elsif ($results{$fct}{'kind'} eq 'test') {
if ($type eq 'normal') {
$test_ulps{$fct} = $ulp;
} else {
$test_ulps{"Real part of: $fct"} = $ulp_real;
$test_ulps{"Imaginary part of: $fct"} = $ulp_imag;
}
} else {
die "unknown results ($fct) kind $results{$fct}{'kind'}\n";
}
}
print ULP "\n/* Maximal error of functions. */\n";
print ULP "static const struct ulp_data func_ulps[] =\n {\n";
foreach $fct (sort keys %func_ulps) {
print ULP " { \"$fct\", $func_ulps{$fct} },\n";
}
print ULP " };\n";
print ULP "static const struct ulp_data func_real_ulps[] =\n {\n";
foreach $fct (sort keys %func_real_ulps) {
print ULP " { \"$fct\", $func_real_ulps{$fct} },\n";
}
print ULP " };\n";
print ULP "static const struct ulp_data func_imag_ulps[] =\n {\n";
foreach $fct (sort keys %func_imag_ulps) {
print ULP " { \"$fct\", $func_imag_ulps{$fct} },\n";
}
print ULP " };\n";
print ULP "\n/* Error of single function calls. */\n"; print ULP "\n/* Error of single function calls. */\n";
for ($i = 0; $i < $count; $i++) { print ULP "static const struct ulp_data test_ulps[] =\n {\n";
output_test (\*ULP, $tests[$i], $i); foreach $fct (sort keys %test_ulps) {
print ULP " { \"$fct\", $test_ulps{$fct} },\n";
} }
print ULP " };\n";
close ULP; close ULP;
} }

View File

@ -115,7 +115,6 @@
# define _GNU_SOURCE # define _GNU_SOURCE
#endif #endif
#include "libm-test-ulps.h"
#include <complex.h> #include <complex.h>
#include <math.h> #include <math.h>
#include <float.h> #include <float.h>
@ -129,6 +128,18 @@
#include <argp.h> #include <argp.h>
#include <tininess.h> #include <tininess.h>
/* Structure for ulp data for a test, a function, or the real or
imaginary part of a function. */
struct ulp_data
{
const char *name;
FLOAT max_ulp;
};
/* This header defines test_ulps, func_ulps, func_real_ulps and
func_imag_ulps arrays. */
#include "libm-test-ulps.h"
/* Allow platforms without all rounding modes to test properly, /* Allow platforms without all rounding modes to test properly,
assuming they provide an __FE_UNDEFINED in <bits/fenv.h> which assuming they provide an __FE_UNDEFINED in <bits/fenv.h> which
causes fesetround() to return failure. */ causes fesetround() to return failure. */
@ -257,11 +268,68 @@ static FLOAT max_error, real_max_error, imag_max_error;
__real__ __retval = (real); \ __real__ __retval = (real); \
__imag__ __retval = (imag); \ __imag__ __retval = (imag); \
__retval; }) __retval; })
#define BUILD_COMPLEX_ULP(real, imag) ((real) + I * (imag))
#define MANT_DIG CHOOSE ((LDBL_MANT_DIG-1), (DBL_MANT_DIG-1), (FLT_MANT_DIG-1), \ #define MANT_DIG CHOOSE ((LDBL_MANT_DIG-1), (DBL_MANT_DIG-1), (FLT_MANT_DIG-1), \
(LDBL_MANT_DIG-1), (DBL_MANT_DIG-1), (FLT_MANT_DIG-1)) (LDBL_MANT_DIG-1), (DBL_MANT_DIG-1), (FLT_MANT_DIG-1))
/* Compare KEY (a string, with the name of a test or 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. */
static int
compare_ulp_data (const void *key, const void *ulp)
{
const char *keystr = key;
const struct ulp_data *ulpdat = ulp;
return strcmp (keystr, ulpdat->name);
}
/* Return the ulps for NAME in array DATA with NMEMB elements, or 0 if
no ulps listed. */
static FLOAT
find_ulps (const char *name, const struct ulp_data *data, size_t nmemb)
{
const struct ulp_data *entry = bsearch (name, data, nmemb, sizeof (*data),
compare_ulp_data);
if (entry == NULL)
return 0;
else
return entry->max_ulp;
}
/* Return the ulps for test NAME. */
static FLOAT
find_test_ulps (const char *name)
{
return find_ulps (name, test_ulps,
sizeof (test_ulps) / sizeof (test_ulps[0]));
}
/* Return the ulps for real function NAME. */
static FLOAT
find_function_ulps (const char *name)
{
return find_ulps (name, func_ulps,
sizeof (func_ulps) / sizeof (func_ulps[0]));
}
/* Return the ulps for complex function NAME. */
static __complex__ FLOAT
find_complex_function_ulps (const char *name)
{
FLOAT ulp_real = find_ulps (name, func_real_ulps,
(sizeof (func_real_ulps)
/ sizeof (func_real_ulps[0])));
FLOAT ulp_imag = find_ulps (name, func_imag_ulps,
(sizeof (func_imag_ulps)
/ sizeof (func_imag_ulps[0])));
return BUILD_COMPLEX (ulp_real, ulp_imag);
}
static void static void
init_max_error (void) init_max_error (void)
{ {
@ -407,8 +475,9 @@ fpstack_test (const char *test_name)
static void static void
print_max_error (const char *func_name, FLOAT allowed) print_max_error (const char *func_name)
{ {
FLOAT allowed = find_function_ulps (func_name);
int ok = 0; int ok = 0;
if (max_error == 0.0 || (max_error <= allowed && !ignore_max_ulp)) if (max_error == 0.0 || (max_error <= allowed && !ignore_max_ulp))
@ -432,8 +501,9 @@ print_max_error (const char *func_name, FLOAT allowed)
static void static void
print_complex_max_error (const char *func_name, __complex__ FLOAT allowed) print_complex_max_error (const char *func_name)
{ {
__complex__ FLOAT allowed = find_complex_function_ulps (func_name);
int ok = 0; int ok = 0;
if ((real_max_error == 0 && imag_max_error == 0) if ((real_max_error == 0 && imag_max_error == 0)
@ -589,7 +659,7 @@ test_errno (const char *test_name, int errno_value, int exceptions)
static void static void
check_float_internal (const char *test_name, FLOAT computed, FLOAT expected, check_float_internal (const char *test_name, FLOAT computed, FLOAT expected,
FLOAT max_ulp, int exceptions, int exceptions,
FLOAT *curr_max_error) FLOAT *curr_max_error)
{ {
int ok = 0; int ok = 0;
@ -600,6 +670,7 @@ check_float_internal (const char *test_name, FLOAT computed, FLOAT expected,
test_exceptions (test_name, exceptions); test_exceptions (test_name, exceptions);
test_errno (test_name, errno_value, exceptions); test_errno (test_name, errno_value, exceptions);
FLOAT max_ulp = find_test_ulps (test_name);
if (issignaling (computed) && issignaling (expected)) if (issignaling (computed) && issignaling (expected))
ok = 1; ok = 1;
else if (issignaling (computed) || issignaling (expected)) else if (issignaling (computed) || issignaling (expected))
@ -686,9 +757,9 @@ check_float_internal (const char *test_name, FLOAT computed, FLOAT expected,
static void static void
check_float (const char *test_name, FLOAT computed, FLOAT expected, check_float (const char *test_name, FLOAT computed, FLOAT expected,
FLOAT max_ulp, int exceptions) int exceptions)
{ {
check_float_internal (test_name, computed, expected, max_ulp, check_float_internal (test_name, computed, expected,
exceptions, &max_error); exceptions, &max_error);
} }
@ -696,10 +767,9 @@ check_float (const char *test_name, FLOAT computed, FLOAT expected,
static void static void
check_complex (const char *test_name, __complex__ FLOAT computed, check_complex (const char *test_name, __complex__ FLOAT computed,
__complex__ FLOAT expected, __complex__ FLOAT expected,
__complex__ FLOAT max_ulp,
int exception) int exception)
{ {
FLOAT part_comp, part_exp, part_max_ulp; FLOAT part_comp, part_exp;
char *str; char *str;
if (asprintf (&str, "Real part of: %s", test_name) == -1) if (asprintf (&str, "Real part of: %s", test_name) == -1)
@ -707,9 +777,8 @@ check_complex (const char *test_name, __complex__ FLOAT computed,
part_comp = __real__ computed; part_comp = __real__ computed;
part_exp = __real__ expected; part_exp = __real__ expected;
part_max_ulp = __real__ max_ulp;
check_float_internal (str, part_comp, part_exp, part_max_ulp, check_float_internal (str, part_comp, part_exp,
exception, &real_max_error); exception, &real_max_error);
free (str); free (str);
@ -718,11 +787,10 @@ check_complex (const char *test_name, __complex__ FLOAT computed,
part_comp = __imag__ computed; part_comp = __imag__ computed;
part_exp = __imag__ expected; part_exp = __imag__ expected;
part_max_ulp = __imag__ max_ulp;
/* Don't check again for exceptions or errno, just pass through the /* Don't check again for exceptions or errno, just pass through the
zero/inf sign test. */ zero/inf sign test. */
check_float_internal (str, part_comp, part_exp, part_max_ulp, check_float_internal (str, part_comp, part_exp,
exception & IGNORE_ZERO_INF_SIGN, exception & IGNORE_ZERO_INF_SIGN,
&imag_max_error); &imag_max_error);
free (str); free (str);
@ -731,7 +799,7 @@ check_complex (const char *test_name, __complex__ FLOAT computed,
/* Check that computed and expected values are equal (int values). */ /* Check that computed and expected values are equal (int values). */
static void static void
check_int (const char *test_name, int computed, int expected, int max_ulp, check_int (const char *test_name, int computed, int expected,
int exceptions) int exceptions)
{ {
int ok = 0; int ok = 0;
@ -762,7 +830,7 @@ check_int (const char *test_name, int computed, int expected, int max_ulp,
/* Check that computed and expected values are equal (long int values). */ /* Check that computed and expected values are equal (long int values). */
static void static void
check_long (const char *test_name, long int computed, long int expected, check_long (const char *test_name, long int computed, long int expected,
long int max_ulp, int exceptions) int exceptions)
{ {
int ok = 0; int ok = 0;
int errno_value = errno; int errno_value = errno;
@ -792,7 +860,7 @@ check_long (const char *test_name, long int computed, long int expected,
/* Check that computed value is true/false. */ /* Check that computed value is true/false. */
static void static void
check_bool (const char *test_name, int computed, int expected, check_bool (const char *test_name, int computed, int expected,
long int max_ulp, int exceptions) int exceptions)
{ {
int ok = 0; int ok = 0;
int errno_value = errno; int errno_value = errno;
@ -823,7 +891,6 @@ check_bool (const char *test_name, int computed, int expected,
static void static void
check_longlong (const char *test_name, long long int computed, check_longlong (const char *test_name, long long int computed,
long long int expected, long long int expected,
long long int max_ulp,
int exceptions) int exceptions)
{ {
int ok = 0; int ok = 0;
@ -856,7 +923,6 @@ struct test_f_f_data
const char *test_name; const char *test_name;
FLOAT arg; FLOAT arg;
FLOAT expected; FLOAT expected;
FLOAT max_ulp;
int exceptions; int exceptions;
}; };
struct test_ff_f_data struct test_ff_f_data
@ -864,7 +930,6 @@ struct test_ff_f_data
const char *test_name; const char *test_name;
FLOAT arg1, arg2; FLOAT arg1, arg2;
FLOAT expected; FLOAT expected;
FLOAT max_ulp;
int exceptions; int exceptions;
}; };
struct test_ff_f_data_nexttoward struct test_ff_f_data_nexttoward
@ -873,7 +938,6 @@ struct test_ff_f_data_nexttoward
FLOAT arg1; FLOAT arg1;
long double arg2; long double arg2;
FLOAT expected; FLOAT expected;
FLOAT max_ulp;
int exceptions; int exceptions;
}; };
struct test_fi_f_data struct test_fi_f_data
@ -882,7 +946,6 @@ struct test_fi_f_data
FLOAT arg1; FLOAT arg1;
int arg2; int arg2;
FLOAT expected; FLOAT expected;
FLOAT max_ulp;
int exceptions; int exceptions;
}; };
struct test_fl_f_data struct test_fl_f_data
@ -891,7 +954,6 @@ struct test_fl_f_data
FLOAT arg1; FLOAT arg1;
long int arg2; long int arg2;
FLOAT expected; FLOAT expected;
FLOAT max_ulp;
int exceptions; int exceptions;
}; };
struct test_if_f_data struct test_if_f_data
@ -900,7 +962,6 @@ struct test_if_f_data
int arg1; int arg1;
FLOAT arg2; FLOAT arg2;
FLOAT expected; FLOAT expected;
FLOAT max_ulp;
int exceptions; int exceptions;
}; };
struct test_fff_f_data struct test_fff_f_data
@ -908,7 +969,6 @@ struct test_fff_f_data
const char *test_name; const char *test_name;
FLOAT arg1, arg2, arg3; FLOAT arg1, arg2, arg3;
FLOAT expected; FLOAT expected;
FLOAT max_ulp;
int exceptions; int exceptions;
}; };
struct test_c_f_data struct test_c_f_data
@ -916,7 +976,6 @@ struct test_c_f_data
const char *test_name; const char *test_name;
FLOAT argr, argc; FLOAT argr, argc;
FLOAT expected; FLOAT expected;
FLOAT max_ulp;
int exceptions; int exceptions;
}; };
/* Used for both RUN_TEST_LOOP_f_f1 and RUN_TEST_LOOP_fI_f1. */ /* Used for both RUN_TEST_LOOP_f_f1 and RUN_TEST_LOOP_fI_f1. */
@ -925,43 +984,36 @@ struct test_f_f1_data
const char *test_name; const char *test_name;
FLOAT arg; FLOAT arg;
FLOAT expected; FLOAT expected;
FLOAT max_ulp;
int exceptions; int exceptions;
const char *extra_name; const char *extra_name;
int extra_test; int extra_test;
int extra_expected; int extra_expected;
int extra_ulp;
}; };
struct test_fF_f1_data struct test_fF_f1_data
{ {
const char *test_name; const char *test_name;
FLOAT arg; FLOAT arg;
FLOAT expected; FLOAT expected;
FLOAT max_ulp;
int exceptions; int exceptions;
const char *extra_name; const char *extra_name;
int extra_test; int extra_test;
FLOAT extra_expected; FLOAT extra_expected;
FLOAT extra_ulp;
}; };
struct test_ffI_f1_data struct test_ffI_f1_data
{ {
const char *test_name; const char *test_name;
FLOAT arg1, arg2; FLOAT arg1, arg2;
FLOAT expected; FLOAT expected;
FLOAT max_ulp;
int exceptions; int exceptions;
const char *extra_name; const char *extra_name;
int extra_test; int extra_test;
int extra_expected; int extra_expected;
int extra_ulp;
}; };
struct test_c_c_data struct test_c_c_data
{ {
const char *test_name; const char *test_name;
FLOAT argr, argc; FLOAT argr, argc;
FLOAT expr, expc; FLOAT expr, expc;
__complex__ FLOAT max_ulp;
int exceptions; int exceptions;
}; };
struct test_cc_c_data struct test_cc_c_data
@ -969,7 +1021,6 @@ struct test_cc_c_data
const char *test_name; const char *test_name;
FLOAT arg1r, arg1c, arg2r, arg2c; FLOAT arg1r, arg1c, arg2r, arg2c;
FLOAT expr, expc; FLOAT expr, expc;
__complex__ FLOAT max_ulp;
int exceptions; int exceptions;
}; };
/* Used for all of RUN_TEST_LOOP_f_i, RUN_TEST_LOOP_f_i_tg, /* Used for all of RUN_TEST_LOOP_f_i, RUN_TEST_LOOP_f_i_tg,
@ -979,7 +1030,6 @@ struct test_f_i_data
const char *test_name; const char *test_name;
FLOAT arg; FLOAT arg;
int expected; int expected;
int max_ulp;
int exceptions; int exceptions;
}; };
struct test_ff_i_data struct test_ff_i_data
@ -987,7 +1037,6 @@ struct test_ff_i_data
const char *test_name; const char *test_name;
FLOAT arg1, arg2; FLOAT arg1, arg2;
int expected; int expected;
int max_ulp;
int exceptions; int exceptions;
}; };
struct test_f_l_data struct test_f_l_data
@ -995,7 +1044,6 @@ struct test_f_l_data
const char *test_name; const char *test_name;
FLOAT arg; FLOAT arg;
long int expected; long int expected;
long int max_ulp;
int exceptions; int exceptions;
}; };
struct test_f_L_data struct test_f_L_data
@ -1003,7 +1051,6 @@ struct test_f_L_data
const char *test_name; const char *test_name;
FLOAT arg; FLOAT arg;
long long int expected; long long int expected;
long long int max_ulp;
int exceptions; int exceptions;
}; };
struct test_sincos_data struct test_sincos_data
@ -1011,10 +1058,8 @@ struct test_sincos_data
FLOAT arg; FLOAT arg;
const char *test_name_sin; const char *test_name_sin;
FLOAT expected_sin; FLOAT expected_sin;
FLOAT max_ulp_sin;
const char *test_name_cos; const char *test_name_cos;
FLOAT expected_cos; FLOAT expected_cos;
FLOAT max_ulp_cos;
int exceptions; int exceptions;
}; };
@ -1045,26 +1090,25 @@ struct test_sincos_data
/* Run an individual test, including any required setup and checking /* Run an individual test, including any required setup and checking
of results, or loop over all tests in an array. */ of results, or loop over all tests in an array. */
#define RUN_TEST_f_f(TEST_NAME, FUNC_NAME, ARG, EXPECTED, \ #define RUN_TEST_f_f(TEST_NAME, FUNC_NAME, ARG, EXPECTED, \
MAX_ULP, EXCEPTIONS) \ EXCEPTIONS) \
check_float (TEST_NAME, FUNC (FUNC_NAME) (ARG), EXPECTED, \ check_float (TEST_NAME, FUNC (FUNC_NAME) (ARG), EXPECTED, \
MAX_ULP, EXCEPTIONS) EXCEPTIONS)
#define RUN_TEST_LOOP_f_f(FUNC_NAME, ARRAY, ROUNDING_MODE) \ #define RUN_TEST_LOOP_f_f(FUNC_NAME, ARRAY, ROUNDING_MODE) \
IF_ROUND_INIT_ ## ROUNDING_MODE \ IF_ROUND_INIT_ ## ROUNDING_MODE \
for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \ for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \
RUN_TEST_f_f ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg, \ RUN_TEST_f_f ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg, \
(ARRAY)[i].expected, (ARRAY)[i].max_ulp, \ (ARRAY)[i].expected, (ARRAY)[i].exceptions); \
(ARRAY)[i].exceptions); \
ROUND_RESTORE_ ## ROUNDING_MODE ROUND_RESTORE_ ## ROUNDING_MODE
#define RUN_TEST_2_f(TEST_NAME, FUNC_NAME, ARG1, ARG2, EXPECTED, \ #define RUN_TEST_2_f(TEST_NAME, FUNC_NAME, ARG1, ARG2, EXPECTED, \
MAX_ULP, EXCEPTIONS) \ EXCEPTIONS) \
check_float (TEST_NAME, FUNC (FUNC_NAME) (ARG1, ARG2), EXPECTED, \ check_float (TEST_NAME, FUNC (FUNC_NAME) (ARG1, ARG2), EXPECTED, \
MAX_ULP, EXCEPTIONS) EXCEPTIONS)
#define RUN_TEST_LOOP_2_f(FUNC_NAME, ARRAY, ROUNDING_MODE) \ #define RUN_TEST_LOOP_2_f(FUNC_NAME, ARRAY, ROUNDING_MODE) \
IF_ROUND_INIT_ ## ROUNDING_MODE \ IF_ROUND_INIT_ ## ROUNDING_MODE \
for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \ for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \
RUN_TEST_2_f ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg1, \ RUN_TEST_2_f ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg1, \
(ARRAY)[i].arg2, (ARRAY)[i].expected, \ (ARRAY)[i].arg2, (ARRAY)[i].expected, \
(ARRAY)[i].max_ulp, (ARRAY)[i].exceptions); \ (ARRAY)[i].exceptions); \
ROUND_RESTORE_ ## ROUNDING_MODE ROUND_RESTORE_ ## ROUNDING_MODE
#define RUN_TEST_ff_f RUN_TEST_2_f #define RUN_TEST_ff_f RUN_TEST_2_f
#define RUN_TEST_LOOP_ff_f RUN_TEST_LOOP_2_f #define RUN_TEST_LOOP_ff_f RUN_TEST_LOOP_2_f
@ -1075,111 +1119,106 @@ struct test_sincos_data
#define RUN_TEST_if_f RUN_TEST_2_f #define RUN_TEST_if_f RUN_TEST_2_f
#define RUN_TEST_LOOP_if_f RUN_TEST_LOOP_2_f #define RUN_TEST_LOOP_if_f RUN_TEST_LOOP_2_f
#define RUN_TEST_fff_f(TEST_NAME, FUNC_NAME, ARG1, ARG2, ARG3, \ #define RUN_TEST_fff_f(TEST_NAME, FUNC_NAME, ARG1, ARG2, ARG3, \
EXPECTED, MAX_ULP, EXCEPTIONS) \ EXPECTED, EXCEPTIONS) \
check_float (TEST_NAME, FUNC (FUNC_NAME) (ARG1, ARG2, ARG3), \ check_float (TEST_NAME, FUNC (FUNC_NAME) (ARG1, ARG2, ARG3), \
EXPECTED, MAX_ULP, EXCEPTIONS) EXPECTED, EXCEPTIONS)
#define RUN_TEST_LOOP_fff_f(FUNC_NAME, ARRAY, ROUNDING_MODE) \ #define RUN_TEST_LOOP_fff_f(FUNC_NAME, ARRAY, ROUNDING_MODE) \
IF_ROUND_INIT_ ## ROUNDING_MODE \ IF_ROUND_INIT_ ## ROUNDING_MODE \
for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \ for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \
RUN_TEST_fff_f ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg1, \ RUN_TEST_fff_f ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg1, \
(ARRAY)[i].arg2, (ARRAY)[i].arg3, \ (ARRAY)[i].arg2, (ARRAY)[i].arg3, \
(ARRAY)[i].expected, (ARRAY)[i].max_ulp, \ (ARRAY)[i].expected, (ARRAY)[i].exceptions); \
(ARRAY)[i].exceptions); \
ROUND_RESTORE_ ## ROUNDING_MODE ROUND_RESTORE_ ## ROUNDING_MODE
#define RUN_TEST_c_f(TEST_NAME, FUNC_NAME, ARG1, ARG2, EXPECTED, \ #define RUN_TEST_c_f(TEST_NAME, FUNC_NAME, ARG1, ARG2, EXPECTED, \
MAX_ULP, EXCEPTIONS) \ EXCEPTIONS) \
check_float (TEST_NAME, \ check_float (TEST_NAME, \
FUNC (FUNC_NAME) (BUILD_COMPLEX (ARG1, ARG2)), \ FUNC (FUNC_NAME) (BUILD_COMPLEX (ARG1, ARG2)), \
EXPECTED, MAX_ULP, EXCEPTIONS) EXPECTED, EXCEPTIONS)
#define RUN_TEST_LOOP_c_f(FUNC_NAME, ARRAY, ROUNDING_MODE) \ #define RUN_TEST_LOOP_c_f(FUNC_NAME, ARRAY, ROUNDING_MODE) \
IF_ROUND_INIT_ ## ROUNDING_MODE \ IF_ROUND_INIT_ ## ROUNDING_MODE \
for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \ for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \
RUN_TEST_c_f ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].argr, \ RUN_TEST_c_f ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].argr, \
(ARRAY)[i].argc, (ARRAY)[i].expected, \ (ARRAY)[i].argc, (ARRAY)[i].expected, \
(ARRAY)[i].max_ulp, (ARRAY)[i].exceptions); \ (ARRAY)[i].exceptions); \
ROUND_RESTORE_ ## ROUNDING_MODE ROUND_RESTORE_ ## ROUNDING_MODE
#define RUN_TEST_f_f1(TEST_NAME, FUNC_NAME, ARG, EXPECTED, \ #define RUN_TEST_f_f1(TEST_NAME, FUNC_NAME, ARG, EXPECTED, \
MAX_ULP, EXCEPTIONS, \ EXCEPTIONS, \
EXTRA_NAME, EXTRA_VAR, EXTRA_TEST, \ EXTRA_NAME, EXTRA_VAR, EXTRA_TEST, \
EXTRA_EXPECTED, EXTRA_ULP) \ EXTRA_EXPECTED) \
do \ do \
{ \ { \
(EXTRA_VAR) = (EXTRA_EXPECTED) == 0 ? 1 : 0; \ (EXTRA_VAR) = (EXTRA_EXPECTED) == 0 ? 1 : 0; \
check_float (TEST_NAME, FUNC (FUNC_NAME) (ARG), EXPECTED, \ check_float (TEST_NAME, FUNC (FUNC_NAME) (ARG), EXPECTED, \
MAX_ULP, EXCEPTIONS); \ EXCEPTIONS); \
if (EXTRA_TEST) \ if (EXTRA_TEST) \
check_int (EXTRA_NAME, EXTRA_VAR, EXTRA_EXPECTED, \ check_int (EXTRA_NAME, EXTRA_VAR, EXTRA_EXPECTED, 0); \
EXTRA_ULP, 0); \
} \ } \
while (0) while (0)
#define RUN_TEST_LOOP_f_f1(FUNC_NAME, ARRAY, ROUNDING_MODE, EXTRA_VAR) \ #define RUN_TEST_LOOP_f_f1(FUNC_NAME, ARRAY, ROUNDING_MODE, EXTRA_VAR) \
IF_ROUND_INIT_ ## ROUNDING_MODE \ IF_ROUND_INIT_ ## ROUNDING_MODE \
for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \ for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \
RUN_TEST_f_f1 ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg, \ RUN_TEST_f_f1 ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg, \
(ARRAY)[i].expected, (ARRAY)[i].max_ulp, \ (ARRAY)[i].expected, \
(ARRAY)[i].exceptions, (ARRAY)[i].extra_name, \ (ARRAY)[i].exceptions, (ARRAY)[i].extra_name, \
EXTRA_VAR, (ARRAY)[i].extra_test, \ EXTRA_VAR, (ARRAY)[i].extra_test, \
(ARRAY)[i].extra_expected, (ARRAY)[i].extra_ulp); \ (ARRAY)[i].extra_expected); \
ROUND_RESTORE_ ## ROUNDING_MODE ROUND_RESTORE_ ## ROUNDING_MODE
#define RUN_TEST_fF_f1(TEST_NAME, FUNC_NAME, ARG, EXPECTED, \ #define RUN_TEST_fF_f1(TEST_NAME, FUNC_NAME, ARG, EXPECTED, \
MAX_ULP, EXCEPTIONS, \ EXCEPTIONS, \
EXTRA_NAME, EXTRA_VAR, EXTRA_TEST, \ EXTRA_NAME, EXTRA_VAR, EXTRA_TEST, \
EXTRA_EXPECTED, EXTRA_ULP) \ EXTRA_EXPECTED) \
do \ do \
{ \ { \
(EXTRA_VAR) = (EXTRA_EXPECTED) == 0 ? 1 : 0; \ (EXTRA_VAR) = (EXTRA_EXPECTED) == 0 ? 1 : 0; \
check_float (TEST_NAME, FUNC (FUNC_NAME) (ARG, &(EXTRA_VAR)), \ check_float (TEST_NAME, FUNC (FUNC_NAME) (ARG, &(EXTRA_VAR)), \
EXPECTED, MAX_ULP, EXCEPTIONS); \ EXPECTED, EXCEPTIONS); \
if (EXTRA_TEST) \ if (EXTRA_TEST) \
check_float (EXTRA_NAME, EXTRA_VAR, EXTRA_EXPECTED, \ check_float (EXTRA_NAME, EXTRA_VAR, EXTRA_EXPECTED, 0); \
EXTRA_ULP, 0); \
} \ } \
while (0) while (0)
#define RUN_TEST_LOOP_fF_f1(FUNC_NAME, ARRAY, ROUNDING_MODE, EXTRA_VAR) \ #define RUN_TEST_LOOP_fF_f1(FUNC_NAME, ARRAY, ROUNDING_MODE, EXTRA_VAR) \
IF_ROUND_INIT_ ## ROUNDING_MODE \ IF_ROUND_INIT_ ## ROUNDING_MODE \
for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \ for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \
RUN_TEST_fF_f1 ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg, \ RUN_TEST_fF_f1 ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg, \
(ARRAY)[i].expected, (ARRAY)[i].max_ulp, \ (ARRAY)[i].expected, \
(ARRAY)[i].exceptions, (ARRAY)[i].extra_name, \ (ARRAY)[i].exceptions, (ARRAY)[i].extra_name, \
EXTRA_VAR, (ARRAY)[i].extra_test, \ EXTRA_VAR, (ARRAY)[i].extra_test, \
(ARRAY)[i].extra_expected, (ARRAY)[i].extra_ulp); \ (ARRAY)[i].extra_expected); \
ROUND_RESTORE_ ## ROUNDING_MODE ROUND_RESTORE_ ## ROUNDING_MODE
#define RUN_TEST_fI_f1(TEST_NAME, FUNC_NAME, ARG, EXPECTED, \ #define RUN_TEST_fI_f1(TEST_NAME, FUNC_NAME, ARG, EXPECTED, \
MAX_ULP, EXCEPTIONS, \ EXCEPTIONS, \
EXTRA_NAME, EXTRA_VAR, EXTRA_TEST, \ EXTRA_NAME, EXTRA_VAR, EXTRA_TEST, \
EXTRA_EXPECTED, EXTRA_ULP) \ EXTRA_EXPECTED) \
do \ do \
{ \ { \
(EXTRA_VAR) = (EXTRA_EXPECTED) == 0 ? 1 : 0; \ (EXTRA_VAR) = (EXTRA_EXPECTED) == 0 ? 1 : 0; \
check_float (TEST_NAME, FUNC (FUNC_NAME) (ARG, &(EXTRA_VAR)), \ check_float (TEST_NAME, FUNC (FUNC_NAME) (ARG, &(EXTRA_VAR)), \
EXPECTED, MAX_ULP, EXCEPTIONS); \ EXPECTED, EXCEPTIONS); \
if (EXTRA_TEST) \ if (EXTRA_TEST) \
check_int (EXTRA_NAME, EXTRA_VAR, EXTRA_EXPECTED, \ check_int (EXTRA_NAME, EXTRA_VAR, EXTRA_EXPECTED, 0); \
EXTRA_ULP, 0); \
} \ } \
while (0) while (0)
#define RUN_TEST_LOOP_fI_f1(FUNC_NAME, ARRAY, ROUNDING_MODE, EXTRA_VAR) \ #define RUN_TEST_LOOP_fI_f1(FUNC_NAME, ARRAY, ROUNDING_MODE, EXTRA_VAR) \
IF_ROUND_INIT_ ## ROUNDING_MODE \ IF_ROUND_INIT_ ## ROUNDING_MODE \
for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \ for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \
RUN_TEST_fI_f1 ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg, \ RUN_TEST_fI_f1 ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg, \
(ARRAY)[i].expected, (ARRAY)[i].max_ulp, \ (ARRAY)[i].expected, \
(ARRAY)[i].exceptions, (ARRAY)[i].extra_name, \ (ARRAY)[i].exceptions, (ARRAY)[i].extra_name, \
EXTRA_VAR, (ARRAY)[i].extra_test, \ EXTRA_VAR, (ARRAY)[i].extra_test, \
(ARRAY)[i].extra_expected, (ARRAY)[i].extra_ulp); \ (ARRAY)[i].extra_expected); \
ROUND_RESTORE_ ## ROUNDING_MODE ROUND_RESTORE_ ## ROUNDING_MODE
#define RUN_TEST_ffI_f1(TEST_NAME, FUNC_NAME, ARG1, ARG2, EXPECTED, \ #define RUN_TEST_ffI_f1(TEST_NAME, FUNC_NAME, ARG1, ARG2, EXPECTED, \
MAX_ULP, EXCEPTIONS, \ EXCEPTIONS, \
EXTRA_NAME, EXTRA_VAR, EXTRA_TEST, \ EXTRA_NAME, EXTRA_VAR, EXTRA_TEST, \
EXTRA_EXPECTED, EXTRA_ULP) \ EXTRA_EXPECTED) \
do \ do \
{ \ { \
(EXTRA_VAR) = (EXTRA_EXPECTED) == 0 ? 1 : 0; \ (EXTRA_VAR) = (EXTRA_EXPECTED) == 0 ? 1 : 0; \
check_float (TEST_NAME, \ check_float (TEST_NAME, \
FUNC (FUNC_NAME) (ARG1, ARG2, &(EXTRA_VAR)), \ FUNC (FUNC_NAME) (ARG1, ARG2, &(EXTRA_VAR)), \
EXPECTED, MAX_ULP, EXCEPTIONS); \ EXPECTED, EXCEPTIONS); \
if (EXTRA_TEST) \ if (EXTRA_TEST) \
check_int (EXTRA_NAME, EXTRA_VAR, EXTRA_EXPECTED, \ check_int (EXTRA_NAME, EXTRA_VAR, EXTRA_EXPECTED, 0); \
EXTRA_ULP, 0); \
} \ } \
while (0) while (0)
#define RUN_TEST_LOOP_ffI_f1(FUNC_NAME, ARRAY, ROUNDING_MODE, \ #define RUN_TEST_LOOP_ffI_f1(FUNC_NAME, ARRAY, ROUNDING_MODE, \
@ -1188,129 +1227,108 @@ struct test_sincos_data
for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \ for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \
RUN_TEST_ffI_f1 ((ARRAY)[i].test_name, FUNC_NAME, \ RUN_TEST_ffI_f1 ((ARRAY)[i].test_name, FUNC_NAME, \
(ARRAY)[i].arg1, (ARRAY)[i].arg2, \ (ARRAY)[i].arg1, (ARRAY)[i].arg2, \
(ARRAY)[i].expected, (ARRAY)[i].max_ulp, \ (ARRAY)[i].expected, \
(ARRAY)[i].exceptions, (ARRAY)[i].extra_name, \ (ARRAY)[i].exceptions, (ARRAY)[i].extra_name, \
EXTRA_VAR, (ARRAY)[i].extra_test, \ EXTRA_VAR, (ARRAY)[i].extra_test, \
(ARRAY)[i].extra_expected, \ (ARRAY)[i].extra_expected); \
(ARRAY)[i].extra_ulp); \
ROUND_RESTORE_ ## ROUNDING_MODE ROUND_RESTORE_ ## ROUNDING_MODE
#define RUN_TEST_c_c(TEST_NAME, FUNC_NAME, ARGR, ARGC, EXPR, EXPC, \ #define RUN_TEST_c_c(TEST_NAME, FUNC_NAME, ARGR, ARGC, EXPR, EXPC, \
MAX_ULP, EXCEPTIONS) \ EXCEPTIONS) \
check_complex (TEST_NAME, \ check_complex (TEST_NAME, \
FUNC (FUNC_NAME) (BUILD_COMPLEX (ARGR, ARGC)), \ FUNC (FUNC_NAME) (BUILD_COMPLEX (ARGR, ARGC)), \
BUILD_COMPLEX (EXPR, EXPC), \ BUILD_COMPLEX (EXPR, EXPC), EXCEPTIONS)
MAX_ULP, EXCEPTIONS)
#define RUN_TEST_LOOP_c_c(FUNC_NAME, ARRAY, ROUNDING_MODE) \ #define RUN_TEST_LOOP_c_c(FUNC_NAME, ARRAY, ROUNDING_MODE) \
IF_ROUND_INIT_ ## ROUNDING_MODE \ IF_ROUND_INIT_ ## ROUNDING_MODE \
for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \ for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \
RUN_TEST_c_c ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].argr, \ RUN_TEST_c_c ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].argr, \
(ARRAY)[i].argc, (ARRAY)[i].expr, (ARRAY)[i].expc, \ (ARRAY)[i].argc, (ARRAY)[i].expr, (ARRAY)[i].expc, \
(ARRAY)[i].max_ulp, (ARRAY)[i].exceptions); \ (ARRAY)[i].exceptions); \
ROUND_RESTORE_ ## ROUNDING_MODE ROUND_RESTORE_ ## ROUNDING_MODE
#define RUN_TEST_cc_c(TEST_NAME, FUNC_NAME, ARG1R, ARG1C, ARG2R, ARG2C, \ #define RUN_TEST_cc_c(TEST_NAME, FUNC_NAME, ARG1R, ARG1C, ARG2R, ARG2C, \
EXPR, EXPC, MAX_ULP, EXCEPTIONS) \ EXPR, EXPC, EXCEPTIONS) \
check_complex (TEST_NAME, \ check_complex (TEST_NAME, \
FUNC (FUNC_NAME) (BUILD_COMPLEX (ARG1R, ARG1C), \ FUNC (FUNC_NAME) (BUILD_COMPLEX (ARG1R, ARG1C), \
BUILD_COMPLEX (ARG2R, ARG2C)), \ BUILD_COMPLEX (ARG2R, ARG2C)), \
BUILD_COMPLEX (EXPR, EXPC), \ BUILD_COMPLEX (EXPR, EXPC), EXCEPTIONS)
MAX_ULP, EXCEPTIONS)
#define RUN_TEST_LOOP_cc_c(FUNC_NAME, ARRAY, ROUNDING_MODE) \ #define RUN_TEST_LOOP_cc_c(FUNC_NAME, ARRAY, ROUNDING_MODE) \
IF_ROUND_INIT_ ## ROUNDING_MODE \ IF_ROUND_INIT_ ## ROUNDING_MODE \
for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \ for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \
RUN_TEST_cc_c ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg1r, \ RUN_TEST_cc_c ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg1r, \
(ARRAY)[i].arg1c, (ARRAY)[i].arg2r, \ (ARRAY)[i].arg1c, (ARRAY)[i].arg2r, \
(ARRAY)[i].arg2c, (ARRAY)[i].expr, \ (ARRAY)[i].arg2c, (ARRAY)[i].expr, \
(ARRAY)[i].expc, (ARRAY)[i].max_ulp, \ (ARRAY)[i].expc, (ARRAY)[i].exceptions); \
(ARRAY)[i].exceptions); \
ROUND_RESTORE_ ## ROUNDING_MODE ROUND_RESTORE_ ## ROUNDING_MODE
#define RUN_TEST_f_i(TEST_NAME, FUNC_NAME, ARG, EXPECTED, \ #define RUN_TEST_f_i(TEST_NAME, FUNC_NAME, ARG, EXPECTED, EXCEPTIONS) \
MAX_ULP, EXCEPTIONS) \ check_int (TEST_NAME, FUNC (FUNC_NAME) (ARG), EXPECTED, EXCEPTIONS)
check_int (TEST_NAME, FUNC (FUNC_NAME) (ARG), EXPECTED, \
MAX_ULP, EXCEPTIONS)
#define RUN_TEST_LOOP_f_i(FUNC_NAME, ARRAY, ROUNDING_MODE) \ #define RUN_TEST_LOOP_f_i(FUNC_NAME, ARRAY, ROUNDING_MODE) \
IF_ROUND_INIT_ ## ROUNDING_MODE \ IF_ROUND_INIT_ ## ROUNDING_MODE \
for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \ for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \
RUN_TEST_f_i ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg, \ RUN_TEST_f_i ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg, \
(ARRAY)[i].expected, (ARRAY)[i].max_ulp, \ (ARRAY)[i].expected, (ARRAY)[i].exceptions); \
(ARRAY)[i].exceptions); \
ROUND_RESTORE_ ## ROUNDING_MODE ROUND_RESTORE_ ## ROUNDING_MODE
#define RUN_TEST_f_i_tg(TEST_NAME, FUNC_NAME, ARG, EXPECTED, \ #define RUN_TEST_f_i_tg(TEST_NAME, FUNC_NAME, ARG, EXPECTED, \
MAX_ULP, EXCEPTIONS) \ EXCEPTIONS) \
check_int (TEST_NAME, FUNC_NAME (ARG), EXPECTED, \ check_int (TEST_NAME, FUNC_NAME (ARG), EXPECTED, EXCEPTIONS)
MAX_ULP, EXCEPTIONS)
#define RUN_TEST_LOOP_f_i_tg(FUNC_NAME, ARRAY, ROUNDING_MODE) \ #define RUN_TEST_LOOP_f_i_tg(FUNC_NAME, ARRAY, ROUNDING_MODE) \
IF_ROUND_INIT_ ## ROUNDING_MODE \ IF_ROUND_INIT_ ## ROUNDING_MODE \
for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \ for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \
RUN_TEST_f_i_tg ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg, \ RUN_TEST_f_i_tg ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg, \
(ARRAY)[i].expected, (ARRAY)[i].max_ulp, \ (ARRAY)[i].expected, (ARRAY)[i].exceptions); \
(ARRAY)[i].exceptions); \
ROUND_RESTORE_ ## ROUNDING_MODE ROUND_RESTORE_ ## ROUNDING_MODE
#define RUN_TEST_ff_i_tg(TEST_NAME, FUNC_NAME, ARG1, ARG2, EXPECTED, \ #define RUN_TEST_ff_i_tg(TEST_NAME, FUNC_NAME, ARG1, ARG2, EXPECTED, \
MAX_ULP, EXCEPTIONS) \ EXCEPTIONS) \
check_int (TEST_NAME, FUNC_NAME (ARG1, ARG2), EXPECTED, \ check_int (TEST_NAME, FUNC_NAME (ARG1, ARG2), EXPECTED, EXCEPTIONS)
MAX_ULP, EXCEPTIONS)
#define RUN_TEST_LOOP_ff_i_tg(FUNC_NAME, ARRAY, ROUNDING_MODE) \ #define RUN_TEST_LOOP_ff_i_tg(FUNC_NAME, ARRAY, ROUNDING_MODE) \
IF_ROUND_INIT_ ## ROUNDING_MODE \ IF_ROUND_INIT_ ## ROUNDING_MODE \
for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \ for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \
RUN_TEST_ff_i_tg ((ARRAY)[i].test_name, FUNC_NAME, \ RUN_TEST_ff_i_tg ((ARRAY)[i].test_name, FUNC_NAME, \
(ARRAY)[i].arg1, (ARRAY)[i].arg2, \ (ARRAY)[i].arg1, (ARRAY)[i].arg2, \
(ARRAY)[i].expected, (ARRAY)[i].max_ulp, \ (ARRAY)[i].expected, (ARRAY)[i].exceptions); \
(ARRAY)[i].exceptions); \
ROUND_RESTORE_ ## ROUNDING_MODE ROUND_RESTORE_ ## ROUNDING_MODE
#define RUN_TEST_f_b(TEST_NAME, FUNC_NAME, ARG, EXPECTED, \ #define RUN_TEST_f_b(TEST_NAME, FUNC_NAME, ARG, EXPECTED, EXCEPTIONS) \
MAX_ULP, EXCEPTIONS) \ check_bool (TEST_NAME, FUNC (FUNC_NAME) (ARG), EXPECTED, EXCEPTIONS)
check_bool (TEST_NAME, FUNC (FUNC_NAME) (ARG), EXPECTED, \
MAX_ULP, EXCEPTIONS)
#define RUN_TEST_LOOP_f_b(FUNC_NAME, ARRAY, ROUNDING_MODE) \ #define RUN_TEST_LOOP_f_b(FUNC_NAME, ARRAY, ROUNDING_MODE) \
IF_ROUND_INIT_ ## ROUNDING_MODE \ IF_ROUND_INIT_ ## ROUNDING_MODE \
for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \ for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \
RUN_TEST_f_b ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg, \ RUN_TEST_f_b ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg, \
(ARRAY)[i].expected, (ARRAY)[i].max_ulp, \ (ARRAY)[i].expected, (ARRAY)[i].exceptions); \
(ARRAY)[i].exceptions); \
ROUND_RESTORE_ ## ROUNDING_MODE ROUND_RESTORE_ ## ROUNDING_MODE
#define RUN_TEST_f_b_tg(TEST_NAME, FUNC_NAME, ARG, EXPECTED, \ #define RUN_TEST_f_b_tg(TEST_NAME, FUNC_NAME, ARG, EXPECTED, \
MAX_ULP, EXCEPTIONS) \ EXCEPTIONS) \
check_bool (TEST_NAME, FUNC_NAME (ARG), EXPECTED, \ check_bool (TEST_NAME, FUNC_NAME (ARG), EXPECTED, EXCEPTIONS)
MAX_ULP, EXCEPTIONS)
#define RUN_TEST_LOOP_f_b_tg(FUNC_NAME, ARRAY, ROUNDING_MODE) \ #define RUN_TEST_LOOP_f_b_tg(FUNC_NAME, ARRAY, ROUNDING_MODE) \
IF_ROUND_INIT_ ## ROUNDING_MODE \ IF_ROUND_INIT_ ## ROUNDING_MODE \
for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \ for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \
RUN_TEST_f_b_tg ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg, \ RUN_TEST_f_b_tg ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg, \
(ARRAY)[i].expected, (ARRAY)[i].max_ulp, \ (ARRAY)[i].expected, (ARRAY)[i].exceptions); \
(ARRAY)[i].exceptions); \
ROUND_RESTORE_ ## ROUNDING_MODE ROUND_RESTORE_ ## ROUNDING_MODE
#define RUN_TEST_f_l(TEST_NAME, FUNC_NAME, ARG, EXPECTED, \ #define RUN_TEST_f_l(TEST_NAME, FUNC_NAME, ARG, EXPECTED, EXCEPTIONS) \
MAX_ULP, EXCEPTIONS) \ check_long (TEST_NAME, FUNC (FUNC_NAME) (ARG), EXPECTED, EXCEPTIONS)
check_long (TEST_NAME, FUNC (FUNC_NAME) (ARG), EXPECTED, \
MAX_ULP, EXCEPTIONS)
#define RUN_TEST_LOOP_f_l(FUNC_NAME, ARRAY, ROUNDING_MODE) \ #define RUN_TEST_LOOP_f_l(FUNC_NAME, ARRAY, ROUNDING_MODE) \
IF_ROUND_INIT_ ## ROUNDING_MODE \ IF_ROUND_INIT_ ## ROUNDING_MODE \
for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \ for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \
RUN_TEST_f_l ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg, \ RUN_TEST_f_l ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg, \
(ARRAY)[i].expected, (ARRAY)[i].max_ulp, \ (ARRAY)[i].expected, (ARRAY)[i].exceptions); \
(ARRAY)[i].exceptions); \
ROUND_RESTORE_ ## ROUNDING_MODE ROUND_RESTORE_ ## ROUNDING_MODE
#define RUN_TEST_f_L(TEST_NAME, FUNC_NAME, ARG, EXPECTED, \ #define RUN_TEST_f_L(TEST_NAME, FUNC_NAME, ARG, EXPECTED, EXCEPTIONS) \
MAX_ULP, EXCEPTIONS) \
check_longlong (TEST_NAME, FUNC (FUNC_NAME) (ARG), EXPECTED, \ check_longlong (TEST_NAME, FUNC (FUNC_NAME) (ARG), EXPECTED, \
MAX_ULP, EXCEPTIONS) EXCEPTIONS)
#define RUN_TEST_LOOP_f_L(FUNC_NAME, ARRAY, ROUNDING_MODE) \ #define RUN_TEST_LOOP_f_L(FUNC_NAME, ARRAY, ROUNDING_MODE) \
IF_ROUND_INIT_ ## ROUNDING_MODE \ IF_ROUND_INIT_ ## ROUNDING_MODE \
for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \ for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \
RUN_TEST_f_L ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg, \ RUN_TEST_f_L ((ARRAY)[i].test_name, FUNC_NAME, (ARRAY)[i].arg, \
(ARRAY)[i].expected, (ARRAY)[i].max_ulp, \ (ARRAY)[i].expected, (ARRAY)[i].exceptions); \
(ARRAY)[i].exceptions); \
ROUND_RESTORE_ ## ROUNDING_MODE ROUND_RESTORE_ ## ROUNDING_MODE
#define RUN_TEST_sincos(ARG, TEST_NAME_SIN, SIN_RES_VAR, EXPECTED_SIN, \ #define RUN_TEST_sincos(ARG, TEST_NAME_SIN, SIN_RES_VAR, \
MAX_ULP_SIN, TEST_NAME_COS, COS_RES_VAR, \ EXPECTED_SIN, TEST_NAME_COS, COS_RES_VAR, \
EXPECTED_COS, MAX_ULP_COS, EXCEPTIONS) \ EXPECTED_COS, EXCEPTIONS) \
do \ do \
{ \ { \
FUNC (sincos) (ARG, &(SIN_RES_VAR), &(COS_RES_VAR)); \ FUNC (sincos) (ARG, &(SIN_RES_VAR), &(COS_RES_VAR)); \
check_float (TEST_NAME_SIN, SIN_RES_VAR, \ check_float (TEST_NAME_SIN, SIN_RES_VAR, \
EXPECTED_SIN, MAX_ULP_SIN, EXCEPTIONS); \ EXPECTED_SIN, EXCEPTIONS); \
check_float (TEST_NAME_COS, COS_RES_VAR, \ check_float (TEST_NAME_COS, COS_RES_VAR, \
EXPECTED_COS, MAX_ULP_COS, 0); \ EXPECTED_COS, 0); \
} \ } \
while (0) while (0)
#define RUN_TEST_LOOP_sincos(ARRAY, ROUNDING_MODE, SIN_RES_VAR, \ #define RUN_TEST_LOOP_sincos(ARRAY, ROUNDING_MODE, SIN_RES_VAR, \
@ -1319,10 +1337,8 @@ struct test_sincos_data
for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \ for (size_t i = 0; i < sizeof (ARRAY) / sizeof (ARRAY)[0]; i++) \
RUN_TEST_sincos ((ARRAY)[i].arg, (ARRAY)[i].test_name_sin, \ RUN_TEST_sincos ((ARRAY)[i].arg, (ARRAY)[i].test_name_sin, \
SIN_RES_VAR, (ARRAY)[i].expected_sin, \ SIN_RES_VAR, (ARRAY)[i].expected_sin, \
(ARRAY)[i].max_ulp_sin, \
(ARRAY)[i].test_name_cos, COS_RES_VAR, \ (ARRAY)[i].test_name_cos, COS_RES_VAR, \
(ARRAY)[i].expected_cos, (ARRAY)[i].max_ulp_cos, \ (ARRAY)[i].expected_cos, (ARRAY)[i].exceptions); \
(ARRAY)[i].exceptions); \
ROUND_RESTORE_ ## ROUNDING_MODE ROUND_RESTORE_ ## ROUNDING_MODE