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