xref: /netbsd/external/lgpl3/mpc/dist/tests/mpc-tests.h (revision aeacce61)
1 /* mpc-tests.h -- Tests helper functions.
2 
3 Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2020, 2022 INRIA
4 
5 This file is part of GNU MPC.
6 
7 GNU MPC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU Lesser General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 GNU MPC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15 more details.
16 
17 You should have received a copy of the GNU Lesser General Public License
18 along with this program. If not, see http://www.gnu.org/licenses/ .
19 */
20 
21 #ifndef __MPC_TESTS_H
22 #define __MPC_TESTS_H
23 
24 #include "config.h"
25 #include <stdio.h>
26 #include <ctype.h>
27 #include <stdlib.h>
28 #include <inttypes.h> /* for the PRIi64 format modifier */
29 #include "mpc-impl.h"
30 
31 /* pieces copied from mpc-impl.h */
32 #define MPC_PREC_RE(x) (mpfr_get_prec(mpc_realref(x)))
33 #define MPC_PREC_IM(x) (mpfr_get_prec(mpc_imagref(x)))
34 #define MPC_MAX_PREC(x) MPC_MAX(MPC_PREC_RE(x), MPC_PREC_IM(x))
35 #define MPC_MAX(h,i) ((h) > (i) ? (h) : (i))
36 
37 #define MPC_ASSERT(expr)                                        \
38   do {                                                          \
39     if (!(expr))                                                \
40       {                                                         \
41         fprintf (stderr, "%s:%d: MPC assertion failed: %s\n",   \
42                  __FILE__, __LINE__, #expr);                    \
43         abort();                                                \
44       }                                                         \
45   } while (0)
46 
47 #if defined (__cplusplus)
48 extern "C" {
49 #endif
50 __MPC_DECLSPEC int64_t sqrt_int64 (int64_t n);
51 __MPC_DECLSPEC int  mpc_mul_naive (mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t);
52 __MPC_DECLSPEC int  mpc_mul_karatsuba (mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t);
53 __MPC_DECLSPEC int  mpc_fma_naive (mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t);
54 #if defined (__cplusplus)
55 }
56 #endif
57 /* end pieces copied from mpc-impl.h */
58 
59 #define MPC_OUT(x)                                              \
60 do {                                                            \
61   printf (#x "[%lu,%lu]=", (unsigned long int) MPC_PREC_RE (x), \
62       (unsigned long int) MPC_PREC_IM (x));                     \
63   mpc_out_str (stdout, 2, 0, x, MPC_RNDNN);                     \
64   printf ("\n");                                                \
65 } while (0)
66 
67 #define MPFR_OUT(x)                                             \
68 do {                                                            \
69   printf (#x "[%lu]=", (unsigned long int) mpfr_get_prec (x));  \
70   mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN);                     \
71   printf ("\n");                                                \
72 } while (0)
73 
74 
75 #define MPC_INEX_STR(inex)                      \
76   (inex) == 0 ? "(0, 0)"                        \
77     : (inex) == 1 ? "(+1, 0)"                   \
78     : (inex) == 2 ? "(-1, 0)"                   \
79     : (inex) == 4 ? "(0, +1)"                   \
80     : (inex) == 5 ? "(+1, +1)"                  \
81     : (inex) == 6 ? "(-1, +1)"                  \
82     : (inex) == 8 ? "(0, -1)"                   \
83     : (inex) == 9 ? "(+1, -1)"                  \
84     : (inex) == 10 ? "(-1, -1)" : "unknown"
85 
86 #define TEST_FAILED(func,op,got,expected,rnd)			\
87   do {								\
88     printf ("%s(op) failed [rnd=%d]\n with", func, rnd);	\
89     MPC_OUT (op);						\
90     printf ("     ");						\
91     MPC_OUT (got);						\
92     MPC_OUT (expected);						\
93     exit (1);							\
94   } while (0)
95 
96 #define QUOTE(X) NAME(X)
97 #define NAME(X) #X
98 
99 /** RANDOM FUNCTIONS **/
100 /* the 3 following functions handle seed for random numbers. Usage:
101    - add test_start at the beginning of your test function
102    - use test_default_random (or use your random functions with
103    gmp_randstate_t rands) in your tests
104    - add test_end at the end the test function */
105 extern gmp_randstate_t  rands;
106 
107 extern void test_start (void);
108 extern void test_end   (void);
109 extern void test_default_random (mpc_ptr, mpfr_exp_t, mpfr_exp_t,
110                                  unsigned int, unsigned int);
111 
112 void test_random_si   (long int *n, unsigned long emax,
113                        unsigned int negative_probability);
114 void test_random_d    (double *x, unsigned int negative_probability);
115 void test_random_mpfr (mpfr_ptr x, mpfr_exp_t emin, mpfr_exp_t emax,
116                        unsigned int negative_probability);
117 void test_random_mpc  (mpc_ptr z, mpfr_exp_t emin, mpfr_exp_t emax,
118                        unsigned int negative_probability);
119 
120 /** COMPARISON FUNCTIONS **/
121 /* some sign are unspecified in ISO C99, thus we record in struct known_signs_t
122    whether the sign has to be checked */
123 typedef struct
124 {
125   int re;  /* boolean value */
126   int im;  /* boolean value */
127 } known_signs_t;
128 
129 /* same_mpfr_value returns 1:
130    - if got and ref have the same value and known_sign is true,
131    or
132    - if they have the same absolute value, got = 0 or got = inf, and known_sign is
133    false.
134    returns 0 in other cases.
135    Unlike mpfr_cmp, same_mpfr_value(got, ref, x) return 1 when got and
136    ref are both NaNs. */
137 extern int same_mpfr_value (mpfr_ptr got, mpfr_ptr ref, int known_sign);
138 extern int same_mpc_value  (mpc_ptr got, mpc_ptr ref,
139                             known_signs_t known_signs);
140 
141 /** READ FILE WITH TEST DATA SET **/
142 extern FILE * open_data_file         (const char *file_name);
143 extern void   close_data_file        (FILE *fp);
144 
145 /* helper file reading functions */
146 extern void skip_whitespace_comments (FILE *fp);
147 extern void read_ternary             (FILE *fp, int* ternary);
148 extern void read_mpfr_rounding_mode  (FILE *fp, mpfr_rnd_t* rnd);
149 extern void read_mpc_rounding_mode   (FILE *fp, mpc_rnd_t* rnd);
150 extern mpfr_prec_t read_mpfr_prec    (FILE *fp);
151 extern void read_int                 (FILE *fp, int *n, const char *name);
152 extern size_t read_string            (FILE *fp, char **buffer_ptr,
153                                       size_t buffer_length, const char *name);
154 extern void read_mpfr                (FILE *fp, mpfr_ptr x, int *known_sign);
155 extern void read_mpc                 (FILE *fp, mpc_ptr z, known_signs_t *ks);
156 
157 void set_mpfr_flags   (int counter);
158 void check_mpfr_flags (int counter);
159 
160 /*
161   function descriptions
162 */
163 
164 /* type for return, output and input parameters */
165 typedef enum {
166   NATIVE_INT,          /* int */
167   NATIVE_UL,           /* unsigned long */
168   NATIVE_L,            /* signed long */
169   NATIVE_D,            /* double */
170   NATIVE_LD,           /* long double */
171   NATIVE_DC,           /* double _Complex */
172   NATIVE_LDC,          /* long double _Complex */
173   NATIVE_IM,           /* intmax_t */
174   NATIVE_UIM,          /* uintmax_t */
175   NATIVE_STRING,       /* char* */
176   GMP_Z,               /* mpz_t */
177   GMP_Q,               /* mpq_t */
178   GMP_F,               /* mpf_t */
179   MPFR_INEX,           /* mpfr_inex */
180   MPFR,                /* mpfr_t  */
181   MPFR_RND,            /* mpfr_rnd_t */
182   MPC_INEX,            /* mpc_inex */
183   MPC,                 /* mpc_t */
184   MPC_RND,             /* mpc_rnd_t */
185   MPCC_INEX            /* mpcc_inex */
186 } mpc_param_t;
187 
188 /* additional information for checking mpfr_t result */
189 typedef struct {
190   mpfr_t              mpfr; /* skip space for the variable */
191   int                 known_sign;
192 } mpfr_data_t;
193 
194 #define TERNARY_NOT_CHECKED 255
195 /* special value to indicate that the ternary value is not checked */
196 #define TERNARY_ERROR 254
197 /* special value to indicate that an error occurred in an mpc function */
198 
199 /* mpc nonary value as a pair of ternary value for data from a file */
200 typedef struct {
201   int                real;
202   int                imag;
203 } mpc_inex_data_t;
204 
205 /* additional information for checking mpc_t result */
206 typedef struct {
207   mpc_t               mpc; /* skip space */
208   int                 known_sign_real;
209   int                 known_sign_imag;
210 } mpc_data_t;
211 
212 /* string buffer information */
213 typedef struct {
214   char*               string; /* skip space */
215   int                 length;
216 } string_info_t;
217 
218 /* abstract parameter type
219 
220    Let consider an abstract parameter p, which is declared as follows:
221    mpc_operand_t p;
222    we use the fact that a mpfr_t (respectively mpc_t) value can be accessed as
223    'p.mpfr' (resp. 'p.mpc') as well as 'p.mpfr_info.mpfr'
224    (resp. 'p.mpc_info.mpc'), the latter form permitting access to the
225    'known_sign' field(s).
226    Similarly, if the abstract parameter represent a string variable, we can
227    access its value with 'p.string' or 'p.string_info.string' and its size
228    with 'p.string_info.length'.
229 
230    The user uses the simple form when adding a test, the second form is used by the
231    test suite itself when reading reference data and checking result against them.
232 */
233 typedef union {
234   int                  i;
235   unsigned long        ui;
236   signed long          si;
237   double               d;
238   long double          ld;
239 #ifdef _MPC_H_HAVE_INTMAX_T
240   intmax_t             im;
241   uintmax_t            uim;
242 #endif
243 #ifdef _Complex_I
244   double _Complex      dc;
245   long double _Complex ldc;
246 #endif
247   char *               string;
248   string_info_t        string_info;
249   mpz_t                mpz;
250   mpq_t                mpq;
251   mpf_t                mpf;
252   mpfr_t               mpfr;
253   mpfr_data_t          mpfr_data;
254   mpfr_rnd_t           mpfr_rnd;
255   int                  mpfr_inex;
256   mpc_t                mpc;
257   mpc_data_t           mpc_data;
258   mpc_rnd_t            mpc_rnd;
259   int                  mpc_inex;
260   mpc_inex_data_t      mpc_inex_data;
261   int                  mpcc_inex;
262 } mpc_operand_t;
263 
264 #define PARAMETER_ARRAY_SIZE 10
265 
266 /* function name plus parameters in the following order:
267    output parameters, input parameters (ending with rounding modes).
268    The input parameters include one rounding mode per mpfr/mpc
269    output starting from rnd_index.
270    For the time being, there may be either one or two rounding modes;
271    in the latter case, we assume that there are three outputs:
272    the inexact value and two complex numbers.
273  */
274 typedef struct {
275   char         *name;  /* name of the function */
276   int           nbout; /* number of output parameters */
277   int           nbin;  /* number of input parameters, including rounding
278                           modes */
279   int           nbrnd; /* number of rounding mode parameters */
280   mpc_operand_t P[PARAMETER_ARRAY_SIZE]; /* value of parameters */
281   mpc_param_t   T[PARAMETER_ARRAY_SIZE]; /* type of parameters */
282 } mpc_fun_param_t;
283 
284 
285 void        read_description    (mpc_fun_param_t* param, const char *file);
286 const char* read_description_findname (mpc_param_t e);
287 
288 /* file functions */
289 typedef struct {
290   char *pathname;
291   FILE *fd;
292   unsigned long line_number;
293   unsigned long test_line_number;
294   int nextchar;
295 } mpc_datafile_context_t;
296 
297 void    open_datafile       (mpc_datafile_context_t* datafile_context,
298                              const char * data_filename);
299 void    close_datafile      (mpc_datafile_context_t *dc);
300 
301 /* data file functions */
302 void    read_line           (mpc_datafile_context_t* datafile_context,
303                              mpc_fun_param_t* params);
304 void    check_data          (mpc_datafile_context_t* datafile_context,
305                              mpc_fun_param_t* params,
306                              int index_reused_operand);
307 
308 /* parameters templated functions */
309 int     data_check_template (const char* descr_file, const char * data_file);
310 
311 void    init_parameters     (mpc_fun_param_t *params);
312 void    clear_parameters    (mpc_fun_param_t *params);
313 void    print_parameter     (mpc_fun_param_t *params, int index);
314 int     copy_parameter      (mpc_fun_param_t *params,
315                              int index_dest, int index_src);
316 
317 void    tpl_read_int        (mpc_datafile_context_t* datafile_context,
318                              int *nread, const char *name);
319 void    tpl_read_ui         (mpc_datafile_context_t* datafile_context,
320                              unsigned long int *ui);
321 void    tpl_read_si         (mpc_datafile_context_t* datafile_context,
322                              long int *si);
323 void    tpl_read_mpz        (mpc_datafile_context_t* datafile_context,
324                              mpz_t z);
325 void    tpl_skip_whitespace_comments (mpc_datafile_context_t* datafile_context);
326 void    tpl_read_ternary    (mpc_datafile_context_t* datafile_context,
327                              int* ternary);
328 void    tpl_read_mpfr       (mpc_datafile_context_t* datafile_context,
329                              mpfr_ptr x, int* known_sign);
330 void    tpl_read_mpfr_rnd   (mpc_datafile_context_t* datafile_context,
331                              mpfr_rnd_t* rnd);
332 void    tpl_read_mpfr_inex  (mpc_datafile_context_t* datafile_context,
333                              int *ternary);
334 void    tpl_read_mpc_inex   (mpc_datafile_context_t* datafile_context,
335                              mpc_inex_data_t* ternarypair);
336 void    tpl_read_mpc        (mpc_datafile_context_t* datafile_context,
337                              mpc_data_t* z);
338 void    tpl_read_mpc_rnd    (mpc_datafile_context_t* datafile_context,
339                              mpc_rnd_t* rnd);
340 
341 int     tpl_same_mpz_value  (mpz_ptr n1, mpz_ptr n2);
342 int     tpl_same_mpfr_value (mpfr_ptr x1, mpfr_ptr x2, int known_sign);
343 int     tpl_check_mpfr_data (mpfr_t got, mpfr_data_t expected);
344 int     tpl_check_mpc_data  (mpc_ptr got, mpc_data_t expected);
345 
346 void    tpl_copy_int        (int *dest, const int * const src);
347 void    tpl_copy_ui         (unsigned long int *dest,
348                              const unsigned long int * const src);
349 void    tpl_copy_si         (long int *dest, const long int * const src);
350 void    tpl_copy_d          (double *dest, const double * const src);
351 void    tpl_copy_mpz        (mpz_ptr dest, mpz_srcptr src);
352 void    tpl_copy_mpfr       (mpfr_ptr dest, mpfr_srcptr src);
353 void    tpl_copy_mpc        (mpc_ptr dest, mpc_srcptr src);
354 
355 int     double_rounding     (mpc_fun_param_t *params);
356 
357 /* iterating over rounding modes */
358 void    first_rnd_mode      (mpc_fun_param_t *params);
359 int     is_valid_rnd_mode   (mpc_fun_param_t *params);
360 void    next_rnd_mode       (mpc_fun_param_t *params);
361 
362 /* parameter precision */
363 void    set_output_precision    (mpc_fun_param_t *params, mpfr_prec_t prec);
364 void    set_input_precision     (mpc_fun_param_t *params, mpfr_prec_t prec);
365 void    set_reference_precision (mpc_fun_param_t *params, mpfr_prec_t prec);
366 
367 #endif /* __MPC_TESTS_H */
368