1/* mpcheck-float -- compare mpc functions against "float 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#include "mpc.h"
43#ifdef __GNUC__
44#include <gnu/libc-version.h>
45#endif
46
47#define PRECISION 24
48#define EMAX 128
49#define TYPE float
50#define SUFFIX f
51
52#define mpfr_set_type mpfr_set_flt
53
54static TYPE complex
55mpc_get_type (mpc_t x, mpc_rnd_t rnd)
56{
57  /* there is no mpc_get_fltc function */
58  return (TYPE complex) mpc_get_dc (x, rnd);
59}
60
61static int
62mpc_set_type (mpc_t x, TYPE complex y, mpc_rnd_t rnd)
63{
64  /* there is no mpc_set_fltc function */
65  return mpc_set_dc (x, (double complex) y, rnd);
66}
67
68gmp_randstate_t state;
69mpz_t expz; /* global variable used in mpcheck_random */
70unsigned long seed = 0;
71int verbose = 0;
72mpfr_exp_t emin, emax;
73
74#include "mpcheck-common.c"
75
76#define FOO add
77#define CFOO(x,y) (x+y)
78#include "mpcheck-template3.c"
79
80#define FOO sub
81#define CFOO(x,y) (x-y)
82#include "mpcheck-template3.c"
83
84#define FOO mul
85#define CFOO(x,y) (x*y)
86#include "mpcheck-template3.c"
87
88#define FOO div
89#define CFOO(x,y) (x/y)
90#include "mpcheck-template3.c"
91
92#define FOO pow
93#include "mpcheck-template3.c"
94
95#define FOO abs
96#include "mpcheck-template2.c"
97
98#define FOO arg
99#include "mpcheck-template2.c"
100
101#define FOO sqrt
102#include "mpcheck-template1.c"
103
104#define FOO acos
105#include "mpcheck-template1.c"
106
107#define FOO acosh
108#include "mpcheck-template1.c"
109
110#define FOO asin
111#include "mpcheck-template1.c"
112
113#define FOO asinh
114#include "mpcheck-template1.c"
115
116#define FOO atan
117#include "mpcheck-template1.c"
118
119#define FOO atanh
120#include "mpcheck-template1.c"
121
122#define FOO cos
123#include "mpcheck-template1.c"
124
125#define FOO cosh
126#include "mpcheck-template1.c"
127
128#define FOO exp
129#include "mpcheck-template1.c"
130
131#define FOO log
132#include "mpcheck-template1.c"
133
134#define FOO log10
135#include "mpcheck-template1.c"
136
137#define FOO sin
138#include "mpcheck-template1.c"
139
140#define FOO sinh
141#include "mpcheck-template1.c"
142
143#define FOO tan
144#include "mpcheck-template1.c"
145
146#define FOO tanh
147#include "mpcheck-template1.c"
148
149int
150main (int argc, char *argv[])
151{
152  mpfr_prec_t p = PRECISION; /* precision of 'float' */
153  unsigned long n = 1000000; /* default number of random tests per function */
154
155  while (argc >= 2 && argv[1][0] == '-')
156    {
157      if (argc >= 3 && strcmp (argv[1], "-p") == 0)
158        {
159          p = atoi (argv[2]);
160          argc -= 2;
161          argv += 2;
162        }
163      else if (argc >= 3 && strcmp (argv[1], "-seed") == 0)
164        {
165          seed = atoi (argv[2]);
166          argc -= 2;
167          argv += 2;
168        }
169      else if (argc >= 3 && strcmp (argv[1], "-num") == 0)
170        {
171          n = atoi (argv[2]);
172          argc -= 2;
173          argv += 2;
174        }
175      else if (strcmp (argv[1], "-v") == 0)
176        {
177          verbose ++;
178          argc --;
179          argv ++;
180        }
181      else if (strcmp (argv[1], "-check") == 0)
182        {
183          recheck = 1;
184          argc --;
185          argv ++;
186        }
187      else
188        {
189          fprintf (stderr, "Unknown option %s\n", argv[1]);
190          exit (1);
191        }
192    }
193
194  /* set exponent range */
195  emin = -EMAX - PRECISION + 4; /* should be -148 */
196  emax = EMAX;
197  mpfr_set_emin (emin);
198  mpfr_set_emax (emax);
199
200  gmp_randinit_default (state);
201  mpz_init (expz);
202
203  printf ("Using GMP %s, MPFR %s\n", gmp_version, mpfr_get_version ());
204
205#ifdef __GNUC__
206  printf ("GNU libc version: %s\n", gnu_get_libc_version ());
207  printf ("GNU libc release: %s\n", gnu_get_libc_release ());
208#endif
209
210  if (seed == 0)
211    seed = getpid ();
212  printf ("Using random seed %lu\n", seed);
213
214  /* (complex,complex) -> complex */
215  test_add (p, n);
216  test_sub (p, n);
217  test_mul (p, n);
218  test_div (p, n);
219  test_pow (p, n);
220
221  /* complex -> real */
222  test_abs (p, n);
223  test_arg (p, n);
224
225  /* complex -> complex */
226  test_sqrt (p, n);
227  test_acos (p, n);
228  test_acosh (p, n);
229  test_asin (p, n);
230  test_asinh (p, n);
231  test_atan (p, n);
232  test_atanh (p, n);
233  test_cos (p, n);
234  test_cosh (p, n);
235  test_exp (p, n);
236  test_log (p, n);
237  test_log10 (p, n);
238  test_sin (p, n);
239  test_sinh (p, n);
240  test_tan (p, n);
241  test_tanh (p, n);
242
243  gmp_randclear (state);
244  mpz_clear (expz);
245
246  report_maximal_errors ();
247
248  return 0;
249}
250