This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] Add convenience target to automatically update ULPs for your machine.
- From: "Carlos O'Donell" <carlos at redhat dot com>
- To: GNU C Library <libc-alpha at sourceware dot org>, Roland McGrath <roland at hack dot frob dot com>
- Date: Thu, 04 Apr 2013 18:59:56 -0400
- Subject: [PATCH] Add convenience target to automatically update ULPs for your machine.
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 following convenience target does this automatically for
developers (with some tweaks to libm-test.inc to support read-only
source directories).
When run it does the following:
* Start with the baseline ULPs file.
* Run each of the libm math tests with -u.
* Add new changes seen with -u to the baseline.
* Sort and prepare the tests with gen-libm-test.pl.
* Leave math/NewUlps for you to copy to your source
tree, cleanup, and checkin.
It looks like this if you don't have perl installed:
~~~
...
Automatic regeneration of ULPs requires perl.
make[1]: *** [regenulps] Error 1
make[1]: Leaving directory `/home/carlos/src/glibc/math'
make: *** [regenulps] Error 2
~~~
It looks like this if you have perl installed and nothing has changed:
~~~
[carlos@koi glibc]$ make regenulps
make -C /home/carlos/src/glibc/math objdir=`pwd` regenulps
make[1]: Entering directory `/home/carlos/src/glibc/math'
make[1]: Leaving directory `/home/carlos/src/glibc/math'
make[1]: Entering directory `/home/carlos/src/glibc/math'
rm -f /home/carlos/build/glibc/math/ULPs; rm -f /home/carlos/build/glibc/math/NewUlps; \
cp ../sysdeps/x86_64/fpu/libm-test-ulps /home/carlos/build/glibc/math/libm-test-ulps; \
for run in /home/carlos/build/glibc/math/test-float /home/carlos/build/glibc/math/test-double /home/carlos/build/glibc/math/test-ldouble /home/carlos/build/glibc/math/test-ildoubl /home/carlos/build/glibc/math/test-ifloat /home/carlos/build/glibc/math/test-idouble; do \
echo "Regenerating ULPs for ${run}"; \
eval env GCONV_PATH=/home/carlos/build/glibc/iconvdata LC_ALL=C /home/carlos/build/glibc/elf/ld-linux-x86-64.so.2 --library-path /home/carlos/build/glibc:/home/carlos/build/glibc/math:/home/carlos/build/glibc/elf:/home/carlos/build/glibc/dlfcn:/home/carlos/build/glibc/nss:/home/carlos/build/glibc/nis:/home/carlos/build/glibc/rt:/home/carlos/build/glibc/resolv:/home/carlos/build/glibc/crypt:/home/carlos/build/glibc/nptl /home/carlos/build/glibc/math/test-double -u -o /home/carlos/build/glibc/math/; \
cat /home/carlos/build/glibc/math/ULPs >> /home/carlos/build/glibc/math/libm-test-ulps; \
rm /home/carlos/build/glibc/math/ULPs; \
done; \
/usr/bin/perl gen-libm-test.pl -o /home/carlos/build/glibc/math/ -n -u /home/carlos/build/glibc/math/libm-test-ulps; \
diff -urN ../sysdeps/x86_64/fpu/libm-test-ulps /home/carlos/build/glibc/math/NewUlps; \
echo "Automatic regeneration of ULPs complete."; \
echo "Copy /home/carlos/build/glibc/math/NewUlps to ../sysdeps/x86_64/fpu/libm-test-ulps, clean up, and checkin changes."
Regenerating ULPs for /home/carlos/build/glibc/math/test-float
testing double (without inline functions)
Test suite completed:
7928 test cases plus 7308 tests for exception flags executed.
All tests passed successfully.
Regenerating ULPs for /home/carlos/build/glibc/math/test-double
testing double (without inline functions)
Test suite completed:
7928 test cases plus 7308 tests for exception flags executed.
All tests passed successfully.
Regenerating ULPs for /home/carlos/build/glibc/math/test-ldouble
testing double (without inline functions)
Test suite completed:
7928 test cases plus 7308 tests for exception flags executed.
All tests passed successfully.
Regenerating ULPs for /home/carlos/build/glibc/math/test-ildoubl
testing double (without inline functions)
Test suite completed:
7928 test cases plus 7308 tests for exception flags executed.
All tests passed successfully.
Regenerating ULPs for /home/carlos/build/glibc/math/test-ifloat
testing double (without inline functions)
Test suite completed:
7928 test cases plus 7308 tests for exception flags executed.
All tests passed successfully.
Regenerating ULPs for /home/carlos/build/glibc/math/test-idouble
testing double (without inline functions)
Test suite completed:
7928 test cases plus 7308 tests for exception flags executed.
All tests passed successfully.
Automatic regeneration of ULPs complete.
Copy /home/carlos/build/glibc/math/NewUlps to ../sysdeps/x86_64/fpu/libm-test-ulps, clean up, and checkin changes.
make[1]: Leaving directory `/home/carlos/src/glibc/math'
~~~
It looks like this if you have perl installed and ULPs is not up to date:
~~~
[carlos@koi glibc]$ make regenulps
make -C /home/carlos/src/glibc/math objdir=`pwd` regenulps
make[1]: Entering directory `/home/carlos/src/glibc/math'
...
echo "Automatic regeneration of ULPs complete."; \
echo "Copy /home/carlos/build/glibc/math/NewUlps to ../sysdeps/x86_64/fpu/libm-test-ulps, clean up, and checkin changes."
Regenerating ULPs for /home/carlos/build/glibc/math/test-float
testing double (without inline functions)
Failure: Test: Imaginary part of: cpow (-1 - 0 i, -1 - 0 i) == -1.0 - 0.0 i
Result:
is: -1.22464679914735320717e-16 -0x1.1a62633145c070000000p-53
should be: -0.00000000000000000000e+00 -0x0.00000000000000000000p+0
difference: 1.22464679914735320717e-16 0x1.1a62633145c070000000p-53
ulp : 0.5515
max.ulp : 0.0000
Failure: Test: Imaginary part of: cpow (-1 + +0 i, -1 + +0 i) == -1.0 - 0.0 i
Result:
is: -1.22464679914735320717e-16 -0x1.1a62633145c070000000p-53
should be: -0.00000000000000000000e+00 -0x0.00000000000000000000p+0
difference: 1.22464679914735320717e-16 0x1.1a62633145c070000000p-53
ulp : 0.5515
max.ulp : 0.0000
Test suite completed:
7928 test cases plus 7308 tests for exception flags executed.
2 errors occurred.
...
--- ../sysdeps/x86_64/fpu/libm-test-ulps 2013-04-04 18:50:39.882446238 -0400
+++ /home/carlos/build/glibc/math/NewUlps 2013-04-04 18:51:14.704157971 -0400
@@ -4901,6 +4901,10 @@
ldouble: 1
# cpow
+Test "Imaginary part of: cpow (-1 + +0 i, -1 + +0 i) == -1.0 - 0.0 i":
+double: 1
+Test "Imaginary part of: cpow (-1 - 0 i, -1 - 0 i) == -1.0 - 0.0 i":
+double: 1
Test "Real part of: cpow (0.75 + 1.25 i, 0.0 + 1.0 i) == 0.331825439177608832276067945276730566 + 0.131338600281188544930936345230903032 i":
float: 1
ifloat: 1
Automatic regeneration of ULPs complete.
Copy /home/carlos/build/glibc/math/NewUlps to ../sysdeps/x86_64/fpu/libm-test-ulps, clean up, and checkin changes.
make[1]: Leaving directory `/home/carlos/src/glibc/math'
[carlos@koi glibc]$
~~~
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).
OK to checkin?
2013-04-04 Carlos O'Donell <carlos@redhat.com>
* Makefile.in (regenulps): New target.
* math/Makefile (regenulps): 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 "".
diff --git a/Makefile.in b/Makefile.in
index df75b8f..1c96974 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -14,3 +14,8 @@ install:
bench:
$(MAKE) -C $(srcdir)/benchtests $(PARALLELMFLAGS) objdir=`pwd` $@
+
+# Convenience target to rebuild ULPs for all math tests.
+regenulps:
+ $(MAKE) -C $(srcdir)/math $(PARALLELMFLAGS) objdir=`pwd` $@
+
diff --git a/math/Makefile b/math/Makefile
index f396ba2..0544c8b 100644
--- a/math/Makefile
+++ b/math/Makefile
@@ -150,6 +150,27 @@ extra-objs += libieee.a ieee-math.o
include ../Rules
+ifneq (no,$(PERL))
+# Run the math programs to automatically generate ULPs files.
+.PHONY: regenulps
+regenulps: $(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}"; \
+ eval $(make-test-out) -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; \
+ diff -urN $(ulps-file) $(objpfx)NewUlps; \
+ echo "Automatic regeneration of ULPs complete."; \
+ echo "Copy $(objpfx)NewUlps to $(ulps-file), clean up, and checkin changes."
+else
+regenulps:
+ @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.
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 08c80fa..c745db9 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -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) */
@@ -12960,6 +12965,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 }
};
@@ -12991,6 +12998,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;
@@ -13040,11 +13054,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;
@@ -13060,7 +13077,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: ");
---
Cheers,
Carlos.