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 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 void 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 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 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