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