xref: /netbsd-src/external/lgpl3/gmp/dist/tests/mpz/reuse.c (revision 9fd8799cb5ceb66c69f2eb1a6d26a1d587ba1f1e)
1 /* Test that routines allow reusing a source variable as destination.
2 
3    Test all relevant functions except:
4 	mpz_bin_ui
5 	mpz_nextprime
6 	mpz_mul_si
7 	mpz_addmul_ui (should this really allow a+=a*c?)
8 
9 Copyright 1996, 1999-2002, 2009, 2012, 2013, 2016 Free Software Foundation,
10 Inc.
11 
12 This file is part of the GNU MP Library test suite.
13 
14 The GNU MP Library test suite is free software; you can redistribute it
15 and/or modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 3 of the License,
17 or (at your option) any later version.
18 
19 The GNU MP Library test suite is distributed in the hope that it will be
20 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
22 Public License for more details.
23 
24 You should have received a copy of the GNU General Public License along with
25 the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 
32 #include "gmp-impl.h"
33 #include "tests.h"
34 
35 #if __GMP_LIBGMP_DLL
36 
37 /* FIXME: When linking to a DLL libgmp, mpz_add etc can't be used as
38    initializers for global variables because they're effectively global
39    variables (function pointers) themselves.  Perhaps calling a test
40    function successively with mpz_add etc would be better.  */
41 
42 int
43 main (void)
44 {
45   printf ("Test suppressed for windows DLL\n");
46   exit (0);
47 }
48 
49 
50 #else /* ! DLL_EXPORT */
51 
52 void dump (const char *, mpz_t, mpz_t, mpz_t);
53 
54 typedef void (*dss_func) (mpz_ptr, mpz_srcptr, mpz_srcptr);
55 typedef void (*dsi_func) (mpz_ptr, mpz_srcptr, unsigned long int);
56 typedef unsigned long int (*dsi_div_func) (mpz_ptr, mpz_srcptr, unsigned long int);
57 typedef unsigned long int (*ddsi_div_func) (mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int);
58 typedef void (*ddss_div_func) (mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr);
59 typedef void (*ds_func) (mpz_ptr, mpz_srcptr);
60 
61 
62 void
63 mpz_xinvert (mpz_ptr r, mpz_srcptr a, mpz_srcptr b)
64 {
65   int res;
66   res = mpz_invert (r, a, b);
67   if (res == 0)
68     mpz_set_ui (r, 0);
69 }
70 
71 struct {
72   dss_func fptr;
73   const char *fname;
74   int isdivision;
75   int isslow;
76 } static dss[] =
77   { { mpz_add,     "mpz_add",	  0, 0 },
78     { mpz_sub,     "mpz_sub",	  0, 0 },
79     { mpz_mul,     "mpz_mul",	  0, 0 },
80     { mpz_cdiv_q,  "mpz_cdiv_q",  1, 0 },
81     { mpz_cdiv_r,  "mpz_cdiv_r",  1, 0 },
82     { mpz_fdiv_q,  "mpz_fdiv_q",  1, 0 },
83     { mpz_fdiv_r,  "mpz_fdiv_r",  1, 0 },
84     { mpz_tdiv_q,  "mpz_tdiv_q",  1, 0 },
85     { mpz_tdiv_r,  "mpz_tdiv_r",  1, 0 },
86     { mpz_mod,     "mpz_mod",	  1, 0 },
87     { mpz_xinvert, "mpz_xinvert", 1, 1 },
88     { mpz_gcd,     "mpz_gcd",	  0, 1 },
89     { mpz_lcm,     "mpz_lcm",	  0, 1 },
90     { mpz_and,     "mpz_and",	  0, 0 },
91     { mpz_ior,     "mpz_ior",	  0, 0 },
92     { mpz_xor,     "mpz_xor",     0, 0 }
93   };
94 
95 
96 struct {
97   dsi_func fptr;
98   const char *fname;
99   int mod;
100 } static dsi[] =
101 {
102   /* Don't change order here without changing the code in main(). */
103   { mpz_add_ui,         "mpz_add_ui",	     0 },
104   { mpz_mul_ui,		"mpz_mul_ui",	     0 },
105   { mpz_sub_ui,		"mpz_sub_ui",	     0 },
106   { mpz_fdiv_q_2exp,    "mpz_fdiv_q_2exp",   0x1000 },
107   { mpz_fdiv_r_2exp,    "mpz_fdiv_r_2exp",   0x1000 },
108   { mpz_cdiv_q_2exp,    "mpz_cdiv_q_2exp",   0x1000 },
109   { mpz_cdiv_r_2exp,    "mpz_cdiv_r_2exp",   0x1000 },
110   { mpz_tdiv_q_2exp,    "mpz_tdiv_q_2exp",   0x1000 },
111   { mpz_tdiv_r_2exp,    "mpz_tdiv_r_2exp",   0x1000 },
112   { mpz_mul_2exp,	"mpz_mul_2exp",      0x100 },
113   { mpz_pow_ui,		"mpz_pow_ui",        0x10 }
114 };
115 
116 struct {
117   dsi_div_func fptr;
118   const char *fname;
119 } static dsi_div[] =
120 {
121   { mpz_cdiv_q_ui,       "mpz_cdiv_q_ui" },
122   { mpz_cdiv_r_ui,       "mpz_cdiv_r_ui" },
123   { mpz_fdiv_q_ui,       "mpz_fdiv_q_ui" },
124   { mpz_fdiv_r_ui,       "mpz_fdiv_r_ui" },
125   { mpz_tdiv_q_ui,       "mpz_tdiv_q_ui" },
126   { mpz_tdiv_r_ui,       "mpz_tdiv_r_ui" }
127 };
128 
129 struct {
130   ddsi_div_func fptr;
131   const char *fname;
132   int isslow;
133 } static ddsi_div[] =
134 {
135   { mpz_cdiv_qr_ui,     "mpz_cdiv_qr_ui",    0 },
136   { mpz_fdiv_qr_ui,     "mpz_fdiv_qr_ui",    0 },
137   { mpz_tdiv_qr_ui,     "mpz_tdiv_qr_ui",    0 },
138 };
139 
140 
141 struct {
142   ddss_div_func fptr;
143   const char *fname;
144   int isslow;
145 } static ddss_div[] =
146 {
147   { mpz_cdiv_qr,  "mpz_cdiv_qr",    0 },
148   { mpz_fdiv_qr,  "mpz_fdiv_qr",    0 },
149   { mpz_tdiv_qr,  "mpz_tdiv_qr",    0 },
150 };
151 
152 struct {
153   ds_func fptr;
154   const char *fname;
155   int nonneg;
156 } static ds[] =
157 {
158   { mpz_abs,    "mpz_abs",    0 },
159   { mpz_com,    "mpz_com",    0 },
160   { mpz_neg,    "mpz_neg",    0 },
161   { mpz_sqrt,   "mpz_sqrt",   1 },
162 };
163 
164 #define FAIL(class,indx,op1,op2,op3)					\
165   do {									\
166     dump (class[indx].fname, op1, op2, op3);				\
167     exit (1);								\
168   } while (0)
169 
170 #define FAIL2(fname,op1,op2,op3)					\
171   do {									\
172     dump (#fname, op1, op2, op3);					\
173     exit (1);								\
174   } while (0)
175 
176 
177 #define INVOKE_RRS(desc,r1,r2,i1)					\
178   do {									\
179     if (pass & 1) _mpz_realloc (r1, ABSIZ(r1));				\
180     if (pass & 2) _mpz_realloc (r2, ABSIZ(r2));				\
181     (desc).fptr (r1, r2, i1);						\
182   } while (0)
183 #define INVOKE_RS(desc,r1,i1)						\
184   do {									\
185     if (pass & 1) _mpz_realloc (r1, ABSIZ(r1));				\
186     (desc).fptr (r1, i1);						\
187   } while (0)
188 #define INVOKE_RRSS(desc,r1,r2,i1,i2)					\
189   do {									\
190     if (pass & 1) _mpz_realloc (r1, ABSIZ(r1));				\
191     if (pass & 2) _mpz_realloc (r2, ABSIZ(r2));				\
192     (desc).fptr (r1, r2, i1, i2);					\
193   } while (0)
194 #define INVOKE_RSS(desc,r1,i1,i2)					\
195   do {									\
196     if (pass & 1) _mpz_realloc (r1, ABSIZ(r1));				\
197     (desc).fptr (r1, i1, i2);						\
198   } while (0)
199 
200 int
201 main (int argc, char **argv)
202 {
203   int i;
204   unsigned int pass, reps = 400;
205   mpz_t in1, in2, in3;
206   unsigned long int in2i;
207   mp_size_t size;
208   mpz_t res1, res2, res3;
209   mpz_t ref1, ref2, ref3;
210   mpz_t t;
211   unsigned long int r1, r2;
212   gmp_randstate_ptr rands;
213   mpz_t bs;
214   unsigned long bsi, size_range;
215 
216   tests_start ();
217   TESTS_REPS (reps, argv, argc);
218 
219   rands = RANDS;
220 
221   mpz_init (bs);
222 
223   mpz_init (in1);
224   mpz_init (in2);
225   mpz_init (in3);
226   mpz_init (ref1);
227   mpz_init (ref2);
228   mpz_init (ref3);
229   mpz_init (res1);
230   mpz_init (res2);
231   mpz_init (res3);
232   mpz_init (t);
233 
234   mpz_set_ui (res1, 1);		/* force allocation */
235   mpz_set_ui (res2, 1);		/* force allocation */
236   mpz_set_ui (res3, 1);		/* force allocation */
237 
238   for (pass = 1; pass <= reps; pass++)
239     {
240 #ifndef VERBOSE
241       if (isatty (fileno (stdout)))
242 	{
243 	  printf ("\r%d/%d passes", pass, reps);
244 	  fflush (stdout);
245 	}
246 #endif
247 
248       mpz_urandomb (bs, rands, 32);
249       /* Make size_range gradually bigger with each pass. */
250       size_range = mpz_get_ui (bs) % (pass * 15 / reps + 1) + 8;
251 
252 #define MAKE_RANDOM_OP(in, size_range, s)				\
253   do {									\
254     mpz_urandomb (bs, rands, size_range);				\
255     if (((pass >> s) & 3) == 3) /* conditional exponential dist */	\
256       mpz_urandomb (bs, rands, mpz_get_ui (bs) % (size_range - 7) + 7);	\
257     mpz_rrandomb (in, rands, mpz_get_ui (bs));				\
258   } while (0)
259 
260       MAKE_RANDOM_OP (in1, size_range, 0);
261       MAKE_RANDOM_OP (in2, size_range, 2);
262       MAKE_RANDOM_OP (in3, size_range, 4);
263 #undef MAKE_RANDOM_OP
264 
265 #ifdef VERBOSE
266       printf("%9d%9d%8d\n",
267 	     mpz_sizeinbase(in1,2),
268 	     mpz_sizeinbase(in2,2),
269 	     mpz_sizeinbase(in3,2));
270 #endif
271 
272       mpz_urandomb (bs, rands, 3);
273       bsi = mpz_get_ui (bs);
274       if ((bsi & 1) != 0)
275 	mpz_neg (in1, in1);
276       if ((bsi & 2) != 0)
277 	mpz_neg (in2, in2);
278       if ((bsi & 4) != 0)
279 	mpz_neg (in3, in3);
280 
281       for (i = 0; i < numberof (dss); i++)
282 	{
283 	  if (dss[i].isdivision && mpz_sgn (in2) == 0)
284 	    continue;
285 	  if (dss[i].isslow && size_range > 19)
286 	    continue;
287 
288 	  (dss[i].fptr) (ref1, in1, in2);
289 	  MPZ_CHECK_FORMAT (ref1);
290 
291 	  mpz_set (res1, in1);
292 	  INVOKE_RSS (dss[i], res1, res1, in2);
293 	  MPZ_CHECK_FORMAT (res1);
294 	  if (mpz_cmp (ref1, res1) != 0)
295 	    FAIL (dss, i, in1, in2, NULL);
296 
297 	  mpz_set (res1, in2);
298 	  INVOKE_RSS (dss[i], res1, in1, res1);
299 	  MPZ_CHECK_FORMAT (res1);
300 	  if (mpz_cmp (ref1, res1) != 0)
301 	    FAIL (dss, i, in1, in2, NULL);
302 	}
303 
304       for (i = 0; i < numberof (ddss_div); i++)
305 	{
306 	  if (mpz_sgn (in2) == 0)
307 	    continue;
308 
309 	  (ddss_div[i].fptr) (ref1, ref2, in1, in2);
310 	  MPZ_CHECK_FORMAT (ref1);
311 	  MPZ_CHECK_FORMAT (ref2);
312 
313 	  mpz_set (res1, in1);
314 	  mpz_clobber (res2);
315 	  INVOKE_RRSS (ddss_div[i], res1, res2, res1, in2);
316 	  MPZ_CHECK_FORMAT (res1);
317 	  MPZ_CHECK_FORMAT (res2);
318 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
319 	    FAIL (ddss_div, i, in1, in2, NULL);
320 
321 	  mpz_clobber (res1);
322 	  mpz_set (res2, in1);
323 	  INVOKE_RRSS (ddss_div[i], res1, res2, res2, in2);
324 	  MPZ_CHECK_FORMAT (res1);
325 	  MPZ_CHECK_FORMAT (res2);
326 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
327 	    FAIL (ddss_div, i, in1, in2, NULL);
328 
329 	  mpz_set (res1, in2);
330 	  mpz_clobber (res2);
331 	  INVOKE_RRSS (ddss_div[i], res1, res2, in1, res1);
332 	  MPZ_CHECK_FORMAT (res1);
333 	  MPZ_CHECK_FORMAT (res2);
334 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
335 	    FAIL (ddss_div, i, in1, in2, NULL);
336 
337 	  mpz_clobber (res1);
338 	  mpz_set (res2, in2);
339 	  INVOKE_RRSS (ddss_div[i], res1, res2, in1, res2);
340 	  MPZ_CHECK_FORMAT (res1);
341 	  MPZ_CHECK_FORMAT (res2);
342 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
343 	    FAIL (ddss_div, i, in1, in2, NULL);
344 	}
345 
346       for (i = 0; i < numberof (ds); i++)
347 	{
348 	  if (ds[i].nonneg && mpz_sgn (in1) < 0)
349 	    continue;
350 
351 	  (ds[i].fptr) (ref1, in1);
352 	  MPZ_CHECK_FORMAT (ref1);
353 
354 	  mpz_set (res1, in1);
355 	  INVOKE_RS (ds[i], res1, res1);
356 	  MPZ_CHECK_FORMAT (res1);
357 	  if (mpz_cmp (ref1, res1) != 0)
358 	    FAIL (ds, i, in1, in2, NULL);
359 	}
360 
361       in2i = mpz_get_ui (in2);
362 
363       for (i = 0; i < numberof (dsi); i++)
364 	{
365 	  if (dsi[i].mod != 0)
366 	    in2i = mpz_get_ui (in2) % dsi[i].mod;
367 
368 	  (dsi[i].fptr) (ref1, in1, in2i);
369 	  MPZ_CHECK_FORMAT (ref1);
370 
371 	  mpz_set (res1, in1);
372 	  INVOKE_RRS (dsi[i], res1, res1, in2i);
373 	  MPZ_CHECK_FORMAT (res1);
374 	  if (mpz_cmp (ref1, res1) != 0)
375 	    FAIL (dsi, i, in1, in2, NULL);
376 	}
377 
378       if (in2i != 0)	  /* Don't divide by 0.  */
379 	{
380 	  for (i = 0; i < numberof (dsi_div); i++)
381 	    {
382 	      r1 = (dsi_div[i].fptr) (ref1, in1, in2i);
383 	      MPZ_CHECK_FORMAT (ref1);
384 
385 	      mpz_set (res1, in1);
386 	      r2 = (dsi_div[i].fptr) (res1, res1, in2i);
387 	      MPZ_CHECK_FORMAT (res1);
388 	      if (mpz_cmp (ref1, res1) != 0 || r1 != r2)
389 		FAIL (dsi_div, i, in1, in2, NULL);
390 	    }
391 
392 	  for (i = 0; i < numberof (ddsi_div); i++)
393 	    {
394 	      r1 = (ddsi_div[i].fptr) (ref1, ref2, in1, in2i);
395 	      MPZ_CHECK_FORMAT (ref1);
396 
397 	      mpz_set (res1, in1);
398 	      mpz_clobber (res2);
399 	      r2 = (ddsi_div[i].fptr) (res1, res2, res1, in2i);
400 	      MPZ_CHECK_FORMAT (res1);
401 	      if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || r1 != r2)
402 		FAIL (ddsi_div, i, in1, in2, NULL);
403 
404 	      mpz_clobber (res1);
405 	      mpz_set (res2, in1);
406 	      (ddsi_div[i].fptr) (res1, res2, res2, in2i);
407 	      MPZ_CHECK_FORMAT (res1);
408 	      if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || r1 != r2)
409 		FAIL (ddsi_div, i, in1, in2, NULL);
410 	    }
411 	}
412 
413       if (mpz_sgn (in1) >= 0)
414 	{
415 	  mpz_sqrtrem (ref1, ref2, in1);
416 	  MPZ_CHECK_FORMAT (ref1);
417 	  MPZ_CHECK_FORMAT (ref2);
418 
419 	  mpz_set (res1, in1);
420 	  mpz_sqrtrem (res1, res2, res1);
421 	  MPZ_CHECK_FORMAT (res1);
422 	  MPZ_CHECK_FORMAT (res2);
423 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
424 	    FAIL2 (mpz_sqrtrem, in1, NULL, NULL);
425 
426 	  mpz_set (res2, in1);
427 	  mpz_sqrtrem (res1, res2, res2);
428 	  MPZ_CHECK_FORMAT (res1);
429 	  MPZ_CHECK_FORMAT (res2);
430 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
431 	    FAIL2 (mpz_sqrtrem, in1, NULL, NULL);
432 
433 	  mpz_set (res1, in1);
434 	  mpz_sqrtrem (res1, res1, res1);
435 	  MPZ_CHECK_FORMAT (res1);
436 	  if (mpz_cmp (ref2, res1) != 0)
437 	    FAIL2 (mpz_sqrtrem, in1, NULL, NULL);
438 	}
439 
440       if (mpz_sgn (in1) >= 0)
441 	{
442 	  mpz_root (ref1, in1, in2i % 0x100 + 1);
443 	  MPZ_CHECK_FORMAT (ref1);
444 
445 	  mpz_set (res1, in1);
446 	  mpz_root (res1, res1, in2i % 0x100 + 1);
447 	  MPZ_CHECK_FORMAT (res1);
448 	  if (mpz_cmp (ref1, res1) != 0)
449 	    FAIL2 (mpz_root, in1, in2, NULL);
450 	}
451 
452       if (mpz_sgn (in1) >= 0)
453 	{
454 	  mpz_rootrem (ref1, ref2, in1, in2i % 0x100 + 1);
455 	  MPZ_CHECK_FORMAT (ref1);
456 	  MPZ_CHECK_FORMAT (ref2);
457 
458 	  mpz_set (res1, in1);
459 	  mpz_rootrem (res1, res2, res1, in2i % 0x100 + 1);
460 	  MPZ_CHECK_FORMAT (res1);
461 	  MPZ_CHECK_FORMAT (res2);
462 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
463 	    FAIL2 (mpz_rootrem, in1, in2, NULL);
464 
465 	  mpz_set (res2, in1);
466 	  mpz_rootrem (res1, res2, res2, in2i % 0x100 + 1);
467 	  MPZ_CHECK_FORMAT (res1);
468 	  MPZ_CHECK_FORMAT (res2);
469 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
470 	    FAIL2 (mpz_rootrem, in1, in2, NULL);
471 	}
472 
473       if (size_range < 18)	/* run fewer tests since gcdext is slow */
474 	{
475 	  mpz_gcdext (ref1, ref2, ref3, in1, in2);
476 	  MPZ_CHECK_FORMAT (ref1);
477 	  MPZ_CHECK_FORMAT (ref2);
478 	  MPZ_CHECK_FORMAT (ref3);
479 
480 #define GCDEXT_CHECK3(i1, i2) do {					\
481 	    mpz_gcdext (res1, res2, res3, i1, i2);			\
482 	    MPZ_CHECK_FORMAT (res1);					\
483 	    MPZ_CHECK_FORMAT (res2);					\
484 	    MPZ_CHECK_FORMAT (res3);					\
485 	    if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0	\
486 		|| mpz_cmp (ref3, res3) != 0)				\
487 	      FAIL2 (mpz_gcdext, i1, i2, NULL);				\
488 	  } while (0)
489 #define GCDEXT_CHECK2(i1, i2) do {					\
490 	    mpz_gcdext (res1, res2, NULL, i1, i2);			\
491 	    MPZ_CHECK_FORMAT (res1);					\
492 	    MPZ_CHECK_FORMAT (res2);					\
493 	    if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)	\
494 	      FAIL2 (mpz_gcdext, i1, i2, NULL);				\
495 	  } while (0)
496 
497 	  mpz_set (res1, in1);
498 	  mpz_clobber (res2);
499 	  mpz_clobber (res3);
500 	  GCDEXT_CHECK3 (res1, in2);
501 
502 	  mpz_clobber (res1);
503 	  mpz_set (res2, in1);
504 	  mpz_clobber (res3);
505 	  GCDEXT_CHECK3 (res2, in2);
506 
507 	  mpz_clobber (res1);
508 	  mpz_clobber (res2);
509 	  mpz_set (res3, in1);
510 	  GCDEXT_CHECK3 (res3, in2);
511 
512 	  mpz_set (res1, in2);
513 	  mpz_clobber (res2);
514 	  mpz_clobber (res3);
515 	  GCDEXT_CHECK3 (in1, res1);
516 
517 	  mpz_clobber (res1);
518 	  mpz_set (res2, in2);
519 	  mpz_clobber (res3);
520 	  GCDEXT_CHECK3 (in1, res2);
521 
522 	  mpz_clobber (res1);
523 	  mpz_clobber (res2);
524 	  mpz_set (res3, in2);
525 	  GCDEXT_CHECK3 (in1, res3);
526 
527 	  mpz_set (res1, in1);
528 	  mpz_set (res2, in2);
529 	  mpz_clobber (res3);
530 	  GCDEXT_CHECK3 (res1, res2);
531 
532 	  mpz_set (res1, in1);
533 	  mpz_clobber (res2);
534 	  mpz_set (res3, in2);
535 	  GCDEXT_CHECK3 (res1, res3);
536 
537 	  mpz_clobber (res1);
538 	  mpz_set (res2, in1);
539 	  mpz_set (res3, in2);
540 	  GCDEXT_CHECK3 (res2, res3);
541 
542 	  mpz_set (res1, in2);
543 	  mpz_set (res2, in1);
544 	  mpz_clobber (res3);
545 	  GCDEXT_CHECK3 (res2, res1);
546 
547 	  mpz_set (res1, in2);
548 	  mpz_clobber (res2);
549 	  mpz_set (res3, in1);
550 	  GCDEXT_CHECK3 (res3, res1);
551 
552 	  mpz_clobber (res1);
553 	  mpz_set (res2, in2);
554 	  mpz_set (res3, in1);
555 	  GCDEXT_CHECK3(res3, res2);
556 
557 	  mpz_set (res1, in1);
558 	  mpz_clobber (res2);
559 	  GCDEXT_CHECK2 (res1, in2);
560 
561 	  mpz_clobber (res1);
562 	  mpz_set (res2, in1);
563 	  GCDEXT_CHECK2 (res2, in2);
564 
565 	  mpz_set (res1, in2);
566 	  mpz_clobber (res2);
567 	  GCDEXT_CHECK2 (in1, res1);
568 
569 	  mpz_clobber (res1);
570 	  mpz_set (res2, in2);
571 	  GCDEXT_CHECK2 (in1, res2);
572 #undef GCDEXT_CHECK
573 	  /* Identical inputs, gcd(in1, in1). Then the result should be
574 	     gcd = abs(in1), s = 0, t = sgn(in1). */
575 	  mpz_abs (ref1, in1);
576 	  mpz_set_ui (ref2, 0);
577 	  mpz_set_si (ref3, mpz_sgn (in1));
578 
579 #define GCDEXT_CHECK_SAME3(in) do {					\
580 	    mpz_gcdext (res1, res2, res3, in, in);			\
581 	    MPZ_CHECK_FORMAT (res1);					\
582 	    MPZ_CHECK_FORMAT (res2);					\
583 	    MPZ_CHECK_FORMAT (res3);					\
584 	    if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0	\
585 		|| mpz_cmp (ref3, res3) != 0)				\
586 	      FAIL2 (mpz_gcdext, in, in, NULL);				\
587 	  } while (0)
588 #define GCDEXT_CHECK_SAME2(in) do {					\
589 	    mpz_gcdext (res1, res2, NULL, in, in);			\
590 	    MPZ_CHECK_FORMAT (res1);					\
591 	    MPZ_CHECK_FORMAT (res2);					\
592 	    if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)	\
593 	      FAIL2 (mpz_gcdext, in, in, NULL);				\
594 	  } while (0)
595 
596 	  mpz_set (res1, in1);
597 	  mpz_clobber (res2);
598 	  mpz_clobber (res3);
599 	  GCDEXT_CHECK_SAME3 (res1);
600 
601 	  mpz_clobber (res1);
602 	  mpz_set (res2, in1);
603 	  mpz_clobber (res3);
604 	  GCDEXT_CHECK_SAME3 (res2);
605 
606 	  mpz_clobber (res1);
607 	  mpz_clobber (res2);
608 	  mpz_set (res3, in1);
609 	  GCDEXT_CHECK_SAME3 (res3);
610 
611 	  mpz_set (res1, in1);
612 	  mpz_clobber (res2);
613 	  mpz_clobber (res3);
614 	  GCDEXT_CHECK_SAME2 (res1);
615 
616 	  mpz_clobber (res1);
617 	  mpz_set (res2, in1);
618 	  mpz_clobber (res3);
619 	  GCDEXT_CHECK_SAME2 (res2);
620 #undef GCDEXT_CHECK_SAME
621 	}
622 
623       /* Don't run mpz_powm for huge exponents or when undefined.  */
624       if (size_range < 17 && mpz_sizeinbase (in2, 2) < 250 && mpz_sgn (in3) != 0
625 	  && (mpz_sgn (in2) >= 0 || mpz_invert (t, in1, in3)))
626 	{
627 	  mpz_powm (ref1, in1, in2, in3);
628 	  MPZ_CHECK_FORMAT (ref1);
629 
630 	  mpz_set (res1, in1);
631 	  mpz_powm (res1, res1, in2, in3);
632 	  MPZ_CHECK_FORMAT (res1);
633 	  if (mpz_cmp (ref1, res1) != 0)
634 	    FAIL2 (mpz_powm, in1, in2, in3);
635 
636 	  mpz_set (res1, in2);
637 	  mpz_powm (res1, in1, res1, in3);
638 	  MPZ_CHECK_FORMAT (res1);
639 	  if (mpz_cmp (ref1, res1) != 0)
640 	    FAIL2 (mpz_powm, in1, in2, in3);
641 
642 	  mpz_set (res1, in3);
643 	  mpz_powm (res1, in1, in2, res1);
644 	  MPZ_CHECK_FORMAT (res1);
645 	  if (mpz_cmp (ref1, res1) != 0)
646 	    FAIL2 (mpz_powm, in1, in2, in3);
647 	}
648 
649       /* Don't run mpz_powm_ui when undefined.  */
650       if (size_range < 17 && mpz_sgn (in3) != 0)
651 	{
652 	  mpz_powm_ui (ref1, in1, in2i, in3);
653 	  MPZ_CHECK_FORMAT (ref1);
654 
655 	  mpz_set (res1, in1);
656 	  mpz_powm_ui (res1, res1, in2i, in3);
657 	  MPZ_CHECK_FORMAT (res1);
658 	  if (mpz_cmp (ref1, res1) != 0)
659 	    FAIL2 (mpz_powm_ui, in1, in2, in3);
660 
661 	  mpz_set (res1, in3);
662 	  mpz_powm_ui (res1, in1, in2i, res1);
663 	  MPZ_CHECK_FORMAT (res1);
664 	  if (mpz_cmp (ref1, res1) != 0)
665 	    FAIL2 (mpz_powm_ui, in1, in2, in3);
666 	}
667 
668       {
669 	r1 = mpz_gcd_ui (ref1, in1, in2i);
670 	MPZ_CHECK_FORMAT (ref1);
671 
672 	mpz_set (res1, in1);
673 	r2 = mpz_gcd_ui (res1, res1, in2i);
674 	MPZ_CHECK_FORMAT (res1);
675 	if (mpz_cmp (ref1, res1) != 0)
676 	  FAIL2 (mpz_gcd_ui, in1, in2, NULL);
677       }
678 
679       if (mpz_sgn (in2) != 0)
680 	{
681 	  /* Test mpz_remove */
682 	  mp_bitcnt_t refretval, retval;
683 	  refretval = mpz_remove (ref1, in1, in2);
684 	  MPZ_CHECK_FORMAT (ref1);
685 
686 	  mpz_set (res1, in1);
687 	  retval = mpz_remove (res1, res1, in2);
688 	  MPZ_CHECK_FORMAT (res1);
689 	  if (mpz_cmp (ref1, res1) != 0 || refretval != retval)
690 	    FAIL2 (mpz_remove, in1, in2, NULL);
691 
692 	  mpz_set (res1, in2);
693 	  retval = mpz_remove (res1, in1, res1);
694 	  MPZ_CHECK_FORMAT (res1);
695 	  if (mpz_cmp (ref1, res1) != 0 || refretval != retval)
696 	    FAIL2 (mpz_remove, in1, in2, NULL);
697 	}
698 
699       if (mpz_sgn (in2) != 0)
700 	{
701 	  /* Test mpz_divexact */
702 	  mpz_mul (t, in1, in2);
703 	  mpz_divexact (ref1, t, in2);
704 	  MPZ_CHECK_FORMAT (ref1);
705 
706 	  mpz_set (res1, t);
707 	  mpz_divexact (res1, res1, in2);
708 	  MPZ_CHECK_FORMAT (res1);
709 	  if (mpz_cmp (ref1, res1) != 0)
710 	    FAIL2 (mpz_divexact, t, in2, NULL);
711 
712 	  mpz_set (res1, in2);
713 	  mpz_divexact (res1, t, res1);
714 	  MPZ_CHECK_FORMAT (res1);
715 	  if (mpz_cmp (ref1, res1) != 0)
716 	    FAIL2 (mpz_divexact, t, in2, NULL);
717 	}
718 
719       if (mpz_sgn (in2) > 0)
720 	{
721 	  /* Test mpz_divexact_gcd, same as mpz_divexact */
722 	  mpz_mul (t, in1, in2);
723 	  mpz_divexact_gcd (ref1, t, in2);
724 	  MPZ_CHECK_FORMAT (ref1);
725 
726 	  mpz_set (res1, t);
727 	  mpz_divexact_gcd (res1, res1, in2);
728 	  MPZ_CHECK_FORMAT (res1);
729 	  if (mpz_cmp (ref1, res1) != 0)
730 	    FAIL2 (mpz_divexact_gcd, t, in2, NULL);
731 
732 	  mpz_set (res1, in2);
733 	  mpz_divexact_gcd (res1, t, res1);
734 	  MPZ_CHECK_FORMAT (res1);
735 	  if (mpz_cmp (ref1, res1) != 0)
736 	    FAIL2 (mpz_divexact_gcd, t, in2, NULL);
737 	}
738     }
739 
740   if (isatty (fileno (stdout)))
741     printf ("\r%20s", "");
742 
743   mpz_clear (bs);
744   mpz_clear (in1);
745   mpz_clear (in2);
746   mpz_clear (in3);
747   mpz_clear (ref1);
748   mpz_clear (ref2);
749   mpz_clear (ref3);
750   mpz_clear (res1);
751   mpz_clear (res2);
752   mpz_clear (res3);
753   mpz_clear (t);
754 
755   if (isatty (fileno (stdout)))
756     printf ("\r");
757 
758   tests_end ();
759   exit (0);
760 }
761 
762 void
763 dump (const char *name, mpz_t in1, mpz_t in2, mpz_t in3)
764 {
765   printf ("failure in %s (", name);
766   0 && mpz_out_str (stdout, -16, in1);
767   if (in2 != NULL)
768     {
769       printf (" ");
770       0 && mpz_out_str (stdout, -16, in2);
771     }
772   if (in3 != NULL)
773     {
774       printf (" ");
775       0 && mpz_out_str (stdout, -16, in3);
776     }
777   printf (")\n");
778 }
779 
780 #endif /* ! DLL_EXPORT */
781