Home | History | Annotate | Line # | Download | only in devel
try.c revision 1.1
      1 /* Run some tests on various mpn routines.
      2 
      3    THIS IS A TEST PROGRAM USED ONLY FOR DEVELOPMENT.  IT'S ALMOST CERTAIN TO
      4    BE SUBJECT TO INCOMPATIBLE CHANGES IN FUTURE VERSIONS OF GMP.
      5 
      6 Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009 Free Software
      7 Foundation, Inc.
      8 
      9 This file is part of the GNU MP Library.
     10 
     11 The GNU MP Library is free software; you can redistribute it and/or modify
     12 it under the terms of the GNU Lesser General Public License as published by
     13 the Free Software Foundation; either version 3 of the License, or (at your
     14 option) any later version.
     15 
     16 The GNU MP Library is distributed in the hope that it will be useful, but
     17 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     18 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
     19 License for more details.
     20 
     21 You should have received a copy of the GNU Lesser General Public License
     22 along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
     23 
     24 
     25 /* Usage: try [options] <function>...
     26 
     27    For example, "./try mpn_add_n" to run tests of that function.
     28 
     29    Combinations of alignments and overlaps are tested, with redzones above
     30    or below the destinations, and with the sources write-protected.
     31 
     32    The number of tests performed becomes ridiculously large with all the
     33    combinations, and for that reason this can't be a part of a "make check",
     34    it's meant only for development.  The code isn't very pretty either.
     35 
     36    During development it can help to disable the redzones, since seeing the
     37    rest of the destination written can show where the wrong part is, or if
     38    the dst pointers are off by 1 or whatever.  The magic DEADVAL initial
     39    fill (see below) will show locations never written.
     40 
     41    The -s option can be used to test only certain size operands, which is
     42    useful if some new code doesn't yet support say sizes less than the
     43    unrolling, or whatever.
     44 
     45    When a problem occurs it'll of course be necessary to run the program
     46    under gdb to find out quite where, how and why it's going wrong.  Disable
     47    the spinner with the -W option when doing this, or single stepping won't
     48    work.  Using the "-1" option to run with simple data can be useful.
     49 
     50    New functions to test can be added in try_array[].  If a new TYPE is
     51    required then add it to the existing constants, set up its parameters in
     52    param_init(), and add it to the call() function.  Extra parameter fields
     53    can be added if necessary, or further interpretations given to existing
     54    fields.
     55 
     56 
     57    Portability:
     58 
     59    This program is not designed for use on Cray vector systems under Unicos,
     60    it will fail to compile due to missing _SC_PAGE_SIZE.  Those systems
     61    don't really have pages or mprotect.  We could arrange to run the tests
     62    without the redzones, but we haven't bothered currently.
     63 
     64 
     65    Enhancements:
     66 
     67    umul_ppmm support is not very good, lots of source data is generated
     68    whereas only two limbs are needed.
     69 
     70    Make a little scheme for interpreting the "SIZE" selections uniformly.
     71 
     72    Make tr->size==SIZE_2 work, for the benefit of find_a which wants just 2
     73    source limbs.  Possibly increase the default repetitions in that case.
     74 
     75    Automatically detect gdb and disable the spinner (use -W for now).
     76 
     77    Make a way to re-run a failing case in the debugger.  Have an option to
     78    snapshot each test case before it's run so the data is available if a
     79    segv occurs.  (This should be more reliable than the current print_all()
     80    in the signal handler.)
     81 
     82    When alignment means a dst isn't hard against the redzone, check the
     83    space in between remains unchanged.
     84 
     85    When a source overlaps a destination, don't run both s[i].high 0 and 1,
     86    as s[i].high has no effect.  Maybe encode s[i].high into overlap->s[i].
     87 
     88    When partial overlaps aren't done, don't loop over source alignments
     89    during overlaps.
     90 
     91    Try to make the looping code a bit less horrible.  Right now it's pretty
     92    hard to see what iterations are actually done.
     93 
     94    Perhaps specific setups and loops for each style of function under test
     95    would be clearer than a parameterized general loop.  There's lots of
     96    stuff common to all functions, but the exceptions get messy.
     97 
     98    When there's no overlap, run with both src>dst and src<dst.  A subtle
     99    calling-conventions violation occurred in a P6 copy which depended on the
    100    relative location of src and dst.
    101 
    102    multiplier_N is more or less a third source region for the addmul_N
    103    routines, and could be done with the redzoned region scheme.
    104 
    105 */
    106 
    107 
    108 /* always do assertion checking */
    109 #define WANT_ASSERT 1
    110 
    111 #include "config.h"
    112 
    113 #include <errno.h>
    114 #include <limits.h>
    115 #include <signal.h>
    116 #include <stdio.h>
    117 #include <stdlib.h>
    118 #include <string.h>
    119 #include <time.h>
    120 
    121 #if HAVE_UNISTD_H
    122 #include <unistd.h>
    123 #endif
    124 
    125 #if HAVE_SYS_MMAN_H
    126 #include <sys/mman.h>
    127 #endif
    128 
    129 #include "gmp.h"
    130 #include "gmp-impl.h"
    131 #include "longlong.h"
    132 #include "tests.h"
    133 
    134 
    135 #if !HAVE_DECL_OPTARG
    136 extern char *optarg;
    137 extern int optind, opterr;
    138 #endif
    139 
    140 #if ! HAVE_DECL_SYS_NERR
    141 extern int sys_nerr;
    142 #endif
    143 
    144 #if ! HAVE_DECL_SYS_ERRLIST
    145 extern char *sys_errlist[];
    146 #endif
    147 
    148 #if ! HAVE_STRERROR
    149 char *
    150 strerror (int n)
    151 {
    152   if (n < 0 || n >= sys_nerr)
    153     return "errno out of range";
    154   else
    155     return sys_errlist[n];
    156 }
    157 #endif
    158 
    159 /* Rumour has it some systems lack a define of PROT_NONE. */
    160 #ifndef PROT_NONE
    161 #define PROT_NONE   0
    162 #endif
    163 
    164 /* Dummy defines for when mprotect doesn't exist. */
    165 #ifndef PROT_READ
    166 #define PROT_READ   0
    167 #endif
    168 #ifndef PROT_WRITE
    169 #define PROT_WRITE  0
    170 #endif
    171 
    172 /* _SC_PAGESIZE is standard, but hpux 9 and possibly other systems have
    173    _SC_PAGE_SIZE instead. */
    174 #if defined (_SC_PAGE_SIZE) && ! defined (_SC_PAGESIZE)
    175 #define _SC_PAGESIZE  _SC_PAGE_SIZE
    176 #endif
    177 
    178 
    179 #ifdef EXTRA_PROTOS
    180 EXTRA_PROTOS
    181 #endif
    182 #ifdef EXTRA_PROTOS2
    183 EXTRA_PROTOS2
    184 #endif
    185 
    186 
    187 #define DEFAULT_REPETITIONS  10
    188 
    189 int  option_repetitions = DEFAULT_REPETITIONS;
    190 int  option_spinner = 1;
    191 int  option_redzones = 1;
    192 int  option_firstsize = 0;
    193 int  option_lastsize = 500;
    194 int  option_firstsize2 = 0;
    195 
    196 #define ALIGNMENTS          4
    197 #define OVERLAPS            4
    198 #define CARRY_RANDOMS       5
    199 #define MULTIPLIER_RANDOMS  5
    200 #define DIVISOR_RANDOMS     5
    201 #define FRACTION_COUNT      4
    202 
    203 int  option_print = 0;
    204 
    205 #define DATA_TRAND  0
    206 #define DATA_ZEROS  1
    207 #define DATA_SEQ    2
    208 #define DATA_FFS    3
    209 #define DATA_2FD    4
    210 int  option_data = DATA_TRAND;
    211 
    212 
    213 mp_size_t  pagesize;
    214 #define PAGESIZE_LIMBS  (pagesize / BYTES_PER_MP_LIMB)
    215 
    216 /* must be a multiple of the page size */
    217 #define REDZONE_BYTES   (pagesize * 16)
    218 #define REDZONE_LIMBS   (REDZONE_BYTES / BYTES_PER_MP_LIMB)
    219 
    220 
    221 #define MAX3(x,y,z)   (MAX (x, MAX (y, z)))
    222 
    223 #if GMP_LIMB_BITS == 32
    224 #define DEADVAL  CNST_LIMB(0xDEADBEEF)
    225 #else
    226 #define DEADVAL  CNST_LIMB(0xDEADBEEFBADDCAFE)
    227 #endif
    228 
    229 
    230 struct region_t {
    231   mp_ptr     ptr;
    232   mp_size_t  size;
    233 };
    234 
    235 
    236 #define TRAP_NOWHERE 0
    237 #define TRAP_REF     1
    238 #define TRAP_FUN     2
    239 #define TRAP_SETUPS  3
    240 int trap_location = TRAP_NOWHERE;
    241 
    242 
    243 #define NUM_SOURCES  2
    244 #define NUM_DESTS    2
    245 
    246 struct source_t {
    247   struct region_t  region;
    248   int        high;
    249   mp_size_t  align;
    250   mp_ptr     p;
    251 };
    252 
    253 struct source_t  s[NUM_SOURCES];
    254 
    255 struct dest_t {
    256   int        high;
    257   mp_size_t  align;
    258   mp_size_t  size;
    259 };
    260 
    261 struct dest_t  d[NUM_DESTS];
    262 
    263 struct source_each_t {
    264   mp_ptr     p;
    265 };
    266 
    267 struct dest_each_t {
    268   struct region_t  region;
    269   mp_ptr     p;
    270 };
    271 
    272 mp_size_t       size;
    273 mp_size_t       size2;
    274 unsigned long   shift;
    275 mp_limb_t       carry;
    276 mp_limb_t       divisor;
    277 mp_limb_t       multiplier;
    278 mp_limb_t       multiplier_N[8];
    279 
    280 struct each_t {
    281   const char  *name;
    282   struct dest_each_t    d[NUM_DESTS];
    283   struct source_each_t  s[NUM_SOURCES];
    284   mp_limb_t  retval;
    285 };
    286 
    287 struct each_t  ref = { "Ref" };
    288 struct each_t  fun = { "Fun" };
    289 
    290 #define SRC_SIZE(n)  ((n) == 1 && tr->size2 ? size2 : size)
    291 
    292 void validate_fail __GMP_PROTO ((void));
    293 
    294 
    295 #if HAVE_TRY_NEW_C
    296 #include "try-new.c"
    297 #endif
    298 
    299 
    300 typedef mp_limb_t (*tryfun_t) __GMP_PROTO ((ANYARGS));
    301 
    302 struct try_t {
    303   char  retval;
    304 
    305   char  src[2];
    306   char  dst[2];
    307 
    308 #define SIZE_YES          1
    309 #define SIZE_ALLOW_ZERO   2
    310 #define SIZE_1            3  /* 1 limb  */
    311 #define SIZE_2            4  /* 2 limbs */
    312 #define SIZE_3            5  /* 3 limbs */
    313 #define SIZE_FRACTION     6  /* size2 is fraction for divrem etc */
    314 #define SIZE_SIZE2        7
    315 #define SIZE_PLUS_1       8
    316 #define SIZE_SUM          9
    317 #define SIZE_DIFF        10
    318 #define SIZE_DIFF_PLUS_1 11
    319 #define SIZE_RETVAL      12
    320 #define SIZE_CEIL_HALF   13
    321 #define SIZE_GET_STR     14
    322 #define SIZE_PLUS_MSIZE_SUB_1 15  /* size+msize-1 */
    323   char  size;
    324   char  size2;
    325   char  dst_size[2];
    326 
    327   /* multiplier_N size in limbs */
    328   mp_size_t  msize;
    329 
    330   char  dst_bytes[2];
    331 
    332   char  dst0_from_src1;
    333 
    334 #define CARRY_BIT     1  /* single bit 0 or 1 */
    335 #define CARRY_3       2  /* 0, 1, 2 */
    336 #define CARRY_4       3  /* 0 to 3 */
    337 #define CARRY_LIMB    4  /* any limb value */
    338 #define CARRY_DIVISOR 5  /* carry<divisor */
    339   char  carry;
    340 
    341   /* a fudge to tell the output when to print negatives */
    342   char  carry_sign;
    343 
    344   char  multiplier;
    345   char  shift;
    346 
    347 #define DIVISOR_LIMB  1
    348 #define DIVISOR_NORM  2
    349 #define DIVISOR_ODD   3
    350   char  divisor;
    351 
    352 #define DATA_NON_ZERO         1
    353 #define DATA_GCD              2
    354 #define DATA_SRC0_ODD         3
    355 #define DATA_SRC0_HIGHBIT     4
    356 #define DATA_SRC1_ODD         5
    357 #define DATA_SRC1_HIGHBIT     6
    358 #define DATA_MULTIPLE_DIVISOR 7
    359 #define DATA_UDIV_QRNND       8
    360   char  data;
    361 
    362 /* Default is allow full overlap. */
    363 #define OVERLAP_NONE         1
    364 #define OVERLAP_LOW_TO_HIGH  2
    365 #define OVERLAP_HIGH_TO_LOW  3
    366 #define OVERLAP_NOT_SRCS     4
    367 #define OVERLAP_NOT_SRC2     8
    368   char  overlap;
    369 
    370   tryfun_t    reference;
    371   const char  *reference_name;
    372 
    373   void        (*validate) __GMP_PROTO ((void));
    374   const char  *validate_name;
    375 };
    376 
    377 struct try_t  *tr;
    378 
    379 
    380 void
    381 validate_mod_34lsub1 (void)
    382 {
    383 #define CNST_34LSUB1   ((CNST_LIMB(1) << (3 * (GMP_NUMB_BITS / 4))) - 1)
    384 
    385   mp_srcptr  ptr = s[0].p;
    386   int        error = 0;
    387   mp_limb_t  got, got_mod, want, want_mod;
    388 
    389   ASSERT (size >= 1);
    390 
    391   got = fun.retval;
    392   got_mod = got % CNST_34LSUB1;
    393 
    394   want = refmpn_mod_34lsub1 (ptr, size);
    395   want_mod = want % CNST_34LSUB1;
    396 
    397   if (got_mod != want_mod)
    398     {
    399       gmp_printf ("got   0x%MX reduced from 0x%MX\n", got_mod, got);
    400       gmp_printf ("want  0x%MX reduced from 0x%MX\n", want_mod, want);
    401       error = 1;
    402     }
    403 
    404   if (error)
    405     validate_fail ();
    406 }
    407 
    408 void
    409 validate_divexact_1 (void)
    410 {
    411   mp_srcptr  src = s[0].p;
    412   mp_srcptr  dst = fun.d[0].p;
    413   int  error = 0;
    414 
    415   ASSERT (size >= 1);
    416 
    417   {
    418     mp_ptr     tp = refmpn_malloc_limbs (size);
    419     mp_limb_t  rem;
    420 
    421     rem = refmpn_divrem_1 (tp, 0, src, size, divisor);
    422     if (rem != 0)
    423       {
    424 	gmp_printf ("Remainder a%%d == 0x%MX, mpn_divexact_1 undefined\n", rem);
    425 	error = 1;
    426       }
    427     if (! refmpn_equal_anynail (tp, dst, size))
    428       {
    429 	printf ("Quotient a/d wrong\n");
    430 	mpn_trace ("fun ", dst, size);
    431 	mpn_trace ("want", tp, size);
    432 	error = 1;
    433       }
    434     free (tp);
    435   }
    436 
    437   if (error)
    438     validate_fail ();
    439 }
    440 
    441 
    442 void
    443 validate_modexact_1c_odd (void)
    444 {
    445   mp_srcptr  ptr = s[0].p;
    446   mp_limb_t  r = fun.retval;
    447   int  error = 0;
    448 
    449   ASSERT (size >= 1);
    450   ASSERT (divisor & 1);
    451 
    452   if ((r & GMP_NAIL_MASK) != 0)
    453     printf ("r has non-zero nail\n");
    454 
    455   if (carry < divisor)
    456     {
    457       if (! (r < divisor))
    458 	{
    459 	  printf ("Don't have r < divisor\n");
    460 	  error = 1;
    461 	}
    462     }
    463   else /* carry >= divisor */
    464     {
    465       if (! (r <= divisor))
    466 	{
    467 	  printf ("Don't have r <= divisor\n");
    468 	  error = 1;
    469 	}
    470     }
    471 
    472   {
    473     mp_limb_t  c = carry % divisor;
    474     mp_ptr     tp = refmpn_malloc_limbs (size+1);
    475     mp_size_t  k;
    476 
    477     for (k = size-1; k <= size; k++)
    478       {
    479 	/* set {tp,size+1} to r*b^k + a - c */
    480 	refmpn_copyi (tp, ptr, size);
    481 	tp[size] = 0;
    482 	ASSERT_NOCARRY (refmpn_add_1 (tp+k, tp+k, size+1-k, r));
    483 	if (refmpn_sub_1 (tp, tp, size+1, c))
    484 	  ASSERT_CARRY (mpn_add_1 (tp, tp, size+1, divisor));
    485 
    486 	if (refmpn_mod_1 (tp, size+1, divisor) == 0)
    487 	  goto good_remainder;
    488       }
    489     printf ("Remainder matches neither r*b^(size-1) nor r*b^size\n");
    490     error = 1;
    491 
    492   good_remainder:
    493     free (tp);
    494   }
    495 
    496   if (error)
    497     validate_fail ();
    498 }
    499 
    500 void
    501 validate_modexact_1_odd (void)
    502 {
    503   carry = 0;
    504   validate_modexact_1c_odd ();
    505 }
    506 
    507 
    508 void
    509 validate_sqrtrem (void)
    510 {
    511   mp_srcptr  orig_ptr = s[0].p;
    512   mp_size_t  orig_size = size;
    513   mp_size_t  root_size = (size+1)/2;
    514   mp_srcptr  root_ptr = fun.d[0].p;
    515   mp_size_t  rem_size = fun.retval;
    516   mp_srcptr  rem_ptr = fun.d[1].p;
    517   mp_size_t  prod_size = 2*root_size;
    518   mp_ptr     p;
    519   int  error = 0;
    520 
    521   if (rem_size < 0 || rem_size > size)
    522     {
    523       printf ("Bad remainder size retval %ld\n", (long) rem_size);
    524       validate_fail ();
    525     }
    526 
    527   p = refmpn_malloc_limbs (prod_size);
    528 
    529   p[root_size] = refmpn_lshift (p, root_ptr, root_size, 1);
    530   if (refmpn_cmp_twosizes (p,root_size+1, rem_ptr,rem_size) < 0)
    531     {
    532       printf ("Remainder bigger than 2*root\n");
    533       error = 1;
    534     }
    535 
    536   refmpn_sqr (p, root_ptr, root_size);
    537   if (rem_size != 0)
    538     refmpn_add (p, p, prod_size, rem_ptr, rem_size);
    539   if (refmpn_cmp_twosizes (p,prod_size, orig_ptr,orig_size) != 0)
    540     {
    541       printf ("root^2+rem != original\n");
    542       mpn_trace ("prod", p, prod_size);
    543       error = 1;
    544     }
    545   free (p);
    546 
    547   if (error)
    548     validate_fail ();
    549 }
    550 
    551 
    552 /* These types are indexes into the param[] array and are arbitrary so long
    553    as they're all distinct and within the size of param[].  Renumber
    554    whenever necessary or desired.  */
    555 
    556 #define TYPE_ADD               1
    557 #define TYPE_ADD_N             2
    558 #define TYPE_ADD_NC            3
    559 #define TYPE_SUB               4
    560 #define TYPE_SUB_N             5
    561 #define TYPE_SUB_NC            6
    562 
    563 #define TYPE_MUL_1             7
    564 #define TYPE_MUL_1C            8
    565 
    566 #define TYPE_MUL_2             9
    567 #define TYPE_MUL_3             92
    568 #define TYPE_MUL_4             93
    569 
    570 #define TYPE_ADDMUL_1         10
    571 #define TYPE_ADDMUL_1C        11
    572 #define TYPE_SUBMUL_1         12
    573 #define TYPE_SUBMUL_1C        13
    574 
    575 #define TYPE_ADDMUL_2         14
    576 #define TYPE_ADDMUL_3         15
    577 #define TYPE_ADDMUL_4         16
    578 #define TYPE_ADDMUL_5         17
    579 #define TYPE_ADDMUL_6         18
    580 #define TYPE_ADDMUL_7         19
    581 #define TYPE_ADDMUL_8         20
    582 
    583 #define TYPE_ADDSUB_N         21
    584 #define TYPE_ADDSUB_NC        22
    585 
    586 #define TYPE_RSHIFT           23
    587 #define TYPE_LSHIFT           24
    588 #define TYPE_LSHIFTC          25
    589 
    590 #define TYPE_COPY             26
    591 #define TYPE_COPYI            27
    592 #define TYPE_COPYD            28
    593 #define TYPE_COM              29
    594 
    595 #define TYPE_ADDLSH1_N        30
    596 #define TYPE_ADDLSH2_N        48
    597 #define TYPE_ADDLSH_N         49
    598 #define TYPE_SUBLSH1_N        31
    599 #define TYPE_SUBLSH_N        130
    600 #define TYPE_RSBLSH1_N        34
    601 #define TYPE_RSBLSH2_N        46
    602 #define TYPE_RSBLSH_N         47
    603 #define TYPE_RSH1ADD_N        32
    604 #define TYPE_RSH1SUB_N        33
    605 
    606 #define TYPE_MOD_1            35
    607 #define TYPE_MOD_1C           36
    608 #define TYPE_DIVMOD_1         37
    609 #define TYPE_DIVMOD_1C        38
    610 #define TYPE_DIVREM_1         39
    611 #define TYPE_DIVREM_1C        40
    612 #define TYPE_PREINV_DIVREM_1  41
    613 #define TYPE_PREINV_MOD_1     42
    614 #define TYPE_MOD_34LSUB1      43
    615 #define TYPE_UDIV_QRNND       44
    616 #define TYPE_UDIV_QRNND_R     45
    617 
    618 #define TYPE_DIVEXACT_1       50
    619 #define TYPE_DIVEXACT_BY3     51
    620 #define TYPE_DIVEXACT_BY3C    52
    621 #define TYPE_MODEXACT_1_ODD   53
    622 #define TYPE_MODEXACT_1C_ODD  54
    623 
    624 #define TYPE_INVERT           55
    625 #define TYPE_BINVERT          56
    626 
    627 #define TYPE_GCD              60
    628 #define TYPE_GCD_1            61
    629 #define TYPE_GCD_FINDA        62
    630 #define TYPE_MPZ_JACOBI       63
    631 #define TYPE_MPZ_KRONECKER    64
    632 #define TYPE_MPZ_KRONECKER_UI 65
    633 #define TYPE_MPZ_KRONECKER_SI 66
    634 #define TYPE_MPZ_UI_KRONECKER 67
    635 #define TYPE_MPZ_SI_KRONECKER 68
    636 
    637 #define TYPE_AND_N            70
    638 #define TYPE_NAND_N           71
    639 #define TYPE_ANDN_N           72
    640 #define TYPE_IOR_N            73
    641 #define TYPE_IORN_N           74
    642 #define TYPE_NIOR_N           75
    643 #define TYPE_XOR_N            76
    644 #define TYPE_XNOR_N           77
    645 
    646 #define TYPE_MUL_MN           80
    647 #define TYPE_MUL_N            81
    648 #define TYPE_SQR              82
    649 #define TYPE_UMUL_PPMM        83
    650 #define TYPE_UMUL_PPMM_R      84
    651 #define TYPE_MULLO_N          85
    652 
    653 #define TYPE_SBPI1_DIV_QR     90
    654 #define TYPE_TDIV_QR          91
    655 
    656 #define TYPE_SQRTREM          100
    657 #define TYPE_ZERO             101
    658 #define TYPE_GET_STR          102
    659 #define TYPE_POPCOUNT         103
    660 #define TYPE_HAMDIST          104
    661 
    662 #define TYPE_EXTRA            110
    663 
    664 struct try_t  param[150];
    665 
    666 
    667 void
    668 param_init (void)
    669 {
    670   struct try_t  *p;
    671 
    672 #define COPY(index)  memcpy (p, &param[index], sizeof (*p))
    673 
    674 #if HAVE_STRINGIZE
    675 #define REFERENCE(fun)                  \
    676   p->reference = (tryfun_t) fun;        \
    677   p->reference_name = #fun
    678 #define VALIDATE(fun)           \
    679   p->validate = fun;            \
    680   p->validate_name = #fun
    681 #else
    682 #define REFERENCE(fun)                  \
    683   p->reference = (tryfun_t) fun;        \
    684   p->reference_name = "fun"
    685 #define VALIDATE(fun)           \
    686   p->validate = fun;            \
    687   p->validate_name = "fun"
    688 #endif
    689 
    690 
    691   p = &param[TYPE_ADD_N];
    692   p->retval = 1;
    693   p->dst[0] = 1;
    694   p->src[0] = 1;
    695   p->src[1] = 1;
    696   REFERENCE (refmpn_add_n);
    697 
    698   p = &param[TYPE_ADD_NC];
    699   COPY (TYPE_ADD_N);
    700   p->carry = CARRY_BIT;
    701   REFERENCE (refmpn_add_nc);
    702 
    703   p = &param[TYPE_SUB_N];
    704   COPY (TYPE_ADD_N);
    705   REFERENCE (refmpn_sub_n);
    706 
    707   p = &param[TYPE_SUB_NC];
    708   COPY (TYPE_ADD_NC);
    709   REFERENCE (refmpn_sub_nc);
    710 
    711   p = &param[TYPE_ADD];
    712   COPY (TYPE_ADD_N);
    713   p->size = SIZE_ALLOW_ZERO;
    714   p->size2 = 1;
    715   REFERENCE (refmpn_add);
    716 
    717   p = &param[TYPE_SUB];
    718   COPY (TYPE_ADD);
    719   REFERENCE (refmpn_sub);
    720 
    721 
    722   p = &param[TYPE_MUL_1];
    723   p->retval = 1;
    724   p->dst[0] = 1;
    725   p->src[0] = 1;
    726   p->multiplier = 1;
    727   p->overlap = OVERLAP_LOW_TO_HIGH;
    728   REFERENCE (refmpn_mul_1);
    729 
    730   p = &param[TYPE_MUL_1C];
    731   COPY (TYPE_MUL_1);
    732   p->carry = CARRY_LIMB;
    733   REFERENCE (refmpn_mul_1c);
    734 
    735 
    736   p = &param[TYPE_MUL_2];
    737   p->retval = 1;
    738   p->dst[0] = 1;
    739   p->dst_size[0] = SIZE_PLUS_MSIZE_SUB_1;
    740   p->src[0] = 1;
    741   p->src[1] = 1;
    742   p->msize = 2;
    743   p->overlap = OVERLAP_NOT_SRC2;
    744   REFERENCE (refmpn_mul_2);
    745 
    746   p = &param[TYPE_MUL_3];
    747   COPY (TYPE_MUL_2);
    748   p->msize = 3;
    749   REFERENCE (refmpn_mul_3);
    750 
    751   p = &param[TYPE_MUL_4];
    752   COPY (TYPE_MUL_2);
    753   p->msize = 4;
    754   REFERENCE (refmpn_mul_4);
    755 
    756 
    757   p = &param[TYPE_ADDMUL_1];
    758   p->retval = 1;
    759   p->dst[0] = 1;
    760   p->src[0] = 1;
    761   p->multiplier = 1;
    762   p->dst0_from_src1 = 1;
    763   REFERENCE (refmpn_addmul_1);
    764 
    765   p = &param[TYPE_ADDMUL_1C];
    766   COPY (TYPE_ADDMUL_1);
    767   p->carry = CARRY_LIMB;
    768   REFERENCE (refmpn_addmul_1c);
    769 
    770   p = &param[TYPE_SUBMUL_1];
    771   COPY (TYPE_ADDMUL_1);
    772   REFERENCE (refmpn_submul_1);
    773 
    774   p = &param[TYPE_SUBMUL_1C];
    775   COPY (TYPE_ADDMUL_1C);
    776   REFERENCE (refmpn_submul_1c);
    777 
    778 
    779   p = &param[TYPE_ADDMUL_2];
    780   p->retval = 1;
    781   p->dst[0] = 1;
    782   p->dst_size[0] = SIZE_PLUS_MSIZE_SUB_1;
    783   p->src[0] = 1;
    784   p->src[1] = 1;
    785   p->msize = 2;
    786   p->dst0_from_src1 = 1;
    787   p->overlap = OVERLAP_NOT_SRC2;
    788   REFERENCE (refmpn_addmul_2);
    789 
    790   p = &param[TYPE_ADDMUL_3];
    791   COPY (TYPE_ADDMUL_2);
    792   p->msize = 3;
    793   REFERENCE (refmpn_addmul_3);
    794 
    795   p = &param[TYPE_ADDMUL_4];
    796   COPY (TYPE_ADDMUL_2);
    797   p->msize = 4;
    798   REFERENCE (refmpn_addmul_4);
    799 
    800   p = &param[TYPE_ADDMUL_5];
    801   COPY (TYPE_ADDMUL_2);
    802   p->msize = 5;
    803   REFERENCE (refmpn_addmul_5);
    804 
    805   p = &param[TYPE_ADDMUL_6];
    806   COPY (TYPE_ADDMUL_2);
    807   p->msize = 6;
    808   REFERENCE (refmpn_addmul_6);
    809 
    810   p = &param[TYPE_ADDMUL_7];
    811   COPY (TYPE_ADDMUL_2);
    812   p->msize = 7;
    813   REFERENCE (refmpn_addmul_7);
    814 
    815   p = &param[TYPE_ADDMUL_8];
    816   COPY (TYPE_ADDMUL_2);
    817   p->msize = 8;
    818   REFERENCE (refmpn_addmul_8);
    819 
    820 
    821   p = &param[TYPE_AND_N];
    822   p->dst[0] = 1;
    823   p->src[0] = 1;
    824   p->src[1] = 1;
    825   REFERENCE (refmpn_and_n);
    826 
    827   p = &param[TYPE_ANDN_N];
    828   COPY (TYPE_AND_N);
    829   REFERENCE (refmpn_andn_n);
    830 
    831   p = &param[TYPE_NAND_N];
    832   COPY (TYPE_AND_N);
    833   REFERENCE (refmpn_nand_n);
    834 
    835   p = &param[TYPE_IOR_N];
    836   COPY (TYPE_AND_N);
    837   REFERENCE (refmpn_ior_n);
    838 
    839   p = &param[TYPE_IORN_N];
    840   COPY (TYPE_AND_N);
    841   REFERENCE (refmpn_iorn_n);
    842 
    843   p = &param[TYPE_NIOR_N];
    844   COPY (TYPE_AND_N);
    845   REFERENCE (refmpn_nior_n);
    846 
    847   p = &param[TYPE_XOR_N];
    848   COPY (TYPE_AND_N);
    849   REFERENCE (refmpn_xor_n);
    850 
    851   p = &param[TYPE_XNOR_N];
    852   COPY (TYPE_AND_N);
    853   REFERENCE (refmpn_xnor_n);
    854 
    855 
    856   p = &param[TYPE_ADDSUB_N];
    857   p->retval = 1;
    858   p->dst[0] = 1;
    859   p->dst[1] = 1;
    860   p->src[0] = 1;
    861   p->src[1] = 1;
    862   REFERENCE (refmpn_add_n_sub_n);
    863 
    864   p = &param[TYPE_ADDSUB_NC];
    865   COPY (TYPE_ADDSUB_N);
    866   p->carry = CARRY_4;
    867   REFERENCE (refmpn_add_n_sub_nc);
    868 
    869 
    870   p = &param[TYPE_COPY];
    871   p->dst[0] = 1;
    872   p->src[0] = 1;
    873   p->overlap = OVERLAP_NONE;
    874   p->size = SIZE_ALLOW_ZERO;
    875   REFERENCE (refmpn_copy);
    876 
    877   p = &param[TYPE_COPYI];
    878   p->dst[0] = 1;
    879   p->src[0] = 1;
    880   p->overlap = OVERLAP_LOW_TO_HIGH;
    881   p->size = SIZE_ALLOW_ZERO;
    882   REFERENCE (refmpn_copyi);
    883 
    884   p = &param[TYPE_COPYD];
    885   p->dst[0] = 1;
    886   p->src[0] = 1;
    887   p->overlap = OVERLAP_HIGH_TO_LOW;
    888   p->size = SIZE_ALLOW_ZERO;
    889   REFERENCE (refmpn_copyd);
    890 
    891   p = &param[TYPE_COM];
    892   p->dst[0] = 1;
    893   p->src[0] = 1;
    894   REFERENCE (refmpn_com);
    895 
    896 
    897   p = &param[TYPE_ADDLSH1_N];
    898   COPY (TYPE_ADD_N);
    899   REFERENCE (refmpn_addlsh1_n);
    900 
    901   p = &param[TYPE_ADDLSH2_N];
    902   COPY (TYPE_ADD_N);
    903   REFERENCE (refmpn_addlsh2_n);
    904 
    905   p = &param[TYPE_ADDLSH_N];
    906   COPY (TYPE_ADD_N);
    907   p->shift = 1;
    908   REFERENCE (refmpn_addlsh_n);
    909 
    910   p = &param[TYPE_SUBLSH1_N];
    911   COPY (TYPE_ADD_N);
    912   REFERENCE (refmpn_sublsh1_n);
    913 
    914   p = &param[TYPE_SUBLSH_N];
    915   COPY (TYPE_ADDLSH_N);
    916   REFERENCE (refmpn_sublsh_n);
    917 
    918   p = &param[TYPE_RSBLSH1_N];
    919   COPY (TYPE_ADD_N);
    920   REFERENCE (refmpn_rsblsh1_n);
    921 
    922   p = &param[TYPE_RSBLSH2_N];
    923   COPY (TYPE_ADD_N);
    924   REFERENCE (refmpn_rsblsh2_n);
    925 
    926   p = &param[TYPE_RSBLSH_N];
    927   COPY (TYPE_ADDLSH_N);
    928   REFERENCE (refmpn_rsblsh_n);
    929 
    930   p = &param[TYPE_RSH1ADD_N];
    931   COPY (TYPE_ADD_N);
    932   REFERENCE (refmpn_rsh1add_n);
    933 
    934   p = &param[TYPE_RSH1SUB_N];
    935   COPY (TYPE_ADD_N);
    936   REFERENCE (refmpn_rsh1sub_n);
    937 
    938 
    939   p = &param[TYPE_MOD_1];
    940   p->retval = 1;
    941   p->src[0] = 1;
    942   p->size = SIZE_ALLOW_ZERO;
    943   p->divisor = DIVISOR_LIMB;
    944   REFERENCE (refmpn_mod_1);
    945 
    946   p = &param[TYPE_MOD_1C];
    947   COPY (TYPE_MOD_1);
    948   p->carry = CARRY_DIVISOR;
    949   REFERENCE (refmpn_mod_1c);
    950 
    951   p = &param[TYPE_DIVMOD_1];
    952   COPY (TYPE_MOD_1);
    953   p->dst[0] = 1;
    954   REFERENCE (refmpn_divmod_1);
    955 
    956   p = &param[TYPE_DIVMOD_1C];
    957   COPY (TYPE_DIVMOD_1);
    958   p->carry = CARRY_DIVISOR;
    959   REFERENCE (refmpn_divmod_1c);
    960 
    961   p = &param[TYPE_DIVREM_1];
    962   COPY (TYPE_DIVMOD_1);
    963   p->size2 = SIZE_FRACTION;
    964   p->dst_size[0] = SIZE_SUM;
    965   REFERENCE (refmpn_divrem_1);
    966 
    967   p = &param[TYPE_DIVREM_1C];
    968   COPY (TYPE_DIVREM_1);
    969   p->carry = CARRY_DIVISOR;
    970   REFERENCE (refmpn_divrem_1c);
    971 
    972   p = &param[TYPE_PREINV_DIVREM_1];
    973   COPY (TYPE_DIVREM_1);
    974   p->size = SIZE_YES; /* ie. no size==0 */
    975   REFERENCE (refmpn_preinv_divrem_1);
    976 
    977   p = &param[TYPE_PREINV_MOD_1];
    978   p->retval = 1;
    979   p->src[0] = 1;
    980   p->divisor = DIVISOR_NORM;
    981   REFERENCE (refmpn_preinv_mod_1);
    982 
    983   p = &param[TYPE_MOD_34LSUB1];
    984   p->retval = 1;
    985   p->src[0] = 1;
    986   VALIDATE (validate_mod_34lsub1);
    987 
    988   p = &param[TYPE_UDIV_QRNND];
    989   p->retval = 1;
    990   p->src[0] = 1;
    991   p->dst[0] = 1;
    992   p->dst_size[0] = SIZE_1;
    993   p->divisor = UDIV_NEEDS_NORMALIZATION ? DIVISOR_NORM : DIVISOR_LIMB;
    994   p->data = DATA_UDIV_QRNND;
    995   p->overlap = OVERLAP_NONE;
    996   REFERENCE (refmpn_udiv_qrnnd);
    997 
    998   p = &param[TYPE_UDIV_QRNND_R];
    999   COPY (TYPE_UDIV_QRNND);
   1000   REFERENCE (refmpn_udiv_qrnnd_r);
   1001 
   1002 
   1003   p = &param[TYPE_DIVEXACT_1];
   1004   p->dst[0] = 1;
   1005   p->src[0] = 1;
   1006   p->divisor = DIVISOR_LIMB;
   1007   p->data = DATA_MULTIPLE_DIVISOR;
   1008   VALIDATE (validate_divexact_1);
   1009   REFERENCE (refmpn_divmod_1);
   1010 
   1011 
   1012   p = &param[TYPE_DIVEXACT_BY3];
   1013   p->retval = 1;
   1014   p->dst[0] = 1;
   1015   p->src[0] = 1;
   1016   REFERENCE (refmpn_divexact_by3);
   1017 
   1018   p = &param[TYPE_DIVEXACT_BY3C];
   1019   COPY (TYPE_DIVEXACT_BY3);
   1020   p->carry = CARRY_3;
   1021   REFERENCE (refmpn_divexact_by3c);
   1022 
   1023 
   1024   p = &param[TYPE_MODEXACT_1_ODD];
   1025   p->retval = 1;
   1026   p->src[0] = 1;
   1027   p->divisor = DIVISOR_ODD;
   1028   VALIDATE (validate_modexact_1_odd);
   1029 
   1030   p = &param[TYPE_MODEXACT_1C_ODD];
   1031   COPY (TYPE_MODEXACT_1_ODD);
   1032   p->carry = CARRY_LIMB;
   1033   VALIDATE (validate_modexact_1c_odd);
   1034 
   1035 
   1036   p = &param[TYPE_GCD_1];
   1037   p->retval = 1;
   1038   p->src[0] = 1;
   1039   p->data = DATA_NON_ZERO;
   1040   p->divisor = DIVISOR_LIMB;
   1041   REFERENCE (refmpn_gcd_1);
   1042 
   1043   p = &param[TYPE_GCD];
   1044   p->retval = 1;
   1045   p->dst[0] = 1;
   1046   p->src[0] = 1;
   1047   p->src[1] = 1;
   1048   p->size2 = 1;
   1049   p->dst_size[0] = SIZE_RETVAL;
   1050   p->overlap = OVERLAP_NOT_SRCS;
   1051   p->data = DATA_GCD;
   1052   REFERENCE (refmpn_gcd);
   1053 
   1054 
   1055   p = &param[TYPE_MPZ_JACOBI];
   1056   p->retval = 1;
   1057   p->src[0] = 1;
   1058   p->size = SIZE_ALLOW_ZERO;
   1059   p->src[1] = 1;
   1060   p->data = DATA_SRC1_ODD;
   1061   p->size2 = 1;
   1062   p->carry = CARRY_4;
   1063   p->carry_sign = 1;
   1064   REFERENCE (refmpz_jacobi);
   1065 
   1066   p = &param[TYPE_MPZ_KRONECKER];
   1067   COPY (TYPE_MPZ_JACOBI);
   1068   p->data = 0;			/* clear inherited DATA_SRC1_ODD */
   1069   REFERENCE (refmpz_kronecker);
   1070 
   1071 
   1072   p = &param[TYPE_MPZ_KRONECKER_UI];
   1073   p->retval = 1;
   1074   p->src[0] = 1;
   1075   p->size = SIZE_ALLOW_ZERO;
   1076   p->multiplier = 1;
   1077   p->carry = CARRY_BIT;
   1078   REFERENCE (refmpz_kronecker_ui);
   1079 
   1080   p = &param[TYPE_MPZ_KRONECKER_SI];
   1081   COPY (TYPE_MPZ_KRONECKER_UI);
   1082   REFERENCE (refmpz_kronecker_si);
   1083 
   1084   p = &param[TYPE_MPZ_UI_KRONECKER];
   1085   COPY (TYPE_MPZ_KRONECKER_UI);
   1086   REFERENCE (refmpz_ui_kronecker);
   1087 
   1088   p = &param[TYPE_MPZ_SI_KRONECKER];
   1089   COPY (TYPE_MPZ_KRONECKER_UI);
   1090   REFERENCE (refmpz_si_kronecker);
   1091 
   1092 
   1093   p = &param[TYPE_SQR];
   1094   p->dst[0] = 1;
   1095   p->src[0] = 1;
   1096   p->dst_size[0] = SIZE_SUM;
   1097   p->overlap = OVERLAP_NONE;
   1098   REFERENCE (refmpn_sqr);
   1099 
   1100   p = &param[TYPE_MUL_N];
   1101   COPY (TYPE_SQR);
   1102   p->src[1] = 1;
   1103   REFERENCE (refmpn_mul_n);
   1104 
   1105   p = &param[TYPE_MULLO_N];
   1106   COPY (TYPE_MUL_N);
   1107   p->dst_size[0] = 0;
   1108   REFERENCE (refmpn_mullo_n);
   1109 
   1110   p = &param[TYPE_MUL_MN];
   1111   COPY (TYPE_MUL_N);
   1112   p->size2 = 1;
   1113   REFERENCE (refmpn_mul_basecase);
   1114 
   1115   p = &param[TYPE_UMUL_PPMM];
   1116   p->retval = 1;
   1117   p->src[0] = 1;
   1118   p->dst[0] = 1;
   1119   p->dst_size[0] = SIZE_1;
   1120   p->overlap = OVERLAP_NONE;
   1121   REFERENCE (refmpn_umul_ppmm);
   1122 
   1123   p = &param[TYPE_UMUL_PPMM_R];
   1124   COPY (TYPE_UMUL_PPMM);
   1125   REFERENCE (refmpn_umul_ppmm_r);
   1126 
   1127 
   1128   p = &param[TYPE_RSHIFT];
   1129   p->retval = 1;
   1130   p->dst[0] = 1;
   1131   p->src[0] = 1;
   1132   p->shift = 1;
   1133   p->overlap = OVERLAP_LOW_TO_HIGH;
   1134   REFERENCE (refmpn_rshift);
   1135 
   1136   p = &param[TYPE_LSHIFT];
   1137   COPY (TYPE_RSHIFT);
   1138   p->overlap = OVERLAP_HIGH_TO_LOW;
   1139   REFERENCE (refmpn_lshift);
   1140 
   1141   p = &param[TYPE_LSHIFTC];
   1142   COPY (TYPE_RSHIFT);
   1143   p->overlap = OVERLAP_HIGH_TO_LOW;
   1144   REFERENCE (refmpn_lshiftc);
   1145 
   1146 
   1147   p = &param[TYPE_POPCOUNT];
   1148   p->retval = 1;
   1149   p->src[0] = 1;
   1150   REFERENCE (refmpn_popcount);
   1151 
   1152   p = &param[TYPE_HAMDIST];
   1153   COPY (TYPE_POPCOUNT);
   1154   p->src[1] = 1;
   1155   REFERENCE (refmpn_hamdist);
   1156 
   1157 
   1158   p = &param[TYPE_SBPI1_DIV_QR];
   1159   p->retval = 1;
   1160   p->dst[0] = 1;
   1161   p->dst[1] = 1;
   1162   p->src[0] = 1;
   1163   p->src[1] = 1;
   1164   p->data = DATA_SRC1_HIGHBIT;
   1165   p->size2 = 1;
   1166   p->dst_size[0] = SIZE_DIFF;
   1167   p->overlap = OVERLAP_NONE;
   1168   REFERENCE (refmpn_sb_div_qr);
   1169 
   1170   p = &param[TYPE_TDIV_QR];
   1171   p->dst[0] = 1;
   1172   p->dst[1] = 1;
   1173   p->src[0] = 1;
   1174   p->src[1] = 1;
   1175   p->size2 = 1;
   1176   p->dst_size[0] = SIZE_DIFF_PLUS_1;
   1177   p->dst_size[1] = SIZE_SIZE2;
   1178   p->overlap = OVERLAP_NONE;
   1179   REFERENCE (refmpn_tdiv_qr);
   1180 
   1181   p = &param[TYPE_SQRTREM];
   1182   p->retval = 1;
   1183   p->dst[0] = 1;
   1184   p->dst[1] = 1;
   1185   p->src[0] = 1;
   1186   p->dst_size[0] = SIZE_CEIL_HALF;
   1187   p->dst_size[1] = SIZE_RETVAL;
   1188   p->overlap = OVERLAP_NONE;
   1189   VALIDATE (validate_sqrtrem);
   1190   REFERENCE (refmpn_sqrtrem);
   1191 
   1192   p = &param[TYPE_ZERO];
   1193   p->dst[0] = 1;
   1194   p->size = SIZE_ALLOW_ZERO;
   1195   REFERENCE (refmpn_zero);
   1196 
   1197   p = &param[TYPE_GET_STR];
   1198   p->retval = 1;
   1199   p->src[0] = 1;
   1200   p->size = SIZE_ALLOW_ZERO;
   1201   p->dst[0] = 1;
   1202   p->dst[1] = 1;
   1203   p->dst_size[0] = SIZE_GET_STR;
   1204   p->dst_bytes[0] = 1;
   1205   p->overlap = OVERLAP_NONE;
   1206   REFERENCE (refmpn_get_str);
   1207 
   1208   p = &param[TYPE_BINVERT];
   1209   p->dst[0] = 1;
   1210   p->src[0] = 1;
   1211   p->data = DATA_SRC0_ODD;
   1212   p->overlap = OVERLAP_NONE;
   1213   REFERENCE (refmpn_binvert);
   1214 
   1215   p = &param[TYPE_INVERT];
   1216   p->dst[0] = 1;
   1217   p->src[0] = 1;
   1218   p->data = DATA_SRC0_HIGHBIT;
   1219   p->overlap = OVERLAP_NONE;
   1220   REFERENCE (refmpn_invert);
   1221 
   1222 #ifdef EXTRA_PARAM_INIT
   1223   EXTRA_PARAM_INIT
   1224 #endif
   1225 }
   1226 
   1227 
   1228 /* The following are macros if there's no native versions, so wrap them in
   1229    functions that can be in try_array[]. */
   1230 
   1231 void
   1232 MPN_COPY_fun (mp_ptr rp, mp_srcptr sp, mp_size_t size)
   1233 { MPN_COPY (rp, sp, size); }
   1234 
   1235 void
   1236 MPN_COPY_INCR_fun (mp_ptr rp, mp_srcptr sp, mp_size_t size)
   1237 { MPN_COPY_INCR (rp, sp, size); }
   1238 
   1239 void
   1240 MPN_COPY_DECR_fun (mp_ptr rp, mp_srcptr sp, mp_size_t size)
   1241 { MPN_COPY_DECR (rp, sp, size); }
   1242 
   1243 void
   1244 __GMPN_COPY_fun (mp_ptr rp, mp_srcptr sp, mp_size_t size)
   1245 { __GMPN_COPY (rp, sp, size); }
   1246 
   1247 #ifdef __GMPN_COPY_INCR
   1248 void
   1249 __GMPN_COPY_INCR_fun (mp_ptr rp, mp_srcptr sp, mp_size_t size)
   1250 { __GMPN_COPY_INCR (rp, sp, size); }
   1251 #endif
   1252 
   1253 void
   1254 mpn_com_fun (mp_ptr rp, mp_srcptr sp, mp_size_t size)
   1255 { mpn_com (rp, sp, size); }
   1256 
   1257 void
   1258 mpn_and_n_fun (mp_ptr rp, mp_srcptr s1, mp_srcptr s2, mp_size_t size)
   1259 { mpn_and_n (rp, s1, s2, size); }
   1260 
   1261 void
   1262 mpn_andn_n_fun (mp_ptr rp, mp_srcptr s1, mp_srcptr s2, mp_size_t size)
   1263 { mpn_andn_n (rp, s1, s2, size); }
   1264 
   1265 void
   1266 mpn_nand_n_fun (mp_ptr rp, mp_srcptr s1, mp_srcptr s2, mp_size_t size)
   1267 { mpn_nand_n (rp, s1, s2, size); }
   1268 
   1269 void
   1270 mpn_ior_n_fun (mp_ptr rp, mp_srcptr s1, mp_srcptr s2, mp_size_t size)
   1271 { mpn_ior_n (rp, s1, s2, size); }
   1272 
   1273 void
   1274 mpn_iorn_n_fun (mp_ptr rp, mp_srcptr s1, mp_srcptr s2, mp_size_t size)
   1275 { mpn_iorn_n (rp, s1, s2, size); }
   1276 
   1277 void
   1278 mpn_nior_n_fun (mp_ptr rp, mp_srcptr s1, mp_srcptr s2, mp_size_t size)
   1279 { mpn_nior_n (rp, s1, s2, size); }
   1280 
   1281 void
   1282 mpn_xor_n_fun (mp_ptr rp, mp_srcptr s1, mp_srcptr s2, mp_size_t size)
   1283 { mpn_xor_n (rp, s1, s2, size); }
   1284 
   1285 void
   1286 mpn_xnor_n_fun (mp_ptr rp, mp_srcptr s1, mp_srcptr s2, mp_size_t size)
   1287 { mpn_xnor_n (rp, s1, s2, size); }
   1288 
   1289 mp_limb_t
   1290 udiv_qrnnd_fun (mp_limb_t *remptr, mp_limb_t n1, mp_limb_t n0, mp_limb_t d)
   1291 {
   1292   mp_limb_t  q;
   1293   udiv_qrnnd (q, *remptr, n1, n0, d);
   1294   return q;
   1295 }
   1296 
   1297 mp_limb_t
   1298 mpn_divexact_by3_fun (mp_ptr rp, mp_srcptr sp, mp_size_t size)
   1299 {
   1300   return mpn_divexact_by3 (rp, sp, size);
   1301 }
   1302 
   1303 mp_limb_t
   1304 mpn_modexact_1_odd_fun (mp_srcptr ptr, mp_size_t size, mp_limb_t divisor)
   1305 {
   1306   return mpn_modexact_1_odd (ptr, size, divisor);
   1307 }
   1308 
   1309 void
   1310 mpn_toom22_mul_fun (mp_ptr dst, mp_srcptr src1, mp_srcptr src2, mp_size_t size)
   1311 {
   1312   mp_ptr  tspace;
   1313   TMP_DECL;
   1314   TMP_MARK;
   1315   tspace = TMP_ALLOC_LIMBS (mpn_toom22_mul_itch (size, size));
   1316   mpn_toom22_mul (dst, src1, size, src2, size, tspace);
   1317   TMP_FREE;
   1318 }
   1319 void
   1320 mpn_toom2_sqr_fun (mp_ptr dst, mp_srcptr src, mp_size_t size)
   1321 {
   1322   mp_ptr tspace;
   1323   TMP_DECL;
   1324   TMP_MARK;
   1325   tspace = TMP_ALLOC_LIMBS (mpn_toom2_sqr_itch (size));
   1326   mpn_toom2_sqr (dst, src, size, tspace);
   1327   TMP_FREE;
   1328 }
   1329 void
   1330 mpn_toom33_mul_fun (mp_ptr dst, mp_srcptr src1, mp_srcptr src2, mp_size_t size)
   1331 {
   1332   mp_ptr  tspace;
   1333   TMP_DECL;
   1334   TMP_MARK;
   1335   tspace = TMP_ALLOC_LIMBS (mpn_toom33_mul_itch (size, size));
   1336   mpn_toom33_mul (dst, src1, size, src2, size, tspace);
   1337   TMP_FREE;
   1338 }
   1339 void
   1340 mpn_toom3_sqr_fun (mp_ptr dst, mp_srcptr src, mp_size_t size)
   1341 {
   1342   mp_ptr tspace;
   1343   TMP_DECL;
   1344   TMP_MARK;
   1345   tspace = TMP_ALLOC_LIMBS (mpn_toom3_sqr_itch (size));
   1346   mpn_toom3_sqr (dst, src, size, tspace);
   1347   TMP_FREE;
   1348 }
   1349 void
   1350 mpn_toom44_mul_fun (mp_ptr dst, mp_srcptr src1, mp_srcptr src2, mp_size_t size)
   1351 {
   1352   mp_ptr  tspace;
   1353   TMP_DECL;
   1354   TMP_MARK;
   1355   tspace = TMP_ALLOC_LIMBS (mpn_toom44_mul_itch (size, size));
   1356   mpn_toom44_mul (dst, src1, size, src2, size, tspace);
   1357   TMP_FREE;
   1358 }
   1359 void
   1360 mpn_toom4_sqr_fun (mp_ptr dst, mp_srcptr src, mp_size_t size)
   1361 {
   1362   mp_ptr tspace;
   1363   TMP_DECL;
   1364   TMP_MARK;
   1365   tspace = TMP_ALLOC_LIMBS (mpn_toom4_sqr_itch (size));
   1366   mpn_toom4_sqr (dst, src, size, tspace);
   1367   TMP_FREE;
   1368 }
   1369 
   1370 mp_limb_t
   1371 umul_ppmm_fun (mp_limb_t *lowptr, mp_limb_t m1, mp_limb_t m2)
   1372 {
   1373   mp_limb_t  high;
   1374   umul_ppmm (high, *lowptr, m1, m2);
   1375   return high;
   1376 }
   1377 
   1378 void
   1379 MPN_ZERO_fun (mp_ptr ptr, mp_size_t size)
   1380 { MPN_ZERO (ptr, size); }
   1381 
   1382 
   1383 struct choice_t {
   1384   const char  *name;
   1385   tryfun_t    function;
   1386   int         type;
   1387   mp_size_t   minsize;
   1388 };
   1389 
   1390 #if HAVE_STRINGIZE
   1391 #define TRY(fun)        #fun, (tryfun_t) fun
   1392 #define TRY_FUNFUN(fun) #fun, (tryfun_t) fun##_fun
   1393 #else
   1394 #define TRY(fun)        "fun", (tryfun_t) fun
   1395 #define TRY_FUNFUN(fun) "fun", (tryfun_t) fun/**/_fun
   1396 #endif
   1397 
   1398 const struct choice_t choice_array[] = {
   1399   { TRY(mpn_add),       TYPE_ADD    },
   1400   { TRY(mpn_sub),       TYPE_SUB    },
   1401 
   1402   { TRY(mpn_add_n),     TYPE_ADD_N  },
   1403   { TRY(mpn_sub_n),     TYPE_SUB_N  },
   1404 
   1405 #if HAVE_NATIVE_mpn_add_nc
   1406   { TRY(mpn_add_nc),    TYPE_ADD_NC },
   1407 #endif
   1408 #if HAVE_NATIVE_mpn_sub_nc
   1409   { TRY(mpn_sub_nc),    TYPE_SUB_NC },
   1410 #endif
   1411 
   1412 #if HAVE_NATIVE_mpn_add_n_sub_n
   1413   { TRY(mpn_add_n_sub_n),  TYPE_ADDSUB_N  },
   1414 #endif
   1415 #if HAVE_NATIVE_mpn_add_n_sub_nc
   1416   { TRY(mpn_add_n_sub_nc), TYPE_ADDSUB_NC },
   1417 #endif
   1418 
   1419   { TRY(mpn_addmul_1),  TYPE_ADDMUL_1  },
   1420   { TRY(mpn_submul_1),  TYPE_SUBMUL_1  },
   1421 #if HAVE_NATIVE_mpn_addmul_1c
   1422   { TRY(mpn_addmul_1c), TYPE_ADDMUL_1C },
   1423 #endif
   1424 #if HAVE_NATIVE_mpn_submul_1c
   1425   { TRY(mpn_submul_1c), TYPE_SUBMUL_1C },
   1426 #endif
   1427 
   1428 #if HAVE_NATIVE_mpn_addmul_2
   1429   { TRY(mpn_addmul_2), TYPE_ADDMUL_2, 2 },
   1430 #endif
   1431 #if HAVE_NATIVE_mpn_addmul_3
   1432   { TRY(mpn_addmul_3), TYPE_ADDMUL_3, 3 },
   1433 #endif
   1434 #if HAVE_NATIVE_mpn_addmul_4
   1435   { TRY(mpn_addmul_4), TYPE_ADDMUL_4, 4 },
   1436 #endif
   1437 #if HAVE_NATIVE_mpn_addmul_5
   1438   { TRY(mpn_addmul_5), TYPE_ADDMUL_5, 5 },
   1439 #endif
   1440 #if HAVE_NATIVE_mpn_addmul_6
   1441   { TRY(mpn_addmul_6), TYPE_ADDMUL_6, 6 },
   1442 #endif
   1443 #if HAVE_NATIVE_mpn_addmul_7
   1444   { TRY(mpn_addmul_7), TYPE_ADDMUL_7, 7 },
   1445 #endif
   1446 #if HAVE_NATIVE_mpn_addmul_8
   1447   { TRY(mpn_addmul_8), TYPE_ADDMUL_8, 8 },
   1448 #endif
   1449 
   1450   { TRY_FUNFUN(mpn_com),  TYPE_COM },
   1451 
   1452   { TRY_FUNFUN(MPN_COPY),      TYPE_COPY },
   1453   { TRY_FUNFUN(MPN_COPY_INCR), TYPE_COPYI },
   1454   { TRY_FUNFUN(MPN_COPY_DECR), TYPE_COPYD },
   1455 
   1456   { TRY_FUNFUN(__GMPN_COPY),      TYPE_COPY },
   1457 #ifdef __GMPN_COPY_INCR
   1458   { TRY_FUNFUN(__GMPN_COPY_INCR), TYPE_COPYI },
   1459 #endif
   1460 
   1461 #if HAVE_NATIVE_mpn_copyi
   1462   { TRY(mpn_copyi), TYPE_COPYI },
   1463 #endif
   1464 #if HAVE_NATIVE_mpn_copyd
   1465   { TRY(mpn_copyd), TYPE_COPYD },
   1466 #endif
   1467 
   1468 #if HAVE_NATIVE_mpn_addlsh1_n
   1469   { TRY(mpn_addlsh1_n), TYPE_ADDLSH1_N },
   1470 #endif
   1471 #if HAVE_NATIVE_mpn_addlsh2_n
   1472   { TRY(mpn_addlsh2_n), TYPE_ADDLSH2_N },
   1473 #endif
   1474 #if HAVE_NATIVE_mpn_addlsh_n
   1475   { TRY(mpn_addlsh_n), TYPE_ADDLSH_N },
   1476 #endif
   1477 #if HAVE_NATIVE_mpn_sublsh1_n
   1478   { TRY(mpn_sublsh1_n), TYPE_SUBLSH1_N },
   1479 #endif
   1480 #if HAVE_NATIVE_mpn_sublsh_n
   1481   { TRY(mpn_sublsh_n), TYPE_SUBLSH_N },
   1482 #endif
   1483 #if HAVE_NATIVE_mpn_rsblsh1_n
   1484   { TRY(mpn_rsblsh1_n), TYPE_RSBLSH1_N },
   1485 #endif
   1486 #if HAVE_NATIVE_mpn_rsblsh2_n
   1487   { TRY(mpn_rsblsh2_n), TYPE_RSBLSH2_N },
   1488 #endif
   1489 #if HAVE_NATIVE_mpn_rsblsh_n
   1490   { TRY(mpn_rsblsh_n), TYPE_RSBLSH_N },
   1491 #endif
   1492 #if HAVE_NATIVE_mpn_rsh1add_n
   1493   { TRY(mpn_rsh1add_n), TYPE_RSH1ADD_N },
   1494 #endif
   1495 #if HAVE_NATIVE_mpn_rsh1sub_n
   1496   { TRY(mpn_rsh1sub_n), TYPE_RSH1SUB_N },
   1497 #endif
   1498 
   1499   { TRY_FUNFUN(mpn_and_n),  TYPE_AND_N  },
   1500   { TRY_FUNFUN(mpn_andn_n), TYPE_ANDN_N },
   1501   { TRY_FUNFUN(mpn_nand_n), TYPE_NAND_N },
   1502   { TRY_FUNFUN(mpn_ior_n),  TYPE_IOR_N  },
   1503   { TRY_FUNFUN(mpn_iorn_n), TYPE_IORN_N },
   1504   { TRY_FUNFUN(mpn_nior_n), TYPE_NIOR_N },
   1505   { TRY_FUNFUN(mpn_xor_n),  TYPE_XOR_N  },
   1506   { TRY_FUNFUN(mpn_xnor_n), TYPE_XNOR_N },
   1507 
   1508   { TRY(mpn_divrem_1),     TYPE_DIVREM_1 },
   1509 #if USE_PREINV_DIVREM_1
   1510   { TRY(mpn_preinv_divrem_1), TYPE_PREINV_DIVREM_1 },
   1511 #endif
   1512   { TRY(mpn_mod_1),        TYPE_MOD_1 },
   1513 #if USE_PREINV_MOD_1
   1514   { TRY(mpn_preinv_mod_1), TYPE_PREINV_MOD_1 },
   1515 #endif
   1516 #if HAVE_NATIVE_mpn_divrem_1c
   1517   { TRY(mpn_divrem_1c),    TYPE_DIVREM_1C },
   1518 #endif
   1519 #if HAVE_NATIVE_mpn_mod_1c
   1520   { TRY(mpn_mod_1c),       TYPE_MOD_1C },
   1521 #endif
   1522 #if GMP_NUMB_BITS % 4 == 0
   1523   { TRY(mpn_mod_34lsub1),  TYPE_MOD_34LSUB1 },
   1524 #endif
   1525 
   1526   { TRY_FUNFUN(udiv_qrnnd), TYPE_UDIV_QRNND, 2 },
   1527 #if HAVE_NATIVE_mpn_udiv_qrnnd
   1528   { TRY(mpn_udiv_qrnnd),    TYPE_UDIV_QRNND, 2 },
   1529 #endif
   1530 #if HAVE_NATIVE_mpn_udiv_qrnnd_r
   1531   { TRY(mpn_udiv_qrnnd_r),  TYPE_UDIV_QRNND_R, 2 },
   1532 #endif
   1533 
   1534   { TRY(mpn_divexact_1),          TYPE_DIVEXACT_1 },
   1535   { TRY_FUNFUN(mpn_divexact_by3), TYPE_DIVEXACT_BY3 },
   1536   { TRY(mpn_divexact_by3c),       TYPE_DIVEXACT_BY3C },
   1537 
   1538   { TRY_FUNFUN(mpn_modexact_1_odd), TYPE_MODEXACT_1_ODD },
   1539   { TRY(mpn_modexact_1c_odd),       TYPE_MODEXACT_1C_ODD },
   1540 
   1541 
   1542   { TRY(mpn_sbpi1_div_qr), TYPE_SBPI1_DIV_QR, 3},
   1543   { TRY(mpn_tdiv_qr),      TYPE_TDIV_QR },
   1544 
   1545   { TRY(mpn_mul_1),      TYPE_MUL_1 },
   1546 #if HAVE_NATIVE_mpn_mul_1c
   1547   { TRY(mpn_mul_1c),     TYPE_MUL_1C },
   1548 #endif
   1549 #if HAVE_NATIVE_mpn_mul_2
   1550   { TRY(mpn_mul_2),      TYPE_MUL_2, 2 },
   1551 #endif
   1552 #if HAVE_NATIVE_mpn_mul_3
   1553   { TRY(mpn_mul_3),      TYPE_MUL_3, 3 },
   1554 #endif
   1555 #if HAVE_NATIVE_mpn_mul_4
   1556   { TRY(mpn_mul_4),      TYPE_MUL_4, 4 },
   1557 #endif
   1558 
   1559   { TRY(mpn_rshift),     TYPE_RSHIFT },
   1560   { TRY(mpn_lshift),     TYPE_LSHIFT },
   1561   { TRY(mpn_lshiftc),    TYPE_LSHIFTC },
   1562 
   1563 
   1564   { TRY(mpn_mul_basecase), TYPE_MUL_MN },
   1565   { TRY(mpn_mullo_basecase), TYPE_MULLO_N },
   1566 #if SQR_TOOM2_THRESHOLD > 0
   1567   { TRY(mpn_sqr_basecase), TYPE_SQR },
   1568 #endif
   1569 
   1570   { TRY(mpn_mul),    TYPE_MUL_MN },
   1571   { TRY(mpn_mul_n),  TYPE_MUL_N },
   1572   { TRY(mpn_sqr),    TYPE_SQR },
   1573 
   1574   { TRY_FUNFUN(umul_ppmm), TYPE_UMUL_PPMM, 2 },
   1575 #if HAVE_NATIVE_mpn_umul_ppmm
   1576   { TRY(mpn_umul_ppmm),    TYPE_UMUL_PPMM, 2 },
   1577 #endif
   1578 #if HAVE_NATIVE_mpn_umul_ppmm_r
   1579   { TRY(mpn_umul_ppmm_r),  TYPE_UMUL_PPMM_R, 2 },
   1580 #endif
   1581 
   1582   { TRY_FUNFUN(mpn_toom22_mul),  TYPE_MUL_N,  MPN_TOOM22_MUL_MINSIZE },
   1583   { TRY_FUNFUN(mpn_toom2_sqr),   TYPE_SQR,    MPN_TOOM2_SQR_MINSIZE },
   1584   { TRY_FUNFUN(mpn_toom33_mul),  TYPE_MUL_N,  MPN_TOOM33_MUL_MINSIZE },
   1585   { TRY_FUNFUN(mpn_toom3_sqr),   TYPE_SQR,    MPN_TOOM3_SQR_MINSIZE },
   1586   { TRY_FUNFUN(mpn_toom44_mul),  TYPE_MUL_N,  MPN_TOOM44_MUL_MINSIZE },
   1587   { TRY_FUNFUN(mpn_toom4_sqr),   TYPE_SQR,    MPN_TOOM4_SQR_MINSIZE },
   1588 
   1589   { TRY(mpn_gcd_1),        TYPE_GCD_1            },
   1590   { TRY(mpn_gcd),          TYPE_GCD              },
   1591   { TRY(mpz_jacobi),       TYPE_MPZ_JACOBI       },
   1592   { TRY(mpz_kronecker_ui), TYPE_MPZ_KRONECKER_UI },
   1593   { TRY(mpz_kronecker_si), TYPE_MPZ_KRONECKER_SI },
   1594   { TRY(mpz_ui_kronecker), TYPE_MPZ_UI_KRONECKER },
   1595   { TRY(mpz_si_kronecker), TYPE_MPZ_SI_KRONECKER },
   1596 
   1597   { TRY(mpn_popcount),   TYPE_POPCOUNT },
   1598   { TRY(mpn_hamdist),    TYPE_HAMDIST },
   1599 
   1600   { TRY(mpn_sqrtrem),    TYPE_SQRTREM },
   1601 
   1602   { TRY_FUNFUN(MPN_ZERO), TYPE_ZERO },
   1603 
   1604   { TRY(mpn_get_str),    TYPE_GET_STR },
   1605 
   1606   { TRY(mpn_binvert),    TYPE_BINVERT },
   1607   { TRY(mpn_invert),     TYPE_INVERT  },
   1608 
   1609 #ifdef EXTRA_ROUTINES
   1610   EXTRA_ROUTINES
   1611 #endif
   1612 };
   1613 
   1614 const struct choice_t *choice = NULL;
   1615 
   1616 
   1617 void
   1618 mprotect_maybe (void *addr, size_t len, int prot)
   1619 {
   1620   if (!option_redzones)
   1621     return;
   1622 
   1623 #if HAVE_MPROTECT
   1624   if (mprotect (addr, len, prot) != 0)
   1625     {
   1626       fprintf (stderr, "Cannot mprotect %p 0x%X 0x%X: %s\n",
   1627 	       addr, (unsigned) len, prot, strerror (errno));
   1628       exit (1);
   1629     }
   1630 #else
   1631   {
   1632     static int  warned = 0;
   1633     if (!warned)
   1634       {
   1635 	fprintf (stderr,
   1636 		 "mprotect not available, bounds testing not performed\n");
   1637 	warned = 1;
   1638       }
   1639   }
   1640 #endif
   1641 }
   1642 
   1643 /* round "a" up to a multiple of "m" */
   1644 size_t
   1645 round_up_multiple (size_t a, size_t m)
   1646 {
   1647   unsigned long  r;
   1648 
   1649   r = a % m;
   1650   if (r == 0)
   1651     return a;
   1652   else
   1653     return a + (m - r);
   1654 }
   1655 
   1656 
   1657 /* On some systems it seems that only an mmap'ed region can be mprotect'ed,
   1658    for instance HP-UX 10.
   1659 
   1660    mmap will almost certainly return a pointer already aligned to a page
   1661    boundary, but it's easy enough to share the alignment handling with the
   1662    malloc case. */
   1663 
   1664 void
   1665 malloc_region (struct region_t *r, mp_size_t n)
   1666 {
   1667   mp_ptr  p;
   1668   size_t  nbytes;
   1669 
   1670   ASSERT ((pagesize % BYTES_PER_MP_LIMB) == 0);
   1671 
   1672   n = round_up_multiple (n, PAGESIZE_LIMBS);
   1673   r->size = n;
   1674 
   1675   nbytes = n*BYTES_PER_MP_LIMB + 2*REDZONE_BYTES + pagesize;
   1676 
   1677 #if defined (MAP_ANONYMOUS) && ! defined (MAP_ANON)
   1678 #define MAP_ANON  MAP_ANONYMOUS
   1679 #endif
   1680 
   1681 #if HAVE_MMAP && defined (MAP_ANON)
   1682   /* note must pass fd=-1 for MAP_ANON on BSD */
   1683   p = mmap (NULL, nbytes, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
   1684   if (p == (void *) -1)
   1685     {
   1686       fprintf (stderr, "Cannot mmap %#x anon bytes: %s\n",
   1687 	       (unsigned) nbytes, strerror (errno));
   1688       exit (1);
   1689     }
   1690 #else
   1691   p = (mp_ptr) malloc (nbytes);
   1692   ASSERT_ALWAYS (p != NULL);
   1693 #endif
   1694 
   1695   p = align_pointer (p, pagesize);
   1696 
   1697   mprotect_maybe (p, REDZONE_BYTES, PROT_NONE);
   1698   p += REDZONE_LIMBS;
   1699   r->ptr = p;
   1700 
   1701   mprotect_maybe (p + n, REDZONE_BYTES, PROT_NONE);
   1702 }
   1703 
   1704 void
   1705 mprotect_region (const struct region_t *r, int prot)
   1706 {
   1707   mprotect_maybe (r->ptr, r->size, prot);
   1708 }
   1709 
   1710 
   1711 /* First four entries must be 0,1,2,3 for the benefit of CARRY_BIT, CARRY_3,
   1712    and CARRY_4 */
   1713 mp_limb_t  carry_array[] = {
   1714   0, 1, 2, 3,
   1715   4,
   1716   CNST_LIMB(1) << 8,
   1717   CNST_LIMB(1) << 16,
   1718   GMP_NUMB_MAX
   1719 };
   1720 int        carry_index;
   1721 
   1722 #define CARRY_COUNT                                             \
   1723   ((tr->carry == CARRY_BIT) ? 2                                 \
   1724    : tr->carry == CARRY_3   ? 3                                 \
   1725    : tr->carry == CARRY_4   ? 4                                 \
   1726    : (tr->carry == CARRY_LIMB || tr->carry == CARRY_DIVISOR)    \
   1727      ? numberof(carry_array) + CARRY_RANDOMS                    \
   1728    : 1)
   1729 
   1730 #define MPN_RANDOM_ALT(index,dst,size) \
   1731   (((index) & 1) ? refmpn_random (dst, size) : refmpn_random2 (dst, size))
   1732 
   1733 /* The dummy value after MPN_RANDOM_ALT ensures both sides of the ":" have
   1734    the same type */
   1735 #define CARRY_ITERATION                                                 \
   1736   for (carry_index = 0;                                                 \
   1737        (carry_index < numberof (carry_array)                            \
   1738 	? (carry = carry_array[carry_index])                            \
   1739 	: (MPN_RANDOM_ALT (carry_index, &carry, 1), (mp_limb_t) 0)),    \
   1740 	 (tr->carry == CARRY_DIVISOR ? carry %= divisor : 0),           \
   1741 	 carry_index < CARRY_COUNT;                                     \
   1742        carry_index++)
   1743 
   1744 
   1745 mp_limb_t  multiplier_array[] = {
   1746   0, 1, 2, 3,
   1747   CNST_LIMB(1) << 8,
   1748   CNST_LIMB(1) << 16,
   1749   GMP_NUMB_MAX - 2,
   1750   GMP_NUMB_MAX - 1,
   1751   GMP_NUMB_MAX
   1752 };
   1753 int        multiplier_index;
   1754 
   1755 mp_limb_t  divisor_array[] = {
   1756   1, 2, 3,
   1757   CNST_LIMB(1) << 8,
   1758   CNST_LIMB(1) << 16,
   1759   CNST_LIMB(1) << (GMP_NUMB_BITS/2 - 1),
   1760   GMP_NUMB_MAX >> (GMP_NUMB_BITS/2),
   1761   GMP_NUMB_HIGHBIT,
   1762   GMP_NUMB_HIGHBIT + 1,
   1763   GMP_NUMB_MAX - 2,
   1764   GMP_NUMB_MAX - 1,
   1765   GMP_NUMB_MAX
   1766 };
   1767 
   1768 int        divisor_index;
   1769 
   1770 /* The dummy value after MPN_RANDOM_ALT ensures both sides of the ":" have
   1771    the same type */
   1772 #define ARRAY_ITERATION(var, index, limit, array, randoms, cond)        \
   1773   for (index = 0;                                                       \
   1774        (index < numberof (array)                                        \
   1775 	? (var = array[index])                                          \
   1776 	: (MPN_RANDOM_ALT (index, &var, 1), (mp_limb_t) 0)),            \
   1777        index < limit;                                                   \
   1778        index++)
   1779 
   1780 #define MULTIPLIER_COUNT                                \
   1781   (tr->multiplier                                       \
   1782     ? numberof (multiplier_array) + MULTIPLIER_RANDOMS  \
   1783     : 1)
   1784 
   1785 #define MULTIPLIER_ITERATION                                            \
   1786   ARRAY_ITERATION(multiplier, multiplier_index, MULTIPLIER_COUNT,       \
   1787 		  multiplier_array, MULTIPLIER_RANDOMS, TRY_MULTIPLIER)
   1788 
   1789 #define DIVISOR_COUNT                           \
   1790   (tr->divisor                                  \
   1791    ? numberof (divisor_array) + DIVISOR_RANDOMS \
   1792    : 1)
   1793 
   1794 #define DIVISOR_ITERATION                                               \
   1795   ARRAY_ITERATION(divisor, divisor_index, DIVISOR_COUNT, divisor_array, \
   1796 		  DIVISOR_RANDOMS, TRY_DIVISOR)
   1797 
   1798 
   1799 /* overlap_array[].s[i] is where s[i] should be, 0 or 1 means overlapping
   1800    d[0] or d[1] respectively, -1 means a separate (write-protected)
   1801    location. */
   1802 
   1803 struct overlap_t {
   1804   int  s[NUM_SOURCES];
   1805 } overlap_array[] = {
   1806   { { -1, -1 } },
   1807   { {  0, -1 } },
   1808   { { -1,  0 } },
   1809   { {  0,  0 } },
   1810   { {  1, -1 } },
   1811   { { -1,  1 } },
   1812   { {  1,  1 } },
   1813   { {  0,  1 } },
   1814   { {  1,  0 } },
   1815 };
   1816 
   1817 struct overlap_t  *overlap, *overlap_limit;
   1818 
   1819 #define OVERLAP_COUNT                   \
   1820   (tr->overlap & OVERLAP_NONE       ? 1 \
   1821    : tr->overlap & OVERLAP_NOT_SRCS ? 3 \
   1822    : tr->overlap & OVERLAP_NOT_SRC2 ? 2 \
   1823    : tr->dst[1]                     ? 9 \
   1824    : tr->src[1]                     ? 4 \
   1825    : tr->dst[0]                     ? 2 \
   1826    : 1)
   1827 
   1828 #define OVERLAP_ITERATION                               \
   1829   for (overlap = &overlap_array[0],                     \
   1830     overlap_limit = &overlap_array[OVERLAP_COUNT];      \
   1831     overlap < overlap_limit;                            \
   1832     overlap++)
   1833 
   1834 
   1835 int  base = 10;
   1836 
   1837 #define T_RAND_COUNT  2
   1838 int  t_rand;
   1839 
   1840 void
   1841 t_random (mp_ptr ptr, mp_size_t n)
   1842 {
   1843   if (n == 0)
   1844     return;
   1845 
   1846   switch (option_data) {
   1847   case DATA_TRAND:
   1848     switch (t_rand) {
   1849     case 0: refmpn_random (ptr, n); break;
   1850     case 1: refmpn_random2 (ptr, n); break;
   1851     default: abort();
   1852     }
   1853     break;
   1854   case DATA_SEQ:
   1855     {
   1856       static mp_limb_t  counter = 0;
   1857       mp_size_t  i;
   1858       for (i = 0; i < n; i++)
   1859 	ptr[i] = ++counter;
   1860     }
   1861     break;
   1862   case DATA_ZEROS:
   1863     refmpn_zero (ptr, n);
   1864     break;
   1865   case DATA_FFS:
   1866     refmpn_fill (ptr, n, GMP_NUMB_MAX);
   1867     break;
   1868   case DATA_2FD:
   1869     /* Special value 0x2FFF...FFFD, which divided by 3 gives 0xFFF...FFF,
   1870        inducing the q1_ff special case in the mul-by-inverse part of some
   1871        versions of divrem_1 and mod_1. */
   1872     refmpn_fill (ptr, n, (mp_limb_t) -1);
   1873     ptr[n-1] = 2;
   1874     ptr[0] -= 2;
   1875     break;
   1876 
   1877   default:
   1878     abort();
   1879   }
   1880 }
   1881 #define T_RAND_ITERATION \
   1882   for (t_rand = 0; t_rand < T_RAND_COUNT; t_rand++)
   1883 
   1884 
   1885 void
   1886 print_each (const struct each_t *e)
   1887 {
   1888   int  i;
   1889 
   1890   printf ("%s %s\n", e->name, e == &ref ? tr->reference_name : choice->name);
   1891   if (tr->retval)
   1892     mpn_trace ("   retval", &e->retval, 1);
   1893 
   1894   for (i = 0; i < NUM_DESTS; i++)
   1895     {
   1896       if (tr->dst[i])
   1897 	{
   1898 	  if (tr->dst_bytes[i])
   1899 	    byte_tracen ("   d[%d]", i, e->d[i].p, d[i].size);
   1900 	  else
   1901 	    mpn_tracen ("   d[%d]", i, e->d[i].p, d[i].size);
   1902 	  printf ("        located %p\n", (void *) (e->d[i].p));
   1903 	}
   1904     }
   1905 
   1906   for (i = 0; i < NUM_SOURCES; i++)
   1907     if (tr->src[i])
   1908       printf ("   s[%d] located %p\n", i, (void *)  (e->s[i].p));
   1909 }
   1910 
   1911 
   1912 void
   1913 print_all (void)
   1914 {
   1915   int  i;
   1916 
   1917   printf ("\n");
   1918   printf ("size  %ld\n", (long) size);
   1919   if (tr->size2)
   1920     printf ("size2 %ld\n", (long) size2);
   1921 
   1922   for (i = 0; i < NUM_DESTS; i++)
   1923     if (d[i].size != size)
   1924       printf ("d[%d].size %ld\n", i, (long) d[i].size);
   1925 
   1926   if (tr->multiplier)
   1927     mpn_trace ("   multiplier", &multiplier, 1);
   1928   if (tr->divisor)
   1929     mpn_trace ("   divisor", &divisor, 1);
   1930   if (tr->shift)
   1931     printf ("   shift %lu\n", shift);
   1932   if (tr->carry)
   1933     mpn_trace ("   carry", &carry, 1);
   1934   if (tr->msize)
   1935     mpn_trace ("   multiplier_N", multiplier_N, tr->msize);
   1936 
   1937   for (i = 0; i < NUM_DESTS; i++)
   1938     if (tr->dst[i])
   1939       printf ("   d[%d] %s, align %ld, size %ld\n",
   1940 	      i, d[i].high ? "high" : "low",
   1941 	      (long) d[i].align, (long) d[i].size);
   1942 
   1943   for (i = 0; i < NUM_SOURCES; i++)
   1944     {
   1945       if (tr->src[i])
   1946 	{
   1947 	  printf ("   s[%d] %s, align %ld, ",
   1948 		  i, s[i].high ? "high" : "low", (long) s[i].align);
   1949 	  switch (overlap->s[i]) {
   1950 	  case -1:
   1951 	    printf ("no overlap\n");
   1952 	    break;
   1953 	  default:
   1954 	    printf ("==d[%d]%s\n",
   1955 		    overlap->s[i],
   1956 		    tr->overlap == OVERLAP_LOW_TO_HIGH ? "+a"
   1957 		    : tr->overlap == OVERLAP_HIGH_TO_LOW ? "-a"
   1958 		    : "");
   1959 	    break;
   1960 	  }
   1961 	  printf ("   s[%d]=", i);
   1962 	  if (tr->carry_sign && (carry & (1 << i)))
   1963 	    printf ("-");
   1964 	  mpn_trace (NULL, s[i].p, SRC_SIZE(i));
   1965 	}
   1966     }
   1967 
   1968   if (tr->dst0_from_src1)
   1969     mpn_trace ("   d[0]", s[1].region.ptr, size);
   1970 
   1971   if (tr->reference)
   1972     print_each (&ref);
   1973   print_each (&fun);
   1974 }
   1975 
   1976 void
   1977 compare (void)
   1978 {
   1979   int  error = 0;
   1980   int  i;
   1981 
   1982   if (tr->retval && ref.retval != fun.retval)
   1983     {
   1984       gmp_printf ("Different return values (%Mu, %Mu)\n",
   1985 		  ref.retval, fun.retval);
   1986       error = 1;
   1987     }
   1988 
   1989   for (i = 0; i < NUM_DESTS; i++)
   1990     {
   1991       switch (tr->dst_size[i]) {
   1992       case SIZE_RETVAL:
   1993       case SIZE_GET_STR:
   1994 	d[i].size = ref.retval;
   1995 	break;
   1996       }
   1997     }
   1998 
   1999   for (i = 0; i < NUM_DESTS; i++)
   2000     {
   2001       if (! tr->dst[i])
   2002 	continue;
   2003 
   2004       if (tr->dst_bytes[i])
   2005 	{
   2006 	  if (memcmp (ref.d[i].p, fun.d[i].p, d[i].size) != 0)
   2007 	    {
   2008 	      printf ("Different d[%d] data results, low diff at %ld, high diff at %ld\n",
   2009 		      i,
   2010 		      (long) byte_diff_lowest (ref.d[i].p, fun.d[i].p, d[i].size),
   2011 		      (long) byte_diff_highest (ref.d[i].p, fun.d[i].p, d[i].size));
   2012 	      error = 1;
   2013 	    }
   2014 	}
   2015       else
   2016 	{
   2017 	  if (d[i].size != 0
   2018 	      && ! refmpn_equal_anynail (ref.d[i].p, fun.d[i].p, d[i].size))
   2019 	    {
   2020 	      printf ("Different d[%d] data results, low diff at %ld, high diff at %ld\n",
   2021 		      i,
   2022 		      (long) mpn_diff_lowest (ref.d[i].p, fun.d[i].p, d[i].size),
   2023 		      (long) mpn_diff_highest (ref.d[i].p, fun.d[i].p, d[i].size));
   2024 	      error = 1;
   2025 	    }
   2026 	}
   2027     }
   2028 
   2029   if (error)
   2030     {
   2031       print_all();
   2032       abort();
   2033     }
   2034 }
   2035 
   2036 
   2037 /* The functions are cast if the return value should be a long rather than
   2038    the default mp_limb_t.  This is necessary under _LONG_LONG_LIMB.  This
   2039    might not be enough if some actual calling conventions checking is
   2040    implemented on a long long limb system.  */
   2041 
   2042 void
   2043 call (struct each_t *e, tryfun_t function)
   2044 {
   2045   switch (choice->type) {
   2046   case TYPE_ADD:
   2047   case TYPE_SUB:
   2048     e->retval = CALLING_CONVENTIONS (function)
   2049       (e->d[0].p, e->s[0].p, size, e->s[1].p, size2);
   2050     break;
   2051 
   2052   case TYPE_ADD_N:
   2053   case TYPE_SUB_N:
   2054   case TYPE_ADDLSH1_N:
   2055   case TYPE_ADDLSH2_N:
   2056   case TYPE_SUBLSH1_N:
   2057   case TYPE_RSBLSH1_N:
   2058   case TYPE_RSBLSH2_N:
   2059   case TYPE_RSH1ADD_N:
   2060   case TYPE_RSH1SUB_N:
   2061     e->retval = CALLING_CONVENTIONS (function)
   2062       (e->d[0].p, e->s[0].p, e->s[1].p, size);
   2063     break;
   2064   case TYPE_ADDLSH_N:
   2065   case TYPE_SUBLSH_N:
   2066   case TYPE_RSBLSH_N:
   2067     e->retval = CALLING_CONVENTIONS (function)
   2068       (e->d[0].p, e->s[0].p, e->s[1].p, size, shift);
   2069     break;
   2070   case TYPE_ADD_NC:
   2071   case TYPE_SUB_NC:
   2072     e->retval = CALLING_CONVENTIONS (function)
   2073       (e->d[0].p, e->s[0].p, e->s[1].p, size, carry);
   2074     break;
   2075 
   2076   case TYPE_MUL_1:
   2077   case TYPE_ADDMUL_1:
   2078   case TYPE_SUBMUL_1:
   2079     e->retval = CALLING_CONVENTIONS (function)
   2080       (e->d[0].p, e->s[0].p, size, multiplier);
   2081     break;
   2082   case TYPE_MUL_1C:
   2083   case TYPE_ADDMUL_1C:
   2084   case TYPE_SUBMUL_1C:
   2085     e->retval = CALLING_CONVENTIONS (function)
   2086       (e->d[0].p, e->s[0].p, size, multiplier, carry);
   2087     break;
   2088 
   2089   case TYPE_MUL_2:
   2090   case TYPE_MUL_3:
   2091   case TYPE_MUL_4:
   2092     if (size == 1)
   2093       abort ();
   2094     e->retval = CALLING_CONVENTIONS (function)
   2095       (e->d[0].p, e->s[0].p, size, multiplier_N);
   2096     break;
   2097 
   2098   case TYPE_ADDMUL_2:
   2099   case TYPE_ADDMUL_3:
   2100   case TYPE_ADDMUL_4:
   2101   case TYPE_ADDMUL_5:
   2102   case TYPE_ADDMUL_6:
   2103   case TYPE_ADDMUL_7:
   2104   case TYPE_ADDMUL_8:
   2105     if (size == 1)
   2106       abort ();
   2107     e->retval = CALLING_CONVENTIONS (function)
   2108       (e->d[0].p, e->s[0].p, size, multiplier_N);
   2109     break;
   2110 
   2111   case TYPE_AND_N:
   2112   case TYPE_ANDN_N:
   2113   case TYPE_NAND_N:
   2114   case TYPE_IOR_N:
   2115   case TYPE_IORN_N:
   2116   case TYPE_NIOR_N:
   2117   case TYPE_XOR_N:
   2118   case TYPE_XNOR_N:
   2119     CALLING_CONVENTIONS (function) (e->d[0].p, e->s[0].p, e->s[1].p, size);
   2120     break;
   2121 
   2122   case TYPE_ADDSUB_N:
   2123     e->retval = CALLING_CONVENTIONS (function)
   2124       (e->d[0].p, e->d[1].p, e->s[0].p, e->s[1].p, size);
   2125     break;
   2126   case TYPE_ADDSUB_NC:
   2127     e->retval = CALLING_CONVENTIONS (function)
   2128       (e->d[0].p, e->d[1].p, e->s[0].p, e->s[1].p, size, carry);
   2129     break;
   2130 
   2131   case TYPE_COPY:
   2132   case TYPE_COPYI:
   2133   case TYPE_COPYD:
   2134   case TYPE_COM:
   2135     CALLING_CONVENTIONS (function) (e->d[0].p, e->s[0].p, size);
   2136     break;
   2137 
   2138 
   2139   case TYPE_DIVEXACT_BY3:
   2140     e->retval = CALLING_CONVENTIONS (function) (e->d[0].p, e->s[0].p, size);
   2141     break;
   2142   case TYPE_DIVEXACT_BY3C:
   2143     e->retval = CALLING_CONVENTIONS (function) (e->d[0].p, e->s[0].p, size,
   2144 						carry);
   2145     break;
   2146 
   2147 
   2148   case TYPE_DIVMOD_1:
   2149   case TYPE_DIVEXACT_1:
   2150     e->retval = CALLING_CONVENTIONS (function)
   2151       (e->d[0].p, e->s[0].p, size, divisor);
   2152     break;
   2153   case TYPE_DIVMOD_1C:
   2154     e->retval = CALLING_CONVENTIONS (function)
   2155       (e->d[0].p, e->s[0].p, size, divisor, carry);
   2156     break;
   2157   case TYPE_DIVREM_1:
   2158     e->retval = CALLING_CONVENTIONS (function)
   2159       (e->d[0].p, size2, e->s[0].p, size, divisor);
   2160     break;
   2161   case TYPE_DIVREM_1C:
   2162     e->retval = CALLING_CONVENTIONS (function)
   2163       (e->d[0].p, size2, e->s[0].p, size, divisor, carry);
   2164     break;
   2165   case TYPE_PREINV_DIVREM_1:
   2166     {
   2167       mp_limb_t  dinv;
   2168       unsigned   shift;
   2169       shift = refmpn_count_leading_zeros (divisor);
   2170       dinv = refmpn_invert_limb (divisor << shift);
   2171       e->retval = CALLING_CONVENTIONS (function)
   2172 	(e->d[0].p, size2, e->s[0].p, size, divisor, dinv, shift);
   2173     }
   2174     break;
   2175   case TYPE_MOD_1:
   2176   case TYPE_MODEXACT_1_ODD:
   2177     e->retval = CALLING_CONVENTIONS (function)
   2178       (e->s[0].p, size, divisor);
   2179     break;
   2180   case TYPE_MOD_1C:
   2181   case TYPE_MODEXACT_1C_ODD:
   2182     e->retval = CALLING_CONVENTIONS (function)
   2183       (e->s[0].p, size, divisor, carry);
   2184     break;
   2185   case TYPE_PREINV_MOD_1:
   2186     e->retval = CALLING_CONVENTIONS (function)
   2187       (e->s[0].p, size, divisor, refmpn_invert_limb (divisor));
   2188     break;
   2189   case TYPE_MOD_34LSUB1:
   2190     e->retval = CALLING_CONVENTIONS (function) (e->s[0].p, size);
   2191     break;
   2192 
   2193   case TYPE_UDIV_QRNND:
   2194     e->retval = CALLING_CONVENTIONS (function)
   2195       (e->d[0].p, e->s[0].p[1], e->s[0].p[0], divisor);
   2196     break;
   2197   case TYPE_UDIV_QRNND_R:
   2198     e->retval = CALLING_CONVENTIONS (function)
   2199       (e->s[0].p[1], e->s[0].p[0], divisor, e->d[0].p);
   2200     break;
   2201 
   2202   case TYPE_SBPI1_DIV_QR:
   2203     {
   2204       gmp_pi1_t dinv;
   2205       invert_pi1 (dinv, e->s[1].p[size2-1], e->s[1].p[size2-2]); /* FIXME: use refinvert_pi1 */
   2206       refmpn_copyi (e->d[1].p, e->s[0].p, size);        /* dividend */
   2207       refmpn_fill (e->d[0].p, size-size2, 0x98765432);  /* quotient */
   2208       e->retval = CALLING_CONVENTIONS (function)
   2209 	(e->d[0].p, e->d[1].p, size, e->s[1].p, size2, dinv.inv32);
   2210       refmpn_zero (e->d[1].p+size2, size-size2);    /* excess over remainder */
   2211     }
   2212     break;
   2213 
   2214   case TYPE_TDIV_QR:
   2215     CALLING_CONVENTIONS (function) (e->d[0].p, e->d[1].p, 0,
   2216 				    e->s[0].p, size, e->s[1].p, size2);
   2217     break;
   2218 
   2219   case TYPE_GCD_1:
   2220     /* Must have a non-zero src, but this probably isn't the best way to do
   2221        it. */
   2222     if (refmpn_zero_p (e->s[0].p, size))
   2223       e->retval = 0;
   2224     else
   2225       e->retval = CALLING_CONVENTIONS (function) (e->s[0].p, size, divisor);
   2226     break;
   2227 
   2228   case TYPE_GCD:
   2229     /* Sources are destroyed, so they're saved and replaced, but a general
   2230        approach to this might be better.  Note that it's still e->s[0].p and
   2231        e->s[1].p that are passed, to get the desired alignments. */
   2232     {
   2233       mp_ptr  s0 = refmpn_malloc_limbs (size);
   2234       mp_ptr  s1 = refmpn_malloc_limbs (size2);
   2235       refmpn_copyi (s0, e->s[0].p, size);
   2236       refmpn_copyi (s1, e->s[1].p, size2);
   2237 
   2238       mprotect_region (&s[0].region, PROT_READ|PROT_WRITE);
   2239       mprotect_region (&s[1].region, PROT_READ|PROT_WRITE);
   2240       e->retval = CALLING_CONVENTIONS (function) (e->d[0].p,
   2241 						  e->s[0].p, size,
   2242 						  e->s[1].p, size2);
   2243       refmpn_copyi (e->s[0].p, s0, size);
   2244       refmpn_copyi (e->s[1].p, s1, size2);
   2245       free (s0);
   2246       free (s1);
   2247     }
   2248     break;
   2249 
   2250   case TYPE_GCD_FINDA:
   2251     {
   2252       /* FIXME: do this with a flag */
   2253       mp_limb_t  c[2];
   2254       c[0] = e->s[0].p[0];
   2255       c[0] += (c[0] == 0);
   2256       c[1] = e->s[0].p[0];
   2257       c[1] += (c[1] == 0);
   2258       e->retval = CALLING_CONVENTIONS (function) (c);
   2259     }
   2260     break;
   2261 
   2262   case TYPE_MPZ_JACOBI:
   2263   case TYPE_MPZ_KRONECKER:
   2264     {
   2265       mpz_t  a, b;
   2266       PTR(a) = e->s[0].p; SIZ(a) = ((carry&1)==0 ? size : -size);
   2267       PTR(b) = e->s[1].p; SIZ(b) = ((carry&2)==0 ? size2 : -size2);
   2268       e->retval = CALLING_CONVENTIONS (function) (a, b);
   2269     }
   2270     break;
   2271   case TYPE_MPZ_KRONECKER_UI:
   2272     {
   2273       mpz_t  a;
   2274       PTR(a) = e->s[0].p; SIZ(a) = (carry==0 ? size : -size);
   2275       e->retval = CALLING_CONVENTIONS(function) (a, (unsigned long)multiplier);
   2276     }
   2277     break;
   2278   case TYPE_MPZ_KRONECKER_SI:
   2279     {
   2280       mpz_t  a;
   2281       PTR(a) = e->s[0].p; SIZ(a) = (carry==0 ? size : -size);
   2282       e->retval = CALLING_CONVENTIONS (function) (a, (long) multiplier);
   2283     }
   2284     break;
   2285   case TYPE_MPZ_UI_KRONECKER:
   2286     {
   2287       mpz_t  b;
   2288       PTR(b) = e->s[0].p; SIZ(b) = (carry==0 ? size : -size);
   2289       e->retval = CALLING_CONVENTIONS(function) ((unsigned long)multiplier, b);
   2290     }
   2291     break;
   2292   case TYPE_MPZ_SI_KRONECKER:
   2293     {
   2294       mpz_t  b;
   2295       PTR(b) = e->s[0].p; SIZ(b) = (carry==0 ? size : -size);
   2296       e->retval = CALLING_CONVENTIONS (function) ((long) multiplier, b);
   2297     }
   2298     break;
   2299 
   2300   case TYPE_MUL_MN:
   2301     CALLING_CONVENTIONS (function)
   2302       (e->d[0].p, e->s[0].p, size, e->s[1].p, size2);
   2303     break;
   2304   case TYPE_MUL_N:
   2305   case TYPE_MULLO_N:
   2306     CALLING_CONVENTIONS (function) (e->d[0].p, e->s[0].p, e->s[1].p, size);
   2307     break;
   2308   case TYPE_SQR:
   2309     CALLING_CONVENTIONS (function) (e->d[0].p, e->s[0].p, size);
   2310     break;
   2311 
   2312   case TYPE_UMUL_PPMM:
   2313     e->retval = CALLING_CONVENTIONS (function)
   2314       (e->d[0].p, e->s[0].p[0], e->s[0].p[1]);
   2315     break;
   2316   case TYPE_UMUL_PPMM_R:
   2317     e->retval = CALLING_CONVENTIONS (function)
   2318       (e->s[0].p[0], e->s[0].p[1], e->d[0].p);
   2319     break;
   2320 
   2321   case TYPE_LSHIFT:
   2322   case TYPE_LSHIFTC:
   2323   case TYPE_RSHIFT:
   2324     e->retval = CALLING_CONVENTIONS (function)
   2325       (e->d[0].p, e->s[0].p, size, shift);
   2326     break;
   2327 
   2328   case TYPE_POPCOUNT:
   2329     e->retval = (* (unsigned long (*)(ANYARGS))
   2330 		 CALLING_CONVENTIONS (function)) (e->s[0].p, size);
   2331     break;
   2332   case TYPE_HAMDIST:
   2333     e->retval = (* (unsigned long (*)(ANYARGS))
   2334 		 CALLING_CONVENTIONS (function)) (e->s[0].p, e->s[1].p, size);
   2335     break;
   2336 
   2337   case TYPE_SQRTREM:
   2338     e->retval = (* (long (*)(ANYARGS)) CALLING_CONVENTIONS (function))
   2339       (e->d[0].p, e->d[1].p, e->s[0].p, size);
   2340     break;
   2341 
   2342   case TYPE_ZERO:
   2343     CALLING_CONVENTIONS (function) (e->d[0].p, size);
   2344     break;
   2345 
   2346   case TYPE_GET_STR:
   2347     {
   2348       size_t  sizeinbase, fill;
   2349       char    *dst;
   2350       MPN_SIZEINBASE (sizeinbase, e->s[0].p, size, base);
   2351       ASSERT_ALWAYS (sizeinbase <= d[0].size);
   2352       fill = d[0].size - sizeinbase;
   2353       if (d[0].high)
   2354 	{
   2355 	  memset (e->d[0].p, 0xBA, fill);
   2356 	  dst = (char *) e->d[0].p + fill;
   2357 	}
   2358       else
   2359 	{
   2360 	  dst = (char *) e->d[0].p;
   2361 	  memset (dst + sizeinbase, 0xBA, fill);
   2362 	}
   2363       if (POW2_P (base))
   2364 	{
   2365 	  e->retval = CALLING_CONVENTIONS (function) (dst, base,
   2366 						      e->s[0].p, size);
   2367 	}
   2368       else
   2369 	{
   2370 	  refmpn_copy (e->d[1].p, e->s[0].p, size);
   2371 	  e->retval = CALLING_CONVENTIONS (function) (dst, base,
   2372 						      e->d[1].p, size);
   2373 	}
   2374       refmpn_zero (e->d[1].p, size);  /* clobbered or unused */
   2375     }
   2376     break;
   2377 
   2378  case TYPE_INVERT:
   2379     {
   2380       mp_ptr scratch;
   2381       TMP_DECL;
   2382       TMP_MARK;
   2383       scratch = TMP_ALLOC_LIMBS (mpn_invert_itch (size));
   2384       CALLING_CONVENTIONS (function) (e->d[0].p, e->s[0].p, size, scratch);
   2385       TMP_FREE;
   2386     }
   2387     break;
   2388   case TYPE_BINVERT:
   2389     {
   2390       mp_ptr scratch;
   2391       TMP_DECL;
   2392       TMP_MARK;
   2393       scratch = TMP_ALLOC_LIMBS (mpn_binvert_itch (size));
   2394       CALLING_CONVENTIONS (function) (e->d[0].p, e->s[0].p, size, scratch);
   2395       TMP_FREE;
   2396     }
   2397     break;
   2398 
   2399 #ifdef EXTRA_CALL
   2400     EXTRA_CALL
   2401 #endif
   2402 
   2403   default:
   2404     printf ("Unknown routine type %d\n", choice->type);
   2405     abort ();
   2406     break;
   2407   }
   2408 }
   2409 
   2410 
   2411 void
   2412 pointer_setup (struct each_t *e)
   2413 {
   2414   int  i, j;
   2415 
   2416   for (i = 0; i < NUM_DESTS; i++)
   2417     {
   2418       switch (tr->dst_size[i]) {
   2419       case 0:
   2420       case SIZE_RETVAL: /* will be adjusted later */
   2421 	d[i].size = size;
   2422 	break;
   2423 
   2424       case SIZE_1:
   2425 	d[i].size = 1;
   2426 	break;
   2427       case SIZE_2:
   2428 	d[i].size = 2;
   2429 	break;
   2430       case SIZE_3:
   2431 	d[i].size = 3;
   2432 	break;
   2433 
   2434       case SIZE_PLUS_1:
   2435 	d[i].size = size+1;
   2436 	break;
   2437       case SIZE_PLUS_MSIZE_SUB_1:
   2438 	d[i].size = size + tr->msize - 1;
   2439 	break;
   2440 
   2441       case SIZE_SUM:
   2442 	if (tr->size2)
   2443 	  d[i].size = size + size2;
   2444 	else
   2445 	  d[i].size = 2*size;
   2446 	break;
   2447 
   2448       case SIZE_SIZE2:
   2449 	d[i].size = size2;
   2450 	break;
   2451 
   2452       case SIZE_DIFF:
   2453 	d[i].size = size - size2;
   2454 	break;
   2455 
   2456       case SIZE_DIFF_PLUS_1:
   2457 	d[i].size = size - size2 + 1;
   2458 	break;
   2459 
   2460       case SIZE_CEIL_HALF:
   2461 	d[i].size = (size+1)/2;
   2462 	break;
   2463 
   2464       case SIZE_GET_STR:
   2465 	{
   2466 	  mp_limb_t ff = GMP_NUMB_MAX;
   2467 	  MPN_SIZEINBASE (d[i].size, &ff - (size-1), size, base);
   2468 	}
   2469 	break;
   2470 
   2471       default:
   2472 	printf ("Unrecognised dst_size type %d\n", tr->dst_size[i]);
   2473 	abort ();
   2474       }
   2475     }
   2476 
   2477   /* establish e->d[].p destinations */
   2478   for (i = 0; i < NUM_DESTS; i++)
   2479     {
   2480       mp_size_t  offset = 0;
   2481 
   2482       /* possible room for overlapping sources */
   2483       for (j = 0; j < numberof (overlap->s); j++)
   2484 	if (overlap->s[j] == i)
   2485 	  offset = MAX (offset, s[j].align);
   2486 
   2487       if (d[i].high)
   2488 	{
   2489 	  if (tr->dst_bytes[i])
   2490 	    {
   2491 	      e->d[i].p = (mp_ptr)
   2492 		((char *) (e->d[i].region.ptr + e->d[i].region.size)
   2493 		 - d[i].size - d[i].align);
   2494 	    }
   2495 	  else
   2496 	    {
   2497 	      e->d[i].p = e->d[i].region.ptr + e->d[i].region.size
   2498 		- d[i].size - d[i].align;
   2499 	      if (tr->overlap == OVERLAP_LOW_TO_HIGH)
   2500 		e->d[i].p -= offset;
   2501 	    }
   2502 	}
   2503       else
   2504 	{
   2505 	  if (tr->dst_bytes[i])
   2506 	    {
   2507 	      e->d[i].p = (mp_ptr) ((char *) e->d[i].region.ptr + d[i].align);
   2508 	    }
   2509 	  else
   2510 	    {
   2511 	      e->d[i].p = e->d[i].region.ptr + d[i].align;
   2512 	      if (tr->overlap == OVERLAP_HIGH_TO_LOW)
   2513 		e->d[i].p += offset;
   2514 	    }
   2515 	}
   2516     }
   2517 
   2518   /* establish e->s[].p sources */
   2519   for (i = 0; i < NUM_SOURCES; i++)
   2520     {
   2521       int  o = overlap->s[i];
   2522       switch (o) {
   2523       case -1:
   2524 	/* no overlap */
   2525 	e->s[i].p = s[i].p;
   2526 	break;
   2527       case 0:
   2528       case 1:
   2529 	/* overlap with d[o] */
   2530 	if (tr->overlap == OVERLAP_HIGH_TO_LOW)
   2531 	  e->s[i].p = e->d[o].p - s[i].align;
   2532 	else if (tr->overlap == OVERLAP_LOW_TO_HIGH)
   2533 	  e->s[i].p = e->d[o].p + s[i].align;
   2534 	else if (tr->size2 == SIZE_FRACTION)
   2535 	  e->s[i].p = e->d[o].p + size2;
   2536 	else
   2537 	  e->s[i].p = e->d[o].p;
   2538 	break;
   2539       default:
   2540 	abort();
   2541 	break;
   2542       }
   2543     }
   2544 }
   2545 
   2546 
   2547 void
   2548 validate_fail (void)
   2549 {
   2550   if (tr->reference)
   2551     {
   2552       trap_location = TRAP_REF;
   2553       call (&ref, tr->reference);
   2554       trap_location = TRAP_NOWHERE;
   2555     }
   2556 
   2557   print_all();
   2558   abort();
   2559 }
   2560 
   2561 
   2562 void
   2563 try_one (void)
   2564 {
   2565   int  i;
   2566 
   2567   if (option_spinner)
   2568     spinner();
   2569   spinner_count++;
   2570 
   2571   trap_location = TRAP_SETUPS;
   2572 
   2573   if (tr->divisor == DIVISOR_NORM)
   2574     divisor |= GMP_NUMB_HIGHBIT;
   2575   if (tr->divisor == DIVISOR_ODD)
   2576     divisor |= 1;
   2577 
   2578   for (i = 0; i < NUM_SOURCES; i++)
   2579     {
   2580       if (s[i].high)
   2581 	s[i].p = s[i].region.ptr + s[i].region.size - SRC_SIZE(i) - s[i].align;
   2582       else
   2583 	s[i].p = s[i].region.ptr + s[i].align;
   2584     }
   2585 
   2586   pointer_setup (&ref);
   2587   pointer_setup (&fun);
   2588 
   2589   ref.retval = 0x04152637;
   2590   fun.retval = 0x8C9DAEBF;
   2591 
   2592   t_random (multiplier_N, tr->msize);
   2593 
   2594   for (i = 0; i < NUM_SOURCES; i++)
   2595     {
   2596       if (! tr->src[i])
   2597 	continue;
   2598 
   2599       mprotect_region (&s[i].region, PROT_READ|PROT_WRITE);
   2600       t_random (s[i].p, SRC_SIZE(i));
   2601 
   2602       switch (tr->data) {
   2603       case DATA_NON_ZERO:
   2604 	if (refmpn_zero_p (s[i].p, SRC_SIZE(i)))
   2605 	  s[i].p[0] = 1;
   2606 	break;
   2607 
   2608       case DATA_MULTIPLE_DIVISOR:
   2609 	/* same number of low zero bits as divisor */
   2610 	s[i].p[0] &= ~ LOW_ZEROS_MASK (divisor);
   2611 	refmpn_sub_1 (s[i].p, s[i].p, size,
   2612 		      refmpn_mod_1 (s[i].p, size, divisor));
   2613 	break;
   2614 
   2615       case DATA_GCD:
   2616 	/* s[1] no more bits than s[0] */
   2617 	if (i == 1 && size2 == size)
   2618 	  s[1].p[size-1] &= refmpn_msbone_mask (s[0].p[size-1]);
   2619 
   2620 	/* high limb non-zero */
   2621 	s[i].p[SRC_SIZE(i)-1] += (s[i].p[SRC_SIZE(i)-1] == 0);
   2622 
   2623 	/* odd */
   2624 	s[i].p[0] |= 1;
   2625 	break;
   2626 
   2627       case DATA_SRC0_ODD:
   2628 	if (i == 0)
   2629 	  s[i].p[0] |= 1;
   2630 	break;
   2631 
   2632       case DATA_SRC1_ODD:
   2633 	if (i == 1)
   2634 	  s[i].p[0] |= 1;
   2635 	break;
   2636 
   2637       case DATA_SRC1_HIGHBIT:
   2638 	if (i == 1)
   2639 	  {
   2640 	    if (tr->size2)
   2641 	      s[i].p[size2-1] |= GMP_NUMB_HIGHBIT;
   2642 	    else
   2643 	      s[i].p[size-1] |= GMP_NUMB_HIGHBIT;
   2644 	  }
   2645 	break;
   2646 
   2647       case DATA_SRC0_HIGHBIT:
   2648        if (i == 0)
   2649          {
   2650            s[i].p[size-1] |= GMP_NUMB_HIGHBIT;
   2651          }
   2652        break;
   2653 
   2654       case DATA_UDIV_QRNND:
   2655 	s[i].p[1] %= divisor;
   2656 	break;
   2657       }
   2658 
   2659       mprotect_region (&s[i].region, PROT_READ);
   2660     }
   2661 
   2662   for (i = 0; i < NUM_DESTS; i++)
   2663     {
   2664       if (! tr->dst[i])
   2665 	continue;
   2666 
   2667       if (tr->dst0_from_src1 && i==0)
   2668 	{
   2669 	  mp_size_t  copy = MIN (d[0].size, SRC_SIZE(1));
   2670 	  mp_size_t  fill = MAX (0, d[0].size - copy);
   2671 	  MPN_COPY (fun.d[0].p, s[1].region.ptr, copy);
   2672 	  MPN_COPY (ref.d[0].p, s[1].region.ptr, copy);
   2673 	  refmpn_fill (fun.d[0].p + copy, fill, DEADVAL);
   2674 	  refmpn_fill (ref.d[0].p + copy, fill, DEADVAL);
   2675 	}
   2676       else if (tr->dst_bytes[i])
   2677 	{
   2678 	  memset (ref.d[i].p, 0xBA, d[i].size);
   2679 	  memset (fun.d[i].p, 0xBA, d[i].size);
   2680 	}
   2681       else
   2682 	{
   2683 	  refmpn_fill (ref.d[i].p, d[i].size, DEADVAL);
   2684 	  refmpn_fill (fun.d[i].p, d[i].size, DEADVAL);
   2685 	}
   2686     }
   2687 
   2688   for (i = 0; i < NUM_SOURCES; i++)
   2689     {
   2690       if (! tr->src[i])
   2691 	continue;
   2692 
   2693       if (ref.s[i].p != s[i].p)
   2694 	{
   2695 	  refmpn_copyi (ref.s[i].p, s[i].p, SRC_SIZE(i));
   2696 	  refmpn_copyi (fun.s[i].p, s[i].p, SRC_SIZE(i));
   2697 	}
   2698     }
   2699 
   2700   if (option_print)
   2701     print_all();
   2702 
   2703   if (tr->validate != NULL)
   2704     {
   2705       trap_location = TRAP_FUN;
   2706       call (&fun, choice->function);
   2707       trap_location = TRAP_NOWHERE;
   2708 
   2709       if (! CALLING_CONVENTIONS_CHECK ())
   2710 	{
   2711 	  print_all();
   2712 	  abort();
   2713 	}
   2714 
   2715       (*tr->validate) ();
   2716     }
   2717   else
   2718     {
   2719       trap_location = TRAP_REF;
   2720       call (&ref, tr->reference);
   2721       trap_location = TRAP_FUN;
   2722       call (&fun, choice->function);
   2723       trap_location = TRAP_NOWHERE;
   2724 
   2725       if (! CALLING_CONVENTIONS_CHECK ())
   2726 	{
   2727 	  print_all();
   2728 	  abort();
   2729 	}
   2730 
   2731       compare ();
   2732     }
   2733 }
   2734 
   2735 
   2736 #define SIZE_ITERATION                                          \
   2737   for (size = MAX3 (option_firstsize,                           \
   2738 		    choice->minsize,                            \
   2739 		    (tr->size == SIZE_ALLOW_ZERO) ? 0 : 1);     \
   2740        size <= option_lastsize;                                 \
   2741        size++)
   2742 
   2743 #define SIZE2_FIRST                                     \
   2744   (tr->size2 == SIZE_2 ? 2                              \
   2745    : tr->size2 == SIZE_FRACTION ? option_firstsize2     \
   2746    : tr->size2 ?                                        \
   2747    MAX (choice->minsize, (option_firstsize2 != 0        \
   2748 			  ? option_firstsize2 : 1))     \
   2749    : 0)
   2750 
   2751 #define SIZE2_LAST                                      \
   2752   (tr->size2 == SIZE_2 ? 2                              \
   2753    : tr->size2 == SIZE_FRACTION ? FRACTION_COUNT-1      \
   2754    : tr->size2 ? size                                   \
   2755    : 0)
   2756 
   2757 #define SIZE2_ITERATION \
   2758   for (size2 = SIZE2_FIRST; size2 <= SIZE2_LAST; size2++)
   2759 
   2760 #define ALIGN_COUNT(cond)  ((cond) ? ALIGNMENTS : 1)
   2761 #define ALIGN_ITERATION(w,n,cond) \
   2762   for (w[n].align = 0; w[n].align < ALIGN_COUNT(cond); w[n].align++)
   2763 
   2764 #define HIGH_LIMIT(cond)  ((cond) != 0)
   2765 #define HIGH_COUNT(cond)  (HIGH_LIMIT (cond) + 1)
   2766 #define HIGH_ITERATION(w,n,cond) \
   2767   for (w[n].high = 0; w[n].high <= HIGH_LIMIT(cond); w[n].high++)
   2768 
   2769 #define SHIFT_LIMIT                                     \
   2770   ((unsigned long) (tr->shift ? GMP_NUMB_BITS -1 : 1))
   2771 
   2772 #define SHIFT_ITERATION                                 \
   2773   for (shift = 1; shift <= SHIFT_LIMIT; shift++)
   2774 
   2775 
   2776 void
   2777 try_many (void)
   2778 {
   2779   int   i;
   2780 
   2781   {
   2782     unsigned long  total = 1;
   2783 
   2784     total *= option_repetitions;
   2785     total *= option_lastsize;
   2786     if (tr->size2 == SIZE_FRACTION) total *= FRACTION_COUNT;
   2787     else if (tr->size2)             total *= (option_lastsize+1)/2;
   2788 
   2789     total *= SHIFT_LIMIT;
   2790     total *= MULTIPLIER_COUNT;
   2791     total *= DIVISOR_COUNT;
   2792     total *= CARRY_COUNT;
   2793     total *= T_RAND_COUNT;
   2794 
   2795     total *= HIGH_COUNT (tr->dst[0]);
   2796     total *= HIGH_COUNT (tr->dst[1]);
   2797     total *= HIGH_COUNT (tr->src[0]);
   2798     total *= HIGH_COUNT (tr->src[1]);
   2799 
   2800     total *= ALIGN_COUNT (tr->dst[0]);
   2801     total *= ALIGN_COUNT (tr->dst[1]);
   2802     total *= ALIGN_COUNT (tr->src[0]);
   2803     total *= ALIGN_COUNT (tr->src[1]);
   2804 
   2805     total *= OVERLAP_COUNT;
   2806 
   2807     printf ("%s %lu\n", choice->name, total);
   2808   }
   2809 
   2810   spinner_count = 0;
   2811 
   2812   for (i = 0; i < option_repetitions; i++)
   2813     SIZE_ITERATION
   2814       SIZE2_ITERATION
   2815 
   2816       SHIFT_ITERATION
   2817       MULTIPLIER_ITERATION
   2818       DIVISOR_ITERATION
   2819       CARRY_ITERATION /* must be after divisor */
   2820       T_RAND_ITERATION
   2821 
   2822       HIGH_ITERATION(d,0, tr->dst[0])
   2823       HIGH_ITERATION(d,1, tr->dst[1])
   2824       HIGH_ITERATION(s,0, tr->src[0])
   2825       HIGH_ITERATION(s,1, tr->src[1])
   2826 
   2827       ALIGN_ITERATION(d,0, tr->dst[0])
   2828       ALIGN_ITERATION(d,1, tr->dst[1])
   2829       ALIGN_ITERATION(s,0, tr->src[0])
   2830       ALIGN_ITERATION(s,1, tr->src[1])
   2831 
   2832       OVERLAP_ITERATION
   2833       try_one();
   2834 
   2835   printf("\n");
   2836 }
   2837 
   2838 
   2839 /* Usually print_all() doesn't show much, but it might give a hint as to
   2840    where the function was up to when it died. */
   2841 void
   2842 trap (int sig)
   2843 {
   2844   const char *name = "noname";
   2845 
   2846   switch (sig) {
   2847   case SIGILL:  name = "SIGILL";  break;
   2848 #ifdef SIGBUS
   2849   case SIGBUS:  name = "SIGBUS";  break;
   2850 #endif
   2851   case SIGSEGV: name = "SIGSEGV"; break;
   2852   case SIGFPE:  name = "SIGFPE";  break;
   2853   }
   2854 
   2855   printf ("\n\nSIGNAL TRAP: %s\n", name);
   2856 
   2857   switch (trap_location) {
   2858   case TRAP_REF:
   2859     printf ("  in reference function: %s\n", tr->reference_name);
   2860     break;
   2861   case TRAP_FUN:
   2862     printf ("  in test function: %s\n", choice->name);
   2863     print_all ();
   2864     break;
   2865   case TRAP_SETUPS:
   2866     printf ("  in parameter setups\n");
   2867     print_all ();
   2868     break;
   2869   default:
   2870     printf ("  somewhere unknown\n");
   2871     break;
   2872   }
   2873   exit (1);
   2874 }
   2875 
   2876 
   2877 void
   2878 try_init (void)
   2879 {
   2880 #if HAVE_GETPAGESIZE
   2881   /* Prefer getpagesize() over sysconf(), since on SunOS 4 sysconf() doesn't
   2882      know _SC_PAGESIZE. */
   2883   pagesize = getpagesize ();
   2884 #else
   2885 #if HAVE_SYSCONF
   2886   if ((pagesize = sysconf (_SC_PAGESIZE)) == -1)
   2887     {
   2888       /* According to the linux man page, sysconf doesn't set errno */
   2889       fprintf (stderr, "Cannot get sysconf _SC_PAGESIZE\n");
   2890       exit (1);
   2891     }
   2892 #else
   2893 Error, error, cannot get page size
   2894 #endif
   2895 #endif
   2896 
   2897   printf ("pagesize is 0x%lX bytes\n", pagesize);
   2898 
   2899   signal (SIGILL,  trap);
   2900 #ifdef SIGBUS
   2901   signal (SIGBUS,  trap);
   2902 #endif
   2903   signal (SIGSEGV, trap);
   2904   signal (SIGFPE,  trap);
   2905 
   2906   {
   2907     int  i;
   2908 
   2909     for (i = 0; i < NUM_SOURCES; i++)
   2910       {
   2911 	malloc_region (&s[i].region, 2*option_lastsize+ALIGNMENTS-1);
   2912 	printf ("s[%d] %p to %p (0x%lX bytes)\n",
   2913 		i, (void *) (s[i].region.ptr),
   2914 		(void *) (s[i].region.ptr + s[i].region.size),
   2915 		(long) s[i].region.size * BYTES_PER_MP_LIMB);
   2916       }
   2917 
   2918 #define INIT_EACH(e,es)                                                 \
   2919     for (i = 0; i < NUM_DESTS; i++)                                     \
   2920       {                                                                 \
   2921 	malloc_region (&e.d[i].region, 2*option_lastsize+ALIGNMENTS-1); \
   2922 	printf ("%s d[%d] %p to %p (0x%lX bytes)\n",                    \
   2923 		es, i, (void *) (e.d[i].region.ptr),			\
   2924 		(void *)  (e.d[i].region.ptr + e.d[i].region.size),	\
   2925 		(long) e.d[i].region.size * BYTES_PER_MP_LIMB);         \
   2926       }
   2927 
   2928     INIT_EACH(ref, "ref");
   2929     INIT_EACH(fun, "fun");
   2930   }
   2931 }
   2932 
   2933 int
   2934 strmatch_wild (const char *pattern, const char *str)
   2935 {
   2936   size_t  plen, slen;
   2937 
   2938   /* wildcard at start */
   2939   if (pattern[0] == '*')
   2940     {
   2941       pattern++;
   2942       plen = strlen (pattern);
   2943       slen = strlen (str);
   2944       return (plen == 0
   2945 	      || (slen >= plen && memcmp (pattern, str+slen-plen, plen) == 0));
   2946     }
   2947 
   2948   /* wildcard at end */
   2949   plen = strlen (pattern);
   2950   if (plen >= 1 && pattern[plen-1] == '*')
   2951     return (memcmp (pattern, str, plen-1) == 0);
   2952 
   2953   /* no wildcards */
   2954   return (strcmp (pattern, str) == 0);
   2955 }
   2956 
   2957 void
   2958 try_name (const char *name)
   2959 {
   2960   int  found = 0;
   2961   int  i;
   2962 
   2963   for (i = 0; i < numberof (choice_array); i++)
   2964     {
   2965       if (strmatch_wild (name, choice_array[i].name))
   2966 	{
   2967 	  choice = &choice_array[i];
   2968 	  tr = &param[choice->type];
   2969 	  try_many ();
   2970 	  found = 1;
   2971 	}
   2972     }
   2973 
   2974   if (!found)
   2975     {
   2976       printf ("%s unknown\n", name);
   2977       /* exit (1); */
   2978     }
   2979 }
   2980 
   2981 
   2982 void
   2983 usage (const char *prog)
   2984 {
   2985   int  col = 0;
   2986   int  i;
   2987 
   2988   printf ("Usage: %s [options] function...\n", prog);
   2989   printf ("    -1        use limb data 1,2,3,etc\n");
   2990   printf ("    -9        use limb data all 0xFF..FFs\n");
   2991   printf ("    -a zeros  use limb data all zeros\n");
   2992   printf ("    -a ffs    use limb data all 0xFF..FFs (same as -9)\n");
   2993   printf ("    -a 2fd    use data 0x2FFF...FFFD\n");
   2994   printf ("    -p        print each case tried (try this if seg faulting)\n");
   2995   printf ("    -R        seed random numbers from time()\n");
   2996   printf ("    -r reps   set repetitions (default %d)\n", DEFAULT_REPETITIONS);
   2997   printf ("    -s size   starting size to test\n");
   2998   printf ("    -S size2  starting size2 to test\n");
   2999   printf ("    -s s1-s2  range of sizes to test\n");
   3000   printf ("    -W        don't show the spinner (use this in gdb)\n");
   3001   printf ("    -z        disable mprotect() redzones\n");
   3002   printf ("Default data is refmpn_random() and refmpn_random2().\n");
   3003   printf ("\n");
   3004   printf ("Functions that can be tested:\n");
   3005 
   3006   for (i = 0; i < numberof (choice_array); i++)
   3007     {
   3008       if (col + 1 + strlen (choice_array[i].name) > 79)
   3009 	{
   3010 	  printf ("\n");
   3011 	  col = 0;
   3012 	}
   3013       printf (" %s", choice_array[i].name);
   3014       col += 1 + strlen (choice_array[i].name);
   3015     }
   3016   printf ("\n");
   3017 
   3018   exit(1);
   3019 }
   3020 
   3021 
   3022 int
   3023 main (int argc, char *argv[])
   3024 {
   3025   int  i;
   3026 
   3027   /* unbuffered output */
   3028   setbuf (stdout, NULL);
   3029   setbuf (stderr, NULL);
   3030 
   3031   /* default trace in hex, and in upper-case so can paste into bc */
   3032   mp_trace_base = -16;
   3033 
   3034   param_init ();
   3035 
   3036   {
   3037     unsigned long  seed = 123;
   3038     int   opt;
   3039 
   3040     while ((opt = getopt(argc, argv, "19a:b:E:pRr:S:s:Wz")) != EOF)
   3041       {
   3042 	switch (opt) {
   3043 	case '1':
   3044 	  /* use limb data values 1, 2, 3, ... etc */
   3045 	  option_data = DATA_SEQ;
   3046 	  break;
   3047 	case '9':
   3048 	  /* use limb data values 0xFFF...FFF always */
   3049 	  option_data = DATA_FFS;
   3050 	  break;
   3051 	case 'a':
   3052 	  if (strcmp (optarg, "zeros") == 0)     option_data = DATA_ZEROS;
   3053 	  else if (strcmp (optarg, "seq") == 0)  option_data = DATA_SEQ;
   3054 	  else if (strcmp (optarg, "ffs") == 0)  option_data = DATA_FFS;
   3055 	  else if (strcmp (optarg, "2fd") == 0)  option_data = DATA_2FD;
   3056 	  else
   3057 	    {
   3058 	      fprintf (stderr, "unrecognised data option: %s\n", optarg);
   3059 	      exit (1);
   3060 	    }
   3061 	  break;
   3062 	case 'b':
   3063 	  mp_trace_base = atoi (optarg);
   3064 	  break;
   3065 	case 'E':
   3066 	  /* re-seed */
   3067 	  sscanf (optarg, "%lu", &seed);
   3068 	  printf ("Re-seeding with %lu\n", seed);
   3069 	  break;
   3070 	case 'p':
   3071 	  option_print = 1;
   3072 	  break;
   3073 	case 'R':
   3074 	  /* randomize */
   3075 	  seed = time (NULL);
   3076 	  printf ("Seeding with %lu, re-run using \"-E %lu\"\n", seed, seed);
   3077 	  break;
   3078 	case 'r':
   3079 	  option_repetitions = atoi (optarg);
   3080 	  break;
   3081 	case 's':
   3082 	  {
   3083 	    char  *p;
   3084 	    option_firstsize = strtol (optarg, 0, 0);
   3085 	    if ((p = strchr (optarg, '-')) != NULL)
   3086 	      option_lastsize = strtol (p+1, 0, 0);
   3087 	  }
   3088 	  break;
   3089 	case 'S':
   3090 	  /* -S <size> sets the starting size for the second of a two size
   3091 	     routine (like mpn_mul_basecase) */
   3092 	  option_firstsize2 = strtol (optarg, 0, 0);
   3093 	  break;
   3094 	case 'W':
   3095 	  /* use this when running in the debugger */
   3096 	  option_spinner = 0;
   3097 	  break;
   3098 	case 'z':
   3099 	  /* disable redzones */
   3100 	  option_redzones = 0;
   3101 	  break;
   3102 	case '?':
   3103 	  usage (argv[0]);
   3104 	  break;
   3105 	}
   3106       }
   3107 
   3108     gmp_randinit_default (__gmp_rands);
   3109     __gmp_rands_initialized = 1;
   3110     gmp_randseed_ui (__gmp_rands, seed);
   3111   }
   3112 
   3113   try_init();
   3114 
   3115   if (argc <= optind)
   3116     usage (argv[0]);
   3117 
   3118   for (i = optind; i < argc; i++)
   3119     try_name (argv[i]);
   3120 
   3121   return 0;
   3122 }
   3123