New Makefile target `regen-ulps'.

The wiki "Regeneration" page has this to say about update ULPs.

"The libm-test-ulps files are semiautomatically updated. To
update an ulps baseline, run each of the failing tests (test-float,
 test-double, etc.) with -u; this will generate a file called ULPs;
concatenate each of those files with the existing libm-test-ulps
file, after removing any entries for particularly huge numbers of
ulps that you do not want to mark as expected. Then run
gen-libm-test.pl -n -u FILE where FILE is the concatenated file
produced in the previous step. This generates a file called
NewUlps which is the new sorted version of libm-test-ulps."

The same information is listed in math/README.libm-test, and is a
lot of manual work that you often want to run over-and-over again
while working on a particular test.

The `regen-ulps' convenience target does this automatically for
developers.

We strictly assume the source tree is readonly and add a
new --output-dir option to libm-test.inc to allow for writing
out ULPs to $(objpfx).

When run the new target does the following:
* Starts with the baseline ULPs file.
* Runs each of the libm math tests with -u.
* Adds new changes seen with -u to the baseline.
* Sorts and prepares the test output with gen-libm-test.pl.
* Leaves math/NewUlps in your build tree to copy to your source
  tree, cleanup, and checkin.

The math test documentation in math/README.libm-test is updated
document the new Makefile target.

---

2013-04-06  Carlos O'Donell  <carlos@redhat.com>

	* Makefile.in (regen-ulps): New target.
	* math/Makefile [ifneq (no,$(PERL)]: Declare regen-ulps with .PHONY.
	[ifneq (no,$(PERL)] (run-regen-ulps): New variable.
	[ifneq (no,$(PERL)] (regen-ulps): New target.
	[ifeq (no,$(PERL)] (regen-ulps): New target.
	* math/libm-test.inc (ulps_file_name): Define.
	(output_dir): New variable.
	(options): Add "output-dir" option.
	(parse_opt): Handle 'o' case.
	(main): If output_dir is non-NULL use it as a prefix
	otherwise use "".
	* math/README.libm-test: Update `How can I generate "libm-test-ulps"?'
This commit is contained in:
Carlos O'Donell 2013-04-06 16:22:47 -04:00
parent a01f19c8fb
commit 26510bdda1
5 changed files with 95 additions and 17 deletions

View File

@ -1,3 +1,18 @@
2013-04-06 Carlos O'Donell <carlos@redhat.com>
* Makefile.in (regen-ulps): New target.
* math/Makefile [ifneq (no,$(PERL)]: Declare regen-ulps with .PHONY.
[ifneq (no,$(PERL)] (run-regen-ulps): New variable.
[ifneq (no,$(PERL)] (regen-ulps): New target.
[ifeq (no,$(PERL)] (regen-ulps): New target.
* math/libm-test.inc (ulps_file_name): Define.
(output_dir): New variable.
(options): Add "output-dir" option.
(parse_opt): Handle 'o' case.
(main): If output_dir is non-NULL use it as a prefix
otherwise use "".
* math/README.libm-test: Update `How can I generate "libm-test-ulps"?'
2013-04-06 Carlos O'Donell <carlos@redhat.com>
[BZ #10060, #10062]

View File

@ -14,3 +14,7 @@ install:
bench:
$(MAKE) -C $(srcdir)/benchtests $(PARALLELMFLAGS) objdir=`pwd` $@
# Convenience target to rebuild ULPs for all math tests.
regen-ulps:
$(MAKE) -C $(srcdir)/math $(PARALLELMFLAGS) objdir=`pwd` $@

View File

@ -150,6 +150,33 @@ extra-objs += libieee.a ieee-math.o
include ../Rules
ifneq (no,$(PERL))
# Run the math programs to automatically generate ULPs files.
.PHONY: regen-ulps
run-regen-ulps = $(test-wrapper-env) \
GCONV_PATH=$(common-objpfx)iconvdata LC_ALL=C \
$($*-ENV) $(run-via-rtld-prefix) $${run}
regen-ulps: $(addprefix $(objpfx),$(libm-tests))
rm -f $(objpfx)ULPs; rm -f $(objpfx)NewUlps; \
cp $(ulps-file) $(objpfx)libm-test-ulps; \
for run in $^; do \
echo "Regenerating ULPs for $${run}"; \
$(run-regen-ulps) -u -o $(objpfx); \
cat $(objpfx)ULPs >> $(objpfx)libm-test-ulps; \
rm $(objpfx)ULPs; \
done; \
$(PERL) gen-libm-test.pl -o $(objpfx) -n -u $(objpfx)libm-test-ulps; \
echo "Automatic regeneration of ULPs complete."; \
echo "Difference between the current baseline and the new baseline is:";\
diff -urN $(ulps-file) $(objpfx)NewUlps; \
echo "Copy $(objpfx)NewUlps to $(ulps-file) (relative to source)."
else
regen-ulps:
@echo "Automatic regeneration of ULPs requires perl."; \
exit 1;
endif
# The generated sysd-rules file defines rules like this for sources
# coming from sysdeps/ directories. These rules find the generic sources.

View File

@ -39,24 +39,33 @@ platform specific sysdep directory.
How can I generate "libm-test-ulps"?
====================================
The test drivers have an option "-u" to output an unsorted list of all
epsilons that the functions have. The output can be read in directly
but it's better to pretty print it first. "gen-libm-test.pl" has an option
to generate a pretty-printed and sorted new ULPs file from the output
of the test drivers.
To automatically generate a new "libm-test-ulps" run "make regen-ulps".
This generates the file "math/NewUlps" in the build directory. The file
contains the sorted results of all the tests. You can use the "NewUlps"
file as the machine's updated "libm-test-ulps" file. Copy "NewUlps" to
"libm-test-ulps" in the appropriate machine sysdep directory. Verify
the changes, post your patch, and check it in after review.
To generate a new "libm-test-ulps" file, first remove "ULPs" file in the
current directory, then you can execute for example:
test-double -u --ignore-max-ulp=yes
To manually generate a new "libm-test-ulps" file, first remove "ULPs"
file in the current directory, then you can execute for example:
/build/elf/ld.so --library--path /build/:/build/elf:/build/math \
test-double -u --ignore-max-ulp=yes
This generates a file "ULPs" with all double ULPs in it, ignoring any
previous calculated ULPs.
Now generate the ULPs for all other formats, the tests will be appending
the data to the "ULPs" file. As final step run "gen-libm-test.pl" with the
file as input and ask to generate a pretty printed output in the file "NewUlps":
previously calculated ULPs, and running with the newly built dynamic
loader and math library (assumes you didn't install your build). Now
generate the ULPs for all other formats, the tests will be appending the
data to the "ULPs" file. As final step run "gen-libm-test.pl" with the
file as input and ask to generate a pretty printed output in the file
"NewUlps":
gen-libm-test.pl -u ULPs -n
Copy "NewUlps" to "libm-test-ulps" in the appropriate machine sysdep
directory.
Now you can rename "NewUlps" to "libm-test-ulps" and move it into
sysdeps.
Note that the test drivers have an option "-u" to output an unsorted
list of all epsilons that the functions have. The output can be read
in directly but it's better to pretty print it first.
"gen-libm-test.pl" has an option to generate a pretty-printed and
sorted new ULPs file from the output of the test drivers.
Contents of libm-test-ulps
==========================

View File

@ -210,8 +210,10 @@
#define M_PI_LOG10El M_PIl * M_LOG10El
#define M_SQRT_2_2 0.70710678118654752440084436210484903L /* sqrt (2) / 2 */
static FILE *ulps_file; /* File to document difference. */
static int output_ulps; /* Should ulps printed? */
#define ulps_file_name "ULPs" /* Name of the ULPs file. */
static FILE *ulps_file; /* File to document difference. */
static int output_ulps; /* Should ulps printed? */
static char *output_dir; /* Directory where generated files will be written. */
static int noErrors; /* number of errors */
static int noTests; /* number of tests (without testing exceptions) */
@ -12985,6 +12987,8 @@ static const struct argp_option options[] =
"Don't output results of functions invocations"},
{ "ignore-max-ulp", 'i', "yes/no", 0,
"Ignore given maximal errors"},
{ "output-dir", 'o', "DIR", 0,
"Directory where generated files will be placed"},
{ NULL, 0, NULL, 0, NULL }
};
@ -13016,6 +13020,13 @@ parse_opt (int key, char *arg, struct argp_state *state)
else if (strcmp (arg, "no") == 0)
ignore_max_ulp = 0;
break;
case 'o':
output_dir = (char *) malloc (strlen (arg) + 1);
if (output_dir != NULL)
strcpy (output_dir, arg);
else
return errno;
break;
case 'p':
output_points = 0;
break;
@ -13065,11 +13076,14 @@ main (int argc, char **argv)
{
int remaining;
char *ulps_file_path;
size_t dir_len = 0;
verbose = 1;
output_ulps = 0;
output_max_error = 1;
output_points = 1;
output_dir = NULL;
/* XXX set to 0 for releases. */
ignore_max_ulp = 0;
@ -13085,7 +13099,16 @@ main (int argc, char **argv)
if (output_ulps)
{
ulps_file = fopen ("ULPs", "a");
if (output_dir != NULL)
dir_len = strlen (output_dir);
ulps_file_path = (char *) malloc (dir_len + strlen (ulps_file_name) + 1);
if (ulps_file_path == NULL)
{
perror ("can't allocate path for `ULPs' file: ");
exit (1);
}
sprintf (ulps_file_path, "%s%s", output_dir == NULL ? "" : output_dir, ulps_file_name);
ulps_file = fopen (ulps_file_path, "a");
if (ulps_file == NULL)
{
perror ("can't open file `ULPs' for writing: ");