1/* mpcheck-double -- compare mpc functions against "double complex"
2                     from the GNU libc implementation
3
4Copyright (C) 2020 INRIA
5
6This file is part of GNU MPC.
7
8GNU MPC is free software; you can redistribute it and/or modify it under
9the terms of the GNU Lesser General Public License as published by the
10Free Software Foundation; either version 3 of the License, or (at your
11option) any later version.
12
13GNU MPC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
16more details.
17
18You should have received a copy of the GNU Lesser General Public License
19along with this program. If not, see http://www.gnu.org/licenses/ .
20*/
21
22/* the GNU libc provides the following functions (as of 2.31),
23   with 'f' suffix for the float/binary32 version, with no suffix
24   for the double/binary64 version, with 'l' suffix for the long double
25   version, and with 'f128' suffix for the __float128 version:
26
27   cabs     casinh    cexp      csinh
28   cacos    catan     clog      csqrt
29   cacosh   catanh    clog10    ctan
30   carg     ccos      cpow      ctanh
31   casin    ccosh     csin
32*/
33
34#define _GNU_SOURCE /* for clog10 */
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38#include <complex.h>
39#include <sys/types.h>
40#include <unistd.h>
41#include <assert.h>
42#ifdef __GNUC__
43#include <gnu/libc-version.h>
44#endif
45#include "mpc.h"
46
47#define PRECISION 53
48#define EMAX 1024
49#define TYPE double
50#define SUFFIX
51
52#define mpc_get_type mpc_get_dc
53#define mpc_set_type mpc_set_dc
54#define mpfr_set_type mpfr_set_d
55
56gmp_randstate_t state;
57mpz_t expz; /* global variable used in mpcheck_random */
58unsigned long seed = 0;
59int verbose = 0;
60mpfr_exp_t emin, emax;
61
62#include "mpcheck-common.c"
63
64#define FOO add
65#define CFOO(x,y) (x+y)
66#include "mpcheck-template3.c"
67
68#define FOO sub
69#define CFOO(x,y) (x-y)
70#include "mpcheck-template3.c"
71
72#define FOO mul
73#define CFOO(x,y) (x*y)
74#include "mpcheck-template3.c"
75
76#define FOO div
77#define CFOO(x,y) (x/y)
78#include "mpcheck-template3.c"
79
80#define FOO pow
81#include "mpcheck-template3.c"
82
83#define FOO abs
84#include "mpcheck-template2.c"
85
86#define FOO arg
87#include "mpcheck-template2.c"
88
89#define FOO sqrt
90#include "mpcheck-template1.c"
91
92#define FOO acos
93#include "mpcheck-template1.c"
94
95#define FOO acosh
96#include "mpcheck-template1.c"
97
98#define FOO asin
99#include "mpcheck-template1.c"
100
101#define FOO asinh
102#include "mpcheck-template1.c"
103
104#define FOO atan
105#include "mpcheck-template1.c"
106
107#define FOO atanh
108#include "mpcheck-template1.c"
109
110#define FOO cos
111#include "mpcheck-template1.c"
112
113#define FOO cosh
114#include "mpcheck-template1.c"
115
116#define FOO exp
117#include "mpcheck-template1.c"
118
119#define FOO log
120#include "mpcheck-template1.c"
121
122#define FOO log10
123#include "mpcheck-template1.c"
124
125#define FOO sin
126#include "mpcheck-template1.c"
127
128#define FOO sinh
129#include "mpcheck-template1.c"
130
131/* use reduced exponent range for tan and tanh */
132#define FOO_EMIN -8
133#define FOO_EMAX  8
134
135#define FOO tan
136#include "mpcheck-template1.c"
137
138#define FOO tanh
139#include "mpcheck-template1.c"
140
141#undef FOO_EMIN
142#undef FOO_EMAX
143
144int
145main (int argc, char *argv[])
146{
147  mpfr_prec_t p = PRECISION; /* precision of 'double' */
148  unsigned long n = 1000000; /* default number of random tests per function */
149
150  while (argc >= 2 && argv[1][0] == '-')
151    {
152      if (argc >= 3 && strcmp (argv[1], "-p") == 0)
153        {
154          p = atoi (argv[2]);
155          argc -= 2;
156          argv += 2;
157        }
158      else if (argc >= 3 && strcmp (argv[1], "-seed") == 0)
159        {
160          seed = atoi (argv[2]);
161          argc -= 2;
162          argv += 2;
163        }
164      else if (argc >= 3 && strcmp (argv[1], "-num") == 0)
165        {
166          n = atoi (argv[2]);
167          argc -= 2;
168          argv += 2;
169        }
170      else if (strcmp (argv[1], "-v") == 0)
171        {
172          verbose ++;
173          argc --;
174          argv ++;
175        }
176      else if (strcmp (argv[1], "-check") == 0)
177        {
178          recheck = 1;
179          argc --;
180          argv ++;
181        }
182      else
183        {
184          fprintf (stderr, "Unknown option %s\n", argv[1]);
185          exit (1);
186        }
187    }
188
189  /* set exponent range */
190  emin = -EMAX - PRECISION + 4; /* should be -1073 */
191  emax = EMAX;
192  mpfr_set_emin (emin);
193  mpfr_set_emax (emax);
194
195  gmp_randinit_default (state);
196  mpz_init (expz);
197
198  printf ("Using GMP %s, MPFR %s\n", gmp_version, mpfr_get_version ());
199
200#ifdef __GNUC__
201  printf ("GNU libc version: %s\n", gnu_get_libc_version ());
202  printf ("GNU libc release: %s\n", gnu_get_libc_release ());
203#endif
204
205  if (seed == 0)
206    seed = getpid ();
207  printf ("Using random seed %lu\n", seed);
208
209  /* (complex,complex) -> complex */
210  test_add (p, n);
211  test_sub (p, n);
212  test_mul (p, n);
213  test_div (p, n);
214  test_pow (p, n);
215
216  /* complex -> real */
217  test_abs (p, n);
218  test_arg (p, n);
219
220  /* complex -> complex */
221  test_sqrt (p, n);
222  test_acos (p, n);
223  test_acosh (p, n);
224  test_asin (p, n);
225  test_asinh (p, n);
226  test_atan (p, n);
227  test_atanh (p, n);
228  test_cos (p, n);
229  test_cosh (p, n);
230  test_exp (p, n);
231  test_log (p, n);
232  test_log10 (p, n);
233  test_sin (p, n);
234  test_sinh (p, n);
235  test_tan (p, n);
236  test_tanh (p, n);
237
238  gmp_randclear (state);
239  mpz_clear (expz);
240
241  report_maximal_errors ();
242
243  return 0;
244}
245