~ubuntu-branches/ubuntu/intrepid/ecl/intrepid

« back to all changes in this revision

Viewing changes to src/gmp/tests/devel/try.c

  • Committer: Bazaar Package Importer
  • Author(s): Peter Van Eynde
  • Date: 2006-05-17 02:46:26 UTC
  • Revision ID: james.westby@ubuntu.com-20060517024626-lljr08ftv9g9vefl
Tags: upstream-0.9h-20060510
ImportĀ upstreamĀ versionĀ 0.9h-20060510

Show diffs side-by-side

added added

removed removed

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