2 # Generate tests for <tgmath.h> macros.
3 # Copyright (C) 2017-2022 Free Software Foundation, Inc.
4 # This file is part of the GNU C Library.
6 # The GNU C Library is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU Lesser General Public
8 # License as published by the Free Software Foundation; either
9 # version 2.1 of the License, or (at your option) any later version.
11 # The GNU C Library is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # Lesser General Public License for more details.
16 # You should have received a copy of the GNU Lesser General Public
17 # License along with the GNU C Library; if not, see
18 # <https://www.gnu.org/licenses/>.
20 # As glibc does not support decimal floating point, the types to
21 # consider for generic parameters are standard and binary
22 # floating-point types, and integer types which are treated as double.
23 # The corresponding complex types may also be used (including complex
24 # integer types, which are a GNU extension, but are currently disabled
25 # here because they do not work properly with tgmath.h).
27 # The proposed resolution to TS 18661-1 DR#9
28 # <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2149.htm#dr_9>
29 # makes the <tgmath.h> rules for selecting a function to call
30 # correspond to the usual arithmetic conversions (applied successively
31 # to the arguments for generic parameters in order), which choose the
32 # type whose set of values contains that of the other type (undefined
33 # behavior if neither type's set of values is a superset of the
34 # other), with interchange types being preferred to standard types
35 # (long double, double, float), being preferred to extended types
36 # (_Float128x, _Float64x, _Float32x).
38 # For the standard and binary floating-point types supported by GCC 7
39 # on any platform, this means the resulting type is the last of the
40 # given types in one of the following orders, or undefined behavior if
41 # types with both ibm128 and binary128 representation are specified.
43 # If double = long double: _Float16, float, _Float32, _Float32x,
44 # double, long double, _Float64, _Float64x, _Float128.
46 # Otherwise: _Float16, float, _Float32, _Float32x, double, _Float64,
47 # _Float64x, long double, _Float128.
49 # We generate tests to verify the return type is exactly as expected.
50 # We also verify that the function called is real or complex as
51 # expected, and that it is called for the right floating-point format
52 # (but it is OK to call a double function instead of a long double one
53 # if they have the same format, for example). For all the formats
54 # supported on any given configuration of glibc, the MANT_DIG value
55 # uniquely determines the format.
61 """A type that may be used as an argument for generic parameters."""
63 # All possible argument or result types.
66 argument_types_list = []
67 # All real argument types.
68 real_argument_types_list = []
69 # Real argument types that correspond to a standard floating type
70 # (float, double or long double; not _FloatN or _FloatNx).
71 standard_real_argument_types_list = []
72 # Real argument types other than float, double and long double
73 # (i.e., those that are valid as arguments to narrowing macros
74 # returning _FloatN or _FloatNx).
75 non_standard_real_argument_types_list = []
76 # The real floating types by their order properties (which are
77 # tuples giving the positions in both the possible orders above).
81 # The type long double.
82 long_double_type = None
83 # The type _Complex double.
84 complex_double_type = None
87 # The type _Complex _Float64.
88 complex_float64_type = None
91 # The type _Float64x if available, otherwise _Float64.
92 float32x_ext_type = None
94 def __init__(self, name, suffix=None, mant_dig=None, condition='1',
95 order=None, integer=False, complex=False, real_type=None):
96 """Initialize a Type object, creating any corresponding complex type
100 self.mant_dig = mant_dig
101 self.condition = condition
103 self.integer = integer
104 self.complex = complex
106 self.complex_type = self
107 self.real_type = real_type
109 # complex_type filled in by the caller once created.
110 self.complex_type = None
111 self.real_type = self
113 def register_type(self, internal):
114 """Record a type in the lists of all types."""
115 Type.all_types_list.append(self)
117 Type.argument_types_list.append(self)
119 Type.real_argument_types_list.append(self)
120 if not self.name.startswith('_Float'):
121 Type.standard_real_argument_types_list.append(self)
122 if self.name not in ('float', 'double', 'long double'):
123 Type.non_standard_real_argument_types_list.append(self)
124 if self.order is not None:
125 Type.real_types_order[self.order] = self
126 if self.name == 'double':
127 Type.double_type = self
128 if self.name == 'long double':
129 Type.long_double_type = self
130 if self.name == '_Complex double':
131 Type.complex_double_type = self
132 if self.name == '_Float64':
133 Type.float64_type = self
134 if self.name == '_Complex _Float64':
135 Type.complex_float64_type = self
136 if self.name == '_Float64x':
137 Type.float64x_type = self
138 if self.name == 'Float32x_ext':
139 Type.float32x_ext_type = self
142 def create_type(name, suffix=None, mant_dig=None, condition='1', order=None,
143 integer=False, complex_name=None, complex_ok=True,
145 """Create and register a Type object for a real type, creating any
146 corresponding complex type in the process."""
147 real_type = Type(name, suffix=suffix, mant_dig=mant_dig,
148 condition=condition, order=order, integer=integer,
151 if complex_name is None:
152 complex_name = '_Complex %s' % name
153 complex_type = Type(complex_name, condition=condition,
154 integer=integer, complex=True,
158 real_type.complex_type = complex_type
159 real_type.register_type(internal)
160 if complex_type is not None:
161 complex_type.register_type(internal)
163 def floating_type(self, floatn):
164 """Return the corresponding floating type."""
167 return (Type.complex_float64_type
169 else Type.float64_type)
171 return (Type.complex_double_type
173 else Type.double_type)
177 def real_floating_type(self, floatn):
178 """Return the corresponding real floating type."""
179 return self.real_type.floating_type(floatn)
182 """Return string representation of a type."""
187 """Initialize all the known types."""
188 Type.create_type('_Float16', 'f16', 'FLT16_MANT_DIG',
189 complex_name='__CFLOAT16',
190 condition='defined HUGE_VAL_F16', order=(0, 0))
191 Type.create_type('float', 'f', 'FLT_MANT_DIG', order=(1, 1))
192 Type.create_type('_Float32', 'f32', 'FLT32_MANT_DIG',
193 complex_name='__CFLOAT32',
194 condition='defined HUGE_VAL_F32', order=(2, 2))
195 Type.create_type('_Float32x', 'f32x', 'FLT32X_MANT_DIG',
196 complex_name='__CFLOAT32X',
197 condition='defined HUGE_VAL_F32X', order=(3, 3))
198 Type.create_type('double', '', 'DBL_MANT_DIG', order=(4, 4))
199 Type.create_type('long double', 'l', 'LDBL_MANT_DIG', order=(5, 7))
200 Type.create_type('_Float64', 'f64', 'FLT64_MANT_DIG',
201 complex_name='__CFLOAT64',
202 condition='defined HUGE_VAL_F64', order=(6, 5))
203 Type.create_type('_Float64x', 'f64x', 'FLT64X_MANT_DIG',
204 complex_name='__CFLOAT64X',
205 condition='defined HUGE_VAL_F64X', order=(7, 6))
206 Type.create_type('_Float128', 'f128', 'FLT128_MANT_DIG',
207 complex_name='__CFLOAT128',
208 condition='defined HUGE_VAL_F128', order=(8, 8))
209 Type.create_type('char', integer=True)
210 Type.create_type('signed char', integer=True)
211 Type.create_type('unsigned char', integer=True)
212 Type.create_type('short int', integer=True)
213 Type.create_type('unsigned short int', integer=True)
214 Type.create_type('int', integer=True)
215 Type.create_type('unsigned int', integer=True)
216 Type.create_type('long int', integer=True)
217 Type.create_type('unsigned long int', integer=True)
218 Type.create_type('long long int', integer=True)
219 Type.create_type('unsigned long long int', integer=True)
220 Type.create_type('__int128', integer=True,
221 condition='defined __SIZEOF_INT128__')
222 Type.create_type('unsigned __int128', integer=True,
223 condition='defined __SIZEOF_INT128__')
224 Type.create_type('enum e', integer=True, complex_ok=False)
225 Type.create_type('_Bool', integer=True, complex_ok=False)
226 Type.create_type('bit_field', integer=True, complex_ok=False)
227 # Internal types represent the combination of long double with
228 # _Float64 or _Float64x, for which the ordering depends on
229 # whether long double has the same format as double.
230 Type.create_type('long_double_Float64', None, 'LDBL_MANT_DIG',
231 complex_name='complex_long_double_Float64',
232 condition='defined HUGE_VAL_F64', order=(6, 7),
234 Type.create_type('long_double_Float64x', None, 'FLT64X_MANT_DIG',
235 complex_name='complex_long_double_Float64x',
236 condition='defined HUGE_VAL_F64X', order=(7, 7),
238 # An internal type for the argument type used by f32x*
239 # narrowing macros (_Float64x if available, otherwise
241 Type.create_type('Float32x_ext', None, 'FLT32X_EXT_MANT_DIG',
242 complex_name='complex_Float32x_ext',
243 condition='1', internal=True)
246 def can_combine_types(types, floatn):
247 """Return a C preprocessor conditional for whether the given list of
248 types can be used together as type-generic macro arguments."""
249 have_long_double = False
250 have_float128 = False
252 t = t.real_floating_type(floatn)
253 if t.name == 'long double':
254 have_long_double = True
255 if t.name == '_Float128' or t.name == '_Float64x':
257 if have_long_double and have_float128:
258 # If ibm128 format is in use for long double, both
259 # _Float64x and _Float128 are binary128 and the types
260 # cannot be combined.
261 return '(LDBL_MANT_DIG != 106)'
265 def combine_types(types, floatn):
266 """Return the result of combining a set of types."""
272 t = t.real_floating_type(floatn)
276 order = (max(combined.order[0], t.order[0]),
277 max(combined.order[1], t.order[1]))
278 combined = Type.real_types_order[order]
279 return combined.complex_type if have_complex else combined
281 def list_product_initial(initial, lists):
282 """Return a list of lists, with an initial sequence from the first
283 argument (a list of lists) followed by each sequence of one
284 element from each successive element of the second argument."""
287 return list_product_initial([a + [b] for a in initial for b in lists[0]],
290 def list_product(lists):
291 """Return a list of lists, with each sequence of one element from each
292 successive element of the argument."""
293 return list_product_initial([[]], lists)
296 trans_id = str.maketrans(' *', '_p')
297 except AttributeError:
298 trans_id = string.maketrans(' *', '_p')
299 def var_for_type(name):
300 """Return the name of a variable with a given type (name)."""
301 return 'var_%s' % name.translate(trans_id)
303 def vol_var_for_type(name):
304 """Return the name of a variable with a given volatile type (name)."""
305 return 'vol_var_%s' % name.translate(trans_id)
307 def define_vars_for_type(name):
308 """Return the definitions of variables with a given type (name)."""
309 if name == 'bit_field':
310 struct_vars = define_vars_for_type('struct s');
311 return '%s#define %s %s.bf\n' % (struct_vars,
312 vol_var_for_type(name),
313 vol_var_for_type('struct s'))
314 return ('%s %s __attribute__ ((unused));\n'
315 '%s volatile %s __attribute__ ((unused));\n'
316 % (name, var_for_type(name), name, vol_var_for_type(name)))
318 def if_cond_text(conds, text):
319 """Return the result of making some text conditional under #if. The
320 text ends with a newline, as does the return value if not empty."""
323 conds = [c for c in conds if c != '1']
324 conds = sorted(set(conds))
327 return '#if %s\n%s#endif\n' % (' && '.join(conds), text)
330 """The state associated with testcase generation."""
333 """Initialize a Tests object."""
334 self.header_list = ['#define __STDC_WANT_IEC_60559_TYPES_EXT__\n'
335 '#include <float.h>\n'
336 '#include <stdbool.h>\n'
337 '#include <stdint.h>\n'
338 '#include <stdio.h>\n'
339 '#include <string.h>\n'
340 '#include <tgmath.h>\n'
344 ' void (*func) (void);\n'
345 ' const char *func_name;\n'
346 ' const char *test_name;\n'
348 ' int narrow_mant_dig;\n'
350 'int num_pass, num_fail;\n'
351 'volatile int called_mant_dig;\n'
352 'const char *volatile called_func_name;\n'
358 float64_text = ('# if LDBL_MANT_DIG == DBL_MANT_DIG\n'
359 'typedef _Float64 long_double_Float64;\n'
360 'typedef __CFLOAT64 complex_long_double_Float64;\n'
362 'typedef long double long_double_Float64;\n'
363 'typedef _Complex long double '
364 'complex_long_double_Float64;\n'
366 float64_text = if_cond_text([Type.float64_type.condition],
368 float64x_text = ('# if LDBL_MANT_DIG == DBL_MANT_DIG\n'
369 'typedef _Float64x long_double_Float64x;\n'
370 'typedef __CFLOAT64X complex_long_double_Float64x;\n'
372 'typedef long double long_double_Float64x;\n'
373 'typedef _Complex long double '
374 'complex_long_double_Float64x;\n'
376 float64x_text = if_cond_text([Type.float64x_type.condition],
378 float32x_ext_text = ('#ifdef HUGE_VAL_F64X\n'
379 'typedef _Float64x Float32x_ext;\n'
380 'typedef __CFLOAT64X complex_Float32x_ext;\n'
381 '# define FLT32X_EXT_MANT_DIG FLT64X_MANT_DIG\n'
383 'typedef _Float64 Float32x_ext;\n'
384 'typedef __CFLOAT64 complex_Float32x_ext;\n'
385 '# define FLT32X_EXT_MANT_DIG FLT64_MANT_DIG\n'
387 self.header_list.append(float64_text)
388 self.header_list.append(float64x_text)
389 self.header_list.append(float32x_ext_text)
390 self.types_seen = set()
391 for t in Type.all_types_list:
392 self.add_type_var(t.name, t.condition)
393 self.test_text_list = []
394 self.test_array_list = []
395 self.macros_seen = set()
397 def add_type_var(self, name, cond):
398 """Add declarations of variables for a type."""
399 if name in self.types_seen:
401 t_vars = define_vars_for_type(name)
402 self.header_list.append(if_cond_text([cond], t_vars))
403 self.types_seen.add(name)
405 def add_tests(self, macro, ret, args, complex_func=None):
406 """Add tests for a given tgmath.h macro, if that is the macro for
407 which tests are to be generated; otherwise just add it to the
408 list of macros for which test generation is supported."""
409 # 'c' means the function argument or return type is
410 # type-generic and complex only (a complex function argument
411 # may still have a real macro argument). 'g' means it is
412 # type-generic and may be real or complex; 'r' means it is
413 # type-generic and may only be real; 's' means the same as
414 # 'r', but restricted to float, double and long double.
415 self.macros_seen.add(macro)
416 if macro != self.macro:
421 narrowing_std = False
422 if ret == 'c' or 'c' in args:
427 elif ret == 'g' or 'g' in args:
430 if complex_func == None:
431 complex_func = 'c%s' % func
432 # For narrowing macros, compute narrow_args, the list of
433 # argument types for which there is an actual corresponding
434 # function. If none of those types exist, or the return type
435 # does not exist, then the macro is not defined and no tests
441 narrow_args = [Type.double_type, Type.long_double_type]
442 narrow_fallback = Type.double_type
443 elif ret == 'double':
447 narrow_args = [Type.long_double_type]
448 narrow_fallback = Type.long_double_type
449 elif ret.startswith('_Float'):
453 narrow_fallback = None
454 for order, real_type in sorted(Type.real_types_order.items()):
455 if real_type.name == ret:
456 nret_type = real_type
457 elif nret_type and real_type.name.startswith('_Float'):
458 narrow_args.append(real_type)
459 if (narrow_fallback is None
460 and ret.endswith('x') == real_type.name.endswith('x')):
461 narrow_fallback = real_type
463 narrow_cond = ('(%s && (%s))'
464 % (nret_type.condition,
465 ' || '.join(t.condition
466 for t in narrow_args)))
467 if narrow_fallback is None:
468 narrow_fallback = narrow_args[0]
469 if ret == '_Float32x':
470 narrow_fallback = Type.float32x_ext_type
472 # No possible argument types, even conditionally.
474 narrowing_nonstd = narrowing and not narrowing_std
477 if t != 'c' and t != 'g' and t != 'r' and t != 's':
478 self.add_type_var(t, '1')
479 for t in Type.argument_types_list:
482 if t.complex and not have_complex:
484 if func == None and not t.complex:
486 if ret == 's' and t.name.startswith('_Float'):
488 if narrowing and t not in narrow_args:
491 ret_name = t.complex_type.name
494 elif ret == 'r' or ret == 's':
495 ret_name = t.real_type.name
498 dummy_func_name = complex_func if t.complex else func
503 arg_name = t.complex_type.name
506 elif a == 'r' or a == 's':
507 arg_name = t.real_type.name
510 arg_list.append('%s arg%d __attribute__ ((unused))'
511 % (arg_name, arg_num))
516 ' called_mant_dig = %s;\n'
517 ' called_func_name = "%s";\n'
519 '}\n' % (ret_name, dummy_func_name,
520 t.real_type.suffix, ', '.join(arg_list),
521 t.real_type.mant_dig, dummy_func_name))
523 dummy_cond = [narrow_cond, t.condition]
525 dummy_cond = [t.condition]
526 dummy_func = if_cond_text(dummy_cond, dummy_func)
527 self.test_text_list.append(dummy_func)
530 if t == 'g' or t == 'c':
531 arg_types.append(Type.argument_types_list)
534 arg_types.append(Type.standard_real_argument_types_list)
537 Type.non_standard_real_argument_types_list)
539 arg_types.append(Type.real_argument_types_list)
541 arg_types.append(Type.standard_real_argument_types_list)
542 arg_types_product = list_product(arg_types)
544 for this_args in arg_types_product:
545 comb_type = Type.combine_types(this_args, narrowing_nonstd)
547 # As long as there are no integer arguments, and as
548 # long as the chosen argument type is as wide as all
549 # the floating-point arguments passed, the semantics
550 # of the macro call do not depend on the exact
551 # function chosen. In particular, for f32x functions
552 # when _Float64x exists, the chosen type should differ
553 # for _Float32x and _Float64 arguments, but it is not
554 # always possible to distinguish those types before
555 # GCC 7 and the implementation does not attempt to do
557 narrow_mant_dig = comb_type.real_type.mant_dig
558 for arg_type in this_args:
564 and comb_type not in narrow_args
565 and narrow_fallback is not None):
566 comb_type = narrow_fallback
567 can_comb = Type.can_combine_types(this_args, narrowing_nonstd)
568 all_conds = [t.condition for t in this_args]
569 all_conds.append(can_comb)
571 all_conds.append(narrow_cond)
572 any_complex = func == None
576 func_name = complex_func if any_complex else func
577 test_name = '%s (%s)' % (macro,
578 ', '.join([t.name for t in this_args]))
579 test_func_name = 'test_%s_%d' % (macro, test_num)
581 mant_dig = comb_type.real_type.mant_dig
582 test_text = '%s, "%s", "%s", %s, %s' % (test_func_name, func_name,
585 test_text = ' { %s },\n' % test_text
586 test_text = if_cond_text(all_conds, test_text)
587 self.test_array_list.append(test_text)
591 if t == 'g' or t == 'c' or t == 'r' or t == 's':
592 type = this_args[call_arg_pos].name
596 call_args.append(vol_var_for_type(type))
597 call_args_text = ', '.join(call_args)
599 ret_type = comb_type.name
600 elif ret == 'r' or ret == 's':
601 ret_type = comb_type.real_type.name
603 ret_type = comb_type.complex_type.name
606 call_text = '%s (%s)' % (macro, call_args_text)
607 test_func_text = ('static void\n'
610 ' extern typeof (%s) %s '
611 '__attribute__ ((unused));\n'
613 '}\n' % (test_func_name, call_text,
614 var_for_type(ret_type),
615 vol_var_for_type(ret_type), call_text))
616 test_func_text = if_cond_text(all_conds, test_func_text)
617 self.test_text_list.append(test_func_text)
619 def add_all_tests(self, macro):
620 """Add tests for the given tgmath.h macro, if any, and generate the
621 list of all supported macros."""
623 # C99/C11 real-only functions.
624 self.add_tests('atan2', 'r', ['r', 'r'])
625 self.add_tests('cbrt', 'r', ['r'])
626 self.add_tests('ceil', 'r', ['r'])
627 self.add_tests('copysign', 'r', ['r', 'r'])
628 self.add_tests('erf', 'r', ['r'])
629 self.add_tests('erfc', 'r', ['r'])
630 self.add_tests('exp2', 'r', ['r'])
631 self.add_tests('expm1', 'r', ['r'])
632 self.add_tests('fdim', 'r', ['r', 'r'])
633 self.add_tests('floor', 'r', ['r'])
634 self.add_tests('fma', 'r', ['r', 'r', 'r'])
635 self.add_tests('fmax', 'r', ['r', 'r'])
636 self.add_tests('fmin', 'r', ['r', 'r'])
637 self.add_tests('fmod', 'r', ['r', 'r'])
638 self.add_tests('frexp', 'r', ['r', 'int *'])
639 self.add_tests('hypot', 'r', ['r', 'r'])
640 self.add_tests('ilogb', 'int', ['r'])
641 self.add_tests('ldexp', 'r', ['r', 'int'])
642 self.add_tests('lgamma', 'r', ['r'])
643 self.add_tests('llrint', 'long long int', ['r'])
644 self.add_tests('llround', 'long long int', ['r'])
645 # log10 is real-only in ISO C, but supports complex arguments
646 # as a GNU extension.
647 self.add_tests('log10', 'g', ['g'])
648 self.add_tests('log1p', 'r', ['r'])
649 self.add_tests('log2', 'r', ['r'])
650 self.add_tests('logb', 'r', ['r'])
651 self.add_tests('lrint', 'long int', ['r'])
652 self.add_tests('lround', 'long int', ['r'])
653 self.add_tests('nearbyint', 'r', ['r'])
654 self.add_tests('nextafter', 'r', ['r', 'r'])
655 self.add_tests('nexttoward', 's', ['s', 'long double'])
656 self.add_tests('remainder', 'r', ['r', 'r'])
657 self.add_tests('remquo', 'r', ['r', 'r', 'int *'])
658 self.add_tests('rint', 'r', ['r'])
659 self.add_tests('round', 'r', ['r'])
660 self.add_tests('scalbn', 'r', ['r', 'int'])
661 self.add_tests('scalbln', 'r', ['r', 'long int'])
662 self.add_tests('tgamma', 'r', ['r'])
663 self.add_tests('trunc', 'r', ['r'])
664 # C99/C11 real-and-complex functions.
665 self.add_tests('acos', 'g', ['g'])
666 self.add_tests('asin', 'g', ['g'])
667 self.add_tests('atan', 'g', ['g'])
668 self.add_tests('acosh', 'g', ['g'])
669 self.add_tests('asinh', 'g', ['g'])
670 self.add_tests('atanh', 'g', ['g'])
671 self.add_tests('cos', 'g', ['g'])
672 self.add_tests('sin', 'g', ['g'])
673 self.add_tests('tan', 'g', ['g'])
674 self.add_tests('cosh', 'g', ['g'])
675 self.add_tests('sinh', 'g', ['g'])
676 self.add_tests('tanh', 'g', ['g'])
677 self.add_tests('exp', 'g', ['g'])
678 self.add_tests('log', 'g', ['g'])
679 self.add_tests('pow', 'g', ['g', 'g'])
680 self.add_tests('sqrt', 'g', ['g'])
681 self.add_tests('fabs', 'r', ['g'], 'cabs')
682 # C99/C11 complex-only functions.
683 self.add_tests('carg', 'r', ['c'])
684 self.add_tests('cimag', 'r', ['c'])
685 self.add_tests('conj', 'c', ['c'])
686 self.add_tests('cproj', 'c', ['c'])
687 self.add_tests('creal', 'r', ['c'])
688 # TS 18661-1 functions.
689 self.add_tests('roundeven', 'r', ['r'])
690 self.add_tests('nextup', 'r', ['r'])
691 self.add_tests('nextdown', 'r', ['r'])
692 self.add_tests('fminmag', 'r', ['r', 'r'])
693 self.add_tests('fmaxmag', 'r', ['r', 'r'])
694 self.add_tests('llogb', 'long int', ['r'])
695 self.add_tests('fromfp', 'intmax_t', ['r', 'int', 'unsigned int'])
696 self.add_tests('fromfpx', 'intmax_t', ['r', 'int', 'unsigned int'])
697 self.add_tests('ufromfp', 'uintmax_t', ['r', 'int', 'unsigned int'])
698 self.add_tests('ufromfpx', 'uintmax_t', ['r', 'int', 'unsigned int'])
699 for fn, args in (('add', 2), ('div', 2), ('fma', 3), ('mul', 2),
700 ('sqrt', 1), ('sub', 2)):
701 for ret, prefix in (('float', 'f'),
706 ('_Float128', 'f128'),
707 ('_Float32x', 'f32x'),
708 ('_Float64x', 'f64x')):
709 self.add_tests(prefix + fn, ret, ['r'] * args)
710 # TS 18661-4 functions.
711 self.add_tests('exp10', 'r', ['r'])
713 self.add_tests('fmaximum', 'r', ['r', 'r'])
714 self.add_tests('fmaximum_mag', 'r', ['r', 'r'])
715 self.add_tests('fmaximum_num', 'r', ['r', 'r'])
716 self.add_tests('fmaximum_mag_num', 'r', ['r', 'r'])
717 self.add_tests('fminimum', 'r', ['r', 'r'])
718 self.add_tests('fminimum_mag', 'r', ['r', 'r'])
719 self.add_tests('fminimum_num', 'r', ['r', 'r'])
720 self.add_tests('fminimum_mag_num', 'r', ['r', 'r'])
721 # Miscellaneous functions.
722 self.add_tests('scalb', 's', ['s', 's'])
724 def tests_text(self):
725 """Return the text of the generated testcase."""
726 test_list = [''.join(self.test_text_list),
727 'static const struct test tests[] =\n'
729 ''.join(self.test_array_list),
731 footer_list = ['static int\n'
734 ' for (size_t i = 0;\n'
735 ' i < sizeof (tests) / sizeof (tests[0]);\n'
738 ' called_mant_dig = 0;\n'
739 ' called_func_name = "";\n'
740 ' tests[i].func ();\n'
741 ' if (called_mant_dig == tests[i].mant_dig\n'
742 ' && strcmp (called_func_name,\n'
743 ' tests[i].func_name) == 0)\n'
745 '#if !__GNUC_PREREQ (8, 0)\n'
746 ' else if (tests[i].narrow_mant_dig > 0\n'
747 ' && (called_mant_dig\n'
748 ' >= tests[i].narrow_mant_dig)\n'
749 ' && strcmp (called_func_name,\n'
750 ' tests[i].func_name) == 0)\n'
753 ' printf ("Test %zu (%s):\\n"\n'
754 ' " Expected: %s precision %d\\n"\n'
755 ' " Actual: %s precision %d\\n"\n'
756 ' " (OK with old GCC)\\n\\n",\n'
757 ' i, tests[i].test_name,\n'
758 ' tests[i].func_name,\n'
759 ' tests[i].mant_dig,\n'
760 ' called_func_name, called_mant_dig);\n'
766 ' printf ("Test %zu (%s):\\n"\n'
767 ' " Expected: %s precision %d\\n"\n'
768 ' " Actual: %s precision %d\\n\\n",\n'
769 ' i, tests[i].test_name,\n'
770 ' tests[i].func_name,\n'
771 ' tests[i].mant_dig,\n'
772 ' called_func_name, called_mant_dig);\n'
775 ' printf ("%d pass, %d fail\\n", num_pass, num_fail);\n'
776 ' return num_fail != 0;\n'
779 '#include <support/test-driver.c>']
780 return ''.join(self.header_list + test_list + footer_list)
782 def check_macro_list(self, macro_list):
783 """Check the list of macros that can be tested."""
784 if self.macros_seen != set(macro_list):
785 print('error: macro list mismatch')
789 """The main entry point."""
792 if sys.argv[1] == 'check-list':
794 macro_list = sys.argv[2:]
798 t.add_all_tests(macro)
800 print(t.tests_text())
802 t.check_macro_list(macro_list)
804 if __name__ == '__main__':