resetting manifest requested domain to floor
[platform/upstream/mpc.git] / tests / tgeneric.c
1 /* tgeneric.c -- File for generic tests.
2
3 Copyright (C) 2008, 2009, 2010, 2011, 2012 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 #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 */
31 static void
32 tgeneric_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
76 static void
77 tgeneric_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
134 static void
135 tgeneric_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
162 static void
163 tgeneric_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
198 static void
199 tgeneric_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 */
235 static void
236 tgeneric_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
279 static void
280 tgeneric_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
324 static void
325 tgeneric_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
360 static void
361 tgeneric_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
396 static void
397 tgeneric_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
433 static void
434 tgeneric_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
469 static void
470 tgeneric_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. */
510 static void
511 reuse_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
529 static void
530 reuse_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
562 static void
563 reuse_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
594 static void
595 reuse_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
615 static void
616 reuse_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 */
637 static void
638 reuse_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
683 static void
684 reuse_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
748 static void
749 reuse_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
769 static void
770 reuse_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
790 static void
791 reuse_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
811 static void
812 reuse_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
832 static void
833 reuse_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 */
856 static mpfr_rnd_t
857 first_rnd_mode (void)
858 {
859    return GMP_RNDN;
860 }
861
862 static mpfr_rnd_t
863 next_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
884 static int
885 is_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). */
904 void
905 tgeneric (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 }