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, 2020 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 */
|