Home | History | Annotate | Line # | Download | only in mpz
      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