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