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