(root)/
gmp-6.3.0/
tests/
mpz/
reuse.c
       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 */