1 /* Test that routines allow reusing a source variable as destination.
2 
3 Copyright 1996, 1999-2002, 2009, 2012 Free Software Foundation, Inc.
4 
5 This file is part of the GNU MP Library test suite.
6 
7 The GNU MP Library test suite is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 3 of the License,
10 or (at your option) any later version.
11 
12 The GNU MP Library test suite is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
15 Public License for more details.
16 
17 You should have received a copy of the GNU General Public License along with
18 the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
19 
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 
24 #include "testutils.h"
25 
26 #define COUNT 100
27 
28 void dump3 (const char *, mpz_t, mpz_t, mpz_t);
29 void mpz_check_format (const mpz_t);
30 
31 typedef void (*dss_func) (mpz_t, const mpz_t, const mpz_t);
32 typedef void (*dsi_func) (mpz_t, const mpz_t, unsigned long int);
33 typedef unsigned long int (*dsi_div_func) (mpz_t, const mpz_t, unsigned long int);
34 typedef unsigned long int (*ddsi_div_func) (mpz_t, mpz_t, const mpz_t, unsigned long int);
35 typedef void (*ddss_div_func) (mpz_t, mpz_t, const mpz_t, const mpz_t);
36 typedef void (*ds_func) (mpz_t, const mpz_t);
37 
38 
39 void
mpz_xinvert(mpz_t r,const mpz_t a,const mpz_t b)40 mpz_xinvert (mpz_t r, const mpz_t a, const mpz_t b)
41 {
42   int res;
43   res = mpz_invert (r, a, b);
44   if (res == 0)
45     mpz_set_ui (r, 0);
46 }
47 
48 dss_func dss_funcs[] =
49 {
50   mpz_add, mpz_sub, mpz_mul,
51   mpz_cdiv_q, mpz_cdiv_r, mpz_fdiv_q, mpz_fdiv_r, mpz_tdiv_q, mpz_tdiv_r,
52   mpz_xinvert,
53   mpz_gcd, mpz_lcm, mpz_and, mpz_ior, mpz_xor
54 };
55 const char *dss_func_names[] =
56 {
57   "mpz_add", "mpz_sub", "mpz_mul",
58   "mpz_cdiv_q", "mpz_cdiv_r", "mpz_fdiv_q", "mpz_fdiv_r", "mpz_tdiv_q", "mpz_tdiv_r",
59   "mpz_xinvert",
60   "mpz_gcd", "mpz_lcm", "mpz_and", "mpz_ior", "mpz_xor"
61 };
62 char dss_func_division[] = {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0};
63 
64 dsi_func dsi_funcs[] =
65 {
66   /* Don't change order here without changing the code in main(). */
67   mpz_add_ui, mpz_mul_ui, mpz_sub_ui,
68   mpz_fdiv_q_2exp, mpz_fdiv_r_2exp,
69   mpz_cdiv_q_2exp, mpz_cdiv_r_2exp,
70   mpz_tdiv_q_2exp, mpz_tdiv_r_2exp,
71   mpz_mul_2exp,
72   mpz_pow_ui
73 };
74 const char *dsi_func_names[] =
75 {
76   "mpz_add_ui", "mpz_mul_ui", "mpz_sub_ui",
77   "mpz_fdiv_q_2exp", "mpz_fdiv_r_2exp",
78   "mpz_cdiv_q_2exp", "mpz_cdiv_r_2exp",
79   "mpz_tdiv_q_2exp", "mpz_tdiv_r_2exp",
80   "mpz_mul_2exp",
81   "mpz_pow_ui"
82 };
83 
84 dsi_div_func dsi_div_funcs[] =
85 {
86   mpz_cdiv_q_ui, mpz_cdiv_r_ui,
87   mpz_fdiv_q_ui, mpz_fdiv_r_ui,
88   mpz_tdiv_q_ui, mpz_tdiv_r_ui
89 };
90 const char *dsi_div_func_names[] =
91 {
92   "mpz_cdiv_q_ui", "mpz_cdiv_r_ui",
93   "mpz_fdiv_q_ui", "mpz_fdiv_r_ui",
94   "mpz_tdiv_q_ui", "mpz_tdiv_r_ui"
95 };
96 
97 ddsi_div_func ddsi_div_funcs[] =
98 {
99   mpz_cdiv_qr_ui,
100   mpz_fdiv_qr_ui,
101   mpz_tdiv_qr_ui
102 };
103 const char *ddsi_div_func_names[] =
104 {
105   "mpz_cdiv_qr_ui",
106   "mpz_fdiv_qr_ui",
107   "mpz_tdiv_qr_ui"
108 };
109 
110 ddss_div_func ddss_div_funcs[] =
111 {
112   mpz_cdiv_qr,
113   mpz_fdiv_qr,
114   mpz_tdiv_qr
115 };
116 const char *ddss_div_func_names[] =
117 {
118   "mpz_cdiv_qr",
119   "mpz_fdiv_qr",
120   "mpz_tdiv_qr"
121 };
122 
123 ds_func ds_funcs[] =
124 {
125   mpz_abs, mpz_com, mpz_neg, mpz_sqrt
126 };
127 const char *ds_func_names[] =
128 {
129   "mpz_abs", "mpz_com", "mpz_neg", "mpz_sqrt"
130 };
131 
132 
133 #define FAIL(class,indx,op1,op2,op3) \
134   do {									\
135   class##_funcs[indx] = 0;						\
136   dump3 (class##_func_names[indx], op1, op2, op3);			\
137   failures++;								\
138   } while (0)
139 #define FAIL2(fname,op1,op2,op3) \
140   do {									\
141   dump3 (#fname, op1, op2, op3);						\
142   failures++;								\
143   } while (0)
144 
145 void
testmain(int argc,char ** argv)146 testmain (int argc, char **argv)
147 {
148   unsigned i;
149   int pass, reps = COUNT;
150   mpz_t in1, in2, in3;
151   unsigned long int in2i;
152   mp_size_t size;
153   mpz_t res1, res2, res3;
154   mpz_t ref1, ref2, ref3;
155   mpz_t t;
156   unsigned long int r1, r2;
157   long failures = 0;
158   mpz_t bs;
159   unsigned long bsi, size_range;
160 
161   mpz_init (bs);
162 
163   mpz_init (in1);
164   mpz_init (in2);
165   mpz_init (in3);
166   mpz_init (ref1);
167   mpz_init (ref2);
168   mpz_init (ref3);
169   mpz_init (res1);
170   mpz_init (res2);
171   mpz_init (res3);
172   mpz_init (t);
173 
174   for (pass = 1; pass <= reps; pass++)
175     {
176       mini_urandomb (bs, 32);
177       size_range = mpz_get_ui (bs) % 12 + 2;
178 
179       mini_urandomb (bs, size_range);
180       size = mpz_get_ui (bs);
181       mini_rrandomb (in1, size);
182 
183       mini_urandomb (bs, size_range);
184       size = mpz_get_ui (bs);
185       mini_rrandomb (in2, size);
186 
187       mini_urandomb (bs, size_range);
188       size = mpz_get_ui (bs);
189       mini_rrandomb (in3, size);
190 
191       mini_urandomb (bs, 3);
192       bsi = mpz_get_ui (bs);
193       if ((bsi & 1) != 0)
194 	mpz_neg (in1, in1);
195       if ((bsi & 2) != 0)
196 	mpz_neg (in2, in2);
197       if ((bsi & 4) != 0)
198 	mpz_neg (in3, in3);
199 
200       for (i = 0; i < sizeof (dss_funcs) / sizeof (dss_func); i++)
201 	{
202 	  if (dss_funcs[i] == 0)
203 	    continue;
204 	  if (dss_func_division[i] && mpz_sgn (in2) == 0)
205 	    continue;
206 
207 	  (dss_funcs[i]) (ref1, in1, in2);
208 	  mpz_check_format (ref1);
209 
210 	  mpz_set (res1, in1);
211 	  (dss_funcs[i]) (res1, res1, in2);
212 	  mpz_check_format (res1);
213 	  if (mpz_cmp (ref1, res1) != 0)
214 	    FAIL (dss, i, in1, in2, NULL);
215 
216 	  mpz_set (res1, in2);
217 	  (dss_funcs[i]) (res1, in1, res1);
218 	  mpz_check_format (res1);
219 	  if (mpz_cmp (ref1, res1) != 0)
220 	    FAIL (dss, i, in1, in2, NULL);
221 	}
222 
223       for (i = 0; i < sizeof (ddss_div_funcs) / sizeof (ddss_div_func); i++)
224 	{
225 	  if (ddss_div_funcs[i] == 0)
226 	    continue;
227 	  if (mpz_sgn (in2) == 0)
228 	    continue;
229 
230 	  (ddss_div_funcs[i]) (ref1, ref2, in1, in2);
231 	  mpz_check_format (ref1);
232 	  mpz_check_format (ref2);
233 
234 	  mpz_set (res1, in1);
235 	  (ddss_div_funcs[i]) (res1, res2, res1, in2);
236 	  mpz_check_format (res1);
237 	  mpz_check_format (res2);
238 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
239 	    FAIL (ddss_div, i, in1, in2, NULL);
240 
241 	  mpz_set (res2, in1);
242 	  (ddss_div_funcs[i]) (res1, res2, res2, in2);
243 	  mpz_check_format (res1);
244 	  mpz_check_format (res2);
245 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
246 	    FAIL (ddss_div, i, in1, in2, NULL);
247 
248 	  mpz_set (res1, in2);
249 	  (ddss_div_funcs[i]) (res1, res2, in1, res1);
250 	  mpz_check_format (res1);
251 	  mpz_check_format (res2);
252 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
253 	    FAIL (ddss_div, i, in1, in2, NULL);
254 
255 	  mpz_set (res2, in2);
256 	  (ddss_div_funcs[i]) (res1, res2, in1, res2);
257 	  mpz_check_format (res1);
258 	  mpz_check_format (res2);
259 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
260 	    FAIL (ddss_div, i, in1, in2, NULL);
261 	}
262 
263       for (i = 0; i < sizeof (ds_funcs) / sizeof (ds_func); i++)
264 	{
265 	  if (ds_funcs[i] == 0)
266 	    continue;
267 	  if (strcmp (ds_func_names[i], "mpz_sqrt") == 0
268 	      && mpz_sgn (in1) < 0)
269 	    continue;
270 
271 	  (ds_funcs[i]) (ref1, in1);
272 	  mpz_check_format (ref1);
273 
274 	  mpz_set (res1, in1);
275 	  (ds_funcs[i]) (res1, res1);
276 	  mpz_check_format (res1);
277 	  if (mpz_cmp (ref1, res1) != 0)
278 	    FAIL (ds, i, in1, in2, NULL);
279 	}
280 
281       in2i = mpz_get_ui (in2);
282 
283       for (i = 0; i < sizeof (dsi_funcs) / sizeof (dsi_func); i++)
284 	{
285 	  if (dsi_funcs[i] == 0)
286 	    continue;
287 	  if (strcmp (dsi_func_names[i], "mpz_fdiv_q_2exp") == 0)
288 	    /* Limit exponent to something reasonable for the division
289 	       functions.  Without this, we'd  normally shift things off
290 	       the end and just generate the trivial values 1, 0, -1.  */
291 	    in2i %= 0x1000;
292 	  if (strcmp (dsi_func_names[i], "mpz_mul_2exp") == 0)
293 	    /* Limit exponent more for mpz_mul_2exp to save time.  */
294 	    in2i %= 0x100;
295 	  if (strcmp (dsi_func_names[i], "mpz_pow_ui") == 0)
296 	    /* Limit exponent yet more for mpz_pow_ui to save time.  */
297 	    in2i %= 0x10;
298 
299 	  (dsi_funcs[i]) (ref1, in1, in2i);
300 	  mpz_check_format (ref1);
301 
302 	  mpz_set (res1, in1);
303 	  (dsi_funcs[i]) (res1, res1, in2i);
304 	  mpz_check_format (res1);
305 	  if (mpz_cmp (ref1, res1) != 0)
306 	    FAIL (dsi, i, in1, in2, NULL);
307 	}
308 
309       if (in2i != 0)	  /* Don't divide by 0.  */
310 	{
311 	  for (i = 0; i < sizeof (dsi_div_funcs) / sizeof (dsi_div_funcs); i++)
312 	    {
313 	      r1 = (dsi_div_funcs[i]) (ref1, in1, in2i);
314 	      mpz_check_format (ref1);
315 
316 	      mpz_set (res1, in1);
317 	      r2 = (dsi_div_funcs[i]) (res1, res1, in2i);
318 	      mpz_check_format (res1);
319 	      if (mpz_cmp (ref1, res1) != 0 || r1 != r2)
320 		FAIL (dsi_div, i, in1, in2, NULL);
321 	    }
322 
323 	  for (i = 0; i < sizeof (ddsi_div_funcs) / sizeof (ddsi_div_funcs); i++)
324 	    {
325 	      r1 = (ddsi_div_funcs[i]) (ref1, ref2, in1, in2i);
326 	      mpz_check_format (ref1);
327 
328 	      mpz_set (res1, in1);
329 	      r2 = (ddsi_div_funcs[i]) (res1, res2, res1, in2i);
330 	      mpz_check_format (res1);
331 	      if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || r1 != r2)
332 		FAIL (ddsi_div, i, in1, in2, NULL);
333 
334 	      mpz_set (res2, in1);
335 	      (ddsi_div_funcs[i]) (res1, res2, res2, in2i);
336 	      mpz_check_format (res1);
337 	      if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || r1 != r2)
338 		FAIL (ddsi_div, i, in1, in2, NULL);
339 	    }
340 	}
341 
342       if (mpz_sgn (in1) >= 0)
343 	{
344 	  mpz_sqrtrem (ref1, ref2, in1);
345 	  mpz_check_format (ref1);
346 	  mpz_check_format (ref2);
347 
348 	  mpz_set (res1, in1);
349 	  mpz_sqrtrem (res1, res2, res1);
350 	  mpz_check_format (res1);
351 	  mpz_check_format (res2);
352 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
353 	    FAIL2 (mpz_sqrtrem, in1, NULL, NULL);
354 
355 	  mpz_set (res2, in1);
356 	  mpz_sqrtrem (res1, res2, res2);
357 	  mpz_check_format (res1);
358 	  mpz_check_format (res2);
359 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
360 	    FAIL2 (mpz_sqrtrem, in1, NULL, NULL);
361 	}
362 
363       if (mpz_sgn (in1) >= 0)
364 	{
365 	  mpz_root (ref1, in1, in2i % 0x1000 + 1);
366 	  mpz_check_format (ref1);
367 
368 	  mpz_set (res1, in1);
369 	  mpz_root (res1, res1, in2i % 0x1000 + 1);
370 	  mpz_check_format (res1);
371 	  if (mpz_cmp (ref1, res1) != 0)
372 	    FAIL2 (mpz_root, in1, in2, NULL);
373 	}
374 
375       if (mpz_sgn (in1) >= 0)
376 	{
377 	  mpz_rootrem (ref1, ref2, in1, in2i % 0x1000 + 1);
378 	  mpz_check_format (ref1);
379 	  mpz_check_format (ref2);
380 
381 	  mpz_set (res1, in1);
382 	  mpz_rootrem (res1, res2, res1, in2i % 0x1000 + 1);
383 	  mpz_check_format (res1);
384 	  mpz_check_format (res2);
385 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
386 	    FAIL2 (mpz_rootrem, in1, in2, NULL);
387 
388 	  mpz_set (res2, in1);
389 	  mpz_rootrem (res1, res2, res2, in2i % 0x1000 + 1);
390 	  mpz_check_format (res1);
391 	  mpz_check_format (res2);
392 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
393 	    FAIL2 (mpz_rootrem, in1, in2, NULL);
394 	}
395 
396       if (pass < reps / 2)	/* run fewer tests since gcdext lots of time */
397 	{
398 	  mpz_gcdext (ref1, ref2, ref3, in1, in2);
399 	  mpz_check_format (ref1);
400 	  mpz_check_format (ref2);
401 	  mpz_check_format (ref3);
402 
403 	  mpz_set (res1, in1);
404 	  mpz_gcdext (res1, res2, res3, res1, in2);
405 	  mpz_check_format (res1);
406 	  mpz_check_format (res2);
407 	  mpz_check_format (res3);
408 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
409 	      || mpz_cmp (ref3, res3) != 0)
410 	    FAIL2 (mpz_gcdext, in1, in2, NULL);
411 
412 	  mpz_set (res2, in1);
413 	  mpz_gcdext (res1, res2, res3, res2, in2);
414 	  mpz_check_format (res1);
415 	  mpz_check_format (res2);
416 	  mpz_check_format (res3);
417 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
418 	      || mpz_cmp (ref3, res3) != 0)
419 	    FAIL2 (mpz_gcdext, in1, in2, NULL);
420 
421 	  mpz_set (res3, in1);
422 	  mpz_gcdext (res1, res2, res3, res3, in2);
423 	  mpz_check_format (res1);
424 	  mpz_check_format (res2);
425 	  mpz_check_format (res3);
426 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
427 	      || mpz_cmp (ref3, res3) != 0)
428 	    FAIL2 (mpz_gcdext, in1, in2, NULL);
429 
430 	  mpz_set (res1, in2);
431 	  mpz_gcdext (res1, res2, res3, in1, res1);
432 	  mpz_check_format (res1);
433 	  mpz_check_format (res2);
434 	  mpz_check_format (res3);
435 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
436 	      || mpz_cmp (ref3, res3) != 0)
437 	    FAIL2 (mpz_gcdext, in1, in2, NULL);
438 
439 	  mpz_set (res2, in2);
440 	  mpz_gcdext (res1, res2, res3, in1, res2);
441 	  mpz_check_format (res1);
442 	  mpz_check_format (res2);
443 	  mpz_check_format (res3);
444 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
445 	      || mpz_cmp (ref3, res3) != 0)
446 	    FAIL2 (mpz_gcdext, in1, in2, NULL);
447 
448 	  mpz_set (res3, in2);
449 	  mpz_gcdext (res1, res2, res3, in1, res3);
450 	  mpz_check_format (res1);
451 	  mpz_check_format (res2);
452 	  mpz_check_format (res3);
453 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
454 	      || mpz_cmp (ref3, res3) != 0)
455 	    FAIL2 (mpz_gcdext, in1, in2, NULL);
456 
457 	  mpz_set (res1, in1);
458 	  mpz_gcdext (res1, res2, NULL, res1, in2);
459 	  mpz_check_format (res1);
460 	  mpz_check_format (res2);
461 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
462 	      || mpz_cmp (ref3, res3) != 0)
463 	    FAIL2 (mpz_gcdext, in1, in2, NULL);
464 
465 	  mpz_set (res2, in1);
466 	  mpz_gcdext (res1, res2, NULL, res2, in2);
467 	  mpz_check_format (res1);
468 	  mpz_check_format (res2);
469 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
470 	      || mpz_cmp (ref3, res3) != 0)
471 	    FAIL2 (mpz_gcdext, in1, in2, NULL);
472 
473 	  mpz_set (res1, in2);
474 	  mpz_gcdext (res1, res2, NULL, in1, res1);
475 	  mpz_check_format (res1);
476 	  mpz_check_format (res2);
477 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
478 	      || mpz_cmp (ref3, res3) != 0)
479 	    FAIL2 (mpz_gcdext, in1, in2, NULL);
480 
481 	  mpz_set (res2, in2);
482 	  mpz_gcdext (res1, res2, NULL, in1, res2);
483 	  mpz_check_format (res1);
484 	  mpz_check_format (res2);
485 	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
486 	      || mpz_cmp (ref3, res3) != 0)
487 	    FAIL2 (mpz_gcdext, in1, in2, NULL);
488 	}
489 
490       /* Don't run mpz_powm for huge exponents or when undefined.  */
491       if (mpz_sizeinbase (in2, 2) < 250 && mpz_sgn (in3) != 0
492 	  && (mpz_sgn (in2) >= 0 || mpz_invert (t, in1, in3)))
493 	{
494 	  mpz_powm (ref1, in1, in2, in3);
495 	  mpz_check_format (ref1);
496 
497 	  mpz_set (res1, in1);
498 	  mpz_powm (res1, res1, in2, in3);
499 	  mpz_check_format (res1);
500 	  if (mpz_cmp (ref1, res1) != 0)
501 	    FAIL2 (mpz_powm, in1, in2, in3);
502 
503 	  mpz_set (res1, in2);
504 	  mpz_powm (res1, in1, res1, in3);
505 	  mpz_check_format (res1);
506 	  if (mpz_cmp (ref1, res1) != 0)
507 	    FAIL2 (mpz_powm, in1, in2, in3);
508 
509 	  mpz_set (res1, in3);
510 	  mpz_powm (res1, in1, in2, res1);
511 	  mpz_check_format (res1);
512 	  if (mpz_cmp (ref1, res1) != 0)
513 	    FAIL2 (mpz_powm, in1, in2, in3);
514 	}
515 
516       /* Don't run mpz_powm_ui when undefined.  */
517       if (mpz_sgn (in3) != 0)
518 	{
519 	  mpz_powm_ui (ref1, in1, in2i, in3);
520 	  mpz_check_format (ref1);
521 
522 	  mpz_set (res1, in1);
523 	  mpz_powm_ui (res1, res1, in2i, in3);
524 	  mpz_check_format (res1);
525 	  if (mpz_cmp (ref1, res1) != 0)
526 	    FAIL2 (mpz_powm_ui, in1, in2, in3);
527 
528 	  mpz_set (res1, in3);
529 	  mpz_powm_ui (res1, in1, in2i, res1);
530 	  mpz_check_format (res1);
531 	  if (mpz_cmp (ref1, res1) != 0)
532 	    FAIL2 (mpz_powm_ui, in1, in2, in3);
533 	}
534 
535       {
536 	r1 = mpz_gcd_ui (ref1, in1, in2i);
537 	mpz_check_format (ref1);
538 
539 	mpz_set (res1, in1);
540 	r2 = mpz_gcd_ui (res1, res1, in2i);
541 	mpz_check_format (res1);
542 	if (mpz_cmp (ref1, res1) != 0)
543 	  FAIL2 (mpz_gcd_ui, in1, in2, NULL);
544       }
545 #if 0
546       if (mpz_cmp_ui (in2, 1L) > 0 && mpz_sgn (in1) != 0)
547 	{
548 	  /* Test mpz_remove */
549 	  mpz_remove (ref1, in1, in2);
550 	  mpz_check_format (ref1);
551 
552 	  mpz_set (res1, in1);
553 	  mpz_remove (res1, res1, in2);
554 	  mpz_check_format (res1);
555 	  if (mpz_cmp (ref1, res1) != 0)
556 	    FAIL2 (mpz_remove, in1, in2, NULL);
557 
558 	  mpz_set (res1, in2);
559 	  mpz_remove (res1, in1, res1);
560 	  mpz_check_format (res1);
561 	  if (mpz_cmp (ref1, res1) != 0)
562 	    FAIL2 (mpz_remove, in1, in2, NULL);
563 	}
564 #endif
565       if (mpz_sgn (in2) != 0)
566 	{
567 	  /* Test mpz_divexact */
568 	  mpz_mul (t, in1, in2);
569 	  mpz_divexact (ref1, t, in2);
570 	  mpz_check_format (ref1);
571 
572 	  mpz_set (res1, t);
573 	  mpz_divexact (res1, res1, in2);
574 	  mpz_check_format (res1);
575 	  if (mpz_cmp (ref1, res1) != 0)
576 	    FAIL2 (mpz_divexact, t, in2, NULL);
577 
578 	  mpz_set (res1, in2);
579 	  mpz_divexact (res1, t, res1);
580 	  mpz_check_format (res1);
581 	  if (mpz_cmp (ref1, res1) != 0)
582 	    FAIL2 (mpz_divexact, t, in2, NULL);
583 	}
584 
585 #if 0
586       if (mpz_sgn (in2) > 0)
587 	{
588 	  /* Test mpz_divexact_gcd, same as mpz_divexact */
589 	  mpz_mul (t, in1, in2);
590 	  mpz_divexact_gcd (ref1, t, in2);
591 	  mpz_check_format (ref1);
592 
593 	  mpz_set (res1, t);
594 	  mpz_divexact_gcd (res1, res1, in2);
595 	  mpz_check_format (res1);
596 	  if (mpz_cmp (ref1, res1) != 0)
597 	    FAIL2 (mpz_divexact_gcd, t, in2, NULL);
598 
599 	  mpz_set (res1, in2);
600 	  mpz_divexact_gcd (res1, t, res1);
601 	  mpz_check_format (res1);
602 	  if (mpz_cmp (ref1, res1) != 0)
603 	    FAIL2 (mpz_divexact_gcd, t, in2, NULL);
604 	}
605 #endif
606     }
607 
608   if (failures != 0)
609     {
610       fprintf (stderr, "mpz/reuse: %ld error%s\n", failures, "s" + (failures == 1));
611       exit (1);
612     }
613 
614   mpz_clear (bs);
615   mpz_clear (in1);
616   mpz_clear (in2);
617   mpz_clear (in3);
618   mpz_clear (ref1);
619   mpz_clear (ref2);
620   mpz_clear (ref3);
621   mpz_clear (res1);
622   mpz_clear (res2);
623   mpz_clear (res3);
624   mpz_clear (t);
625 }
626 
627 void
dump3(const char * name,mpz_t in1,mpz_t in2,mpz_t in3)628 dump3 (const char *name, mpz_t in1, mpz_t in2, mpz_t in3)
629 {
630   printf ("failure in %s (", name);
631   mpz_out_str (stdout, -16, in1);
632   if (in2 != NULL)
633     {
634       printf (" ");
635       mpz_out_str (stdout, -16, in2);
636     }
637   if (in3 != NULL)
638     {
639       printf (" ");
640       mpz_out_str (stdout, -16, in3);
641     }
642   printf (")\n");
643 }
644 
645 void
mpz_check_format(const mpz_t x)646 mpz_check_format (const mpz_t x)
647 {
648   mp_size_t n = x ->_mp_size;
649   if (n < 0)
650     n = - n;
651 
652   if (n > x->_mp_alloc)
653     {
654       fprintf (stderr, "mpz_t size exceeds allocation!\n");
655       abort ();
656     }
657 
658   if (n > 0 && x->_mp_d[n-1] == 0)
659     {
660       fprintf (stderr, "Unnormalized mpz_t!\n");
661       abort ();
662     }
663 }
664