1/* tgeneric.c -- File for generic tests.
2
3Copyright (C) 2008, 2009, 2010, 2011, 2012 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#include "mpc-tests.h"
22
23/* Warning: unlike the MPFR macro (defined in mpfr-impl.h), this one returns
24   true when b is singular */
25#define MPFR_CAN_ROUND(b,err,prec,rnd)                                  \
26  (mpfr_zero_p (b) || mpfr_inf_p (b)                                    \
27   || mpfr_can_round (b, (long)mpfr_get_prec (b) - (err), (rnd),        \
28                      GMP_RNDZ, (prec) + ((rnd)==GMP_RNDN)))
29
30/* functions with one input, one output */
31static void
32tgeneric_cc (mpc_function *function, mpc_ptr op, mpc_ptr rop,
33             mpc_ptr rop4, mpc_ptr rop4rnd, mpc_rnd_t rnd)
34{
35  known_signs_t ks = {1, 1};
36
37  /* We compute the result with four times the precision and check whether the
38     rounding is correct. Error reports in this part of the algorithm might
39     still be wrong, though, since there are two consecutive roundings (but we
40     try to avoid them).  */
41  function->pointer.CC (rop4, op, rnd);
42  function->pointer.CC (rop, op, rnd);
43
44  /* can't use the mpfr_can_round function when argument is singular,
45     use a custom macro instead. */
46  if (MPFR_CAN_ROUND (mpc_realref (rop4), 1, MPC_PREC_RE (rop),
47                      MPC_RND_RE (rnd))
48      && MPFR_CAN_ROUND (mpc_imagref (rop4), 1, MPC_PREC_IM (rop),
49                         MPC_RND_IM (rnd)))
50    mpc_set (rop4rnd, rop4, rnd);
51  else
52    /* avoid double rounding error */
53    return;
54
55  if (same_mpc_value (rop, rop4rnd, ks))
56    return;
57
58  /* rounding failed */
59  printf ("Rounding in %s might be incorrect for\n", function->name);
60  MPC_OUT (op);
61
62  printf ("with rounding mode (%s, %s)",
63          mpfr_print_rnd_mode (MPC_RND_RE (rnd)),
64          mpfr_print_rnd_mode (MPC_RND_IM (rnd)));
65
66  printf ("\n%s                     gives ", function->name);
67  MPC_OUT (rop);
68  printf ("%s quadruple precision gives ", function->name);
69  MPC_OUT (rop4);
70  printf ("and is rounded to                  ");
71  MPC_OUT (rop4rnd);
72
73  exit (1);
74}
75
76static void
77tgeneric_cc_c (mpc_function *function, mpc_ptr op, mpc_ptr rop1, mpc_ptr rop2,
78   mpc_ptr rop14, mpc_ptr rop24, mpc_ptr rop14rnd, mpc_ptr rop24rnd,
79   mpc_rnd_t rnd1, mpc_rnd_t rnd2)
80{
81   /* same as the previous function, but for mpc functions computing two
82      results from one argument                                          */
83   known_signs_t ks = {1, 1};
84
85   function->pointer.CC_C (rop14, rop24, op, rnd1, rnd2);
86   function->pointer.CC_C (rop1,  rop2,  op, rnd1, rnd2);
87
88   if (   MPFR_CAN_ROUND (mpc_realref (rop14), 1, MPC_PREC_RE (rop1),
89                          MPC_RND_RE (rnd1))
90       && MPFR_CAN_ROUND (mpc_imagref (rop14), 1, MPC_PREC_IM (rop1),
91                          MPC_RND_IM (rnd1))
92       && MPFR_CAN_ROUND (mpc_realref (rop24), 1, MPC_PREC_RE (rop2),
93                          MPC_RND_RE (rnd2))
94       && MPFR_CAN_ROUND (mpc_imagref (rop24), 1, MPC_PREC_IM (rop2),
95                          MPC_RND_IM (rnd2))) {
96     mpc_set (rop14rnd, rop14, rnd1);
97     mpc_set (rop24rnd, rop24, rnd2);
98   }
99   else
100     return;
101
102   if (!same_mpc_value (rop1, rop14rnd, ks)) {
103      /* rounding failed for first result */
104      printf ("Rounding might be incorrect for the first result of %s at\n", function->name);
105      MPC_OUT (op);
106      printf ("with rounding mode (%s, %s)",
107          mpfr_print_rnd_mode (MPC_RND_RE (rnd1)),
108          mpfr_print_rnd_mode (MPC_RND_IM (rnd1)));
109      printf ("\n%s                     gives ", function->name);
110      MPC_OUT (rop1);
111      printf ("%s quadruple precision gives ", function->name);
112      MPC_OUT (rop14);
113      printf ("and is rounded to                  ");
114      MPC_OUT (rop14rnd);
115      exit (1);
116   }
117   else if (!same_mpc_value (rop2, rop24rnd, ks)) {
118      /* rounding failed for second result */
119      printf ("Rounding might be incorrect for the second result of %s at\n", function->name);
120      MPC_OUT (op);
121      printf ("with rounding mode (%s, %s)",
122          mpfr_print_rnd_mode (MPC_RND_RE (rnd2)),
123          mpfr_print_rnd_mode (MPC_RND_IM (rnd2)));
124      printf ("\n%s                     gives ", function->name);
125      MPC_OUT (rop2);
126      printf ("%s quadruple precision gives ", function->name);
127      MPC_OUT (rop24);
128      printf ("and is rounded to                  ");
129      MPC_OUT (rop24rnd);
130      exit (1);
131   }
132}
133
134static void
135tgeneric_fc (mpc_function *function, mpc_ptr op, mpfr_ptr rop,
136             mpfr_ptr rop4, mpfr_ptr rop4rnd, mpfr_rnd_t rnd)
137{
138  function->pointer.FC (rop4, op, rnd);
139  function->pointer.FC (rop, op, rnd);
140  if (MPFR_CAN_ROUND (rop4, 1, mpfr_get_prec (rop), rnd))
141    mpfr_set (rop4rnd, rop4, rnd);
142  else
143    return;
144
145  if (same_mpfr_value (rop, rop4rnd, 1))
146    return;
147
148  printf ("Rounding in %s might be incorrect for\n", function->name);
149  MPC_OUT (op);
150  printf ("with rounding mode %s", mpfr_print_rnd_mode (rnd));
151
152  printf ("\n%s                     gives ", function->name);
153  MPFR_OUT (rop);
154  printf ("%s quadruple precision gives ", function->name);
155  MPFR_OUT (rop4);
156  printf ("and is rounded to                  ");
157  MPFR_OUT (rop4rnd);
158
159  exit (1);
160}
161
162static void
163tgeneric_cfc (mpc_function *function, mpfr_ptr op1, mpc_ptr op2,
164              mpc_ptr rop, mpc_ptr rop4, mpc_ptr rop4rnd, mpc_rnd_t rnd)
165{
166  known_signs_t ks = {1, 1};
167
168  function->pointer.CFC (rop4, op1, op2, rnd);
169  function->pointer.CFC (rop, op1, op2, rnd);
170  if (MPFR_CAN_ROUND (mpc_realref (rop4), 1, MPC_PREC_RE (rop),
171                      MPC_RND_RE (rnd))
172      && MPFR_CAN_ROUND (mpc_imagref (rop4), 1, MPC_PREC_IM (rop),
173                         MPC_RND_IM (rnd)))
174    mpc_set (rop4rnd, rop4, rnd);
175  else
176    return;
177
178  if (same_mpc_value (rop, rop4rnd, ks))
179    return;
180
181  printf ("Rounding in %s might be incorrect for\n", function->name);
182  MPFR_OUT (op1);
183  MPC_OUT (op2);
184  printf ("with rounding mode (%s, %s)",
185          mpfr_print_rnd_mode (MPC_RND_RE (rnd)),
186          mpfr_print_rnd_mode (MPC_RND_IM (rnd)));
187
188  printf ("\n%s                     gives ", function->name);
189  MPC_OUT (rop);
190  printf ("%s quadruple precision gives ", function->name);
191  MPC_OUT (rop4);
192  printf ("and is rounded to                  ");
193  MPC_OUT (rop4rnd);
194
195  exit (1);
196}
197
198static void
199tgeneric_ccf (mpc_function *function, mpc_ptr op1, mpfr_ptr op2,
200              mpc_ptr rop, mpc_ptr rop4, mpc_ptr rop4rnd, mpc_rnd_t rnd)
201{
202  known_signs_t ks = {1, 1};
203
204  function->pointer.CCF (rop4, op1, op2, rnd);
205  function->pointer.CCF (rop, op1, op2, rnd);
206  if (MPFR_CAN_ROUND (mpc_realref (rop4), 1, MPC_PREC_RE (rop),
207                      MPC_RND_RE (rnd))
208      && MPFR_CAN_ROUND (mpc_imagref (rop4), 1, MPC_PREC_IM (rop),
209                         MPC_RND_IM (rnd)))
210    mpc_set (rop4rnd, rop4, rnd);
211  else
212    return;
213
214  if (same_mpc_value (rop, rop4rnd, ks))
215    return;
216
217  printf ("Rounding in %s might be incorrect for\n", function->name);
218  MPC_OUT (op1);
219  MPFR_OUT (op2);
220  printf ("with rounding mode (%s, %s)",
221          mpfr_print_rnd_mode (MPC_RND_RE (rnd)),
222          mpfr_print_rnd_mode (MPC_RND_IM (rnd)));
223
224  printf ("\n%s                     gives ", function->name);
225  MPC_OUT (rop);
226  printf ("%s quadruple precision gives ", function->name);
227  MPC_OUT (rop4);
228  printf ("and is rounded to                  ");
229  MPC_OUT (rop4rnd);
230
231  exit (1);
232}
233
234/* for functions with one mpc_t output, two mpc_t inputs */
235static void
236tgeneric_c_cc (mpc_function *function, mpc_ptr op1, mpc_ptr op2,
237	       mpc_ptr rop, mpc_ptr rop4, mpc_ptr rop4rnd, mpc_rnd_t rnd)
238{
239  known_signs_t ks = {1, 1};
240
241  /* We compute the result with four times the precision and check whether the
242     rounding is correct. Error reports in this part of the algorithm might
243     still be wrong, though, since there are two consecutive roundings (but we
244     try to avoid them).  */
245  function->pointer.C_CC (rop4, op1, op2, rnd);
246  function->pointer.C_CC (rop, op1, op2, rnd);
247
248  /* can't use mpfr_can_round when argument is singular */
249  if (MPFR_CAN_ROUND (mpc_realref (rop4), 1, MPC_PREC_RE (rop),
250                      MPC_RND_RE (rnd))
251      && MPFR_CAN_ROUND (mpc_imagref (rop4), 1, MPC_PREC_IM (rop),
252                         MPC_RND_IM (rnd)))
253    mpc_set (rop4rnd, rop4, rnd);
254  else
255    /* avoid double rounding error */
256    return;
257
258  if (same_mpc_value (rop, rop4rnd, ks))
259    return;
260
261  /* rounding failed */
262  printf ("Rounding in %s might be incorrect for\n", function->name);
263  MPC_OUT (op1);
264  MPC_OUT (op2);
265  printf ("with rounding mode (%s, %s)",
266          mpfr_print_rnd_mode (MPC_RND_RE (rnd)),
267          mpfr_print_rnd_mode (MPC_RND_IM (rnd)));
268
269  printf ("\n%s                     gives ", function->name);
270  MPC_OUT (rop);
271  printf ("%s quadruple precision gives ", function->name);
272  MPC_OUT (rop4);
273  printf ("and is rounded to                  ");
274  MPC_OUT (rop4rnd);
275
276  exit (1);
277}
278
279static void
280tgeneric_cccc (mpc_function *function, mpc_ptr op1, mpc_ptr op2, mpc_ptr op3,
281              mpc_ptr rop, mpc_ptr rop4, mpc_ptr rop4rnd, mpc_rnd_t rnd)
282{
283  known_signs_t ks = {1, 1};
284
285  /* We compute the result with four times the precision and check whether the
286     rounding is correct. Error reports in this part of the algorithm might
287     still be wrong, though, since there are two consecutive roundings (but we
288     try to avoid them).  */
289  function->pointer.CCCC (rop4, op1, op2, op3, rnd);
290  function->pointer.CCCC (rop, op1, op2, op3, rnd);
291
292  /* can't use mpfr_can_round when argument is singular */
293  if (MPFR_CAN_ROUND (mpc_realref (rop4), 1, MPC_PREC_RE (rop),
294                      MPC_RND_RE (rnd))
295      && MPFR_CAN_ROUND (mpc_imagref (rop4), 1, MPC_PREC_IM (rop),
296                         MPC_RND_IM (rnd)))
297    mpc_set (rop4rnd, rop4, rnd);
298  else
299    /* avoid double rounding error */
300    return;
301
302  if (same_mpc_value (rop, rop4rnd, ks))
303    return;
304
305  /* rounding failed */
306  printf ("Rounding in %s might be incorrect for\n", function->name);
307  MPC_OUT (op1);
308  MPC_OUT (op2);
309  MPC_OUT (op3);
310  printf ("with rounding mode (%s, %s)",
311          mpfr_print_rnd_mode (MPC_RND_RE (rnd)),
312          mpfr_print_rnd_mode (MPC_RND_IM (rnd)));
313
314  printf ("\n%s                     gives ", function->name);
315  MPC_OUT (rop);
316  printf ("%s quadruple precision gives ", function->name);
317  MPC_OUT (rop4);
318  printf ("and is rounded to                  ");
319  MPC_OUT (rop4rnd);
320
321  exit (1);
322}
323
324static void
325tgeneric_ccu (mpc_function *function, mpc_ptr op1, unsigned long int op2,
326              mpc_ptr rop, mpc_ptr rop4, mpc_ptr rop4rnd, mpc_rnd_t rnd)
327{
328  known_signs_t ks = {1, 1};
329
330  function->pointer.CCU (rop4, op1, op2, rnd);
331  function->pointer.CCU (rop, op1, op2, rnd);
332  if (MPFR_CAN_ROUND (mpc_realref (rop4), 1, MPC_PREC_RE (rop),
333                      MPC_RND_RE (rnd))
334      && MPFR_CAN_ROUND (mpc_imagref (rop4), 1, MPC_PREC_IM (rop),
335                         MPC_RND_IM (rnd)))
336    mpc_set (rop4rnd, rop4, rnd);
337  else
338    return;
339
340  if (same_mpc_value (rop, rop4rnd, ks))
341    return;
342
343  printf ("Rounding in %s might be incorrect for\n", function->name);
344  MPC_OUT (op1);
345  printf ("op2=%lu\n", op2);
346  printf ("with rounding mode (%s, %s)",
347          mpfr_print_rnd_mode (MPC_RND_RE (rnd)),
348          mpfr_print_rnd_mode (MPC_RND_IM (rnd)));
349
350  printf ("\n%s                     gives ", function->name);
351  MPC_OUT (rop);
352  printf ("%s quadruple precision gives ", function->name);
353  MPC_OUT (rop4);
354  printf ("and is rounded to                  ");
355  MPC_OUT (rop4rnd);
356
357  exit (1);
358}
359
360static void
361tgeneric_cuc (mpc_function *function, unsigned long int op1, mpc_ptr op2,
362              mpc_ptr rop, mpc_ptr rop4, mpc_ptr rop4rnd, mpc_rnd_t rnd)
363{
364  known_signs_t ks = {1, 1};
365
366  function->pointer.CUC (rop4, op1, op2, rnd);
367  function->pointer.CUC (rop, op1, op2, rnd);
368  if (MPFR_CAN_ROUND (mpc_realref (rop4), 1, MPC_PREC_RE (rop),
369                      MPC_RND_RE (rnd))
370      && MPFR_CAN_ROUND (mpc_imagref (rop4), 1, MPC_PREC_IM (rop),
371                         MPC_RND_IM (rnd)))
372    mpc_set (rop4rnd, rop4, rnd);
373  else
374    return;
375
376  if (same_mpc_value (rop, rop4rnd, ks))
377    return;
378
379  printf ("Rounding in %s might be incorrect for\n", function->name);
380  printf ("op1=%lu\n", op1);
381  MPC_OUT (op2);
382  printf ("with rounding mode (%s, %s)",
383          mpfr_print_rnd_mode (MPC_RND_RE (rnd)),
384          mpfr_print_rnd_mode (MPC_RND_IM (rnd)));
385
386  printf ("\n%s                     gives ", function->name);
387  MPC_OUT (rop);
388  printf ("%s quadruple precision gives ", function->name);
389  MPC_OUT (rop4);
390  printf ("and is rounded to                  ");
391  MPC_OUT (rop4rnd);
392
393  exit (1);
394}
395
396static void
397tgeneric_ccs (mpc_function *function, mpc_ptr op1, long int op2,
398              mpc_ptr rop, mpc_ptr rop4, mpc_ptr rop4rnd, mpc_rnd_t rnd)
399{
400  known_signs_t ks = {1, 1};
401
402  function->pointer.CCS (rop4, op1, op2, rnd);
403  function->pointer.CCS (rop, op1, op2, rnd);
404  if (MPFR_CAN_ROUND (mpc_realref (rop4), 1, MPC_PREC_RE (rop),
405                      MPC_RND_RE (rnd))
406      && MPFR_CAN_ROUND (mpc_imagref (rop4), 1, MPC_PREC_IM (rop),
407                         MPC_RND_IM (rnd)))
408    mpc_set (rop4rnd, rop4, rnd);
409  else
410    return;
411
412  if (same_mpc_value (rop, rop4rnd, ks))
413    return;
414
415  printf ("Rounding in %s might be incorrect for\n", function->name);
416  MPC_OUT (op1);
417  printf ("op2=%ld\n", op2);
418  printf ("with rounding mode (%s, %s)",
419          mpfr_print_rnd_mode (MPC_RND_RE (rnd)),
420          mpfr_print_rnd_mode (MPC_RND_IM (rnd)));
421
422  printf ("\n%s                     gives ", function->name);
423  MPC_OUT (rop);
424  printf ("%s quadruple precision gives ", function->name);
425  MPC_OUT (rop4);
426  printf ("and is rounded to                  ");
427  MPC_OUT (rop4rnd);
428
429  exit (1);
430}
431
432
433static void
434tgeneric_cci (mpc_function *function, mpc_ptr op1, int op2,
435              mpc_ptr rop, mpc_ptr rop4, mpc_ptr rop4rnd, mpc_rnd_t rnd)
436{
437  known_signs_t ks = {1, 1};
438
439  function->pointer.CCI (rop4, op1, op2, rnd);
440  function->pointer.CCI (rop, op1, op2, rnd);
441  if (MPFR_CAN_ROUND (mpc_realref (rop4), 1, MPC_PREC_RE (rop),
442                      MPC_RND_RE (rnd))
443      && MPFR_CAN_ROUND (mpc_imagref (rop4), 1, MPC_PREC_IM (rop),
444                         MPC_RND_IM (rnd)))
445    mpc_set (rop4rnd, rop4, rnd);
446  else
447    return;
448
449  if (same_mpc_value (rop, rop4rnd, ks))
450    return;
451
452  printf ("Rounding in %s might be incorrect for\n", function->name);
453  MPC_OUT (op1);
454  printf ("op2=%d\n", op2);
455  printf ("with rounding mode (%s, %s)",
456          mpfr_print_rnd_mode (MPC_RND_RE (rnd)),
457          mpfr_print_rnd_mode (MPC_RND_IM (rnd)));
458
459  printf ("\n%s                     gives ", function->name);
460  MPC_OUT (rop);
461  printf ("%s quadruple precision gives ", function->name);
462  MPC_OUT (rop4);
463  printf ("and is rounded to                  ");
464  MPC_OUT (rop4rnd);
465
466  exit (1);
467}
468
469static void
470tgeneric_cuuc (mpc_function *function, unsigned long int op1,
471               unsigned long int op2, mpc_ptr op3, mpc_ptr rop,
472               mpc_ptr rop4, mpc_ptr rop4rnd, mpc_rnd_t rnd)
473{
474  known_signs_t ks = {1, 1};
475
476  function->pointer.CUUC (rop4, op1, op2, op3, rnd);
477  function->pointer.CUUC (rop, op1, op2, op3, rnd);
478  if (MPFR_CAN_ROUND (mpc_realref (rop4), 1, MPC_PREC_RE (rop),
479                      MPC_RND_RE (rnd))
480      && MPFR_CAN_ROUND (mpc_imagref (rop4), 1, MPC_PREC_IM (rop),
481                         MPC_RND_IM (rnd)))
482    mpc_set (rop4rnd, rop4, rnd);
483  else
484    return;
485
486  if (same_mpc_value (rop, rop4rnd, ks))
487    return;
488
489  printf ("Rounding in %s might be incorrect for\n", function->name);
490  printf ("op1=%lu\n", op1);
491  printf ("op2=%lu\n", op2);
492  MPC_OUT (op3);
493  printf ("with rounding mode (%s, %s)",
494          mpfr_print_rnd_mode (MPC_RND_RE (rnd)),
495          mpfr_print_rnd_mode (MPC_RND_IM (rnd)));
496
497  printf ("\n%s                     gives ", function->name);
498  MPC_OUT (rop);
499  printf ("%s quadruple precision gives ", function->name);
500  MPC_OUT (rop4);
501  printf ("and is rounded to                  ");
502  MPC_OUT (rop4rnd);
503
504  exit (1);
505}
506
507
508/* Test parameter reuse: the function should not use its output parameter in
509   internal computations. */
510static void
511reuse_cc (mpc_function* function, mpc_srcptr z, mpc_ptr got, mpc_ptr expected)
512{
513  known_signs_t ks = {1, 1};
514
515  mpc_set (got, z, MPC_RNDNN); /* exact */
516  function->pointer.CC (expected, z, MPC_RNDNN);
517  function->pointer.CC (got, got, MPC_RNDNN);
518  if (!same_mpc_value (got, expected, ks))
519    {
520      printf ("Reuse error for %s(z, z) for\n", function->name);
521      MPC_OUT (z);
522      MPC_OUT (expected);
523      MPC_OUT (got);
524
525      exit (1);
526    }
527}
528
529static void
530reuse_cc_c (mpc_function* function, mpc_srcptr z, mpc_ptr got1, mpc_ptr got2,
531            mpc_ptr exp1, mpc_ptr exp2)
532{
533   known_signs_t ks = {1, 1};
534
535   function->pointer.CC_C (exp1, exp2, z, MPC_RNDNN, MPC_RNDNN);
536   mpc_set (got1, z, MPC_RNDNN); /* exact */
537   function->pointer.CC_C (got1, got2, got1, MPC_RNDNN, MPC_RNDNN);
538   if (   !same_mpc_value (got1, exp1, ks)
539       || !same_mpc_value (got2, exp2, ks)) {
540      printf ("Reuse error in first result of %s for\n", function->name);
541      MPC_OUT (z);
542      MPC_OUT (exp1);
543      MPC_OUT (got1);
544      MPC_OUT (exp2);
545      MPC_OUT (got2);
546      exit (1);
547   }
548   mpc_set (got2, z, MPC_RNDNN); /* exact */
549   function->pointer.CC_C (got1, got2, got2, MPC_RNDNN, MPC_RNDNN);
550   if (   !same_mpc_value (got1, exp1, ks)
551       || !same_mpc_value (got2, exp2, ks)) {
552      printf ("Reuse error in second result of %s for\n", function->name);
553      MPC_OUT (z);
554      MPC_OUT (exp1);
555      MPC_OUT (got1);
556      MPC_OUT (exp2);
557      MPC_OUT (got2);
558      exit (1);
559   }
560}
561
562static void
563reuse_fc (mpc_function* function, mpc_ptr z, mpc_ptr x, mpfr_ptr expected)
564{
565  mpc_set (x, z, MPC_RNDNN); /* exact */
566  function->pointer.FC (expected, z, GMP_RNDN);
567  function->pointer.FC (mpc_realref (x), x, GMP_RNDN);
568  if (!same_mpfr_value (mpc_realref (x), expected, 1))
569    {
570      mpfr_t got;
571      got[0] = mpc_realref(x)[0]; /* display sensible name */
572      printf ("Reuse error for %s(mpc_realref(z), z) for\n", function->name);
573      MPC_OUT (z);
574      MPFR_OUT (expected);
575      MPFR_OUT (got);
576
577      exit (1);
578    }
579  mpc_set (x, z, MPC_RNDNN); /* exact */
580  function->pointer.FC (mpc_imagref (x), x, GMP_RNDN);
581  if (!same_mpfr_value (mpc_imagref (x), expected, 1))
582    {
583      mpfr_t got;
584      got[0] = mpc_imagref(x)[0]; /* display sensible name */
585      printf ("Reuse error for %s(mpc_imagref(z), z) for \n", function->name);
586      MPC_OUT (z);
587      MPFR_OUT (expected);
588      MPFR_OUT (got);
589
590      exit (1);
591    }
592}
593
594static void
595reuse_cfc (mpc_function* function, mpc_srcptr z, mpfr_srcptr x, mpc_ptr got,
596           mpc_ptr expected)
597{
598  known_signs_t ks = {1, 1};
599
600  mpc_set (got, z, MPC_RNDNN); /* exact */
601  function->pointer.CFC (expected, x, z, MPC_RNDNN);
602  function->pointer.CFC (got, x, got, MPC_RNDNN);
603  if (!same_mpc_value (got, expected, ks))
604    {
605      printf ("Reuse error for %s(z, x, z) for\n", function->name);
606      MPFR_OUT (x);
607      MPC_OUT (z);
608      MPC_OUT (expected);
609      MPC_OUT (got);
610
611      exit (1);
612    }
613}
614
615static void
616reuse_ccf (mpc_function* function, mpc_srcptr z, mpfr_srcptr x, mpc_ptr got,
617           mpc_ptr expected)
618{
619  known_signs_t ks = {1, 1};
620
621  mpc_set (got, z, MPC_RNDNN); /* exact */
622  function->pointer.CCF (expected, z, x, MPC_RNDNN);
623  function->pointer.CCF (got, got, x, MPC_RNDNN);
624  if (!same_mpc_value (got, expected, ks))
625    {
626      printf ("Reuse error for %s(z, z, x, RNDNN) for\n", function->name);
627      MPC_OUT (z);
628      MPFR_OUT (x);
629      MPC_OUT (expected);
630      MPC_OUT (got);
631
632      exit (1);
633    }
634}
635
636/* for functions with one mpc_t output, two mpc_t inputs */
637static void
638reuse_c_cc (mpc_function* function, mpc_srcptr z, mpc_srcptr x,
639           mpc_ptr got, mpc_ptr expected)
640{
641  known_signs_t ks = {1, 1};
642
643  mpc_set (got, z, MPC_RNDNN); /* exact */
644  function->pointer.C_CC (expected, z, x, MPC_RNDNN);
645  function->pointer.C_CC (got, got, x, MPC_RNDNN);
646  if (!same_mpc_value (got, expected, ks))
647    {
648      printf ("Reuse error for %s(z, z, x) for\n", function->name);
649      MPC_OUT (z);
650      MPC_OUT (x);
651      MPC_OUT (expected);
652      MPC_OUT (got);
653
654      exit (1);
655    }
656  mpc_set (got, x, MPC_RNDNN); /* exact */
657  function->pointer.C_CC (expected, z, x, MPC_RNDNN);
658  function->pointer.C_CC (got, z, got, MPC_RNDNN);
659  if (!same_mpc_value (got, expected, ks))
660    {
661      printf ("Reuse error for %s(x, z, x) for\n", function->name);
662      MPC_OUT (z);
663      MPC_OUT (x);
664      MPC_OUT (expected);
665      MPC_OUT (got);
666
667      exit (1);
668    }
669  mpc_set (got, x, MPC_RNDNN); /* exact */
670  function->pointer.C_CC (expected, x, x, MPC_RNDNN);
671  function->pointer.C_CC (got, got, got, MPC_RNDNN);
672  if (!same_mpc_value (got, expected, ks))
673    {
674      printf ("Reuse error for %s(x, x, x) for\n", function->name);
675      MPC_OUT (x);
676      MPC_OUT (expected);
677      MPC_OUT (got);
678
679      exit (1);
680    }
681}
682
683static void
684reuse_cccc (mpc_function* function, mpc_srcptr z, mpc_srcptr x, mpc_srcptr y,
685	    mpc_ptr got, mpc_ptr expected)
686{
687  known_signs_t ks = {1, 1};
688
689  mpc_set (got, z, MPC_RNDNN); /* exact */
690  function->pointer.CCCC (expected, z, x, y, MPC_RNDNN);
691  function->pointer.CCCC (got, got, x, y, MPC_RNDNN);
692  if (!same_mpc_value (got, expected, ks))
693    {
694      printf ("Reuse error for %s(z, z, x, y) for\n", function->name);
695      MPC_OUT (z);
696      MPC_OUT (x);
697      MPC_OUT (y);
698      MPC_OUT (expected);
699      MPC_OUT (got);
700
701      exit (1);
702    }
703
704  mpc_set (got, x, MPC_RNDNN); /* exact */
705  function->pointer.CCCC (expected, z, x, y, MPC_RNDNN);
706  function->pointer.CCCC (got, z, got, y, MPC_RNDNN);
707  if (!same_mpc_value (got, expected, ks))
708    {
709      printf ("Reuse error for %s(x, z, x, y) for\n", function->name);
710      MPC_OUT (z);
711      MPC_OUT (x);
712      MPC_OUT (y);
713      MPC_OUT (expected);
714      MPC_OUT (got);
715
716      exit (1);
717    }
718
719  mpc_set (got, y, MPC_RNDNN); /* exact */
720  function->pointer.CCCC (expected, z, x, y, MPC_RNDNN);
721  function->pointer.CCCC (got, z, x, got, MPC_RNDNN);
722  if (!same_mpc_value (got, expected, ks))
723    {
724      printf ("Reuse error for %s(y, z, x, y) for\n", function->name);
725      MPC_OUT (z);
726      MPC_OUT (x);
727      MPC_OUT (y);
728      MPC_OUT (expected);
729      MPC_OUT (got);
730
731      exit (1);
732    }
733
734  mpc_set (got, x, MPC_RNDNN); /* exact */
735  function->pointer.CCCC (expected, x, x, x, MPC_RNDNN);
736  function->pointer.CCCC (got, got, got, got, MPC_RNDNN);
737  if (!same_mpc_value (got, expected, ks))
738    {
739      printf ("Reuse error for %s(x, x, x, x) for\n", function->name);
740      MPC_OUT (x);
741      MPC_OUT (expected);
742      MPC_OUT (got);
743
744      exit (1);
745    }
746}
747
748static void
749reuse_ccu (mpc_function* function, mpc_srcptr z, unsigned long ul,
750           mpc_ptr got, mpc_ptr expected)
751{
752  known_signs_t ks = {1, 1};
753
754  mpc_set (got, z, MPC_RNDNN); /* exact */
755  function->pointer.CCU (expected, z, ul, MPC_RNDNN);
756  function->pointer.CCU (got, got, ul, MPC_RNDNN);
757  if (!same_mpc_value (got, expected, ks))
758    {
759      printf ("Reuse error for %s(z, z, n) for\n", function->name);
760      MPC_OUT (z);
761      printf ("n=%lu\n", ul);
762      MPC_OUT (expected);
763      MPC_OUT (got);
764
765      exit (1);
766    }
767}
768
769static void
770reuse_cuc (mpc_function* function, unsigned long ul, mpc_srcptr z,
771           mpc_ptr got, mpc_ptr expected)
772{
773  known_signs_t ks = {1, 1};
774
775  mpc_set (got, z, MPC_RNDNN); /* exact */
776  function->pointer.CUC (expected, ul, z,MPC_RNDNN);
777  function->pointer.CUC (got, ul, got, MPC_RNDNN);
778  if (!same_mpc_value (got, expected, ks))
779    {
780      printf ("Reuse error for %s(z, n, z) for\n", function->name);
781      printf ("n=%lu\n", ul);
782      MPC_OUT (z);
783      MPC_OUT (expected);
784      MPC_OUT (got);
785
786      exit (1);
787    }
788}
789
790static void
791reuse_ccs (mpc_function* function, mpc_srcptr z, long lo,
792           mpc_ptr got, mpc_ptr expected)
793{
794  known_signs_t ks = {1, 1};
795
796  mpc_set (got, z, MPC_RNDNN); /* exact */
797  function->pointer.CCS (expected, z, lo, MPC_RNDNN);
798  function->pointer.CCS (got, got, lo, MPC_RNDNN);
799  if (!same_mpc_value (got, expected, ks))
800    {
801      printf ("Reuse error for %s(z, z, n) for\n", function->name);
802      MPC_OUT (z);
803      printf ("n=%ld\n", lo);
804      MPC_OUT (expected);
805      MPC_OUT (got);
806
807      exit (1);
808    }
809}
810
811static void
812reuse_cci (mpc_function* function, mpc_srcptr z, int i,
813           mpc_ptr got, mpc_ptr expected)
814{
815  known_signs_t ks = {1, 1};
816
817  mpc_set (got, z, MPC_RNDNN); /* exact */
818  function->pointer.CCI (expected, z, i, MPC_RNDNN);
819  function->pointer.CCI (got, got, i, MPC_RNDNN);
820  if (!same_mpc_value (got, expected, ks))
821    {
822      printf ("Reuse error for %s(z, z, n) for\n", function->name);
823      MPC_OUT (z);
824      printf ("n=%d\n", i);
825      MPC_OUT (expected);
826      MPC_OUT (got);
827
828      exit (1);
829    }
830}
831
832static void
833reuse_cuuc (mpc_function* function, unsigned long ul1, unsigned long ul2,
834            mpc_srcptr z, mpc_ptr got, mpc_ptr expected)
835{
836  known_signs_t ks = {1, 1};
837
838  mpc_set (got, z, MPC_RNDNN); /* exact */
839  function->pointer.CUUC (expected, ul1, ul2, z,MPC_RNDNN);
840  function->pointer.CUUC (got, ul1, ul2, got, MPC_RNDNN);
841  if (!same_mpc_value (got, expected, ks))
842    {
843      printf ("Reuse error for %s(z, m, n, z) for\n", function->name);
844      printf ("m=%lu\n", ul1);
845      printf ("n=%lu\n", ul2);
846      MPC_OUT (z);
847      MPC_OUT (expected);
848      MPC_OUT (got);
849
850      exit (1);
851    }
852}
853
854
855/* helper functions for iterating over mpfr rounding modes */
856static mpfr_rnd_t
857first_rnd_mode (void)
858{
859   return GMP_RNDN;
860}
861
862static mpfr_rnd_t
863next_rnd_mode (mpfr_rnd_t curr)
864   /* assumes that all rounding modes are non-negative, and returns -1
865      when curr is the last rounding mode                              */
866{
867   switch (curr) {
868      case GMP_RNDN:
869         return GMP_RNDZ;
870      case GMP_RNDZ:
871         return GMP_RNDU;
872      case GMP_RNDU:
873         return GMP_RNDD;
874      default:
875         /* return invalid guard value in mpfr_rnd_t */
876#if MPFR_VERSION_MAJOR < 3
877         return GMP_RNDNA;
878#else
879         return MPFR_RNDA; /* valid rounding type, but not (yet) used in mpc */
880#endif
881   }
882}
883
884static int
885is_valid_rnd_mode (mpfr_rnd_t curr)
886   /* returns 1 if curr is a valid rounding mode, and 0otherwise */
887{
888   if (   curr == GMP_RNDN || curr == GMP_RNDZ
889       || curr == GMP_RNDU || curr == GMP_RNDD)
890      return 1;
891   else
892      return 0;
893}
894
895/* tgeneric(prec_min, prec_max, step, exp_max) checks rounding with random
896   numbers:
897   - with precision ranging from prec_min to prec_max with an increment of
898   step,
899   - with exponent between -exp_max and exp_max.
900
901   It also checks parameter reuse (it is assumed here that either two mpc_t
902   variables are equal or they are different, in the sense that the real part
903   of one of them cannot be the imaginary part of the other). */
904void
905tgeneric (mpc_function function, mpfr_prec_t prec_min,
906          mpfr_prec_t prec_max, mpfr_prec_t step, mpfr_exp_t exp_max)
907{
908  unsigned long ul1 = 0, ul2 = 0;
909  long lo = 0;
910  int i = 0;
911  mpfr_t x1, x2, xxxx;
912  mpc_t  z1, z2, z3, z4, z5, zzzz, zzzz2;
913
914  mpfr_rnd_t rnd_re, rnd_im, rnd2_re, rnd2_im;
915  mpfr_prec_t prec;
916  mpfr_exp_t exp_min;
917  int special, special_cases;
918
919  mpc_init2 (z1, prec_max);
920  switch (function.type)
921    {
922    case C_CC:
923      mpc_init2 (z2, prec_max);
924      mpc_init2 (z3, prec_max);
925      mpc_init2 (z4, prec_max);
926      mpc_init2 (zzzz, 4*prec_max);
927      special_cases = 8;
928      break;
929    case CCCC:
930      mpc_init2 (z2, prec_max);
931      mpc_init2 (z3, prec_max);
932      mpc_init2 (z4, prec_max);
933      mpc_init2 (z5, prec_max);
934      mpc_init2 (zzzz, 4*prec_max);
935      special_cases = 8;
936      break;
937    case FC:
938      mpfr_init2 (x1, prec_max);
939      mpfr_init2 (x2, prec_max);
940      mpfr_init2 (xxxx, 4*prec_max);
941      mpc_init2 (z2, prec_max);
942      special_cases = 4;
943      break;
944    case CCF: case CFC:
945      mpfr_init2 (x1, prec_max);
946      mpc_init2 (z2, prec_max);
947      mpc_init2 (z3, prec_max);
948      mpc_init2 (zzzz, 4*prec_max);
949      special_cases = 6;
950      break;
951    case CCI: case CCS:
952    case CCU: case CUC:
953      mpc_init2 (z2, prec_max);
954      mpc_init2 (z3, prec_max);
955      mpc_init2 (zzzz, 4*prec_max);
956      special_cases = 5;
957      break;
958    case CUUC:
959      mpc_init2 (z2, prec_max);
960      mpc_init2 (z3, prec_max);
961      mpc_init2 (zzzz, 4*prec_max);
962      special_cases = 6;
963      break;
964    case CC_C:
965      mpc_init2 (z2, prec_max);
966      mpc_init2 (z3, prec_max);
967      mpc_init2 (z4, prec_max);
968      mpc_init2 (z5, prec_max);
969      mpc_init2 (zzzz, 4*prec_max);
970      mpc_init2 (zzzz2, 4*prec_max);
971      special_cases = 4;
972      break;
973    case CC:
974    default:
975      mpc_init2 (z2, prec_max);
976      mpc_init2 (z3, prec_max);
977      mpc_init2 (zzzz, 4*prec_max);
978      special_cases = 4;
979    }
980
981  exp_min = mpfr_get_emin ();
982  if (exp_max <= 0 || exp_max > mpfr_get_emax ())
983    exp_max = mpfr_get_emax();
984  if (-exp_max > exp_min)
985    exp_min = - exp_max;
986
987  if (step < 1)
988    step = 1;
989
990  for (prec = prec_min, special = 0;
991       prec <= prec_max || special <= special_cases;
992       prec+=step, special += (prec > prec_max ? 1 : 0)) {
993       /* In the end, test functions in special cases of purely real, purely
994          imaginary or infinite arguments. */
995
996      /* probability of one zero part in 256th (25 is almost 10%) */
997      const unsigned int zero_probability = special != 0 ? 0 : 25;
998
999      mpc_set_prec (z1, prec);
1000      test_default_random (z1, exp_min, exp_max, 128, zero_probability);
1001
1002      switch (function.type)
1003        {
1004        case C_CC:
1005          mpc_set_prec (z2, prec);
1006          test_default_random (z2, exp_min, exp_max, 128, zero_probability);
1007          mpc_set_prec (z3, prec);
1008          mpc_set_prec (z4, prec);
1009          mpc_set_prec (zzzz, 4*prec);
1010          switch (special)
1011            {
1012            case 1:
1013              mpfr_set_ui (mpc_realref (z1), 0, GMP_RNDN);
1014              break;
1015            case 2:
1016              mpfr_set_inf (mpc_realref (z1), +1);
1017              break;
1018            case 3:
1019              mpfr_set_ui (mpc_imagref (z1), 0, GMP_RNDN);
1020              break;
1021            case 4:
1022              mpfr_set_inf (mpc_imagref (z1), -1);
1023              break;
1024            case 5:
1025              mpfr_set_ui (mpc_realref (z2), 0, GMP_RNDN);
1026              break;
1027            case 6:
1028              mpfr_set_inf (mpc_realref (z2), -1);
1029              break;
1030            case 7:
1031              mpfr_set_ui (mpc_imagref (z2), 0, GMP_RNDN);
1032              break;
1033            case 8:
1034              mpfr_set_inf (mpc_imagref (z2), +1);
1035              break;
1036            }
1037          break;
1038        case CCCC:
1039          mpc_set_prec (z2, prec);
1040          test_default_random (z2, exp_min, exp_max, 128, zero_probability);
1041          mpc_set_prec (z3, prec);
1042          mpc_set_prec (z4, prec);
1043          mpc_set_prec (z5, prec);
1044          mpc_set_prec (zzzz, 4*prec);
1045          switch (special)
1046            {
1047            case 1:
1048              mpfr_set_ui (mpc_realref (z1), 0, GMP_RNDN);
1049              break;
1050            case 2:
1051              mpfr_set_inf (mpc_realref (z1), +1);
1052              break;
1053            case 3:
1054              mpfr_set_ui (mpc_imagref (z1), 0, GMP_RNDN);
1055              break;
1056            case 4:
1057              mpfr_set_inf (mpc_imagref (z1), -1);
1058              break;
1059            case 5:
1060              mpfr_set_ui (mpc_realref (z2), 0, GMP_RNDN);
1061              break;
1062            case 6:
1063              mpfr_set_inf (mpc_realref (z2), -1);
1064              break;
1065            case 7:
1066              mpfr_set_ui (mpc_imagref (z2), 0, GMP_RNDN);
1067              break;
1068            case 8:
1069              mpfr_set_inf (mpc_imagref (z2), +1);
1070              break;
1071            }
1072          break;
1073        case FC:
1074          mpc_set_prec (z2, prec);
1075          mpfr_set_prec (x1, prec);
1076          mpfr_set_prec (x2, prec);
1077          mpfr_set_prec (xxxx, 4*prec);
1078          switch (special)
1079            {
1080            case 1:
1081              mpfr_set_ui (mpc_realref (z1), 0, GMP_RNDN);
1082              break;
1083            case 2:
1084              mpfr_set_inf (mpc_realref (z1), +1);
1085              break;
1086            case 3:
1087              mpfr_set_ui (mpc_imagref (z1), 0, GMP_RNDN);
1088              break;
1089            case 4:
1090              mpfr_set_inf (mpc_imagref (z1), -1);
1091              break;
1092            }
1093          break;
1094        case CCU: case CUC:
1095          mpc_set_prec (z2, 128);
1096          do {
1097            test_default_random (z2, 0, 64, 128, zero_probability);
1098          } while (!mpfr_fits_ulong_p (mpc_realref (z2), GMP_RNDN));
1099          ul1 = mpfr_get_ui (mpc_realref(z2), GMP_RNDN);
1100          mpc_set_prec (z2, prec);
1101          mpc_set_prec (z3, prec);
1102          mpc_set_prec (zzzz, 4*prec);
1103          switch (special)
1104            {
1105            case 1:
1106              mpfr_set_ui (mpc_realref (z1), 0, GMP_RNDN);
1107              break;
1108            case 2:
1109              mpfr_set_inf (mpc_realref (z1), +1);
1110              break;
1111            case 3:
1112              mpfr_set_ui (mpc_imagref (z1), 0, GMP_RNDN);
1113              break;
1114            case 4:
1115              mpfr_set_inf (mpc_imagref (z1), -1);
1116              break;
1117            case 5:
1118              ul1 = 0;
1119              break;
1120            }
1121          break;
1122        case CUUC:
1123          mpc_set_prec (z2, 128);
1124          do {
1125            test_default_random (z2, 0, 64, 128, zero_probability);
1126          } while (!mpfr_fits_ulong_p (mpc_realref (z2), GMP_RNDN)
1127                   ||!mpfr_fits_ulong_p (mpc_imagref (z2), GMP_RNDN));
1128          ul1 = mpfr_get_ui (mpc_realref(z2), GMP_RNDN);
1129          ul2 = mpfr_get_ui (mpc_imagref(z2), GMP_RNDN);
1130          mpc_set_prec (z2, prec);
1131          mpc_set_prec (z3, prec);
1132          mpc_set_prec (zzzz, 4*prec);
1133          switch (special)
1134            {
1135            case 1:
1136              mpfr_set_ui (mpc_realref (z1), 0, GMP_RNDN);
1137              break;
1138            case 2:
1139              mpfr_set_inf (mpc_realref (z1), +1);
1140              break;
1141            case 3:
1142              mpfr_set_ui (mpc_imagref (z1), 0, GMP_RNDN);
1143              break;
1144            case 4:
1145              mpfr_set_inf (mpc_imagref (z1), -1);
1146              break;
1147            case 5:
1148              ul1 = 0;
1149              break;
1150            case 6:
1151              ul2 = 0;
1152              break;
1153            }
1154          break;
1155        case CCS:
1156          mpc_set_prec (z2, 128);
1157          do {
1158            test_default_random (z2, 0, 64, 128, zero_probability);
1159          } while (!mpfr_fits_slong_p (mpc_realref (z2), GMP_RNDN));
1160          lo = mpfr_get_si (mpc_realref(z2), GMP_RNDN);
1161          mpc_set_prec (z2, prec);
1162          mpc_set_prec (z3, prec);
1163          mpc_set_prec (zzzz, 4*prec);
1164          switch (special)
1165            {
1166            case 1:
1167              mpfr_set_ui (mpc_realref (z1), 0, GMP_RNDN);
1168              break;
1169            case 2:
1170              mpfr_set_inf (mpc_realref (z1), +1);
1171              break;
1172            case 3:
1173              mpfr_set_ui (mpc_imagref (z1), 0, GMP_RNDN);
1174              break;
1175            case 4:
1176              mpfr_set_inf (mpc_imagref (z1), -1);
1177              break;
1178            case 5:
1179              lo = 0;
1180              break;
1181            }
1182          break;
1183        case CCI:
1184          mpc_set_prec (z2, 128);
1185          do {
1186            test_default_random (z2, 0, 64, 128, zero_probability);
1187          } while (!mpfr_fits_slong_p (mpc_realref (z2), GMP_RNDN));
1188          i = (int)mpfr_get_si (mpc_realref(z2), GMP_RNDN);
1189          mpc_set_prec (z2, prec);
1190          mpc_set_prec (z3, prec);
1191          mpc_set_prec (zzzz, 4*prec);
1192          switch (special)
1193            {
1194            case 1:
1195              mpfr_set_ui (mpc_realref (z1), 0, GMP_RNDN);
1196              break;
1197            case 2:
1198              mpfr_set_inf (mpc_realref (z1), +1);
1199              break;
1200            case 3:
1201              mpfr_set_ui (mpc_imagref (z1), 0, GMP_RNDN);
1202              break;
1203            case 4:
1204              mpfr_set_inf (mpc_imagref (z1), -1);
1205              break;
1206            case 5:
1207              i = 0;
1208              break;
1209            }
1210          break;
1211        case CCF: case CFC:
1212          mpfr_set_prec (x1, prec);
1213          mpfr_set (x1, mpc_realref (z1), GMP_RNDN);
1214          test_default_random (z1, exp_min, exp_max, 128, zero_probability);
1215          mpc_set_prec (z2, prec);
1216          mpc_set_prec (z3, prec);
1217          mpc_set_prec (zzzz, 4*prec);
1218          switch (special)
1219            {
1220            case 1:
1221              mpfr_set_ui (mpc_realref (z1), 0, GMP_RNDN);
1222              break;
1223            case 2:
1224              mpfr_set_inf (mpc_realref (z1), +1);
1225              break;
1226            case 3:
1227              mpfr_set_ui (mpc_imagref (z1), 0, GMP_RNDN);
1228              break;
1229            case 4:
1230              mpfr_set_inf (mpc_imagref (z1), -1);
1231              break;
1232            case 5:
1233              mpfr_set_ui (x1, 0, GMP_RNDN);
1234              break;
1235            case 6:
1236              mpfr_set_inf (x1, +1);
1237              break;
1238            }
1239          break;
1240        case CC_C:
1241          mpc_set_prec (z2, prec);
1242          mpc_set_prec (z3, prec);
1243          mpc_set_prec (z4, prec);
1244          mpc_set_prec (z5, prec);
1245          mpc_set_prec (zzzz, 4*prec);
1246          mpc_set_prec (zzzz2, 4*prec);
1247          switch (special)
1248            {
1249            case 1:
1250              mpfr_set_ui (mpc_realref (z1), 0, GMP_RNDN);
1251              break;
1252            case 2:
1253              mpfr_set_inf (mpc_realref (z1), +1);
1254              break;
1255            case 3:
1256              mpfr_set_ui (mpc_imagref (z1), 0, GMP_RNDN);
1257              break;
1258            case 4:
1259              mpfr_set_inf (mpc_imagref (z1), -1);
1260              break;
1261            }
1262          break;
1263        case CC:
1264        default:
1265          mpc_set_prec (z2, prec);
1266          mpc_set_prec (z3, prec);
1267          mpc_set_prec (zzzz, 4*prec);
1268          switch (special)
1269            {
1270            case 1:
1271              mpfr_set_ui (mpc_realref (z1), 0, GMP_RNDN);
1272              break;
1273            case 2:
1274              mpfr_set_inf (mpc_realref (z1), +1);
1275              break;
1276            case 3:
1277              mpfr_set_ui (mpc_imagref (z1), 0, GMP_RNDN);
1278              break;
1279            case 4:
1280              mpfr_set_inf (mpc_imagref (z1), -1);
1281              break;
1282            }
1283        }
1284
1285      for (rnd_re = first_rnd_mode (); is_valid_rnd_mode (rnd_re); rnd_re = next_rnd_mode (rnd_re))
1286        switch (function.type)
1287          {
1288          case C_CC:
1289            for (rnd_im = first_rnd_mode (); is_valid_rnd_mode (rnd_im); rnd_im = next_rnd_mode (rnd_im))
1290              tgeneric_c_cc (&function, z1, z2, z3, zzzz, z4,
1291			     MPC_RND (rnd_re, rnd_im));
1292            reuse_c_cc (&function, z1, z2, z3, z4);
1293            break;
1294          case CCCC:
1295            for (rnd_im = first_rnd_mode (); is_valid_rnd_mode (rnd_im); rnd_im = next_rnd_mode (rnd_im))
1296              tgeneric_cccc (&function, z1, z2, z3, z4, zzzz, z5,
1297                            MPC_RND (rnd_re, rnd_im));
1298            reuse_cccc (&function, z1, z2, z3, z4, z5);
1299            break;
1300          case FC:
1301            tgeneric_fc (&function, z1, x1, xxxx, x2, rnd_re);
1302            reuse_fc (&function, z1, z2, x1);
1303            break;
1304          case CC:
1305            for (rnd_im = first_rnd_mode (); is_valid_rnd_mode (rnd_im); rnd_im = next_rnd_mode (rnd_im))
1306              tgeneric_cc (&function, z1, z2, zzzz, z3,
1307                           MPC_RND (rnd_re, rnd_im));
1308            reuse_cc (&function, z1, z2, z3);
1309            break;
1310          case CC_C:
1311            for (rnd_im = first_rnd_mode (); is_valid_rnd_mode (rnd_im); rnd_im = next_rnd_mode (rnd_im))
1312               for (rnd2_re = first_rnd_mode (); is_valid_rnd_mode (rnd2_re); rnd2_re = next_rnd_mode (rnd2_re))
1313                  for (rnd2_im = first_rnd_mode (); is_valid_rnd_mode (rnd2_im); rnd2_im = next_rnd_mode (rnd2_im))
1314                     tgeneric_cc_c (&function, z1, z2, z3, zzzz, zzzz2, z4, z5,
1315                           MPC_RND (rnd_re, rnd_im), MPC_RND (rnd2_re, rnd2_im));
1316             reuse_cc_c (&function, z1, z2, z3, z4, z5);
1317            break;
1318          case CFC:
1319            for (rnd_im = first_rnd_mode (); is_valid_rnd_mode (rnd_im); rnd_im = next_rnd_mode (rnd_im))
1320              tgeneric_cfc (&function, x1, z1, z2, zzzz, z3,
1321                            MPC_RND (rnd_re, rnd_im));
1322            reuse_cfc (&function, z1, x1, z2, z3);
1323            break;
1324          case CCF:
1325            for (rnd_im = first_rnd_mode (); is_valid_rnd_mode (rnd_im); rnd_im = next_rnd_mode (rnd_im))
1326              tgeneric_ccf (&function, z1, x1, z2, zzzz, z3,
1327                            MPC_RND (rnd_re, rnd_im));
1328            reuse_ccf (&function, z1, x1, z2, z3);
1329            break;
1330          case CCU:
1331            for (rnd_im = first_rnd_mode (); is_valid_rnd_mode (rnd_im); rnd_im = next_rnd_mode (rnd_im))
1332              tgeneric_ccu (&function, z1, ul1, z2, zzzz, z3,
1333                            MPC_RND (rnd_re, rnd_im));
1334            reuse_ccu (&function, z1, ul1, z2, z3);
1335            break;
1336          case CUC:
1337            for (rnd_im = first_rnd_mode (); is_valid_rnd_mode (rnd_im); rnd_im = next_rnd_mode (rnd_im))
1338              tgeneric_cuc (&function, ul1, z1, z2, zzzz, z3,
1339                            MPC_RND (rnd_re, rnd_im));
1340            reuse_cuc (&function, ul1, z1, z2, z3);
1341            break;
1342          case CCS:
1343            for (rnd_im = first_rnd_mode (); is_valid_rnd_mode (rnd_im); rnd_im = next_rnd_mode (rnd_im))
1344              tgeneric_ccs (&function, z1, lo, z2, zzzz, z3,
1345                            MPC_RND (rnd_re, rnd_im));
1346            reuse_ccs (&function, z1, lo, z2, z3);
1347            break;
1348          case CCI:
1349            for (rnd_im = first_rnd_mode (); is_valid_rnd_mode (rnd_im); rnd_im = next_rnd_mode (rnd_im))
1350              tgeneric_cci (&function, z1, i, z2, zzzz, z3,
1351                            MPC_RND (rnd_re, rnd_im));
1352            reuse_cci (&function, z1, i, z2, z3);
1353            break;
1354          case CUUC:
1355            for (rnd_im = first_rnd_mode (); is_valid_rnd_mode (rnd_im); rnd_im = next_rnd_mode (rnd_im))
1356              tgeneric_cuuc (&function, ul1, ul2, z1, z2, zzzz, z3,
1357                             MPC_RND (rnd_re, rnd_im));
1358            reuse_cuuc (&function, ul1, ul2, z1, z2, z3);
1359            break;
1360          default:
1361            printf ("tgeneric not yet implemented for this kind of"
1362                    "function\n");
1363            exit (1);
1364          }
1365    }
1366
1367  mpc_clear (z1);
1368  switch (function.type)
1369    {
1370    case C_CC:
1371      mpc_clear (z2);
1372      mpc_clear (z3);
1373      mpc_clear (z4);
1374      mpc_clear (zzzz);
1375      break;
1376    case CCCC:
1377      mpc_clear (z2);
1378      mpc_clear (z3);
1379      mpc_clear (z4);
1380      mpc_clear (z5);
1381      mpc_clear (zzzz);
1382      break;
1383    case FC:
1384      mpc_clear (z2);
1385      mpfr_clear (x1);
1386      mpfr_clear (x2);
1387      mpfr_clear (xxxx);
1388      break;
1389    case CCF: case CFC:
1390      mpfr_clear (x1);
1391      mpc_clear (z2);
1392      mpc_clear (z3);
1393      mpc_clear (zzzz);
1394      break;
1395    case CC_C:
1396      mpc_clear (z2);
1397      mpc_clear (z3);
1398      mpc_clear (z4);
1399      mpc_clear (z5);
1400      mpc_clear (zzzz);
1401      mpc_clear (zzzz2);
1402      break;
1403    case CUUC:
1404    case CCI: case CCS:
1405    case CCU: case CUC:
1406    case CC:
1407    default:
1408      mpc_clear (z2);
1409      mpc_clear (z3);
1410      mpc_clear (zzzz);
1411    }
1412}
1413