]> git.ipfire.org Git - thirdparty/glibc.git/blame - math/gen-auto-libm-tests.c
arc: Cleanup arcbe
[thirdparty/glibc.git] / math / gen-auto-libm-tests.c
CommitLineData
ffb536d0 1/* Generate expected output for libm tests with MPFR and MPC.
dff8da6b 2 Copyright (C) 2013-2024 Free Software Foundation, Inc.
ffb536d0
JM
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
5a82c748 17 <https://www.gnu.org/licenses/>. */
ffb536d0
JM
18
19/* Compile this program as:
20
783dd2d3 21 gcc -std=gnu11 -O2 -Wall -Wextra gen-auto-libm-tests.c -lmpc -lmpfr -lgmp \
ffb536d0
JM
22 -o gen-auto-libm-tests
23
24 (use of current MPC and MPFR versions recommended) and run it as:
25
4f1bc131 26 gen-auto-libm-tests auto-libm-test-in <func> auto-libm-test-out-<func>
ffb536d0 27
8e554659
JM
28 to generate results for normal libm functions, or
29
30 gen-auto-libm-tests --narrow auto-libm-test-in <func> \
31 auto-libm-test-out-narrow-<func>
32
33 to generate results for a function rounding results to a narrower
34 type (in the case of fma and sqrt, both output files are generated
35 from the same test inputs).
36
ffb536d0
JM
37 The input file auto-libm-test-in contains three kinds of lines:
38
39 Lines beginning with "#" are comments, and are ignored, as are
40 empty lines.
41
42 Other lines are test lines, of the form "function input1 input2
43 ... [flag1 flag2 ...]". Inputs are either finite real numbers or
44 integers, depending on the function under test. Real numbers may
45 be in any form acceptable to mpfr_strtofr (base 0); integers in any
46 form acceptable to mpz_set_str (base 0). In addition, real numbers
47 may be certain special strings such as "pi", as listed in the
48 special_real_inputs array.
49
50 Each flag is a flag name possibly followed by a series of
51 ":condition". Conditions may be any of the names of floating-point
52 formats in the floating_point_formats array, "long32" and "long64"
53 to indicate the number of bits in the "long" type, or other strings
54 for which libm-test.inc defines a TEST_COND_<condition> macro (with
55 "-"- changed to "_" in the condition name) evaluating to nonzero
56 when the condition is true and zero when the condition is false.
57 The meaning is that the flag applies to the test if all the listed
58 conditions are true. "flag:cond1:cond2 flag:cond3:cond4" means the
59 flag applies if ((cond1 && cond2) || (cond3 && cond4)).
60
61 A real number specified as an input is considered to represent the
62 set of real numbers arising from rounding the given number in any
63 direction for any supported floating-point format; any roundings
64 that give infinity are ignored. Each input on a test line has all
65 the possible roundings considered independently. Each resulting
66 choice of the tuple of inputs to the function is ignored if the
67 mathematical result of the function involves a NaN or an exact
68 infinity, and is otherwise considered for each floating-point
69 format for which all those inputs are exactly representable. Thus
70 tests may result in "overflow", "underflow" and "inexact"
71 exceptions; "invalid" may arise only when the final result type is
72 an integer type and it is the conversion of a mathematically
73 defined finite result to integer type that results in that
74 exception.
75
76 By default, it is assumed that "overflow" and "underflow"
77 exceptions should be correct, but that "inexact" exceptions should
78 only be correct for functions listed as exactly determined. For
79 such functions, "underflow" exceptions should respect whether the
80 machine has before-rounding or after-rounding tininess detection.
81 For other functions, it is considered that if the exact result is
82 somewhere between the greatest magnitude subnormal of a given sign
83 (exclusive) and the least magnitude normal of that sign
84 (inclusive), underflow exceptions are permitted but optional on all
85 machines, and they are also permitted but optional for smaller
86 subnormal exact results for functions that are not exactly
87 determined. errno setting is expected for overflow to infinity and
88 underflow to zero (for real functions), and for out-of-range
89 conversion of a finite result to integer type, and is considered
90 permitted but optional for all other cases where overflow
91 exceptions occur, and where underflow exceptions occur or are
92 permitted. In other cases (where no overflow or underflow is
93 permitted), errno is expected to be left unchanged.
94
1c15464c 95 The flag "ignore-zero-inf-sign" indicates the the signs of
863893ec
JM
96 zero and infinite results should be ignored; "xfail" indicates the
97 test is disabled as expected to produce incorrect results,
98 "xfail-rounding" indicates the test is disabled only in rounding
5bc9b3a1
WD
99 modes other than round-to-nearest; "no-mathvec" indicates the test
100 is disabled in vector math libraries. Otherwise, test flags are of
863893ec
JM
101 the form "spurious-<exception>" and "missing-<exception>", for any
102 exception ("overflow", "underflow", "inexact", "invalid",
103 "divbyzero"), "spurious-errno" and "missing-errno", to indicate
104 when tests are expected to deviate from the exception and errno
105 settings corresponding to the mathematical results. "xfail",
d8e2dbe3
JM
106 "xfail-rounding", "spurious-" and "missing-" flags should be
107 accompanied by a comment referring to an open bug in glibc
108 Bugzilla.
ffb536d0 109
4f1bc131 110 The output file auto-libm-test-out-<func> contains the test lines from
ffb536d0
JM
111 auto-libm-test-in, and, after the line for a given test, some
112 number of output test lines. An output test line is of the form "=
113 function rounding-mode format input1 input2 ... : output1 output2
114 ... : flags". rounding-mode is "tonearest", "towardzero", "upward"
115 or "downward". format is a name from the floating_point_formats
116 array, possibly followed by a sequence of ":flag" for flags from
aa97dee1
JM
117 "long32" and "long64". Inputs and outputs are specified as hex
118 floats with the required suffix for the floating-point type, or
119 plus_infty or minus_infty for infinite expected results, or as
120 integer constant expressions (not necessarily with the right type)
121 or IGNORE for integer inputs and outputs. Flags are
1c15464c 122 "ignore-zero-info-sign", "xfail", "<exception>",
863893ec
JM
123 "<exception>-ok", "errno-<value>", "errno-<value>-ok", which may be
124 unconditional or conditional. "<exception>" indicates that a
125 correct result means the given exception should be raised.
126 "errno-<value>" indicates that a correct result means errno should
127 be set to the given value. "-ok" means not to test for the given
128 exception or errno value (whether because it was marked as possibly
129 missing or spurious, or because the calculation of correct results
130 indicated it was optional). Conditions "before-rounding" and
131 "after-rounding" indicate tests where expectations for underflow
8e554659
JM
132 exceptions depend on how the architecture detects tininess.
133
134 For functions rounding their results to a narrower type, the format
135 given on an output test line is the result format followed by
136 information about the requirements on the argument format to be
137 able to represent the argument values, in the form
138 "format:arg_fmt(MAX_EXP,NUM_ONES,MIN_EXP,MAX_PREC)". Instead of
139 separate lines for separate argument formats, an output test line
140 relates to all argument formats that can represent the values.
141 MAX_EXP is the maximum exponent of a nonzero bit in any argument,
142 or 0 if all arguments are zero; NUM_ONES is the maximum number of
143 leading bits with value 1 in an argument with exponent MAX_EXP, or
144 0 if all arguments are zero; MIN_EXP is the minimum exponent of a
145 nonzero bit in any argument, or 0 if all arguments are zero;
146 MAX_PREC is the maximum precision required to represent all
147 arguments, or 0 if all arguments are zero. */
ffb536d0
JM
148
149#define _GNU_SOURCE
150
151#include <assert.h>
152#include <ctype.h>
153#include <errno.h>
154#include <error.h>
155#include <stdbool.h>
156#include <stdint.h>
157#include <stdio.h>
158#include <stdlib.h>
159#include <string.h>
160
161#include <gmp.h>
162#include <mpfr.h>
163#include <mpc.h>
164
165#define ARRAY_SIZE(A) (sizeof (A) / sizeof ((A)[0]))
166
167/* The supported floating-point formats. */
168typedef enum
169 {
170 fp_flt_32,
171 fp_dbl_64,
172 fp_ldbl_96_intel,
173 fp_ldbl_96_m68k,
174 fp_ldbl_128,
175 fp_ldbl_128ibm,
176 fp_num_formats,
177 fp_first_format = 0
178 } fp_format;
179
180/* Structure describing a single floating-point format. */
181typedef struct
182{
183 /* The name of the format. */
184 const char *name;
ffb536d0
JM
185 /* A string for the largest normal value, or NULL for IEEE formats
186 where this can be determined automatically. */
187 const char *max_string;
188 /* The number of mantissa bits. */
189 int mant_dig;
190 /* The least N such that 2^N overflows. */
191 int max_exp;
192 /* One more than the least N such that 2^N is normal. */
193 int min_exp;
194 /* The largest normal value. */
195 mpfr_t max;
046651c1
JM
196 /* The value 0.5ulp above the least positive normal value. */
197 mpfr_t min_plus_half;
ffb536d0
JM
198 /* The least positive normal value, 2^(MIN_EXP-1). */
199 mpfr_t min;
200 /* The greatest positive subnormal value. */
201 mpfr_t subnorm_max;
202 /* The least positive subnormal value, 2^(MIN_EXP-MANT_DIG). */
203 mpfr_t subnorm_min;
204} fp_format_desc;
205
206/* List of floating-point formats, in the same order as the fp_format
207 enumeration. */
208static fp_format_desc fp_formats[fp_num_formats] =
209 {
5188b973
PM
210 { "binary32", NULL, 24, 128, -125, {}, {}, {}, {}, {} },
211 { "binary64", NULL, 53, 1024, -1021, {}, {}, {}, {}, {} },
212 { "intel96", NULL, 64, 16384, -16381, {}, {}, {}, {}, {} },
213 { "m68k96", NULL, 64, 16384, -16382, {}, {}, {}, {}, {} },
214 { "binary128", NULL, 113, 16384, -16381, {}, {}, {}, {}, {} },
215 { "ibm128", "0x1.fffffffffffff7ffffffffffff8p+1023",
046651c1 216 106, 1024, -968, {}, {}, {}, {}, {} },
ffb536d0
JM
217 };
218
219/* The supported rounding modes. */
220typedef enum
221 {
222 rm_downward,
223 rm_tonearest,
224 rm_towardzero,
225 rm_upward,
226 rm_num_modes,
227 rm_first_mode = 0
228 } rounding_mode;
229
230/* Structure describing a single rounding mode. */
231typedef struct
232{
233 /* The name of the rounding mode. */
234 const char *name;
235 /* The MPFR rounding mode. */
236 mpfr_rnd_t mpfr_mode;
c6af2d89
JM
237 /* The MPC rounding mode. */
238 mpc_rnd_t mpc_mode;
ffb536d0
JM
239} rounding_mode_desc;
240
241/* List of rounding modes, in the same order as the rounding_mode
242 enumeration. */
243static const rounding_mode_desc rounding_modes[rm_num_modes] =
244 {
c6af2d89
JM
245 { "downward", MPFR_RNDD, MPC_RNDDD },
246 { "tonearest", MPFR_RNDN, MPC_RNDNN },
247 { "towardzero", MPFR_RNDZ, MPC_RNDZZ },
248 { "upward", MPFR_RNDU, MPC_RNDUU },
ffb536d0
JM
249 };
250
251/* The supported exceptions. */
252typedef enum
253 {
254 exc_divbyzero,
255 exc_inexact,
256 exc_invalid,
257 exc_overflow,
258 exc_underflow,
259 exc_num_exceptions,
260 exc_first_exception = 0
261 } fp_exception;
262
263/* List of exceptions, in the same order as the fp_exception
264 enumeration. */
265static const char *const exceptions[exc_num_exceptions] =
266 {
267 "divbyzero",
268 "inexact",
269 "invalid",
270 "overflow",
271 "underflow",
272 };
273
274/* The internal precision to use for most MPFR calculations, which
275 must be at least 2 more than the greatest precision of any
276 supported floating-point format. */
277static int internal_precision;
278
279/* A value that overflows all supported floating-point formats. */
280static mpfr_t global_max;
281
282/* A value that is at most half the least subnormal in any
283 floating-point format and so is rounded the same way as all
284 sufficiently small positive values. */
285static mpfr_t global_min;
286
287/* The maximum number of (real or integer) arguments to a function
288 handled by this program (complex arguments count as two real
289 arguments). */
290#define MAX_NARGS 4
291
292/* The maximum number of (real or integer) return values from a
293 function handled by this program. */
294#define MAX_NRET 2
295
296/* A type of a function argument or return value. */
297typedef enum
298 {
299 /* No type (not a valid argument or return value). */
300 type_none,
301 /* A floating-point value with the type corresponding to that of
302 the function. */
303 type_fp,
304 /* An integer value of type int. */
305 type_int,
306 /* An integer value of type long. */
307 type_long,
308 /* An integer value of type long long. */
309 type_long_long,
310 } arg_ret_type;
311
312/* A type of a generic real or integer value. */
313typedef enum
314 {
315 /* No type. */
316 gtype_none,
317 /* Floating-point (represented with MPFR). */
318 gtype_fp,
319 /* Integer (represented with GMP). */
320 gtype_int,
321 } generic_value_type;
322
323/* A generic value (argument or result). */
324typedef struct
325{
326 /* The type of this value. */
327 generic_value_type type;
328 /* Its value. */
329 union
330 {
331 mpfr_t f;
332 mpz_t i;
333 } value;
334} generic_value;
335
336/* A type of input flag. */
337typedef enum
338 {
863893ec 339 flag_ignore_zero_inf_sign,
ffb536d0 340 flag_xfail,
d8e2dbe3 341 flag_xfail_rounding,
ffb536d0
JM
342 /* The "spurious" and "missing" flags must be in the same order as
343 the fp_exception enumeration. */
344 flag_spurious_divbyzero,
345 flag_spurious_inexact,
346 flag_spurious_invalid,
347 flag_spurious_overflow,
348 flag_spurious_underflow,
349 flag_spurious_errno,
350 flag_missing_divbyzero,
351 flag_missing_inexact,
352 flag_missing_invalid,
353 flag_missing_overflow,
354 flag_missing_underflow,
355 flag_missing_errno,
5bc9b3a1 356 flag_no_mathvec,
ffb536d0
JM
357 num_input_flag_types,
358 flag_first_flag = 0,
359 flag_spurious_first = flag_spurious_divbyzero,
360 flag_missing_first = flag_missing_divbyzero
361 } input_flag_type;
362
363/* List of flags, in the same order as the input_flag_type
364 enumeration. */
365static const char *const input_flags[num_input_flag_types] =
366 {
863893ec 367 "ignore-zero-inf-sign",
ffb536d0 368 "xfail",
d8e2dbe3 369 "xfail-rounding",
ffb536d0
JM
370 "spurious-divbyzero",
371 "spurious-inexact",
372 "spurious-invalid",
373 "spurious-overflow",
374 "spurious-underflow",
375 "spurious-errno",
376 "missing-divbyzero",
377 "missing-inexact",
378 "missing-invalid",
379 "missing-overflow",
380 "missing-underflow",
381 "missing-errno",
5bc9b3a1 382 "no-mathvec",
ffb536d0
JM
383 };
384
385/* An input flag, possibly conditional. */
386typedef struct
387{
388 /* The type of this flag. */
389 input_flag_type type;
390 /* The conditions on this flag, as a string ":cond1:cond2..." or
391 NULL. */
392 const char *cond;
393} input_flag;
394
395/* Structure describing a single test from the input file (which may
396 expand into many tests in the output). The choice of function,
397 which implies the numbers and types of arguments and results, is
398 implicit rather than stored in this structure (except as part of
399 the source line). */
400typedef struct
401{
402 /* The text of the input line describing the test, including the
403 trailing newline. */
404 const char *line;
405 /* The number of combinations of interpretations of input values for
406 different floating-point formats and rounding modes. */
407 size_t num_input_cases;
408 /* The corresponding lists of inputs. */
409 generic_value **inputs;
410 /* The number of flags for this test. */
411 size_t num_flags;
412 /* The corresponding list of flags. */
413 input_flag *flags;
414 /* The old output for this test. */
415 const char *old_output;
416} input_test;
417
418/* Ways to calculate a function. */
419typedef enum
420 {
421 /* MPFR function with a single argument and result. */
422 mpfr_f_f,
ff362e5b
JM
423 /* MPFR function with two arguments and one result. */
424 mpfr_ff_f,
c6af2d89
JM
425 /* MPFR function with three arguments and one result. */
426 mpfr_fff_f,
9f0be4f8
JM
427 /* MPFR function with a single argument and floating-point and
428 integer results. */
429 mpfr_f_f1,
f889953b
JM
430 /* MPFR function with integer and floating-point arguments and one
431 result. */
432 mpfr_if_f,
6f6fc482
JM
433 /* MPFR function with a single argument and two floating-point
434 results. */
435 mpfr_f_11,
64a17f1a
JM
436 /* MPC function with a single complex argument and one real
437 result. */
438 mpc_c_f,
7fda5682
JM
439 /* MPC function with a single complex argument and one complex
440 result. */
441 mpc_c_c,
b7867a3b
JM
442 /* MPC function with two complex arguments and one complex
443 result. */
444 mpc_cc_c,
ffb536d0
JM
445 } func_calc_method;
446
447/* Description of how to calculate a function. */
448typedef struct
449{
450 /* Which method is used to calculate the function. */
451 func_calc_method method;
452 /* The specific function called. */
453 union
454 {
455 int (*mpfr_f_f) (mpfr_t, const mpfr_t, mpfr_rnd_t);
ff362e5b 456 int (*mpfr_ff_f) (mpfr_t, const mpfr_t, const mpfr_t, mpfr_rnd_t);
c6af2d89
JM
457 int (*mpfr_fff_f) (mpfr_t, const mpfr_t, const mpfr_t, const mpfr_t,
458 mpfr_rnd_t);
9f0be4f8 459 int (*mpfr_f_f1) (mpfr_t, int *, const mpfr_t, mpfr_rnd_t);
f889953b 460 int (*mpfr_if_f) (mpfr_t, long, const mpfr_t, mpfr_rnd_t);
6f6fc482 461 int (*mpfr_f_11) (mpfr_t, mpfr_t, const mpfr_t, mpfr_rnd_t);
64a17f1a 462 int (*mpc_c_f) (mpfr_t, const mpc_t, mpfr_rnd_t);
7fda5682 463 int (*mpc_c_c) (mpc_t, const mpc_t, mpc_rnd_t);
b7867a3b 464 int (*mpc_cc_c) (mpc_t, const mpc_t, const mpc_t, mpc_rnd_t);
ffb536d0
JM
465 } func;
466} func_calc_desc;
467
468/* Structure describing a function handled by this program. */
469typedef struct
470{
471 /* The name of the function. */
472 const char *name;
473 /* The number of arguments. */
474 size_t num_args;
475 /* The types of the arguments. */
476 arg_ret_type arg_types[MAX_NARGS];
477 /* The number of return values. */
478 size_t num_ret;
479 /* The types of the return values. */
480 arg_ret_type ret_types[MAX_NRET];
481 /* Whether the function has exactly determined results and
482 exceptions. */
483 bool exact;
484 /* Whether the function is a complex function, so errno setting is
485 optional. */
486 bool complex_fn;
c6af2d89
JM
487 /* Whether to treat arguments given as floating-point constants as
488 exact only, rather than rounding them up and down to all
489 formats. */
490 bool exact_args;
ffb536d0
JM
491 /* How to calculate this function. */
492 func_calc_desc calc;
493 /* The number of tests allocated for this function. */
494 size_t num_tests_alloc;
495 /* The number of tests for this function. */
496 size_t num_tests;
497 /* The tests themselves. */
498 input_test *tests;
499} test_function;
500
9f0be4f8
JM
501#define ARGS1(T1) 1, { T1 }
502#define ARGS2(T1, T2) 2, { T1, T2 }
503#define ARGS3(T1, T2, T3) 3, { T1, T2, T3 }
504#define ARGS4(T1, T2, T3, T4) 4, { T1, T2, T3, T4 }
505#define RET1(T1) 1, { T1 }
506#define RET2(T1, T2) 2, { T1, T2 }
507#define CALC(TYPE, FN) { TYPE, { .TYPE = FN } }
c6af2d89
JM
508#define FUNC(NAME, ARGS, RET, EXACT, COMPLEX_FN, EXACT_ARGS, CALC) \
509 { \
510 NAME, ARGS, RET, EXACT, COMPLEX_FN, EXACT_ARGS, CALC, 0, 0, NULL \
ffb536d0
JM
511 }
512
c6af2d89
JM
513#define FUNC_mpfr_f_f(NAME, MPFR_FUNC, EXACT) \
514 FUNC (NAME, ARGS1 (type_fp), RET1 (type_fp), EXACT, false, false, \
9f0be4f8 515 CALC (mpfr_f_f, MPFR_FUNC))
ff362e5b
JM
516#define FUNC_mpfr_ff_f(NAME, MPFR_FUNC, EXACT) \
517 FUNC (NAME, ARGS2 (type_fp, type_fp), RET1 (type_fp), EXACT, false, \
c6af2d89 518 false, CALC (mpfr_ff_f, MPFR_FUNC))
f889953b
JM
519#define FUNC_mpfr_if_f(NAME, MPFR_FUNC, EXACT) \
520 FUNC (NAME, ARGS2 (type_int, type_fp), RET1 (type_fp), EXACT, false, \
c6af2d89 521 false, CALC (mpfr_if_f, MPFR_FUNC))
64a17f1a
JM
522#define FUNC_mpc_c_f(NAME, MPFR_FUNC, EXACT) \
523 FUNC (NAME, ARGS2 (type_fp, type_fp), RET1 (type_fp), EXACT, true, \
c6af2d89 524 false, CALC (mpc_c_f, MPFR_FUNC))
7fda5682
JM
525#define FUNC_mpc_c_c(NAME, MPFR_FUNC, EXACT) \
526 FUNC (NAME, ARGS2 (type_fp, type_fp), RET2 (type_fp, type_fp), EXACT, \
c6af2d89 527 true, false, CALC (mpc_c_c, MPFR_FUNC))
9f0be4f8 528
ffb536d0
JM
529/* List of functions handled by this program. */
530static test_function test_functions[] =
531 {
176b0c79
JM
532 FUNC_mpfr_f_f ("acos", mpfr_acos, false),
533 FUNC_mpfr_f_f ("acosh", mpfr_acosh, false),
d8742dd8 534 FUNC_mpfr_ff_f ("add", mpfr_add, true),
176b0c79
JM
535 FUNC_mpfr_f_f ("asin", mpfr_asin, false),
536 FUNC_mpfr_f_f ("asinh", mpfr_asinh, false),
537 FUNC_mpfr_f_f ("atan", mpfr_atan, false),
ff362e5b 538 FUNC_mpfr_ff_f ("atan2", mpfr_atan2, false),
176b0c79 539 FUNC_mpfr_f_f ("atanh", mpfr_atanh, false),
64a17f1a 540 FUNC_mpc_c_f ("cabs", mpc_abs, false),
7fda5682
JM
541 FUNC_mpc_c_c ("cacos", mpc_acos, false),
542 FUNC_mpc_c_c ("cacosh", mpc_acosh, false),
64a17f1a 543 FUNC_mpc_c_f ("carg", mpc_arg, false),
7fda5682
JM
544 FUNC_mpc_c_c ("casin", mpc_asin, false),
545 FUNC_mpc_c_c ("casinh", mpc_asinh, false),
546 FUNC_mpc_c_c ("catan", mpc_atan, false),
547 FUNC_mpc_c_c ("catanh", mpc_atanh, false),
176b0c79 548 FUNC_mpfr_f_f ("cbrt", mpfr_cbrt, false),
7fda5682
JM
549 FUNC_mpc_c_c ("ccos", mpc_cos, false),
550 FUNC_mpc_c_c ("ccosh", mpc_cosh, false),
551 FUNC_mpc_c_c ("cexp", mpc_exp, false),
552 FUNC_mpc_c_c ("clog", mpc_log, false),
553 FUNC_mpc_c_c ("clog10", mpc_log10, false),
176b0c79
JM
554 FUNC_mpfr_f_f ("cos", mpfr_cos, false),
555 FUNC_mpfr_f_f ("cosh", mpfr_cosh, false),
b7867a3b 556 FUNC ("cpow", ARGS4 (type_fp, type_fp, type_fp, type_fp),
c6af2d89
JM
557 RET2 (type_fp, type_fp), false, true, false,
558 CALC (mpc_cc_c, mpc_pow)),
7fda5682
JM
559 FUNC_mpc_c_c ("csin", mpc_sin, false),
560 FUNC_mpc_c_c ("csinh", mpc_sinh, false),
561 FUNC_mpc_c_c ("csqrt", mpc_sqrt, false),
562 FUNC_mpc_c_c ("ctan", mpc_tan, false),
563 FUNC_mpc_c_c ("ctanh", mpc_tanh, false),
632a6cbe 564 FUNC_mpfr_ff_f ("div", mpfr_div, true),
176b0c79
JM
565 FUNC_mpfr_f_f ("erf", mpfr_erf, false),
566 FUNC_mpfr_f_f ("erfc", mpfr_erfc, false),
567 FUNC_mpfr_f_f ("exp", mpfr_exp, false),
568 FUNC_mpfr_f_f ("exp10", mpfr_exp10, false),
7ec903e0 569 FUNC_mpfr_f_f ("exp10m1", mpfr_exp10m1, false),
176b0c79 570 FUNC_mpfr_f_f ("exp2", mpfr_exp2, false),
7ec903e0 571 FUNC_mpfr_f_f ("exp2m1", mpfr_exp2m1, false),
176b0c79 572 FUNC_mpfr_f_f ("expm1", mpfr_expm1, false),
c6af2d89
JM
573 FUNC ("fma", ARGS3 (type_fp, type_fp, type_fp), RET1 (type_fp),
574 true, false, true, CALC (mpfr_fff_f, mpfr_fma)),
ff362e5b 575 FUNC_mpfr_ff_f ("hypot", mpfr_hypot, false),
176b0c79
JM
576 FUNC_mpfr_f_f ("j0", mpfr_j0, false),
577 FUNC_mpfr_f_f ("j1", mpfr_j1, false),
f889953b 578 FUNC_mpfr_if_f ("jn", mpfr_jn, false),
9f0be4f8 579 FUNC ("lgamma", ARGS1 (type_fp), RET2 (type_fp, type_int), false, false,
c6af2d89 580 false, CALC (mpfr_f_f1, mpfr_lgamma)),
176b0c79
JM
581 FUNC_mpfr_f_f ("log", mpfr_log, false),
582 FUNC_mpfr_f_f ("log10", mpfr_log10, false),
55eb99e9 583 FUNC_mpfr_f_f ("log10p1", mpfr_log10p1, false),
176b0c79
JM
584 FUNC_mpfr_f_f ("log1p", mpfr_log1p, false),
585 FUNC_mpfr_f_f ("log2", mpfr_log2, false),
79c52daf 586 FUNC_mpfr_f_f ("log2p1", mpfr_log2p1, false),
69a01461 587 FUNC_mpfr_ff_f ("mul", mpfr_mul, true),
ff362e5b 588 FUNC_mpfr_ff_f ("pow", mpfr_pow, false),
176b0c79 589 FUNC_mpfr_f_f ("sin", mpfr_sin, false),
6f6fc482 590 FUNC ("sincos", ARGS1 (type_fp), RET2 (type_fp, type_fp), false, false,
c6af2d89 591 false, CALC (mpfr_f_11, mpfr_sin_cos)),
176b0c79 592 FUNC_mpfr_f_f ("sinh", mpfr_sinh, false),
8d3f9e85 593 FUNC_mpfr_ff_f ("sub", mpfr_sub, true),
ffb536d0 594 FUNC_mpfr_f_f ("sqrt", mpfr_sqrt, true),
176b0c79
JM
595 FUNC_mpfr_f_f ("tan", mpfr_tan, false),
596 FUNC_mpfr_f_f ("tanh", mpfr_tanh, false),
597 FUNC_mpfr_f_f ("tgamma", mpfr_gamma, false),
598 FUNC_mpfr_f_f ("y0", mpfr_y0, false),
599 FUNC_mpfr_f_f ("y1", mpfr_y1, false),
f889953b 600 FUNC_mpfr_if_f ("yn", mpfr_yn, false),
ffb536d0
JM
601 };
602
603/* Allocate memory, with error checking. */
604
605static void *
606xmalloc (size_t n)
607{
608 void *p = malloc (n);
609 if (p == NULL)
610 error (EXIT_FAILURE, errno, "xmalloc failed");
611 return p;
612}
613
614static void *
615xrealloc (void *p, size_t n)
616{
617 p = realloc (p, n);
618 if (p == NULL)
619 error (EXIT_FAILURE, errno, "xrealloc failed");
620 return p;
621}
622
623static char *
624xstrdup (const char *s)
625{
626 char *p = strdup (s);
627 if (p == NULL)
628 error (EXIT_FAILURE, errno, "xstrdup failed");
629 return p;
630}
631
632/* Assert that the result of an MPFR operation was exact; that is,
633 that the returned ternary value was 0. */
634
635static void
636assert_exact (int i)
637{
638 assert (i == 0);
639}
640
641/* Return the generic type of an argument or return value type T. */
642
643static generic_value_type
644generic_arg_ret_type (arg_ret_type t)
645{
646 switch (t)
647 {
648 case type_fp:
649 return gtype_fp;
650
651 case type_int:
652 case type_long:
653 case type_long_long:
654 return gtype_int;
655
656 default:
657 abort ();
658 }
659}
660
661/* Free a generic_value *V. */
662
663static void
664generic_value_free (generic_value *v)
665{
666 switch (v->type)
667 {
668 case gtype_fp:
669 mpfr_clear (v->value.f);
670 break;
671
672 case gtype_int:
673 mpz_clear (v->value.i);
674 break;
675
676 default:
677 abort ();
678 }
679}
680
681/* Copy a generic_value *SRC to *DEST. */
682
683static void
684generic_value_copy (generic_value *dest, const generic_value *src)
685{
686 dest->type = src->type;
687 switch (src->type)
688 {
689 case gtype_fp:
690 mpfr_init (dest->value.f);
691 assert_exact (mpfr_set (dest->value.f, src->value.f, MPFR_RNDN));
692 break;
693
694 case gtype_int:
695 mpz_init (dest->value.i);
696 mpz_set (dest->value.i, src->value.i);
697 break;
698
699 default:
700 abort ();
701 }
702}
703
704/* Initialize data for floating-point formats. */
705
706static void
9dd346ff 707init_fp_formats (void)
ffb536d0
JM
708{
709 int global_max_exp = 0, global_min_subnorm_exp = 0;
710 for (fp_format f = fp_first_format; f < fp_num_formats; f++)
711 {
712 if (fp_formats[f].mant_dig + 2 > internal_precision)
713 internal_precision = fp_formats[f].mant_dig + 2;
714 if (fp_formats[f].max_exp > global_max_exp)
715 global_max_exp = fp_formats[f].max_exp;
716 int min_subnorm_exp = fp_formats[f].min_exp - fp_formats[f].mant_dig;
717 if (min_subnorm_exp < global_min_subnorm_exp)
718 global_min_subnorm_exp = min_subnorm_exp;
719 mpfr_init2 (fp_formats[f].max, fp_formats[f].mant_dig);
720 if (fp_formats[f].max_string != NULL)
721 {
722 char *ep = NULL;
723 assert_exact (mpfr_strtofr (fp_formats[f].max,
724 fp_formats[f].max_string,
725 &ep, 0, MPFR_RNDN));
726 assert (*ep == 0);
727 }
728 else
729 {
730 assert_exact (mpfr_set_ui_2exp (fp_formats[f].max, 1,
731 fp_formats[f].max_exp,
732 MPFR_RNDN));
733 mpfr_nextbelow (fp_formats[f].max);
734 }
735 mpfr_init2 (fp_formats[f].min, fp_formats[f].mant_dig);
736 assert_exact (mpfr_set_ui_2exp (fp_formats[f].min, 1,
737 fp_formats[f].min_exp - 1,
738 MPFR_RNDN));
046651c1
JM
739 mpfr_init2 (fp_formats[f].min_plus_half, fp_formats[f].mant_dig + 1);
740 assert_exact (mpfr_set (fp_formats[f].min_plus_half,
741 fp_formats[f].min, MPFR_RNDN));
742 mpfr_nextabove (fp_formats[f].min_plus_half);
ffb536d0
JM
743 mpfr_init2 (fp_formats[f].subnorm_max, fp_formats[f].mant_dig);
744 assert_exact (mpfr_set (fp_formats[f].subnorm_max, fp_formats[f].min,
745 MPFR_RNDN));
746 mpfr_nextbelow (fp_formats[f].subnorm_max);
747 mpfr_nextbelow (fp_formats[f].subnorm_max);
748 mpfr_init2 (fp_formats[f].subnorm_min, fp_formats[f].mant_dig);
749 assert_exact (mpfr_set_ui_2exp (fp_formats[f].subnorm_min, 1,
750 min_subnorm_exp, MPFR_RNDN));
751 }
752 mpfr_set_default_prec (internal_precision);
753 mpfr_init (global_max);
754 assert_exact (mpfr_set_ui_2exp (global_max, 1, global_max_exp, MPFR_RNDN));
755 mpfr_init (global_min);
756 assert_exact (mpfr_set_ui_2exp (global_min, 1, global_min_subnorm_exp - 1,
757 MPFR_RNDN));
758}
759
760/* Fill in mpfr_t values for special strings in input arguments. */
761
762static size_t
763special_fill_max (mpfr_t res0, mpfr_t res1 __attribute__ ((unused)),
764 fp_format format)
765{
766 mpfr_init2 (res0, fp_formats[format].mant_dig);
767 assert_exact (mpfr_set (res0, fp_formats[format].max, MPFR_RNDN));
768 return 1;
769}
770
771static size_t
772special_fill_minus_max (mpfr_t res0, mpfr_t res1 __attribute__ ((unused)),
773 fp_format format)
774{
775 mpfr_init2 (res0, fp_formats[format].mant_dig);
776 assert_exact (mpfr_neg (res0, fp_formats[format].max, MPFR_RNDN));
777 return 1;
778}
779
ff362e5b
JM
780static size_t
781special_fill_min (mpfr_t res0, mpfr_t res1 __attribute__ ((unused)),
782 fp_format format)
783{
784 mpfr_init2 (res0, fp_formats[format].mant_dig);
785 assert_exact (mpfr_set (res0, fp_formats[format].min, MPFR_RNDN));
786 return 1;
787}
788
789static size_t
790special_fill_minus_min (mpfr_t res0, mpfr_t res1 __attribute__ ((unused)),
791 fp_format format)
792{
793 mpfr_init2 (res0, fp_formats[format].mant_dig);
794 assert_exact (mpfr_neg (res0, fp_formats[format].min, MPFR_RNDN));
795 return 1;
796}
797
798static size_t
799special_fill_min_subnorm (mpfr_t res0, mpfr_t res1 __attribute__ ((unused)),
800 fp_format format)
801{
802 mpfr_init2 (res0, fp_formats[format].mant_dig);
803 assert_exact (mpfr_set (res0, fp_formats[format].subnorm_min, MPFR_RNDN));
804 return 1;
805}
806
807static size_t
808special_fill_minus_min_subnorm (mpfr_t res0,
809 mpfr_t res1 __attribute__ ((unused)),
810 fp_format format)
811{
812 mpfr_init2 (res0, fp_formats[format].mant_dig);
813 assert_exact (mpfr_neg (res0, fp_formats[format].subnorm_min, MPFR_RNDN));
814 return 1;
815}
816
7fda5682
JM
817static size_t
818special_fill_min_subnorm_p120 (mpfr_t res0,
819 mpfr_t res1 __attribute__ ((unused)),
820 fp_format format)
821{
822 mpfr_init2 (res0, fp_formats[format].mant_dig);
823 assert_exact (mpfr_mul_2ui (res0, fp_formats[format].subnorm_min,
824 120, MPFR_RNDN));
825 return 1;
826}
827
ffb536d0
JM
828static size_t
829special_fill_pi (mpfr_t res0, mpfr_t res1, fp_format format)
830{
831 mpfr_init2 (res0, fp_formats[format].mant_dig);
832 mpfr_const_pi (res0, MPFR_RNDU);
833 mpfr_init2 (res1, fp_formats[format].mant_dig);
834 mpfr_const_pi (res1, MPFR_RNDD);
835 return 2;
836}
837
838static size_t
839special_fill_minus_pi (mpfr_t res0, mpfr_t res1, fp_format format)
840{
841 mpfr_init2 (res0, fp_formats[format].mant_dig);
842 mpfr_const_pi (res0, MPFR_RNDU);
843 assert_exact (mpfr_neg (res0, res0, MPFR_RNDN));
844 mpfr_init2 (res1, fp_formats[format].mant_dig);
845 mpfr_const_pi (res1, MPFR_RNDD);
846 assert_exact (mpfr_neg (res1, res1, MPFR_RNDN));
847 return 2;
848}
849
176b0c79
JM
850static size_t
851special_fill_pi_2 (mpfr_t res0, mpfr_t res1, fp_format format)
852{
853 mpfr_init2 (res0, fp_formats[format].mant_dig);
854 mpfr_const_pi (res0, MPFR_RNDU);
855 assert_exact (mpfr_div_ui (res0, res0, 2, MPFR_RNDN));
856 mpfr_init2 (res1, fp_formats[format].mant_dig);
857 mpfr_const_pi (res1, MPFR_RNDD);
858 assert_exact (mpfr_div_ui (res1, res1, 2, MPFR_RNDN));
859 return 2;
860}
861
862static size_t
863special_fill_minus_pi_2 (mpfr_t res0, mpfr_t res1, fp_format format)
864{
865 mpfr_init2 (res0, fp_formats[format].mant_dig);
866 mpfr_const_pi (res0, MPFR_RNDU);
867 assert_exact (mpfr_div_ui (res0, res0, 2, MPFR_RNDN));
868 assert_exact (mpfr_neg (res0, res0, MPFR_RNDN));
869 mpfr_init2 (res1, fp_formats[format].mant_dig);
870 mpfr_const_pi (res1, MPFR_RNDD);
871 assert_exact (mpfr_div_ui (res1, res1, 2, MPFR_RNDN));
872 assert_exact (mpfr_neg (res1, res1, MPFR_RNDN));
873 return 2;
874}
875
bbf37bdc
JM
876static size_t
877special_fill_pi_4 (mpfr_t res0, mpfr_t res1, fp_format format)
878{
879 mpfr_init2 (res0, fp_formats[format].mant_dig);
880 assert_exact (mpfr_set_si (res0, 1, MPFR_RNDN));
881 mpfr_atan (res0, res0, MPFR_RNDU);
882 mpfr_init2 (res1, fp_formats[format].mant_dig);
883 assert_exact (mpfr_set_si (res1, 1, MPFR_RNDN));
884 mpfr_atan (res1, res1, MPFR_RNDD);
885 return 2;
886}
887
176b0c79
JM
888static size_t
889special_fill_pi_6 (mpfr_t res0, mpfr_t res1, fp_format format)
890{
891 mpfr_init2 (res0, fp_formats[format].mant_dig);
892 assert_exact (mpfr_set_si_2exp (res0, 1, -1, MPFR_RNDN));
893 mpfr_asin (res0, res0, MPFR_RNDU);
894 mpfr_init2 (res1, fp_formats[format].mant_dig);
895 assert_exact (mpfr_set_si_2exp (res1, 1, -1, MPFR_RNDN));
896 mpfr_asin (res1, res1, MPFR_RNDD);
897 return 2;
898}
899
900static size_t
901special_fill_minus_pi_6 (mpfr_t res0, mpfr_t res1, fp_format format)
902{
903 mpfr_init2 (res0, fp_formats[format].mant_dig);
904 assert_exact (mpfr_set_si_2exp (res0, -1, -1, MPFR_RNDN));
905 mpfr_asin (res0, res0, MPFR_RNDU);
906 mpfr_init2 (res1, fp_formats[format].mant_dig);
907 assert_exact (mpfr_set_si_2exp (res1, -1, -1, MPFR_RNDN));
908 mpfr_asin (res1, res1, MPFR_RNDD);
909 return 2;
910}
911
912static size_t
913special_fill_pi_3 (mpfr_t res0, mpfr_t res1, fp_format format)
914{
915 mpfr_init2 (res0, fp_formats[format].mant_dig);
916 assert_exact (mpfr_set_si_2exp (res0, 1, -1, MPFR_RNDN));
917 mpfr_acos (res0, res0, MPFR_RNDU);
918 mpfr_init2 (res1, fp_formats[format].mant_dig);
919 assert_exact (mpfr_set_si_2exp (res1, 1, -1, MPFR_RNDN));
920 mpfr_acos (res1, res1, MPFR_RNDD);
921 return 2;
922}
923
924static size_t
925special_fill_2pi_3 (mpfr_t res0, mpfr_t res1, fp_format format)
926{
927 mpfr_init2 (res0, fp_formats[format].mant_dig);
928 assert_exact (mpfr_set_si_2exp (res0, -1, -1, MPFR_RNDN));
929 mpfr_acos (res0, res0, MPFR_RNDU);
930 mpfr_init2 (res1, fp_formats[format].mant_dig);
931 assert_exact (mpfr_set_si_2exp (res1, -1, -1, MPFR_RNDN));
932 mpfr_acos (res1, res1, MPFR_RNDD);
933 return 2;
934}
935
b7867a3b
JM
936static size_t
937special_fill_2pi (mpfr_t res0, mpfr_t res1, fp_format format)
938{
939 mpfr_init2 (res0, fp_formats[format].mant_dig);
940 mpfr_const_pi (res0, MPFR_RNDU);
941 assert_exact (mpfr_mul_ui (res0, res0, 2, MPFR_RNDN));
942 mpfr_init2 (res1, fp_formats[format].mant_dig);
943 mpfr_const_pi (res1, MPFR_RNDD);
944 assert_exact (mpfr_mul_ui (res1, res1, 2, MPFR_RNDN));
945 return 2;
946}
947
176b0c79
JM
948static size_t
949special_fill_e (mpfr_t res0, mpfr_t res1, fp_format format)
950{
951 mpfr_init2 (res0, fp_formats[format].mant_dig);
952 assert_exact (mpfr_set_si (res0, 1, MPFR_RNDN));
953 mpfr_exp (res0, res0, MPFR_RNDU);
954 mpfr_init2 (res1, fp_formats[format].mant_dig);
955 assert_exact (mpfr_set_si (res1, 1, MPFR_RNDN));
956 mpfr_exp (res1, res1, MPFR_RNDD);
957 return 2;
958}
959
960static size_t
961special_fill_1_e (mpfr_t res0, mpfr_t res1, fp_format format)
962{
963 mpfr_init2 (res0, fp_formats[format].mant_dig);
964 assert_exact (mpfr_set_si (res0, -1, MPFR_RNDN));
965 mpfr_exp (res0, res0, MPFR_RNDU);
966 mpfr_init2 (res1, fp_formats[format].mant_dig);
967 assert_exact (mpfr_set_si (res1, -1, MPFR_RNDN));
968 mpfr_exp (res1, res1, MPFR_RNDD);
969 return 2;
970}
971
972static size_t
973special_fill_e_minus_1 (mpfr_t res0, mpfr_t res1, fp_format format)
974{
975 mpfr_init2 (res0, fp_formats[format].mant_dig);
976 assert_exact (mpfr_set_si (res0, 1, MPFR_RNDN));
977 mpfr_expm1 (res0, res0, MPFR_RNDU);
978 mpfr_init2 (res1, fp_formats[format].mant_dig);
979 assert_exact (mpfr_set_si (res1, 1, MPFR_RNDN));
980 mpfr_expm1 (res1, res1, MPFR_RNDD);
981 return 2;
982}
983
ffb536d0
JM
984/* A special string accepted in input arguments. */
985typedef struct
986{
987 /* The string. */
988 const char *str;
989 /* The function that interprets it for a given floating-point
990 format, filling in up to two mpfr_t values and returning the
991 number of values filled. */
992 size_t (*func) (mpfr_t, mpfr_t, fp_format);
993} special_real_input;
994
995/* List of special strings accepted in input arguments. */
996
997static const special_real_input special_real_inputs[] =
998 {
999 { "max", special_fill_max },
1000 { "-max", special_fill_minus_max },
ff362e5b
JM
1001 { "min", special_fill_min },
1002 { "-min", special_fill_minus_min },
1003 { "min_subnorm", special_fill_min_subnorm },
1004 { "-min_subnorm", special_fill_minus_min_subnorm },
7fda5682 1005 { "min_subnorm_p120", special_fill_min_subnorm_p120 },
ffb536d0
JM
1006 { "pi", special_fill_pi },
1007 { "-pi", special_fill_minus_pi },
176b0c79
JM
1008 { "pi/2", special_fill_pi_2 },
1009 { "-pi/2", special_fill_minus_pi_2 },
bbf37bdc 1010 { "pi/4", special_fill_pi_4 },
176b0c79
JM
1011 { "pi/6", special_fill_pi_6 },
1012 { "-pi/6", special_fill_minus_pi_6 },
1013 { "pi/3", special_fill_pi_3 },
1014 { "2pi/3", special_fill_2pi_3 },
b7867a3b 1015 { "2pi", special_fill_2pi },
176b0c79
JM
1016 { "e", special_fill_e },
1017 { "1/e", special_fill_1_e },
1018 { "e-1", special_fill_e_minus_1 },
ffb536d0
JM
1019 };
1020
1021/* Given a real number R computed in round-to-zero mode, set the
1022 lowest bit as a sticky bit if INEXACT, and saturate the exponent
1023 range for very large or small values. */
1024
1025static void
1026adjust_real (mpfr_t r, bool inexact)
1027{
1028 if (!inexact)
1029 return;
1030 /* NaNs are exact, as are infinities in round-to-zero mode. */
d8e2dbe3 1031 assert (mpfr_number_p (r));
ffb536d0
JM
1032 if (mpfr_cmpabs (r, global_min) < 0)
1033 assert_exact (mpfr_copysign (r, global_min, r, MPFR_RNDN));
1034 else if (mpfr_cmpabs (r, global_max) > 0)
1035 assert_exact (mpfr_copysign (r, global_max, r, MPFR_RNDN));
1036 else
1037 {
1038 mpz_t tmp;
1039 mpz_init (tmp);
1040 mpfr_exp_t e = mpfr_get_z_2exp (tmp, r);
a4fb7861
JM
1041 if (mpz_sgn (tmp) < 0)
1042 {
1043 mpz_neg (tmp, tmp);
1044 mpz_setbit (tmp, 0);
1045 mpz_neg (tmp, tmp);
1046 }
1047 else
1048 mpz_setbit (tmp, 0);
ffb536d0
JM
1049 assert_exact (mpfr_set_z_2exp (r, tmp, e, MPFR_RNDN));
1050 mpz_clear (tmp);
1051 }
1052}
1053
1054/* Given a finite real number R with sticky bit, compute the roundings
1055 to FORMAT in each rounding mode, storing the results in RES, the
1056 before-rounding exceptions in EXC_BEFORE and the after-rounding
1057 exceptions in EXC_AFTER. */
1058
1059static void
1060round_real (mpfr_t res[rm_num_modes],
1061 unsigned int exc_before[rm_num_modes],
1062 unsigned int exc_after[rm_num_modes],
1063 mpfr_t r, fp_format format)
1064{
1065 assert (mpfr_number_p (r));
1066 for (rounding_mode m = rm_first_mode; m < rm_num_modes; m++)
1067 {
1068 mpfr_init2 (res[m], fp_formats[format].mant_dig);
1069 exc_before[m] = exc_after[m] = 0;
1070 bool inexact = mpfr_set (res[m], r, rounding_modes[m].mpfr_mode);
1071 if (mpfr_cmpabs (res[m], fp_formats[format].max) > 0)
1072 {
1073 inexact = true;
1074 exc_before[m] |= 1U << exc_overflow;
1075 exc_after[m] |= 1U << exc_overflow;
1076 bool overflow_inf;
1077 switch (m)
1078 {
1079 case rm_tonearest:
1080 overflow_inf = true;
1081 break;
1082 case rm_towardzero:
1083 overflow_inf = false;
1084 break;
1085 case rm_downward:
1086 overflow_inf = mpfr_signbit (res[m]);
1087 break;
1088 case rm_upward:
1089 overflow_inf = !mpfr_signbit (res[m]);
1090 break;
1091 default:
1092 abort ();
1093 }
1094 if (overflow_inf)
1095 mpfr_set_inf (res[m], mpfr_signbit (res[m]) ? -1 : 1);
1096 else
1097 assert_exact (mpfr_copysign (res[m], fp_formats[format].max,
1098 res[m], MPFR_RNDN));
1099 }
1100 if (mpfr_cmpabs (r, fp_formats[format].min) < 0)
1101 {
1102 /* Tiny before rounding; may or may not be tiny after
1103 rounding, and underflow applies only if also inexact
1104 around rounding to a possibly subnormal value. */
1105 bool tiny_after_rounding
1106 = mpfr_cmpabs (res[m], fp_formats[format].min) < 0;
1107 /* To round to a possibly subnormal value, and determine
1108 inexactness as a subnormal in the process, scale up and
1109 round to integer, then scale back down. */
1110 mpfr_t tmp;
1111 mpfr_init (tmp);
1112 assert_exact (mpfr_mul_2si (tmp, r, (fp_formats[format].mant_dig
1113 - fp_formats[format].min_exp),
1114 MPFR_RNDN));
1115 int rint_res = mpfr_rint (tmp, tmp, rounding_modes[m].mpfr_mode);
1116 /* The integer must be representable. */
1117 assert (rint_res == 0 || rint_res == 2 || rint_res == -2);
1118 /* If rounding to full precision was inexact, so must
1119 rounding to subnormal precision be inexact. */
1120 if (inexact)
1121 assert (rint_res != 0);
1122 else
1123 inexact = rint_res != 0;
1124 assert_exact (mpfr_mul_2si (res[m], tmp,
1125 (fp_formats[format].min_exp
1126 - fp_formats[format].mant_dig),
1127 MPFR_RNDN));
1128 mpfr_clear (tmp);
1129 if (inexact)
1130 {
1131 exc_before[m] |= 1U << exc_underflow;
1132 if (tiny_after_rounding)
1133 exc_after[m] |= 1U << exc_underflow;
1134 }
1135 }
1136 if (inexact)
1137 {
1138 exc_before[m] |= 1U << exc_inexact;
1139 exc_after[m] |= 1U << exc_inexact;
1140 }
1141 }
1142}
1143
1144/* Handle the input argument at ARG (NUL-terminated), updating the
1145 lists of test inputs in IT accordingly. NUM_PREV_ARGS arguments
c6af2d89
JM
1146 are already in those lists. If EXACT_ARGS, interpret a value given
1147 as a floating-point constant exactly (it must be exact for some
1148 supported format) rather than rounding up and down. The argument,
1149 of type GTYPE, comes from file FILENAME, line LINENO. */
ffb536d0
JM
1150
1151static void
1152handle_input_arg (const char *arg, input_test *it, size_t num_prev_args,
c6af2d89 1153 generic_value_type gtype, bool exact_args,
ffb536d0
JM
1154 const char *filename, unsigned int lineno)
1155{
1156 size_t num_values = 0;
1157 generic_value values[2 * fp_num_formats];
c6af2d89 1158 bool check_empty_list = false;
ffb536d0
JM
1159 switch (gtype)
1160 {
1161 case gtype_fp:
1162 for (fp_format f = fp_first_format; f < fp_num_formats; f++)
1163 {
1164 mpfr_t extra_values[2];
1165 size_t num_extra_values = 0;
1166 for (size_t i = 0; i < ARRAY_SIZE (special_real_inputs); i++)
1167 {
1168 if (strcmp (arg, special_real_inputs[i].str) == 0)
1169 {
1170 num_extra_values
1171 = special_real_inputs[i].func (extra_values[0],
1172 extra_values[1], f);
1173 assert (num_extra_values > 0
1174 && num_extra_values <= ARRAY_SIZE (extra_values));
1175 break;
1176 }
1177 }
1178 if (num_extra_values == 0)
1179 {
1180 mpfr_t tmp;
1181 char *ep;
c6af2d89
JM
1182 if (exact_args)
1183 check_empty_list = true;
ffb536d0
JM
1184 mpfr_init (tmp);
1185 bool inexact = mpfr_strtofr (tmp, arg, &ep, 0, MPFR_RNDZ);
1186 if (*ep != 0 || !mpfr_number_p (tmp))
1187 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1188 "bad floating-point argument: '%s'", arg);
1189 adjust_real (tmp, inexact);
1190 mpfr_t rounded[rm_num_modes];
1191 unsigned int exc_before[rm_num_modes];
1192 unsigned int exc_after[rm_num_modes];
1193 round_real (rounded, exc_before, exc_after, tmp, f);
1194 mpfr_clear (tmp);
c6af2d89
JM
1195 if (mpfr_number_p (rounded[rm_upward])
1196 && (!exact_args || mpfr_equal_p (rounded[rm_upward],
1197 rounded[rm_downward])))
ffb536d0
JM
1198 {
1199 mpfr_init2 (extra_values[num_extra_values],
1200 fp_formats[f].mant_dig);
1201 assert_exact (mpfr_set (extra_values[num_extra_values],
1202 rounded[rm_upward], MPFR_RNDN));
1203 num_extra_values++;
1204 }
c6af2d89 1205 if (mpfr_number_p (rounded[rm_downward]) && !exact_args)
ffb536d0
JM
1206 {
1207 mpfr_init2 (extra_values[num_extra_values],
1208 fp_formats[f].mant_dig);
1209 assert_exact (mpfr_set (extra_values[num_extra_values],
1210 rounded[rm_downward], MPFR_RNDN));
1211 num_extra_values++;
1212 }
1213 for (rounding_mode m = rm_first_mode; m < rm_num_modes; m++)
1214 mpfr_clear (rounded[m]);
1215 }
1216 for (size_t i = 0; i < num_extra_values; i++)
1217 {
1218 bool found = false;
1219 for (size_t j = 0; j < num_values; j++)
1220 {
1221 if (mpfr_equal_p (values[j].value.f, extra_values[i])
1222 && ((mpfr_signbit (values[j].value.f) != 0)
1223 == (mpfr_signbit (extra_values[i]) != 0)))
1224 {
1225 found = true;
1226 break;
1227 }
1228 }
1229 if (!found)
1230 {
1231 assert (num_values < ARRAY_SIZE (values));
1232 values[num_values].type = gtype_fp;
1233 mpfr_init2 (values[num_values].value.f,
1234 fp_formats[f].mant_dig);
1235 assert_exact (mpfr_set (values[num_values].value.f,
1236 extra_values[i], MPFR_RNDN));
1237 num_values++;
1238 }
1239 mpfr_clear (extra_values[i]);
1240 }
1241 }
1242 break;
1243
1244 case gtype_int:
1245 num_values = 1;
1246 values[0].type = gtype_int;
1247 int ret = mpz_init_set_str (values[0].value.i, arg, 0);
1248 if (ret != 0)
1249 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1250 "bad integer argument: '%s'", arg);
1251 break;
1252
1253 default:
1254 abort ();
1255 }
c6af2d89
JM
1256 if (check_empty_list && num_values == 0)
1257 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1258 "floating-point argument not exact for any format: '%s'",
1259 arg);
ffb536d0
JM
1260 assert (num_values > 0 && num_values <= ARRAY_SIZE (values));
1261 if (it->num_input_cases >= SIZE_MAX / num_values)
1262 error_at_line (EXIT_FAILURE, 0, filename, lineno, "too many input cases");
1263 generic_value **old_inputs = it->inputs;
1264 size_t new_num_input_cases = it->num_input_cases * num_values;
1265 generic_value **new_inputs = xmalloc (new_num_input_cases
1266 * sizeof (new_inputs[0]));
1267 for (size_t i = 0; i < it->num_input_cases; i++)
1268 {
1269 for (size_t j = 0; j < num_values; j++)
1270 {
1271 size_t idx = i * num_values + j;
1272 new_inputs[idx] = xmalloc ((num_prev_args + 1)
1273 * sizeof (new_inputs[idx][0]));
1274 for (size_t k = 0; k < num_prev_args; k++)
1275 generic_value_copy (&new_inputs[idx][k], &old_inputs[i][k]);
1276 generic_value_copy (&new_inputs[idx][num_prev_args], &values[j]);
1277 }
1278 for (size_t j = 0; j < num_prev_args; j++)
1279 generic_value_free (&old_inputs[i][j]);
1280 free (old_inputs[i]);
1281 }
1282 free (old_inputs);
1283 for (size_t i = 0; i < num_values; i++)
1284 generic_value_free (&values[i]);
1285 it->inputs = new_inputs;
1286 it->num_input_cases = new_num_input_cases;
1287}
1288
1289/* Handle the input flag ARG (NUL-terminated), storing it in *FLAG.
1290 The flag comes from file FILENAME, line LINENO. */
1291
1292static void
1293handle_input_flag (char *arg, input_flag *flag,
1294 const char *filename, unsigned int lineno)
1295{
1296 char *ep = strchr (arg, ':');
1297 if (ep == NULL)
1298 {
1299 ep = strchr (arg, 0);
1300 assert (ep != NULL);
1301 }
1302 char c = *ep;
1303 *ep = 0;
1304 bool found = false;
dae7bf38 1305 for (input_flag_type i = flag_first_flag; i < num_input_flag_types; i++)
ffb536d0
JM
1306 {
1307 if (strcmp (arg, input_flags[i]) == 0)
1308 {
1309 found = true;
1310 flag->type = i;
1311 break;
1312 }
1313 }
1314 if (!found)
1315 error_at_line (EXIT_FAILURE, 0, filename, lineno, "unknown flag: '%s'",
1316 arg);
1317 *ep = c;
1318 if (c == 0)
1319 flag->cond = NULL;
1320 else
1321 flag->cond = xstrdup (ep);
1322}
1323
1324/* Add the test LINE (file FILENAME, line LINENO) to the test
1325 data. */
1326
1327static void
1328add_test (char *line, const char *filename, unsigned int lineno)
1329{
1330 size_t num_tokens = 1;
1331 char *p = line;
1332 while ((p = strchr (p, ' ')) != NULL)
1333 {
1334 num_tokens++;
1335 p++;
1336 }
1337 if (num_tokens < 2)
1338 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1339 "line too short: '%s'", line);
1340 p = strchr (line, ' ');
1341 size_t func_name_len = p - line;
1342 for (size_t i = 0; i < ARRAY_SIZE (test_functions); i++)
1343 {
1344 if (func_name_len == strlen (test_functions[i].name)
1345 && strncmp (line, test_functions[i].name, func_name_len) == 0)
1346 {
1347 test_function *tf = &test_functions[i];
1348 if (num_tokens < 1 + tf->num_args)
1349 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1350 "line too short: '%s'", line);
1351 if (tf->num_tests == tf->num_tests_alloc)
1352 {
1353 tf->num_tests_alloc = 2 * tf->num_tests_alloc + 16;
1354 tf->tests
1355 = xrealloc (tf->tests,
1356 tf->num_tests_alloc * sizeof (tf->tests[0]));
1357 }
1358 input_test *it = &tf->tests[tf->num_tests];
1359 it->line = line;
1360 it->num_input_cases = 1;
1361 it->inputs = xmalloc (sizeof (it->inputs[0]));
1362 it->inputs[0] = NULL;
1363 it->old_output = NULL;
1364 p++;
1365 for (size_t j = 0; j < tf->num_args; j++)
1366 {
1367 char *ep = strchr (p, ' ');
1368 if (ep == NULL)
1369 {
1370 ep = strchr (p, '\n');
1371 assert (ep != NULL);
1372 }
1373 if (ep == p)
1374 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1375 "empty token in line: '%s'", line);
1376 for (char *t = p; t < ep; t++)
1377 if (isspace ((unsigned char) *t))
1378 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1379 "whitespace in token in line: '%s'", line);
1380 char c = *ep;
1381 *ep = 0;
1382 handle_input_arg (p, it, j,
1383 generic_arg_ret_type (tf->arg_types[j]),
c6af2d89 1384 tf->exact_args, filename, lineno);
ffb536d0
JM
1385 *ep = c;
1386 p = ep + 1;
1387 }
1388 it->num_flags = num_tokens - 1 - tf->num_args;
1389 it->flags = xmalloc (it->num_flags * sizeof (it->flags[0]));
1390 for (size_t j = 0; j < it->num_flags; j++)
1391 {
1392 char *ep = strchr (p, ' ');
1393 if (ep == NULL)
1394 {
1395 ep = strchr (p, '\n');
1396 assert (ep != NULL);
1397 }
1398 if (ep == p)
1399 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1400 "empty token in line: '%s'", line);
1401 for (char *t = p; t < ep; t++)
1402 if (isspace ((unsigned char) *t))
1403 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1404 "whitespace in token in line: '%s'", line);
1405 char c = *ep;
1406 *ep = 0;
1407 handle_input_flag (p, &it->flags[j], filename, lineno);
1408 *ep = c;
1409 p = ep + 1;
1410 }
1411 assert (*p == 0);
1412 tf->num_tests++;
1413 return;
1414 }
1415 }
1416 error_at_line (EXIT_FAILURE, 0, filename, lineno,
1417 "unknown function in line: '%s'", line);
1418}
1419
1420/* Read in the test input data from FILENAME. */
1421
1422static void
1423read_input (const char *filename)
1424{
1425 FILE *fp = fopen (filename, "r");
1426 if (fp == NULL)
1427 error (EXIT_FAILURE, errno, "open '%s'", filename);
1428 unsigned int lineno = 0;
1429 for (;;)
1430 {
1431 size_t size = 0;
1432 char *line = NULL;
1433 ssize_t ret = getline (&line, &size, fp);
1434 if (ret == -1)
1435 break;
1436 lineno++;
1437 if (line[0] == '#' || line[0] == '\n')
1438 continue;
1439 add_test (line, filename, lineno);
1440 }
1441 if (ferror (fp))
1442 error (EXIT_FAILURE, errno, "read from '%s'", filename);
1443 if (fclose (fp) != 0)
1444 error (EXIT_FAILURE, errno, "close '%s'", filename);
1445}
1446
1447/* Calculate the generic results (round-to-zero with sticky bit) for
c6af2d89
JM
1448 the function described by CALC, with inputs INPUTS, if MODE is
1449 rm_towardzero; for other modes, calculate results in that mode,
1450 which must be exact zero results. */
ffb536d0
JM
1451
1452static void
1453calc_generic_results (generic_value *outputs, generic_value *inputs,
c6af2d89 1454 const func_calc_desc *calc, rounding_mode mode)
ffb536d0
JM
1455{
1456 bool inexact;
b7867a3b
JM
1457 int mpc_ternary;
1458 mpc_t ci1, ci2, co;
c6af2d89
JM
1459 mpfr_rnd_t mode_mpfr = rounding_modes[mode].mpfr_mode;
1460 mpc_rnd_t mode_mpc = rounding_modes[mode].mpc_mode;
b7867a3b 1461
ffb536d0
JM
1462 switch (calc->method)
1463 {
1464 case mpfr_f_f:
1465 assert (inputs[0].type == gtype_fp);
1466 outputs[0].type = gtype_fp;
1467 mpfr_init (outputs[0].value.f);
1468 inexact = calc->func.mpfr_f_f (outputs[0].value.f, inputs[0].value.f,
c6af2d89
JM
1469 mode_mpfr);
1470 if (mode != rm_towardzero)
1471 assert (!inexact && mpfr_zero_p (outputs[0].value.f));
ffb536d0
JM
1472 adjust_real (outputs[0].value.f, inexact);
1473 break;
1474
ff362e5b
JM
1475 case mpfr_ff_f:
1476 assert (inputs[0].type == gtype_fp);
f889953b 1477 assert (inputs[1].type == gtype_fp);
ff362e5b
JM
1478 outputs[0].type = gtype_fp;
1479 mpfr_init (outputs[0].value.f);
1480 inexact = calc->func.mpfr_ff_f (outputs[0].value.f, inputs[0].value.f,
c6af2d89
JM
1481 inputs[1].value.f, mode_mpfr);
1482 if (mode != rm_towardzero)
1483 assert (!inexact && mpfr_zero_p (outputs[0].value.f));
1484 adjust_real (outputs[0].value.f, inexact);
1485 break;
1486
1487 case mpfr_fff_f:
1488 assert (inputs[0].type == gtype_fp);
1489 assert (inputs[1].type == gtype_fp);
1490 assert (inputs[2].type == gtype_fp);
1491 outputs[0].type = gtype_fp;
1492 mpfr_init (outputs[0].value.f);
1493 inexact = calc->func.mpfr_fff_f (outputs[0].value.f, inputs[0].value.f,
1494 inputs[1].value.f, inputs[2].value.f,
1495 mode_mpfr);
1496 if (mode != rm_towardzero)
1497 assert (!inexact && mpfr_zero_p (outputs[0].value.f));
ff362e5b
JM
1498 adjust_real (outputs[0].value.f, inexact);
1499 break;
1500
9f0be4f8
JM
1501 case mpfr_f_f1:
1502 assert (inputs[0].type == gtype_fp);
1503 outputs[0].type = gtype_fp;
1504 outputs[1].type = gtype_int;
1505 mpfr_init (outputs[0].value.f);
1506 int i = 0;
1507 inexact = calc->func.mpfr_f_f1 (outputs[0].value.f, &i,
c6af2d89
JM
1508 inputs[0].value.f, mode_mpfr);
1509 if (mode != rm_towardzero)
1510 assert (!inexact && mpfr_zero_p (outputs[0].value.f));
9f0be4f8
JM
1511 adjust_real (outputs[0].value.f, inexact);
1512 mpz_init_set_si (outputs[1].value.i, i);
1513 break;
1514
f889953b
JM
1515 case mpfr_if_f:
1516 assert (inputs[0].type == gtype_int);
1517 assert (inputs[1].type == gtype_fp);
1518 outputs[0].type = gtype_fp;
1519 mpfr_init (outputs[0].value.f);
1520 assert (mpz_fits_slong_p (inputs[0].value.i));
1521 long l = mpz_get_si (inputs[0].value.i);
1522 inexact = calc->func.mpfr_if_f (outputs[0].value.f, l,
c6af2d89
JM
1523 inputs[1].value.f, mode_mpfr);
1524 if (mode != rm_towardzero)
1525 assert (!inexact && mpfr_zero_p (outputs[0].value.f));
f889953b
JM
1526 adjust_real (outputs[0].value.f, inexact);
1527 break;
1528
6f6fc482
JM
1529 case mpfr_f_11:
1530 assert (inputs[0].type == gtype_fp);
1531 outputs[0].type = gtype_fp;
1532 mpfr_init (outputs[0].value.f);
1533 outputs[1].type = gtype_fp;
1534 mpfr_init (outputs[1].value.f);
1535 int comb_ternary = calc->func.mpfr_f_11 (outputs[0].value.f,
1536 outputs[1].value.f,
1537 inputs[0].value.f,
c6af2d89
JM
1538 mode_mpfr);
1539 if (mode != rm_towardzero)
1540 assert (((comb_ternary & 0x3) == 0
1541 && mpfr_zero_p (outputs[0].value.f))
1542 || ((comb_ternary & 0xc) == 0
1543 && mpfr_zero_p (outputs[1].value.f)));
6f6fc482
JM
1544 adjust_real (outputs[0].value.f, (comb_ternary & 0x3) != 0);
1545 adjust_real (outputs[1].value.f, (comb_ternary & 0xc) != 0);
1546 break;
1547
64a17f1a
JM
1548 case mpc_c_f:
1549 assert (inputs[0].type == gtype_fp);
1550 assert (inputs[1].type == gtype_fp);
1551 outputs[0].type = gtype_fp;
1552 mpfr_init (outputs[0].value.f);
b7867a3b
JM
1553 mpc_init2 (ci1, internal_precision);
1554 assert_exact (mpc_set_fr_fr (ci1, inputs[0].value.f, inputs[1].value.f,
64a17f1a 1555 MPC_RNDNN));
c6af2d89
JM
1556 inexact = calc->func.mpc_c_f (outputs[0].value.f, ci1, mode_mpfr);
1557 if (mode != rm_towardzero)
1558 assert (!inexact && mpfr_zero_p (outputs[0].value.f));
64a17f1a 1559 adjust_real (outputs[0].value.f, inexact);
b7867a3b 1560 mpc_clear (ci1);
64a17f1a
JM
1561 break;
1562
7fda5682
JM
1563 case mpc_c_c:
1564 assert (inputs[0].type == gtype_fp);
1565 assert (inputs[1].type == gtype_fp);
1566 outputs[0].type = gtype_fp;
1567 mpfr_init (outputs[0].value.f);
1568 outputs[1].type = gtype_fp;
1569 mpfr_init (outputs[1].value.f);
b7867a3b 1570 mpc_init2 (ci1, internal_precision);
7fda5682 1571 mpc_init2 (co, internal_precision);
b7867a3b
JM
1572 assert_exact (mpc_set_fr_fr (ci1, inputs[0].value.f, inputs[1].value.f,
1573 MPC_RNDNN));
c6af2d89
JM
1574 mpc_ternary = calc->func.mpc_c_c (co, ci1, mode_mpc);
1575 if (mode != rm_towardzero)
1576 assert ((!MPC_INEX_RE (mpc_ternary)
1577 && mpfr_zero_p (mpc_realref (co)))
1578 || (!MPC_INEX_IM (mpc_ternary)
1579 && mpfr_zero_p (mpc_imagref (co))));
b7867a3b
JM
1580 assert_exact (mpfr_set (outputs[0].value.f, mpc_realref (co),
1581 MPFR_RNDN));
1582 assert_exact (mpfr_set (outputs[1].value.f, mpc_imagref (co),
1583 MPFR_RNDN));
1584 adjust_real (outputs[0].value.f, MPC_INEX_RE (mpc_ternary));
1585 adjust_real (outputs[1].value.f, MPC_INEX_IM (mpc_ternary));
1586 mpc_clear (ci1);
1587 mpc_clear (co);
1588 break;
1589
1590 case mpc_cc_c:
1591 assert (inputs[0].type == gtype_fp);
1592 assert (inputs[1].type == gtype_fp);
1593 assert (inputs[2].type == gtype_fp);
1594 assert (inputs[3].type == gtype_fp);
1595 outputs[0].type = gtype_fp;
1596 mpfr_init (outputs[0].value.f);
1597 outputs[1].type = gtype_fp;
1598 mpfr_init (outputs[1].value.f);
1599 mpc_init2 (ci1, internal_precision);
1600 mpc_init2 (ci2, internal_precision);
1601 mpc_init2 (co, internal_precision);
1602 assert_exact (mpc_set_fr_fr (ci1, inputs[0].value.f, inputs[1].value.f,
1603 MPC_RNDNN));
1604 assert_exact (mpc_set_fr_fr (ci2, inputs[2].value.f, inputs[3].value.f,
7fda5682 1605 MPC_RNDNN));
c6af2d89
JM
1606 mpc_ternary = calc->func.mpc_cc_c (co, ci1, ci2, mode_mpc);
1607 if (mode != rm_towardzero)
1608 assert ((!MPC_INEX_RE (mpc_ternary)
1609 && mpfr_zero_p (mpc_realref (co)))
1610 || (!MPC_INEX_IM (mpc_ternary)
1611 && mpfr_zero_p (mpc_imagref (co))));
7fda5682
JM
1612 assert_exact (mpfr_set (outputs[0].value.f, mpc_realref (co),
1613 MPFR_RNDN));
1614 assert_exact (mpfr_set (outputs[1].value.f, mpc_imagref (co),
1615 MPFR_RNDN));
1616 adjust_real (outputs[0].value.f, MPC_INEX_RE (mpc_ternary));
1617 adjust_real (outputs[1].value.f, MPC_INEX_IM (mpc_ternary));
b7867a3b
JM
1618 mpc_clear (ci1);
1619 mpc_clear (ci2);
7fda5682
JM
1620 mpc_clear (co);
1621 break;
1622
ffb536d0
JM
1623 default:
1624 abort ();
1625 }
1626}
1627
1628/* Return the number of bits for integer type TYPE, where "long" has
1629 LONG_BITS bits (32 or 64). */
1630
1631static int
1632int_type_bits (arg_ret_type type, int long_bits)
1633{
1634 assert (long_bits == 32 || long_bits == 64);
1635 switch (type)
1636 {
1637 case type_int:
1638 return 32;
1639 break;
1640
1641 case type_long:
1642 return long_bits;
1643 break;
1644
1645 case type_long_long:
1646 return 64;
1647 break;
1648
1649 default:
1650 abort ();
1651 }
1652}
1653
1654/* Check whether an integer Z fits a given type TYPE, where "long" has
1655 LONG_BITS bits (32 or 64). */
1656
1657static bool
1658int_fits_type (mpz_t z, arg_ret_type type, int long_bits)
1659{
1660 int bits = int_type_bits (type, long_bits);
1661 bool ret = true;
1662 mpz_t t;
1663 mpz_init (t);
1664 mpz_ui_pow_ui (t, 2, bits - 1);
1665 if (mpz_cmp (z, t) >= 0)
1666 ret = false;
1667 mpz_neg (t, t);
1668 if (mpz_cmp (z, t) < 0)
1669 ret = false;
1670 mpz_clear (t);
1671 return ret;
1672}
1673
1674/* Print a generic value V to FP (name FILENAME), preceded by a space,
5188b973
PM
1675 for type TYPE, LONG_BITS bits per long, printing " IGNORE" instead
1676 if IGNORE. */
ffb536d0
JM
1677
1678static void
1679output_generic_value (FILE *fp, const char *filename, const generic_value *v,
5188b973 1680 bool ignore, arg_ret_type type, int long_bits)
ffb536d0
JM
1681{
1682 if (ignore)
1683 {
1684 if (fputs (" IGNORE", fp) < 0)
1685 error (EXIT_FAILURE, errno, "write to '%s'", filename);
1686 return;
1687 }
1688 assert (v->type == generic_arg_ret_type (type));
1689 const char *suffix;
1690 switch (type)
1691 {
1692 case type_fp:
5188b973 1693 suffix = "";
ffb536d0
JM
1694 break;
1695
1696 case type_int:
1697 suffix = "";
1698 break;
1699
1700 case type_long:
1701 suffix = "L";
1702 break;
1703
1704 case type_long_long:
1705 suffix = "LL";
1706 break;
1707
1708 default:
1709 abort ();
1710 }
1711 switch (v->type)
1712 {
1713 case gtype_fp:
1714 if (mpfr_inf_p (v->value.f))
1715 {
1716 if (fputs ((mpfr_signbit (v->value.f)
1717 ? " minus_infty" : " plus_infty"), fp) < 0)
1718 error (EXIT_FAILURE, errno, "write to '%s'", filename);
1719 }
1720 else
1721 {
1722 assert (mpfr_number_p (v->value.f));
1723 if (mpfr_fprintf (fp, " %Ra%s", v->value.f, suffix) < 0)
1724 error (EXIT_FAILURE, errno, "mpfr_fprintf to '%s'", filename);
1725 }
1726 break;
1727
1728 case gtype_int: ;
1729 int bits = int_type_bits (type, long_bits);
1730 mpz_t tmp;
1731 mpz_init (tmp);
1732 mpz_ui_pow_ui (tmp, 2, bits - 1);
1733 mpz_neg (tmp, tmp);
1734 if (mpz_cmp (v->value.i, tmp) == 0)
1735 {
1736 mpz_add_ui (tmp, tmp, 1);
1737 if (mpfr_fprintf (fp, " (%Zd%s-1)", tmp, suffix) < 0)
1738 error (EXIT_FAILURE, errno, "mpfr_fprintf to '%s'", filename);
1739 }
1740 else
1741 {
1742 if (mpfr_fprintf (fp, " %Zd%s", v->value.i, suffix) < 0)
1743 error (EXIT_FAILURE, errno, "mpfr_fprintf to '%s'", filename);
1744 }
1745 mpz_clear (tmp);
1746 break;
1747
1748 default:
1749 abort ();
1750 }
1751}
1752
8e554659
JM
1753/* Generate test output to FP (name FILENAME) for test function TF
1754 (rounding results to a narrower type if NARROW), input test IT,
1755 choice of input values INPUTS. */
ffb536d0
JM
1756
1757static void
1758output_for_one_input_case (FILE *fp, const char *filename, test_function *tf,
8e554659 1759 bool narrow, input_test *it, generic_value *inputs)
ffb536d0
JM
1760{
1761 bool long_bits_matters = false;
1762 bool fits_long32 = true;
1763 for (size_t i = 0; i < tf->num_args; i++)
1764 {
1765 generic_value_type gtype = generic_arg_ret_type (tf->arg_types[i]);
1766 assert (inputs[i].type == gtype);
1767 if (gtype == gtype_int)
1768 {
1769 bool fits_64 = int_fits_type (inputs[i].value.i, tf->arg_types[i],
1770 64);
1771 if (!fits_64)
1772 return;
1773 if (tf->arg_types[i] == type_long
1774 && !int_fits_type (inputs[i].value.i, tf->arg_types[i], 32))
1775 {
1776 long_bits_matters = true;
1777 fits_long32 = false;
1778 }
1779 }
1780 }
1781 generic_value generic_outputs[MAX_NRET];
c6af2d89 1782 calc_generic_results (generic_outputs, inputs, &tf->calc, rm_towardzero);
ffb536d0
JM
1783 bool ignore_output_long32[MAX_NRET] = { false };
1784 bool ignore_output_long64[MAX_NRET] = { false };
1785 for (size_t i = 0; i < tf->num_ret; i++)
1786 {
1787 assert (generic_outputs[i].type
1788 == generic_arg_ret_type (tf->ret_types[i]));
1789 switch (generic_outputs[i].type)
1790 {
1791 case gtype_fp:
1792 if (!mpfr_number_p (generic_outputs[i].value.f))
1793 goto out; /* Result is NaN or exact infinity. */
1794 break;
1795
1796 case gtype_int:
1797 ignore_output_long32[i] = !int_fits_type (generic_outputs[i].value.i,
1798 tf->ret_types[i], 32);
1799 ignore_output_long64[i] = !int_fits_type (generic_outputs[i].value.i,
1800 tf->ret_types[i], 64);
1801 if (ignore_output_long32[i] != ignore_output_long64[i])
1802 long_bits_matters = true;
1803 break;
1804
1805 default:
1806 abort ();
1807 }
1808 }
1809 /* Iterate over relevant sizes of long and floating-point formats. */
1810 for (int long_bits = 32; long_bits <= 64; long_bits += 32)
1811 {
1812 if (long_bits == 32 && !fits_long32)
1813 continue;
1814 if (long_bits == 64 && !long_bits_matters)
1815 continue;
1816 const char *long_cond;
1817 if (long_bits_matters)
1818 long_cond = (long_bits == 32 ? ":long32" : ":long64");
1819 else
1820 long_cond = "";
1821 bool *ignore_output = (long_bits == 32
1822 ? ignore_output_long32
1823 : ignore_output_long64);
1824 for (fp_format f = fp_first_format; f < fp_num_formats; f++)
1825 {
1826 bool fits = true;
1827 mpfr_t res[rm_num_modes];
1828 unsigned int exc_before[rm_num_modes];
1829 unsigned int exc_after[rm_num_modes];
8e554659
JM
1830 bool have_fp_arg = false;
1831 int max_exp = 0;
1832 int num_ones = 0;
1833 int min_exp = 0;
1834 int max_prec = 0;
ffb536d0
JM
1835 for (size_t i = 0; i < tf->num_args; i++)
1836 {
1837 if (inputs[i].type == gtype_fp)
f889953b 1838 {
8e554659
JM
1839 if (narrow)
1840 {
1841 if (mpfr_zero_p (inputs[i].value.f))
1842 continue;
1843 assert (mpfr_regular_p (inputs[i].value.f));
1844 int this_exp, this_num_ones, this_min_exp, this_prec;
1845 mpz_t tmp;
1846 mpz_init (tmp);
1847 mpfr_exp_t e = mpfr_get_z_2exp (tmp, inputs[i].value.f);
1848 if (mpz_sgn (tmp) < 0)
1849 mpz_neg (tmp, tmp);
1850 size_t bits = mpz_sizeinbase (tmp, 2);
1851 mp_bitcnt_t tz = mpz_scan1 (tmp, 0);
1852 this_min_exp = e + tz;
1853 this_prec = bits - tz;
1854 assert (this_prec > 0);
1855 this_exp = this_min_exp + this_prec - 1;
1856 assert (this_exp
1857 == mpfr_get_exp (inputs[i].value.f) - 1);
1858 this_num_ones = 1;
1859 while ((size_t) this_num_ones < bits
1860 && mpz_tstbit (tmp, bits - 1 - this_num_ones))
1861 this_num_ones++;
1862 mpz_clear (tmp);
1863 if (have_fp_arg)
1864 {
1865 if (this_exp > max_exp
1866 || (this_exp == max_exp
1867 && this_num_ones > num_ones))
1868 {
1869 max_exp = this_exp;
1870 num_ones = this_num_ones;
1871 }
1872 if (this_min_exp < min_exp)
1873 min_exp = this_min_exp;
1874 if (this_prec > max_prec)
1875 max_prec = this_prec;
1876 }
1877 else
1878 {
1879 max_exp = this_exp;
1880 num_ones = this_num_ones;
1881 min_exp = this_min_exp;
1882 max_prec = this_prec;
1883 }
1884 have_fp_arg = true;
1885 }
1886 else
1887 {
1888 round_real (res, exc_before, exc_after,
1889 inputs[i].value.f, f);
1890 if (!mpfr_equal_p (res[rm_tonearest], inputs[i].value.f))
1891 fits = false;
1892 for (rounding_mode m = rm_first_mode;
1893 m < rm_num_modes;
1894 m++)
1895 mpfr_clear (res[m]);
1896 if (!fits)
1897 break;
1898 }
f889953b 1899 }
ffb536d0
JM
1900 }
1901 if (!fits)
1902 continue;
8e554659
JM
1903 /* The inputs fit this type if required to do so, so compute
1904 the ideal outputs and exceptions. */
ffb536d0
JM
1905 mpfr_t all_res[MAX_NRET][rm_num_modes];
1906 unsigned int all_exc_before[MAX_NRET][rm_num_modes];
1907 unsigned int all_exc_after[MAX_NRET][rm_num_modes];
1908 unsigned int merged_exc_before[rm_num_modes] = { 0 };
1909 unsigned int merged_exc_after[rm_num_modes] = { 0 };
1910 /* For functions not exactly determined, track whether
1911 underflow is required (some result is inexact, and
1912 magnitude does not exceed the greatest magnitude
1913 subnormal), and permitted (not an exact zero, and
1914 magnitude does not exceed the least magnitude
1915 normal). */
1916 bool must_underflow = false;
1917 bool may_underflow = false;
1918 for (size_t i = 0; i < tf->num_ret; i++)
1919 {
1920 switch (generic_outputs[i].type)
1921 {
1922 case gtype_fp:
1923 round_real (all_res[i], all_exc_before[i], all_exc_after[i],
1924 generic_outputs[i].value.f, f);
1925 for (rounding_mode m = rm_first_mode; m < rm_num_modes; m++)
1926 {
1927 merged_exc_before[m] |= all_exc_before[i][m];
1928 merged_exc_after[m] |= all_exc_after[i][m];
1929 if (!tf->exact)
1930 {
1931 must_underflow
1932 |= ((all_exc_before[i][m]
1933 & (1U << exc_inexact)) != 0
1934 && (mpfr_cmpabs (generic_outputs[i].value.f,
1935 fp_formats[f].subnorm_max)
1936 <= 0));
1937 may_underflow
1938 |= (!mpfr_zero_p (generic_outputs[i].value.f)
046651c1
JM
1939 && (mpfr_cmpabs (generic_outputs[i].value.f,
1940 fp_formats[f].min_plus_half)
1941 <= 0));
ffb536d0 1942 }
c6af2d89
JM
1943 /* If the result is an exact zero, the sign may
1944 depend on the rounding mode, so recompute it
1945 directly in that mode. */
1946 if (mpfr_zero_p (all_res[i][m])
1947 && (all_exc_before[i][m] & (1U << exc_inexact)) == 0)
1948 {
1949 generic_value outputs_rm[MAX_NRET];
1950 calc_generic_results (outputs_rm, inputs,
1951 &tf->calc, m);
1952 assert_exact (mpfr_set (all_res[i][m],
1953 outputs_rm[i].value.f,
1954 MPFR_RNDN));
1955 for (size_t j = 0; j < tf->num_ret; j++)
1956 generic_value_free (&outputs_rm[j]);
1957 }
ffb536d0
JM
1958 }
1959 break;
1960
1961 case gtype_int:
1962 if (ignore_output[i])
1963 for (rounding_mode m = rm_first_mode;
1964 m < rm_num_modes;
1965 m++)
1966 {
1967 merged_exc_before[m] |= 1U << exc_invalid;
1968 merged_exc_after[m] |= 1U << exc_invalid;
1969 }
1970 break;
1971
1972 default:
1973 abort ();
1974 }
1975 }
1976 assert (may_underflow || !must_underflow);
1977 for (rounding_mode m = rm_first_mode; m < rm_num_modes; m++)
1978 {
1979 bool before_after_matters
1980 = tf->exact && merged_exc_before[m] != merged_exc_after[m];
aa97dee1 1981 if (before_after_matters)
ffb536d0 1982 {
aa97dee1
JM
1983 assert ((merged_exc_before[m] ^ merged_exc_after[m])
1984 == (1U << exc_underflow));
1985 assert ((merged_exc_before[m] & (1U << exc_underflow)) != 0);
1986 }
1987 unsigned int merged_exc = merged_exc_before[m];
8e554659
JM
1988 if (narrow)
1989 {
1990 if (fprintf (fp, "= %s %s %s%s:arg_fmt(%d,%d,%d,%d)",
1991 tf->name, rounding_modes[m].name,
1992 fp_formats[f].name, long_cond, max_exp,
1993 num_ones, min_exp, max_prec) < 0)
1994 error (EXIT_FAILURE, errno, "write to '%s'", filename);
1995 }
1996 else
1997 {
1998 if (fprintf (fp, "= %s %s %s%s", tf->name,
1999 rounding_modes[m].name, fp_formats[f].name,
2000 long_cond) < 0)
2001 error (EXIT_FAILURE, errno, "write to '%s'", filename);
2002 }
aa97dee1
JM
2003 /* Print inputs. */
2004 for (size_t i = 0; i < tf->num_args; i++)
2005 output_generic_value (fp, filename, &inputs[i], false,
5188b973 2006 tf->arg_types[i], long_bits);
aa97dee1
JM
2007 if (fputs (" :", fp) < 0)
2008 error (EXIT_FAILURE, errno, "write to '%s'", filename);
2009 /* Print outputs. */
2010 bool must_erange = false;
08f7b95d 2011 bool some_underflow_zero = false;
aa97dee1
JM
2012 for (size_t i = 0; i < tf->num_ret; i++)
2013 {
2014 generic_value g;
2015 g.type = generic_outputs[i].type;
2016 switch (g.type)
ffb536d0 2017 {
aa97dee1
JM
2018 case gtype_fp:
2019 if (mpfr_inf_p (all_res[i][m])
2020 && (all_exc_before[i][m]
2021 & (1U << exc_overflow)) != 0)
2022 must_erange = true;
2023 if (mpfr_zero_p (all_res[i][m])
2024 && (tf->exact
2025 || mpfr_zero_p (all_res[i][rm_tonearest]))
2026 && (all_exc_before[i][m]
2027 & (1U << exc_underflow)) != 0)
2028 must_erange = true;
08f7b95d
JM
2029 if (mpfr_zero_p (all_res[i][rm_towardzero])
2030 && (all_exc_before[i][m]
2031 & (1U << exc_underflow)) != 0)
2032 some_underflow_zero = true;
aa97dee1
JM
2033 mpfr_init2 (g.value.f, fp_formats[f].mant_dig);
2034 assert_exact (mpfr_set (g.value.f, all_res[i][m],
2035 MPFR_RNDN));
2036 break;
ffb536d0 2037
aa97dee1
JM
2038 case gtype_int:
2039 mpz_init (g.value.i);
2040 mpz_set (g.value.i, generic_outputs[i].value.i);
2041 break;
ffb536d0 2042
aa97dee1
JM
2043 default:
2044 abort ();
ffb536d0 2045 }
aa97dee1 2046 output_generic_value (fp, filename, &g, ignore_output[i],
5188b973 2047 tf->ret_types[i], long_bits);
aa97dee1
JM
2048 generic_value_free (&g);
2049 }
2050 if (fputs (" :", fp) < 0)
2051 error (EXIT_FAILURE, errno, "write to '%s'", filename);
2052 /* Print miscellaneous flags (passed through from
2053 input). */
2054 for (size_t i = 0; i < it->num_flags; i++)
2055 switch (it->flags[i].type)
2056 {
863893ec 2057 case flag_ignore_zero_inf_sign:
aa97dee1 2058 case flag_xfail:
5bc9b3a1 2059 case flag_no_mathvec:
aa97dee1
JM
2060 if (fprintf (fp, " %s%s",
2061 input_flags[it->flags[i].type],
2062 (it->flags[i].cond
2063 ? it->flags[i].cond
2064 : "")) < 0)
2065 error (EXIT_FAILURE, errno, "write to '%s'",
2066 filename);
2067 break;
2068 case flag_xfail_rounding:
2069 if (m != rm_tonearest)
2070 if (fprintf (fp, " xfail%s",
2071 (it->flags[i].cond
2072 ? it->flags[i].cond
2073 : "")) < 0)
2074 error (EXIT_FAILURE, errno, "write to '%s'",
2075 filename);
2076 break;
2077 default:
2078 break;
2079 }
08f7b95d
JM
2080 /* For the ibm128 format, expect incorrect overflowing
2081 results in rounding modes other than to nearest;
2082 likewise incorrect results where the result may
2083 underflow to 0. */
2084 if (f == fp_ldbl_128ibm
2085 && m != rm_tonearest
2086 && (some_underflow_zero
2087 || (merged_exc_before[m] & (1U << exc_overflow)) != 0))
2088 if (fputs (" xfail:ibm128-libgcc", fp) < 0)
2089 error (EXIT_FAILURE, errno, "write to '%s'", filename);
aa97dee1
JM
2090 /* Print exception flags and compute errno
2091 expectations where not already computed. */
2092 bool may_edom = false;
2093 bool must_edom = false;
2094 bool may_erange = must_erange || may_underflow;
2095 for (fp_exception e = exc_first_exception;
2096 e < exc_num_exceptions;
2097 e++)
2098 {
2099 bool expect_e = (merged_exc & (1U << e)) != 0;
2100 bool e_optional = false;
2101 switch (e)
2102 {
2103 case exc_divbyzero:
2104 if (expect_e)
2105 may_erange = must_erange = true;
2106 break;
2107
2108 case exc_inexact:
2109 if (!tf->exact)
2110 e_optional = true;
2111 break;
2112
2113 case exc_invalid:
2114 if (expect_e)
2115 may_edom = must_edom = true;
2116 break;
2117
2118 case exc_overflow:
2119 if (expect_e)
2120 may_erange = true;
2121 break;
2122
2123 case exc_underflow:
2124 if (expect_e)
2125 may_erange = true;
2126 if (must_underflow)
2127 assert (expect_e);
2128 if (may_underflow && !must_underflow)
2129 e_optional = true;
2130 break;
2131
2132 default:
2133 abort ();
2134 }
2135 if (e_optional)
2136 {
2137 assert (!before_after_matters);
2138 if (fprintf (fp, " %s-ok", exceptions[e]) < 0)
2139 error (EXIT_FAILURE, errno, "write to '%s'",
2140 filename);
2141 }
2142 else
2143 {
2144 if (expect_e)
2145 if (fprintf (fp, " %s", exceptions[e]) < 0)
ffb536d0
JM
2146 error (EXIT_FAILURE, errno, "write to '%s'",
2147 filename);
aa97dee1
JM
2148 if (before_after_matters && e == exc_underflow)
2149 if (fputs (":before-rounding", fp) < 0)
2150 error (EXIT_FAILURE, errno, "write to '%s'",
2151 filename);
2152 for (int after = 0; after <= 1; after++)
ffb536d0 2153 {
aa97dee1
JM
2154 bool expect_e_here = expect_e;
2155 if (after == 1 && (!before_after_matters
2156 || e != exc_underflow))
2157 continue;
2158 const char *after_cond;
2159 if (before_after_matters && e == exc_underflow)
2160 {
2161 after_cond = (after
2162 ? ":after-rounding"
2163 : ":before-rounding");
2164 expect_e_here = !after;
2165 }
2166 else
2167 after_cond = "";
ffb536d0 2168 input_flag_type okflag;
aa97dee1 2169 okflag = (expect_e_here
ffb536d0
JM
2170 ? flag_missing_first
2171 : flag_spurious_first) + e;
2172 for (size_t i = 0; i < it->num_flags; i++)
2173 if (it->flags[i].type == okflag)
aa97dee1 2174 if (fprintf (fp, " %s-ok%s%s",
ffb536d0
JM
2175 exceptions[e],
2176 (it->flags[i].cond
2177 ? it->flags[i].cond
aa97dee1 2178 : ""), after_cond) < 0)
ffb536d0
JM
2179 error (EXIT_FAILURE, errno, "write to '%s'",
2180 filename);
2181 }
2182 }
aa97dee1
JM
2183 }
2184 /* Print errno expectations. */
2185 if (tf->complex_fn)
2186 {
2187 must_edom = false;
2188 must_erange = false;
2189 }
2190 if (may_edom && !must_edom)
2191 {
2192 if (fputs (" errno-edom-ok", fp) < 0)
2193 error (EXIT_FAILURE, errno, "write to '%s'",
2194 filename);
2195 }
2196 else
2197 {
2198 if (must_edom)
2199 if (fputs (" errno-edom", fp) < 0)
2200 error (EXIT_FAILURE, errno, "write to '%s'",
2201 filename);
2202 input_flag_type okflag = (must_edom
2203 ? flag_missing_errno
2204 : flag_spurious_errno);
2205 for (size_t i = 0; i < it->num_flags; i++)
2206 if (it->flags[i].type == okflag)
2207 if (fprintf (fp, " errno-edom-ok%s",
2208 (it->flags[i].cond
2209 ? it->flags[i].cond
2210 : "")) < 0)
ffb536d0
JM
2211 error (EXIT_FAILURE, errno, "write to '%s'",
2212 filename);
aa97dee1
JM
2213 }
2214 if (before_after_matters)
2215 assert (may_erange && !must_erange);
2216 if (may_erange && !must_erange)
2217 {
2218 if (fprintf (fp, " errno-erange-ok%s",
2219 (before_after_matters
2220 ? ":before-rounding"
2221 : "")) < 0)
2222 error (EXIT_FAILURE, errno, "write to '%s'",
2223 filename);
2224 }
2225 if (before_after_matters || !(may_erange && !must_erange))
2226 {
2227 if (must_erange)
2228 if (fputs (" errno-erange", fp) < 0)
2229 error (EXIT_FAILURE, errno, "write to '%s'",
2230 filename);
2231 input_flag_type okflag = (must_erange
2232 ? flag_missing_errno
2233 : flag_spurious_errno);
2234 for (size_t i = 0; i < it->num_flags; i++)
2235 if (it->flags[i].type == okflag)
2236 if (fprintf (fp, " errno-erange-ok%s%s",
2237 (it->flags[i].cond
2238 ? it->flags[i].cond
2239 : ""),
2240 (before_after_matters
2241 ? ":after-rounding"
2242 : "")) < 0)
ffb536d0
JM
2243 error (EXIT_FAILURE, errno, "write to '%s'",
2244 filename);
ffb536d0 2245 }
aa97dee1
JM
2246 if (putc ('\n', fp) < 0)
2247 error (EXIT_FAILURE, errno, "write to '%s'", filename);
ffb536d0
JM
2248 }
2249 for (size_t i = 0; i < tf->num_ret; i++)
2250 {
2251 if (generic_outputs[i].type == gtype_fp)
2252 for (rounding_mode m = rm_first_mode; m < rm_num_modes; m++)
2253 mpfr_clear (all_res[i][m]);
2254 }
2255 }
2256 }
2257 out:
2258 for (size_t i = 0; i < tf->num_ret; i++)
2259 generic_value_free (&generic_outputs[i]);
2260}
2261
8e554659
JM
2262/* Generate test output data for FUNCTION to FILENAME. The function
2263 is interpreted as rounding its results to a narrower type if
2264 NARROW. */
ffb536d0
JM
2265
2266static void
8e554659 2267generate_output (const char *function, bool narrow, const char *filename)
ffb536d0
JM
2268{
2269 FILE *fp = fopen (filename, "w");
2270 if (fp == NULL)
2271 error (EXIT_FAILURE, errno, "open '%s'", filename);
2272 for (size_t i = 0; i < ARRAY_SIZE (test_functions); i++)
2273 {
2274 test_function *tf = &test_functions[i];
4f1bc131
JM
2275 if (strcmp (tf->name, function) != 0)
2276 continue;
ffb536d0
JM
2277 for (size_t j = 0; j < tf->num_tests; j++)
2278 {
2279 input_test *it = &tf->tests[j];
2280 if (fputs (it->line, fp) < 0)
2281 error (EXIT_FAILURE, errno, "write to '%s'", filename);
2282 for (size_t k = 0; k < it->num_input_cases; k++)
8e554659
JM
2283 output_for_one_input_case (fp, filename, tf, narrow,
2284 it, it->inputs[k]);
ffb536d0
JM
2285 }
2286 }
2287 if (fclose (fp) != 0)
2288 error (EXIT_FAILURE, errno, "close '%s'", filename);
2289}
2290
2291int
2292main (int argc, char **argv)
2293{
8e554659
JM
2294 if (argc != 4
2295 && !(argc == 5 && strcmp (argv[1], "--narrow") == 0))
4f1bc131 2296 error (EXIT_FAILURE, 0,
8e554659
JM
2297 "usage: gen-auto-libm-tests [--narrow] <input> <func> <output>");
2298 bool narrow;
ffb536d0 2299 const char *input_filename = argv[1];
4f1bc131
JM
2300 const char *function = argv[2];
2301 const char *output_filename = argv[3];
8e554659
JM
2302 if (argc == 4)
2303 {
2304 narrow = false;
2305 input_filename = argv[1];
2306 function = argv[2];
2307 output_filename = argv[3];
2308 }
2309 else
2310 {
2311 narrow = true;
2312 input_filename = argv[2];
2313 function = argv[3];
2314 output_filename = argv[4];
2315 }
ffb536d0
JM
2316 init_fp_formats ();
2317 read_input (input_filename);
8e554659 2318 generate_output (function, narrow, output_filename);
ffb536d0
JM
2319 exit (EXIT_SUCCESS);
2320}