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