]> git.ipfire.org Git - thirdparty/glibc.git/blob - math/gen-auto-libm-tests.c
Move TEST_f_f tests for [a-c]* functions from libm-test.inc to auto-libm-test-in.
[thirdparty/glibc.git] / math / gen-auto-libm-tests.c
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.
4
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.
9
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.
14
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/>. */
18
19 /* Compile this program as:
20
21 gcc -std=gnu99 -O2 -Wall -Wextra gen-auto-libm-tests.c -lmpc -lmpfr -lgmp \
22 -o gen-auto-libm-tests
23
24 (use of current MPC and MPFR versions recommended) and run it as:
25
26 gen-auto-libm-tests auto-libm-test-in auto-libm-test-out
27
28 The input file auto-libm-test-in contains three kinds of lines:
29
30 Lines beginning with "#" are comments, and are ignored, as are
31 empty lines.
32
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.
40
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)).
51
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.
66
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.
85
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. Otherwise, test flags are
89 of the form "spurious-<exception>" and "missing-<exception>", for
90 any exception ("overflow", "underflow", "inexact", "invalid",
91 "divbyzero"), "spurious-errno" and "missing-errno", to indicate
92 when tests are expected to deviate from the exception and errno
93 settings corresponding to the mathematical results. "xfail",
94 "spurious-" and "missing-" flags should be accompanied by a comment
95 referring to an open bug in glibc Bugzilla.
96
97 The output file auto-libm-test-out contains the test lines from
98 auto-libm-test-in, and, after the line for a given test, some
99 number of output test lines. An output test line is of the form "=
100 function rounding-mode format input1 input2 ... : output1 output2
101 ... : flags". rounding-mode is "tonearest", "towardzero", "upward"
102 or "downward". format is a name from the floating_point_formats
103 array, possibly followed by a sequence of ":flag" for flags from
104 "long32", "long64", "before-rounding" and "after-rounding" (the
105 last two indicating tests where expectations for underflow
106 exceptions depend on how the architecture detects tininess).
107 Inputs and outputs are specified as hex floats with the required
108 suffix for the floating-point type, or plus_infty or minus_infty
109 for infinite expected results, or as integer constant expressions
110 (not necessarily with the right type) or IGNORE for integer inputs
111 and outputs. Flags are "no-test-inline", "xfail", "<exception>",
112 "<exception>-ok", "errno-<value>", "errno-<value>-ok", where
113 "<exception>" and "errno-<value>" are unconditional, indicating
114 that a correct result means the given exception should be raised or
115 errno should be set to the given value, and other settings may be
116 conditional or unconditional; "-ok" means not to test for the given
117 exception or errno value (whether because it was marked as possibly
118 missing or spurious, or because the calculation of correct results
119 indicated it was optional). */
120
121 #define _GNU_SOURCE
122
123 #include <assert.h>
124 #include <ctype.h>
125 #include <errno.h>
126 #include <error.h>
127 #include <stdbool.h>
128 #include <stdint.h>
129 #include <stdio.h>
130 #include <stdlib.h>
131 #include <string.h>
132
133 #include <gmp.h>
134 #include <mpfr.h>
135 #include <mpc.h>
136
137 #define ARRAY_SIZE(A) (sizeof (A) / sizeof ((A)[0]))
138
139 /* The supported floating-point formats. */
140 typedef enum
141 {
142 fp_flt_32,
143 fp_dbl_64,
144 fp_ldbl_96_intel,
145 fp_ldbl_96_m68k,
146 fp_ldbl_128,
147 fp_ldbl_128ibm,
148 fp_num_formats,
149 fp_first_format = 0
150 } fp_format;
151
152 /* Structure describing a single floating-point format. */
153 typedef struct
154 {
155 /* The name of the format. */
156 const char *name;
157 /* The suffix to use on floating-point constants with this
158 format. */
159 const char *suffix;
160 /* A string for the largest normal value, or NULL for IEEE formats
161 where this can be determined automatically. */
162 const char *max_string;
163 /* The number of mantissa bits. */
164 int mant_dig;
165 /* The least N such that 2^N overflows. */
166 int max_exp;
167 /* One more than the least N such that 2^N is normal. */
168 int min_exp;
169 /* The largest normal value. */
170 mpfr_t max;
171 /* The least positive normal value, 2^(MIN_EXP-1). */
172 mpfr_t min;
173 /* The greatest positive subnormal value. */
174 mpfr_t subnorm_max;
175 /* The least positive subnormal value, 2^(MIN_EXP-MANT_DIG). */
176 mpfr_t subnorm_min;
177 } fp_format_desc;
178
179 /* List of floating-point formats, in the same order as the fp_format
180 enumeration. */
181 static fp_format_desc fp_formats[fp_num_formats] =
182 {
183 { "flt-32", "f", NULL, 24, 128, -125, {}, {}, {}, {} },
184 { "dbl-64", "", NULL, 53, 1024, -1021, {}, {}, {}, {} },
185 { "ldbl-96-intel", "L", NULL, 64, 16384, -16381, {}, {}, {}, {} },
186 { "ldbl-96-m68k", "L", NULL, 64, 16384, -16382, {}, {}, {}, {} },
187 { "ldbl-128", "L", NULL, 113, 16384, -16381, {}, {}, {}, {} },
188 { "ldbl-128ibm", "L", "0x1.fffffffffffff7ffffffffffff8p+1023",
189 106, 1024, -968, {}, {}, {}, {} },
190 };
191
192 /* The supported rounding modes. */
193 typedef enum
194 {
195 rm_downward,
196 rm_tonearest,
197 rm_towardzero,
198 rm_upward,
199 rm_num_modes,
200 rm_first_mode = 0
201 } rounding_mode;
202
203 /* Structure describing a single rounding mode. */
204 typedef struct
205 {
206 /* The name of the rounding mode. */
207 const char *name;
208 /* The MPFR rounding mode. */
209 mpfr_rnd_t mpfr_mode;
210 } rounding_mode_desc;
211
212 /* List of rounding modes, in the same order as the rounding_mode
213 enumeration. */
214 static const rounding_mode_desc rounding_modes[rm_num_modes] =
215 {
216 { "downward", MPFR_RNDD },
217 { "tonearest", MPFR_RNDN },
218 { "towardzero", MPFR_RNDZ },
219 { "upward", MPFR_RNDU },
220 };
221
222 /* The supported exceptions. */
223 typedef enum
224 {
225 exc_divbyzero,
226 exc_inexact,
227 exc_invalid,
228 exc_overflow,
229 exc_underflow,
230 exc_num_exceptions,
231 exc_first_exception = 0
232 } fp_exception;
233
234 /* List of exceptions, in the same order as the fp_exception
235 enumeration. */
236 static const char *const exceptions[exc_num_exceptions] =
237 {
238 "divbyzero",
239 "inexact",
240 "invalid",
241 "overflow",
242 "underflow",
243 };
244
245 /* The internal precision to use for most MPFR calculations, which
246 must be at least 2 more than the greatest precision of any
247 supported floating-point format. */
248 static int internal_precision;
249
250 /* A value that overflows all supported floating-point formats. */
251 static mpfr_t global_max;
252
253 /* A value that is at most half the least subnormal in any
254 floating-point format and so is rounded the same way as all
255 sufficiently small positive values. */
256 static mpfr_t global_min;
257
258 /* The maximum number of (real or integer) arguments to a function
259 handled by this program (complex arguments count as two real
260 arguments). */
261 #define MAX_NARGS 4
262
263 /* The maximum number of (real or integer) return values from a
264 function handled by this program. */
265 #define MAX_NRET 2
266
267 /* A type of a function argument or return value. */
268 typedef enum
269 {
270 /* No type (not a valid argument or return value). */
271 type_none,
272 /* A floating-point value with the type corresponding to that of
273 the function. */
274 type_fp,
275 /* An integer value of type int. */
276 type_int,
277 /* An integer value of type long. */
278 type_long,
279 /* An integer value of type long long. */
280 type_long_long,
281 } arg_ret_type;
282
283 /* A type of a generic real or integer value. */
284 typedef enum
285 {
286 /* No type. */
287 gtype_none,
288 /* Floating-point (represented with MPFR). */
289 gtype_fp,
290 /* Integer (represented with GMP). */
291 gtype_int,
292 } generic_value_type;
293
294 /* A generic value (argument or result). */
295 typedef struct
296 {
297 /* The type of this value. */
298 generic_value_type type;
299 /* Its value. */
300 union
301 {
302 mpfr_t f;
303 mpz_t i;
304 } value;
305 } generic_value;
306
307 /* A type of input flag. */
308 typedef enum
309 {
310 flag_no_test_inline,
311 flag_xfail,
312 /* The "spurious" and "missing" flags must be in the same order as
313 the fp_exception enumeration. */
314 flag_spurious_divbyzero,
315 flag_spurious_inexact,
316 flag_spurious_invalid,
317 flag_spurious_overflow,
318 flag_spurious_underflow,
319 flag_spurious_errno,
320 flag_missing_divbyzero,
321 flag_missing_inexact,
322 flag_missing_invalid,
323 flag_missing_overflow,
324 flag_missing_underflow,
325 flag_missing_errno,
326 num_input_flag_types,
327 flag_first_flag = 0,
328 flag_spurious_first = flag_spurious_divbyzero,
329 flag_missing_first = flag_missing_divbyzero
330 } input_flag_type;
331
332 /* List of flags, in the same order as the input_flag_type
333 enumeration. */
334 static const char *const input_flags[num_input_flag_types] =
335 {
336 "no-test-inline",
337 "xfail",
338 "spurious-divbyzero",
339 "spurious-inexact",
340 "spurious-invalid",
341 "spurious-overflow",
342 "spurious-underflow",
343 "spurious-errno",
344 "missing-divbyzero",
345 "missing-inexact",
346 "missing-invalid",
347 "missing-overflow",
348 "missing-underflow",
349 "missing-errno",
350 };
351
352 /* An input flag, possibly conditional. */
353 typedef struct
354 {
355 /* The type of this flag. */
356 input_flag_type type;
357 /* The conditions on this flag, as a string ":cond1:cond2..." or
358 NULL. */
359 const char *cond;
360 } input_flag;
361
362 /* Structure describing a single test from the input file (which may
363 expand into many tests in the output). The choice of function,
364 which implies the numbers and types of arguments and results, is
365 implicit rather than stored in this structure (except as part of
366 the source line). */
367 typedef struct
368 {
369 /* The text of the input line describing the test, including the
370 trailing newline. */
371 const char *line;
372 /* The number of combinations of interpretations of input values for
373 different floating-point formats and rounding modes. */
374 size_t num_input_cases;
375 /* The corresponding lists of inputs. */
376 generic_value **inputs;
377 /* The number of flags for this test. */
378 size_t num_flags;
379 /* The corresponding list of flags. */
380 input_flag *flags;
381 /* The old output for this test. */
382 const char *old_output;
383 } input_test;
384
385 /* Ways to calculate a function. */
386 typedef enum
387 {
388 /* MPFR function with a single argument and result. */
389 mpfr_f_f,
390 } func_calc_method;
391
392 /* Description of how to calculate a function. */
393 typedef struct
394 {
395 /* Which method is used to calculate the function. */
396 func_calc_method method;
397 /* The specific function called. */
398 union
399 {
400 int (*mpfr_f_f) (mpfr_t, const mpfr_t, mpfr_rnd_t);
401 } func;
402 } func_calc_desc;
403
404 /* Structure describing a function handled by this program. */
405 typedef struct
406 {
407 /* The name of the function. */
408 const char *name;
409 /* The number of arguments. */
410 size_t num_args;
411 /* The types of the arguments. */
412 arg_ret_type arg_types[MAX_NARGS];
413 /* The number of return values. */
414 size_t num_ret;
415 /* The types of the return values. */
416 arg_ret_type ret_types[MAX_NRET];
417 /* Whether the function has exactly determined results and
418 exceptions. */
419 bool exact;
420 /* Whether the function is a complex function, so errno setting is
421 optional. */
422 bool complex_fn;
423 /* How to calculate this function. */
424 func_calc_desc calc;
425 /* The number of tests allocated for this function. */
426 size_t num_tests_alloc;
427 /* The number of tests for this function. */
428 size_t num_tests;
429 /* The tests themselves. */
430 input_test *tests;
431 } test_function;
432
433 #define FUNC_mpfr_f_f(NAME, MPFR_FUNC, EXACT) \
434 { \
435 NAME, 1, { type_fp }, 1, { type_fp }, EXACT, false, \
436 { mpfr_f_f, { .mpfr_f_f = MPFR_FUNC } }, 0, 0, NULL \
437 }
438
439 /* List of functions handled by this program. */
440 static test_function test_functions[] =
441 {
442 FUNC_mpfr_f_f ("acos", mpfr_acos, false),
443 FUNC_mpfr_f_f ("acosh", mpfr_acosh, false),
444 FUNC_mpfr_f_f ("asin", mpfr_asin, false),
445 FUNC_mpfr_f_f ("asinh", mpfr_asinh, false),
446 FUNC_mpfr_f_f ("atan", mpfr_atan, false),
447 FUNC_mpfr_f_f ("atanh", mpfr_atanh, false),
448 FUNC_mpfr_f_f ("cbrt", mpfr_cbrt, false),
449 FUNC_mpfr_f_f ("cos", mpfr_cos, false),
450 FUNC_mpfr_f_f ("cosh", mpfr_cosh, false),
451 FUNC_mpfr_f_f ("erf", mpfr_erf, false),
452 FUNC_mpfr_f_f ("erfc", mpfr_erfc, false),
453 FUNC_mpfr_f_f ("exp", mpfr_exp, false),
454 FUNC_mpfr_f_f ("exp10", mpfr_exp10, false),
455 FUNC_mpfr_f_f ("exp2", mpfr_exp2, false),
456 FUNC_mpfr_f_f ("expm1", mpfr_expm1, false),
457 FUNC_mpfr_f_f ("j0", mpfr_j0, false),
458 FUNC_mpfr_f_f ("j1", mpfr_j1, false),
459 FUNC_mpfr_f_f ("log", mpfr_log, false),
460 FUNC_mpfr_f_f ("log10", mpfr_log10, false),
461 FUNC_mpfr_f_f ("log1p", mpfr_log1p, false),
462 FUNC_mpfr_f_f ("log2", mpfr_log2, false),
463 FUNC_mpfr_f_f ("sin", mpfr_sin, false),
464 FUNC_mpfr_f_f ("sinh", mpfr_sinh, false),
465 FUNC_mpfr_f_f ("sqrt", mpfr_sqrt, true),
466 FUNC_mpfr_f_f ("tan", mpfr_tan, false),
467 FUNC_mpfr_f_f ("tanh", mpfr_tanh, false),
468 FUNC_mpfr_f_f ("tgamma", mpfr_gamma, false),
469 FUNC_mpfr_f_f ("y0", mpfr_y0, false),
470 FUNC_mpfr_f_f ("y1", mpfr_y1, false),
471 };
472
473 /* Allocate memory, with error checking. */
474
475 static void *
476 xmalloc (size_t n)
477 {
478 void *p = malloc (n);
479 if (p == NULL)
480 error (EXIT_FAILURE, errno, "xmalloc failed");
481 return p;
482 }
483
484 static void *
485 xrealloc (void *p, size_t n)
486 {
487 p = realloc (p, n);
488 if (p == NULL)
489 error (EXIT_FAILURE, errno, "xrealloc failed");
490 return p;
491 }
492
493 static char *
494 xstrdup (const char *s)
495 {
496 char *p = strdup (s);
497 if (p == NULL)
498 error (EXIT_FAILURE, errno, "xstrdup failed");
499 return p;
500 }
501
502 /* Assert that the result of an MPFR operation was exact; that is,
503 that the returned ternary value was 0. */
504
505 static void
506 assert_exact (int i)
507 {
508 assert (i == 0);
509 }
510
511 /* Return the generic type of an argument or return value type T. */
512
513 static generic_value_type
514 generic_arg_ret_type (arg_ret_type t)
515 {
516 switch (t)
517 {
518 case type_fp:
519 return gtype_fp;
520
521 case type_int:
522 case type_long:
523 case type_long_long:
524 return gtype_int;
525
526 default:
527 abort ();
528 }
529 }
530
531 /* Free a generic_value *V. */
532
533 static void
534 generic_value_free (generic_value *v)
535 {
536 switch (v->type)
537 {
538 case gtype_fp:
539 mpfr_clear (v->value.f);
540 break;
541
542 case gtype_int:
543 mpz_clear (v->value.i);
544 break;
545
546 default:
547 abort ();
548 }
549 }
550
551 /* Copy a generic_value *SRC to *DEST. */
552
553 static void
554 generic_value_copy (generic_value *dest, const generic_value *src)
555 {
556 dest->type = src->type;
557 switch (src->type)
558 {
559 case gtype_fp:
560 mpfr_init (dest->value.f);
561 assert_exact (mpfr_set (dest->value.f, src->value.f, MPFR_RNDN));
562 break;
563
564 case gtype_int:
565 mpz_init (dest->value.i);
566 mpz_set (dest->value.i, src->value.i);
567 break;
568
569 default:
570 abort ();
571 }
572 }
573
574 /* Initialize data for floating-point formats. */
575
576 static void
577 init_fp_formats ()
578 {
579 int global_max_exp = 0, global_min_subnorm_exp = 0;
580 for (fp_format f = fp_first_format; f < fp_num_formats; f++)
581 {
582 if (fp_formats[f].mant_dig + 2 > internal_precision)
583 internal_precision = fp_formats[f].mant_dig + 2;
584 if (fp_formats[f].max_exp > global_max_exp)
585 global_max_exp = fp_formats[f].max_exp;
586 int min_subnorm_exp = fp_formats[f].min_exp - fp_formats[f].mant_dig;
587 if (min_subnorm_exp < global_min_subnorm_exp)
588 global_min_subnorm_exp = min_subnorm_exp;
589 mpfr_init2 (fp_formats[f].max, fp_formats[f].mant_dig);
590 if (fp_formats[f].max_string != NULL)
591 {
592 char *ep = NULL;
593 assert_exact (mpfr_strtofr (fp_formats[f].max,
594 fp_formats[f].max_string,
595 &ep, 0, MPFR_RNDN));
596 assert (*ep == 0);
597 }
598 else
599 {
600 assert_exact (mpfr_set_ui_2exp (fp_formats[f].max, 1,
601 fp_formats[f].max_exp,
602 MPFR_RNDN));
603 mpfr_nextbelow (fp_formats[f].max);
604 }
605 mpfr_init2 (fp_formats[f].min, fp_formats[f].mant_dig);
606 assert_exact (mpfr_set_ui_2exp (fp_formats[f].min, 1,
607 fp_formats[f].min_exp - 1,
608 MPFR_RNDN));
609 mpfr_init2 (fp_formats[f].subnorm_max, fp_formats[f].mant_dig);
610 assert_exact (mpfr_set (fp_formats[f].subnorm_max, fp_formats[f].min,
611 MPFR_RNDN));
612 mpfr_nextbelow (fp_formats[f].subnorm_max);
613 mpfr_nextbelow (fp_formats[f].subnorm_max);
614 mpfr_init2 (fp_formats[f].subnorm_min, fp_formats[f].mant_dig);
615 assert_exact (mpfr_set_ui_2exp (fp_formats[f].subnorm_min, 1,
616 min_subnorm_exp, MPFR_RNDN));
617 }
618 mpfr_set_default_prec (internal_precision);
619 mpfr_init (global_max);
620 assert_exact (mpfr_set_ui_2exp (global_max, 1, global_max_exp, MPFR_RNDN));
621 mpfr_init (global_min);
622 assert_exact (mpfr_set_ui_2exp (global_min, 1, global_min_subnorm_exp - 1,
623 MPFR_RNDN));
624 }
625
626 /* Fill in mpfr_t values for special strings in input arguments. */
627
628 static size_t
629 special_fill_max (mpfr_t res0, mpfr_t res1 __attribute__ ((unused)),
630 fp_format format)
631 {
632 mpfr_init2 (res0, fp_formats[format].mant_dig);
633 assert_exact (mpfr_set (res0, fp_formats[format].max, MPFR_RNDN));
634 return 1;
635 }
636
637 static size_t
638 special_fill_minus_max (mpfr_t res0, mpfr_t res1 __attribute__ ((unused)),
639 fp_format format)
640 {
641 mpfr_init2 (res0, fp_formats[format].mant_dig);
642 assert_exact (mpfr_neg (res0, fp_formats[format].max, MPFR_RNDN));
643 return 1;
644 }
645
646 static size_t
647 special_fill_pi (mpfr_t res0, mpfr_t res1, fp_format format)
648 {
649 mpfr_init2 (res0, fp_formats[format].mant_dig);
650 mpfr_const_pi (res0, MPFR_RNDU);
651 mpfr_init2 (res1, fp_formats[format].mant_dig);
652 mpfr_const_pi (res1, MPFR_RNDD);
653 return 2;
654 }
655
656 static size_t
657 special_fill_minus_pi (mpfr_t res0, mpfr_t res1, fp_format format)
658 {
659 mpfr_init2 (res0, fp_formats[format].mant_dig);
660 mpfr_const_pi (res0, MPFR_RNDU);
661 assert_exact (mpfr_neg (res0, res0, MPFR_RNDN));
662 mpfr_init2 (res1, fp_formats[format].mant_dig);
663 mpfr_const_pi (res1, MPFR_RNDD);
664 assert_exact (mpfr_neg (res1, res1, MPFR_RNDN));
665 return 2;
666 }
667
668 static size_t
669 special_fill_pi_2 (mpfr_t res0, mpfr_t res1, fp_format format)
670 {
671 mpfr_init2 (res0, fp_formats[format].mant_dig);
672 mpfr_const_pi (res0, MPFR_RNDU);
673 assert_exact (mpfr_div_ui (res0, res0, 2, MPFR_RNDN));
674 mpfr_init2 (res1, fp_formats[format].mant_dig);
675 mpfr_const_pi (res1, MPFR_RNDD);
676 assert_exact (mpfr_div_ui (res1, res1, 2, MPFR_RNDN));
677 return 2;
678 }
679
680 static size_t
681 special_fill_minus_pi_2 (mpfr_t res0, mpfr_t res1, fp_format format)
682 {
683 mpfr_init2 (res0, fp_formats[format].mant_dig);
684 mpfr_const_pi (res0, MPFR_RNDU);
685 assert_exact (mpfr_div_ui (res0, res0, 2, MPFR_RNDN));
686 assert_exact (mpfr_neg (res0, res0, MPFR_RNDN));
687 mpfr_init2 (res1, fp_formats[format].mant_dig);
688 mpfr_const_pi (res1, MPFR_RNDD);
689 assert_exact (mpfr_div_ui (res1, res1, 2, MPFR_RNDN));
690 assert_exact (mpfr_neg (res1, res1, MPFR_RNDN));
691 return 2;
692 }
693
694 static size_t
695 special_fill_pi_6 (mpfr_t res0, mpfr_t res1, fp_format format)
696 {
697 mpfr_init2 (res0, fp_formats[format].mant_dig);
698 assert_exact (mpfr_set_si_2exp (res0, 1, -1, MPFR_RNDN));
699 mpfr_asin (res0, res0, MPFR_RNDU);
700 mpfr_init2 (res1, fp_formats[format].mant_dig);
701 assert_exact (mpfr_set_si_2exp (res1, 1, -1, MPFR_RNDN));
702 mpfr_asin (res1, res1, MPFR_RNDD);
703 return 2;
704 }
705
706 static size_t
707 special_fill_minus_pi_6 (mpfr_t res0, mpfr_t res1, fp_format format)
708 {
709 mpfr_init2 (res0, fp_formats[format].mant_dig);
710 assert_exact (mpfr_set_si_2exp (res0, -1, -1, MPFR_RNDN));
711 mpfr_asin (res0, res0, MPFR_RNDU);
712 mpfr_init2 (res1, fp_formats[format].mant_dig);
713 assert_exact (mpfr_set_si_2exp (res1, -1, -1, MPFR_RNDN));
714 mpfr_asin (res1, res1, MPFR_RNDD);
715 return 2;
716 }
717
718 static size_t
719 special_fill_pi_3 (mpfr_t res0, mpfr_t res1, fp_format format)
720 {
721 mpfr_init2 (res0, fp_formats[format].mant_dig);
722 assert_exact (mpfr_set_si_2exp (res0, 1, -1, MPFR_RNDN));
723 mpfr_acos (res0, res0, MPFR_RNDU);
724 mpfr_init2 (res1, fp_formats[format].mant_dig);
725 assert_exact (mpfr_set_si_2exp (res1, 1, -1, MPFR_RNDN));
726 mpfr_acos (res1, res1, MPFR_RNDD);
727 return 2;
728 }
729
730 static size_t
731 special_fill_2pi_3 (mpfr_t res0, mpfr_t res1, fp_format format)
732 {
733 mpfr_init2 (res0, fp_formats[format].mant_dig);
734 assert_exact (mpfr_set_si_2exp (res0, -1, -1, MPFR_RNDN));
735 mpfr_acos (res0, res0, MPFR_RNDU);
736 mpfr_init2 (res1, fp_formats[format].mant_dig);
737 assert_exact (mpfr_set_si_2exp (res1, -1, -1, MPFR_RNDN));
738 mpfr_acos (res1, res1, MPFR_RNDD);
739 return 2;
740 }
741
742 static size_t
743 special_fill_e (mpfr_t res0, mpfr_t res1, fp_format format)
744 {
745 mpfr_init2 (res0, fp_formats[format].mant_dig);
746 assert_exact (mpfr_set_si (res0, 1, MPFR_RNDN));
747 mpfr_exp (res0, res0, MPFR_RNDU);
748 mpfr_init2 (res1, fp_formats[format].mant_dig);
749 assert_exact (mpfr_set_si (res1, 1, MPFR_RNDN));
750 mpfr_exp (res1, res1, MPFR_RNDD);
751 return 2;
752 }
753
754 static size_t
755 special_fill_1_e (mpfr_t res0, mpfr_t res1, fp_format format)
756 {
757 mpfr_init2 (res0, fp_formats[format].mant_dig);
758 assert_exact (mpfr_set_si (res0, -1, MPFR_RNDN));
759 mpfr_exp (res0, res0, MPFR_RNDU);
760 mpfr_init2 (res1, fp_formats[format].mant_dig);
761 assert_exact (mpfr_set_si (res1, -1, MPFR_RNDN));
762 mpfr_exp (res1, res1, MPFR_RNDD);
763 return 2;
764 }
765
766 static size_t
767 special_fill_e_minus_1 (mpfr_t res0, mpfr_t res1, fp_format format)
768 {
769 mpfr_init2 (res0, fp_formats[format].mant_dig);
770 assert_exact (mpfr_set_si (res0, 1, MPFR_RNDN));
771 mpfr_expm1 (res0, res0, MPFR_RNDU);
772 mpfr_init2 (res1, fp_formats[format].mant_dig);
773 assert_exact (mpfr_set_si (res1, 1, MPFR_RNDN));
774 mpfr_expm1 (res1, res1, MPFR_RNDD);
775 return 2;
776 }
777
778 /* A special string accepted in input arguments. */
779 typedef struct
780 {
781 /* The string. */
782 const char *str;
783 /* The function that interprets it for a given floating-point
784 format, filling in up to two mpfr_t values and returning the
785 number of values filled. */
786 size_t (*func) (mpfr_t, mpfr_t, fp_format);
787 } special_real_input;
788
789 /* List of special strings accepted in input arguments. */
790
791 static const special_real_input special_real_inputs[] =
792 {
793 { "max", special_fill_max },
794 { "-max", special_fill_minus_max },
795 { "pi", special_fill_pi },
796 { "-pi", special_fill_minus_pi },
797 { "pi/2", special_fill_pi_2 },
798 { "-pi/2", special_fill_minus_pi_2 },
799 { "pi/6", special_fill_pi_6 },
800 { "-pi/6", special_fill_minus_pi_6 },
801 { "pi/3", special_fill_pi_3 },
802 { "2pi/3", special_fill_2pi_3 },
803 { "e", special_fill_e },
804 { "1/e", special_fill_1_e },
805 { "e-1", special_fill_e_minus_1 },
806 };
807
808 /* Given a real number R computed in round-to-zero mode, set the
809 lowest bit as a sticky bit if INEXACT, and saturate the exponent
810 range for very large or small values. */
811
812 static void
813 adjust_real (mpfr_t r, bool inexact)
814 {
815 if (!inexact)
816 return;
817 /* NaNs are exact, as are infinities in round-to-zero mode. */
818 assert (mpfr_regular_p (r));
819 if (mpfr_cmpabs (r, global_min) < 0)
820 assert_exact (mpfr_copysign (r, global_min, r, MPFR_RNDN));
821 else if (mpfr_cmpabs (r, global_max) > 0)
822 assert_exact (mpfr_copysign (r, global_max, r, MPFR_RNDN));
823 else
824 {
825 mpz_t tmp;
826 mpz_init (tmp);
827 mpfr_exp_t e = mpfr_get_z_2exp (tmp, r);
828 mpz_setbit (tmp, 0);
829 assert_exact (mpfr_set_z_2exp (r, tmp, e, MPFR_RNDN));
830 mpz_clear (tmp);
831 }
832 }
833
834 /* Given a finite real number R with sticky bit, compute the roundings
835 to FORMAT in each rounding mode, storing the results in RES, the
836 before-rounding exceptions in EXC_BEFORE and the after-rounding
837 exceptions in EXC_AFTER. */
838
839 static void
840 round_real (mpfr_t res[rm_num_modes],
841 unsigned int exc_before[rm_num_modes],
842 unsigned int exc_after[rm_num_modes],
843 mpfr_t r, fp_format format)
844 {
845 assert (mpfr_number_p (r));
846 for (rounding_mode m = rm_first_mode; m < rm_num_modes; m++)
847 {
848 mpfr_init2 (res[m], fp_formats[format].mant_dig);
849 exc_before[m] = exc_after[m] = 0;
850 bool inexact = mpfr_set (res[m], r, rounding_modes[m].mpfr_mode);
851 if (mpfr_cmpabs (res[m], fp_formats[format].max) > 0)
852 {
853 inexact = true;
854 exc_before[m] |= 1U << exc_overflow;
855 exc_after[m] |= 1U << exc_overflow;
856 bool overflow_inf;
857 switch (m)
858 {
859 case rm_tonearest:
860 overflow_inf = true;
861 break;
862 case rm_towardzero:
863 overflow_inf = false;
864 break;
865 case rm_downward:
866 overflow_inf = mpfr_signbit (res[m]);
867 break;
868 case rm_upward:
869 overflow_inf = !mpfr_signbit (res[m]);
870 break;
871 default:
872 abort ();
873 }
874 if (overflow_inf)
875 mpfr_set_inf (res[m], mpfr_signbit (res[m]) ? -1 : 1);
876 else
877 assert_exact (mpfr_copysign (res[m], fp_formats[format].max,
878 res[m], MPFR_RNDN));
879 }
880 if (mpfr_cmpabs (r, fp_formats[format].min) < 0)
881 {
882 /* Tiny before rounding; may or may not be tiny after
883 rounding, and underflow applies only if also inexact
884 around rounding to a possibly subnormal value. */
885 bool tiny_after_rounding
886 = mpfr_cmpabs (res[m], fp_formats[format].min) < 0;
887 /* To round to a possibly subnormal value, and determine
888 inexactness as a subnormal in the process, scale up and
889 round to integer, then scale back down. */
890 mpfr_t tmp;
891 mpfr_init (tmp);
892 assert_exact (mpfr_mul_2si (tmp, r, (fp_formats[format].mant_dig
893 - fp_formats[format].min_exp),
894 MPFR_RNDN));
895 int rint_res = mpfr_rint (tmp, tmp, rounding_modes[m].mpfr_mode);
896 /* The integer must be representable. */
897 assert (rint_res == 0 || rint_res == 2 || rint_res == -2);
898 /* If rounding to full precision was inexact, so must
899 rounding to subnormal precision be inexact. */
900 if (inexact)
901 assert (rint_res != 0);
902 else
903 inexact = rint_res != 0;
904 assert_exact (mpfr_mul_2si (res[m], tmp,
905 (fp_formats[format].min_exp
906 - fp_formats[format].mant_dig),
907 MPFR_RNDN));
908 mpfr_clear (tmp);
909 if (inexact)
910 {
911 exc_before[m] |= 1U << exc_underflow;
912 if (tiny_after_rounding)
913 exc_after[m] |= 1U << exc_underflow;
914 }
915 }
916 if (inexact)
917 {
918 exc_before[m] |= 1U << exc_inexact;
919 exc_after[m] |= 1U << exc_inexact;
920 }
921 }
922 }
923
924 /* Handle the input argument at ARG (NUL-terminated), updating the
925 lists of test inputs in IT accordingly. NUM_PREV_ARGS arguments
926 are already in those lists. The argument, of type GTYPE, comes
927 from file FILENAME, line LINENO. */
928
929 static void
930 handle_input_arg (const char *arg, input_test *it, size_t num_prev_args,
931 generic_value_type gtype,
932 const char *filename, unsigned int lineno)
933 {
934 size_t num_values = 0;
935 generic_value values[2 * fp_num_formats];
936 switch (gtype)
937 {
938 case gtype_fp:
939 for (fp_format f = fp_first_format; f < fp_num_formats; f++)
940 {
941 mpfr_t extra_values[2];
942 size_t num_extra_values = 0;
943 for (size_t i = 0; i < ARRAY_SIZE (special_real_inputs); i++)
944 {
945 if (strcmp (arg, special_real_inputs[i].str) == 0)
946 {
947 num_extra_values
948 = special_real_inputs[i].func (extra_values[0],
949 extra_values[1], f);
950 assert (num_extra_values > 0
951 && num_extra_values <= ARRAY_SIZE (extra_values));
952 break;
953 }
954 }
955 if (num_extra_values == 0)
956 {
957 mpfr_t tmp;
958 char *ep;
959 mpfr_init (tmp);
960 bool inexact = mpfr_strtofr (tmp, arg, &ep, 0, MPFR_RNDZ);
961 if (*ep != 0 || !mpfr_number_p (tmp))
962 error_at_line (EXIT_FAILURE, 0, filename, lineno,
963 "bad floating-point argument: '%s'", arg);
964 adjust_real (tmp, inexact);
965 mpfr_t rounded[rm_num_modes];
966 unsigned int exc_before[rm_num_modes];
967 unsigned int exc_after[rm_num_modes];
968 round_real (rounded, exc_before, exc_after, tmp, f);
969 mpfr_clear (tmp);
970 if (mpfr_number_p (rounded[rm_upward]))
971 {
972 mpfr_init2 (extra_values[num_extra_values],
973 fp_formats[f].mant_dig);
974 assert_exact (mpfr_set (extra_values[num_extra_values],
975 rounded[rm_upward], MPFR_RNDN));
976 num_extra_values++;
977 }
978 if (mpfr_number_p (rounded[rm_downward]))
979 {
980 mpfr_init2 (extra_values[num_extra_values],
981 fp_formats[f].mant_dig);
982 assert_exact (mpfr_set (extra_values[num_extra_values],
983 rounded[rm_downward], MPFR_RNDN));
984 num_extra_values++;
985 }
986 for (rounding_mode m = rm_first_mode; m < rm_num_modes; m++)
987 mpfr_clear (rounded[m]);
988 }
989 for (size_t i = 0; i < num_extra_values; i++)
990 {
991 bool found = false;
992 for (size_t j = 0; j < num_values; j++)
993 {
994 if (mpfr_equal_p (values[j].value.f, extra_values[i])
995 && ((mpfr_signbit (values[j].value.f) != 0)
996 == (mpfr_signbit (extra_values[i]) != 0)))
997 {
998 found = true;
999 break;
1000 }
1001 }
1002 if (!found)
1003 {
1004 assert (num_values < ARRAY_SIZE (values));
1005 values[num_values].type = gtype_fp;
1006 mpfr_init2 (values[num_values].value.f,
1007 fp_formats[f].mant_dig);
1008 assert_exact (mpfr_set (values[num_values].value.f,
1009 extra_values[i], MPFR_RNDN));
1010 num_values++;
1011 }
1012 mpfr_clear (extra_values[i]);
1013 }
1014 }
1015 break;
1016
1017 case gtype_int:
1018 num_values = 1;
1019 values[0].type = gtype_int;
1020 int ret = mpz_init_set_str (values[0].value.i, arg, 0);
1021 if (ret != 0)
1022 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1023 "bad integer argument: '%s'", arg);
1024 break;
1025
1026 default:
1027 abort ();
1028 }
1029 assert (num_values > 0 && num_values <= ARRAY_SIZE (values));
1030 if (it->num_input_cases >= SIZE_MAX / num_values)
1031 error_at_line (EXIT_FAILURE, 0, filename, lineno, "too many input cases");
1032 generic_value **old_inputs = it->inputs;
1033 size_t new_num_input_cases = it->num_input_cases * num_values;
1034 generic_value **new_inputs = xmalloc (new_num_input_cases
1035 * sizeof (new_inputs[0]));
1036 for (size_t i = 0; i < it->num_input_cases; i++)
1037 {
1038 for (size_t j = 0; j < num_values; j++)
1039 {
1040 size_t idx = i * num_values + j;
1041 new_inputs[idx] = xmalloc ((num_prev_args + 1)
1042 * sizeof (new_inputs[idx][0]));
1043 for (size_t k = 0; k < num_prev_args; k++)
1044 generic_value_copy (&new_inputs[idx][k], &old_inputs[i][k]);
1045 generic_value_copy (&new_inputs[idx][num_prev_args], &values[j]);
1046 }
1047 for (size_t j = 0; j < num_prev_args; j++)
1048 generic_value_free (&old_inputs[i][j]);
1049 free (old_inputs[i]);
1050 }
1051 free (old_inputs);
1052 for (size_t i = 0; i < num_values; i++)
1053 generic_value_free (&values[i]);
1054 it->inputs = new_inputs;
1055 it->num_input_cases = new_num_input_cases;
1056 }
1057
1058 /* Handle the input flag ARG (NUL-terminated), storing it in *FLAG.
1059 The flag comes from file FILENAME, line LINENO. */
1060
1061 static void
1062 handle_input_flag (char *arg, input_flag *flag,
1063 const char *filename, unsigned int lineno)
1064 {
1065 char *ep = strchr (arg, ':');
1066 if (ep == NULL)
1067 {
1068 ep = strchr (arg, 0);
1069 assert (ep != NULL);
1070 }
1071 char c = *ep;
1072 *ep = 0;
1073 bool found = false;
1074 for (input_flag_type i = flag_first_flag; i <= num_input_flag_types; i++)
1075 {
1076 if (strcmp (arg, input_flags[i]) == 0)
1077 {
1078 found = true;
1079 flag->type = i;
1080 break;
1081 }
1082 }
1083 if (!found)
1084 error_at_line (EXIT_FAILURE, 0, filename, lineno, "unknown flag: '%s'",
1085 arg);
1086 *ep = c;
1087 if (c == 0)
1088 flag->cond = NULL;
1089 else
1090 flag->cond = xstrdup (ep);
1091 }
1092
1093 /* Add the test LINE (file FILENAME, line LINENO) to the test
1094 data. */
1095
1096 static void
1097 add_test (char *line, const char *filename, unsigned int lineno)
1098 {
1099 size_t num_tokens = 1;
1100 char *p = line;
1101 while ((p = strchr (p, ' ')) != NULL)
1102 {
1103 num_tokens++;
1104 p++;
1105 }
1106 if (num_tokens < 2)
1107 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1108 "line too short: '%s'", line);
1109 p = strchr (line, ' ');
1110 size_t func_name_len = p - line;
1111 for (size_t i = 0; i < ARRAY_SIZE (test_functions); i++)
1112 {
1113 if (func_name_len == strlen (test_functions[i].name)
1114 && strncmp (line, test_functions[i].name, func_name_len) == 0)
1115 {
1116 test_function *tf = &test_functions[i];
1117 if (num_tokens < 1 + tf->num_args)
1118 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1119 "line too short: '%s'", line);
1120 if (tf->num_tests == tf->num_tests_alloc)
1121 {
1122 tf->num_tests_alloc = 2 * tf->num_tests_alloc + 16;
1123 tf->tests
1124 = xrealloc (tf->tests,
1125 tf->num_tests_alloc * sizeof (tf->tests[0]));
1126 }
1127 input_test *it = &tf->tests[tf->num_tests];
1128 it->line = line;
1129 it->num_input_cases = 1;
1130 it->inputs = xmalloc (sizeof (it->inputs[0]));
1131 it->inputs[0] = NULL;
1132 it->old_output = NULL;
1133 p++;
1134 for (size_t j = 0; j < tf->num_args; j++)
1135 {
1136 char *ep = strchr (p, ' ');
1137 if (ep == NULL)
1138 {
1139 ep = strchr (p, '\n');
1140 assert (ep != NULL);
1141 }
1142 if (ep == p)
1143 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1144 "empty token in line: '%s'", line);
1145 for (char *t = p; t < ep; t++)
1146 if (isspace ((unsigned char) *t))
1147 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1148 "whitespace in token in line: '%s'", line);
1149 char c = *ep;
1150 *ep = 0;
1151 handle_input_arg (p, it, j,
1152 generic_arg_ret_type (tf->arg_types[j]),
1153 filename, lineno);
1154 *ep = c;
1155 p = ep + 1;
1156 }
1157 it->num_flags = num_tokens - 1 - tf->num_args;
1158 it->flags = xmalloc (it->num_flags * sizeof (it->flags[0]));
1159 for (size_t j = 0; j < it->num_flags; j++)
1160 {
1161 char *ep = strchr (p, ' ');
1162 if (ep == NULL)
1163 {
1164 ep = strchr (p, '\n');
1165 assert (ep != NULL);
1166 }
1167 if (ep == p)
1168 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1169 "empty token in line: '%s'", line);
1170 for (char *t = p; t < ep; t++)
1171 if (isspace ((unsigned char) *t))
1172 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1173 "whitespace in token in line: '%s'", line);
1174 char c = *ep;
1175 *ep = 0;
1176 handle_input_flag (p, &it->flags[j], filename, lineno);
1177 *ep = c;
1178 p = ep + 1;
1179 }
1180 assert (*p == 0);
1181 tf->num_tests++;
1182 return;
1183 }
1184 }
1185 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1186 "unknown function in line: '%s'", line);
1187 }
1188
1189 /* Read in the test input data from FILENAME. */
1190
1191 static void
1192 read_input (const char *filename)
1193 {
1194 FILE *fp = fopen (filename, "r");
1195 if (fp == NULL)
1196 error (EXIT_FAILURE, errno, "open '%s'", filename);
1197 unsigned int lineno = 0;
1198 for (;;)
1199 {
1200 size_t size = 0;
1201 char *line = NULL;
1202 ssize_t ret = getline (&line, &size, fp);
1203 if (ret == -1)
1204 break;
1205 lineno++;
1206 if (line[0] == '#' || line[0] == '\n')
1207 continue;
1208 add_test (line, filename, lineno);
1209 }
1210 if (ferror (fp))
1211 error (EXIT_FAILURE, errno, "read from '%s'", filename);
1212 if (fclose (fp) != 0)
1213 error (EXIT_FAILURE, errno, "close '%s'", filename);
1214 }
1215
1216 /* Calculate the generic results (round-to-zero with sticky bit) for
1217 the function described by CALC, with inputs INPUTS. */
1218
1219 static void
1220 calc_generic_results (generic_value *outputs, generic_value *inputs,
1221 const func_calc_desc *calc)
1222 {
1223 bool inexact;
1224 switch (calc->method)
1225 {
1226 case mpfr_f_f:
1227 assert (inputs[0].type == gtype_fp);
1228 outputs[0].type = gtype_fp;
1229 mpfr_init (outputs[0].value.f);
1230 inexact = calc->func.mpfr_f_f (outputs[0].value.f, inputs[0].value.f,
1231 MPFR_RNDZ);
1232 adjust_real (outputs[0].value.f, inexact);
1233 break;
1234
1235 default:
1236 abort ();
1237 }
1238 }
1239
1240 /* Return the number of bits for integer type TYPE, where "long" has
1241 LONG_BITS bits (32 or 64). */
1242
1243 static int
1244 int_type_bits (arg_ret_type type, int long_bits)
1245 {
1246 assert (long_bits == 32 || long_bits == 64);
1247 switch (type)
1248 {
1249 case type_int:
1250 return 32;
1251 break;
1252
1253 case type_long:
1254 return long_bits;
1255 break;
1256
1257 case type_long_long:
1258 return 64;
1259 break;
1260
1261 default:
1262 abort ();
1263 }
1264 }
1265
1266 /* Check whether an integer Z fits a given type TYPE, where "long" has
1267 LONG_BITS bits (32 or 64). */
1268
1269 static bool
1270 int_fits_type (mpz_t z, arg_ret_type type, int long_bits)
1271 {
1272 int bits = int_type_bits (type, long_bits);
1273 bool ret = true;
1274 mpz_t t;
1275 mpz_init (t);
1276 mpz_ui_pow_ui (t, 2, bits - 1);
1277 if (mpz_cmp (z, t) >= 0)
1278 ret = false;
1279 mpz_neg (t, t);
1280 if (mpz_cmp (z, t) < 0)
1281 ret = false;
1282 mpz_clear (t);
1283 return ret;
1284 }
1285
1286 /* Print a generic value V to FP (name FILENAME), preceded by a space,
1287 for type TYPE, floating-point format FORMAT, LONG_BITS bits per
1288 long, printing " IGNORE" instead if IGNORE. */
1289
1290 static void
1291 output_generic_value (FILE *fp, const char *filename, const generic_value *v,
1292 bool ignore, arg_ret_type type, fp_format format,
1293 int long_bits)
1294 {
1295 if (ignore)
1296 {
1297 if (fputs (" IGNORE", fp) < 0)
1298 error (EXIT_FAILURE, errno, "write to '%s'", filename);
1299 return;
1300 }
1301 assert (v->type == generic_arg_ret_type (type));
1302 const char *suffix;
1303 switch (type)
1304 {
1305 case type_fp:
1306 suffix = fp_formats[format].suffix;
1307 break;
1308
1309 case type_int:
1310 suffix = "";
1311 break;
1312
1313 case type_long:
1314 suffix = "L";
1315 break;
1316
1317 case type_long_long:
1318 suffix = "LL";
1319 break;
1320
1321 default:
1322 abort ();
1323 }
1324 switch (v->type)
1325 {
1326 case gtype_fp:
1327 if (mpfr_inf_p (v->value.f))
1328 {
1329 if (fputs ((mpfr_signbit (v->value.f)
1330 ? " minus_infty" : " plus_infty"), fp) < 0)
1331 error (EXIT_FAILURE, errno, "write to '%s'", filename);
1332 }
1333 else
1334 {
1335 assert (mpfr_number_p (v->value.f));
1336 if (mpfr_fprintf (fp, " %Ra%s", v->value.f, suffix) < 0)
1337 error (EXIT_FAILURE, errno, "mpfr_fprintf to '%s'", filename);
1338 }
1339 break;
1340
1341 case gtype_int: ;
1342 int bits = int_type_bits (type, long_bits);
1343 mpz_t tmp;
1344 mpz_init (tmp);
1345 mpz_ui_pow_ui (tmp, 2, bits - 1);
1346 mpz_neg (tmp, tmp);
1347 if (mpz_cmp (v->value.i, tmp) == 0)
1348 {
1349 mpz_add_ui (tmp, tmp, 1);
1350 if (mpfr_fprintf (fp, " (%Zd%s-1)", tmp, suffix) < 0)
1351 error (EXIT_FAILURE, errno, "mpfr_fprintf to '%s'", filename);
1352 }
1353 else
1354 {
1355 if (mpfr_fprintf (fp, " %Zd%s", v->value.i, suffix) < 0)
1356 error (EXIT_FAILURE, errno, "mpfr_fprintf to '%s'", filename);
1357 }
1358 mpz_clear (tmp);
1359 break;
1360
1361 default:
1362 abort ();
1363 }
1364 }
1365
1366 /* Generate test output to FP (name FILENAME) for test function TF,
1367 input test IT, choice of input values INPUTS. */
1368
1369 static void
1370 output_for_one_input_case (FILE *fp, const char *filename, test_function *tf,
1371 input_test *it, generic_value *inputs)
1372 {
1373 bool long_bits_matters = false;
1374 bool fits_long32 = true;
1375 for (size_t i = 0; i < tf->num_args; i++)
1376 {
1377 generic_value_type gtype = generic_arg_ret_type (tf->arg_types[i]);
1378 assert (inputs[i].type == gtype);
1379 if (gtype == gtype_int)
1380 {
1381 bool fits_64 = int_fits_type (inputs[i].value.i, tf->arg_types[i],
1382 64);
1383 if (!fits_64)
1384 return;
1385 if (tf->arg_types[i] == type_long
1386 && !int_fits_type (inputs[i].value.i, tf->arg_types[i], 32))
1387 {
1388 long_bits_matters = true;
1389 fits_long32 = false;
1390 }
1391 }
1392 }
1393 generic_value generic_outputs[MAX_NRET];
1394 calc_generic_results (generic_outputs, inputs, &tf->calc);
1395 bool ignore_output_long32[MAX_NRET] = { false };
1396 bool ignore_output_long64[MAX_NRET] = { false };
1397 for (size_t i = 0; i < tf->num_ret; i++)
1398 {
1399 assert (generic_outputs[i].type
1400 == generic_arg_ret_type (tf->ret_types[i]));
1401 switch (generic_outputs[i].type)
1402 {
1403 case gtype_fp:
1404 if (!mpfr_number_p (generic_outputs[i].value.f))
1405 goto out; /* Result is NaN or exact infinity. */
1406 break;
1407
1408 case gtype_int:
1409 ignore_output_long32[i] = !int_fits_type (generic_outputs[i].value.i,
1410 tf->ret_types[i], 32);
1411 ignore_output_long64[i] = !int_fits_type (generic_outputs[i].value.i,
1412 tf->ret_types[i], 64);
1413 if (ignore_output_long32[i] != ignore_output_long64[i])
1414 long_bits_matters = true;
1415 break;
1416
1417 default:
1418 abort ();
1419 }
1420 }
1421 /* Iterate over relevant sizes of long and floating-point formats. */
1422 for (int long_bits = 32; long_bits <= 64; long_bits += 32)
1423 {
1424 if (long_bits == 32 && !fits_long32)
1425 continue;
1426 if (long_bits == 64 && !long_bits_matters)
1427 continue;
1428 const char *long_cond;
1429 if (long_bits_matters)
1430 long_cond = (long_bits == 32 ? ":long32" : ":long64");
1431 else
1432 long_cond = "";
1433 bool *ignore_output = (long_bits == 32
1434 ? ignore_output_long32
1435 : ignore_output_long64);
1436 for (fp_format f = fp_first_format; f < fp_num_formats; f++)
1437 {
1438 bool fits = true;
1439 mpfr_t res[rm_num_modes];
1440 unsigned int exc_before[rm_num_modes];
1441 unsigned int exc_after[rm_num_modes];
1442 for (size_t i = 0; i < tf->num_args; i++)
1443 {
1444 if (inputs[i].type == gtype_fp)
1445 round_real (res, exc_before, exc_after, inputs[i].value.f, f);
1446 if (!mpfr_equal_p (res[rm_tonearest], inputs[i].value.f))
1447 fits = false;
1448 for (rounding_mode m = rm_first_mode; m < rm_num_modes; m++)
1449 mpfr_clear (res[m]);
1450 if (!fits)
1451 break;
1452 }
1453 if (!fits)
1454 continue;
1455 /* The inputs fit this type, so compute the ideal outputs
1456 and exceptions. */
1457 mpfr_t all_res[MAX_NRET][rm_num_modes];
1458 unsigned int all_exc_before[MAX_NRET][rm_num_modes];
1459 unsigned int all_exc_after[MAX_NRET][rm_num_modes];
1460 unsigned int merged_exc_before[rm_num_modes] = { 0 };
1461 unsigned int merged_exc_after[rm_num_modes] = { 0 };
1462 /* For functions not exactly determined, track whether
1463 underflow is required (some result is inexact, and
1464 magnitude does not exceed the greatest magnitude
1465 subnormal), and permitted (not an exact zero, and
1466 magnitude does not exceed the least magnitude
1467 normal). */
1468 bool must_underflow = false;
1469 bool may_underflow = false;
1470 for (size_t i = 0; i < tf->num_ret; i++)
1471 {
1472 switch (generic_outputs[i].type)
1473 {
1474 case gtype_fp:
1475 round_real (all_res[i], all_exc_before[i], all_exc_after[i],
1476 generic_outputs[i].value.f, f);
1477 for (rounding_mode m = rm_first_mode; m < rm_num_modes; m++)
1478 {
1479 merged_exc_before[m] |= all_exc_before[i][m];
1480 merged_exc_after[m] |= all_exc_after[i][m];
1481 if (!tf->exact)
1482 {
1483 must_underflow
1484 |= ((all_exc_before[i][m]
1485 & (1U << exc_inexact)) != 0
1486 && (mpfr_cmpabs (generic_outputs[i].value.f,
1487 fp_formats[f].subnorm_max)
1488 <= 0));
1489 may_underflow
1490 |= (!mpfr_zero_p (generic_outputs[i].value.f)
1491 && mpfr_cmpabs (generic_outputs[i].value.f,
1492 fp_formats[f].min) <= 0);
1493 }
1494 }
1495 break;
1496
1497 case gtype_int:
1498 if (ignore_output[i])
1499 for (rounding_mode m = rm_first_mode;
1500 m < rm_num_modes;
1501 m++)
1502 {
1503 merged_exc_before[m] |= 1U << exc_invalid;
1504 merged_exc_after[m] |= 1U << exc_invalid;
1505 }
1506 break;
1507
1508 default:
1509 abort ();
1510 }
1511 }
1512 assert (may_underflow || !must_underflow);
1513 for (rounding_mode m = rm_first_mode; m < rm_num_modes; m++)
1514 {
1515 bool before_after_matters
1516 = tf->exact && merged_exc_before[m] != merged_exc_after[m];
1517 for (int after = 0; after <= 1; after++)
1518 {
1519 if (after == 1 && !before_after_matters)
1520 continue;
1521 const char *after_cond;
1522 if (before_after_matters)
1523 after_cond = (after
1524 ? ":after-rounding"
1525 : ":before-rounding");
1526 else
1527 after_cond = "";
1528 unsigned int merged_exc = (after
1529 ? merged_exc_after[m]
1530 : merged_exc_before[m]);
1531 if (fprintf (fp, "= %s %s %s%s%s", tf->name,
1532 rounding_modes[m].name, fp_formats[f].name,
1533 long_cond, after_cond) < 0)
1534 error (EXIT_FAILURE, errno, "write to '%s'", filename);
1535 /* Print inputs. */
1536 for (size_t i = 0; i < tf->num_args; i++)
1537 output_generic_value (fp, filename, &inputs[i], false,
1538 tf->arg_types[i], f, long_bits);
1539 if (fputs (" :", fp) < 0)
1540 error (EXIT_FAILURE, errno, "write to '%s'", filename);
1541 /* Print outputs. */
1542 bool must_erange = false;
1543 for (size_t i = 0; i < tf->num_ret; i++)
1544 {
1545 generic_value g;
1546 g.type = generic_outputs[i].type;
1547 switch (g.type)
1548 {
1549 case gtype_fp:
1550 if (mpfr_inf_p (all_res[i][m])
1551 && (all_exc_before[i][m]
1552 & (1U << exc_overflow)) != 0)
1553 must_erange = true;
1554 if (mpfr_zero_p (all_res[i][m])
1555 && (tf->exact
1556 || mpfr_zero_p (all_res[i][rm_tonearest]))
1557 && (all_exc_before[i][m]
1558 & (1U << exc_underflow)) != 0)
1559 must_erange = true;
1560 mpfr_init2 (g.value.f, fp_formats[f].mant_dig);
1561 assert_exact (mpfr_set (g.value.f, all_res[i][m],
1562 MPFR_RNDN));
1563 break;
1564
1565 case gtype_int:
1566 mpz_init (g.value.i);
1567 mpz_set (g.value.i, generic_outputs[i].value.i);
1568 break;
1569
1570 default:
1571 abort ();
1572 }
1573 output_generic_value (fp, filename, &g, ignore_output[i],
1574 tf->ret_types[i], f, long_bits);
1575 generic_value_free (&g);
1576 }
1577 if (fputs (" :", fp) < 0)
1578 error (EXIT_FAILURE, errno, "write to '%s'", filename);
1579 /* Print miscellaneous flags (passed through from
1580 input). */
1581 for (size_t i = 0; i < it->num_flags; i++)
1582 switch (it->flags[i].type)
1583 {
1584 case flag_no_test_inline:
1585 case flag_xfail:
1586 if (fprintf (fp, " %s%s",
1587 input_flags[it->flags[i].type],
1588 (it->flags[i].cond
1589 ? it->flags[i].cond
1590 : "")) < 0)
1591 error (EXIT_FAILURE, errno, "write to '%s'",
1592 filename);
1593 break;
1594 default:
1595 break;
1596 }
1597 /* Print exception flags and compute errno
1598 expectations where not already computed. */
1599 bool may_edom = false;
1600 bool must_edom = false;
1601 bool may_erange = must_erange || may_underflow;
1602 for (fp_exception e = exc_first_exception;
1603 e < exc_num_exceptions;
1604 e++)
1605 {
1606 bool expect_e = (merged_exc & (1U << e)) != 0;
1607 bool e_optional = false;
1608 switch (e)
1609 {
1610 case exc_divbyzero:
1611 if (expect_e)
1612 may_erange = must_erange = true;
1613 break;
1614
1615 case exc_inexact:
1616 if (!tf->exact)
1617 e_optional = true;
1618 break;
1619
1620 case exc_invalid:
1621 if (expect_e)
1622 may_edom = must_edom = true;
1623 break;
1624
1625 case exc_overflow:
1626 if (expect_e)
1627 may_erange = true;
1628 break;
1629
1630 case exc_underflow:
1631 if (expect_e)
1632 may_erange = true;
1633 if (must_underflow)
1634 assert (expect_e);
1635 if (may_underflow && !must_underflow)
1636 e_optional = true;
1637 break;
1638
1639 default:
1640 abort ();
1641 }
1642 if (e_optional)
1643 {
1644 if (fprintf (fp, " %s-ok", exceptions[e]) < 0)
1645 error (EXIT_FAILURE, errno, "write to '%s'",
1646 filename);
1647 }
1648 else
1649 {
1650 if (expect_e)
1651 if (fprintf (fp, " %s", exceptions[e]) < 0)
1652 error (EXIT_FAILURE, errno, "write to '%s'",
1653 filename);
1654 input_flag_type okflag;
1655 okflag = (expect_e
1656 ? flag_missing_first
1657 : flag_spurious_first) + e;
1658 for (size_t i = 0; i < it->num_flags; i++)
1659 if (it->flags[i].type == okflag)
1660 if (fprintf (fp, " %s-ok%s",
1661 exceptions[e],
1662 (it->flags[i].cond
1663 ? it->flags[i].cond
1664 : "")) < 0)
1665 error (EXIT_FAILURE, errno, "write to '%s'",
1666 filename);
1667 }
1668 }
1669 /* Print errno expectations. */
1670 if (tf->complex_fn)
1671 {
1672 must_edom = false;
1673 must_erange = false;
1674 }
1675 if (may_edom && !must_edom)
1676 {
1677 if (fputs (" errno-edom-ok", fp) < 0)
1678 error (EXIT_FAILURE, errno, "write to '%s'",
1679 filename);
1680 }
1681 else
1682 {
1683 if (must_edom)
1684 if (fputs (" errno-edom", fp) < 0)
1685 error (EXIT_FAILURE, errno, "write to '%s'",
1686 filename);
1687 input_flag_type okflag = (must_edom
1688 ? flag_missing_errno
1689 : flag_spurious_errno);
1690 for (size_t i = 0; i < it->num_flags; i++)
1691 if (it->flags[i].type == okflag)
1692 if (fprintf (fp, " errno-edom-ok%s",
1693 (it->flags[i].cond
1694 ? it->flags[i].cond
1695 : "")) < 0)
1696 error (EXIT_FAILURE, errno, "write to '%s'",
1697 filename);
1698 }
1699 if (may_erange && !must_erange)
1700 {
1701 if (fputs (" errno-erange-ok", fp) < 0)
1702 error (EXIT_FAILURE, errno, "write to '%s'",
1703 filename);
1704 }
1705 else
1706 {
1707 if (must_erange)
1708 if (fputs (" errno-erange", fp) < 0)
1709 error (EXIT_FAILURE, errno, "write to '%s'",
1710 filename);
1711 input_flag_type okflag = (must_erange
1712 ? flag_missing_errno
1713 : flag_spurious_errno);
1714 for (size_t i = 0; i < it->num_flags; i++)
1715 if (it->flags[i].type == okflag)
1716 if (fprintf (fp, " errno-erange-ok%s",
1717 (it->flags[i].cond
1718 ? it->flags[i].cond
1719 : "")) < 0)
1720 error (EXIT_FAILURE, errno, "write to '%s'",
1721 filename);
1722 }
1723 if (putc ('\n', fp) < 0)
1724 error (EXIT_FAILURE, errno, "write to '%s'", filename);
1725 }
1726 }
1727 for (size_t i = 0; i < tf->num_ret; i++)
1728 {
1729 if (generic_outputs[i].type == gtype_fp)
1730 for (rounding_mode m = rm_first_mode; m < rm_num_modes; m++)
1731 mpfr_clear (all_res[i][m]);
1732 }
1733 }
1734 }
1735 out:
1736 for (size_t i = 0; i < tf->num_ret; i++)
1737 generic_value_free (&generic_outputs[i]);
1738 }
1739
1740 /* Generate test output data to FILENAME. */
1741
1742 static void
1743 generate_output (const char *filename)
1744 {
1745 FILE *fp = fopen (filename, "w");
1746 if (fp == NULL)
1747 error (EXIT_FAILURE, errno, "open '%s'", filename);
1748 for (size_t i = 0; i < ARRAY_SIZE (test_functions); i++)
1749 {
1750 test_function *tf = &test_functions[i];
1751 for (size_t j = 0; j < tf->num_tests; j++)
1752 {
1753 input_test *it = &tf->tests[j];
1754 if (fputs (it->line, fp) < 0)
1755 error (EXIT_FAILURE, errno, "write to '%s'", filename);
1756 for (size_t k = 0; k < it->num_input_cases; k++)
1757 output_for_one_input_case (fp, filename, tf, it, it->inputs[k]);
1758 }
1759 }
1760 if (fclose (fp) != 0)
1761 error (EXIT_FAILURE, errno, "close '%s'", filename);
1762 }
1763
1764 int
1765 main (int argc, char **argv)
1766 {
1767 if (argc != 3)
1768 error (EXIT_FAILURE, 0, "usage: gen-auto-libm-tests <input> <output>");
1769 const char *input_filename = argv[1];
1770 const char *output_filename = argv[2];
1771 init_fp_formats ();
1772 read_input (input_filename);
1773 generate_output (output_filename);
1774 exit (EXIT_SUCCESS);
1775 }