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