summaryrefslogtreecommitdiff
path: root/tests/mpc-tests.h
blob: 4c2c260cd5acff0da8aa47babf25b87bbb3e35b4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
/* mpc-tests.h -- Tests helper functions.

Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014 INRIA

This file is part of GNU MPC.

GNU MPC is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 3 of the License, or (at your
option) any later version.

GNU MPC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
more details.

You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see http://www.gnu.org/licenses/ .
*/

#ifndef __MPC_TESTS_H
#define __MPC_TESTS_H

#include "config.h"
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include "mpc.h"

/* pieces copied from mpc-impl.h */
#define MPC_PREC_RE(x) (mpfr_get_prec(mpc_realref(x)))
#define MPC_PREC_IM(x) (mpfr_get_prec(mpc_imagref(x)))
#define MPC_MAX_PREC(x) MPC_MAX(MPC_PREC_RE(x), MPC_PREC_IM(x))
#define MPC_MAX(h,i) ((h) > (i) ? (h) : (i))

#define MPC_ASSERT(expr)                                        \
  do {                                                          \
    if (!(expr))                                                \
      {                                                         \
        fprintf (stderr, "%s:%d: MPC assertion failed: %s\n",   \
                 __FILE__, __LINE__, #expr);                    \
        abort();                                                \
      }                                                         \
  } while (0)

#if defined (__cplusplus)
extern "C" {
#endif
__MPC_DECLSPEC int  mpc_mul_naive (mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t);
__MPC_DECLSPEC int  mpc_mul_karatsuba (mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t);
__MPC_DECLSPEC int  mpc_fma_naive (mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t);
#if defined (__cplusplus)
}
#endif
/* end pieces copied from mpc-impl.h */

#define MPC_OUT(x)                                              \
do {                                                            \
  printf (#x "[%lu,%lu]=", (unsigned long int) MPC_PREC_RE (x), \
      (unsigned long int) MPC_PREC_IM (x));                     \
  mpc_out_str (stdout, 2, 0, x, MPC_RNDNN);                     \
  printf ("\n");                                                \
} while (0)

#define MPFR_OUT(x)                                             \
do {                                                            \
  printf (#x "[%lu]=", (unsigned long int) mpfr_get_prec (x));  \
  mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN);                     \
  printf ("\n");                                                \
} while (0)


#define MPC_INEX_STR(inex)                      \
  (inex) == 0 ? "(0, 0)"                        \
    : (inex) == 1 ? "(+1, 0)"                   \
    : (inex) == 2 ? "(-1, 0)"                   \
    : (inex) == 4 ? "(0, +1)"                   \
    : (inex) == 5 ? "(+1, +1)"                  \
    : (inex) == 6 ? "(-1, +1)"                  \
    : (inex) == 8 ? "(0, -1)"                   \
    : (inex) == 9 ? "(+1, -1)"                  \
    : (inex) == 10 ? "(-1, -1)" : "unknown"

#define TEST_FAILED(func,op,got,expected,rnd)			\
  do {								\
    printf ("%s(op) failed [rnd=%d]\n with", func, rnd);	\
    MPC_OUT (op);						\
    printf ("     ");						\
    MPC_OUT (got);						\
    MPC_OUT (expected);						\
    exit (1);							\
  } while (0)

#define QUOTE(X) NAME(X)
#define NAME(X) #X

/** RANDOM FUNCTIONS **/
/* the 3 following functions handle seed for random numbers. Usage:
   - add test_start at the beginning of your test function
   - use test_default_random (or use your random functions with
   gmp_randstate_t rands) in your tests
   - add test_end at the end the test function */
extern gmp_randstate_t  rands;

extern void test_start (void);
extern void test_end   (void);
extern void test_default_random (mpc_ptr, mpfr_exp_t, mpfr_exp_t,
                                 unsigned int, unsigned int);

void test_random_si   (long int *n, unsigned long emax,
                       unsigned int negative_probability);
void test_random_d    (double *x, unsigned int negative_probability);
void test_random_mpfr (mpfr_ptr x, mpfr_exp_t emin, mpfr_exp_t emax,
                       unsigned int negative_probability);
void test_random_mpc  (mpc_ptr z, mpfr_exp_t emin, mpfr_exp_t emax,
                       unsigned int negative_probability);

/** COMPARISON FUNCTIONS **/
/* some sign are unspecified in ISO C99, thus we record in struct known_signs_t
   whether the sign has to be checked */
typedef struct
{
  int re;  /* boolean value */
  int im;  /* boolean value */
} known_signs_t;

/* same_mpfr_value returns 1:
   - if got and ref have the same value and known_sign is true,
   or
   - if they have the same absolute value, got = 0 or got = inf, and known_sign is
   false.
   returns 0 in other cases.
   Unlike mpfr_cmp, same_mpfr_value(got, ref, x) return 1 when got and
   ref are both NaNs. */
extern int same_mpfr_value (mpfr_ptr got, mpfr_ptr ref, int known_sign);
extern int same_mpc_value  (mpc_ptr got, mpc_ptr ref,
                            known_signs_t known_signs);

/** READ FILE WITH TEST DATA SET **/
extern FILE * open_data_file         (const char *file_name);
extern void   close_data_file        (FILE *fp);

/* helper file reading functions */
extern void skip_whitespace_comments (FILE *fp);
extern void read_ternary             (FILE *fp, int* ternary);
extern void read_mpfr_rounding_mode  (FILE *fp, mpfr_rnd_t* rnd);
extern void read_mpc_rounding_mode   (FILE *fp, mpc_rnd_t* rnd);
extern mpfr_prec_t read_mpfr_prec    (FILE *fp);
extern void read_int                 (FILE *fp, int *n, const char *name);
extern size_t read_string            (FILE *fp, char **buffer_ptr,
                                      size_t buffer_length, const char *name);
extern void read_mpfr                (FILE *fp, mpfr_ptr x, int *known_sign);
extern void read_mpc                 (FILE *fp, mpc_ptr z, known_signs_t *ks);

void set_mpfr_flags   (int counter);
void check_mpfr_flags (int counter);

/*
  function descriptions
*/

/* type for return, output and input parameters */
typedef enum {
  NATIVE_INT,          /* int */
  NATIVE_UL,           /* unsigned long */
  NATIVE_L,            /* signed long */
  NATIVE_D,            /* double */
  NATIVE_LD,           /* long double */
  NATIVE_DC,           /* double _Complex */
  NATIVE_LDC,          /* long double _Complex */
  NATIVE_IM,           /* intmax_t */
  NATIVE_UIM,          /* uintmax_t */
  NATIVE_STRING,       /* char* */
  GMP_Z,               /* mpz_t */
  GMP_Q,               /* mpq_t */
  GMP_F,               /* mpf_t */
  MPFR_INEX,           /* mpfr_inex */
  MPFR,                /* mpfr_t  */
  MPFR_RND,            /* mpfr_rnd_t */
  MPC_INEX,            /* mpc_inex */
  MPC,                 /* mpc_t */
  MPC_RND,             /* mpc_rnd_t */
  MPCC_INEX            /* mpcc_inex */
} mpc_param_t;

/* additional information for checking mpfr_t result */
typedef struct {
  mpfr_t              mpfr; /* skip space for the variable */
  int                 known_sign;
} mpfr_data_t;

#define TERNARY_NOT_CHECKED 255
/* special value to indicate that the ternary value is not checked */
#define TERNARY_ERROR 254
/* special value to indicate that an error occurred in an mpc function */

/* mpc nonary value as a pair of ternary value for data from a file */
typedef struct {
  int                real;
  int                imag;
} mpc_inex_data_t;

/* additional information for checking mpc_t result */
typedef struct {
  mpc_t               mpc; /* skip space */
  int                 known_sign_real;
  int                 known_sign_imag;
} mpc_data_t;

/* string buffer information */
typedef struct {
  char*               string; /* skip space */
  int                 length;
} string_info_t;

/* abstract parameter type

   Let consider an abstract parameter p, which is declared as follows:
   mpc_operand_t p;
   we use the fact that a mpfr_t (respectively mpc_t) value can be accessed as
   'p.mpfr' (resp. 'p.mpc') as well as 'p.mpfr_info.mpfr'
   (resp. 'p.mpc_info.mpc'), the latter form permitting access to the
   'known_sign' field(s).
   Similarly, if the abstract parameter represent a string variable, we can
   access its value with 'p.string' or 'p.string_info.string' and its size
   with 'p.string_info.length'.

   The user uses the simple form when adding a test, the second form is used by the
   test suite itself when reading reference data and checking result against them.
*/
typedef union {
  int                  i;
  unsigned long        ui;
  signed long          si;
  double               d;
  long double          ld;
#ifdef _MPC_H_HAVE_INTMAX_T
  intmax_t             im;
  uintmax_t            uim;
#endif
#ifdef _Complex_I
  double _Complex      dc;
  long double _Complex ldc;
#endif
  char *               string;
  string_info_t        string_info;
  mpz_t                mpz;
  mpq_t                mpq;
  mpf_t                mpf;
  mpfr_t               mpfr;
  mpfr_data_t          mpfr_data;
  mpfr_rnd_t           mpfr_rnd;
  int                  mpfr_inex;
  mpc_t                mpc;
  mpc_data_t           mpc_data;
  mpc_rnd_t            mpc_rnd;
  int                  mpc_inex;
  mpc_inex_data_t      mpc_inex_data;
  int                  mpcc_inex;
} mpc_operand_t;

#define PARAMETER_ARRAY_SIZE 10

/* function name plus parameters in the following order:
   output parameters, input parameters (ending with rounding modes).
   The input parameters include one rounding mode per mpfr/mpc
   output starting from rnd_index.
   For the time being, there may be either one or two rounding modes;
   in the latter case, we assume that there are three outputs:
   the inexact value and two complex numbers.
 */
typedef struct {
  char         *name;  /* name of the function */
  int           nbout; /* number of output parameters */
  int           nbin;  /* number of input parameters, including rounding
                          modes */
  int           nbrnd; /* number of rounding mode parameters */
  mpc_operand_t P[PARAMETER_ARRAY_SIZE]; /* value of parameters */
  mpc_param_t   T[PARAMETER_ARRAY_SIZE]; /* type of parameters */
} mpc_fun_param_t;


void        read_description    (mpc_fun_param_t* param, const char *file);
const char* read_description_findname (mpc_param_t e);

/* file functions */
typedef struct {
  char *pathname;
  FILE *fd;
  unsigned long line_number;
  unsigned long test_line_number;
  int nextchar;
} mpc_datafile_context_t;

void    open_datafile       (mpc_datafile_context_t* datafile_context,
                             const char * data_filename);
void    close_datafile      (mpc_datafile_context_t *dc);

/* data file functions */
void    read_line           (mpc_datafile_context_t* datafile_context,
                             mpc_fun_param_t* params);
void    check_data          (mpc_datafile_context_t* datafile_context,
                             mpc_fun_param_t* params,
                             int index_reused_operand);

/* parameters templated functions */
int     data_check_template (const char* descr_file, const char * data_file);

void    init_parameters     (mpc_fun_param_t *params);
void    clear_parameters    (mpc_fun_param_t *params);
void    print_parameter     (mpc_fun_param_t *params, int index);
int     copy_parameter      (mpc_fun_param_t *params,
                             int index_dest, int index_src);

void    tpl_read_int        (mpc_datafile_context_t* datafile_context,
                             int *nread, const char *name);
void    tpl_read_ui         (mpc_datafile_context_t* datafile_context,
                             unsigned long int *ui);
void    tpl_read_si         (mpc_datafile_context_t* datafile_context,
                             long int *si);
void    tpl_read_mpz        (mpc_datafile_context_t* datafile_context,
                             mpz_t z);
void    tpl_skip_whitespace_comments (mpc_datafile_context_t* datafile_context);
void    tpl_read_ternary    (mpc_datafile_context_t* datafile_context,
                             int* ternary);
void    tpl_read_mpfr       (mpc_datafile_context_t* datafile_context,
                             mpfr_ptr x, int* known_sign);
void    tpl_read_mpfr_rnd   (mpc_datafile_context_t* datafile_context,
                             mpfr_rnd_t* rnd);
void    tpl_read_mpfr_inex  (mpc_datafile_context_t* datafile_context,
                             int *ternary);
void    tpl_read_mpc_inex   (mpc_datafile_context_t* datafile_context,
                             mpc_inex_data_t* ternarypair);
void    tpl_read_mpc        (mpc_datafile_context_t* datafile_context,
                             mpc_data_t* z);
void    tpl_read_mpc_rnd    (mpc_datafile_context_t* datafile_context,
                             mpc_rnd_t* rnd);

int     tpl_same_mpz_value  (mpz_ptr n1, mpz_ptr n2);
int     tpl_same_mpfr_value (mpfr_ptr x1, mpfr_ptr x2, int known_sign);
int     tpl_check_mpfr_data (mpfr_t got, mpfr_data_t expected);
int     tpl_check_mpc_data  (mpc_ptr got, mpc_data_t expected);

void    tpl_copy_int        (int *dest, const int * const src);
void    tpl_copy_ui         (unsigned long int *dest,
                             const unsigned long int * const src);
void    tpl_copy_si         (long int *dest, const long int * const src);
void    tpl_copy_d          (double *dest, const double * const src);
void    tpl_copy_mpz        (mpz_ptr dest, mpz_srcptr src);
void    tpl_copy_mpfr       (mpfr_ptr dest, mpfr_srcptr src);
void    tpl_copy_mpc        (mpc_ptr dest, mpc_srcptr src);

int     double_rounding     (mpc_fun_param_t *params);

/* iterating over rounding modes */
void    first_rnd_mode      (mpc_fun_param_t *params);
int     is_valid_rnd_mode   (mpc_fun_param_t *params);
void    next_rnd_mode       (mpc_fun_param_t *params);

/* parameter precision */
void    set_output_precision    (mpc_fun_param_t *params, mpfr_prec_t prec);
void    set_input_precision     (mpc_fun_param_t *params, mpfr_prec_t prec);
void    set_reference_precision (mpc_fun_param_t *params, mpfr_prec_t prec);

#endif /* __MPC_TESTS_H */