Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Make libm-test look up ulps by name at runtime.
  • Loading branch information
Joseph Myers committed May 18, 2013
1 parent bb38759 commit 3779b5b
Show file tree
Hide file tree
Showing 3 changed files with 315 additions and 228 deletions.
90 changes: 90 additions & 0 deletions ChangeLog
@@ -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>

[BZ #15480]
Expand Down
161 changes: 71 additions & 90 deletions math/gen-libm-test.pl
Expand Up @@ -41,8 +41,7 @@

use vars qw ($input $output);
use vars qw (%results);
use vars qw (@tests @functions);
use vars qw ($count);
use vars qw (@functions);
use vars qw (%beautify @all_floats);
use vars qw ($output_dir $ulps_file);

Expand Down Expand Up @@ -103,8 +102,6 @@
$input = "libm-test.inc";
$output = "${output_dir}libm-test.c";

$count = 0;

&parse_ulps ($ulps_file);
&generate_testfile ($input, $output) unless ($opt_n);
&output_ulps ("${output_dir}libm-test-ulps.h", $ulps_file) unless ($opt_n);
Expand Down Expand Up @@ -160,29 +157,15 @@ sub get_variable {
return "x$number";
}

# Add a new test to internal data structures and fill in the
# ulps and exception information for the C line.
sub new_test {
my ($test, $exception, $show_exception) = @_;
my $rest;

# Add ulp.
if (exists $results{$test}{'has_ulps'}) {
$rest = ", DELTA$count";
# Return the text to put in an initializer for a test's exception
# information.
sub show_exceptions {
my ($exception) = @_;
if (defined $exception) {
return ", $exception";
} else {
$rest = ', 0';
}
if ($show_exception) {
if (defined $exception) {
$rest .= ", $exception";
} 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.
Expand All @@ -203,12 +186,11 @@ sub special_functions {
$test = $str . ' puts ' . &beautify ($args[2]) . ' in sin_res';

$cline .= ", \"$test\", $args[2]";
$cline .= &new_test ($test, $args[4], 0);

# handle cos
$test = $str . ' puts ' . &beautify ($args[3]) . ' in cos_res';
$cline .= ", \"$test\", $args[3]";
$cline .= &new_test ($test, $args[4], 1);
$cline .= show_exceptions ($args[4]);
$cline .= " },\n";
print $file $cline;
}
Expand Down Expand Up @@ -332,8 +314,10 @@ sub parse_args {
++$current_arg;
}
}
# Add ulp.
$cline .= &new_test ($str, ($current_arg <= $#args) ? $args[$current_arg] : undef, 1);
# Add exceptions.
$cline .= show_exceptions (($current_arg <= $#args)
? $args[$current_arg]
: undef);

# special treatment for some functions
if ($args[0] eq 'frexp') {
Expand All @@ -346,11 +330,6 @@ sub parse_args {
$extra_expected = "0";
}
$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') {
if (defined $special[0]) {
Expand All @@ -362,11 +341,6 @@ sub parse_args {
$extra_expected = "0";
}
$cline .= ", \"$str\", $run_extra, $extra_expected";
if ($run_extra) {
$cline .= &new_test ($str, undef, 0);
} else {
$cline .= ", 0";
}
}
} elsif ($args[0] eq 'modf') {
if (defined $special[0]) {
Expand All @@ -378,11 +352,6 @@ sub parse_args {
$extra_expected = "0";
}
$cline .= ", \"$str\", $run_extra, $extra_expected";
if ($run_extra) {
$cline .= &new_test ($str, undef, 0);
} else {
$cline .= ", 0";
}
}
} elsif ($args[0] eq 'remquo') {
if (defined $special[0]) {
Expand All @@ -394,11 +363,6 @@ sub parse_args {
$extra_expected = "0";
}
$cline .= ", \"$str\", $run_extra, $extra_expected";
if ($run_extra) {
$cline .= &new_test ($str, undef, 0);
} else {
$cline .= ", 0";
}
}
}
print $file " $cline },\n";
Expand Down Expand Up @@ -450,16 +414,10 @@ sub generate_testfile {
}
($fct) = ($_ =~ /END\s*\((.*)\)/);
if ($type eq 'complex') {
$line = " print_complex_max_error (\"$fct\", ";
} else {
$line = " print_max_error (\"$fct\", ";
}
if (exists $results{$fct}{'has_ulps'}) {
$line .= "DELTA$fct";
$line = " print_complex_max_error (\"$fct\");\n";
} else {
$line .= '0';
$line = " print_max_error (\"$fct\");\n";
}
$line .= ");\n";
print OUTPUT $line;
push @functions, $fct;
next;
Expand Down Expand Up @@ -620,37 +578,15 @@ sub print_ulps_file {
sub get_ulps {
my ($test, $type, $float) = @_;

if ($type eq 'complex') {
my ($res);
# 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");
return (exists $results{$test}{$type}{'ulp'}{$float}
? $results{$test}{$type}{'ulp'}{$float} : "0");
}

# Output the defines for a single test
sub output_test {
my ($file, $test, $name) = @_;
# Return the ulps value for a single test.
sub get_all_ulps_for_test {
my ($test, $type) = @_;
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'}) {
# XXX use all_floats (change order!)
$ldouble = &get_ulps ($test, $type, "ldouble");
Expand All @@ -659,29 +595,74 @@ sub output_test {
$ildouble = &get_ulps ($test, $type, "ildouble");
$idouble = &get_ulps ($test, $type, "idouble");
$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
sub output_ulps {
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: $!");

print ULP "/* This file is automatically generated\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";

foreach $fct (keys %results) {
$type = $results{$fct}{'type'};
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";
foreach $fct (@functions) {
output_test (\*ULP, $fct, $fct);
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";
for ($i = 0; $i < $count; $i++) {
output_test (\*ULP, $tests[$i], $i);
print ULP "static const struct ulp_data test_ulps[] =\n {\n";
foreach $fct (sort keys %test_ulps) {
print ULP " { \"$fct\", $test_ulps{$fct} },\n";
}
print ULP " };\n";
close ULP;
}

0 comments on commit 3779b5b

Please sign in to comment.