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
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
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. 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.
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). */
137 #define ARRAY_SIZE(A) (sizeof (A) / sizeof ((A)[0]))
139 /* The supported floating-point formats. */
152 /* Structure describing a single floating-point format. */
155 /* The name of the format. */
157 /* The suffix to use on floating-point constants with this
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. */
165 /* The least N such that 2^N overflows. */
167 /* One more than the least N such that 2^N is normal. */
169 /* The largest normal value. */
171 /* The least positive normal value, 2^(MIN_EXP-1). */
173 /* The greatest positive subnormal value. */
175 /* The least positive subnormal value, 2^(MIN_EXP-MANT_DIG). */
179 /* List of floating-point formats, in the same order as the fp_format
181 static fp_format_desc fp_formats
[fp_num_formats
] =
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, {}, {}, {}, {} },
192 /* The supported rounding modes. */
203 /* Structure describing a single rounding mode. */
206 /* The name of the rounding mode. */
208 /* The MPFR rounding mode. */
209 mpfr_rnd_t mpfr_mode
;
210 } rounding_mode_desc
;
212 /* List of rounding modes, in the same order as the rounding_mode
214 static const rounding_mode_desc rounding_modes
[rm_num_modes
] =
216 { "downward", MPFR_RNDD
},
217 { "tonearest", MPFR_RNDN
},
218 { "towardzero", MPFR_RNDZ
},
219 { "upward", MPFR_RNDU
},
222 /* The supported exceptions. */
231 exc_first_exception
= 0
234 /* List of exceptions, in the same order as the fp_exception
236 static const char *const exceptions
[exc_num_exceptions
] =
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
;
250 /* A value that overflows all supported floating-point formats. */
251 static mpfr_t global_max
;
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
;
258 /* The maximum number of (real or integer) arguments to a function
259 handled by this program (complex arguments count as two real
263 /* The maximum number of (real or integer) return values from a
264 function handled by this program. */
267 /* A type of a function argument or return value. */
270 /* No type (not a valid argument or return value). */
272 /* A floating-point value with the type corresponding to that of
275 /* An integer value of type int. */
277 /* An integer value of type long. */
279 /* An integer value of type long long. */
283 /* A type of a generic real or integer value. */
288 /* Floating-point (represented with MPFR). */
290 /* Integer (represented with GMP). */
292 } generic_value_type
;
294 /* A generic value (argument or result). */
297 /* The type of this value. */
298 generic_value_type type
;
307 /* A type of input flag. */
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
,
320 flag_missing_divbyzero
,
321 flag_missing_inexact
,
322 flag_missing_invalid
,
323 flag_missing_overflow
,
324 flag_missing_underflow
,
326 num_input_flag_types
,
328 flag_spurious_first
= flag_spurious_divbyzero
,
329 flag_missing_first
= flag_missing_divbyzero
332 /* List of flags, in the same order as the input_flag_type
334 static const char *const input_flags
[num_input_flag_types
] =
338 "spurious-divbyzero",
342 "spurious-underflow",
352 /* An input flag, possibly conditional. */
355 /* The type of this flag. */
356 input_flag_type type
;
357 /* The conditions on this flag, as a string ":cond1:cond2..." or
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
369 /* The text of the input line describing the test, including the
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. */
379 /* The corresponding list of flags. */
381 /* The old output for this test. */
382 const char *old_output
;
385 /* Ways to calculate a function. */
388 /* MPFR function with a single argument and result. */
392 /* Description of how to calculate a function. */
395 /* Which method is used to calculate the function. */
396 func_calc_method method
;
397 /* The specific function called. */
400 int (*mpfr_f_f
) (mpfr_t
, const mpfr_t
, mpfr_rnd_t
);
404 /* Structure describing a function handled by this program. */
407 /* The name of the function. */
409 /* The number of arguments. */
411 /* The types of the arguments. */
412 arg_ret_type arg_types
[MAX_NARGS
];
413 /* The number of return values. */
415 /* The types of the return values. */
416 arg_ret_type ret_types
[MAX_NRET
];
417 /* Whether the function has exactly determined results and
420 /* Whether the function is a complex function, so errno setting is
423 /* How to calculate this function. */
425 /* The number of tests allocated for this function. */
426 size_t num_tests_alloc
;
427 /* The number of tests for this function. */
429 /* The tests themselves. */
433 #define FUNC_mpfr_f_f(NAME, MPFR_FUNC, EXACT) \
435 NAME, 1, { type_fp }, 1, { type_fp }, EXACT, false, \
436 { mpfr_f_f, { .mpfr_f_f = MPFR_FUNC } }, 0, 0, NULL \
439 /* List of functions handled by this program. */
440 static test_function test_functions
[] =
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),
473 /* Allocate memory, with error checking. */
478 void *p
= malloc (n
);
480 error (EXIT_FAILURE
, errno
, "xmalloc failed");
485 xrealloc (void *p
, size_t n
)
489 error (EXIT_FAILURE
, errno
, "xrealloc failed");
494 xstrdup (const char *s
)
496 char *p
= strdup (s
);
498 error (EXIT_FAILURE
, errno
, "xstrdup failed");
502 /* Assert that the result of an MPFR operation was exact; that is,
503 that the returned ternary value was 0. */
511 /* Return the generic type of an argument or return value type T. */
513 static generic_value_type
514 generic_arg_ret_type (arg_ret_type t
)
531 /* Free a generic_value *V. */
534 generic_value_free (generic_value
*v
)
539 mpfr_clear (v
->value
.f
);
543 mpz_clear (v
->value
.i
);
551 /* Copy a generic_value *SRC to *DEST. */
554 generic_value_copy (generic_value
*dest
, const generic_value
*src
)
556 dest
->type
= src
->type
;
560 mpfr_init (dest
->value
.f
);
561 assert_exact (mpfr_set (dest
->value
.f
, src
->value
.f
, MPFR_RNDN
));
565 mpz_init (dest
->value
.i
);
566 mpz_set (dest
->value
.i
, src
->value
.i
);
574 /* Initialize data for floating-point formats. */
579 int global_max_exp
= 0, global_min_subnorm_exp
= 0;
580 for (fp_format f
= fp_first_format
; f
< fp_num_formats
; f
++)
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
)
593 assert_exact (mpfr_strtofr (fp_formats
[f
].max
,
594 fp_formats
[f
].max_string
,
600 assert_exact (mpfr_set_ui_2exp (fp_formats
[f
].max
, 1,
601 fp_formats
[f
].max_exp
,
603 mpfr_nextbelow (fp_formats
[f
].max
);
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,
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
,
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
));
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,
626 /* Fill in mpfr_t values for special strings in input arguments. */
629 special_fill_max (mpfr_t res0
, mpfr_t res1
__attribute__ ((unused
)),
632 mpfr_init2 (res0
, fp_formats
[format
].mant_dig
);
633 assert_exact (mpfr_set (res0
, fp_formats
[format
].max
, MPFR_RNDN
));
638 special_fill_minus_max (mpfr_t res0
, mpfr_t res1
__attribute__ ((unused
)),
641 mpfr_init2 (res0
, fp_formats
[format
].mant_dig
);
642 assert_exact (mpfr_neg (res0
, fp_formats
[format
].max
, MPFR_RNDN
));
647 special_fill_pi (mpfr_t res0
, mpfr_t res1
, fp_format format
)
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
);
657 special_fill_minus_pi (mpfr_t res0
, mpfr_t res1
, fp_format format
)
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
));
669 special_fill_pi_2 (mpfr_t res0
, mpfr_t res1
, fp_format format
)
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
));
681 special_fill_minus_pi_2 (mpfr_t res0
, mpfr_t res1
, fp_format format
)
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
));
695 special_fill_pi_6 (mpfr_t res0
, mpfr_t res1
, fp_format format
)
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
);
707 special_fill_minus_pi_6 (mpfr_t res0
, mpfr_t res1
, fp_format format
)
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
);
719 special_fill_pi_3 (mpfr_t res0
, mpfr_t res1
, fp_format format
)
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
);
731 special_fill_2pi_3 (mpfr_t res0
, mpfr_t res1
, fp_format format
)
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
);
743 special_fill_e (mpfr_t res0
, mpfr_t res1
, fp_format format
)
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
);
755 special_fill_1_e (mpfr_t res0
, mpfr_t res1
, fp_format format
)
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
);
767 special_fill_e_minus_1 (mpfr_t res0
, mpfr_t res1
, fp_format format
)
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
);
778 /* A special string accepted in input arguments. */
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
;
789 /* List of special strings accepted in input arguments. */
791 static const special_real_input special_real_inputs
[] =
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
},
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. */
813 adjust_real (mpfr_t r
, bool inexact
)
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
));
827 mpfr_exp_t e
= mpfr_get_z_2exp (tmp
, r
);
829 assert_exact (mpfr_set_z_2exp (r
, tmp
, e
, MPFR_RNDN
));
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. */
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
)
845 assert (mpfr_number_p (r
));
846 for (rounding_mode m
= rm_first_mode
; m
< rm_num_modes
; m
++)
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)
854 exc_before
[m
] |= 1U << exc_overflow
;
855 exc_after
[m
] |= 1U << exc_overflow
;
863 overflow_inf
= false;
866 overflow_inf
= mpfr_signbit (res
[m
]);
869 overflow_inf
= !mpfr_signbit (res
[m
]);
875 mpfr_set_inf (res
[m
], mpfr_signbit (res
[m
]) ? -1 : 1);
877 assert_exact (mpfr_copysign (res
[m
], fp_formats
[format
].max
,
880 if (mpfr_cmpabs (r
, fp_formats
[format
].min
) < 0)
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. */
892 assert_exact (mpfr_mul_2si (tmp
, r
, (fp_formats
[format
].mant_dig
893 - fp_formats
[format
].min_exp
),
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. */
901 assert (rint_res
!= 0);
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
),
911 exc_before
[m
] |= 1U << exc_underflow
;
912 if (tiny_after_rounding
)
913 exc_after
[m
] |= 1U << exc_underflow
;
918 exc_before
[m
] |= 1U << exc_inexact
;
919 exc_after
[m
] |= 1U << exc_inexact
;
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. */
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
)
934 size_t num_values
= 0;
935 generic_value values
[2 * fp_num_formats
];
939 for (fp_format f
= fp_first_format
; f
< fp_num_formats
; f
++)
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
++)
945 if (strcmp (arg
, special_real_inputs
[i
].str
) == 0)
948 = special_real_inputs
[i
].func (extra_values
[0],
950 assert (num_extra_values
> 0
951 && num_extra_values
<= ARRAY_SIZE (extra_values
));
955 if (num_extra_values
== 0)
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
);
970 if (mpfr_number_p (rounded
[rm_upward
]))
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
));
978 if (mpfr_number_p (rounded
[rm_downward
]))
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
));
986 for (rounding_mode m
= rm_first_mode
; m
< rm_num_modes
; m
++)
987 mpfr_clear (rounded
[m
]);
989 for (size_t i
= 0; i
< num_extra_values
; i
++)
992 for (size_t j
= 0; j
< num_values
; j
++)
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)))
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
));
1012 mpfr_clear (extra_values
[i
]);
1019 values
[0].type
= gtype_int
;
1020 int ret
= mpz_init_set_str (values
[0].value
.i
, arg
, 0);
1022 error_at_line (EXIT_FAILURE
, 0, filename
, lineno
,
1023 "bad integer argument: '%s'", arg
);
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
++)
1038 for (size_t j
= 0; j
< num_values
; j
++)
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
]);
1047 for (size_t j
= 0; j
< num_prev_args
; j
++)
1048 generic_value_free (&old_inputs
[i
][j
]);
1049 free (old_inputs
[i
]);
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
;
1058 /* Handle the input flag ARG (NUL-terminated), storing it in *FLAG.
1059 The flag comes from file FILENAME, line LINENO. */
1062 handle_input_flag (char *arg
, input_flag
*flag
,
1063 const char *filename
, unsigned int lineno
)
1065 char *ep
= strchr (arg
, ':');
1068 ep
= strchr (arg
, 0);
1069 assert (ep
!= NULL
);
1074 for (input_flag_type i
= flag_first_flag
; i
<= num_input_flag_types
; i
++)
1076 if (strcmp (arg
, input_flags
[i
]) == 0)
1084 error_at_line (EXIT_FAILURE
, 0, filename
, lineno
, "unknown flag: '%s'",
1090 flag
->cond
= xstrdup (ep
);
1093 /* Add the test LINE (file FILENAME, line LINENO) to the test
1097 add_test (char *line
, const char *filename
, unsigned int lineno
)
1099 size_t num_tokens
= 1;
1101 while ((p
= strchr (p
, ' ')) != NULL
)
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
++)
1113 if (func_name_len
== strlen (test_functions
[i
].name
)
1114 && strncmp (line
, test_functions
[i
].name
, func_name_len
) == 0)
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
)
1122 tf
->num_tests_alloc
= 2 * tf
->num_tests_alloc
+ 16;
1124 = xrealloc (tf
->tests
,
1125 tf
->num_tests_alloc
* sizeof (tf
->tests
[0]));
1127 input_test
*it
= &tf
->tests
[tf
->num_tests
];
1129 it
->num_input_cases
= 1;
1130 it
->inputs
= xmalloc (sizeof (it
->inputs
[0]));
1131 it
->inputs
[0] = NULL
;
1132 it
->old_output
= NULL
;
1134 for (size_t j
= 0; j
< tf
->num_args
; j
++)
1136 char *ep
= strchr (p
, ' ');
1139 ep
= strchr (p
, '\n');
1140 assert (ep
!= NULL
);
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
);
1151 handle_input_arg (p
, it
, j
,
1152 generic_arg_ret_type (tf
->arg_types
[j
]),
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
++)
1161 char *ep
= strchr (p
, ' ');
1164 ep
= strchr (p
, '\n');
1165 assert (ep
!= NULL
);
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
);
1176 handle_input_flag (p
, &it
->flags
[j
], filename
, lineno
);
1185 error_at_line (EXIT_FAILURE
, 0, filename
, lineno
,
1186 "unknown function in line: '%s'", line
);
1189 /* Read in the test input data from FILENAME. */
1192 read_input (const char *filename
)
1194 FILE *fp
= fopen (filename
, "r");
1196 error (EXIT_FAILURE
, errno
, "open '%s'", filename
);
1197 unsigned int lineno
= 0;
1202 ssize_t ret
= getline (&line
, &size
, fp
);
1206 if (line
[0] == '#' || line
[0] == '\n')
1208 add_test (line
, filename
, lineno
);
1211 error (EXIT_FAILURE
, errno
, "read from '%s'", filename
);
1212 if (fclose (fp
) != 0)
1213 error (EXIT_FAILURE
, errno
, "close '%s'", filename
);
1216 /* Calculate the generic results (round-to-zero with sticky bit) for
1217 the function described by CALC, with inputs INPUTS. */
1220 calc_generic_results (generic_value
*outputs
, generic_value
*inputs
,
1221 const func_calc_desc
*calc
)
1224 switch (calc
->method
)
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
,
1232 adjust_real (outputs
[0].value
.f
, inexact
);
1240 /* Return the number of bits for integer type TYPE, where "long" has
1241 LONG_BITS bits (32 or 64). */
1244 int_type_bits (arg_ret_type type
, int long_bits
)
1246 assert (long_bits
== 32 || long_bits
== 64);
1257 case type_long_long
:
1266 /* Check whether an integer Z fits a given type TYPE, where "long" has
1267 LONG_BITS bits (32 or 64). */
1270 int_fits_type (mpz_t z
, arg_ret_type type
, int long_bits
)
1272 int bits
= int_type_bits (type
, long_bits
);
1276 mpz_ui_pow_ui (t
, 2, bits
- 1);
1277 if (mpz_cmp (z
, t
) >= 0)
1280 if (mpz_cmp (z
, t
) < 0)
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. */
1291 output_generic_value (FILE *fp
, const char *filename
, const generic_value
*v
,
1292 bool ignore
, arg_ret_type type
, fp_format format
,
1297 if (fputs (" IGNORE", fp
) < 0)
1298 error (EXIT_FAILURE
, errno
, "write to '%s'", filename
);
1301 assert (v
->type
== generic_arg_ret_type (type
));
1306 suffix
= fp_formats
[format
].suffix
;
1317 case type_long_long
:
1327 if (mpfr_inf_p (v
->value
.f
))
1329 if (fputs ((mpfr_signbit (v
->value
.f
)
1330 ? " minus_infty" : " plus_infty"), fp
) < 0)
1331 error (EXIT_FAILURE
, errno
, "write to '%s'", filename
);
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
);
1342 int bits
= int_type_bits (type
, long_bits
);
1345 mpz_ui_pow_ui (tmp
, 2, bits
- 1);
1347 if (mpz_cmp (v
->value
.i
, tmp
) == 0)
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
);
1355 if (mpfr_fprintf (fp
, " %Zd%s", v
->value
.i
, suffix
) < 0)
1356 error (EXIT_FAILURE
, errno
, "mpfr_fprintf to '%s'", filename
);
1366 /* Generate test output to FP (name FILENAME) for test function TF,
1367 input test IT, choice of input values INPUTS. */
1370 output_for_one_input_case (FILE *fp
, const char *filename
, test_function
*tf
,
1371 input_test
*it
, generic_value
*inputs
)
1373 bool long_bits_matters
= false;
1374 bool fits_long32
= true;
1375 for (size_t i
= 0; i
< tf
->num_args
; i
++)
1377 generic_value_type gtype
= generic_arg_ret_type (tf
->arg_types
[i
]);
1378 assert (inputs
[i
].type
== gtype
);
1379 if (gtype
== gtype_int
)
1381 bool fits_64
= int_fits_type (inputs
[i
].value
.i
, tf
->arg_types
[i
],
1385 if (tf
->arg_types
[i
] == type_long
1386 && !int_fits_type (inputs
[i
].value
.i
, tf
->arg_types
[i
], 32))
1388 long_bits_matters
= true;
1389 fits_long32
= false;
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
++)
1399 assert (generic_outputs
[i
].type
1400 == generic_arg_ret_type (tf
->ret_types
[i
]));
1401 switch (generic_outputs
[i
].type
)
1404 if (!mpfr_number_p (generic_outputs
[i
].value
.f
))
1405 goto out
; /* Result is NaN or exact infinity. */
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;
1421 /* Iterate over relevant sizes of long and floating-point formats. */
1422 for (int long_bits
= 32; long_bits
<= 64; long_bits
+= 32)
1424 if (long_bits
== 32 && !fits_long32
)
1426 if (long_bits
== 64 && !long_bits_matters
)
1428 const char *long_cond
;
1429 if (long_bits_matters
)
1430 long_cond
= (long_bits
== 32 ? ":long32" : ":long64");
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
++)
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
++)
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
))
1448 for (rounding_mode m
= rm_first_mode
; m
< rm_num_modes
; m
++)
1449 mpfr_clear (res
[m
]);
1455 /* The inputs fit this type, so compute the ideal outputs
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
1468 bool must_underflow
= false;
1469 bool may_underflow
= false;
1470 for (size_t i
= 0; i
< tf
->num_ret
; i
++)
1472 switch (generic_outputs
[i
].type
)
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
++)
1479 merged_exc_before
[m
] |= all_exc_before
[i
][m
];
1480 merged_exc_after
[m
] |= all_exc_after
[i
][m
];
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
)
1490 |= (!mpfr_zero_p (generic_outputs
[i
].value
.f
)
1491 && mpfr_cmpabs (generic_outputs
[i
].value
.f
,
1492 fp_formats
[f
].min
) <= 0);
1498 if (ignore_output
[i
])
1499 for (rounding_mode m
= rm_first_mode
;
1503 merged_exc_before
[m
] |= 1U << exc_invalid
;
1504 merged_exc_after
[m
] |= 1U << exc_invalid
;
1512 assert (may_underflow
|| !must_underflow
);
1513 for (rounding_mode m
= rm_first_mode
; m
< rm_num_modes
; m
++)
1515 bool before_after_matters
1516 = tf
->exact
&& merged_exc_before
[m
] != merged_exc_after
[m
];
1517 for (int after
= 0; after
<= 1; after
++)
1519 if (after
== 1 && !before_after_matters
)
1521 const char *after_cond
;
1522 if (before_after_matters
)
1525 : ":before-rounding");
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
);
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
++)
1546 g
.type
= generic_outputs
[i
].type
;
1550 if (mpfr_inf_p (all_res
[i
][m
])
1551 && (all_exc_before
[i
][m
]
1552 & (1U << exc_overflow
)) != 0)
1554 if (mpfr_zero_p (all_res
[i
][m
])
1556 || mpfr_zero_p (all_res
[i
][rm_tonearest
]))
1557 && (all_exc_before
[i
][m
]
1558 & (1U << exc_underflow
)) != 0)
1560 mpfr_init2 (g
.value
.f
, fp_formats
[f
].mant_dig
);
1561 assert_exact (mpfr_set (g
.value
.f
, all_res
[i
][m
],
1566 mpz_init (g
.value
.i
);
1567 mpz_set (g
.value
.i
, generic_outputs
[i
].value
.i
);
1573 output_generic_value (fp
, filename
, &g
, ignore_output
[i
],
1574 tf
->ret_types
[i
], f
, long_bits
);
1575 generic_value_free (&g
);
1577 if (fputs (" :", fp
) < 0)
1578 error (EXIT_FAILURE
, errno
, "write to '%s'", filename
);
1579 /* Print miscellaneous flags (passed through from
1581 for (size_t i
= 0; i
< it
->num_flags
; i
++)
1582 switch (it
->flags
[i
].type
)
1584 case flag_no_test_inline
:
1586 if (fprintf (fp
, " %s%s",
1587 input_flags
[it
->flags
[i
].type
],
1591 error (EXIT_FAILURE
, errno
, "write to '%s'",
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
;
1606 bool expect_e
= (merged_exc
& (1U << e
)) != 0;
1607 bool e_optional
= false;
1612 may_erange
= must_erange
= true;
1622 may_edom
= must_edom
= true;
1635 if (may_underflow
&& !must_underflow
)
1644 if (fprintf (fp
, " %s-ok", exceptions
[e
]) < 0)
1645 error (EXIT_FAILURE
, errno
, "write to '%s'",
1651 if (fprintf (fp
, " %s", exceptions
[e
]) < 0)
1652 error (EXIT_FAILURE
, errno
, "write to '%s'",
1654 input_flag_type okflag
;
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",
1665 error (EXIT_FAILURE
, errno
, "write to '%s'",
1669 /* Print errno expectations. */
1673 must_erange
= false;
1675 if (may_edom
&& !must_edom
)
1677 if (fputs (" errno-edom-ok", fp
) < 0)
1678 error (EXIT_FAILURE
, errno
, "write to '%s'",
1684 if (fputs (" errno-edom", fp
) < 0)
1685 error (EXIT_FAILURE
, errno
, "write to '%s'",
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",
1696 error (EXIT_FAILURE
, errno
, "write to '%s'",
1699 if (may_erange
&& !must_erange
)
1701 if (fputs (" errno-erange-ok", fp
) < 0)
1702 error (EXIT_FAILURE
, errno
, "write to '%s'",
1708 if (fputs (" errno-erange", fp
) < 0)
1709 error (EXIT_FAILURE
, errno
, "write to '%s'",
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",
1720 error (EXIT_FAILURE
, errno
, "write to '%s'",
1723 if (putc ('\n', fp
) < 0)
1724 error (EXIT_FAILURE
, errno
, "write to '%s'", filename
);
1727 for (size_t i
= 0; i
< tf
->num_ret
; i
++)
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
]);
1736 for (size_t i
= 0; i
< tf
->num_ret
; i
++)
1737 generic_value_free (&generic_outputs
[i
]);
1740 /* Generate test output data to FILENAME. */
1743 generate_output (const char *filename
)
1745 FILE *fp
= fopen (filename
, "w");
1747 error (EXIT_FAILURE
, errno
, "open '%s'", filename
);
1748 for (size_t i
= 0; i
< ARRAY_SIZE (test_functions
); i
++)
1750 test_function
*tf
= &test_functions
[i
];
1751 for (size_t j
= 0; j
< tf
->num_tests
; j
++)
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
]);
1760 if (fclose (fp
) != 0)
1761 error (EXIT_FAILURE
, errno
, "close '%s'", filename
);
1765 main (int argc
, char **argv
)
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];
1772 read_input (input_filename
);
1773 generate_output (output_filename
);
1774 exit (EXIT_SUCCESS
);