[BACK]Return to try.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp / tests / devel

Annotation of OpenXM_contrib/gmp/tests/devel/try.c, Revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>