benchtests: skip over blank lines in benchmark input files
[glibc.git] / math / gen-auto-libm-tests.c
blob206a5d7475ddf7b7c3d5fb7c41ba93f60d89aa07
1 /* Generate expected output for libm tests with MPFR and MPC.
2 Copyright (C) 2013 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
19 /* Compile this program as:
21 gcc -std=gnu99 -O2 -Wall -Wextra gen-auto-libm-tests.c -lmpc -lmpfr -lgmp \
22 -o gen-auto-libm-tests
24 (use of current MPC and MPFR versions recommended) and run it as:
26 gen-auto-libm-tests auto-libm-test-in auto-libm-test-out
28 The input file auto-libm-test-in contains three kinds of lines:
30 Lines beginning with "#" are comments, and are ignored, as are
31 empty lines.
33 Other lines are test lines, of the form "function input1 input2
34 ... [flag1 flag2 ...]". Inputs are either finite real numbers or
35 integers, depending on the function under test. Real numbers may
36 be in any form acceptable to mpfr_strtofr (base 0); integers in any
37 form acceptable to mpz_set_str (base 0). In addition, real numbers
38 may be certain special strings such as "pi", as listed in the
39 special_real_inputs array.
41 Each flag is a flag name possibly followed by a series of
42 ":condition". Conditions may be any of the names of floating-point
43 formats in the floating_point_formats array, "long32" and "long64"
44 to indicate the number of bits in the "long" type, or other strings
45 for which libm-test.inc defines a TEST_COND_<condition> macro (with
46 "-"- changed to "_" in the condition name) evaluating to nonzero
47 when the condition is true and zero when the condition is false.
48 The meaning is that the flag applies to the test if all the listed
49 conditions are true. "flag:cond1:cond2 flag:cond3:cond4" means the
50 flag applies if ((cond1 && cond2) || (cond3 && cond4)).
52 A real number specified as an input is considered to represent the
53 set of real numbers arising from rounding the given number in any
54 direction for any supported floating-point format; any roundings
55 that give infinity are ignored. Each input on a test line has all
56 the possible roundings considered independently. Each resulting
57 choice of the tuple of inputs to the function is ignored if the
58 mathematical result of the function involves a NaN or an exact
59 infinity, and is otherwise considered for each floating-point
60 format for which all those inputs are exactly representable. Thus
61 tests may result in "overflow", "underflow" and "inexact"
62 exceptions; "invalid" may arise only when the final result type is
63 an integer type and it is the conversion of a mathematically
64 defined finite result to integer type that results in that
65 exception.
67 By default, it is assumed that "overflow" and "underflow"
68 exceptions should be correct, but that "inexact" exceptions should
69 only be correct for functions listed as exactly determined. For
70 such functions, "underflow" exceptions should respect whether the
71 machine has before-rounding or after-rounding tininess detection.
72 For other functions, it is considered that if the exact result is
73 somewhere between the greatest magnitude subnormal of a given sign
74 (exclusive) and the least magnitude normal of that sign
75 (inclusive), underflow exceptions are permitted but optional on all
76 machines, and they are also permitted but optional for smaller
77 subnormal exact results for functions that are not exactly
78 determined. errno setting is expected for overflow to infinity and
79 underflow to zero (for real functions), and for out-of-range
80 conversion of a finite result to integer type, and is considered
81 permitted but optional for all other cases where overflow
82 exceptions occur, and where underflow exceptions occur or are
83 permitted. In other cases (where no overflow or underflow is
84 permitted), errno is expected to be left unchanged.
86 The flag "no-test-inline" indicates a test is disabled for inline
87 function testing; "xfail" indicates the test is disabled as
88 expected to produce incorrect results, "xfail-rounding" indicates
89 the test is disabled only in rounding modes other than
90 round-to-nearest. Otherwise, test flags are of the form
91 "spurious-<exception>" and "missing-<exception>", for any exception
92 ("overflow", "underflow", "inexact", "invalid", "divbyzero"),
93 "spurious-errno" and "missing-errno", to indicate when tests are
94 expected to deviate from the exception and errno settings
95 corresponding to the mathematical results. "xfail",
96 "xfail-rounding", "spurious-" and "missing-" flags should be
97 accompanied by a comment referring to an open bug in glibc
98 Bugzilla.
100 The output file auto-libm-test-out contains the test lines from
101 auto-libm-test-in, and, after the line for a given test, some
102 number of output test lines. An output test line is of the form "=
103 function rounding-mode format input1 input2 ... : output1 output2
104 ... : flags". rounding-mode is "tonearest", "towardzero", "upward"
105 or "downward". format is a name from the floating_point_formats
106 array, possibly followed by a sequence of ":flag" for flags from
107 "long32", "long64", "before-rounding" and "after-rounding" (the
108 last two indicating tests where expectations for underflow
109 exceptions depend on how the architecture detects tininess).
110 Inputs and outputs are specified as hex floats with the required
111 suffix for the floating-point type, or plus_infty or minus_infty
112 for infinite expected results, or as integer constant expressions
113 (not necessarily with the right type) or IGNORE for integer inputs
114 and outputs. Flags are "no-test-inline", "xfail", "<exception>",
115 "<exception>-ok", "errno-<value>", "errno-<value>-ok", where
116 "<exception>" and "errno-<value>" are unconditional, indicating
117 that a correct result means the given exception should be raised or
118 errno should be set to the given value, and other settings may be
119 conditional or unconditional; "-ok" means not to test for the given
120 exception or errno value (whether because it was marked as possibly
121 missing or spurious, or because the calculation of correct results
122 indicated it was optional). */
124 #define _GNU_SOURCE
126 #include <assert.h>
127 #include <ctype.h>
128 #include <errno.h>
129 #include <error.h>
130 #include <stdbool.h>
131 #include <stdint.h>
132 #include <stdio.h>
133 #include <stdlib.h>
134 #include <string.h>
136 #include <gmp.h>
137 #include <mpfr.h>
138 #include <mpc.h>
140 #define ARRAY_SIZE(A) (sizeof (A) / sizeof ((A)[0]))
142 /* The supported floating-point formats. */
143 typedef enum
145 fp_flt_32,
146 fp_dbl_64,
147 fp_ldbl_96_intel,
148 fp_ldbl_96_m68k,
149 fp_ldbl_128,
150 fp_ldbl_128ibm,
151 fp_num_formats,
152 fp_first_format = 0
153 } fp_format;
155 /* Structure describing a single floating-point format. */
156 typedef struct
158 /* The name of the format. */
159 const char *name;
160 /* The suffix to use on floating-point constants with this
161 format. */
162 const char *suffix;
163 /* A string for the largest normal value, or NULL for IEEE formats
164 where this can be determined automatically. */
165 const char *max_string;
166 /* The number of mantissa bits. */
167 int mant_dig;
168 /* The least N such that 2^N overflows. */
169 int max_exp;
170 /* One more than the least N such that 2^N is normal. */
171 int min_exp;
172 /* The largest normal value. */
173 mpfr_t max;
174 /* The least positive normal value, 2^(MIN_EXP-1). */
175 mpfr_t min;
176 /* The greatest positive subnormal value. */
177 mpfr_t subnorm_max;
178 /* The least positive subnormal value, 2^(MIN_EXP-MANT_DIG). */
179 mpfr_t subnorm_min;
180 } fp_format_desc;
182 /* List of floating-point formats, in the same order as the fp_format
183 enumeration. */
184 static fp_format_desc fp_formats[fp_num_formats] =
186 { "flt-32", "f", NULL, 24, 128, -125, {}, {}, {}, {} },
187 { "dbl-64", "", NULL, 53, 1024, -1021, {}, {}, {}, {} },
188 { "ldbl-96-intel", "L", NULL, 64, 16384, -16381, {}, {}, {}, {} },
189 { "ldbl-96-m68k", "L", NULL, 64, 16384, -16382, {}, {}, {}, {} },
190 { "ldbl-128", "L", NULL, 113, 16384, -16381, {}, {}, {}, {} },
191 { "ldbl-128ibm", "L", "0x1.fffffffffffff7ffffffffffff8p+1023",
192 106, 1024, -968, {}, {}, {}, {} },
195 /* The supported rounding modes. */
196 typedef enum
198 rm_downward,
199 rm_tonearest,
200 rm_towardzero,
201 rm_upward,
202 rm_num_modes,
203 rm_first_mode = 0
204 } rounding_mode;
206 /* Structure describing a single rounding mode. */
207 typedef struct
209 /* The name of the rounding mode. */
210 const char *name;
211 /* The MPFR rounding mode. */
212 mpfr_rnd_t mpfr_mode;
213 } rounding_mode_desc;
215 /* List of rounding modes, in the same order as the rounding_mode
216 enumeration. */
217 static const rounding_mode_desc rounding_modes[rm_num_modes] =
219 { "downward", MPFR_RNDD },
220 { "tonearest", MPFR_RNDN },
221 { "towardzero", MPFR_RNDZ },
222 { "upward", MPFR_RNDU },
225 /* The supported exceptions. */
226 typedef enum
228 exc_divbyzero,
229 exc_inexact,
230 exc_invalid,
231 exc_overflow,
232 exc_underflow,
233 exc_num_exceptions,
234 exc_first_exception = 0
235 } fp_exception;
237 /* List of exceptions, in the same order as the fp_exception
238 enumeration. */
239 static const char *const exceptions[exc_num_exceptions] =
241 "divbyzero",
242 "inexact",
243 "invalid",
244 "overflow",
245 "underflow",
248 /* The internal precision to use for most MPFR calculations, which
249 must be at least 2 more than the greatest precision of any
250 supported floating-point format. */
251 static int internal_precision;
253 /* A value that overflows all supported floating-point formats. */
254 static mpfr_t global_max;
256 /* A value that is at most half the least subnormal in any
257 floating-point format and so is rounded the same way as all
258 sufficiently small positive values. */
259 static mpfr_t global_min;
261 /* The maximum number of (real or integer) arguments to a function
262 handled by this program (complex arguments count as two real
263 arguments). */
264 #define MAX_NARGS 4
266 /* The maximum number of (real or integer) return values from a
267 function handled by this program. */
268 #define MAX_NRET 2
270 /* A type of a function argument or return value. */
271 typedef enum
273 /* No type (not a valid argument or return value). */
274 type_none,
275 /* A floating-point value with the type corresponding to that of
276 the function. */
277 type_fp,
278 /* An integer value of type int. */
279 type_int,
280 /* An integer value of type long. */
281 type_long,
282 /* An integer value of type long long. */
283 type_long_long,
284 } arg_ret_type;
286 /* A type of a generic real or integer value. */
287 typedef enum
289 /* No type. */
290 gtype_none,
291 /* Floating-point (represented with MPFR). */
292 gtype_fp,
293 /* Integer (represented with GMP). */
294 gtype_int,
295 } generic_value_type;
297 /* A generic value (argument or result). */
298 typedef struct
300 /* The type of this value. */
301 generic_value_type type;
302 /* Its value. */
303 union
305 mpfr_t f;
306 mpz_t i;
307 } value;
308 } generic_value;
310 /* A type of input flag. */
311 typedef enum
313 flag_no_test_inline,
314 flag_xfail,
315 flag_xfail_rounding,
316 /* The "spurious" and "missing" flags must be in the same order as
317 the fp_exception enumeration. */
318 flag_spurious_divbyzero,
319 flag_spurious_inexact,
320 flag_spurious_invalid,
321 flag_spurious_overflow,
322 flag_spurious_underflow,
323 flag_spurious_errno,
324 flag_missing_divbyzero,
325 flag_missing_inexact,
326 flag_missing_invalid,
327 flag_missing_overflow,
328 flag_missing_underflow,
329 flag_missing_errno,
330 num_input_flag_types,
331 flag_first_flag = 0,
332 flag_spurious_first = flag_spurious_divbyzero,
333 flag_missing_first = flag_missing_divbyzero
334 } input_flag_type;
336 /* List of flags, in the same order as the input_flag_type
337 enumeration. */
338 static const char *const input_flags[num_input_flag_types] =
340 "no-test-inline",
341 "xfail",
342 "xfail-rounding",
343 "spurious-divbyzero",
344 "spurious-inexact",
345 "spurious-invalid",
346 "spurious-overflow",
347 "spurious-underflow",
348 "spurious-errno",
349 "missing-divbyzero",
350 "missing-inexact",
351 "missing-invalid",
352 "missing-overflow",
353 "missing-underflow",
354 "missing-errno",
357 /* An input flag, possibly conditional. */
358 typedef struct
360 /* The type of this flag. */
361 input_flag_type type;
362 /* The conditions on this flag, as a string ":cond1:cond2..." or
363 NULL. */
364 const char *cond;
365 } input_flag;
367 /* Structure describing a single test from the input file (which may
368 expand into many tests in the output). The choice of function,
369 which implies the numbers and types of arguments and results, is
370 implicit rather than stored in this structure (except as part of
371 the source line). */
372 typedef struct
374 /* The text of the input line describing the test, including the
375 trailing newline. */
376 const char *line;
377 /* The number of combinations of interpretations of input values for
378 different floating-point formats and rounding modes. */
379 size_t num_input_cases;
380 /* The corresponding lists of inputs. */
381 generic_value **inputs;
382 /* The number of flags for this test. */
383 size_t num_flags;
384 /* The corresponding list of flags. */
385 input_flag *flags;
386 /* The old output for this test. */
387 const char *old_output;
388 } input_test;
390 /* Ways to calculate a function. */
391 typedef enum
393 /* MPFR function with a single argument and result. */
394 mpfr_f_f,
395 } func_calc_method;
397 /* Description of how to calculate a function. */
398 typedef struct
400 /* Which method is used to calculate the function. */
401 func_calc_method method;
402 /* The specific function called. */
403 union
405 int (*mpfr_f_f) (mpfr_t, const mpfr_t, mpfr_rnd_t);
406 } func;
407 } func_calc_desc;
409 /* Structure describing a function handled by this program. */
410 typedef struct
412 /* The name of the function. */
413 const char *name;
414 /* The number of arguments. */
415 size_t num_args;
416 /* The types of the arguments. */
417 arg_ret_type arg_types[MAX_NARGS];
418 /* The number of return values. */
419 size_t num_ret;
420 /* The types of the return values. */
421 arg_ret_type ret_types[MAX_NRET];
422 /* Whether the function has exactly determined results and
423 exceptions. */
424 bool exact;
425 /* Whether the function is a complex function, so errno setting is
426 optional. */
427 bool complex_fn;
428 /* How to calculate this function. */
429 func_calc_desc calc;
430 /* The number of tests allocated for this function. */
431 size_t num_tests_alloc;
432 /* The number of tests for this function. */
433 size_t num_tests;
434 /* The tests themselves. */
435 input_test *tests;
436 } test_function;
438 #define FUNC_mpfr_f_f(NAME, MPFR_FUNC, EXACT) \
440 NAME, 1, { type_fp }, 1, { type_fp }, EXACT, false, \
441 { mpfr_f_f, { .mpfr_f_f = MPFR_FUNC } }, 0, 0, NULL \
444 /* List of functions handled by this program. */
445 static test_function test_functions[] =
447 FUNC_mpfr_f_f ("acos", mpfr_acos, false),
448 FUNC_mpfr_f_f ("acosh", mpfr_acosh, false),
449 FUNC_mpfr_f_f ("asin", mpfr_asin, false),
450 FUNC_mpfr_f_f ("asinh", mpfr_asinh, false),
451 FUNC_mpfr_f_f ("atan", mpfr_atan, false),
452 FUNC_mpfr_f_f ("atanh", mpfr_atanh, false),
453 FUNC_mpfr_f_f ("cbrt", mpfr_cbrt, false),
454 FUNC_mpfr_f_f ("cos", mpfr_cos, false),
455 FUNC_mpfr_f_f ("cosh", mpfr_cosh, false),
456 FUNC_mpfr_f_f ("erf", mpfr_erf, false),
457 FUNC_mpfr_f_f ("erfc", mpfr_erfc, false),
458 FUNC_mpfr_f_f ("exp", mpfr_exp, false),
459 FUNC_mpfr_f_f ("exp10", mpfr_exp10, false),
460 FUNC_mpfr_f_f ("exp2", mpfr_exp2, false),
461 FUNC_mpfr_f_f ("expm1", mpfr_expm1, false),
462 FUNC_mpfr_f_f ("j0", mpfr_j0, false),
463 FUNC_mpfr_f_f ("j1", mpfr_j1, false),
464 FUNC_mpfr_f_f ("log", mpfr_log, false),
465 FUNC_mpfr_f_f ("log10", mpfr_log10, false),
466 FUNC_mpfr_f_f ("log1p", mpfr_log1p, false),
467 FUNC_mpfr_f_f ("log2", mpfr_log2, false),
468 FUNC_mpfr_f_f ("sin", mpfr_sin, false),
469 FUNC_mpfr_f_f ("sinh", mpfr_sinh, false),
470 FUNC_mpfr_f_f ("sqrt", mpfr_sqrt, true),
471 FUNC_mpfr_f_f ("tan", mpfr_tan, false),
472 FUNC_mpfr_f_f ("tanh", mpfr_tanh, false),
473 FUNC_mpfr_f_f ("tgamma", mpfr_gamma, false),
474 FUNC_mpfr_f_f ("y0", mpfr_y0, false),
475 FUNC_mpfr_f_f ("y1", mpfr_y1, false),
478 /* Allocate memory, with error checking. */
480 static void *
481 xmalloc (size_t n)
483 void *p = malloc (n);
484 if (p == NULL)
485 error (EXIT_FAILURE, errno, "xmalloc failed");
486 return p;
489 static void *
490 xrealloc (void *p, size_t n)
492 p = realloc (p, n);
493 if (p == NULL)
494 error (EXIT_FAILURE, errno, "xrealloc failed");
495 return p;
498 static char *
499 xstrdup (const char *s)
501 char *p = strdup (s);
502 if (p == NULL)
503 error (EXIT_FAILURE, errno, "xstrdup failed");
504 return p;
507 /* Assert that the result of an MPFR operation was exact; that is,
508 that the returned ternary value was 0. */
510 static void
511 assert_exact (int i)
513 assert (i == 0);
516 /* Return the generic type of an argument or return value type T. */
518 static generic_value_type
519 generic_arg_ret_type (arg_ret_type t)
521 switch (t)
523 case type_fp:
524 return gtype_fp;
526 case type_int:
527 case type_long:
528 case type_long_long:
529 return gtype_int;
531 default:
532 abort ();
536 /* Free a generic_value *V. */
538 static void
539 generic_value_free (generic_value *v)
541 switch (v->type)
543 case gtype_fp:
544 mpfr_clear (v->value.f);
545 break;
547 case gtype_int:
548 mpz_clear (v->value.i);
549 break;
551 default:
552 abort ();
556 /* Copy a generic_value *SRC to *DEST. */
558 static void
559 generic_value_copy (generic_value *dest, const generic_value *src)
561 dest->type = src->type;
562 switch (src->type)
564 case gtype_fp:
565 mpfr_init (dest->value.f);
566 assert_exact (mpfr_set (dest->value.f, src->value.f, MPFR_RNDN));
567 break;
569 case gtype_int:
570 mpz_init (dest->value.i);
571 mpz_set (dest->value.i, src->value.i);
572 break;
574 default:
575 abort ();
579 /* Initialize data for floating-point formats. */
581 static void
582 init_fp_formats ()
584 int global_max_exp = 0, global_min_subnorm_exp = 0;
585 for (fp_format f = fp_first_format; f < fp_num_formats; f++)
587 if (fp_formats[f].mant_dig + 2 > internal_precision)
588 internal_precision = fp_formats[f].mant_dig + 2;
589 if (fp_formats[f].max_exp > global_max_exp)
590 global_max_exp = fp_formats[f].max_exp;
591 int min_subnorm_exp = fp_formats[f].min_exp - fp_formats[f].mant_dig;
592 if (min_subnorm_exp < global_min_subnorm_exp)
593 global_min_subnorm_exp = min_subnorm_exp;
594 mpfr_init2 (fp_formats[f].max, fp_formats[f].mant_dig);
595 if (fp_formats[f].max_string != NULL)
597 char *ep = NULL;
598 assert_exact (mpfr_strtofr (fp_formats[f].max,
599 fp_formats[f].max_string,
600 &ep, 0, MPFR_RNDN));
601 assert (*ep == 0);
603 else
605 assert_exact (mpfr_set_ui_2exp (fp_formats[f].max, 1,
606 fp_formats[f].max_exp,
607 MPFR_RNDN));
608 mpfr_nextbelow (fp_formats[f].max);
610 mpfr_init2 (fp_formats[f].min, fp_formats[f].mant_dig);
611 assert_exact (mpfr_set_ui_2exp (fp_formats[f].min, 1,
612 fp_formats[f].min_exp - 1,
613 MPFR_RNDN));
614 mpfr_init2 (fp_formats[f].subnorm_max, fp_formats[f].mant_dig);
615 assert_exact (mpfr_set (fp_formats[f].subnorm_max, fp_formats[f].min,
616 MPFR_RNDN));
617 mpfr_nextbelow (fp_formats[f].subnorm_max);
618 mpfr_nextbelow (fp_formats[f].subnorm_max);
619 mpfr_init2 (fp_formats[f].subnorm_min, fp_formats[f].mant_dig);
620 assert_exact (mpfr_set_ui_2exp (fp_formats[f].subnorm_min, 1,
621 min_subnorm_exp, MPFR_RNDN));
623 mpfr_set_default_prec (internal_precision);
624 mpfr_init (global_max);
625 assert_exact (mpfr_set_ui_2exp (global_max, 1, global_max_exp, MPFR_RNDN));
626 mpfr_init (global_min);
627 assert_exact (mpfr_set_ui_2exp (global_min, 1, global_min_subnorm_exp - 1,
628 MPFR_RNDN));
631 /* Fill in mpfr_t values for special strings in input arguments. */
633 static size_t
634 special_fill_max (mpfr_t res0, mpfr_t res1 __attribute__ ((unused)),
635 fp_format format)
637 mpfr_init2 (res0, fp_formats[format].mant_dig);
638 assert_exact (mpfr_set (res0, fp_formats[format].max, MPFR_RNDN));
639 return 1;
642 static size_t
643 special_fill_minus_max (mpfr_t res0, mpfr_t res1 __attribute__ ((unused)),
644 fp_format format)
646 mpfr_init2 (res0, fp_formats[format].mant_dig);
647 assert_exact (mpfr_neg (res0, fp_formats[format].max, MPFR_RNDN));
648 return 1;
651 static size_t
652 special_fill_pi (mpfr_t res0, mpfr_t res1, fp_format format)
654 mpfr_init2 (res0, fp_formats[format].mant_dig);
655 mpfr_const_pi (res0, MPFR_RNDU);
656 mpfr_init2 (res1, fp_formats[format].mant_dig);
657 mpfr_const_pi (res1, MPFR_RNDD);
658 return 2;
661 static size_t
662 special_fill_minus_pi (mpfr_t res0, mpfr_t res1, fp_format format)
664 mpfr_init2 (res0, fp_formats[format].mant_dig);
665 mpfr_const_pi (res0, MPFR_RNDU);
666 assert_exact (mpfr_neg (res0, res0, MPFR_RNDN));
667 mpfr_init2 (res1, fp_formats[format].mant_dig);
668 mpfr_const_pi (res1, MPFR_RNDD);
669 assert_exact (mpfr_neg (res1, res1, MPFR_RNDN));
670 return 2;
673 static size_t
674 special_fill_pi_2 (mpfr_t res0, mpfr_t res1, fp_format format)
676 mpfr_init2 (res0, fp_formats[format].mant_dig);
677 mpfr_const_pi (res0, MPFR_RNDU);
678 assert_exact (mpfr_div_ui (res0, res0, 2, MPFR_RNDN));
679 mpfr_init2 (res1, fp_formats[format].mant_dig);
680 mpfr_const_pi (res1, MPFR_RNDD);
681 assert_exact (mpfr_div_ui (res1, res1, 2, MPFR_RNDN));
682 return 2;
685 static size_t
686 special_fill_minus_pi_2 (mpfr_t res0, mpfr_t res1, fp_format format)
688 mpfr_init2 (res0, fp_formats[format].mant_dig);
689 mpfr_const_pi (res0, MPFR_RNDU);
690 assert_exact (mpfr_div_ui (res0, res0, 2, MPFR_RNDN));
691 assert_exact (mpfr_neg (res0, res0, MPFR_RNDN));
692 mpfr_init2 (res1, fp_formats[format].mant_dig);
693 mpfr_const_pi (res1, MPFR_RNDD);
694 assert_exact (mpfr_div_ui (res1, res1, 2, MPFR_RNDN));
695 assert_exact (mpfr_neg (res1, res1, MPFR_RNDN));
696 return 2;
699 static size_t
700 special_fill_pi_6 (mpfr_t res0, mpfr_t res1, fp_format format)
702 mpfr_init2 (res0, fp_formats[format].mant_dig);
703 assert_exact (mpfr_set_si_2exp (res0, 1, -1, MPFR_RNDN));
704 mpfr_asin (res0, res0, MPFR_RNDU);
705 mpfr_init2 (res1, fp_formats[format].mant_dig);
706 assert_exact (mpfr_set_si_2exp (res1, 1, -1, MPFR_RNDN));
707 mpfr_asin (res1, res1, MPFR_RNDD);
708 return 2;
711 static size_t
712 special_fill_minus_pi_6 (mpfr_t res0, mpfr_t res1, fp_format format)
714 mpfr_init2 (res0, fp_formats[format].mant_dig);
715 assert_exact (mpfr_set_si_2exp (res0, -1, -1, MPFR_RNDN));
716 mpfr_asin (res0, res0, MPFR_RNDU);
717 mpfr_init2 (res1, fp_formats[format].mant_dig);
718 assert_exact (mpfr_set_si_2exp (res1, -1, -1, MPFR_RNDN));
719 mpfr_asin (res1, res1, MPFR_RNDD);
720 return 2;
723 static size_t
724 special_fill_pi_3 (mpfr_t res0, mpfr_t res1, fp_format format)
726 mpfr_init2 (res0, fp_formats[format].mant_dig);
727 assert_exact (mpfr_set_si_2exp (res0, 1, -1, MPFR_RNDN));
728 mpfr_acos (res0, res0, MPFR_RNDU);
729 mpfr_init2 (res1, fp_formats[format].mant_dig);
730 assert_exact (mpfr_set_si_2exp (res1, 1, -1, MPFR_RNDN));
731 mpfr_acos (res1, res1, MPFR_RNDD);
732 return 2;
735 static size_t
736 special_fill_2pi_3 (mpfr_t res0, mpfr_t res1, fp_format format)
738 mpfr_init2 (res0, fp_formats[format].mant_dig);
739 assert_exact (mpfr_set_si_2exp (res0, -1, -1, MPFR_RNDN));
740 mpfr_acos (res0, res0, MPFR_RNDU);
741 mpfr_init2 (res1, fp_formats[format].mant_dig);
742 assert_exact (mpfr_set_si_2exp (res1, -1, -1, MPFR_RNDN));
743 mpfr_acos (res1, res1, MPFR_RNDD);
744 return 2;
747 static size_t
748 special_fill_e (mpfr_t res0, mpfr_t res1, fp_format format)
750 mpfr_init2 (res0, fp_formats[format].mant_dig);
751 assert_exact (mpfr_set_si (res0, 1, MPFR_RNDN));
752 mpfr_exp (res0, res0, MPFR_RNDU);
753 mpfr_init2 (res1, fp_formats[format].mant_dig);
754 assert_exact (mpfr_set_si (res1, 1, MPFR_RNDN));
755 mpfr_exp (res1, res1, MPFR_RNDD);
756 return 2;
759 static size_t
760 special_fill_1_e (mpfr_t res0, mpfr_t res1, fp_format format)
762 mpfr_init2 (res0, fp_formats[format].mant_dig);
763 assert_exact (mpfr_set_si (res0, -1, MPFR_RNDN));
764 mpfr_exp (res0, res0, MPFR_RNDU);
765 mpfr_init2 (res1, fp_formats[format].mant_dig);
766 assert_exact (mpfr_set_si (res1, -1, MPFR_RNDN));
767 mpfr_exp (res1, res1, MPFR_RNDD);
768 return 2;
771 static size_t
772 special_fill_e_minus_1 (mpfr_t res0, mpfr_t res1, fp_format format)
774 mpfr_init2 (res0, fp_formats[format].mant_dig);
775 assert_exact (mpfr_set_si (res0, 1, MPFR_RNDN));
776 mpfr_expm1 (res0, res0, MPFR_RNDU);
777 mpfr_init2 (res1, fp_formats[format].mant_dig);
778 assert_exact (mpfr_set_si (res1, 1, MPFR_RNDN));
779 mpfr_expm1 (res1, res1, MPFR_RNDD);
780 return 2;
783 /* A special string accepted in input arguments. */
784 typedef struct
786 /* The string. */
787 const char *str;
788 /* The function that interprets it for a given floating-point
789 format, filling in up to two mpfr_t values and returning the
790 number of values filled. */
791 size_t (*func) (mpfr_t, mpfr_t, fp_format);
792 } special_real_input;
794 /* List of special strings accepted in input arguments. */
796 static const special_real_input special_real_inputs[] =
798 { "max", special_fill_max },
799 { "-max", special_fill_minus_max },
800 { "pi", special_fill_pi },
801 { "-pi", special_fill_minus_pi },
802 { "pi/2", special_fill_pi_2 },
803 { "-pi/2", special_fill_minus_pi_2 },
804 { "pi/6", special_fill_pi_6 },
805 { "-pi/6", special_fill_minus_pi_6 },
806 { "pi/3", special_fill_pi_3 },
807 { "2pi/3", special_fill_2pi_3 },
808 { "e", special_fill_e },
809 { "1/e", special_fill_1_e },
810 { "e-1", special_fill_e_minus_1 },
813 /* Given a real number R computed in round-to-zero mode, set the
814 lowest bit as a sticky bit if INEXACT, and saturate the exponent
815 range for very large or small values. */
817 static void
818 adjust_real (mpfr_t r, bool inexact)
820 if (!inexact)
821 return;
822 /* NaNs are exact, as are infinities in round-to-zero mode. */
823 assert (mpfr_number_p (r));
824 if (mpfr_cmpabs (r, global_min) < 0)
825 assert_exact (mpfr_copysign (r, global_min, r, MPFR_RNDN));
826 else if (mpfr_cmpabs (r, global_max) > 0)
827 assert_exact (mpfr_copysign (r, global_max, r, MPFR_RNDN));
828 else
830 mpz_t tmp;
831 mpz_init (tmp);
832 mpfr_exp_t e = mpfr_get_z_2exp (tmp, r);
833 mpz_setbit (tmp, 0);
834 assert_exact (mpfr_set_z_2exp (r, tmp, e, MPFR_RNDN));
835 mpz_clear (tmp);
839 /* Given a finite real number R with sticky bit, compute the roundings
840 to FORMAT in each rounding mode, storing the results in RES, the
841 before-rounding exceptions in EXC_BEFORE and the after-rounding
842 exceptions in EXC_AFTER. */
844 static void
845 round_real (mpfr_t res[rm_num_modes],
846 unsigned int exc_before[rm_num_modes],
847 unsigned int exc_after[rm_num_modes],
848 mpfr_t r, fp_format format)
850 assert (mpfr_number_p (r));
851 for (rounding_mode m = rm_first_mode; m < rm_num_modes; m++)
853 mpfr_init2 (res[m], fp_formats[format].mant_dig);
854 exc_before[m] = exc_after[m] = 0;
855 bool inexact = mpfr_set (res[m], r, rounding_modes[m].mpfr_mode);
856 if (mpfr_cmpabs (res[m], fp_formats[format].max) > 0)
858 inexact = true;
859 exc_before[m] |= 1U << exc_overflow;
860 exc_after[m] |= 1U << exc_overflow;
861 bool overflow_inf;
862 switch (m)
864 case rm_tonearest:
865 overflow_inf = true;
866 break;
867 case rm_towardzero:
868 overflow_inf = false;
869 break;
870 case rm_downward:
871 overflow_inf = mpfr_signbit (res[m]);
872 break;
873 case rm_upward:
874 overflow_inf = !mpfr_signbit (res[m]);
875 break;
876 default:
877 abort ();
879 if (overflow_inf)
880 mpfr_set_inf (res[m], mpfr_signbit (res[m]) ? -1 : 1);
881 else
882 assert_exact (mpfr_copysign (res[m], fp_formats[format].max,
883 res[m], MPFR_RNDN));
885 if (mpfr_cmpabs (r, fp_formats[format].min) < 0)
887 /* Tiny before rounding; may or may not be tiny after
888 rounding, and underflow applies only if also inexact
889 around rounding to a possibly subnormal value. */
890 bool tiny_after_rounding
891 = mpfr_cmpabs (res[m], fp_formats[format].min) < 0;
892 /* To round to a possibly subnormal value, and determine
893 inexactness as a subnormal in the process, scale up and
894 round to integer, then scale back down. */
895 mpfr_t tmp;
896 mpfr_init (tmp);
897 assert_exact (mpfr_mul_2si (tmp, r, (fp_formats[format].mant_dig
898 - fp_formats[format].min_exp),
899 MPFR_RNDN));
900 int rint_res = mpfr_rint (tmp, tmp, rounding_modes[m].mpfr_mode);
901 /* The integer must be representable. */
902 assert (rint_res == 0 || rint_res == 2 || rint_res == -2);
903 /* If rounding to full precision was inexact, so must
904 rounding to subnormal precision be inexact. */
905 if (inexact)
906 assert (rint_res != 0);
907 else
908 inexact = rint_res != 0;
909 assert_exact (mpfr_mul_2si (res[m], tmp,
910 (fp_formats[format].min_exp
911 - fp_formats[format].mant_dig),
912 MPFR_RNDN));
913 mpfr_clear (tmp);
914 if (inexact)
916 exc_before[m] |= 1U << exc_underflow;
917 if (tiny_after_rounding)
918 exc_after[m] |= 1U << exc_underflow;
921 if (inexact)
923 exc_before[m] |= 1U << exc_inexact;
924 exc_after[m] |= 1U << exc_inexact;
929 /* Handle the input argument at ARG (NUL-terminated), updating the
930 lists of test inputs in IT accordingly. NUM_PREV_ARGS arguments
931 are already in those lists. The argument, of type GTYPE, comes
932 from file FILENAME, line LINENO. */
934 static void
935 handle_input_arg (const char *arg, input_test *it, size_t num_prev_args,
936 generic_value_type gtype,
937 const char *filename, unsigned int lineno)
939 size_t num_values = 0;
940 generic_value values[2 * fp_num_formats];
941 switch (gtype)
943 case gtype_fp:
944 for (fp_format f = fp_first_format; f < fp_num_formats; f++)
946 mpfr_t extra_values[2];
947 size_t num_extra_values = 0;
948 for (size_t i = 0; i < ARRAY_SIZE (special_real_inputs); i++)
950 if (strcmp (arg, special_real_inputs[i].str) == 0)
952 num_extra_values
953 = special_real_inputs[i].func (extra_values[0],
954 extra_values[1], f);
955 assert (num_extra_values > 0
956 && num_extra_values <= ARRAY_SIZE (extra_values));
957 break;
960 if (num_extra_values == 0)
962 mpfr_t tmp;
963 char *ep;
964 mpfr_init (tmp);
965 bool inexact = mpfr_strtofr (tmp, arg, &ep, 0, MPFR_RNDZ);
966 if (*ep != 0 || !mpfr_number_p (tmp))
967 error_at_line (EXIT_FAILURE, 0, filename, lineno,
968 "bad floating-point argument: '%s'", arg);
969 adjust_real (tmp, inexact);
970 mpfr_t rounded[rm_num_modes];
971 unsigned int exc_before[rm_num_modes];
972 unsigned int exc_after[rm_num_modes];
973 round_real (rounded, exc_before, exc_after, tmp, f);
974 mpfr_clear (tmp);
975 if (mpfr_number_p (rounded[rm_upward]))
977 mpfr_init2 (extra_values[num_extra_values],
978 fp_formats[f].mant_dig);
979 assert_exact (mpfr_set (extra_values[num_extra_values],
980 rounded[rm_upward], MPFR_RNDN));
981 num_extra_values++;
983 if (mpfr_number_p (rounded[rm_downward]))
985 mpfr_init2 (extra_values[num_extra_values],
986 fp_formats[f].mant_dig);
987 assert_exact (mpfr_set (extra_values[num_extra_values],
988 rounded[rm_downward], MPFR_RNDN));
989 num_extra_values++;
991 for (rounding_mode m = rm_first_mode; m < rm_num_modes; m++)
992 mpfr_clear (rounded[m]);
994 for (size_t i = 0; i < num_extra_values; i++)
996 bool found = false;
997 for (size_t j = 0; j < num_values; j++)
999 if (mpfr_equal_p (values[j].value.f, extra_values[i])
1000 && ((mpfr_signbit (values[j].value.f) != 0)
1001 == (mpfr_signbit (extra_values[i]) != 0)))
1003 found = true;
1004 break;
1007 if (!found)
1009 assert (num_values < ARRAY_SIZE (values));
1010 values[num_values].type = gtype_fp;
1011 mpfr_init2 (values[num_values].value.f,
1012 fp_formats[f].mant_dig);
1013 assert_exact (mpfr_set (values[num_values].value.f,
1014 extra_values[i], MPFR_RNDN));
1015 num_values++;
1017 mpfr_clear (extra_values[i]);
1020 break;
1022 case gtype_int:
1023 num_values = 1;
1024 values[0].type = gtype_int;
1025 int ret = mpz_init_set_str (values[0].value.i, arg, 0);
1026 if (ret != 0)
1027 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1028 "bad integer argument: '%s'", arg);
1029 break;
1031 default:
1032 abort ();
1034 assert (num_values > 0 && num_values <= ARRAY_SIZE (values));
1035 if (it->num_input_cases >= SIZE_MAX / num_values)
1036 error_at_line (EXIT_FAILURE, 0, filename, lineno, "too many input cases");
1037 generic_value **old_inputs = it->inputs;
1038 size_t new_num_input_cases = it->num_input_cases * num_values;
1039 generic_value **new_inputs = xmalloc (new_num_input_cases
1040 * sizeof (new_inputs[0]));
1041 for (size_t i = 0; i < it->num_input_cases; i++)
1043 for (size_t j = 0; j < num_values; j++)
1045 size_t idx = i * num_values + j;
1046 new_inputs[idx] = xmalloc ((num_prev_args + 1)
1047 * sizeof (new_inputs[idx][0]));
1048 for (size_t k = 0; k < num_prev_args; k++)
1049 generic_value_copy (&new_inputs[idx][k], &old_inputs[i][k]);
1050 generic_value_copy (&new_inputs[idx][num_prev_args], &values[j]);
1052 for (size_t j = 0; j < num_prev_args; j++)
1053 generic_value_free (&old_inputs[i][j]);
1054 free (old_inputs[i]);
1056 free (old_inputs);
1057 for (size_t i = 0; i < num_values; i++)
1058 generic_value_free (&values[i]);
1059 it->inputs = new_inputs;
1060 it->num_input_cases = new_num_input_cases;
1063 /* Handle the input flag ARG (NUL-terminated), storing it in *FLAG.
1064 The flag comes from file FILENAME, line LINENO. */
1066 static void
1067 handle_input_flag (char *arg, input_flag *flag,
1068 const char *filename, unsigned int lineno)
1070 char *ep = strchr (arg, ':');
1071 if (ep == NULL)
1073 ep = strchr (arg, 0);
1074 assert (ep != NULL);
1076 char c = *ep;
1077 *ep = 0;
1078 bool found = false;
1079 for (input_flag_type i = flag_first_flag; i <= num_input_flag_types; i++)
1081 if (strcmp (arg, input_flags[i]) == 0)
1083 found = true;
1084 flag->type = i;
1085 break;
1088 if (!found)
1089 error_at_line (EXIT_FAILURE, 0, filename, lineno, "unknown flag: '%s'",
1090 arg);
1091 *ep = c;
1092 if (c == 0)
1093 flag->cond = NULL;
1094 else
1095 flag->cond = xstrdup (ep);
1098 /* Add the test LINE (file FILENAME, line LINENO) to the test
1099 data. */
1101 static void
1102 add_test (char *line, const char *filename, unsigned int lineno)
1104 size_t num_tokens = 1;
1105 char *p = line;
1106 while ((p = strchr (p, ' ')) != NULL)
1108 num_tokens++;
1109 p++;
1111 if (num_tokens < 2)
1112 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1113 "line too short: '%s'", line);
1114 p = strchr (line, ' ');
1115 size_t func_name_len = p - line;
1116 for (size_t i = 0; i < ARRAY_SIZE (test_functions); i++)
1118 if (func_name_len == strlen (test_functions[i].name)
1119 && strncmp (line, test_functions[i].name, func_name_len) == 0)
1121 test_function *tf = &test_functions[i];
1122 if (num_tokens < 1 + tf->num_args)
1123 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1124 "line too short: '%s'", line);
1125 if (tf->num_tests == tf->num_tests_alloc)
1127 tf->num_tests_alloc = 2 * tf->num_tests_alloc + 16;
1128 tf->tests
1129 = xrealloc (tf->tests,
1130 tf->num_tests_alloc * sizeof (tf->tests[0]));
1132 input_test *it = &tf->tests[tf->num_tests];
1133 it->line = line;
1134 it->num_input_cases = 1;
1135 it->inputs = xmalloc (sizeof (it->inputs[0]));
1136 it->inputs[0] = NULL;
1137 it->old_output = NULL;
1138 p++;
1139 for (size_t j = 0; j < tf->num_args; j++)
1141 char *ep = strchr (p, ' ');
1142 if (ep == NULL)
1144 ep = strchr (p, '\n');
1145 assert (ep != NULL);
1147 if (ep == p)
1148 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1149 "empty token in line: '%s'", line);
1150 for (char *t = p; t < ep; t++)
1151 if (isspace ((unsigned char) *t))
1152 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1153 "whitespace in token in line: '%s'", line);
1154 char c = *ep;
1155 *ep = 0;
1156 handle_input_arg (p, it, j,
1157 generic_arg_ret_type (tf->arg_types[j]),
1158 filename, lineno);
1159 *ep = c;
1160 p = ep + 1;
1162 it->num_flags = num_tokens - 1 - tf->num_args;
1163 it->flags = xmalloc (it->num_flags * sizeof (it->flags[0]));
1164 for (size_t j = 0; j < it->num_flags; j++)
1166 char *ep = strchr (p, ' ');
1167 if (ep == NULL)
1169 ep = strchr (p, '\n');
1170 assert (ep != NULL);
1172 if (ep == p)
1173 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1174 "empty token in line: '%s'", line);
1175 for (char *t = p; t < ep; t++)
1176 if (isspace ((unsigned char) *t))
1177 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1178 "whitespace in token in line: '%s'", line);
1179 char c = *ep;
1180 *ep = 0;
1181 handle_input_flag (p, &it->flags[j], filename, lineno);
1182 *ep = c;
1183 p = ep + 1;
1185 assert (*p == 0);
1186 tf->num_tests++;
1187 return;
1190 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1191 "unknown function in line: '%s'", line);
1194 /* Read in the test input data from FILENAME. */
1196 static void
1197 read_input (const char *filename)
1199 FILE *fp = fopen (filename, "r");
1200 if (fp == NULL)
1201 error (EXIT_FAILURE, errno, "open '%s'", filename);
1202 unsigned int lineno = 0;
1203 for (;;)
1205 size_t size = 0;
1206 char *line = NULL;
1207 ssize_t ret = getline (&line, &size, fp);
1208 if (ret == -1)
1209 break;
1210 lineno++;
1211 if (line[0] == '#' || line[0] == '\n')
1212 continue;
1213 add_test (line, filename, lineno);
1215 if (ferror (fp))
1216 error (EXIT_FAILURE, errno, "read from '%s'", filename);
1217 if (fclose (fp) != 0)
1218 error (EXIT_FAILURE, errno, "close '%s'", filename);
1221 /* Calculate the generic results (round-to-zero with sticky bit) for
1222 the function described by CALC, with inputs INPUTS. */
1224 static void
1225 calc_generic_results (generic_value *outputs, generic_value *inputs,
1226 const func_calc_desc *calc)
1228 bool inexact;
1229 switch (calc->method)
1231 case mpfr_f_f:
1232 assert (inputs[0].type == gtype_fp);
1233 outputs[0].type = gtype_fp;
1234 mpfr_init (outputs[0].value.f);
1235 inexact = calc->func.mpfr_f_f (outputs[0].value.f, inputs[0].value.f,
1236 MPFR_RNDZ);
1237 adjust_real (outputs[0].value.f, inexact);
1238 break;
1240 default:
1241 abort ();
1245 /* Return the number of bits for integer type TYPE, where "long" has
1246 LONG_BITS bits (32 or 64). */
1248 static int
1249 int_type_bits (arg_ret_type type, int long_bits)
1251 assert (long_bits == 32 || long_bits == 64);
1252 switch (type)
1254 case type_int:
1255 return 32;
1256 break;
1258 case type_long:
1259 return long_bits;
1260 break;
1262 case type_long_long:
1263 return 64;
1264 break;
1266 default:
1267 abort ();
1271 /* Check whether an integer Z fits a given type TYPE, where "long" has
1272 LONG_BITS bits (32 or 64). */
1274 static bool
1275 int_fits_type (mpz_t z, arg_ret_type type, int long_bits)
1277 int bits = int_type_bits (type, long_bits);
1278 bool ret = true;
1279 mpz_t t;
1280 mpz_init (t);
1281 mpz_ui_pow_ui (t, 2, bits - 1);
1282 if (mpz_cmp (z, t) >= 0)
1283 ret = false;
1284 mpz_neg (t, t);
1285 if (mpz_cmp (z, t) < 0)
1286 ret = false;
1287 mpz_clear (t);
1288 return ret;
1291 /* Print a generic value V to FP (name FILENAME), preceded by a space,
1292 for type TYPE, floating-point format FORMAT, LONG_BITS bits per
1293 long, printing " IGNORE" instead if IGNORE. */
1295 static void
1296 output_generic_value (FILE *fp, const char *filename, const generic_value *v,
1297 bool ignore, arg_ret_type type, fp_format format,
1298 int long_bits)
1300 if (ignore)
1302 if (fputs (" IGNORE", fp) < 0)
1303 error (EXIT_FAILURE, errno, "write to '%s'", filename);
1304 return;
1306 assert (v->type == generic_arg_ret_type (type));
1307 const char *suffix;
1308 switch (type)
1310 case type_fp:
1311 suffix = fp_formats[format].suffix;
1312 break;
1314 case type_int:
1315 suffix = "";
1316 break;
1318 case type_long:
1319 suffix = "L";
1320 break;
1322 case type_long_long:
1323 suffix = "LL";
1324 break;
1326 default:
1327 abort ();
1329 switch (v->type)
1331 case gtype_fp:
1332 if (mpfr_inf_p (v->value.f))
1334 if (fputs ((mpfr_signbit (v->value.f)
1335 ? " minus_infty" : " plus_infty"), fp) < 0)
1336 error (EXIT_FAILURE, errno, "write to '%s'", filename);
1338 else
1340 assert (mpfr_number_p (v->value.f));
1341 if (mpfr_fprintf (fp, " %Ra%s", v->value.f, suffix) < 0)
1342 error (EXIT_FAILURE, errno, "mpfr_fprintf to '%s'", filename);
1344 break;
1346 case gtype_int: ;
1347 int bits = int_type_bits (type, long_bits);
1348 mpz_t tmp;
1349 mpz_init (tmp);
1350 mpz_ui_pow_ui (tmp, 2, bits - 1);
1351 mpz_neg (tmp, tmp);
1352 if (mpz_cmp (v->value.i, tmp) == 0)
1354 mpz_add_ui (tmp, tmp, 1);
1355 if (mpfr_fprintf (fp, " (%Zd%s-1)", tmp, suffix) < 0)
1356 error (EXIT_FAILURE, errno, "mpfr_fprintf to '%s'", filename);
1358 else
1360 if (mpfr_fprintf (fp, " %Zd%s", v->value.i, suffix) < 0)
1361 error (EXIT_FAILURE, errno, "mpfr_fprintf to '%s'", filename);
1363 mpz_clear (tmp);
1364 break;
1366 default:
1367 abort ();
1371 /* Generate test output to FP (name FILENAME) for test function TF,
1372 input test IT, choice of input values INPUTS. */
1374 static void
1375 output_for_one_input_case (FILE *fp, const char *filename, test_function *tf,
1376 input_test *it, generic_value *inputs)
1378 bool long_bits_matters = false;
1379 bool fits_long32 = true;
1380 for (size_t i = 0; i < tf->num_args; i++)
1382 generic_value_type gtype = generic_arg_ret_type (tf->arg_types[i]);
1383 assert (inputs[i].type == gtype);
1384 if (gtype == gtype_int)
1386 bool fits_64 = int_fits_type (inputs[i].value.i, tf->arg_types[i],
1387 64);
1388 if (!fits_64)
1389 return;
1390 if (tf->arg_types[i] == type_long
1391 && !int_fits_type (inputs[i].value.i, tf->arg_types[i], 32))
1393 long_bits_matters = true;
1394 fits_long32 = false;
1398 generic_value generic_outputs[MAX_NRET];
1399 calc_generic_results (generic_outputs, inputs, &tf->calc);
1400 bool ignore_output_long32[MAX_NRET] = { false };
1401 bool ignore_output_long64[MAX_NRET] = { false };
1402 for (size_t i = 0; i < tf->num_ret; i++)
1404 assert (generic_outputs[i].type
1405 == generic_arg_ret_type (tf->ret_types[i]));
1406 switch (generic_outputs[i].type)
1408 case gtype_fp:
1409 if (!mpfr_number_p (generic_outputs[i].value.f))
1410 goto out; /* Result is NaN or exact infinity. */
1411 break;
1413 case gtype_int:
1414 ignore_output_long32[i] = !int_fits_type (generic_outputs[i].value.i,
1415 tf->ret_types[i], 32);
1416 ignore_output_long64[i] = !int_fits_type (generic_outputs[i].value.i,
1417 tf->ret_types[i], 64);
1418 if (ignore_output_long32[i] != ignore_output_long64[i])
1419 long_bits_matters = true;
1420 break;
1422 default:
1423 abort ();
1426 /* Iterate over relevant sizes of long and floating-point formats. */
1427 for (int long_bits = 32; long_bits <= 64; long_bits += 32)
1429 if (long_bits == 32 && !fits_long32)
1430 continue;
1431 if (long_bits == 64 && !long_bits_matters)
1432 continue;
1433 const char *long_cond;
1434 if (long_bits_matters)
1435 long_cond = (long_bits == 32 ? ":long32" : ":long64");
1436 else
1437 long_cond = "";
1438 bool *ignore_output = (long_bits == 32
1439 ? ignore_output_long32
1440 : ignore_output_long64);
1441 for (fp_format f = fp_first_format; f < fp_num_formats; f++)
1443 bool fits = true;
1444 mpfr_t res[rm_num_modes];
1445 unsigned int exc_before[rm_num_modes];
1446 unsigned int exc_after[rm_num_modes];
1447 for (size_t i = 0; i < tf->num_args; i++)
1449 if (inputs[i].type == gtype_fp)
1450 round_real (res, exc_before, exc_after, inputs[i].value.f, f);
1451 if (!mpfr_equal_p (res[rm_tonearest], inputs[i].value.f))
1452 fits = false;
1453 for (rounding_mode m = rm_first_mode; m < rm_num_modes; m++)
1454 mpfr_clear (res[m]);
1455 if (!fits)
1456 break;
1458 if (!fits)
1459 continue;
1460 /* The inputs fit this type, so compute the ideal outputs
1461 and exceptions. */
1462 mpfr_t all_res[MAX_NRET][rm_num_modes];
1463 unsigned int all_exc_before[MAX_NRET][rm_num_modes];
1464 unsigned int all_exc_after[MAX_NRET][rm_num_modes];
1465 unsigned int merged_exc_before[rm_num_modes] = { 0 };
1466 unsigned int merged_exc_after[rm_num_modes] = { 0 };
1467 /* For functions not exactly determined, track whether
1468 underflow is required (some result is inexact, and
1469 magnitude does not exceed the greatest magnitude
1470 subnormal), and permitted (not an exact zero, and
1471 magnitude does not exceed the least magnitude
1472 normal). */
1473 bool must_underflow = false;
1474 bool may_underflow = false;
1475 for (size_t i = 0; i < tf->num_ret; i++)
1477 switch (generic_outputs[i].type)
1479 case gtype_fp:
1480 round_real (all_res[i], all_exc_before[i], all_exc_after[i],
1481 generic_outputs[i].value.f, f);
1482 for (rounding_mode m = rm_first_mode; m < rm_num_modes; m++)
1484 merged_exc_before[m] |= all_exc_before[i][m];
1485 merged_exc_after[m] |= all_exc_after[i][m];
1486 if (!tf->exact)
1488 must_underflow
1489 |= ((all_exc_before[i][m]
1490 & (1U << exc_inexact)) != 0
1491 && (mpfr_cmpabs (generic_outputs[i].value.f,
1492 fp_formats[f].subnorm_max)
1493 <= 0));
1494 may_underflow
1495 |= (!mpfr_zero_p (generic_outputs[i].value.f)
1496 && mpfr_cmpabs (generic_outputs[i].value.f,
1497 fp_formats[f].min) <= 0);
1500 break;
1502 case gtype_int:
1503 if (ignore_output[i])
1504 for (rounding_mode m = rm_first_mode;
1505 m < rm_num_modes;
1506 m++)
1508 merged_exc_before[m] |= 1U << exc_invalid;
1509 merged_exc_after[m] |= 1U << exc_invalid;
1511 break;
1513 default:
1514 abort ();
1517 assert (may_underflow || !must_underflow);
1518 for (rounding_mode m = rm_first_mode; m < rm_num_modes; m++)
1520 bool before_after_matters
1521 = tf->exact && merged_exc_before[m] != merged_exc_after[m];
1522 for (int after = 0; after <= 1; after++)
1524 if (after == 1 && !before_after_matters)
1525 continue;
1526 const char *after_cond;
1527 if (before_after_matters)
1528 after_cond = (after
1529 ? ":after-rounding"
1530 : ":before-rounding");
1531 else
1532 after_cond = "";
1533 unsigned int merged_exc = (after
1534 ? merged_exc_after[m]
1535 : merged_exc_before[m]);
1536 if (fprintf (fp, "= %s %s %s%s%s", tf->name,
1537 rounding_modes[m].name, fp_formats[f].name,
1538 long_cond, after_cond) < 0)
1539 error (EXIT_FAILURE, errno, "write to '%s'", filename);
1540 /* Print inputs. */
1541 for (size_t i = 0; i < tf->num_args; i++)
1542 output_generic_value (fp, filename, &inputs[i], false,
1543 tf->arg_types[i], f, long_bits);
1544 if (fputs (" :", fp) < 0)
1545 error (EXIT_FAILURE, errno, "write to '%s'", filename);
1546 /* Print outputs. */
1547 bool must_erange = false;
1548 for (size_t i = 0; i < tf->num_ret; i++)
1550 generic_value g;
1551 g.type = generic_outputs[i].type;
1552 switch (g.type)
1554 case gtype_fp:
1555 if (mpfr_inf_p (all_res[i][m])
1556 && (all_exc_before[i][m]
1557 & (1U << exc_overflow)) != 0)
1558 must_erange = true;
1559 if (mpfr_zero_p (all_res[i][m])
1560 && (tf->exact
1561 || mpfr_zero_p (all_res[i][rm_tonearest]))
1562 && (all_exc_before[i][m]
1563 & (1U << exc_underflow)) != 0)
1564 must_erange = true;
1565 mpfr_init2 (g.value.f, fp_formats[f].mant_dig);
1566 assert_exact (mpfr_set (g.value.f, all_res[i][m],
1567 MPFR_RNDN));
1568 break;
1570 case gtype_int:
1571 mpz_init (g.value.i);
1572 mpz_set (g.value.i, generic_outputs[i].value.i);
1573 break;
1575 default:
1576 abort ();
1578 output_generic_value (fp, filename, &g, ignore_output[i],
1579 tf->ret_types[i], f, long_bits);
1580 generic_value_free (&g);
1582 if (fputs (" :", fp) < 0)
1583 error (EXIT_FAILURE, errno, "write to '%s'", filename);
1584 /* Print miscellaneous flags (passed through from
1585 input). */
1586 for (size_t i = 0; i < it->num_flags; i++)
1587 switch (it->flags[i].type)
1589 case flag_no_test_inline:
1590 case flag_xfail:
1591 if (fprintf (fp, " %s%s",
1592 input_flags[it->flags[i].type],
1593 (it->flags[i].cond
1594 ? it->flags[i].cond
1595 : "")) < 0)
1596 error (EXIT_FAILURE, errno, "write to '%s'",
1597 filename);
1598 break;
1599 case flag_xfail_rounding:
1600 if (m != rm_tonearest)
1601 if (fprintf (fp, " xfail%s",
1602 (it->flags[i].cond
1603 ? it->flags[i].cond
1604 : "")) < 0)
1605 error (EXIT_FAILURE, errno, "write to '%s'",
1606 filename);
1607 break;
1608 default:
1609 break;
1611 /* Print exception flags and compute errno
1612 expectations where not already computed. */
1613 bool may_edom = false;
1614 bool must_edom = false;
1615 bool may_erange = must_erange || may_underflow;
1616 for (fp_exception e = exc_first_exception;
1617 e < exc_num_exceptions;
1618 e++)
1620 bool expect_e = (merged_exc & (1U << e)) != 0;
1621 bool e_optional = false;
1622 switch (e)
1624 case exc_divbyzero:
1625 if (expect_e)
1626 may_erange = must_erange = true;
1627 break;
1629 case exc_inexact:
1630 if (!tf->exact)
1631 e_optional = true;
1632 break;
1634 case exc_invalid:
1635 if (expect_e)
1636 may_edom = must_edom = true;
1637 break;
1639 case exc_overflow:
1640 if (expect_e)
1641 may_erange = true;
1642 break;
1644 case exc_underflow:
1645 if (expect_e)
1646 may_erange = true;
1647 if (must_underflow)
1648 assert (expect_e);
1649 if (may_underflow && !must_underflow)
1650 e_optional = true;
1651 break;
1653 default:
1654 abort ();
1656 if (e_optional)
1658 if (fprintf (fp, " %s-ok", exceptions[e]) < 0)
1659 error (EXIT_FAILURE, errno, "write to '%s'",
1660 filename);
1662 else
1664 if (expect_e)
1665 if (fprintf (fp, " %s", exceptions[e]) < 0)
1666 error (EXIT_FAILURE, errno, "write to '%s'",
1667 filename);
1668 input_flag_type okflag;
1669 okflag = (expect_e
1670 ? flag_missing_first
1671 : flag_spurious_first) + e;
1672 for (size_t i = 0; i < it->num_flags; i++)
1673 if (it->flags[i].type == okflag)
1674 if (fprintf (fp, " %s-ok%s",
1675 exceptions[e],
1676 (it->flags[i].cond
1677 ? it->flags[i].cond
1678 : "")) < 0)
1679 error (EXIT_FAILURE, errno, "write to '%s'",
1680 filename);
1683 /* Print errno expectations. */
1684 if (tf->complex_fn)
1686 must_edom = false;
1687 must_erange = false;
1689 if (may_edom && !must_edom)
1691 if (fputs (" errno-edom-ok", fp) < 0)
1692 error (EXIT_FAILURE, errno, "write to '%s'",
1693 filename);
1695 else
1697 if (must_edom)
1698 if (fputs (" errno-edom", fp) < 0)
1699 error (EXIT_FAILURE, errno, "write to '%s'",
1700 filename);
1701 input_flag_type okflag = (must_edom
1702 ? flag_missing_errno
1703 : flag_spurious_errno);
1704 for (size_t i = 0; i < it->num_flags; i++)
1705 if (it->flags[i].type == okflag)
1706 if (fprintf (fp, " errno-edom-ok%s",
1707 (it->flags[i].cond
1708 ? it->flags[i].cond
1709 : "")) < 0)
1710 error (EXIT_FAILURE, errno, "write to '%s'",
1711 filename);
1713 if (may_erange && !must_erange)
1715 if (fputs (" errno-erange-ok", fp) < 0)
1716 error (EXIT_FAILURE, errno, "write to '%s'",
1717 filename);
1719 else
1721 if (must_erange)
1722 if (fputs (" errno-erange", fp) < 0)
1723 error (EXIT_FAILURE, errno, "write to '%s'",
1724 filename);
1725 input_flag_type okflag = (must_erange
1726 ? flag_missing_errno
1727 : flag_spurious_errno);
1728 for (size_t i = 0; i < it->num_flags; i++)
1729 if (it->flags[i].type == okflag)
1730 if (fprintf (fp, " errno-erange-ok%s",
1731 (it->flags[i].cond
1732 ? it->flags[i].cond
1733 : "")) < 0)
1734 error (EXIT_FAILURE, errno, "write to '%s'",
1735 filename);
1737 if (putc ('\n', fp) < 0)
1738 error (EXIT_FAILURE, errno, "write to '%s'", filename);
1741 for (size_t i = 0; i < tf->num_ret; i++)
1743 if (generic_outputs[i].type == gtype_fp)
1744 for (rounding_mode m = rm_first_mode; m < rm_num_modes; m++)
1745 mpfr_clear (all_res[i][m]);
1749 out:
1750 for (size_t i = 0; i < tf->num_ret; i++)
1751 generic_value_free (&generic_outputs[i]);
1754 /* Generate test output data to FILENAME. */
1756 static void
1757 generate_output (const char *filename)
1759 FILE *fp = fopen (filename, "w");
1760 if (fp == NULL)
1761 error (EXIT_FAILURE, errno, "open '%s'", filename);
1762 for (size_t i = 0; i < ARRAY_SIZE (test_functions); i++)
1764 test_function *tf = &test_functions[i];
1765 for (size_t j = 0; j < tf->num_tests; j++)
1767 input_test *it = &tf->tests[j];
1768 if (fputs (it->line, fp) < 0)
1769 error (EXIT_FAILURE, errno, "write to '%s'", filename);
1770 for (size_t k = 0; k < it->num_input_cases; k++)
1771 output_for_one_input_case (fp, filename, tf, it, it->inputs[k]);
1774 if (fclose (fp) != 0)
1775 error (EXIT_FAILURE, errno, "close '%s'", filename);
1779 main (int argc, char **argv)
1781 if (argc != 3)
1782 error (EXIT_FAILURE, 0, "usage: gen-auto-libm-tests <input> <output>");
1783 const char *input_filename = argv[1];
1784 const char *output_filename = argv[2];
1785 init_fp_formats ();
1786 read_input (input_filename);
1787 generate_output (output_filename);
1788 exit (EXIT_SUCCESS);