summaryrefslogtreecommitdiff
path: root/mpc/tests/mpc-tests.h
blob: d1ce58690e1947029d219db84864113ea318a856 (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
/* mpc-tests.h -- Tests helper functions.

Copyright (C) 2008, 2009, 2010, 2011, 2012 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, GMP_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, mp_exp_t, mp_exp_t, unsigned int, unsigned int);


/** 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);


/** GENERIC TESTS **/

typedef int (*CC_func_ptr) (mpc_t, mpc_srcptr, mpc_rnd_t);
typedef int (*C_CC_func_ptr) (mpc_t, mpc_srcptr, mpc_srcptr, mpc_rnd_t);
typedef int (*CCCC_func_ptr) (mpc_t, mpc_srcptr, mpc_srcptr, mpc_srcptr,
			      mpc_rnd_t);
typedef int (*CCU_func_ptr) (mpc_t, mpc_srcptr, unsigned long, mpc_rnd_t);
typedef int (*CCS_func_ptr) (mpc_t, mpc_srcptr, long, mpc_rnd_t);
typedef int (*CCI_func_ptr) (mpc_t, mpc_srcptr, int, mpc_rnd_t);
typedef int (*CCF_func_ptr) (mpc_t, mpc_srcptr, mpfr_srcptr, mpc_rnd_t);
typedef int (*CFC_func_ptr) (mpc_t, mpfr_srcptr, mpc_srcptr, mpc_rnd_t);
typedef int (*CUC_func_ptr) (mpc_t, unsigned long, mpc_srcptr, mpc_rnd_t);
typedef int (*CUUC_func_ptr) (mpc_t, unsigned long, unsigned long, mpc_srcptr,
                              mpc_rnd_t);
typedef int (*FC_func_ptr) (mpfr_t, mpc_srcptr, mpfr_rnd_t);
typedef int (*CC_C_func_ptr) (mpc_t, mpc_t, mpc_srcptr, mpc_rnd_t, mpc_rnd_t);

typedef union {
   FC_func_ptr FC;     /* output: mpfr_t, input: mpc_t */
   CC_func_ptr CC;     /* output: mpc_t, input: mpc_t */
   C_CC_func_ptr C_CC; /* output: mpc_t, inputs: (mpc_t, mpc_t) */
   CCCC_func_ptr CCCC; /* output: mpc_t, inputs: (mpc_t, mpc_t, mpc_t) */
   CCU_func_ptr CCU;   /* output: mpc_t, inputs: (mpc_t, unsigned long) */
   CCS_func_ptr CCS;   /* output: mpc_t, inputs: (mpc_t, long) */
   CCI_func_ptr CCI;   /* output: mpc_t, inputs: (mpc_t, int) */
   CCF_func_ptr CCF;   /* output: mpc_t, inputs: (mpc_t, mpfr_t) */
   CFC_func_ptr CFC;   /* output: mpc_t, inputs: (mpfr_t, mpc_t) */
   CUC_func_ptr CUC;   /* output: mpc_t, inputs: (unsigned long, mpc_t) */
   CUUC_func_ptr CUUC; /* output: mpc_t, inputs: (ulong, ulong, mpc_t) */
   CC_C_func_ptr CC_C;   /* outputs: (mpc_t, mpc_t), input: mpc_t */
} func_ptr;

/* the rounding mode is implicit */
typedef enum {
   FC,   /* output: mpfr_t, input: mpc_t */
   CC,   /* output: mpc_t, input: mpc_t */
   C_CC, /* output: mpc_t, inputs: (mpc_t, mpc_t) */
   CCCC, /* output: mpc_t, inputs: (mpc_t, mpc_t, mpc_t) */
   CCU,  /* output: mpc_t, inputs: (mpc_t, unsigned long) */
   CCS,  /* output: mpc_t, inputs: (mpc_t, long) */
   CCI,  /* output: mpc_t, inputs: (mpc_t, int) */
   CCF,  /* output: mpc_t, inputs: (mpc_t, mpfr_t) */
   CFC,  /* output: mpc_t, inputs: (mpfr_t, mpc_t) */
   CUC,  /* output: mpc_t, inputs: (unsigned long, mpc_t) */
   CUUC, /* output: mpc_t, inputs: (ulong, ulong, mpc_t) */
   CC_C  /* outputs: (mpc_t, mpc_t), input: mpc_t */
} func_type;

/* properties */
#define FUNC_PROP_NONE     0
#define FUNC_PROP_SYMETRIC 1

typedef struct
{
  func_ptr     pointer;
  func_type    type;
  const char * name;
  int          properties;
} mpc_function;

#define DECL_FUNC(_ftype, _fvar, _func)         \
  mpc_function _fvar;                           \
  _fvar.pointer._ftype = _func;                 \
  _fvar.type = _ftype;                          \
  _fvar.name = QUOTE (_func);                   \
  _fvar.properties = FUNC_PROP_NONE;


/* tgeneric(mpc_function, prec_min, prec_max, step, exp_max) checks rounding
 with random numbers:
 - with precision ranging from prec_min to prec_max with an increment of
   step,
 - with exponent between -exp_max and exp_max.

 It also checks parameter reuse (it is assumed here that either two mpc_t
 variables are equal or they are different, in the sense that the real part of
 one of them cannot be the imaginary part of the other). */
void tgeneric (mpc_function, mpfr_prec_t, mpfr_prec_t, mpfr_prec_t, mp_exp_t);


/** READ FILE WITH TEST DATA SET **/
/* data_check (function, "data_file_name") checks function results against
   precomputed data in a file.*/
extern void data_check (mpc_function, const char *);

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);

#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 */

#endif /* __MPC_TESTS_H */