xref: /netbsd-src/external/lgpl3/mpc/dist/tests/tgeneric.tpl (revision 39f28e1e142c5bfb6be935a49cb55e2287fec7ea)
1/* tgeneric.tpl -- template file for generic tests.
2
3Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014 INRIA
4
5This file is part of GNU MPC.
6
7GNU MPC is free software; you can redistribute it and/or modify it under
8the terms of the GNU Lesser General Public License as published by the
9Free Software Foundation; either version 3 of the License, or (at your
10option) any later version.
11
12GNU MPC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15more details.
16
17You should have received a copy of the GNU Lesser General Public License
18along with this program. If not, see http://www.gnu.org/licenses/ .
19*/
20
21#ifndef MPC_FUNCTION_CALL
22#error Define MPC_FUNCTION_CALL before including 'data_check.tpl'.
23#endif
24
25/* helper functions, defined after tgeneric */
26static int  count_special_cases  (mpc_fun_param_t *params);
27static void random_params        (mpc_fun_param_t *params,
28                                  mpfr_exp_t exp_min, mpfr_exp_t exp_max,
29                                  int special);
30static void check_against_quadruple_precision (mpc_fun_param_t *params,
31                                               mpfr_prec_t prec,
32                                               mpfr_exp_t exp_min,
33                                               mpfr_exp_t exp_max,
34                                               int special);
35
36
37/* tgeneric(desc, prec_min, prec_max, step, exp_max) checks rounding with
38   random numbers:
39   - with precision ranging from prec_min to prec_max with an increment of
40   step,
41   - with exponent between -exp_max and exp_max.
42   - for pure real, pure imaginary and infinite random parameters.
43
44   It also checks parameter reuse.
45*/
46static void
47tgeneric_template (const char *description_file,
48                   mpfr_prec_t prec_min, mpfr_prec_t prec_max, mpfr_prec_t step,
49                   mpfr_exp_t exp_max)
50{
51  int special = 0;
52  int last_special;
53  mpfr_prec_t prec;
54  mpfr_exp_t exp_min;
55  mpc_fun_param_t params;
56
57  read_description (&params, description_file);
58  init_parameters (&params);
59
60  /* ask for enough memory */
61  set_output_precision (&params, 4 * prec_max);
62  set_input_precision (&params, prec_max);
63  set_reference_precision (&params, prec_max);
64
65  /* sanity checks */
66  exp_min = mpfr_get_emin ();
67  if (exp_max <= 0 || exp_max > mpfr_get_emax ())
68    exp_max = mpfr_get_emax();
69  if (-exp_max > exp_min)
70    exp_min = - exp_max;
71  if (step < 1)
72    step = 1;
73
74  /* check consistency with quadruple precision for random parameters */
75  for (prec = prec_min; prec <= prec_max; prec += step)
76    check_against_quadruple_precision (&params, prec, exp_min, exp_max, -1);
77
78  /* check consistency with quadruple precision for special values:
79     pure real, pure imaginary, or infinite arguments */
80  last_special = count_special_cases (&params);
81  for (special = 0; special < last_special ; special++)
82    check_against_quadruple_precision (&params, prec_max, exp_min, exp_max,
83                                       special);
84
85  clear_parameters (&params);
86}
87
88
89static void
90check_against_quadruple_precision (mpc_fun_param_t *params,
91                                   mpfr_prec_t prec,
92                                   mpfr_exp_t exp_min, mpfr_exp_t exp_max,
93                                   int special)
94{
95  static int rand_counter = 0;
96  mpc_operand_t *P = params->P; /* developer-friendly alias, used in macros */
97
98  set_input_precision (params, prec);
99  set_reference_precision (params, prec);
100
101  set_output_precision (params, 4 * prec);
102  random_params (params, exp_min, exp_max, special);
103
104  for (first_rnd_mode (params);
105       is_valid_rnd_mode (params);
106       next_rnd_mode (params))
107    {
108      MPC_FUNCTION_CALL;
109      while (double_rounding (params))
110        /* try another input parameters until no double rounding occurs when
111           the extra-precise result is rounded to working precision */
112        {
113          random_params (params, exp_min, exp_max, special);
114          MPC_FUNCTION_CALL;
115        }
116      set_output_precision (params, prec);
117
118      set_mpfr_flags (rand_counter);
119      MPC_FUNCTION_CALL;
120      check_mpfr_flags (rand_counter++);
121      check_data (NULL, params, 0);
122
123#ifdef MPC_FUNCTION_CALL_SYMMETRIC
124      MPC_FUNCTION_CALL_SYMMETRIC;
125      check_data (NULL, params, 0);
126#endif
127
128#ifdef MPC_FUNCTION_CALL_REUSE_OP1
129      if (copy_parameter (params, 1, 2) == 0)
130        {
131          MPC_FUNCTION_CALL_REUSE_OP1;
132          check_data (NULL, params, 2);
133        }
134#endif
135
136#ifdef MPC_FUNCTION_CALL_REUSE_OP2
137      if (copy_parameter (params, 1, 3) == 0)
138        {
139          MPC_FUNCTION_CALL_REUSE_OP2;
140          check_data (NULL, params, 3);
141        }
142#endif
143
144#ifdef MPC_FUNCTION_CALL_REUSE_OP3
145      if (copy_parameter (params, 1, 4) == 0)
146        {
147          MPC_FUNCTION_CALL_REUSE_OP3;
148          check_data (NULL, params, 4);
149        }
150#endif
151
152      set_output_precision (params, 4 * prec);
153    }
154}
155
156
157/* special cases */
158
159enum {
160  SPECIAL_MINF,
161  SPECIAL_MZERO,
162  SPECIAL_PZERO,
163  SPECIAL_PINF,
164  SPECIAL_COUNT
165};
166
167static int
168count_special_cases (mpc_fun_param_t *params)
169/* counts the number of possibilities of exactly one real or imaginary part of
170   any input parameter being special, all others being finite real numbers */
171{
172  int i;
173  const int start = params->nbout;
174  const int end = start + params->nbin - 1; /* the last input parameter is the
175                                               rounding mode */
176  int count = 0;
177
178  for (i = start; i < end; i++)
179    {
180      if (params->T[i] == MPFR)
181        count += SPECIAL_COUNT;
182      else if (params->T[i] == MPC)
183        /* special + i x random and random + i x special */
184        count += 2 * SPECIAL_COUNT;
185    }
186  return count;
187}
188
189static void
190special_mpfr (mpfr_ptr x, int special)
191{
192  switch (special)
193    {
194    case SPECIAL_MINF:
195      mpfr_set_inf (x, -1);
196      break;
197    case SPECIAL_MZERO:
198      mpfr_set_zero (x, -1);
199      break;
200    case SPECIAL_PZERO:
201      mpfr_set_zero (x, +1);
202      break;
203    case SPECIAL_PINF:
204      mpfr_set_inf (x, +1);
205      break;
206    case SPECIAL_COUNT:
207       /* does not occur */
208       break;
209   }
210}
211
212static void
213special_random_mpc (mpc_ptr z, mpfr_exp_t exp_min, mpfr_exp_t exp_max,
214                    int special)
215{
216  mpfr_ptr special_part;
217  mpfr_ptr random_part;
218  int mpfr_special;
219
220  if (special < SPECIAL_COUNT)
221    {
222      mpfr_special = special;
223      special_part = mpc_realref (z);
224      random_part  = mpc_imagref (z);
225    }
226  else
227    {
228      mpfr_special = special - SPECIAL_COUNT;
229      special_part = mpc_imagref (z);
230      random_part  = mpc_realref (z);
231    }
232
233  special_mpfr (special_part, mpfr_special);
234  test_random_mpfr (random_part, exp_min, exp_max, 128);
235}
236
237static void
238random_params (mpc_fun_param_t *params,
239               mpfr_exp_t exp_min, mpfr_exp_t exp_max,
240               int special)
241{
242  int i;
243  int base_index = 0;
244  const int start = params->nbout;
245  const int end = start + params->nbin;
246  const unsigned int int_emax = 42; /* maximum binary exponent for random
247                                       integer */
248
249  for (i = start; i < end; i++)
250    {
251      long int si;
252      switch (params->T[i])
253        {
254        case NATIVE_INT:
255          test_random_si (&si, int_emax, 128);
256          params->P[i].i = (int) si;
257          break;
258        case NATIVE_L:
259          test_random_si (&params->P[i].si, int_emax, 128);
260          break;
261        case NATIVE_UL:
262          test_random_si (&si, int_emax, 128);
263          params->P[i].ui = (unsigned long)si;
264          break;
265
266        case NATIVE_D:
267          test_random_d (&params->P[i].d, 128);
268          break;
269
270        case NATIVE_LD:
271        case NATIVE_DC:
272        case NATIVE_LDC:
273          /* TODO: draw random value */
274          fprintf (stderr, "random_params: type not implemented.\n");
275          exit (1);
276          break;
277
278        case NATIVE_IM:
279        case NATIVE_UIM:
280          /* TODO: draw random value */
281          fprintf (stderr, "random_params: type not implemented.\n");
282          exit (1);
283          break;
284
285        case GMP_Z:
286          /* TODO: draw random value */
287          fprintf (stderr, "random_params: type not implemented.\n");
288          exit (1);
289          break;
290        case GMP_Q:
291          /* TODO: draw random value */
292          fprintf (stderr, "random_params: type not implemented.\n");
293          exit (1);
294          break;
295        case GMP_F:
296          /* TODO: draw random value */
297          fprintf (stderr, "random_params: type not implemented.\n");
298          exit (1);
299          break;
300
301        case MPFR:
302          if (base_index <= special
303              && special - base_index < SPECIAL_COUNT)
304            special_mpfr (params->P[i].mpfr, special - base_index);
305          else
306            test_random_mpfr (params->P[i].mpfr, exp_min, exp_max, 128);
307          base_index += SPECIAL_COUNT;
308          break;
309
310        case MPC:
311          if (base_index <= special
312              && special - base_index < 2 * SPECIAL_COUNT)
313            special_random_mpc (params->P[i].mpc, exp_min, exp_max,
314                                special - base_index);
315          else
316            test_random_mpc (params->P[i].mpc, exp_min, exp_max, 128);
317          base_index += 2 * SPECIAL_COUNT;
318          break;
319
320        case NATIVE_STRING:
321        case MPFR_INEX:
322        case MPC_INEX:
323        case MPCC_INEX:
324          /* unsupported types */
325          fprintf (stderr, "random_params: unsupported type.\n");
326          exit (1);
327          break;
328
329        case MPFR_RND:
330        case MPC_RND:
331          /* just skip rounding mode(s) */
332          break;
333        }
334    }
335}
336