aboutsummaryrefslogtreecommitdiff
path: root/math/gen-libm-test.py
diff options
context:
space:
mode:
Diffstat (limited to 'math/gen-libm-test.py')
-rwxr-xr-xmath/gen-libm-test.py75
1 files changed, 17 insertions, 58 deletions
diff --git a/math/gen-libm-test.py b/math/gen-libm-test.py
index 397dbd3..1abc7fb 100755
--- a/math/gen-libm-test.py
+++ b/math/gen-libm-test.py
@@ -1,6 +1,6 @@
#!/usr/bin/python3
# Generate tests for libm functions.
-# Copyright (C) 2018-2024 Free Software Foundation, Inc.
+# Copyright (C) 2018-2025 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
#
# The GNU C Library is free software; you can redistribute it and/or
@@ -93,8 +93,7 @@ BEAUTIFY_MAP = {'minus_zero': '-0',
# Flags in auto-libm-test-out that map directly to C flags.
FLAGS_SIMPLE = {'ignore-zero-inf-sign': 'IGNORE_ZERO_INF_SIGN',
- 'xfail': 'XFAIL_TEST',
- 'no-mathvec': 'NO_TEST_MATHVEC'}
+ 'xfail': 'XFAIL_TEST'}
# Exceptions in auto-libm-test-out, and their corresponding C flags
# for being required, OK or required to be absent.
@@ -103,7 +102,7 @@ EXC_EXPECTED = {'divbyzero': 'DIVBYZERO_EXCEPTION',
'invalid': 'INVALID_EXCEPTION',
'overflow': 'OVERFLOW_EXCEPTION',
'underflow': 'UNDERFLOW_EXCEPTION'}
-EXC_OK = {'divbyzero': 'DIVBYZERO_EXCEPTION_OK',
+EXC_OK = {'divbyzero': 'DIVIDE_BY_ZERO_EXCEPTION_OK',
'inexact': '0',
'invalid': 'INVALID_EXCEPTION_OK',
'overflow': 'OVERFLOW_EXCEPTION_OK',
@@ -122,19 +121,20 @@ class Ulps(object):
"""Initialize an Ulps object."""
# normal[function][float_type] is the ulps value, and likewise
# for real and imag.
- self.normal = defaultdict(lambda: defaultdict(lambda: 0))
- self.real = defaultdict(lambda: defaultdict(lambda: 0))
- self.imag = defaultdict(lambda: defaultdict(lambda: 0))
+ self.normal = defaultdict(lambda: defaultdict(lambda: -1))
+ self.real = defaultdict(lambda: defaultdict(lambda: -1))
+ self.imag = defaultdict(lambda: defaultdict(lambda: -1))
# List of ulps kinds, in the order in which they appear in
# sorted ulps files.
self.ulps_kinds = (('Real part of ', self.real),
('Imaginary part of ', self.imag),
('', self.normal))
+ self.ulps_file = []
self
def read(self, ulps_file):
"""Read ulps from a file into an Ulps object."""
- self.ulps_file = ulps_file
+ self.ulps_file.append(ulps_file)
with open(ulps_file, 'r') as f:
ulps_dict = None
ulps_fn = None
@@ -166,10 +166,7 @@ class Ulps(object):
if line_first not in ALL_FLOATS:
raise ValueError('bad ulps line: %s' % line)
ulps_val = int(line_second)
- if ulps_val > 0:
- ulps_dict[ulps_fn][line_first] = max(
- ulps_dict[ulps_fn][line_first],
- ulps_val)
+ ulps_dict[ulps_fn][line_first] = ulps_val
def all_functions(self):
"""Return the set of functions with ulps and whether they are
@@ -182,27 +179,6 @@ class Ulps(object):
complex[f] = True if k_prefix else False
return funcs, complex
- def write(self, ulps_file):
- """Write ulps back out as a sorted ulps file."""
- # Output is sorted first by function name, then by (real,
- # imag, normal), then by float type.
- out_data = {}
- for order, (prefix, d) in enumerate(self.ulps_kinds):
- for fn in d.keys():
- fn_data = ['%s: %d' % (f, d[fn][f])
- for f in sorted(d[fn].keys())]
- fn_text = 'Function: %s"%s":\n%s' % (prefix, fn,
- '\n'.join(fn_data))
- out_data[(fn, order)] = fn_text
- out_list = [out_data[fn_order] for fn_order in sorted(out_data.keys())]
- out_text = ('# Begin of automatic generation\n\n'
- '# Maximal error of functions:\n'
- '%s\n\n'
- '# end of automatic generation\n'
- % '\n\n'.join(out_list))
- with open(ulps_file, 'w') as f:
- f.write(out_text)
-
@staticmethod
def ulps_table(name, ulps_dict):
"""Return text of a C table of ulps."""
@@ -221,14 +197,14 @@ class Ulps(object):
"""Write header file with ulps data."""
header_text_1 = ('/* This file is automatically generated\n'
' from %s with gen-libm-test.py.\n'
- ' Don\'t change it - change instead the master '
+ ' Don\'t change it - change the original source '
'files. */\n\n'
'struct ulp_data\n'
'{\n'
' const char *name;\n'
' FLOAT max_ulp[%d];\n'
'};'
- % (self.ulps_file, len(ALL_FLOATS)))
+ % (', '.join(self.ulps_file), len(ALL_FLOATS)))
macro_list = []
for i, f in enumerate(ALL_FLOATS):
if f.startswith('i'):
@@ -252,18 +228,6 @@ class Ulps(object):
f.write(header_text)
-def read_all_ulps(srcdir):
- """Read all platforms' libm-test-ulps files."""
- all_ulps = {}
- for dirpath, dirnames, filenames in os.walk(srcdir):
- if 'libm-test-ulps' in filenames:
- with open(os.path.join(dirpath, 'libm-test-ulps-name')) as f:
- name = f.read().rstrip()
- all_ulps[name] = Ulps()
- all_ulps[name].read(os.path.join(dirpath, 'libm-test-ulps'))
- return all_ulps
-
-
def read_auto_tests(test_file):
"""Read tests from auto-libm-test-out-<function> (possibly None)."""
auto_tests = defaultdict(lambda: defaultdict(dict))
@@ -654,12 +618,8 @@ def main():
help='input file with automatically generated tests')
parser.add_argument('-c', dest='inc_input', metavar='FILE',
help='input file .inc file with tests')
- parser.add_argument('-u', dest='ulps_file', metavar='FILE',
- help='input file with ulps')
- parser.add_argument('-s', dest='srcdir', metavar='DIR',
- help='input source directory with all ulps')
- parser.add_argument('-n', dest='ulps_output', metavar='FILE',
- help='generate sorted ulps file FILE')
+ parser.add_argument('-u', dest='ulps_file', metavar='list',
+ help='input files with ulps (multiple input separated by colon')
parser.add_argument('-C', dest='c_output', metavar='FILE',
help='generate output C file FILE from .inc file')
parser.add_argument('-H', dest='ulps_header', metavar='FILE',
@@ -669,12 +629,11 @@ def main():
args = parser.parse_args()
ulps = Ulps()
if args.ulps_file is not None:
- ulps.read(args.ulps_file)
+ # Iterate in reverse order so arch specific definitions can override
+ # the generic ones.
+ for ulp_file in reversed(args.ulps_file.split(':')):
+ ulps.read(ulp_file)
auto_tests = read_auto_tests(args.auto_input)
- if args.srcdir is not None:
- all_ulps = read_all_ulps(args.srcdir)
- if args.ulps_output is not None:
- ulps.write(args.ulps_output)
if args.ulps_header is not None:
ulps.write_header(args.ulps_header)
if args.c_output is not None: