2 # Generate tests for <tgmath.h> macros.
3 # Copyright (C) 2017-2023 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
23 # _Float32x if any argument has a _FloatNx type and otherwise as
24 # double. The corresponding complex types may also be used (including
25 # complex integer types, which are a GNU extension, but are currently
26 # disabled here because they do not work properly with tgmath.h).
28 # C2x makes the <tgmath.h> rules for selecting a function to call
29 # correspond to the usual arithmetic conversions (applied successively
30 # to the arguments for generic parameters in order), which choose the
31 # type whose set of values contains that of the other type (undefined
32 # behavior if neither type's set of values is a superset of the
33 # other), with interchange types being preferred to standard types
34 # (long double, double, float), being preferred to extended types
35 # (_Float128x, _Float64x, _Float32x).
37 # For the standard and binary floating-point types supported by GCC 7
38 # on any platform, this means the resulting type is the last of the
39 # given types in one of the following orders, or undefined behavior if
40 # types with both ibm128 and binary128 representation are specified.
42 # If double = long double: _Float16, float, _Float32, _Float32x,
43 # double, long double, _Float64, _Float64x, _Float128.
45 # Otherwise: _Float16, float, _Float32, _Float32x, double, _Float64,
46 # _Float64x, long double, _Float128.
48 # We generate tests to verify the return type is exactly as expected.
49 # We also verify that the function called is real or complex as
50 # expected, and that it is called for the right floating-point format
51 # (but it is OK to call a double function instead of a long double one
52 # if they have the same format, for example). For all the formats
53 # supported on any given configuration of glibc, the MANT_DIG value
54 # uniquely determines the format.
60 """A type that may be used as an argument for generic parameters."""
62 # All possible argument or result types.
65 argument_types_list
= []
66 # All real argument types.
67 real_argument_types_list
= []
68 # Real argument types that correspond to a standard floating type
69 # (float, double or long double; not _FloatN or _FloatNx).
70 standard_real_argument_types_list
= []
71 # The real floating types by their order properties (which are
72 # tuples giving the positions in both the possible orders above).
76 # The type long double.
77 long_double_type
= None
78 # The type _Complex double.
79 complex_double_type
= None
82 # The type _Complex _Float64.
83 complex_float64_type
= None
86 # The type _Complex _Float32x.
87 complex_float32x_type
= None
91 def __init__(self
, name
, suffix
=None, mant_dig
=None, condition
='1',
92 order
=None, integer
=False, complex=False, real_type
=None,
94 """Initialize a Type object, creating any corresponding complex type
98 self
.mant_dig
= mant_dig
99 self
.condition
= condition
101 self
.integer
= integer
102 self
.complex = complex
103 self
.floatnx
= floatnx
105 self
.complex_type
= self
106 self
.real_type
= real_type
108 # complex_type filled in by the caller once created.
109 self
.complex_type
= None
110 self
.real_type
= self
112 def register_type(self
, internal
):
113 """Record a type in the lists of all types."""
114 Type
.all_types_list
.append(self
)
116 Type
.argument_types_list
.append(self
)
118 Type
.real_argument_types_list
.append(self
)
119 if not self
.name
.startswith('_Float'):
120 Type
.standard_real_argument_types_list
.append(self
)
121 if self
.order
is not None:
122 Type
.real_types_order
[self
.order
] = self
123 if self
.name
== 'double':
124 Type
.double_type
= self
125 if self
.name
== 'long double':
126 Type
.long_double_type
= self
127 if self
.name
== '_Complex double':
128 Type
.complex_double_type
= self
129 if self
.name
== '_Float64':
130 Type
.float64_type
= self
131 if self
.name
== '_Complex _Float64':
132 Type
.complex_float64_type
= self
133 if self
.name
== '_Float32x':
134 Type
.float32x_type
= self
135 if self
.name
== '_Complex _Float32x':
136 Type
.complex_float32x_type
= self
137 if self
.name
== '_Float64x':
138 Type
.float64x_type
= self
141 def create_type(name
, suffix
=None, mant_dig
=None, condition
='1', order
=None,
142 integer
=False, complex_name
=None, complex_ok
=True,
143 floatnx
=False, internal
=False):
144 """Create and register a Type object for a real type, creating any
145 corresponding complex type in the process."""
146 real_type
= Type(name
, suffix
=suffix
, mant_dig
=mant_dig
,
147 condition
=condition
, order
=order
, integer
=integer
,
148 complex=False, floatnx
=floatnx
)
150 if complex_name
is None:
151 complex_name
= '_Complex %s' % name
152 complex_type
= Type(complex_name
, condition
=condition
,
153 integer
=integer
, complex=True,
154 real_type
=real_type
, floatnx
=floatnx
)
157 real_type
.complex_type
= complex_type
158 real_type
.register_type(internal
)
159 if complex_type
is not None:
160 complex_type
.register_type(internal
)
162 def floating_type(self
, integer_float32x
):
163 """Return the corresponding floating type."""
166 return (Type
.complex_float32x_type
168 else Type
.float32x_type
)
170 return (Type
.complex_double_type
172 else Type
.double_type
)
176 def real_floating_type(self
, integer_float32x
):
177 """Return the corresponding real floating type."""
178 return self
.real_type
.floating_type(integer_float32x
)
181 """Return string representation of a type."""
186 """Initialize all the known types."""
187 Type
.create_type('_Float16', 'f16', 'FLT16_MANT_DIG',
188 complex_name
='__CFLOAT16',
189 condition
='defined HUGE_VAL_F16', order
=(0, 0))
190 Type
.create_type('float', 'f', 'FLT_MANT_DIG', order
=(1, 1))
191 Type
.create_type('_Float32', 'f32', 'FLT32_MANT_DIG',
192 complex_name
='__CFLOAT32',
193 condition
='defined HUGE_VAL_F32', order
=(2, 2))
194 Type
.create_type('_Float32x', 'f32x', 'FLT32X_MANT_DIG',
195 complex_name
='__CFLOAT32X',
196 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),
207 Type
.create_type('_Float128', 'f128', 'FLT128_MANT_DIG',
208 complex_name
='__CFLOAT128',
209 condition
='defined HUGE_VAL_F128', order
=(8, 8))
210 Type
.create_type('char', integer
=True)
211 Type
.create_type('signed char', integer
=True)
212 Type
.create_type('unsigned char', integer
=True)
213 Type
.create_type('short int', integer
=True)
214 Type
.create_type('unsigned short int', integer
=True)
215 Type
.create_type('int', integer
=True)
216 Type
.create_type('unsigned int', integer
=True)
217 Type
.create_type('long int', integer
=True)
218 Type
.create_type('unsigned long int', integer
=True)
219 Type
.create_type('long long int', integer
=True)
220 Type
.create_type('unsigned long long int', integer
=True)
221 Type
.create_type('__int128', integer
=True,
222 condition
='defined __SIZEOF_INT128__')
223 Type
.create_type('unsigned __int128', integer
=True,
224 condition
='defined __SIZEOF_INT128__')
225 Type
.create_type('enum e', integer
=True, complex_ok
=False)
226 Type
.create_type('_Bool', integer
=True, complex_ok
=False)
227 Type
.create_type('bit_field', integer
=True, complex_ok
=False)
228 # Internal types represent the combination of long double with
229 # _Float64 or _Float64x, for which the ordering depends on
230 # whether long double has the same format as double.
231 Type
.create_type('long_double_Float64', None, 'LDBL_MANT_DIG',
232 complex_name
='complex_long_double_Float64',
233 condition
='defined HUGE_VAL_F64', order
=(6, 7),
235 Type
.create_type('long_double_Float64x', None, 'FLT64X_MANT_DIG',
236 complex_name
='complex_long_double_Float64x',
237 condition
='defined HUGE_VAL_F64X', order
=(7, 7),
241 def can_combine_types(types
):
242 """Return a C preprocessor conditional for whether the given list of
243 types can be used together as type-generic macro arguments."""
244 have_long_double
= False
245 have_float128
= False
246 integer_float32x
= any(t
.floatnx
for t
in types
)
248 t
= t
.real_floating_type(integer_float32x
)
249 if t
.name
== 'long double':
250 have_long_double
= True
251 if t
.name
== '_Float128' or t
.name
== '_Float64x':
253 if have_long_double
and have_float128
:
254 # If ibm128 format is in use for long double, both
255 # _Float64x and _Float128 are binary128 and the types
256 # cannot be combined.
257 return '(LDBL_MANT_DIG != 106)'
261 def combine_types(types
):
262 """Return the result of combining a set of types."""
265 integer_float32x
= any(t
.floatnx
for t
in types
)
269 t
= t
.real_floating_type(integer_float32x
)
273 order
= (max(combined
.order
[0], t
.order
[0]),
274 max(combined
.order
[1], t
.order
[1]))
275 combined
= Type
.real_types_order
[order
]
276 return combined
.complex_type
if have_complex
else combined
278 def list_product_initial(initial
, lists
):
279 """Return a list of lists, with an initial sequence from the first
280 argument (a list of lists) followed by each sequence of one
281 element from each successive element of the second argument."""
284 return list_product_initial([a
+ [b
] for a
in initial
for b
in lists
[0]],
287 def list_product(lists
):
288 """Return a list of lists, with each sequence of one element from each
289 successive element of the argument."""
290 return list_product_initial([[]], lists
)
293 trans_id
= str.maketrans(' *', '_p')
294 except AttributeError:
295 trans_id
= string
.maketrans(' *', '_p')
296 def var_for_type(name
):
297 """Return the name of a variable with a given type (name)."""
298 return 'var_%s' % name
.translate(trans_id
)
300 def vol_var_for_type(name
):
301 """Return the name of a variable with a given volatile type (name)."""
302 return 'vol_var_%s' % name
.translate(trans_id
)
304 def define_vars_for_type(name
):
305 """Return the definitions of variables with a given type (name)."""
306 if name
== 'bit_field':
307 struct_vars
= define_vars_for_type('struct s');
308 return '%s#define %s %s.bf\n' % (struct_vars
,
309 vol_var_for_type(name
),
310 vol_var_for_type('struct s'))
311 return ('%s %s __attribute__ ((unused));\n'
312 '%s volatile %s __attribute__ ((unused));\n'
313 % (name
, var_for_type(name
), name
, vol_var_for_type(name
)))
315 def if_cond_text(conds
, text
):
316 """Return the result of making some text conditional under #if. The
317 text ends with a newline, as does the return value if not empty."""
320 conds
= [c
for c
in conds
if c
!= '1']
321 conds
= sorted(set(conds
))
324 return '#if %s\n%s#endif\n' % (' && '.join(conds
), text
)
327 """The state associated with testcase generation."""
330 """Initialize a Tests object."""
331 self
.header_list
= ['#define __STDC_WANT_IEC_60559_TYPES_EXT__\n'
332 '#include <float.h>\n'
333 '#include <stdbool.h>\n'
334 '#include <stdint.h>\n'
335 '#include <stdio.h>\n'
336 '#include <string.h>\n'
337 '#include <tgmath.h>\n'
341 ' void (*func) (void);\n'
342 ' const char *func_name;\n'
343 ' const char *test_name;\n'
345 ' int narrow_mant_dig;\n'
347 'int num_pass, num_fail;\n'
348 'volatile int called_mant_dig;\n'
349 'const char *volatile called_func_name;\n'
355 float64_text
= ('# if LDBL_MANT_DIG == DBL_MANT_DIG\n'
356 'typedef _Float64 long_double_Float64;\n'
357 'typedef __CFLOAT64 complex_long_double_Float64;\n'
359 'typedef long double long_double_Float64;\n'
360 'typedef _Complex long double '
361 'complex_long_double_Float64;\n'
363 float64_text
= if_cond_text([Type
.float64_type
.condition
],
365 float64x_text
= ('# if LDBL_MANT_DIG == DBL_MANT_DIG\n'
366 'typedef _Float64x long_double_Float64x;\n'
367 'typedef __CFLOAT64X complex_long_double_Float64x;\n'
369 'typedef long double long_double_Float64x;\n'
370 'typedef _Complex long double '
371 'complex_long_double_Float64x;\n'
373 float64x_text
= if_cond_text([Type
.float64x_type
.condition
],
375 self
.header_list
.append(float64_text
)
376 self
.header_list
.append(float64x_text
)
377 self
.types_seen
= set()
378 for t
in Type
.all_types_list
:
379 self
.add_type_var(t
.name
, t
.condition
)
380 self
.test_text_list
= []
381 self
.test_array_list
= []
382 self
.macros_seen
= set()
384 def add_type_var(self
, name
, cond
):
385 """Add declarations of variables for a type."""
386 if name
in self
.types_seen
:
388 t_vars
= define_vars_for_type(name
)
389 self
.header_list
.append(if_cond_text([cond
], t_vars
))
390 self
.types_seen
.add(name
)
392 def add_tests(self
, macro
, ret
, args
, complex_func
=None):
393 """Add tests for a given tgmath.h macro, if that is the macro for
394 which tests are to be generated; otherwise just add it to the
395 list of macros for which test generation is supported."""
396 # 'c' means the function argument or return type is
397 # type-generic and complex only (a complex function argument
398 # may still have a real macro argument). 'g' means it is
399 # type-generic and may be real or complex; 'r' means it is
400 # type-generic and may only be real; 's' means the same as
401 # 'r', but restricted to float, double and long double.
402 self
.macros_seen
.add(macro
)
403 if macro
!= self
.macro
:
408 narrowing_std
= False
409 if ret
== 'c' or 'c' in args
:
414 elif ret
== 'g' or 'g' in args
:
417 if complex_func
== None:
418 complex_func
= 'c%s' % func
419 # For narrowing macros, compute narrow_args, the list of
420 # argument types for which there is an actual corresponding
421 # function. If none of those types exist, or the return type
422 # does not exist, then the macro is not defined and no tests
428 narrow_args
= [Type
.double_type
, Type
.long_double_type
]
429 elif ret
== 'double':
433 narrow_args
= [Type
.long_double_type
]
434 elif ret
.startswith('_Float'):
439 for order
, real_type
in sorted(Type
.real_types_order
.items()):
440 if real_type
.name
== ret
:
441 nret_type
= real_type
442 elif nret_type
and real_type
.name
.startswith('_Float'):
443 if ret
.endswith('x') == real_type
.name
.endswith('x'):
444 narrow_args_1
.append(real_type
)
446 narrow_args_2
.append(real_type
)
447 narrow_args
= narrow_args_1
+ narrow_args_2
449 narrow_cond
= ('(%s && (%s))'
450 % (nret_type
.condition
,
451 ' || '.join(t
.condition
452 for t
in narrow_args
)))
454 # No possible argument types, even conditionally.
458 if t
!= 'c' and t
!= 'g' and t
!= 'r' and t
!= 's':
459 self
.add_type_var(t
, '1')
460 for t
in Type
.argument_types_list
:
463 if t
.complex and not have_complex
:
465 if func
== None and not t
.complex:
467 if ret
== 's' and t
.name
.startswith('_Float'):
469 if narrowing
and t
not in narrow_args
:
472 ret_name
= t
.complex_type
.name
475 elif ret
== 'r' or ret
== 's':
476 ret_name
= t
.real_type
.name
479 dummy_func_name
= complex_func
if t
.complex else func
484 arg_name
= t
.complex_type
.name
487 elif a
== 'r' or a
== 's':
488 arg_name
= t
.real_type
.name
491 arg_list
.append('%s arg%d __attribute__ ((unused))'
492 % (arg_name
, arg_num
))
497 ' called_mant_dig = %s;\n'
498 ' called_func_name = "%s";\n'
500 '}\n' % (ret_name
, dummy_func_name
,
501 t
.real_type
.suffix
, ', '.join(arg_list
),
502 t
.real_type
.mant_dig
, dummy_func_name
))
504 dummy_cond
= [narrow_cond
, t
.condition
]
506 dummy_cond
= [t
.condition
]
507 dummy_func
= if_cond_text(dummy_cond
, dummy_func
)
508 self
.test_text_list
.append(dummy_func
)
511 if t
== 'g' or t
== 'c':
512 arg_types
.append(Type
.argument_types_list
)
514 arg_types
.append(Type
.real_argument_types_list
)
516 arg_types
.append(Type
.standard_real_argument_types_list
)
517 arg_types_product
= list_product(arg_types
)
519 for this_args
in arg_types_product
:
520 comb_type
= Type
.combine_types(this_args
)
522 # As long as there are no integer arguments, and as
523 # long as the chosen argument type is as wide as all
524 # the floating-point arguments passed, the semantics
525 # of the macro call do not depend on the exact
526 # function chosen. In particular, for f32x functions
527 # when _Float64x exists, the chosen type should differ
528 # for double / _Float32x and _Float64 arguments, but
529 # it is not always possible to distinguish those types
530 # before GCC 7 (resulting in some cases - only real
531 # arguments - where a wider argument type is used,
532 # which is semantically OK, and others - integer
533 # arguments present - where it may not be OK, but is
535 narrow_mant_dig
= comb_type
.real_type
.mant_dig
536 for arg_type
in this_args
:
541 can_comb
= Type
.can_combine_types(this_args
)
542 all_conds
= [t
.condition
for t
in this_args
]
543 narrow_args_cond
= '(%s)' % ' && '.join(sorted(set(all_conds
)))
544 all_conds
.append(can_comb
)
546 all_conds
.append(narrow_cond
)
547 any_complex
= func
== None
551 func_name
= complex_func
if any_complex
else func
552 test_name
= '%s (%s)' % (macro
,
553 ', '.join([t
.name
for t
in this_args
]))
554 test_func_name
= 'test_%s_%d' % (macro
, test_num
)
556 mant_dig
= comb_type
.real_type
.mant_dig
557 test_mant_dig_comp
= ''
559 and comb_type
not in narrow_args
):
560 # The expected argument type is the first in
561 # narrow_args that can represent all the values of
562 # comb_type (which, for the supported cases, means the
563 # first with mant_dig at least as large as that for
564 # comb_type, provided this isn't the case of an IBM
565 # long double argument with binary128 type from
567 narrow_extra_conds
= []
568 test_mant_dig_list
= ['#undef NARROW_MANT_DIG\n#if 0\n']
569 for t
in narrow_args
:
570 t_cond
= '(%s && %s && %s <= %s && %s)' % (
571 narrow_args_cond
, t
.condition
, mant_dig
, t
.mant_dig
,
572 Type
.can_combine_types(this_args
+ [t
]))
573 narrow_extra_conds
.append(t_cond
)
574 test_mant_dig_list
.append('#elif %s\n'
575 '#define NARROW_MANT_DIG %s\n'
576 % (t_cond
, t
.mant_dig
))
577 test_mant_dig_list
.append('#endif\n')
578 test_mant_dig_comp
= ''.join(test_mant_dig_list
)
579 all_conds
.append('(%s)' % ' || '.join(narrow_extra_conds
))
580 # A special case where this logic isn't correct is
581 # where comb_type is the internal long_double_Float64
582 # or long_double_Float64x, which will be detected as
583 # not in narrow_args even if the actual type chosen in
584 # a particular configuration would have been in
585 # narrow_args, so check for that case and handle it
586 # appropriately. In particular, if long double has
587 # the same format as double and there are long double
588 # and _Float64 arguments, and the macro returns
589 # _Float32x, the function called should be one for
590 # _Float64 arguments, not one for _Float64x arguments
591 # that would arise from this logic.
592 if comb_type
.real_type
.name
== 'long_double_Float64':
593 comb_type_1
= Type
.long_double_type
594 comb_type_2
= Type
.float64_type
595 comb_type_is_2_cond
= 'LDBL_MANT_DIG <= FLT64_MANT_DIG'
596 elif comb_type
.real_type
.name
== 'long_double_Float64x':
597 comb_type_1
= Type
.long_double_type
598 comb_type_2
= Type
.float64x_type
599 comb_type_is_2_cond
= 'LDBL_MANT_DIG < FLT64X_MANT_DIG'
603 if comb_type_1
is None:
604 mant_dig
= 'NARROW_MANT_DIG'
607 if comb_type_1
in narrow_args
:
608 mant_dig
+= '!(%s) ? %s : ' % (comb_type_is_2_cond
,
609 comb_type_1
.mant_dig
)
610 if comb_type_2
in narrow_args
:
611 mant_dig
+= '%s ? %s : ' % (comb_type_is_2_cond
,
612 comb_type_2
.mant_dig
)
613 mant_dig
+= 'NARROW_MANT_DIG'
614 if narrow_mant_dig
!= 0:
615 narrow_mant_dig
= mant_dig
616 test_text
= '%s, "%s", "%s", %s, %s' % (test_func_name
, func_name
,
619 test_text
= '%s { %s },\n' % (test_mant_dig_comp
, test_text
)
620 test_text
= if_cond_text(all_conds
, test_text
)
621 self
.test_array_list
.append(test_text
)
625 if t
== 'g' or t
== 'c' or t
== 'r' or t
== 's':
626 type = this_args
[call_arg_pos
].name
630 call_args
.append(vol_var_for_type(type))
631 call_args_text
= ', '.join(call_args
)
633 ret_type
= comb_type
.name
634 elif ret
== 'r' or ret
== 's':
635 ret_type
= comb_type
.real_type
.name
637 ret_type
= comb_type
.complex_type
.name
640 call_text
= '%s (%s)' % (macro
, call_args_text
)
641 test_func_text
= ('static void\n'
644 ' extern typeof (%s) %s '
645 '__attribute__ ((unused));\n'
647 '}\n' % (test_func_name
, call_text
,
648 var_for_type(ret_type
),
649 vol_var_for_type(ret_type
), call_text
))
650 test_func_text
= if_cond_text(all_conds
, test_func_text
)
651 self
.test_text_list
.append(test_func_text
)
653 def add_all_tests(self
, macro
):
654 """Add tests for the given tgmath.h macro, if any, and generate the
655 list of all supported macros."""
657 # C99/C11 real-only functions.
658 self
.add_tests('atan2', 'r', ['r', 'r'])
659 self
.add_tests('cbrt', 'r', ['r'])
660 self
.add_tests('ceil', 'r', ['r'])
661 self
.add_tests('copysign', 'r', ['r', 'r'])
662 self
.add_tests('erf', 'r', ['r'])
663 self
.add_tests('erfc', 'r', ['r'])
664 self
.add_tests('exp2', 'r', ['r'])
665 self
.add_tests('expm1', 'r', ['r'])
666 self
.add_tests('fdim', 'r', ['r', 'r'])
667 self
.add_tests('floor', 'r', ['r'])
668 self
.add_tests('fma', 'r', ['r', 'r', 'r'])
669 self
.add_tests('fmax', 'r', ['r', 'r'])
670 self
.add_tests('fmin', 'r', ['r', 'r'])
671 self
.add_tests('fmod', 'r', ['r', 'r'])
672 self
.add_tests('frexp', 'r', ['r', 'int *'])
673 self
.add_tests('hypot', 'r', ['r', 'r'])
674 self
.add_tests('ilogb', 'int', ['r'])
675 self
.add_tests('ldexp', 'r', ['r', 'int'])
676 self
.add_tests('lgamma', 'r', ['r'])
677 self
.add_tests('llrint', 'long long int', ['r'])
678 self
.add_tests('llround', 'long long int', ['r'])
679 # log10 is real-only in ISO C, but supports complex arguments
680 # as a GNU extension.
681 self
.add_tests('log10', 'g', ['g'])
682 self
.add_tests('log1p', 'r', ['r'])
683 self
.add_tests('log2', 'r', ['r'])
684 self
.add_tests('logb', 'r', ['r'])
685 self
.add_tests('lrint', 'long int', ['r'])
686 self
.add_tests('lround', 'long int', ['r'])
687 self
.add_tests('nearbyint', 'r', ['r'])
688 self
.add_tests('nextafter', 'r', ['r', 'r'])
689 self
.add_tests('nexttoward', 's', ['s', 'long double'])
690 self
.add_tests('remainder', 'r', ['r', 'r'])
691 self
.add_tests('remquo', 'r', ['r', 'r', 'int *'])
692 self
.add_tests('rint', 'r', ['r'])
693 self
.add_tests('round', 'r', ['r'])
694 self
.add_tests('scalbn', 'r', ['r', 'int'])
695 self
.add_tests('scalbln', 'r', ['r', 'long int'])
696 self
.add_tests('tgamma', 'r', ['r'])
697 self
.add_tests('trunc', 'r', ['r'])
698 # C99/C11 real-and-complex functions.
699 self
.add_tests('acos', 'g', ['g'])
700 self
.add_tests('asin', 'g', ['g'])
701 self
.add_tests('atan', 'g', ['g'])
702 self
.add_tests('acosh', 'g', ['g'])
703 self
.add_tests('asinh', 'g', ['g'])
704 self
.add_tests('atanh', 'g', ['g'])
705 self
.add_tests('cos', 'g', ['g'])
706 self
.add_tests('sin', 'g', ['g'])
707 self
.add_tests('tan', 'g', ['g'])
708 self
.add_tests('cosh', 'g', ['g'])
709 self
.add_tests('sinh', 'g', ['g'])
710 self
.add_tests('tanh', 'g', ['g'])
711 self
.add_tests('exp', 'g', ['g'])
712 self
.add_tests('log', 'g', ['g'])
713 self
.add_tests('pow', 'g', ['g', 'g'])
714 self
.add_tests('sqrt', 'g', ['g'])
715 self
.add_tests('fabs', 'r', ['g'], 'cabs')
716 # C99/C11 complex-only functions.
717 self
.add_tests('carg', 'r', ['c'])
718 self
.add_tests('cimag', 'r', ['c'])
719 self
.add_tests('conj', 'c', ['c'])
720 self
.add_tests('cproj', 'c', ['c'])
721 self
.add_tests('creal', 'r', ['c'])
722 # TS 18661-1 functions.
723 self
.add_tests('roundeven', 'r', ['r'])
724 self
.add_tests('nextup', 'r', ['r'])
725 self
.add_tests('nextdown', 'r', ['r'])
726 self
.add_tests('fminmag', 'r', ['r', 'r'])
727 self
.add_tests('fmaxmag', 'r', ['r', 'r'])
728 self
.add_tests('llogb', 'long int', ['r'])
729 self
.add_tests('fromfp', 'intmax_t', ['r', 'int', 'unsigned int'])
730 self
.add_tests('fromfpx', 'intmax_t', ['r', 'int', 'unsigned int'])
731 self
.add_tests('ufromfp', 'uintmax_t', ['r', 'int', 'unsigned int'])
732 self
.add_tests('ufromfpx', 'uintmax_t', ['r', 'int', 'unsigned int'])
733 for fn
, args
in (('add', 2), ('div', 2), ('fma', 3), ('mul', 2),
734 ('sqrt', 1), ('sub', 2)):
735 for ret
, prefix
in (('float', 'f'),
740 ('_Float128', 'f128'),
741 ('_Float32x', 'f32x'),
742 ('_Float64x', 'f64x')):
743 self
.add_tests(prefix
+ fn
, ret
, ['r'] * args
)
744 # TS 18661-4 functions.
745 self
.add_tests('exp10', 'r', ['r'])
747 self
.add_tests('fmaximum', 'r', ['r', 'r'])
748 self
.add_tests('fmaximum_mag', 'r', ['r', 'r'])
749 self
.add_tests('fmaximum_num', 'r', ['r', 'r'])
750 self
.add_tests('fmaximum_mag_num', 'r', ['r', 'r'])
751 self
.add_tests('fminimum', 'r', ['r', 'r'])
752 self
.add_tests('fminimum_mag', 'r', ['r', 'r'])
753 self
.add_tests('fminimum_num', 'r', ['r', 'r'])
754 self
.add_tests('fminimum_mag_num', 'r', ['r', 'r'])
755 # Miscellaneous functions.
756 self
.add_tests('scalb', 's', ['s', 's'])
758 def tests_text(self
):
759 """Return the text of the generated testcase."""
760 test_list
= [''.join(self
.test_text_list
),
761 'static const struct test tests[] =\n'
763 ''.join(self
.test_array_list
),
765 footer_list
= ['static int\n'
768 ' for (size_t i = 0;\n'
769 ' i < sizeof (tests) / sizeof (tests[0]);\n'
772 ' called_mant_dig = 0;\n'
773 ' called_func_name = "";\n'
774 ' tests[i].func ();\n'
775 ' if (called_mant_dig == tests[i].mant_dig\n'
776 ' && strcmp (called_func_name,\n'
777 ' tests[i].func_name) == 0)\n'
779 '#if !__GNUC_PREREQ (7, 0)\n'
780 ' else if (tests[i].narrow_mant_dig > 0\n'
781 ' && (called_mant_dig\n'
782 ' >= tests[i].narrow_mant_dig)\n'
783 ' && strcmp (called_func_name,\n'
784 ' tests[i].func_name) == 0)\n'
787 ' printf ("Test %zu (%s):\\n"\n'
788 ' " Expected: %s precision %d\\n"\n'
789 ' " Actual: %s precision %d\\n"\n'
790 ' " (OK with old GCC)\\n\\n",\n'
791 ' i, tests[i].test_name,\n'
792 ' tests[i].func_name,\n'
793 ' tests[i].mant_dig,\n'
794 ' called_func_name, called_mant_dig);\n'
796 ' else if (tests[i].narrow_mant_dig == 0\n'
797 ' && strcmp (called_func_name,\n'
798 ' tests[i].func_name) == 0)\n'
801 ' printf ("Test %zu (%s):\\n"\n'
802 ' " Expected: %s precision %d\\n"\n'
803 ' " Actual: %s precision %d\\n"\n'
804 ' " (unavoidable with old GCC)'
806 ' i, tests[i].test_name,\n'
807 ' tests[i].func_name,\n'
808 ' tests[i].mant_dig,\n'
809 ' called_func_name, called_mant_dig);\n'
815 ' printf ("Test %zu (%s):\\n"\n'
816 ' " Expected: %s precision %d\\n"\n'
817 ' " Actual: %s precision %d\\n\\n",\n'
818 ' i, tests[i].test_name,\n'
819 ' tests[i].func_name,\n'
820 ' tests[i].mant_dig,\n'
821 ' called_func_name, called_mant_dig);\n'
824 ' printf ("%d pass, %d fail\\n", num_pass, num_fail);\n'
825 ' return num_fail != 0;\n'
828 '#include <support/test-driver.c>']
829 return ''.join(self
.header_list
+ test_list
+ footer_list
)
831 def check_macro_list(self
, macro_list
):
832 """Check the list of macros that can be tested."""
833 if self
.macros_seen
!= set(macro_list
):
834 print('error: macro list mismatch')
838 """The main entry point."""
841 if sys
.argv
[1] == 'check-list':
843 macro_list
= sys
.argv
[2:]
847 t
.add_all_tests(macro
)
849 print(t
.tests_text())
851 t
.check_macro_list(macro_list
)
853 if __name__
== '__main__':