blob: f057a9672ae1e8c49909ca16aa5104c19fc7e0ad [file] [log] [blame]
Austin Schuhbb1338c2024-06-15 19:31:16 -07001/* 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
9Copyright 1996, 1999-2002, 2009, 2012, 2013, 2016 Free Software Foundation,
10Inc.
11
12This file is part of the GNU MP Library test suite.
13
14The GNU MP Library test suite is free software; you can redistribute it
15and/or modify it under the terms of the GNU General Public License as
16published by the Free Software Foundation; either version 3 of the License,
17or (at your option) any later version.
18
19The GNU MP Library test suite is distributed in the hope that it will be
20useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
21MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
22Public License for more details.
23
24You should have received a copy of the GNU General Public License along with
25the 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
42int
43main (void)
44{
45 printf ("Test suppressed for windows DLL\n");
46 exit (0);
47}
48
49
50#else /* ! DLL_EXPORT */
51
52void dump (const char *, mpz_t, mpz_t, mpz_t);
53
54typedef void (*dss_func) (mpz_ptr, mpz_srcptr, mpz_srcptr);
55typedef void (*dsi_func) (mpz_ptr, mpz_srcptr, unsigned long int);
56typedef unsigned long int (*dsi_div_func) (mpz_ptr, mpz_srcptr, unsigned long int);
57typedef unsigned long int (*ddsi_div_func) (mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int);
58typedef void (*ddss_div_func) (mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr);
59typedef void (*ds_func) (mpz_ptr, mpz_srcptr);
60
61
62void
63mpz_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
71struct {
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
96struct {
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
116struct {
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
129struct {
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
141struct {
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
152struct {
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
200int
201main (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
762void
763dump (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 */