xref: /netbsd-src/external/lgpl3/gmp/dist/tests/mpz/reuse.c (revision 1daf83e636cd998f45e5597a8f995a540e2d5b4a)
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, 2020 Free Software
10 Foundation, 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
main(void)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
mpz_xinvert(mpz_ptr r,mpz_srcptr a,mpz_srcptr b)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 void
realloc_if_reducing(mpz_ptr r)178 realloc_if_reducing (mpz_ptr r)
179 {
180   if (ABSIZ(r) < ALLOC(r))
181       _mpz_realloc (r, ABSIZ(r));
182 }
183 
184 #define INVOKE_RRS(desc,r1,r2,i1)					\
185   do {									\
186     if (pass & 1) realloc_if_reducing (r1);				\
187     if (pass & 2) realloc_if_reducing (r2);				\
188     (desc).fptr (r1, r2, i1);						\
189   } while (0)
190 #define INVOKE_RS(desc,r1,i1)						\
191   do {									\
192     if (pass & 1) realloc_if_reducing (r1);				\
193     (desc).fptr (r1, i1);						\
194   } while (0)
195 #define INVOKE_RRSS(desc,r1,r2,i1,i2)					\
196   do {									\
197     if (pass & 1) realloc_if_reducing (r1);				\
198     if (pass & 2) realloc_if_reducing (r2);				\
199     (desc).fptr (r1, r2, i1, i2);					\
200   } while (0)
201 #define INVOKE_RSS(desc,r1,i1,i2)					\
202   do {									\
203     if (pass & 1) realloc_if_reducing (r1);				\
204     (desc).fptr (r1, i1, i2);						\
205   } while (0)
206 
207 int
main(int argc,char ** argv)208 main (int argc, char **argv)
209 {
210   int i;
211   unsigned int pass, reps = 400;
212   mpz_t in1, in2, in3;
213   unsigned long int in2i;
214   mpz_t res1, res2, res3;
215   mpz_t ref1, ref2, ref3;
216   mpz_t t;
217   unsigned long int r1, r2;
218   gmp_randstate_ptr rands;
219   mpz_t bs;
220   unsigned long bsi, size_range;
221 
222   tests_start ();
223   TESTS_REPS (reps, argv, argc);
224 
225   rands = RANDS;
226 
227   mpz_init (bs);
228 
229   mpz_init (in1);
230   mpz_init (in2);
231   mpz_init (in3);
232   mpz_init (ref1);
233   mpz_init (ref2);
234   mpz_init (ref3);
235   mpz_init (res1);
236   mpz_init (res2);
237   mpz_init (res3);
238   mpz_init (t);
239 
240   mpz_set_ui (res1, 1);		/* force allocation */
241   mpz_set_ui (res2, 1);		/* force allocation */
242   mpz_set_ui (res3, 1);		/* force allocation */
243 
244   for (pass = 1; pass <= reps; pass++)
245     {
246 #ifndef VERBOSE
247       if (isatty (STDOUT_FILENO))
248 	{
249 	  printf ("\r%d/%d passes", pass, reps);
250 	  fflush (stdout);
251 	}
252 #endif
253 
254       mpz_urandomb (bs, rands, 32);
255       /* Make size_range gradually bigger with each pass. */
256       size_range = mpz_get_ui (bs) % (pass * 15 / reps + 1) + 8;
257 
258 #define MAKE_RANDOM_OP(in, size_range, s)				\
259   do {									\
260     mpz_urandomb (bs, rands, size_range);				\
261     if (((pass >> s) & 3) == 3) /* conditional exponential dist */	\
262       mpz_urandomb (bs, rands, mpz_get_ui (bs) % (size_range - 7) + 7);	\
263     mpz_rrandomb (in, rands, mpz_get_ui (bs));				\
264   } while (0)
265 
266       MAKE_RANDOM_OP (in1, size_range, 0);
267       MAKE_RANDOM_OP (in2, size_range, 2);
268       MAKE_RANDOM_OP (in3, size_range, 4);
269 #undef MAKE_RANDOM_OP
270 
271 #ifdef VERBOSE
272       printf("%9d%9d%8d\n",
273 	     mpz_sizeinbase(in1,2),
274 	     mpz_sizeinbase(in2,2),
275 	     mpz_sizeinbase(in3,2));
276 #endif
277 
278       mpz_urandomb (bs, rands, 3);
279       bsi = mpz_get_ui (bs);
280       if ((bsi & 1) != 0)
281 	mpz_neg (in1, in1);
282       if ((bsi & 2) != 0)
283 	mpz_neg (in2, in2);
284       if ((bsi & 4) != 0)
285 	mpz_neg (in3, in3);
286 
287       for (i = 0; i < numberof (dss); i++)
288 	{
289 	  if (dss[i].isdivision && mpz_sgn (in2) == 0)
290 	    continue;
291 	  if (dss[i].isslow && size_range > 19)
292 	    continue;
293 
294 	  (dss[i].fptr) (ref1, in1, in2);
295 	  MPZ_CHECK_FORMAT (ref1);
296 
297 	  mpz_set (res1, in1);
298 	  INVOKE_RSS (dss[i], res1, res1, in2);
299 	  MPZ_CHECK_FORMAT (res1);
300 	  if (mpz_cmp (ref1, res1) != 0)
301 	    FAIL (dss, i, in1, in2, NULL);
302 
303 	  mpz_set (res1, in2);
304 	  INVOKE_RSS (dss[i], res1, in1, res1);
305 	  MPZ_CHECK_FORMAT (res1);
306 	  if (mpz_cmp (ref1, res1) != 0)
307 	    FAIL (dss, i, in1, in2, NULL);
308 	}
309 
310       for (i = 0; i < numberof (ddss_div); i++)
311 	{
312 	  if (mpz_sgn (in2) == 0)
313 	    continue;
314 
315 	  (ddss_div[i].fptr) (ref1, ref2, in1, in2);
316 	  MPZ_CHECK_FORMAT (ref1);
317 	  MPZ_CHECK_FORMAT (ref2);
318 
319 	  mpz_set (res1, in1);
320 	  mpz_clobber (res2);
321 	  INVOKE_RRSS (ddss_div[i], res1, res2, res1, in2);
322 	  MPZ_CHECK_FORMAT (res1);
323 	  MPZ_CHECK_FORMAT (res2);
324 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
325 	    FAIL (ddss_div, i, in1, in2, NULL);
326 
327 	  mpz_clobber (res1);
328 	  mpz_set (res2, in1);
329 	  INVOKE_RRSS (ddss_div[i], res1, res2, res2, in2);
330 	  MPZ_CHECK_FORMAT (res1);
331 	  MPZ_CHECK_FORMAT (res2);
332 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
333 	    FAIL (ddss_div, i, in1, in2, NULL);
334 
335 	  mpz_set (res1, in2);
336 	  mpz_clobber (res2);
337 	  INVOKE_RRSS (ddss_div[i], res1, res2, in1, res1);
338 	  MPZ_CHECK_FORMAT (res1);
339 	  MPZ_CHECK_FORMAT (res2);
340 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
341 	    FAIL (ddss_div, i, in1, in2, NULL);
342 
343 	  mpz_clobber (res1);
344 	  mpz_set (res2, in2);
345 	  INVOKE_RRSS (ddss_div[i], res1, res2, in1, res2);
346 	  MPZ_CHECK_FORMAT (res1);
347 	  MPZ_CHECK_FORMAT (res2);
348 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
349 	    FAIL (ddss_div, i, in1, in2, NULL);
350 	}
351 
352       for (i = 0; i < numberof (ds); i++)
353 	{
354 	  if (ds[i].nonneg && mpz_sgn (in1) < 0)
355 	    continue;
356 
357 	  (ds[i].fptr) (ref1, in1);
358 	  MPZ_CHECK_FORMAT (ref1);
359 
360 	  mpz_set (res1, in1);
361 	  INVOKE_RS (ds[i], res1, res1);
362 	  MPZ_CHECK_FORMAT (res1);
363 	  if (mpz_cmp (ref1, res1) != 0)
364 	    FAIL (ds, i, in1, in2, NULL);
365 	}
366 
367       in2i = mpz_get_ui (in2);
368 
369       for (i = 0; i < numberof (dsi); i++)
370 	{
371 	  if (dsi[i].mod != 0)
372 	    in2i = mpz_get_ui (in2) % dsi[i].mod;
373 
374 	  (dsi[i].fptr) (ref1, in1, in2i);
375 	  MPZ_CHECK_FORMAT (ref1);
376 
377 	  mpz_set (res1, in1);
378 	  INVOKE_RRS (dsi[i], res1, res1, in2i);
379 	  MPZ_CHECK_FORMAT (res1);
380 	  if (mpz_cmp (ref1, res1) != 0)
381 	    FAIL (dsi, i, in1, in2, NULL);
382 	}
383 
384       if (in2i != 0)	  /* Don't divide by 0.  */
385 	{
386 	  for (i = 0; i < numberof (dsi_div); i++)
387 	    {
388 	      r1 = (dsi_div[i].fptr) (ref1, in1, in2i);
389 	      MPZ_CHECK_FORMAT (ref1);
390 
391 	      mpz_set (res1, in1);
392 	      r2 = (dsi_div[i].fptr) (res1, res1, in2i);
393 	      MPZ_CHECK_FORMAT (res1);
394 	      if (mpz_cmp (ref1, res1) != 0 || r1 != r2)
395 		FAIL (dsi_div, i, in1, in2, NULL);
396 	    }
397 
398 	  for (i = 0; i < numberof (ddsi_div); i++)
399 	    {
400 	      r1 = (ddsi_div[i].fptr) (ref1, ref2, in1, in2i);
401 	      MPZ_CHECK_FORMAT (ref1);
402 
403 	      mpz_set (res1, in1);
404 	      mpz_clobber (res2);
405 	      r2 = (ddsi_div[i].fptr) (res1, res2, res1, in2i);
406 	      MPZ_CHECK_FORMAT (res1);
407 	      if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || r1 != r2)
408 		FAIL (ddsi_div, i, in1, in2, NULL);
409 
410 	      mpz_clobber (res1);
411 	      mpz_set (res2, in1);
412 	      (ddsi_div[i].fptr) (res1, res2, res2, in2i);
413 	      MPZ_CHECK_FORMAT (res1);
414 	      if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || r1 != r2)
415 		FAIL (ddsi_div, i, in1, in2, NULL);
416 	    }
417 	}
418 
419       if (mpz_sgn (in1) >= 0)
420 	{
421 	  mpz_sqrtrem (ref1, ref2, in1);
422 	  MPZ_CHECK_FORMAT (ref1);
423 	  MPZ_CHECK_FORMAT (ref2);
424 
425 	  mpz_set (res1, in1);
426 	  mpz_sqrtrem (res1, res2, res1);
427 	  MPZ_CHECK_FORMAT (res1);
428 	  MPZ_CHECK_FORMAT (res2);
429 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
430 	    FAIL2 (mpz_sqrtrem, in1, NULL, NULL);
431 
432 	  mpz_set (res2, in1);
433 	  mpz_sqrtrem (res1, res2, res2);
434 	  MPZ_CHECK_FORMAT (res1);
435 	  MPZ_CHECK_FORMAT (res2);
436 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
437 	    FAIL2 (mpz_sqrtrem, in1, NULL, NULL);
438 
439 	  mpz_set (res1, in1);
440 	  mpz_sqrtrem (res1, res1, res1);
441 	  MPZ_CHECK_FORMAT (res1);
442 	  if (mpz_cmp (ref2, res1) != 0)
443 	    FAIL2 (mpz_sqrtrem, in1, NULL, NULL);
444 	}
445 
446       if (mpz_sgn (in1) >= 0)
447 	{
448 	  mpz_root (ref1, in1, in2i % 0x100 + 1);
449 	  MPZ_CHECK_FORMAT (ref1);
450 
451 	  mpz_set (res1, in1);
452 	  mpz_root (res1, res1, in2i % 0x100 + 1);
453 	  MPZ_CHECK_FORMAT (res1);
454 	  if (mpz_cmp (ref1, res1) != 0)
455 	    FAIL2 (mpz_root, in1, in2, NULL);
456 	}
457 
458       if (mpz_sgn (in1) >= 0)
459 	{
460 	  mpz_rootrem (ref1, ref2, in1, in2i % 0x100 + 1);
461 	  MPZ_CHECK_FORMAT (ref1);
462 	  MPZ_CHECK_FORMAT (ref2);
463 
464 	  mpz_set (res1, in1);
465 	  mpz_rootrem (res1, res2, res1, in2i % 0x100 + 1);
466 	  MPZ_CHECK_FORMAT (res1);
467 	  MPZ_CHECK_FORMAT (res2);
468 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
469 	    FAIL2 (mpz_rootrem, in1, in2, NULL);
470 
471 	  mpz_set (res2, in1);
472 	  mpz_rootrem (res1, res2, res2, in2i % 0x100 + 1);
473 	  MPZ_CHECK_FORMAT (res1);
474 	  MPZ_CHECK_FORMAT (res2);
475 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
476 	    FAIL2 (mpz_rootrem, in1, in2, NULL);
477 	}
478 
479       if (size_range < 18)	/* run fewer tests since gcdext is slow */
480 	{
481 	  mpz_gcdext (ref1, ref2, ref3, in1, in2);
482 	  MPZ_CHECK_FORMAT (ref1);
483 	  MPZ_CHECK_FORMAT (ref2);
484 	  MPZ_CHECK_FORMAT (ref3);
485 
486 #define GCDEXT_CHECK3(i1, i2) do {					\
487 	    mpz_gcdext (res1, res2, res3, i1, i2);			\
488 	    MPZ_CHECK_FORMAT (res1);					\
489 	    MPZ_CHECK_FORMAT (res2);					\
490 	    MPZ_CHECK_FORMAT (res3);					\
491 	    if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0	\
492 		|| mpz_cmp (ref3, res3) != 0)				\
493 	      FAIL2 (mpz_gcdext, i1, i2, NULL);				\
494 	  } while (0)
495 #define GCDEXT_CHECK2(i1, i2) do {					\
496 	    mpz_gcdext (res1, res2, NULL, i1, i2);			\
497 	    MPZ_CHECK_FORMAT (res1);					\
498 	    MPZ_CHECK_FORMAT (res2);					\
499 	    if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)	\
500 	      FAIL2 (mpz_gcdext, i1, i2, NULL);				\
501 	  } while (0)
502 
503 	  mpz_set (res1, in1);
504 	  mpz_clobber (res2);
505 	  mpz_clobber (res3);
506 	  GCDEXT_CHECK3 (res1, in2);
507 
508 	  mpz_clobber (res1);
509 	  mpz_set (res2, in1);
510 	  mpz_clobber (res3);
511 	  GCDEXT_CHECK3 (res2, in2);
512 
513 	  mpz_clobber (res1);
514 	  mpz_clobber (res2);
515 	  mpz_set (res3, in1);
516 	  GCDEXT_CHECK3 (res3, in2);
517 
518 	  mpz_set (res1, in2);
519 	  mpz_clobber (res2);
520 	  mpz_clobber (res3);
521 	  GCDEXT_CHECK3 (in1, res1);
522 
523 	  mpz_clobber (res1);
524 	  mpz_set (res2, in2);
525 	  mpz_clobber (res3);
526 	  GCDEXT_CHECK3 (in1, res2);
527 
528 	  mpz_clobber (res1);
529 	  mpz_clobber (res2);
530 	  mpz_set (res3, in2);
531 	  GCDEXT_CHECK3 (in1, res3);
532 
533 	  mpz_set (res1, in1);
534 	  mpz_set (res2, in2);
535 	  mpz_clobber (res3);
536 	  GCDEXT_CHECK3 (res1, res2);
537 
538 	  mpz_set (res1, in1);
539 	  mpz_clobber (res2);
540 	  mpz_set (res3, in2);
541 	  GCDEXT_CHECK3 (res1, res3);
542 
543 	  mpz_clobber (res1);
544 	  mpz_set (res2, in1);
545 	  mpz_set (res3, in2);
546 	  GCDEXT_CHECK3 (res2, res3);
547 
548 	  mpz_set (res1, in2);
549 	  mpz_set (res2, in1);
550 	  mpz_clobber (res3);
551 	  GCDEXT_CHECK3 (res2, res1);
552 
553 	  mpz_set (res1, in2);
554 	  mpz_clobber (res2);
555 	  mpz_set (res3, in1);
556 	  GCDEXT_CHECK3 (res3, res1);
557 
558 	  mpz_clobber (res1);
559 	  mpz_set (res2, in2);
560 	  mpz_set (res3, in1);
561 	  GCDEXT_CHECK3(res3, res2);
562 
563 	  mpz_set (res1, in1);
564 	  mpz_clobber (res2);
565 	  GCDEXT_CHECK2 (res1, in2);
566 
567 	  mpz_clobber (res1);
568 	  mpz_set (res2, in1);
569 	  GCDEXT_CHECK2 (res2, in2);
570 
571 	  mpz_set (res1, in2);
572 	  mpz_clobber (res2);
573 	  GCDEXT_CHECK2 (in1, res1);
574 
575 	  mpz_clobber (res1);
576 	  mpz_set (res2, in2);
577 	  GCDEXT_CHECK2 (in1, res2);
578 #undef GCDEXT_CHECK
579 	  /* Identical inputs, gcd(in1, in1). Then the result should be
580 	     gcd = abs(in1), s = 0, t = sgn(in1). */
581 	  mpz_abs (ref1, in1);
582 	  mpz_set_ui (ref2, 0);
583 	  mpz_set_si (ref3, mpz_sgn (in1));
584 
585 #define GCDEXT_CHECK_SAME3(in) do {					\
586 	    mpz_gcdext (res1, res2, res3, in, in);			\
587 	    MPZ_CHECK_FORMAT (res1);					\
588 	    MPZ_CHECK_FORMAT (res2);					\
589 	    MPZ_CHECK_FORMAT (res3);					\
590 	    if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0	\
591 		|| mpz_cmp (ref3, res3) != 0)				\
592 	      FAIL2 (mpz_gcdext, in, in, NULL);				\
593 	  } while (0)
594 #define GCDEXT_CHECK_SAME2(in) do {					\
595 	    mpz_gcdext (res1, res2, NULL, in, in);			\
596 	    MPZ_CHECK_FORMAT (res1);					\
597 	    MPZ_CHECK_FORMAT (res2);					\
598 	    if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)	\
599 	      FAIL2 (mpz_gcdext, in, in, NULL);				\
600 	  } while (0)
601 
602 	  mpz_set (res1, in1);
603 	  mpz_clobber (res2);
604 	  mpz_clobber (res3);
605 	  GCDEXT_CHECK_SAME3 (res1);
606 
607 	  mpz_clobber (res1);
608 	  mpz_set (res2, in1);
609 	  mpz_clobber (res3);
610 	  GCDEXT_CHECK_SAME3 (res2);
611 
612 	  mpz_clobber (res1);
613 	  mpz_clobber (res2);
614 	  mpz_set (res3, in1);
615 	  GCDEXT_CHECK_SAME3 (res3);
616 
617 	  mpz_set (res1, in1);
618 	  mpz_clobber (res2);
619 	  mpz_clobber (res3);
620 	  GCDEXT_CHECK_SAME2 (res1);
621 
622 	  mpz_clobber (res1);
623 	  mpz_set (res2, in1);
624 	  mpz_clobber (res3);
625 	  GCDEXT_CHECK_SAME2 (res2);
626 #undef GCDEXT_CHECK_SAME
627 	}
628 
629       /* Don't run mpz_powm for huge exponents or when undefined.  */
630       if (size_range < 17 && mpz_sizeinbase (in2, 2) < 250 && mpz_sgn (in3) != 0
631 	  && (mpz_sgn (in2) >= 0 || mpz_invert (t, in1, in3)))
632 	{
633 	  mpz_powm (ref1, in1, in2, in3);
634 	  MPZ_CHECK_FORMAT (ref1);
635 
636 	  mpz_set (res1, in1);
637 	  mpz_powm (res1, res1, in2, 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, in2);
643 	  mpz_powm (res1, in1, res1, in3);
644 	  MPZ_CHECK_FORMAT (res1);
645 	  if (mpz_cmp (ref1, res1) != 0)
646 	    FAIL2 (mpz_powm, in1, in2, in3);
647 
648 	  mpz_set (res1, in3);
649 	  mpz_powm (res1, in1, in2, res1);
650 	  MPZ_CHECK_FORMAT (res1);
651 	  if (mpz_cmp (ref1, res1) != 0)
652 	    FAIL2 (mpz_powm, in1, in2, in3);
653 	}
654 
655       /* Don't run mpz_powm_ui when undefined.  */
656       if (size_range < 17 && mpz_sgn (in3) != 0)
657 	{
658 	  mpz_powm_ui (ref1, in1, in2i, in3);
659 	  MPZ_CHECK_FORMAT (ref1);
660 
661 	  mpz_set (res1, in1);
662 	  mpz_powm_ui (res1, res1, in2i, in3);
663 	  MPZ_CHECK_FORMAT (res1);
664 	  if (mpz_cmp (ref1, res1) != 0)
665 	    FAIL2 (mpz_powm_ui, in1, in2, in3);
666 
667 	  mpz_set (res1, in3);
668 	  mpz_powm_ui (res1, in1, in2i, res1);
669 	  MPZ_CHECK_FORMAT (res1);
670 	  if (mpz_cmp (ref1, res1) != 0)
671 	    FAIL2 (mpz_powm_ui, in1, in2, in3);
672 	}
673 
674       {
675 	r1 = mpz_gcd_ui (ref1, in1, in2i);
676 	MPZ_CHECK_FORMAT (ref1);
677 
678 	mpz_set (res1, in1);
679 	r2 = mpz_gcd_ui (res1, res1, in2i);
680 	MPZ_CHECK_FORMAT (res1);
681 	if (mpz_cmp (ref1, res1) != 0)
682 	  FAIL2 (mpz_gcd_ui, in1, in2, NULL);
683       }
684 
685       if (mpz_sgn (in2) != 0)
686 	{
687 	  /* Test mpz_remove */
688 	  mp_bitcnt_t refretval, retval;
689 	  refretval = mpz_remove (ref1, in1, in2);
690 	  MPZ_CHECK_FORMAT (ref1);
691 
692 	  mpz_set (res1, in1);
693 	  retval = mpz_remove (res1, res1, in2);
694 	  MPZ_CHECK_FORMAT (res1);
695 	  if (mpz_cmp (ref1, res1) != 0 || refretval != retval)
696 	    FAIL2 (mpz_remove, in1, in2, NULL);
697 
698 	  mpz_set (res1, in2);
699 	  retval = mpz_remove (res1, in1, res1);
700 	  MPZ_CHECK_FORMAT (res1);
701 	  if (mpz_cmp (ref1, res1) != 0 || refretval != retval)
702 	    FAIL2 (mpz_remove, in1, in2, NULL);
703 	}
704 
705       if (mpz_sgn (in2) != 0)
706 	{
707 	  /* Test mpz_divexact */
708 	  mpz_mul (t, in1, in2);
709 	  mpz_divexact (ref1, t, in2);
710 	  MPZ_CHECK_FORMAT (ref1);
711 
712 	  mpz_set (res1, t);
713 	  mpz_divexact (res1, res1, in2);
714 	  MPZ_CHECK_FORMAT (res1);
715 	  if (mpz_cmp (ref1, res1) != 0)
716 	    FAIL2 (mpz_divexact, t, in2, NULL);
717 
718 	  mpz_set (res1, in2);
719 	  mpz_divexact (res1, t, res1);
720 	  MPZ_CHECK_FORMAT (res1);
721 	  if (mpz_cmp (ref1, res1) != 0)
722 	    FAIL2 (mpz_divexact, t, in2, NULL);
723 	}
724 
725       if (mpz_sgn (in2) > 0)
726 	{
727 	  /* Test mpz_divexact_gcd, same as mpz_divexact */
728 	  mpz_mul (t, in1, in2);
729 	  mpz_divexact_gcd (ref1, t, in2);
730 	  MPZ_CHECK_FORMAT (ref1);
731 
732 	  mpz_set (res1, t);
733 	  mpz_divexact_gcd (res1, res1, in2);
734 	  MPZ_CHECK_FORMAT (res1);
735 	  if (mpz_cmp (ref1, res1) != 0)
736 	    FAIL2 (mpz_divexact_gcd, t, in2, NULL);
737 
738 	  mpz_set (res1, in2);
739 	  mpz_divexact_gcd (res1, t, res1);
740 	  MPZ_CHECK_FORMAT (res1);
741 	  if (mpz_cmp (ref1, res1) != 0)
742 	    FAIL2 (mpz_divexact_gcd, t, in2, NULL);
743 	}
744     }
745 
746   if (isatty (STDOUT_FILENO))
747     printf ("\r%20s", "");
748 
749   mpz_clear (bs);
750   mpz_clear (in1);
751   mpz_clear (in2);
752   mpz_clear (in3);
753   mpz_clear (ref1);
754   mpz_clear (ref2);
755   mpz_clear (ref3);
756   mpz_clear (res1);
757   mpz_clear (res2);
758   mpz_clear (res3);
759   mpz_clear (t);
760 
761   if (isatty (STDOUT_FILENO))
762     printf ("\r");
763 
764   tests_end ();
765   exit (0);
766 }
767 
768 void
dump(const char * name,mpz_t in1,mpz_t in2,mpz_t in3)769 dump (const char *name, mpz_t in1, mpz_t in2, mpz_t in3)
770 {
771   printf ("failure in %s (", name);
772   mpz_out_str (stdout, -16, in1);
773   if (in2 != NULL)
774     {
775       printf (" ");
776       mpz_out_str (stdout, -16, in2);
777     }
778   if (in3 != NULL)
779     {
780       printf (" ");
781       mpz_out_str (stdout, -16, in3);
782     }
783   printf (")\n");
784 }
785 
786 #endif /* ! DLL_EXPORT */
787