diff --git a/.gitattributes b/.gitattributes index 5cb0f7baf1bc6167712307b9f68d40c9566937e7..85087c8e0fe5c13b5551e69e24c641fd9c5c1ee1 100644 --- a/.gitattributes +++ b/.gitattributes @@ -10,6 +10,9 @@ /bench/encoding/ export-ignore /examples/in_progress/ export-ignore +/examples/multiprecision/random/ export-ignore +/examples/multiprecision/bench-include/ export-ignore +/examples/multiprecision/mini-gmp/ export-ignore /misc/ export-ignore /opam/ export-ignore /tests/ export-ignore diff --git a/bench/bench b/bench/bench index 3e9fcb91d77423c238cfe8a0cc4710703b9211a1..503fdc7d5b35301eb1eeed40930c08a49530ede1 100755 --- a/bench/bench +++ b/bench/bench @@ -182,7 +182,7 @@ extract_and_run () { } extract_and_test_wmp () { - dir="examples/in_progress/multiprecision" + dir=$1 shift printf " $dir... " printf "clean... " @@ -346,7 +346,8 @@ extract_and_run examples/sudoku sudoku.ml 2,0,9,0,0,0,0,1,0,0,0,0,0,6,0,0,0,0,0, echo "" echo "=== Checking extraction to C ===" -extract_and_test_wmp +extract_and_test_wmp examples/in_progress/multiprecision +extract_and_test_wmp examples/multiprecision echo "" echo "=== Checking --list-* ===" diff --git a/drivers/c.drv b/drivers/c.drv index ed621ace14bb531b0d0dde3046b31b9c396a2d28..1c18780597bdb2b060a49660db44ff62f1857e9c 100644 --- a/drivers/c.drv +++ b/drivers/c.drv @@ -3,6 +3,7 @@ printer "c" prelude "#include <stdlib.h>" prelude "#include <stdint.h>" prelude "#include <stdio.h>" +prelude "#include <assert.h>" module ref.Ref @@ -141,6 +142,44 @@ struct __lsld32_result lsld32(uint32_t x, uint32_t cnt) result.__field_1 = (uint32_t)(r >> 32); return result; } +" + + interface +" +struct __add32_with_carry_result +{ uint32_t __field_0; + uint32_t __field_1; +}; + +struct __add32_with_carry_result add32_with_carry(uint32_t x, uint32_t y, uint32_t c); + +struct __sub32_with_borrow_result +{ uint32_t __field_0; + uint32_t __field_1; +}; + +struct __sub32_with_borrow_result sub32_with_borrow(uint32_t x, uint32_t y, uint32_t b); + +struct __mul32_double_result +{ uint32_t __field_0; + uint32_t __field_1; +}; + +struct __mul32_double_result mul32_double(uint32_t x, uint32_t y); + +struct __add32_3_result +{ uint32_t __field_0; + uint32_t __field_1; +}; + +struct __add32_3_result add32_3(uint32_t x, uint32_t y, uint32_t z); + +struct __lsld32_result +{ uint32_t __field_0; + uint32_t __field_1; +}; + +struct __lsld32_result lsld32(uint32_t x, uint32_t cnt); " syntax converter of_int "%1U" @@ -213,7 +252,6 @@ module mach.int.UInt64GMP prelude " -#include \"config.h\" #include \"gmp.h\" #include \"gmp-impl.h\" #include \"longlong.h\" @@ -225,7 +263,7 @@ struct __add64_with_carry_result uint64_t __field_1; }; -struct __add64_with_carry_result +struct __add64_with_carry_result add64_with_carry(uint64_t x, uint64_t y, uint64_t c) { struct __add64_with_carry_result result; @@ -241,7 +279,7 @@ struct __add64_double_result uint64_t __field_1; }; -struct __add64_double_result +struct __add64_double_result add64_double(uint64_t a1, uint64_t a0, uint64_t b1, uint64_t b0) { struct __add64_double_result result; @@ -254,7 +292,7 @@ struct __sub64_with_borrow_result uint64_t __field_1; }; -struct __sub64_with_borrow_result +struct __sub64_with_borrow_result sub64_with_borrow(uint64_t x, uint64_t y, uint64_t b) { struct __sub64_with_borrow_result result; @@ -271,7 +309,7 @@ struct __sub64_double_result uint64_t __field_1; }; -struct __sub64_double_result +struct __sub64_double_result sub64_double(uint64_t a1, uint64_t a0, uint64_t b1, uint64_t b0) { struct __sub64_double_result result; @@ -331,6 +369,69 @@ struct __lsld64_result lsld64(uint64_t x, uint64_t cnt) } " + interface +" +#include \"gmp.h\" +#include \"gmp-impl.h\" +#include \"longlong.h\" + +#undef invert_limb + +struct __add64_with_carry_result +{ uint64_t __field_0; + uint64_t __field_1; +}; + +struct __add64_with_carry_result +add64_with_carry(uint64_t x, uint64_t y, uint64_t c); + +struct __add64_double_result +{ uint64_t __field_0; + uint64_t __field_1; +}; + +struct __add64_double_result +add64_double(uint64_t a1, uint64_t a0, uint64_t b1, uint64_t b0); + +struct __sub64_with_borrow_result +{ uint64_t __field_0; + uint64_t __field_1; +}; + +struct __sub64_with_borrow_result +sub64_with_borrow(uint64_t x, uint64_t y, uint64_t b); + +struct __sub64_double_result +{ uint64_t __field_0; + uint64_t __field_1; +}; + +struct __sub64_double_result +sub64_double(uint64_t a1, uint64_t a0, uint64_t b1, uint64_t b0); + +struct __mul64_double_result +{ uint64_t __field_0; + uint64_t __field_1; +}; + +struct __mul64_double_result mul64_double(uint64_t x, uint64_t y); + +uint64_t div64_2by1(uint64_t ul, uint64_t uh, uint64_t d); + +struct __add64_3_result +{ uint64_t __field_0; + uint64_t __field_1; +}; + +struct __add64_3_result add64_3(uint64_t x, uint64_t y, uint64_t z); + +struct __lsld64_result +{ uint64_t __field_0; + uint64_t __field_1; +}; + +struct __lsld64_result lsld64(uint64_t x, uint64_t cnt); +" syntax converter of_int "%1ULL" syntax val (+) "%1 + %2" diff --git a/examples/multiprecision/.gitignore b/examples/multiprecision/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..a3185c67ba43ec3dc8d5acdf316f252228833df5 --- /dev/null +++ b/examples/multiprecision/.gitignore @@ -0,0 +1,2 @@ +bench/ +build/ \ No newline at end of file diff --git a/examples/multiprecision/Makefile b/examples/multiprecision/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..ef9886c894aeeb8cf1719f417f4dbfe848820ddf --- /dev/null +++ b/examples/multiprecision/Makefile @@ -0,0 +1,73 @@ +BENCH ?= no + +ifeq ($(BENCH),yes) + WHY3=../../bin/why3.opt +else + ifeq ($(BINDIR),) + WHY3=why3 + else + WHY3=$(BINDIR)/why3 + endif +endif + +all: why3 extract + +clean: + rm -rf build + +why3: + make -C ../.. + +dir: + mkdir -p build + +cfiles: why3 dir + $(WHY3) extract -D c -L . --recursive --modular --interface -o build/ wmpn.mlw + +extract: why3 dir cfiles + +CFILES = build/uint64gmp.c build/div.c build/logical.c build/mul.c build/sub.c build/add.c build/compare.c build/util.c build/int32.c + +tests: extract check-gmp + gcc -O2 -Wall -Wno-unused-function -g -std=gnu99 tests.c $(CFILES) -I$(GMP_DIR) -Irandom -L$(GMP_LIB) -fomit-frame-pointer -mtune=haswell -march=haswell -fno-tree-vectorize -lgmp -o build/tests + gcc -O2 -Wall -Wno-unused-function -g -std=gnu99 -DCOMPARE_MINI tests.c $(CFILES) -I$(GMP_DIR) -Irandom -Imini-gmp -fomit-frame-pointer -mtune=haswell -march=haswell -fno-tree-vectorize -o build/minitests + ./build/tests + ./build/minitests + +bench-tests: extract + gcc -O2 -Wall -g -std=gnu99 tests.c $(CFILES) -Ibench-include -Irandom -fomit-frame-pointer -fno-tree-vectorize -lgmp -o build/bench-tests + + +build/why3%bench: extract check-gmp + gcc -O3 -Wall -g -std=gnu99 -DTEST_WHY3 -DTEST_`echo $* | tr [:lower:] [:upper:]` tests.c $(CFILES) -I$(GMP_DIR) -L$(GMP_LIB) -fomit-frame-pointer -mtune=haswell -march=haswell -fno-tree-vectorize -lgmp -o $@ + +build/gmp%bench: extract check-gmp + gcc -O3 -Wall -g -std=gnu99 -DTEST_GMP -DTEST_`echo $* | tr [:lower:] [:upper:]` tests.c $(CFILES) -I$(GMP_DIR) -L$(GMP_LIB) -fomit-frame-pointer -mtune=haswell -march=haswell -fno-tree-vectorize -lgmp -o $@ + +build/minigmp%bench: extract + gcc -O3 -Wall -g -std=gnu99 -DTEST_MINIGMP -DTEST_`echo $* | tr [:lower:] [:upper:]` tests.c $(CFILES) -I$(GMP_DIR) -fomit-frame-pointer -mtune=haswell -march=haswell -fno-tree-vectorize -o $@ + +alltests: tests build/why3addbench build/why3mulbench build/why3divbench build/gmpaddbench build/gmpmulbench build/gmpdivbench build/minigmpaddbench build/minigmpmulbench build/minigmpdivbench + +data: alltests + mkdir -p bench + ./build/why3addbench > bench/why3add + ./build/why3mulbench > bench/why3mul + ./build/why3divbench > bench/why3div + ./build/gmpaddbench > bench/gmpadd + ./build/gmpmulbench > bench/gmpmul + ./build/gmpdivbench > bench/gmpdiv + ./build/minigmpaddbench > bench/minigmpadd + ./build/minigmpmulbench > bench/minigmpmul + ./build/minigmpdivbench > bench/minigmpdiv + +plots: data + make all -C plots + +check-gmp: +ifndef GMP_DIR + $(error GMP_DIR is undefined) +endif +ifndef GMP_LIB + $(error GMP_LIB is undefined) +endif diff --git a/examples/multiprecision/bench-include/config.h b/examples/multiprecision/bench-include/config.h new file mode 100644 index 0000000000000000000000000000000000000000..dccc114f6ec9d50ab9cddf56e347fd08bf31904c --- /dev/null +++ b/examples/multiprecision/bench-include/config.h @@ -0,0 +1,642 @@ +/* config.h. Generated from config.in by configure. */ +/* config.in. Generated from configure.ac by autoheader. */ + +/* + +Copyright 1996-2016 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + +or + + * the GNU General Public License as published by the Free Software + Foundation; either version 2 of the License, or (at your option) any + later version. + +or both in parallel, as here. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received copies of the GNU General Public License and the +GNU Lesser General Public License along with the GNU MP Library. If not, +see https://www.gnu.org/licenses/. +*/ + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* The gmp-mparam.h file (a string) the tune program should suggest updating. + */ +#define GMP_MPARAM_H_SUGGEST "./mpn/generic/gmp-mparam.h" + +/* Define to 1 if you have the `alarm' function. */ +#define HAVE_ALARM 1 + +/* Define to 1 if alloca() works (via gmp-impl.h). */ +#define HAVE_ALLOCA 1 + +/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix). + */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if the compiler accepts gcc style __attribute__ ((const)) */ +#define HAVE_ATTRIBUTE_CONST 1 + +/* Define to 1 if the compiler accepts gcc style __attribute__ ((malloc)) */ +#define HAVE_ATTRIBUTE_MALLOC 1 + +/* Define to 1 if the compiler accepts gcc style __attribute__ ((mode (XX))) + */ +#define HAVE_ATTRIBUTE_MODE 1 + +/* Define to 1 if the compiler accepts gcc style __attribute__ ((noreturn)) */ +#define HAVE_ATTRIBUTE_NORETURN 1 + +/* Define to 1 if you have the `attr_get' function. */ +/* #undef HAVE_ATTR_GET */ + +/* Define to 1 if tests/libtests has calling conventions checking for the CPU + */ +/* #undef HAVE_CALLING_CONVENTIONS */ + +/* Define to 1 if you have the `clock' function. */ +#define HAVE_CLOCK 1 + +/* Define to 1 if you have the `clock_gettime' function */ +#define HAVE_CLOCK_GETTIME 1 + +/* Define to 1 if you have the `cputime' function. */ +/* #undef HAVE_CPUTIME */ + +/* Define to 1 if you have the declaration of `fgetc', and to 0 if you don't. + */ +#define HAVE_DECL_FGETC 1 + +/* Define to 1 if you have the declaration of `fscanf', and to 0 if you don't. + */ +#define HAVE_DECL_FSCANF 1 + +/* Define to 1 if you have the declaration of `optarg', and to 0 if you don't. + */ +#define HAVE_DECL_OPTARG 1 + +/* Define to 1 if you have the declaration of `sys_errlist', and to 0 if you + don't. */ +#define HAVE_DECL_SYS_ERRLIST 1 + +/* Define to 1 if you have the declaration of `sys_nerr', and to 0 if you + don't. */ +#define HAVE_DECL_SYS_NERR 1 + +/* Define to 1 if you have the declaration of `ungetc', and to 0 if you don't. + */ +#define HAVE_DECL_UNGETC 1 + +/* Define to 1 if you have the declaration of `vfprintf', and to 0 if you + don't. */ +#define HAVE_DECL_VFPRINTF 1 + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#define HAVE_DLFCN_H 1 + +/* Define one of the following to 1 for the format of a `double'. + If your format is not among these choices, or you don't know what it is, + then leave all undefined. + IEEE_LITTLE_SWAPPED means little endian, but with the two 4-byte halves + swapped, as used by ARM CPUs in little endian mode. */ +/* #undef HAVE_DOUBLE_IEEE_BIG_ENDIAN */ +#define HAVE_DOUBLE_IEEE_LITTLE_ENDIAN 1 +/* #undef HAVE_DOUBLE_IEEE_LITTLE_SWAPPED */ +/* #undef HAVE_DOUBLE_VAX_D */ +/* #undef HAVE_DOUBLE_VAX_G */ +/* #undef HAVE_DOUBLE_CRAY_CFP */ + +/* Define to 1 if you have the <fcntl.h> header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the <float.h> header file. */ +#define HAVE_FLOAT_H 1 + +/* Define to 1 if you have the `getpagesize' function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define to 1 if you have the `getrusage' function. */ +#define HAVE_GETRUSAGE 1 + +/* Define to 1 if you have the `getsysinfo' function. */ +/* #undef HAVE_GETSYSINFO */ + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if the compiler accepts gcc style __attribute__ ((visibility)) + and __attribute__ ((alias)) */ +#define HAVE_HIDDEN_ALIAS 1 + +/* Define one of these to 1 for the host CPU family. + If your CPU is not in any of these families, leave all undefined. + For an AMD64 chip, define "x86" in ABI=32, but not in ABI=64. */ +/* #undef HAVE_HOST_CPU_FAMILY_alpha */ +/* #undef HAVE_HOST_CPU_FAMILY_m68k */ +/* #undef HAVE_HOST_CPU_FAMILY_power */ +/* #undef HAVE_HOST_CPU_FAMILY_powerpc */ +/* #undef HAVE_HOST_CPU_FAMILY_x86 */ +#define HAVE_HOST_CPU_FAMILY_x86_64 1 + +/* Define one of the following to 1 for the host CPU, as per the output of + ./config.guess. If your CPU is not listed here, leave all undefined. */ +/* #undef HAVE_HOST_CPU_alphaev67 */ +/* #undef HAVE_HOST_CPU_alphaev68 */ +/* #undef HAVE_HOST_CPU_alphaev7 */ +/* #undef HAVE_HOST_CPU_m68020 */ +/* #undef HAVE_HOST_CPU_m68030 */ +/* #undef HAVE_HOST_CPU_m68040 */ +/* #undef HAVE_HOST_CPU_m68060 */ +/* #undef HAVE_HOST_CPU_m68360 */ +/* #undef HAVE_HOST_CPU_powerpc604 */ +/* #undef HAVE_HOST_CPU_powerpc604e */ +/* #undef HAVE_HOST_CPU_powerpc750 */ +/* #undef HAVE_HOST_CPU_powerpc7400 */ +/* #undef HAVE_HOST_CPU_supersparc */ +/* #undef HAVE_HOST_CPU_i386 */ +/* #undef HAVE_HOST_CPU_i586 */ +/* #undef HAVE_HOST_CPU_i686 */ +/* #undef HAVE_HOST_CPU_pentium */ +/* #undef HAVE_HOST_CPU_pentiummmx */ +/* #undef HAVE_HOST_CPU_pentiumpro */ +/* #undef HAVE_HOST_CPU_pentium2 */ +/* #undef HAVE_HOST_CPU_pentium3 */ +/* #undef HAVE_HOST_CPU_s390_z900 */ +/* #undef HAVE_HOST_CPU_s390_z990 */ +/* #undef HAVE_HOST_CPU_s390_z9 */ +/* #undef HAVE_HOST_CPU_s390_z10 */ +/* #undef HAVE_HOST_CPU_s390_z196 */ + +/* Define to 1 iff we have a s390 with 64-bit registers. */ +/* #undef HAVE_HOST_CPU_s390_zarch */ + +/* Define to 1 if the system has the type `intmax_t'. */ +#define HAVE_INTMAX_T 1 + +/* Define to 1 if the system has the type `intptr_t'. */ +#define HAVE_INTPTR_T 1 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the <invent.h> header file. */ +/* #undef HAVE_INVENT_H */ + +/* Define to 1 if you have the <langinfo.h> header file. */ +#define HAVE_LANGINFO_H 1 + +/* Define one of these to 1 for the endianness of `mp_limb_t'. + If the endianness is not a simple big or little, or you don't know what + it is, then leave both undefined. */ +/* #undef HAVE_LIMB_BIG_ENDIAN */ +#define HAVE_LIMB_LITTLE_ENDIAN 1 + +/* Define to 1 if you have the `localeconv' function. */ +#define HAVE_LOCALECONV 1 + +/* Define to 1 if you have the <locale.h> header file. */ +#define HAVE_LOCALE_H 1 + +/* Define to 1 if the system has the type `long double'. */ +#define HAVE_LONG_DOUBLE 1 + +/* Define to 1 if the system has the type `long long'. */ +#define HAVE_LONG_LONG 1 + +/* Define to 1 if you have the <machine/hal_sysinfo.h> header file. */ +/* #undef HAVE_MACHINE_HAL_SYSINFO_H */ + +/* Define to 1 if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `memset' function. */ +#define HAVE_MEMSET 1 + +/* Define to 1 if you have the `mmap' function. */ +#define HAVE_MMAP 1 + +/* Define to 1 if you have the `mprotect' function. */ +#define HAVE_MPROTECT 1 + +/* Define to 1 each of the following for which a native (ie. CPU specific) + implementation of the corresponding routine exists. */ +/* #undef HAVE_NATIVE_mpn_add_n */ +/* #undef HAVE_NATIVE_mpn_add_n_sub_n */ +/* #undef HAVE_NATIVE_mpn_add_nc */ +/* #undef HAVE_NATIVE_mpn_addaddmul_1msb0 */ +/* #undef HAVE_NATIVE_mpn_addlsh1_n */ +/* #undef HAVE_NATIVE_mpn_addlsh2_n */ +/* #undef HAVE_NATIVE_mpn_addlsh_n */ +/* #undef HAVE_NATIVE_mpn_addlsh1_nc */ +/* #undef HAVE_NATIVE_mpn_addlsh2_nc */ +/* #undef HAVE_NATIVE_mpn_addlsh_nc */ +/* #undef HAVE_NATIVE_mpn_addlsh1_n_ip1 */ +/* #undef HAVE_NATIVE_mpn_addlsh2_n_ip1 */ +/* #undef HAVE_NATIVE_mpn_addlsh_n_ip1 */ +/* #undef HAVE_NATIVE_mpn_addlsh1_nc_ip1 */ +/* #undef HAVE_NATIVE_mpn_addlsh2_nc_ip1 */ +/* #undef HAVE_NATIVE_mpn_addlsh_nc_ip1 */ +/* #undef HAVE_NATIVE_mpn_addlsh1_n_ip2 */ +/* #undef HAVE_NATIVE_mpn_addlsh2_n_ip2 */ +/* #undef HAVE_NATIVE_mpn_addlsh_n_ip2 */ +/* #undef HAVE_NATIVE_mpn_addlsh1_nc_ip2 */ +/* #undef HAVE_NATIVE_mpn_addlsh2_nc_ip2 */ +/* #undef HAVE_NATIVE_mpn_addlsh_nc_ip2 */ +/* #undef HAVE_NATIVE_mpn_addmul_1c */ +/* #undef HAVE_NATIVE_mpn_addmul_2 */ +/* #undef HAVE_NATIVE_mpn_addmul_3 */ +/* #undef HAVE_NATIVE_mpn_addmul_4 */ +/* #undef HAVE_NATIVE_mpn_addmul_5 */ +/* #undef HAVE_NATIVE_mpn_addmul_6 */ +/* #undef HAVE_NATIVE_mpn_addmul_7 */ +/* #undef HAVE_NATIVE_mpn_addmul_8 */ +/* #undef HAVE_NATIVE_mpn_addmul_2s */ +/* #undef HAVE_NATIVE_mpn_and_n */ +/* #undef HAVE_NATIVE_mpn_andn_n */ +/* #undef HAVE_NATIVE_mpn_bdiv_dbm1c */ +/* #undef HAVE_NATIVE_mpn_bdiv_q_1 */ +/* #undef HAVE_NATIVE_mpn_pi1_bdiv_q_1 */ +/* #undef HAVE_NATIVE_mpn_cnd_add_n */ +/* #undef HAVE_NATIVE_mpn_cnd_sub_n */ +/* #undef HAVE_NATIVE_mpn_com */ +/* #undef HAVE_NATIVE_mpn_copyd */ +/* #undef HAVE_NATIVE_mpn_copyi */ +/* #undef HAVE_NATIVE_mpn_div_qr_1n_pi1 */ +/* #undef HAVE_NATIVE_mpn_div_qr_2 */ +/* #undef HAVE_NATIVE_mpn_divexact_1 */ +/* #undef HAVE_NATIVE_mpn_divexact_by3c */ +/* #undef HAVE_NATIVE_mpn_divrem_1 */ +/* #undef HAVE_NATIVE_mpn_divrem_1c */ +/* #undef HAVE_NATIVE_mpn_divrem_2 */ +/* #undef HAVE_NATIVE_mpn_gcd_1 */ +/* #undef HAVE_NATIVE_mpn_hamdist */ +/* #undef HAVE_NATIVE_mpn_invert_limb */ +/* #undef HAVE_NATIVE_mpn_ior_n */ +/* #undef HAVE_NATIVE_mpn_iorn_n */ +/* #undef HAVE_NATIVE_mpn_lshift */ +/* #undef HAVE_NATIVE_mpn_lshiftc */ +/* #undef HAVE_NATIVE_mpn_lshsub_n */ +/* #undef HAVE_NATIVE_mpn_mod_1 */ +/* #undef HAVE_NATIVE_mpn_mod_1_1p */ +/* #undef HAVE_NATIVE_mpn_mod_1c */ +/* #undef HAVE_NATIVE_mpn_mod_1s_2p */ +/* #undef HAVE_NATIVE_mpn_mod_1s_4p */ +/* #undef HAVE_NATIVE_mpn_mod_34lsub1 */ +/* #undef HAVE_NATIVE_mpn_modexact_1_odd */ +/* #undef HAVE_NATIVE_mpn_modexact_1c_odd */ +/* #undef HAVE_NATIVE_mpn_mul_1 */ +/* #undef HAVE_NATIVE_mpn_mul_1c */ +/* #undef HAVE_NATIVE_mpn_mul_2 */ +/* #undef HAVE_NATIVE_mpn_mul_3 */ +/* #undef HAVE_NATIVE_mpn_mul_4 */ +/* #undef HAVE_NATIVE_mpn_mul_5 */ +/* #undef HAVE_NATIVE_mpn_mul_6 */ +/* #undef HAVE_NATIVE_mpn_mul_basecase */ +/* #undef HAVE_NATIVE_mpn_mullo_basecase */ +/* #undef HAVE_NATIVE_mpn_nand_n */ +/* #undef HAVE_NATIVE_mpn_nior_n */ +/* #undef HAVE_NATIVE_mpn_popcount */ +/* #undef HAVE_NATIVE_mpn_preinv_divrem_1 */ +/* #undef HAVE_NATIVE_mpn_preinv_mod_1 */ +/* #undef HAVE_NATIVE_mpn_redc_1 */ +/* #undef HAVE_NATIVE_mpn_redc_2 */ +/* #undef HAVE_NATIVE_mpn_rsblsh1_n */ +/* #undef HAVE_NATIVE_mpn_rsblsh2_n */ +/* #undef HAVE_NATIVE_mpn_rsblsh_n */ +/* #undef HAVE_NATIVE_mpn_rsblsh1_nc */ +/* #undef HAVE_NATIVE_mpn_rsblsh2_nc */ +/* #undef HAVE_NATIVE_mpn_rsblsh_nc */ +/* #undef HAVE_NATIVE_mpn_rsh1add_n */ +/* #undef HAVE_NATIVE_mpn_rsh1add_nc */ +/* #undef HAVE_NATIVE_mpn_rsh1sub_n */ +/* #undef HAVE_NATIVE_mpn_rsh1sub_nc */ +/* #undef HAVE_NATIVE_mpn_rshift */ +/* #undef HAVE_NATIVE_mpn_sqr_basecase */ +/* #undef HAVE_NATIVE_mpn_sqr_diagonal */ +/* #undef HAVE_NATIVE_mpn_sqr_diag_addlsh1 */ +/* #undef HAVE_NATIVE_mpn_sub_n */ +/* #undef HAVE_NATIVE_mpn_sub_nc */ +/* #undef HAVE_NATIVE_mpn_sublsh1_n */ +/* #undef HAVE_NATIVE_mpn_sublsh2_n */ +/* #undef HAVE_NATIVE_mpn_sublsh_n */ +/* #undef HAVE_NATIVE_mpn_sublsh1_nc */ +/* #undef HAVE_NATIVE_mpn_sublsh2_nc */ +/* #undef HAVE_NATIVE_mpn_sublsh_nc */ +/* #undef HAVE_NATIVE_mpn_sublsh1_n_ip1 */ +/* #undef HAVE_NATIVE_mpn_sublsh2_n_ip1 */ +/* #undef HAVE_NATIVE_mpn_sublsh_n_ip1 */ +/* #undef HAVE_NATIVE_mpn_sublsh1_nc_ip1 */ +/* #undef HAVE_NATIVE_mpn_sublsh2_nc_ip1 */ +/* #undef HAVE_NATIVE_mpn_sublsh_nc_ip1 */ +/* #undef HAVE_NATIVE_mpn_submul_1c */ +/* #undef HAVE_NATIVE_mpn_tabselect */ +/* #undef HAVE_NATIVE_mpn_udiv_qrnnd */ +/* #undef HAVE_NATIVE_mpn_udiv_qrnnd_r */ +/* #undef HAVE_NATIVE_mpn_umul_ppmm */ +/* #undef HAVE_NATIVE_mpn_umul_ppmm_r */ +/* #undef HAVE_NATIVE_mpn_xor_n */ +/* #undef HAVE_NATIVE_mpn_xnor_n */ + +/* Define to 1 if you have the `nl_langinfo' function. */ +#define HAVE_NL_LANGINFO 1 + +/* Define to 1 if you have the <nl_types.h> header file. */ +#define HAVE_NL_TYPES_H 1 + +/* Define to 1 if you have the `obstack_vprintf' function. */ +#define HAVE_OBSTACK_VPRINTF 1 + +/* Define to 1 if you have the `popen' function. */ +#define HAVE_POPEN 1 + +/* Define to 1 if you have the `processor_info' function. */ +/* #undef HAVE_PROCESSOR_INFO */ + +/* Define to 1 if <sys/pstat.h> `struct pst_processor' exists and contains + `psp_iticksperclktick'. */ +/* #undef HAVE_PSP_ITICKSPERCLKTICK */ + +/* Define to 1 if you have the `pstat_getprocessor' function. */ +/* #undef HAVE_PSTAT_GETPROCESSOR */ + +/* Define to 1 if the system has the type `ptrdiff_t'. */ +#define HAVE_PTRDIFF_T 1 + +/* Define to 1 if the system has the type `quad_t'. */ +#define HAVE_QUAD_T 1 + +/* Define to 1 if you have the `raise' function. */ +#define HAVE_RAISE 1 + +/* Define to 1 if you have the `read_real_time' function. */ +/* #undef HAVE_READ_REAL_TIME */ + +/* Define to 1 if you have the `sigaction' function. */ +#define HAVE_SIGACTION 1 + +/* Define to 1 if you have the `sigaltstack' function. */ +#define HAVE_SIGALTSTACK 1 + +/* Define to 1 if you have the `sigstack' function. */ +#define HAVE_SIGSTACK 1 + +/* Tune directory speed_cyclecounter, undef=none, 1=32bits, 2=64bits) */ +#define HAVE_SPEED_CYCLECOUNTER 2 + +/* Define to 1 if you have the <sstream> header file. */ +/* #undef HAVE_SSTREAM */ + +/* Define to 1 if the system has the type `stack_t'. */ +#define HAVE_STACK_T 1 + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if the system has the type `std::locale'. */ +/* #undef HAVE_STD__LOCALE */ + +/* Define to 1 if you have the `strchr' function. */ +#define HAVE_STRCHR 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strnlen' function. */ +#define HAVE_STRNLEN 1 + +/* Define to 1 if you have the `strtol' function. */ +#define HAVE_STRTOL 1 + +/* Define to 1 if you have the `strtoul' function. */ +#define HAVE_STRTOUL 1 + +/* Define to 1 if you have the `sysconf' function. */ +#define HAVE_SYSCONF 1 + +/* Define to 1 if you have the `sysctl' function. */ +#define HAVE_SYSCTL 1 + +/* Define to 1 if you have the `sysctlbyname' function. */ +/* #undef HAVE_SYSCTLBYNAME */ + +/* Define to 1 if you have the `syssgi' function. */ +/* #undef HAVE_SYSSGI */ + +/* Define to 1 if you have the <sys/attributes.h> header file. */ +/* #undef HAVE_SYS_ATTRIBUTES_H */ + +/* Define to 1 if you have the <sys/iograph.h> header file. */ +/* #undef HAVE_SYS_IOGRAPH_H */ + +/* Define to 1 if you have the <sys/mman.h> header file. */ +#define HAVE_SYS_MMAN_H 1 + +/* Define to 1 if you have the <sys/param.h> header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the <sys/processor.h> header file. */ +/* #undef HAVE_SYS_PROCESSOR_H */ + +/* Define to 1 if you have the <sys/pstat.h> header file. */ +/* #undef HAVE_SYS_PSTAT_H */ + +/* Define to 1 if you have the <sys/resource.h> header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/sysctl.h> header file. */ +#define HAVE_SYS_SYSCTL_H 1 + +/* Define to 1 if you have the <sys/sysinfo.h> header file. */ +#define HAVE_SYS_SYSINFO_H 1 + +/* Define to 1 if you have the <sys/syssgi.h> header file. */ +/* #undef HAVE_SYS_SYSSGI_H */ + +/* Define to 1 if you have the <sys/systemcfg.h> header file. */ +/* #undef HAVE_SYS_SYSTEMCFG_H */ + +/* Define to 1 if you have the <sys/times.h> header file. */ +#define HAVE_SYS_TIMES_H 1 + +/* Define to 1 if you have the <sys/time.h> header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the `times' function. */ +#define HAVE_TIMES 1 + +/* Define to 1 if the system has the type `uint_least32_t'. */ +#define HAVE_UINT_LEAST32_T 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `vsnprintf' function and it works properly. */ +#define HAVE_VSNPRINTF 1 + +/* Define to 1 for Windos/64 */ +/* #undef HOST_DOS64 */ + +/* Assembler local label prefix */ +#define LSYM_PREFIX ".L" + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#define LT_OBJDIR ".libs/" + +/* Define to 1 to disable the use of inline assembly */ +#define NO_ASM 1 + +/* Name of package */ +#define PACKAGE "gmp" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "gmp-bugs@gmplib.org, see https://gmplib.org/manual/Reporting-Bugs.html" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "GNU MP" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "GNU MP 6.1.2" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "gmp" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "http://www.gnu.org/software/gmp/" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "6.1.2" + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* The size of `mp_limb_t', as computed by sizeof. */ +#define SIZEOF_MP_LIMB_T 8 + +/* The size of `unsigned', as computed by sizeof. */ +#define SIZEOF_UNSIGNED 4 + +/* The size of `unsigned long', as computed by sizeof. */ +#define SIZEOF_UNSIGNED_LONG 8 + +/* The size of `unsigned short', as computed by sizeof. */ +#define SIZEOF_UNSIGNED_SHORT 2 + +/* The size of `void *', as computed by sizeof. */ +#define SIZEOF_VOID_P 8 + +/* Define to 1 if sscanf requires writable inputs */ +/* #undef SSCANF_WRITABLE_INPUT */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ +#define TIME_WITH_SYS_TIME 1 + +/* Maximum size the tune program can test for SQR_TOOM2_THRESHOLD */ +#define TUNE_SQR_TOOM2_MAX SQR_TOOM2_MAX_GENERIC + +/* Version number of package */ +#define VERSION "6.1.2" + +/* Define to 1 to enable ASSERT checking, per --enable-assert */ +/* #undef WANT_ASSERT */ + +/* Define to 1 to enable GMP_CPU_TYPE faking cpuid, per --enable-fake-cpuid */ +/* #undef WANT_FAKE_CPUID */ + +/* Define to 1 when building a fat binary. */ +/* #undef WANT_FAT_BINARY */ + +/* Define to 1 to enable FFTs for multiplication, per --enable-fft */ +#define WANT_FFT 1 + +/* Define to 1 to enable old mpn_mul_fft_full for multiplication, per + --enable-old-fft-full */ +/* #undef WANT_OLD_FFT_FULL */ + +/* Define to 1 if --enable-profiling=gprof */ +/* #undef WANT_PROFILING_GPROF */ + +/* Define to 1 if --enable-profiling=instrument */ +/* #undef WANT_PROFILING_INSTRUMENT */ + +/* Define to 1 if --enable-profiling=prof */ +/* #undef WANT_PROFILING_PROF */ + +/* Define one of these to 1 for the desired temporary memory allocation + method, per --enable-alloca. */ +#define WANT_TMP_ALLOCA 1 +/* #undef WANT_TMP_REENTRANT */ +/* #undef WANT_TMP_NOTREENTRANT */ +/* #undef WANT_TMP_DEBUG */ + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a + `char[]'. */ +/* #undef YYTEXT_POINTER */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to the equivalent of the C99 'restrict' keyword, or to + nothing if this is not supported. Do not define if restrict is + supported directly. */ +#define restrict __restrict +/* Work around a bug in Sun C++: it does not support _Restrict or + __restrict__, even though the corresponding Sun C compiler ends up with + "#define restrict _Restrict" or "#define restrict __restrict__" in the + previous line. Perhaps some future version of Sun C++ will work with + restrict; if so, hopefully it defines __RESTRICT like Sun C does. */ +#if defined __SUNPRO_CC && !defined __RESTRICT +# define _Restrict +# define __restrict__ +#endif + +/* Define to empty if the keyword `volatile' does not work. Warning: valid + code using `volatile' can become incorrect without. Disable with care. */ +/* #undef volatile */ diff --git a/examples/multiprecision/bench-include/fac_table.h b/examples/multiprecision/bench-include/fac_table.h new file mode 100644 index 0000000000000000000000000000000000000000..67083481752bfa1d7d01139213c9063147db0d64 --- /dev/null +++ b/examples/multiprecision/bench-include/fac_table.h @@ -0,0 +1,49 @@ +/* This file is automatically generated by gen-fac.c */ + +#if GMP_NUMB_BITS != 64 +Error , error this data is for 64 GMP_NUMB_BITS only +#endif +/* This table is 0!,1!,2!,3!,...,n! where n! has <= GMP_NUMB_BITS bits */ +#define ONE_LIMB_FACTORIAL_TABLE CNST_LIMB(0x1),CNST_LIMB(0x1),CNST_LIMB(0x2),CNST_LIMB(0x6),CNST_LIMB(0x18),CNST_LIMB(0x78),CNST_LIMB(0x2d0),CNST_LIMB(0x13b0),CNST_LIMB(0x9d80),CNST_LIMB(0x58980),CNST_LIMB(0x375f00),CNST_LIMB(0x2611500),CNST_LIMB(0x1c8cfc00),CNST_LIMB(0x17328cc00),CNST_LIMB(0x144c3b2800),CNST_LIMB(0x13077775800),CNST_LIMB(0x130777758000),CNST_LIMB(0x1437eeecd8000),CNST_LIMB(0x16beecca730000),CNST_LIMB(0x1b02b9306890000),CNST_LIMB(0x21c3677c82b40000) + +/* This table is 0!,1!,2!/2,3!/2,...,n!/2^sn where n!/2^sn is an */ +/* odd integer for each n, and n!/2^sn has <= GMP_NUMB_BITS bits */ +#define ONE_LIMB_ODD_FACTORIAL_TABLE CNST_LIMB(0x1),CNST_LIMB(0x1),CNST_LIMB(0x1),CNST_LIMB(0x3),CNST_LIMB(0x3),CNST_LIMB(0xf),CNST_LIMB(0x2d),CNST_LIMB(0x13b),CNST_LIMB(0x13b),CNST_LIMB(0xb13),CNST_LIMB(0x375f),CNST_LIMB(0x26115),CNST_LIMB(0x7233f),CNST_LIMB(0x5cca33),CNST_LIMB(0x2898765),CNST_LIMB(0x260eeeeb),CNST_LIMB(0x260eeeeb),CNST_LIMB(0x286fddd9b),CNST_LIMB(0x16beecca73),CNST_LIMB(0x1b02b930689),CNST_LIMB(0x870d9df20ad),CNST_LIMB(0xb141df4dae31),CNST_LIMB(0x79dd498567c1b),CNST_LIMB(0xaf2e19afc5266d),CNST_LIMB(0x20d8a4d0f4f7347),CNST_LIMB(0x335281867ec241ef) +#define ODD_FACTORIAL_TABLE_MAX CNST_LIMB(0x335281867ec241ef) +#define ODD_FACTORIAL_TABLE_LIMIT (25) + +/* Previous table, continued, values modulo 2^GMP_NUMB_BITS */ +#define ONE_LIMB_ODD_FACTORIAL_EXTTABLE CNST_LIMB(0x9b3093d46fdd5923),CNST_LIMB(0x5e1f9767cc5866b1),CNST_LIMB(0x92dd23d6966aced7),CNST_LIMB(0xa30d0f4f0a196e5b),CNST_LIMB(0x8dc3e5a1977d7755),CNST_LIMB(0x2ab8ce915831734b),CNST_LIMB(0x2ab8ce915831734b),CNST_LIMB(0x81d2a0bc5e5fdcab),CNST_LIMB(0x9efcac82445da75b),CNST_LIMB(0xbc8b95cf58cde171),CNST_LIMB(0xa0e8444a1f3cecf9),CNST_LIMB(0x4191deb683ce3ffd),CNST_LIMB(0xddd3878bc84ebfc7),CNST_LIMB(0xcb39a64b83ff3751),CNST_LIMB(0xf8203f7993fc1495),CNST_LIMB(0xbd2a2a78b35f4bdd),CNST_LIMB(0x84757be6b6d13921),CNST_LIMB(0x3fbbcfc0b524988b),CNST_LIMB(0xbd11ed47c8928df9),CNST_LIMB(0x3c26b59e41c2f4c5),CNST_LIMB(0x677a5137e883fdb3),CNST_LIMB(0xff74e943b03b93dd),CNST_LIMB(0xfe5ebbcb10b2bb97),CNST_LIMB(0xb021f1de3235e7e7),CNST_LIMB(0x33509eb2e743a58f),CNST_LIMB(0x390f9da41279fb7d),CNST_LIMB(0xe5cb0154f031c559),CNST_LIMB(0x93074695ba4ddb6d),CNST_LIMB(0x81c471caa636247f),CNST_LIMB(0xe1347289b5a1d749),CNST_LIMB(0x286f21c3f76ce2ff),CNST_LIMB(0xbe84a2173e8ac7),CNST_LIMB(0x1595065ca215b88b),CNST_LIMB(0xf95877595b018809),CNST_LIMB(0x9c2efe3c5516f887),CNST_LIMB(0x373294604679382b),CNST_LIMB(0xaf1ff7a888adcd35),CNST_LIMB(0x18ddf279a2c5800b),CNST_LIMB(0x18ddf279a2c5800b),CNST_LIMB(0x505a90e2542582cb),CNST_LIMB(0x5bacad2cd8d5dc2b),CNST_LIMB(0xfe3152bcbff89f41) +#define ODD_FACTORIAL_EXTTABLE_LIMIT (67) + +/* This table is 1!!,3!!,...,(2n+1)!! where (2n+1)!! has <= GMP_NUMB_BITS bits */ +#define ONE_LIMB_ODD_DOUBLEFACTORIAL_TABLE CNST_LIMB(0x1),CNST_LIMB(0x3),CNST_LIMB(0xf),CNST_LIMB(0x69),CNST_LIMB(0x3b1),CNST_LIMB(0x289b),CNST_LIMB(0x20fdf),CNST_LIMB(0x1eee11),CNST_LIMB(0x20dcf21),CNST_LIMB(0x27065f73),CNST_LIMB(0x33385d46f),CNST_LIMB(0x49a10615f9),CNST_LIMB(0x730b9982551),CNST_LIMB(0xc223930bef8b),CNST_LIMB(0x15fe07a85a22bf),CNST_LIMB(0x2a9c2ed62ea3521),CNST_LIMB(0x57e22099c030d941) +#define ODD_DOUBLEFACTORIAL_TABLE_MAX CNST_LIMB(0x57e22099c030d941) +#define ODD_DOUBLEFACTORIAL_TABLE_LIMIT (33) + +/* This table x_1, x_2,... contains values s.t. x_n^n has <= GMP_NUMB_BITS bits */ +#define NTH_ROOT_NUMB_MASK_TABLE (GMP_NUMB_MASK),CNST_LIMB(0xffffffff),CNST_LIMB(0x285145),CNST_LIMB(0xffff),CNST_LIMB(0x1bdb),CNST_LIMB(0x659),CNST_LIMB(0x235),CNST_LIMB(0xff) + +/* This table contains inverses of odd factorials, modulo 2^GMP_NUMB_BITS */ + +/* It begins with (2!/2)^-1=1 */ +#define ONE_LIMB_ODD_FACTORIAL_INVERSES_TABLE CNST_LIMB(0x1),CNST_LIMB(0xaaaaaaaaaaaaaaab),CNST_LIMB(0xaaaaaaaaaaaaaaab),CNST_LIMB(0xeeeeeeeeeeeeeeef),CNST_LIMB(0x4fa4fa4fa4fa4fa5),CNST_LIMB(0x2ff2ff2ff2ff2ff3),CNST_LIMB(0x2ff2ff2ff2ff2ff3),CNST_LIMB(0x938cc70553e3771b),CNST_LIMB(0xb71c27cddd93e49f),CNST_LIMB(0xb38e3229fcdee63d),CNST_LIMB(0xe684bb63544a4cbf),CNST_LIMB(0xc2f684917ca340fb),CNST_LIMB(0xf747c9cba417526d),CNST_LIMB(0xbb26eb51d7bd49c3),CNST_LIMB(0xbb26eb51d7bd49c3),CNST_LIMB(0xb0a7efb985294093),CNST_LIMB(0xbe4b8c69f259eabb),CNST_LIMB(0x6854d17ed6dc4fb9),CNST_LIMB(0xe1aa904c915f4325),CNST_LIMB(0x3b8206df131cead1),CNST_LIMB(0x79c6009fea76fe13),CNST_LIMB(0xd8c5d381633cd365),CNST_LIMB(0x4841f12b21144677),CNST_LIMB(0x4a91ff68200b0d0f),CNST_LIMB(0x8f9513a58c4f9e8b),CNST_LIMB(0x2b3e690621a42251),CNST_LIMB(0x4f520f00e03c04e7),CNST_LIMB(0x2edf84ee600211d3),CNST_LIMB(0xadcaa2764aaacdfd),CNST_LIMB(0x161f4f9033f4fe63),CNST_LIMB(0x161f4f9033f4fe63),CNST_LIMB(0xbada2932ea4d3e03),CNST_LIMB(0xcec189f3efaa30d3),CNST_LIMB(0xf7475bb68330bf91),CNST_LIMB(0x37eb7bf7d5b01549),CNST_LIMB(0x46b35660a4e91555),CNST_LIMB(0xa567c12d81f151f7),CNST_LIMB(0x4c724007bb2071b1),CNST_LIMB(0xf4a0cce58a016bd),CNST_LIMB(0xfa21068e66106475),CNST_LIMB(0x244ab72b5a318ae1),CNST_LIMB(0x366ce67e080d0f23),CNST_LIMB(0xd666fdae5dd2a449),CNST_LIMB(0xd740ddd0acc06a0d),CNST_LIMB(0xb050bbbb28e6f97b),CNST_LIMB(0x70b003fe890a5c75),CNST_LIMB(0xd03aabff83037427),CNST_LIMB(0x13ec4ca72c783bd7),CNST_LIMB(0x90282c06afdbd96f),CNST_LIMB(0x4414ddb9db4a95d5),CNST_LIMB(0xa2c68735ae6832e9),CNST_LIMB(0xbf72d71455676665),CNST_LIMB(0xa8469fab6b759b7f),CNST_LIMB(0xc1e55b56e606caf9),CNST_LIMB(0x40455630fc4a1cff),CNST_LIMB(0x120a7b0046d16f7),CNST_LIMB(0xa7c3553b08faef23),CNST_LIMB(0x9f0bfd1b08d48639),CNST_LIMB(0xa433ffce9a304d37),CNST_LIMB(0xa22ad1d53915c683),CNST_LIMB(0xcb6cbc723ba5dd1d),CNST_LIMB(0x547fb1b8ab9d0ba3),CNST_LIMB(0x547fb1b8ab9d0ba3),CNST_LIMB(0x8f15a826498852e3) + +/* This table contains 2n-popc(2n) for small n */ + +/* It begins with 2-1=1 (n=1) */ +#define TABLE_2N_MINUS_POPC_2N 1,3,4,7,8,10,11,15,16,18,19,22,23,25,26,31,32,34,35,38,39,41,42,46,47,49,50,53,54,56,57,63,64,66,67,70,71,73,74,78 +#define TABLE_LIMIT_2N_MINUS_POPC_2N 81 +#define ODD_CENTRAL_BINOMIAL_OFFSET (13) + +/* This table contains binomial(2k,k)/2^t */ + +/* It begins with ODD_CENTRAL_BINOMIAL_TABLE_MIN */ +#define ONE_LIMB_ODD_CENTRAL_BINOMIAL_TABLE CNST_LIMB(0x13d66b),CNST_LIMB(0x4c842f),CNST_LIMB(0x93ee7d),CNST_LIMB(0x11e9e123),CNST_LIMB(0x22c60053),CNST_LIMB(0x873ae4d1),CNST_LIMB(0x10757bd97),CNST_LIMB(0x80612c6cd),CNST_LIMB(0xfaa556bc1),CNST_LIMB(0x3d3cc24821),CNST_LIMB(0x77cfeb6bbb),CNST_LIMB(0x7550ebd97c7),CNST_LIMB(0xe5f08695caf),CNST_LIMB(0x386120ffce11),CNST_LIMB(0x6eabb28dd6df),CNST_LIMB(0x3658e31c82a8f),CNST_LIMB(0x6ad2050312783),CNST_LIMB(0x1a42902a5af0bf),CNST_LIMB(0x33ac44f881661d),CNST_LIMB(0xcb764f927d82123),CNST_LIMB(0x190c23fa46b93983),CNST_LIMB(0x62b7609e25caf1b9),CNST_LIMB(0xc29cb72925ef2cff) +#define ODD_CENTRAL_BINOMIAL_TABLE_LIMIT (35) + +/* This table contains the inverses of elements in the previous table. */ +#define ONE_LIMB_ODD_CENTRAL_BINOMIAL_INVERSE_TABLE CNST_LIMB(0x61e5bd199bb12643),CNST_LIMB(0x78321494dc8342cf),CNST_LIMB(0x4fd348704ebf7ad5),CNST_LIMB(0x7e722ba086ab568b),CNST_LIMB(0xa5fcc124265843db),CNST_LIMB(0x89c4a6b18633f431),CNST_LIMB(0x4daa2c15f8ce9227),CNST_LIMB(0x801c618ca9be9605),CNST_LIMB(0x32dc192f948a441),CNST_LIMB(0xd02b90c2bf3be1),CNST_LIMB(0xd897e8c1749aa173),CNST_LIMB(0x54a234fc01fef9f7),CNST_LIMB(0x83ff2ab4d1ff7a4f),CNST_LIMB(0xa427f1c9b304e2f1),CNST_LIMB(0x9c14595d1793651f),CNST_LIMB(0x883a71c607a7b46f),CNST_LIMB(0xd089863c54bc9f2b),CNST_LIMB(0x9022f6bce5d07f3f),CNST_LIMB(0xbec207e218768c35),CNST_LIMB(0x9d70cb4cbb4f168b),CNST_LIMB(0x3c3d3403828a9d2b),CNST_LIMB(0x7672df58c56bc489),CNST_LIMB(0x1e66ca55d727d2ff) + +/* This table contains the values t in the formula binomial(2k,k)/2^t */ +#define CENTRAL_BINOMIAL_2FAC_TABLE 3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,1,2,2,3 diff --git a/examples/multiprecision/bench-include/fib_table.h b/examples/multiprecision/bench-include/fib_table.h new file mode 100644 index 0000000000000000000000000000000000000000..66ac4d65a52c703c8190d691ef4353398938c351 --- /dev/null +++ b/examples/multiprecision/bench-include/fib_table.h @@ -0,0 +1,8 @@ +/* This file generated by gen-fib.c - DO NOT EDIT. */ + +#if GMP_NUMB_BITS != 64 +Error, error, this data is for 64 bits +#endif + +#define FIB_TABLE_LIMIT 93 +#define FIB_TABLE_LUCNUM_LIMIT 92 diff --git a/examples/multiprecision/bench-include/gmp-impl.h b/examples/multiprecision/bench-include/gmp-impl.h new file mode 100644 index 0000000000000000000000000000000000000000..dcc233bb4434628ddd2de8ff18b1b2014344fd11 --- /dev/null +++ b/examples/multiprecision/bench-include/gmp-impl.h @@ -0,0 +1,5222 @@ +/* Include file for internal GNU MP types and definitions. + + THE CONTENTS OF THIS FILE ARE FOR INTERNAL USE AND ARE ALMOST CERTAIN TO + BE SUBJECT TO INCOMPATIBLE CHANGES IN FUTURE GNU MP RELEASES. + +Copyright 1991, 1993-1997, 1999-2015 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + +or + + * the GNU General Public License as published by the Free Software + Foundation; either version 2 of the License, or (at your option) any + later version. + +or both in parallel, as here. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received copies of the GNU General Public License and the +GNU Lesser General Public License along with the GNU MP Library. If not, +see https://www.gnu.org/licenses/. */ + + +/* __GMP_DECLSPEC must be given on any global data that will be accessed + from outside libgmp, meaning from the test or development programs, or + from libgmpxx. Failing to do this will result in an incorrect address + being used for the accesses. On functions __GMP_DECLSPEC makes calls + from outside libgmp more efficient, but they'll still work fine without + it. */ + + +#ifndef __GMP_IMPL_H__ +#define __GMP_IMPL_H__ + +#if defined _CRAY +#include <intrinsics.h> /* for _popcnt */ +#endif + +/* For INT_MAX, etc. We used to avoid it because of a bug (on solaris, + gcc 2.95 under -mcpu=ultrasparc in ABI=32 ends up getting wrong + values (the ABI=64 values)), but it should be safe now. + + On Cray vector systems, however, we need the system limits.h since sizes + of signed and unsigned types can differ there, depending on compiler + options (eg. -hnofastmd), making our SHRT_MAX etc expressions fail. For + reference, int can be 46 or 64 bits, whereas uint is always 64 bits; and + short can be 24, 32, 46 or 64 bits, and different for ushort. */ + +#include <limits.h> + +/* For fat.h and other fat binary stuff. + No need for __GMP_ATTRIBUTE_PURE or __GMP_NOTHROW, since functions + declared this way are only used to set function pointers in __gmpn_cpuvec, + they're not called directly. */ +#define DECL_add_n(name) \ + __GMP_DECLSPEC mp_limb_t name (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t) +#define DECL_addlsh1_n(name) \ + DECL_add_n (name) +#define DECL_addlsh2_n(name) \ + DECL_add_n (name) +#define DECL_addmul_1(name) \ + __GMP_DECLSPEC mp_limb_t name (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t) +#define DECL_addmul_2(name) \ + __GMP_DECLSPEC mp_limb_t name (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr) +#define DECL_bdiv_dbm1c(name) \ + __GMP_DECLSPEC mp_limb_t name (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t) +#define DECL_cnd_add_n(name) \ + __GMP_DECLSPEC mp_limb_t name (mp_limb_t, mp_ptr, mp_srcptr, mp_srcptr, mp_size_t) +#define DECL_cnd_sub_n(name) \ + __GMP_DECLSPEC mp_limb_t name (mp_limb_t, mp_ptr, mp_srcptr, mp_srcptr, mp_size_t) +#define DECL_com(name) \ + __GMP_DECLSPEC void name (mp_ptr, mp_srcptr, mp_size_t) +#define DECL_copyd(name) \ + __GMP_DECLSPEC void name (mp_ptr, mp_srcptr, mp_size_t) +#define DECL_copyi(name) \ + DECL_copyd (name) +#define DECL_divexact_1(name) \ + __GMP_DECLSPEC void name (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t) +#define DECL_divexact_by3c(name) \ + __GMP_DECLSPEC mp_limb_t name (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t) +#define DECL_divrem_1(name) \ + __GMP_DECLSPEC mp_limb_t name (mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t) +#define DECL_gcd_1(name) \ + __GMP_DECLSPEC mp_limb_t name (mp_srcptr, mp_size_t, mp_limb_t) +#define DECL_lshift(name) \ + __GMP_DECLSPEC mp_limb_t name (mp_ptr, mp_srcptr, mp_size_t, unsigned) +#define DECL_lshiftc(name) \ + DECL_lshift (name) +#define DECL_mod_1(name) \ + __GMP_DECLSPEC mp_limb_t name (mp_srcptr, mp_size_t, mp_limb_t) +#define DECL_mod_1_1p(name) \ + __GMP_DECLSPEC mp_limb_t name (mp_srcptr, mp_size_t, mp_limb_t, const mp_limb_t []) +#define DECL_mod_1_1p_cps(name) \ + __GMP_DECLSPEC void name (mp_limb_t cps[], mp_limb_t b) +#define DECL_mod_1s_2p(name) \ + DECL_mod_1_1p (name) +#define DECL_mod_1s_2p_cps(name) \ + DECL_mod_1_1p_cps (name) +#define DECL_mod_1s_4p(name) \ + DECL_mod_1_1p (name) +#define DECL_mod_1s_4p_cps(name) \ + DECL_mod_1_1p_cps (name) +#define DECL_mod_34lsub1(name) \ + __GMP_DECLSPEC mp_limb_t name (mp_srcptr, mp_size_t) +#define DECL_modexact_1c_odd(name) \ + __GMP_DECLSPEC mp_limb_t name (mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t) +#define DECL_mul_1(name) \ + DECL_addmul_1 (name) +#define DECL_mul_basecase(name) \ + __GMP_DECLSPEC void name (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t) +#define DECL_mullo_basecase(name) \ + __GMP_DECLSPEC void name (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t) +#define DECL_preinv_divrem_1(name) \ + __GMP_DECLSPEC mp_limb_t name (mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t, int) +#define DECL_preinv_mod_1(name) \ + __GMP_DECLSPEC mp_limb_t name (mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t) +#define DECL_redc_1(name) \ + __GMP_DECLSPEC mp_limb_t name (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_limb_t) +#define DECL_redc_2(name) \ + __GMP_DECLSPEC mp_limb_t name (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_srcptr) +#define DECL_rshift(name) \ + DECL_lshift (name) +#define DECL_sqr_basecase(name) \ + __GMP_DECLSPEC void name (mp_ptr, mp_srcptr, mp_size_t) +#define DECL_sub_n(name) \ + DECL_add_n (name) +#define DECL_sublsh1_n(name) \ + DECL_add_n (name) +#define DECL_submul_1(name) \ + DECL_addmul_1 (name) + +#if ! defined (__GMP_WITHIN_CONFIGURE) +#include "config.h" +#include "gmp-mparam.h" +#include "fib_table.h" +#include "fac_table.h" +#include "mp_bases.h" +#if WANT_FAT_BINARY +#include "fat.h" +#endif +#endif + +#if HAVE_INTTYPES_H /* for uint_least32_t */ +# include <inttypes.h> +#else +# if HAVE_STDINT_H +# include <stdint.h> +# endif +#endif + +#ifdef __cplusplus +#include <cstring> /* for strlen */ +#include <string> /* for std::string */ +#endif + + +#ifndef WANT_TMP_DEBUG /* for TMP_ALLOC_LIMBS_2 and others */ +#define WANT_TMP_DEBUG 0 +#endif + +/* The following tries to get a good version of alloca. The tests are + adapted from autoconf AC_FUNC_ALLOCA, with a couple of additions. + Whether this succeeds is tested by GMP_FUNC_ALLOCA and HAVE_ALLOCA will + be setup appropriately. + + ifndef alloca - a cpp define might already exist. + glibc <stdlib.h> includes <alloca.h> which uses GCC __builtin_alloca. + HP cc +Olibcalls adds a #define of alloca to __builtin_alloca. + + GCC __builtin_alloca - preferred whenever available. + + _AIX pragma - IBM compilers need a #pragma in "each module that needs to + use alloca". Pragma indented to protect pre-ANSI cpp's. _IBMR2 was + used in past versions of GMP, retained still in case it matters. + + The autoconf manual says this pragma needs to be at the start of a C + file, apart from comments and preprocessor directives. Is that true? + xlc on aix 4.xxx doesn't seem to mind it being after prototypes etc + from gmp.h. +*/ + +#ifndef alloca +# ifdef __GNUC__ +# define alloca __builtin_alloca +# else +# ifdef __DECC +# define alloca(x) __ALLOCA(x) +# else +# ifdef _MSC_VER +# include <malloc.h> +# define alloca _alloca +# else +# if HAVE_ALLOCA_H +# include <alloca.h> +# else +# if defined (_AIX) || defined (_IBMR2) + #pragma alloca +# else + char *alloca (); +# endif +# endif +# endif +# endif +# endif +#endif + + +/* if not provided by gmp-mparam.h */ +#ifndef GMP_LIMB_BYTES +#define GMP_LIMB_BYTES SIZEOF_MP_LIMB_T +#endif +#ifndef GMP_LIMB_BITS +#define GMP_LIMB_BITS (8 * SIZEOF_MP_LIMB_T) +#endif + +#define BITS_PER_ULONG (8 * SIZEOF_UNSIGNED_LONG) + + +/* gmp_uint_least32_t is an unsigned integer type with at least 32 bits. */ +#if HAVE_UINT_LEAST32_T +typedef uint_least32_t gmp_uint_least32_t; +#else +#if SIZEOF_UNSIGNED_SHORT >= 4 +typedef unsigned short gmp_uint_least32_t; +#else +#if SIZEOF_UNSIGNED >= 4 +typedef unsigned gmp_uint_least32_t; +#else +typedef unsigned long gmp_uint_least32_t; +#endif +#endif +#endif + + +/* gmp_intptr_t, for pointer to integer casts */ +#if HAVE_INTPTR_T +typedef intptr_t gmp_intptr_t; +#else /* fallback */ +typedef size_t gmp_intptr_t; +#endif + + +/* pre-inverse types for truncating division and modulo */ +typedef struct {mp_limb_t inv32;} gmp_pi1_t; +typedef struct {mp_limb_t inv21, inv32, inv53;} gmp_pi2_t; + + +/* "const" basically means a function does nothing but examine its arguments + and give a return value, it doesn't read or write any memory (neither + global nor pointed to by arguments), and has no other side-effects. This + is more restrictive than "pure". See info node "(gcc)Function + Attributes". __GMP_NO_ATTRIBUTE_CONST_PURE lets tune/common.c etc turn + this off when trying to write timing loops. */ +#if HAVE_ATTRIBUTE_CONST && ! defined (__GMP_NO_ATTRIBUTE_CONST_PURE) +#define ATTRIBUTE_CONST __attribute__ ((const)) +#else +#define ATTRIBUTE_CONST +#endif + +#if HAVE_ATTRIBUTE_NORETURN +#define ATTRIBUTE_NORETURN __attribute__ ((noreturn)) +#else +#define ATTRIBUTE_NORETURN +#endif + +/* "malloc" means a function behaves like malloc in that the pointer it + returns doesn't alias anything. */ +#if HAVE_ATTRIBUTE_MALLOC +#define ATTRIBUTE_MALLOC __attribute__ ((malloc)) +#else +#define ATTRIBUTE_MALLOC +#endif + + +#if ! HAVE_STRCHR +#define strchr(s,c) index(s,c) +#endif + +#if ! HAVE_MEMSET +#define memset(p, c, n) \ + do { \ + ASSERT ((n) >= 0); \ + char *__memset__p = (p); \ + int __i; \ + for (__i = 0; __i < (n); __i++) \ + __memset__p[__i] = (c); \ + } while (0) +#endif + +/* va_copy is standard in C99, and gcc provides __va_copy when in strict C89 + mode. Falling back to a memcpy will give maximum portability, since it + works no matter whether va_list is a pointer, struct or array. */ +#if ! defined (va_copy) && defined (__va_copy) +#define va_copy(dst,src) __va_copy(dst,src) +#endif +#if ! defined (va_copy) +#define va_copy(dst,src) \ + do { memcpy (&(dst), &(src), sizeof (va_list)); } while (0) +#endif + + +/* HAVE_HOST_CPU_alpha_CIX is 1 on an alpha with the CIX instructions + (ie. ctlz, ctpop, cttz). */ +#if HAVE_HOST_CPU_alphaev67 || HAVE_HOST_CPU_alphaev68 \ + || HAVE_HOST_CPU_alphaev7 +#define HAVE_HOST_CPU_alpha_CIX 1 +#endif + + +#if defined (__cplusplus) +extern "C" { +#endif + + +/* Usage: TMP_DECL; + TMP_MARK; + ptr = TMP_ALLOC (bytes); + TMP_FREE; + + Small allocations should use TMP_SALLOC, big allocations should use + TMP_BALLOC. Allocations that might be small or big should use TMP_ALLOC. + + Functions that use just TMP_SALLOC should use TMP_SDECL, TMP_SMARK, and + TMP_SFREE. + + TMP_DECL just declares a variable, but might be empty and so must be last + in a list of variables. TMP_MARK must be done before any TMP_ALLOC. + TMP_ALLOC(0) is not allowed. TMP_FREE doesn't need to be done if a + TMP_MARK was made, but then no TMP_ALLOCs. */ + +/* The alignment in bytes, used for TMP_ALLOCed blocks, when alloca or + __gmp_allocate_func doesn't already determine it. Currently TMP_ALLOC + isn't used for "double"s, so that's not in the union. */ +union tmp_align_t { + mp_limb_t l; + char *p; +}; +#define __TMP_ALIGN sizeof (union tmp_align_t) + +/* Return "a" rounded upwards to a multiple of "m", if it isn't already. + "a" must be an unsigned type. + This is designed for use with a compile-time constant "m". + The POW2 case is expected to be usual, and gcc 3.0 and up recognises + "(-(8*n))%8" or the like is always zero, which means the rounding up in + the WANT_TMP_NOTREENTRANT version of TMP_ALLOC below will be a noop. */ +#define ROUND_UP_MULTIPLE(a,m) \ + (POW2_P(m) ? (a) + (-(a))%(m) \ + : (a)+(m)-1 - (((a)+(m)-1) % (m))) + +#if defined (WANT_TMP_ALLOCA) || defined (WANT_TMP_REENTRANT) +struct tmp_reentrant_t { + struct tmp_reentrant_t *next; + size_t size; /* bytes, including header */ +}; +__GMP_DECLSPEC void *__gmp_tmp_reentrant_alloc (struct tmp_reentrant_t **, size_t) ATTRIBUTE_MALLOC; +__GMP_DECLSPEC void __gmp_tmp_reentrant_free (struct tmp_reentrant_t *); +#endif + +#if WANT_TMP_ALLOCA +#define TMP_SDECL +#define TMP_DECL struct tmp_reentrant_t *__tmp_marker +#define TMP_SMARK +#define TMP_MARK __tmp_marker = 0 +#define TMP_SALLOC(n) alloca(n) +#define TMP_BALLOC(n) __gmp_tmp_reentrant_alloc (&__tmp_marker, n) +/* The peculiar stack allocation limit here is chosen for efficient asm. */ +#define TMP_ALLOC(n) \ + (LIKELY ((n) <= 0x7f00) ? TMP_SALLOC(n) : TMP_BALLOC(n)) +#define TMP_SFREE +#define TMP_FREE \ + do { \ + if (UNLIKELY (__tmp_marker != 0)) \ + __gmp_tmp_reentrant_free (__tmp_marker); \ + } while (0) +#endif + +#if WANT_TMP_REENTRANT +#define TMP_SDECL TMP_DECL +#define TMP_DECL struct tmp_reentrant_t *__tmp_marker +#define TMP_SMARK TMP_MARK +#define TMP_MARK __tmp_marker = 0 +#define TMP_SALLOC(n) TMP_ALLOC(n) +#define TMP_BALLOC(n) TMP_ALLOC(n) +#define TMP_ALLOC(n) __gmp_tmp_reentrant_alloc (&__tmp_marker, n) +#define TMP_SFREE TMP_FREE +#define TMP_FREE __gmp_tmp_reentrant_free (__tmp_marker) +#endif + +#if WANT_TMP_NOTREENTRANT +struct tmp_marker +{ + struct tmp_stack *which_chunk; + void *alloc_point; +}; +__GMP_DECLSPEC void *__gmp_tmp_alloc (unsigned long) ATTRIBUTE_MALLOC; +__GMP_DECLSPEC void __gmp_tmp_mark (struct tmp_marker *); +__GMP_DECLSPEC void __gmp_tmp_free (struct tmp_marker *); +#define TMP_SDECL TMP_DECL +#define TMP_DECL struct tmp_marker __tmp_marker +#define TMP_SMARK TMP_MARK +#define TMP_MARK __gmp_tmp_mark (&__tmp_marker) +#define TMP_SALLOC(n) TMP_ALLOC(n) +#define TMP_BALLOC(n) TMP_ALLOC(n) +#define TMP_ALLOC(n) \ + __gmp_tmp_alloc (ROUND_UP_MULTIPLE ((unsigned long) (n), __TMP_ALIGN)) +#define TMP_SFREE TMP_FREE +#define TMP_FREE __gmp_tmp_free (&__tmp_marker) +#endif + +#if WANT_TMP_DEBUG +/* See tal-debug.c for some comments. */ +struct tmp_debug_t { + struct tmp_debug_entry_t *list; + const char *file; + int line; +}; +struct tmp_debug_entry_t { + struct tmp_debug_entry_t *next; + void *block; + size_t size; +}; +__GMP_DECLSPEC void __gmp_tmp_debug_mark (const char *, int, struct tmp_debug_t **, + struct tmp_debug_t *, + const char *, const char *); +__GMP_DECLSPEC void *__gmp_tmp_debug_alloc (const char *, int, int, + struct tmp_debug_t **, const char *, + size_t) ATTRIBUTE_MALLOC; +__GMP_DECLSPEC void __gmp_tmp_debug_free (const char *, int, int, + struct tmp_debug_t **, + const char *, const char *); +#define TMP_SDECL TMP_DECL_NAME(__tmp_xmarker, "__tmp_marker") +#define TMP_DECL TMP_DECL_NAME(__tmp_xmarker, "__tmp_marker") +#define TMP_SMARK TMP_MARK_NAME(__tmp_xmarker, "__tmp_marker") +#define TMP_MARK TMP_MARK_NAME(__tmp_xmarker, "__tmp_marker") +#define TMP_SFREE TMP_FREE_NAME(__tmp_xmarker, "__tmp_marker") +#define TMP_FREE TMP_FREE_NAME(__tmp_xmarker, "__tmp_marker") +/* The marker variable is designed to provoke an uninitialized variable + warning from the compiler if TMP_FREE is used without a TMP_MARK. + __tmp_marker_inscope does the same for TMP_ALLOC. Runtime tests pick + these things up too. */ +#define TMP_DECL_NAME(marker, marker_name) \ + int marker; \ + int __tmp_marker_inscope; \ + const char *__tmp_marker_name = marker_name; \ + struct tmp_debug_t __tmp_marker_struct; \ + /* don't demand NULL, just cast a zero */ \ + struct tmp_debug_t *__tmp_marker = (struct tmp_debug_t *) 0 +#define TMP_MARK_NAME(marker, marker_name) \ + do { \ + marker = 1; \ + __tmp_marker_inscope = 1; \ + __gmp_tmp_debug_mark (ASSERT_FILE, ASSERT_LINE, \ + &__tmp_marker, &__tmp_marker_struct, \ + __tmp_marker_name, marker_name); \ + } while (0) +#define TMP_SALLOC(n) TMP_ALLOC(n) +#define TMP_BALLOC(n) TMP_ALLOC(n) +#define TMP_ALLOC(size) \ + __gmp_tmp_debug_alloc (ASSERT_FILE, ASSERT_LINE, \ + __tmp_marker_inscope, \ + &__tmp_marker, __tmp_marker_name, size) +#define TMP_FREE_NAME(marker, marker_name) \ + do { \ + __gmp_tmp_debug_free (ASSERT_FILE, ASSERT_LINE, \ + marker, &__tmp_marker, \ + __tmp_marker_name, marker_name); \ + } while (0) +#endif /* WANT_TMP_DEBUG */ + + +/* Allocating various types. */ +#define TMP_ALLOC_TYPE(n,type) ((type *) TMP_ALLOC ((n) * sizeof (type))) +#define TMP_SALLOC_TYPE(n,type) ((type *) TMP_SALLOC ((n) * sizeof (type))) +#define TMP_BALLOC_TYPE(n,type) ((type *) TMP_BALLOC ((n) * sizeof (type))) +#define TMP_ALLOC_LIMBS(n) TMP_ALLOC_TYPE(n,mp_limb_t) +#define TMP_SALLOC_LIMBS(n) TMP_SALLOC_TYPE(n,mp_limb_t) +#define TMP_BALLOC_LIMBS(n) TMP_BALLOC_TYPE(n,mp_limb_t) +#define TMP_ALLOC_MP_PTRS(n) TMP_ALLOC_TYPE(n,mp_ptr) +#define TMP_SALLOC_MP_PTRS(n) TMP_SALLOC_TYPE(n,mp_ptr) +#define TMP_BALLOC_MP_PTRS(n) TMP_BALLOC_TYPE(n,mp_ptr) + +/* It's more efficient to allocate one block than many. This is certainly + true of the malloc methods, but it can even be true of alloca if that + involves copying a chunk of stack (various RISCs), or a call to a stack + bounds check (mingw). In any case, when debugging keep separate blocks + so a redzoning malloc debugger can protect each individually. */ +#define TMP_ALLOC_LIMBS_2(xp,xsize, yp,ysize) \ + do { \ + if (WANT_TMP_DEBUG) \ + { \ + (xp) = TMP_ALLOC_LIMBS (xsize); \ + (yp) = TMP_ALLOC_LIMBS (ysize); \ + } \ + else \ + { \ + (xp) = TMP_ALLOC_LIMBS ((xsize) + (ysize)); \ + (yp) = (xp) + (xsize); \ + } \ + } while (0) +#define TMP_ALLOC_LIMBS_3(xp,xsize, yp,ysize, zp,zsize) \ + do { \ + if (WANT_TMP_DEBUG) \ + { \ + (xp) = TMP_ALLOC_LIMBS (xsize); \ + (yp) = TMP_ALLOC_LIMBS (ysize); \ + (zp) = TMP_ALLOC_LIMBS (zsize); \ + } \ + else \ + { \ + (xp) = TMP_ALLOC_LIMBS ((xsize) + (ysize) + (zsize)); \ + (yp) = (xp) + (xsize); \ + (zp) = (yp) + (ysize); \ + } \ + } while (0) + +/* From gmp.h, nicer names for internal use. */ +#define CRAY_Pragma(str) __GMP_CRAY_Pragma(str) +#define MPN_CMP(result, xp, yp, size) __GMPN_CMP(result, xp, yp, size) +#define LIKELY(cond) __GMP_LIKELY(cond) +#define UNLIKELY(cond) __GMP_UNLIKELY(cond) + +#define ABS(x) ((x) >= 0 ? (x) : -(x)) +#define NEG_CAST(T,x) (- (__GMP_CAST (T, (x) + 1) - 1)) +#define ABS_CAST(T,x) ((x) >= 0 ? __GMP_CAST (T, x) : NEG_CAST (T,x)) +#undef MIN +#define MIN(l,o) ((l) < (o) ? (l) : (o)) +#undef MAX +#define MAX(h,i) ((h) > (i) ? (h) : (i)) +#define numberof(x) (sizeof (x) / sizeof ((x)[0])) + +/* Field access macros. */ +#define SIZ(x) ((x)->_mp_size) +#define ABSIZ(x) ABS (SIZ (x)) +#define PTR(x) ((x)->_mp_d) +#define EXP(x) ((x)->_mp_exp) +#define PREC(x) ((x)->_mp_prec) +#define ALLOC(x) ((x)->_mp_alloc) +#define NUM(x) mpq_numref(x) +#define DEN(x) mpq_denref(x) + +/* n-1 inverts any low zeros and the lowest one bit. If n&(n-1) leaves zero + then that lowest one bit must have been the only bit set. n==0 will + return true though, so avoid that. */ +#define POW2_P(n) (((n) & ((n) - 1)) == 0) + +/* This is intended for constant THRESHOLDs only, where the compiler + can completely fold the result. */ +#define LOG2C(n) \ + (((n) >= 0x1) + ((n) >= 0x2) + ((n) >= 0x4) + ((n) >= 0x8) + \ + ((n) >= 0x10) + ((n) >= 0x20) + ((n) >= 0x40) + ((n) >= 0x80) + \ + ((n) >= 0x100) + ((n) >= 0x200) + ((n) >= 0x400) + ((n) >= 0x800) + \ + ((n) >= 0x1000) + ((n) >= 0x2000) + ((n) >= 0x4000) + ((n) >= 0x8000)) + +#define MP_LIMB_T_MAX (~ (mp_limb_t) 0) + +/* Must cast ULONG_MAX etc to unsigned long etc, since they might not be + unsigned on a K&R compiler. In particular the HP-UX 10 bundled K&R cc + treats the plain decimal values in <limits.h> as signed. */ +#define ULONG_HIGHBIT (ULONG_MAX ^ ((unsigned long) ULONG_MAX >> 1)) +#define UINT_HIGHBIT (UINT_MAX ^ ((unsigned) UINT_MAX >> 1)) +#define USHRT_HIGHBIT (USHRT_MAX ^ ((unsigned short) USHRT_MAX >> 1)) +#define GMP_LIMB_HIGHBIT (MP_LIMB_T_MAX ^ (MP_LIMB_T_MAX >> 1)) + +#if __GMP_MP_SIZE_T_INT +#define MP_SIZE_T_MAX INT_MAX +#define MP_SIZE_T_MIN INT_MIN +#else +#define MP_SIZE_T_MAX LONG_MAX +#define MP_SIZE_T_MIN LONG_MIN +#endif + +/* mp_exp_t is the same as mp_size_t */ +#define MP_EXP_T_MAX MP_SIZE_T_MAX +#define MP_EXP_T_MIN MP_SIZE_T_MIN + +#define LONG_HIGHBIT LONG_MIN +#define INT_HIGHBIT INT_MIN +#define SHRT_HIGHBIT SHRT_MIN + + +#define GMP_NUMB_HIGHBIT (CNST_LIMB(1) << (GMP_NUMB_BITS-1)) + +#if GMP_NAIL_BITS == 0 +#define GMP_NAIL_LOWBIT CNST_LIMB(0) +#else +#define GMP_NAIL_LOWBIT (CNST_LIMB(1) << GMP_NUMB_BITS) +#endif + +#if GMP_NAIL_BITS != 0 +/* Set various *_THRESHOLD values to be used for nails. Thus we avoid using + code that has not yet been qualified. */ + +#undef DC_DIV_QR_THRESHOLD +#define DC_DIV_QR_THRESHOLD 50 + +#undef DIVREM_1_NORM_THRESHOLD +#undef DIVREM_1_UNNORM_THRESHOLD +#undef MOD_1_NORM_THRESHOLD +#undef MOD_1_UNNORM_THRESHOLD +#undef USE_PREINV_DIVREM_1 +#undef DIVREM_2_THRESHOLD +#undef DIVEXACT_1_THRESHOLD +#define DIVREM_1_NORM_THRESHOLD MP_SIZE_T_MAX /* no preinv */ +#define DIVREM_1_UNNORM_THRESHOLD MP_SIZE_T_MAX /* no preinv */ +#define MOD_1_NORM_THRESHOLD MP_SIZE_T_MAX /* no preinv */ +#define MOD_1_UNNORM_THRESHOLD MP_SIZE_T_MAX /* no preinv */ +#define USE_PREINV_DIVREM_1 0 /* no preinv */ +#define DIVREM_2_THRESHOLD MP_SIZE_T_MAX /* no preinv */ + +/* mpn/generic/mul_fft.c is not nails-capable. */ +#undef MUL_FFT_THRESHOLD +#undef SQR_FFT_THRESHOLD +#define MUL_FFT_THRESHOLD MP_SIZE_T_MAX +#define SQR_FFT_THRESHOLD MP_SIZE_T_MAX +#endif + +/* Swap macros. */ + +#define MP_LIMB_T_SWAP(x, y) \ + do { \ + mp_limb_t __mp_limb_t_swap__tmp = (x); \ + (x) = (y); \ + (y) = __mp_limb_t_swap__tmp; \ + } while (0) +#define MP_SIZE_T_SWAP(x, y) \ + do { \ + mp_size_t __mp_size_t_swap__tmp = (x); \ + (x) = (y); \ + (y) = __mp_size_t_swap__tmp; \ + } while (0) + +#define MP_PTR_SWAP(x, y) \ + do { \ + mp_ptr __mp_ptr_swap__tmp = (x); \ + (x) = (y); \ + (y) = __mp_ptr_swap__tmp; \ + } while (0) +#define MP_SRCPTR_SWAP(x, y) \ + do { \ + mp_srcptr __mp_srcptr_swap__tmp = (x); \ + (x) = (y); \ + (y) = __mp_srcptr_swap__tmp; \ + } while (0) + +#define MPN_PTR_SWAP(xp,xs, yp,ys) \ + do { \ + MP_PTR_SWAP (xp, yp); \ + MP_SIZE_T_SWAP (xs, ys); \ + } while(0) +#define MPN_SRCPTR_SWAP(xp,xs, yp,ys) \ + do { \ + MP_SRCPTR_SWAP (xp, yp); \ + MP_SIZE_T_SWAP (xs, ys); \ + } while(0) + +#define MPZ_PTR_SWAP(x, y) \ + do { \ + mpz_ptr __mpz_ptr_swap__tmp = (x); \ + (x) = (y); \ + (y) = __mpz_ptr_swap__tmp; \ + } while (0) +#define MPZ_SRCPTR_SWAP(x, y) \ + do { \ + mpz_srcptr __mpz_srcptr_swap__tmp = (x); \ + (x) = (y); \ + (y) = __mpz_srcptr_swap__tmp; \ + } while (0) + +#define MPQ_PTR_SWAP(x, y) \ + do { \ + mpq_ptr __mpq_ptr_swap__tmp = (x); \ + (x) = (y); \ + (y) = __mpq_ptr_swap__tmp; \ + } while (0) +#define MPQ_SRCPTR_SWAP(x, y) \ + do { \ + mpq_srcptr __mpq_srcptr_swap__tmp = (x); \ + (x) = (y); \ + (y) = __mpq_srcptr_swap__tmp; \ + } while (0) + + +/* Enhancement: __gmp_allocate_func could have "__attribute__ ((malloc))", + but current gcc (3.0) doesn't seem to support that. */ +__GMP_DECLSPEC extern void * (*__gmp_allocate_func) (size_t); +__GMP_DECLSPEC extern void * (*__gmp_reallocate_func) (void *, size_t, size_t); +__GMP_DECLSPEC extern void (*__gmp_free_func) (void *, size_t); + +__GMP_DECLSPEC void *__gmp_default_allocate (size_t); +__GMP_DECLSPEC void *__gmp_default_reallocate (void *, size_t, size_t); +__GMP_DECLSPEC void __gmp_default_free (void *, size_t); + +#define __GMP_ALLOCATE_FUNC_TYPE(n,type) \ + ((type *) (*__gmp_allocate_func) ((n) * sizeof (type))) +#define __GMP_ALLOCATE_FUNC_LIMBS(n) __GMP_ALLOCATE_FUNC_TYPE (n, mp_limb_t) + +#define __GMP_REALLOCATE_FUNC_TYPE(p, old_size, new_size, type) \ + ((type *) (*__gmp_reallocate_func) \ + (p, (old_size) * sizeof (type), (new_size) * sizeof (type))) +#define __GMP_REALLOCATE_FUNC_LIMBS(p, old_size, new_size) \ + __GMP_REALLOCATE_FUNC_TYPE(p, old_size, new_size, mp_limb_t) + +#define __GMP_FREE_FUNC_TYPE(p,n,type) (*__gmp_free_func) (p, (n) * sizeof (type)) +#define __GMP_FREE_FUNC_LIMBS(p,n) __GMP_FREE_FUNC_TYPE (p, n, mp_limb_t) + +#define __GMP_REALLOCATE_FUNC_MAYBE(ptr, oldsize, newsize) \ + do { \ + if ((oldsize) != (newsize)) \ + (ptr) = (*__gmp_reallocate_func) (ptr, oldsize, newsize); \ + } while (0) + +#define __GMP_REALLOCATE_FUNC_MAYBE_TYPE(ptr, oldsize, newsize, type) \ + do { \ + if ((oldsize) != (newsize)) \ + (ptr) = (type *) (*__gmp_reallocate_func) \ + (ptr, (oldsize) * sizeof (type), (newsize) * sizeof (type)); \ + } while (0) + + +/* Dummy for non-gcc, code involving it will go dead. */ +#if ! defined (__GNUC__) || __GNUC__ < 2 +#define __builtin_constant_p(x) 0 +#endif + + +/* In gcc 2.96 and up on i386, tail calls are optimized to jumps if the + stack usage is compatible. __attribute__ ((regparm (N))) helps by + putting leading parameters in registers, avoiding extra stack. + + regparm cannot be used with calls going through the PLT, because the + binding code there may clobber the registers (%eax, %edx, %ecx) used for + the regparm parameters. Calls to local (ie. static) functions could + still use this, if we cared to differentiate locals and globals. + + On athlon-unknown-freebsd4.9 with gcc 3.3.3, regparm cannot be used with + -p or -pg profiling, since that version of gcc doesn't realize the + .mcount calls will clobber the parameter registers. Other systems are + ok, like debian with glibc 2.3.2 (mcount doesn't clobber), but we don't + bother to try to detect this. regparm is only an optimization so we just + disable it when profiling (profiling being a slowdown anyway). */ + +#if HAVE_HOST_CPU_FAMILY_x86 && __GMP_GNUC_PREREQ (2,96) && ! defined (PIC) \ + && ! WANT_PROFILING_PROF && ! WANT_PROFILING_GPROF +#define USE_LEADING_REGPARM 1 +#else +#define USE_LEADING_REGPARM 0 +#endif + +/* Macros for altering parameter order according to regparm usage. */ +#if USE_LEADING_REGPARM +#define REGPARM_2_1(a,b,x) x,a,b +#define REGPARM_3_1(a,b,c,x) x,a,b,c +#define REGPARM_ATTR(n) __attribute__ ((regparm (n))) +#else +#define REGPARM_2_1(a,b,x) a,b,x +#define REGPARM_3_1(a,b,c,x) a,b,c,x +#define REGPARM_ATTR(n) +#endif + + +/* ASM_L gives a local label for a gcc asm block, for use when temporary + local labels like "1:" might not be available, which is the case for + instance on the x86s (the SCO assembler doesn't support them). + + The label generated is made unique by including "%=" which is a unique + number for each insn. This ensures the same name can be used in multiple + asm blocks, perhaps via a macro. Since jumps between asm blocks are not + allowed there's no need for a label to be usable outside a single + block. */ + +#define ASM_L(name) LSYM_PREFIX "asm_%=_" #name + + +#if defined (__GNUC__) && HAVE_HOST_CPU_FAMILY_x86 +#if 0 +/* FIXME: Check that these actually improve things. + FIXME: Need a cld after each std. + FIXME: Can't have inputs in clobbered registers, must describe them as + dummy outputs, and add volatile. */ +#define MPN_COPY_INCR(DST, SRC, N) \ + __asm__ ("cld\n\trep\n\tmovsl" : : \ + "D" (DST), "S" (SRC), "c" (N) : \ + "cx", "di", "si", "memory") +#define MPN_COPY_DECR(DST, SRC, N) \ + __asm__ ("std\n\trep\n\tmovsl" : : \ + "D" ((DST) + (N) - 1), "S" ((SRC) + (N) - 1), "c" (N) : \ + "cx", "di", "si", "memory") +#endif +#endif + + +__GMP_DECLSPEC void __gmpz_aorsmul_1 (REGPARM_3_1 (mpz_ptr, mpz_srcptr, mp_limb_t, mp_size_t)) REGPARM_ATTR(1); +#define mpz_aorsmul_1(w,u,v,sub) __gmpz_aorsmul_1 (REGPARM_3_1 (w, u, v, sub)) + +#define mpz_n_pow_ui __gmpz_n_pow_ui +__GMP_DECLSPEC void mpz_n_pow_ui (mpz_ptr, mp_srcptr, mp_size_t, unsigned long); + + +#define mpn_addmul_1c __MPN(addmul_1c) +__GMP_DECLSPEC mp_limb_t mpn_addmul_1c (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t); + +#ifndef mpn_addmul_2 /* if not done with cpuvec in a fat binary */ +#define mpn_addmul_2 __MPN(addmul_2) +__GMP_DECLSPEC mp_limb_t mpn_addmul_2 (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr); +#endif + +#define mpn_addmul_3 __MPN(addmul_3) +__GMP_DECLSPEC mp_limb_t mpn_addmul_3 (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr); + +#define mpn_addmul_4 __MPN(addmul_4) +__GMP_DECLSPEC mp_limb_t mpn_addmul_4 (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr); + +#define mpn_addmul_5 __MPN(addmul_5) +__GMP_DECLSPEC mp_limb_t mpn_addmul_5 (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr); + +#define mpn_addmul_6 __MPN(addmul_6) +__GMP_DECLSPEC mp_limb_t mpn_addmul_6 (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr); + +#define mpn_addmul_7 __MPN(addmul_7) +__GMP_DECLSPEC mp_limb_t mpn_addmul_7 (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr); + +#define mpn_addmul_8 __MPN(addmul_8) +__GMP_DECLSPEC mp_limb_t mpn_addmul_8 (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr); + +/* Alternative entry point in mpn_addmul_2 for the benefit of mpn_sqr_basecase. */ +#define mpn_addmul_2s __MPN(addmul_2s) +__GMP_DECLSPEC mp_limb_t mpn_addmul_2s (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr); + +/* mpn_addlsh1_n(c,a,b,n), when it exists, sets {c,n} to {a,n}+2*{b,n}, and + returns the carry out (0, 1 or 2). Use _ip1 when a=c. */ +#ifndef mpn_addlsh1_n /* if not done with cpuvec in a fat binary */ +#define mpn_addlsh1_n __MPN(addlsh1_n) +__GMP_DECLSPEC mp_limb_t mpn_addlsh1_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#endif +#define mpn_addlsh1_nc __MPN(addlsh1_nc) +__GMP_DECLSPEC mp_limb_t mpn_addlsh1_nc (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t, mp_limb_t); +#if HAVE_NATIVE_mpn_addlsh1_n && ! HAVE_NATIVE_mpn_addlsh1_n_ip1 +#define mpn_addlsh1_n_ip1(dst,src,n) mpn_addlsh1_n(dst,dst,src,n) +#define HAVE_NATIVE_mpn_addlsh1_n_ip1 1 +#else +#define mpn_addlsh1_n_ip1 __MPN(addlsh1_n_ip1) +__GMP_DECLSPEC mp_limb_t mpn_addlsh1_n_ip1 (mp_ptr, mp_srcptr, mp_size_t); +#endif +#if HAVE_NATIVE_mpn_addlsh1_nc && ! HAVE_NATIVE_mpn_addlsh1_nc_ip1 +#define mpn_addlsh1_nc_ip1(dst,src,n,c) mpn_addlsh1_nc(dst,dst,src,n,c) +#define HAVE_NATIVE_mpn_addlsh1_nc_ip1 1 +#else +#define mpn_addlsh1_nc_ip1 __MPN(addlsh1_nc_ip1) +__GMP_DECLSPEC mp_limb_t mpn_addlsh1_nc_ip1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); +#endif + +#ifndef mpn_addlsh2_n /* if not done with cpuvec in a fat binary */ +/* mpn_addlsh2_n(c,a,b,n), when it exists, sets {c,n} to {a,n}+4*{b,n}, and + returns the carry out (0, ..., 4). Use _ip1 when a=c. */ +#define mpn_addlsh2_n __MPN(addlsh2_n) +__GMP_DECLSPEC mp_limb_t mpn_addlsh2_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#endif +#define mpn_addlsh2_nc __MPN(addlsh2_nc) +__GMP_DECLSPEC mp_limb_t mpn_addlsh2_nc (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t, mp_limb_t); +#if HAVE_NATIVE_mpn_addlsh2_n && ! HAVE_NATIVE_mpn_addlsh2_n_ip1 +#define mpn_addlsh2_n_ip1(dst,src,n) mpn_addlsh2_n(dst,dst,src,n) +#define HAVE_NATIVE_mpn_addlsh2_n_ip1 1 +#else +#define mpn_addlsh2_n_ip1 __MPN(addlsh2_n_ip1) +__GMP_DECLSPEC mp_limb_t mpn_addlsh2_n_ip1 (mp_ptr, mp_srcptr, mp_size_t); +#endif +#if HAVE_NATIVE_mpn_addlsh2_nc && ! HAVE_NATIVE_mpn_addlsh2_nc_ip1 +#define mpn_addlsh2_nc_ip1(dst,src,n,c) mpn_addlsh2_nc(dst,dst,src,n,c) +#define HAVE_NATIVE_mpn_addlsh2_nc_ip1 1 +#else +#define mpn_addlsh2_nc_ip1 __MPN(addlsh2_nc_ip1) +__GMP_DECLSPEC mp_limb_t mpn_addlsh2_nc_ip1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); +#endif + +/* mpn_addlsh_n(c,a,b,n,k), when it exists, sets {c,n} to {a,n}+2^k*{b,n}, and + returns the carry out (0, ..., 2^k). Use _ip1 when a=c. */ +#define mpn_addlsh_n __MPN(addlsh_n) +__GMP_DECLSPEC mp_limb_t mpn_addlsh_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t, unsigned int); +#define mpn_addlsh_nc __MPN(addlsh_nc) +__GMP_DECLSPEC mp_limb_t mpn_addlsh_nc (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t, unsigned int, mp_limb_t); +#if HAVE_NATIVE_mpn_addlsh_n && ! HAVE_NATIVE_mpn_addlsh_n_ip1 +#define mpn_addlsh_n_ip1(dst,src,n,s) mpn_addlsh_n(dst,dst,src,n,s) +#define HAVE_NATIVE_mpn_addlsh_n_ip1 1 +#else +#define mpn_addlsh_n_ip1 __MPN(addlsh_n_ip1) + __GMP_DECLSPEC mp_limb_t mpn_addlsh_n_ip1 (mp_ptr, mp_srcptr, mp_size_t, unsigned int); +#endif +#if HAVE_NATIVE_mpn_addlsh_nc && ! HAVE_NATIVE_mpn_addlsh_nc_ip1 +#define mpn_addlsh_nc_ip1(dst,src,n,s,c) mpn_addlsh_nc(dst,dst,src,n,s,c) +#define HAVE_NATIVE_mpn_addlsh_nc_ip1 1 +#else +#define mpn_addlsh_nc_ip1 __MPN(addlsh_nc_ip1) +__GMP_DECLSPEC mp_limb_t mpn_addlsh_nc_ip1 (mp_ptr, mp_srcptr, mp_size_t, unsigned int, mp_limb_t); +#endif + +#ifndef mpn_sublsh1_n /* if not done with cpuvec in a fat binary */ +/* mpn_sublsh1_n(c,a,b,n), when it exists, sets {c,n} to {a,n}-2*{b,n}, and + returns the borrow out (0, 1 or 2). Use _ip1 when a=c. */ +#define mpn_sublsh1_n __MPN(sublsh1_n) +__GMP_DECLSPEC mp_limb_t mpn_sublsh1_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#endif +#define mpn_sublsh1_nc __MPN(sublsh1_nc) +__GMP_DECLSPEC mp_limb_t mpn_sublsh1_nc (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t, mp_limb_t); +#if HAVE_NATIVE_mpn_sublsh1_n && ! HAVE_NATIVE_mpn_sublsh1_n_ip1 +#define mpn_sublsh1_n_ip1(dst,src,n) mpn_sublsh1_n(dst,dst,src,n) +#define HAVE_NATIVE_mpn_sublsh1_n_ip1 1 +#else +#define mpn_sublsh1_n_ip1 __MPN(sublsh1_n_ip1) +__GMP_DECLSPEC mp_limb_t mpn_sublsh1_n_ip1 (mp_ptr, mp_srcptr, mp_size_t); +#endif +#if HAVE_NATIVE_mpn_sublsh1_nc && ! HAVE_NATIVE_mpn_sublsh1_nc_ip1 +#define mpn_sublsh1_nc_ip1(dst,src,n,c) mpn_sublsh1_nc(dst,dst,src,n,c) +#define HAVE_NATIVE_mpn_sublsh1_nc_ip1 1 +#else +#define mpn_sublsh1_nc_ip1 __MPN(sublsh1_nc_ip1) +__GMP_DECLSPEC mp_limb_t mpn_sublsh1_nc_ip1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); +#endif + +/* mpn_rsblsh1_n(c,a,b,n), when it exists, sets {c,n} to 2*{b,n}-{a,n}, and + returns the carry out (-1, 0, 1). */ +#define mpn_rsblsh1_n __MPN(rsblsh1_n) +__GMP_DECLSPEC mp_limb_signed_t mpn_rsblsh1_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_rsblsh1_nc __MPN(rsblsh1_nc) +__GMP_DECLSPEC mp_limb_signed_t mpn_rsblsh1_nc (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t, mp_limb_t); + +/* mpn_sublsh2_n(c,a,b,n), when it exists, sets {c,n} to {a,n}-4*{b,n}, and + returns the borrow out (0, ..., 4). Use _ip1 when a=c. */ +#define mpn_sublsh2_n __MPN(sublsh2_n) +__GMP_DECLSPEC mp_limb_t mpn_sublsh2_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_sublsh2_nc __MPN(sublsh2_nc) +__GMP_DECLSPEC mp_limb_t mpn_sublsh2_nc (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t, mp_limb_t); +#if HAVE_NATIVE_mpn_sublsh2_n && ! HAVE_NATIVE_mpn_sublsh2_n_ip1 +#define mpn_sublsh2_n_ip1(dst,src,n) mpn_sublsh2_n(dst,dst,src,n) +#define HAVE_NATIVE_mpn_sublsh2_n_ip1 1 +#else +#define mpn_sublsh2_n_ip1 __MPN(sublsh2_n_ip1) +__GMP_DECLSPEC mp_limb_t mpn_sublsh2_n_ip1 (mp_ptr, mp_srcptr, mp_size_t); +#endif +#if HAVE_NATIVE_mpn_sublsh2_nc && ! HAVE_NATIVE_mpn_sublsh2_nc_ip1 +#define mpn_sublsh2_nc_ip1(dst,src,n,c) mpn_sublsh2_nc(dst,dst,src,n,c) +#define HAVE_NATIVE_mpn_sublsh2_nc_ip1 1 +#else +#define mpn_sublsh2_nc_ip1 __MPN(sublsh2_nc_ip1) +__GMP_DECLSPEC mp_limb_t mpn_sublsh2_nc_ip1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); +#endif + +/* mpn_sublsh_n(c,a,b,n,k), when it exists, sets {c,n} to {a,n}-2^k*{b,n}, and + returns the carry out (0, ..., 2^k). Use _ip1 when a=c. */ +#define mpn_sublsh_n __MPN(sublsh_n) +__GMP_DECLSPEC mp_limb_t mpn_sublsh_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t, unsigned int); +#if HAVE_NATIVE_mpn_sublsh_n && ! HAVE_NATIVE_mpn_sublsh_n_ip1 +#define mpn_sublsh_n_ip1(dst,src,n,s) mpn_sublsh_n(dst,dst,src,n,s) +#define HAVE_NATIVE_mpn_sublsh_n_ip1 1 +#else +#define mpn_sublsh_n_ip1 __MPN(sublsh_n_ip1) +__GMP_DECLSPEC mp_limb_t mpn_sublsh_n_ip1 (mp_ptr, mp_srcptr, mp_size_t, unsigned int); +#endif +#if HAVE_NATIVE_mpn_sublsh_nc && ! HAVE_NATIVE_mpn_sublsh_nc_ip1 +#define mpn_sublsh_nc_ip1(dst,src,n,s,c) mpn_sublsh_nc(dst,dst,src,n,s,c) +#define HAVE_NATIVE_mpn_sublsh_nc_ip1 1 +#else +#define mpn_sublsh_nc_ip1 __MPN(sublsh_nc_ip1) +__GMP_DECLSPEC mp_limb_t mpn_sublsh_nc_ip1 (mp_ptr, mp_srcptr, mp_size_t, unsigned int, mp_limb_t); +#endif + +/* mpn_rsblsh2_n(c,a,b,n), when it exists, sets {c,n} to 4*{b,n}-{a,n}, and + returns the carry out (-1, ..., 3). */ +#define mpn_rsblsh2_n __MPN(rsblsh2_n) +__GMP_DECLSPEC mp_limb_signed_t mpn_rsblsh2_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_rsblsh2_nc __MPN(rsblsh2_nc) +__GMP_DECLSPEC mp_limb_signed_t mpn_rsblsh2_nc (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t, mp_limb_t); + +/* mpn_rsblsh_n(c,a,b,n,k), when it exists, sets {c,n} to 2^k*{b,n}-{a,n}, and + returns the carry out (-1, 0, ..., 2^k-1). */ +#define mpn_rsblsh_n __MPN(rsblsh_n) +__GMP_DECLSPEC mp_limb_signed_t mpn_rsblsh_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t, unsigned int); +#define mpn_rsblsh_nc __MPN(rsblsh_nc) +__GMP_DECLSPEC mp_limb_signed_t mpn_rsblsh_nc (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t, unsigned int, mp_limb_t); + +/* mpn_rsh1add_n(c,a,b,n), when it exists, sets {c,n} to ({a,n} + {b,n}) >> 1, + and returns the bit rshifted out (0 or 1). */ +#define mpn_rsh1add_n __MPN(rsh1add_n) +__GMP_DECLSPEC mp_limb_t mpn_rsh1add_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_rsh1add_nc __MPN(rsh1add_nc) +__GMP_DECLSPEC mp_limb_t mpn_rsh1add_nc (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t, mp_limb_t); + +/* mpn_rsh1sub_n(c,a,b,n), when it exists, sets {c,n} to ({a,n} - {b,n}) >> 1, + and returns the bit rshifted out (0 or 1). If there's a borrow from the + subtract, it's stored as a 1 in the high bit of c[n-1], like a twos + complement negative. */ +#define mpn_rsh1sub_n __MPN(rsh1sub_n) +__GMP_DECLSPEC mp_limb_t mpn_rsh1sub_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_rsh1sub_nc __MPN(rsh1sub_nc) +__GMP_DECLSPEC mp_limb_t mpn_rsh1sub_nc (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t, mp_limb_t); + +#ifndef mpn_lshiftc /* if not done with cpuvec in a fat binary */ +#define mpn_lshiftc __MPN(lshiftc) +__GMP_DECLSPEC mp_limb_t mpn_lshiftc (mp_ptr, mp_srcptr, mp_size_t, unsigned int); +#endif + +#define mpn_add_err1_n __MPN(add_err1_n) +__GMP_DECLSPEC mp_limb_t mpn_add_err1_n (mp_ptr, mp_srcptr, mp_srcptr, mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_add_err2_n __MPN(add_err2_n) +__GMP_DECLSPEC mp_limb_t mpn_add_err2_n (mp_ptr, mp_srcptr, mp_srcptr, mp_ptr, mp_srcptr, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_add_err3_n __MPN(add_err3_n) +__GMP_DECLSPEC mp_limb_t mpn_add_err3_n (mp_ptr, mp_srcptr, mp_srcptr, mp_ptr, mp_srcptr, mp_srcptr, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_sub_err1_n __MPN(sub_err1_n) +__GMP_DECLSPEC mp_limb_t mpn_sub_err1_n (mp_ptr, mp_srcptr, mp_srcptr, mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_sub_err2_n __MPN(sub_err2_n) +__GMP_DECLSPEC mp_limb_t mpn_sub_err2_n (mp_ptr, mp_srcptr, mp_srcptr, mp_ptr, mp_srcptr, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_sub_err3_n __MPN(sub_err3_n) +__GMP_DECLSPEC mp_limb_t mpn_sub_err3_n (mp_ptr, mp_srcptr, mp_srcptr, mp_ptr, mp_srcptr, mp_srcptr, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_add_n_sub_n __MPN(add_n_sub_n) +__GMP_DECLSPEC mp_limb_t mpn_add_n_sub_n (mp_ptr, mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); + +#define mpn_add_n_sub_nc __MPN(add_n_sub_nc) +__GMP_DECLSPEC mp_limb_t mpn_add_n_sub_nc (mp_ptr, mp_ptr, mp_srcptr, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_addaddmul_1msb0 __MPN(addaddmul_1msb0) +__GMP_DECLSPEC mp_limb_t mpn_addaddmul_1msb0 (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t); + +#define mpn_divrem_1c __MPN(divrem_1c) +__GMP_DECLSPEC mp_limb_t mpn_divrem_1c (mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t); + +#define mpn_dump __MPN(dump) +__GMP_DECLSPEC void mpn_dump (mp_srcptr, mp_size_t); + +#define mpn_fib2_ui __MPN(fib2_ui) +__GMP_DECLSPEC mp_size_t mpn_fib2_ui (mp_ptr, mp_ptr, unsigned long); + +/* Remap names of internal mpn functions. */ +#define __clz_tab __MPN(clz_tab) +#define mpn_udiv_w_sdiv __MPN(udiv_w_sdiv) + +#define mpn_jacobi_base __MPN(jacobi_base) +__GMP_DECLSPEC int mpn_jacobi_base (mp_limb_t, mp_limb_t, int) ATTRIBUTE_CONST; + +#define mpn_jacobi_2 __MPN(jacobi_2) +__GMP_DECLSPEC int mpn_jacobi_2 (mp_srcptr, mp_srcptr, unsigned); + +#define mpn_jacobi_n __MPN(jacobi_n) +__GMP_DECLSPEC int mpn_jacobi_n (mp_ptr, mp_ptr, mp_size_t, unsigned); + +#define mpn_mod_1c __MPN(mod_1c) +__GMP_DECLSPEC mp_limb_t mpn_mod_1c (mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_mul_1c __MPN(mul_1c) +__GMP_DECLSPEC mp_limb_t mpn_mul_1c (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t); + +#define mpn_mul_2 __MPN(mul_2) +__GMP_DECLSPEC mp_limb_t mpn_mul_2 (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr); + +#define mpn_mul_3 __MPN(mul_3) +__GMP_DECLSPEC mp_limb_t mpn_mul_3 (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr); + +#define mpn_mul_4 __MPN(mul_4) +__GMP_DECLSPEC mp_limb_t mpn_mul_4 (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr); + +#define mpn_mul_5 __MPN(mul_5) +__GMP_DECLSPEC mp_limb_t mpn_mul_5 (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr); + +#define mpn_mul_6 __MPN(mul_6) +__GMP_DECLSPEC mp_limb_t mpn_mul_6 (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr); + +#ifndef mpn_mul_basecase /* if not done with cpuvec in a fat binary */ +#define mpn_mul_basecase __MPN(mul_basecase) +__GMP_DECLSPEC void mpn_mul_basecase (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); +#endif + +#define mpn_mullo_n __MPN(mullo_n) +__GMP_DECLSPEC void mpn_mullo_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); + +#ifndef mpn_mullo_basecase /* if not done with cpuvec in a fat binary */ +#define mpn_mullo_basecase __MPN(mullo_basecase) +__GMP_DECLSPEC void mpn_mullo_basecase (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#endif + +#ifndef mpn_sqr_basecase /* if not done with cpuvec in a fat binary */ +#define mpn_sqr_basecase __MPN(sqr_basecase) +__GMP_DECLSPEC void mpn_sqr_basecase (mp_ptr, mp_srcptr, mp_size_t); +#endif + +#define mpn_sqrlo __MPN(sqrlo) +__GMP_DECLSPEC void mpn_sqrlo (mp_ptr, mp_srcptr, mp_size_t); + +#define mpn_sqrlo_basecase __MPN(sqrlo_basecase) +__GMP_DECLSPEC void mpn_sqrlo_basecase (mp_ptr, mp_srcptr, mp_size_t); + +#define mpn_mulmid_basecase __MPN(mulmid_basecase) +__GMP_DECLSPEC void mpn_mulmid_basecase (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); + +#define mpn_mulmid_n __MPN(mulmid_n) +__GMP_DECLSPEC void mpn_mulmid_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); + +#define mpn_mulmid __MPN(mulmid) +__GMP_DECLSPEC void mpn_mulmid (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); + +#define mpn_submul_1c __MPN(submul_1c) +__GMP_DECLSPEC mp_limb_t mpn_submul_1c (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t); + +#ifndef mpn_redc_1 /* if not done with cpuvec in a fat binary */ +#define mpn_redc_1 __MPN(redc_1) +__GMP_DECLSPEC mp_limb_t mpn_redc_1 (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); +#endif + +#ifndef mpn_redc_2 /* if not done with cpuvec in a fat binary */ +#define mpn_redc_2 __MPN(redc_2) +__GMP_DECLSPEC mp_limb_t mpn_redc_2 (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_srcptr); +#endif + +#define mpn_redc_n __MPN(redc_n) +__GMP_DECLSPEC void mpn_redc_n (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_srcptr); + + +#ifndef mpn_mod_1_1p_cps /* if not done with cpuvec in a fat binary */ +#define mpn_mod_1_1p_cps __MPN(mod_1_1p_cps) +__GMP_DECLSPEC void mpn_mod_1_1p_cps (mp_limb_t [4], mp_limb_t); +#endif +#ifndef mpn_mod_1_1p /* if not done with cpuvec in a fat binary */ +#define mpn_mod_1_1p __MPN(mod_1_1p) +__GMP_DECLSPEC mp_limb_t mpn_mod_1_1p (mp_srcptr, mp_size_t, mp_limb_t, const mp_limb_t [4]) __GMP_ATTRIBUTE_PURE; +#endif + +#ifndef mpn_mod_1s_2p_cps /* if not done with cpuvec in a fat binary */ +#define mpn_mod_1s_2p_cps __MPN(mod_1s_2p_cps) +__GMP_DECLSPEC void mpn_mod_1s_2p_cps (mp_limb_t [5], mp_limb_t); +#endif +#ifndef mpn_mod_1s_2p /* if not done with cpuvec in a fat binary */ +#define mpn_mod_1s_2p __MPN(mod_1s_2p) +__GMP_DECLSPEC mp_limb_t mpn_mod_1s_2p (mp_srcptr, mp_size_t, mp_limb_t, const mp_limb_t [5]) __GMP_ATTRIBUTE_PURE; +#endif + +#ifndef mpn_mod_1s_3p_cps /* if not done with cpuvec in a fat binary */ +#define mpn_mod_1s_3p_cps __MPN(mod_1s_3p_cps) +__GMP_DECLSPEC void mpn_mod_1s_3p_cps (mp_limb_t [6], mp_limb_t); +#endif +#ifndef mpn_mod_1s_3p /* if not done with cpuvec in a fat binary */ +#define mpn_mod_1s_3p __MPN(mod_1s_3p) +__GMP_DECLSPEC mp_limb_t mpn_mod_1s_3p (mp_srcptr, mp_size_t, mp_limb_t, const mp_limb_t [6]) __GMP_ATTRIBUTE_PURE; +#endif + +#ifndef mpn_mod_1s_4p_cps /* if not done with cpuvec in a fat binary */ +#define mpn_mod_1s_4p_cps __MPN(mod_1s_4p_cps) +__GMP_DECLSPEC void mpn_mod_1s_4p_cps (mp_limb_t [7], mp_limb_t); +#endif +#ifndef mpn_mod_1s_4p /* if not done with cpuvec in a fat binary */ +#define mpn_mod_1s_4p __MPN(mod_1s_4p) +__GMP_DECLSPEC mp_limb_t mpn_mod_1s_4p (mp_srcptr, mp_size_t, mp_limb_t, const mp_limb_t [7]) __GMP_ATTRIBUTE_PURE; +#endif + +#define mpn_bc_mulmod_bnm1 __MPN(bc_mulmod_bnm1) +__GMP_DECLSPEC void mpn_bc_mulmod_bnm1 (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_mulmod_bnm1 __MPN(mulmod_bnm1) +__GMP_DECLSPEC void mpn_mulmod_bnm1 (mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_mulmod_bnm1_next_size __MPN(mulmod_bnm1_next_size) +__GMP_DECLSPEC mp_size_t mpn_mulmod_bnm1_next_size (mp_size_t) ATTRIBUTE_CONST; +static inline mp_size_t +mpn_mulmod_bnm1_itch (mp_size_t rn, mp_size_t an, mp_size_t bn) { + mp_size_t n, itch; + n = rn >> 1; + itch = rn + 4 + + (an > n ? (bn > n ? rn : n) : 0); + return itch; +} + +#define mpn_sqrmod_bnm1 __MPN(sqrmod_bnm1) +__GMP_DECLSPEC void mpn_sqrmod_bnm1 (mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_sqrmod_bnm1_next_size __MPN(sqrmod_bnm1_next_size) +__GMP_DECLSPEC mp_size_t mpn_sqrmod_bnm1_next_size (mp_size_t) ATTRIBUTE_CONST; +static inline mp_size_t +mpn_sqrmod_bnm1_itch (mp_size_t rn, mp_size_t an) { + mp_size_t n, itch; + n = rn >> 1; + itch = rn + 3 + + (an > n ? an : 0); + return itch; +} + +typedef __gmp_randstate_struct *gmp_randstate_ptr; +typedef const __gmp_randstate_struct *gmp_randstate_srcptr; + +/* Pseudo-random number generator function pointers structure. */ +typedef struct { + void (*randseed_fn) (gmp_randstate_t, mpz_srcptr); + void (*randget_fn) (gmp_randstate_t, mp_ptr, unsigned long int); + void (*randclear_fn) (gmp_randstate_t); + void (*randiset_fn) (gmp_randstate_ptr, gmp_randstate_srcptr); +} gmp_randfnptr_t; + +/* Macro to obtain a void pointer to the function pointers structure. */ +#define RNG_FNPTR(rstate) ((rstate)->_mp_algdata._mp_lc) + +/* Macro to obtain a pointer to the generator's state. + When used as a lvalue the rvalue needs to be cast to mp_ptr. */ +#define RNG_STATE(rstate) ((rstate)->_mp_seed->_mp_d) + +/* Write a given number of random bits to rp. */ +#define _gmp_rand(rp, state, bits) \ + do { \ + gmp_randstate_ptr __rstate = (state); \ + (*((gmp_randfnptr_t *) RNG_FNPTR (__rstate))->randget_fn) \ + (__rstate, rp, bits); \ + } while (0) + +__GMP_DECLSPEC void __gmp_randinit_mt_noseed (gmp_randstate_t); + + +/* __gmp_rands is the global state for the old-style random functions, and + is also used in the test programs (hence the __GMP_DECLSPEC). + + There's no seeding here, so mpz_random etc will generate the same + sequence every time. This is not unlike the C library random functions + if you don't seed them, so perhaps it's acceptable. Digging up a seed + from /dev/random or the like would work on many systems, but might + encourage a false confidence, since it'd be pretty much impossible to do + something that would work reliably everywhere. In any case the new style + functions are recommended to applications which care about randomness, so + the old functions aren't too important. */ + +__GMP_DECLSPEC extern char __gmp_rands_initialized; +__GMP_DECLSPEC extern gmp_randstate_t __gmp_rands; + +#define RANDS \ + ((__gmp_rands_initialized ? 0 \ + : (__gmp_rands_initialized = 1, \ + __gmp_randinit_mt_noseed (__gmp_rands), 0)), \ + __gmp_rands) + +/* this is used by the test programs, to free memory */ +#define RANDS_CLEAR() \ + do { \ + if (__gmp_rands_initialized) \ + { \ + __gmp_rands_initialized = 0; \ + gmp_randclear (__gmp_rands); \ + } \ + } while (0) + + +/* For a threshold between algorithms A and B, size>=thresh is where B + should be used. Special value MP_SIZE_T_MAX means only ever use A, or + value 0 means only ever use B. The tests for these special values will + be compile-time constants, so the compiler should be able to eliminate + the code for the unwanted algorithm. */ + +#if ! defined (__GNUC__) || __GNUC__ < 2 +#define ABOVE_THRESHOLD(size,thresh) \ + ((thresh) == 0 \ + || ((thresh) != MP_SIZE_T_MAX \ + && (size) >= (thresh))) +#else +#define ABOVE_THRESHOLD(size,thresh) \ + ((__builtin_constant_p (thresh) && (thresh) == 0) \ + || (!(__builtin_constant_p (thresh) && (thresh) == MP_SIZE_T_MAX) \ + && (size) >= (thresh))) +#endif +#define BELOW_THRESHOLD(size,thresh) (! ABOVE_THRESHOLD (size, thresh)) + +/* The minimal supported value for Toom22 depends also on Toom32 and + Toom42 implementations. */ +#define MPN_TOOM22_MUL_MINSIZE 6 +#define MPN_TOOM2_SQR_MINSIZE 4 + +#define MPN_TOOM33_MUL_MINSIZE 17 +#define MPN_TOOM3_SQR_MINSIZE 17 + +#define MPN_TOOM44_MUL_MINSIZE 30 +#define MPN_TOOM4_SQR_MINSIZE 30 + +#define MPN_TOOM6H_MUL_MINSIZE 46 +#define MPN_TOOM6_SQR_MINSIZE 46 + +#define MPN_TOOM8H_MUL_MINSIZE 86 +#define MPN_TOOM8_SQR_MINSIZE 86 + +#define MPN_TOOM32_MUL_MINSIZE 10 +#define MPN_TOOM42_MUL_MINSIZE 10 +#define MPN_TOOM43_MUL_MINSIZE 25 +#define MPN_TOOM53_MUL_MINSIZE 17 +#define MPN_TOOM54_MUL_MINSIZE 31 +#define MPN_TOOM63_MUL_MINSIZE 49 + +#define MPN_TOOM42_MULMID_MINSIZE 4 + +#define mpn_sqr_diagonal __MPN(sqr_diagonal) +__GMP_DECLSPEC void mpn_sqr_diagonal (mp_ptr, mp_srcptr, mp_size_t); + +#define mpn_sqr_diag_addlsh1 __MPN(sqr_diag_addlsh1) +__GMP_DECLSPEC void mpn_sqr_diag_addlsh1 (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); + +#define mpn_toom_interpolate_5pts __MPN(toom_interpolate_5pts) +__GMP_DECLSPEC void mpn_toom_interpolate_5pts (mp_ptr, mp_ptr, mp_ptr, mp_size_t, mp_size_t, int, mp_limb_t); + +enum toom6_flags {toom6_all_pos = 0, toom6_vm1_neg = 1, toom6_vm2_neg = 2}; +#define mpn_toom_interpolate_6pts __MPN(toom_interpolate_6pts) +__GMP_DECLSPEC void mpn_toom_interpolate_6pts (mp_ptr, mp_size_t, enum toom6_flags, mp_ptr, mp_ptr, mp_ptr, mp_size_t); + +enum toom7_flags { toom7_w1_neg = 1, toom7_w3_neg = 2 }; +#define mpn_toom_interpolate_7pts __MPN(toom_interpolate_7pts) +__GMP_DECLSPEC void mpn_toom_interpolate_7pts (mp_ptr, mp_size_t, enum toom7_flags, mp_ptr, mp_ptr, mp_ptr, mp_ptr, mp_size_t, mp_ptr); + +#define mpn_toom_interpolate_8pts __MPN(toom_interpolate_8pts) +__GMP_DECLSPEC void mpn_toom_interpolate_8pts (mp_ptr, mp_size_t, mp_ptr, mp_ptr, mp_size_t, mp_ptr); + +#define mpn_toom_interpolate_12pts __MPN(toom_interpolate_12pts) +__GMP_DECLSPEC void mpn_toom_interpolate_12pts (mp_ptr, mp_ptr, mp_ptr, mp_ptr, mp_size_t, mp_size_t, int, mp_ptr); + +#define mpn_toom_interpolate_16pts __MPN(toom_interpolate_16pts) +__GMP_DECLSPEC void mpn_toom_interpolate_16pts (mp_ptr, mp_ptr, mp_ptr, mp_ptr, mp_ptr, mp_size_t, mp_size_t, int, mp_ptr); + +#define mpn_toom_couple_handling __MPN(toom_couple_handling) +__GMP_DECLSPEC void mpn_toom_couple_handling (mp_ptr, mp_size_t, mp_ptr, int, mp_size_t, int, int); + +#define mpn_toom_eval_dgr3_pm1 __MPN(toom_eval_dgr3_pm1) +__GMP_DECLSPEC int mpn_toom_eval_dgr3_pm1 (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_size_t, mp_ptr); + +#define mpn_toom_eval_dgr3_pm2 __MPN(toom_eval_dgr3_pm2) +__GMP_DECLSPEC int mpn_toom_eval_dgr3_pm2 (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_size_t, mp_ptr); + +#define mpn_toom_eval_pm1 __MPN(toom_eval_pm1) +__GMP_DECLSPEC int mpn_toom_eval_pm1 (mp_ptr, mp_ptr, unsigned, mp_srcptr, mp_size_t, mp_size_t, mp_ptr); + +#define mpn_toom_eval_pm2 __MPN(toom_eval_pm2) +__GMP_DECLSPEC int mpn_toom_eval_pm2 (mp_ptr, mp_ptr, unsigned, mp_srcptr, mp_size_t, mp_size_t, mp_ptr); + +#define mpn_toom_eval_pm2exp __MPN(toom_eval_pm2exp) +__GMP_DECLSPEC int mpn_toom_eval_pm2exp (mp_ptr, mp_ptr, unsigned, mp_srcptr, mp_size_t, mp_size_t, unsigned, mp_ptr); + +#define mpn_toom_eval_pm2rexp __MPN(toom_eval_pm2rexp) +__GMP_DECLSPEC int mpn_toom_eval_pm2rexp (mp_ptr, mp_ptr, unsigned, mp_srcptr, mp_size_t, mp_size_t, unsigned, mp_ptr); + +#define mpn_toom22_mul __MPN(toom22_mul) +__GMP_DECLSPEC void mpn_toom22_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); + +#define mpn_toom32_mul __MPN(toom32_mul) +__GMP_DECLSPEC void mpn_toom32_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); + +#define mpn_toom42_mul __MPN(toom42_mul) +__GMP_DECLSPEC void mpn_toom42_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); + +#define mpn_toom52_mul __MPN(toom52_mul) +__GMP_DECLSPEC void mpn_toom52_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); + +#define mpn_toom62_mul __MPN(toom62_mul) +__GMP_DECLSPEC void mpn_toom62_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); + +#define mpn_toom2_sqr __MPN(toom2_sqr) +__GMP_DECLSPEC void mpn_toom2_sqr (mp_ptr, mp_srcptr, mp_size_t, mp_ptr); + +#define mpn_toom33_mul __MPN(toom33_mul) +__GMP_DECLSPEC void mpn_toom33_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); + +#define mpn_toom43_mul __MPN(toom43_mul) +__GMP_DECLSPEC void mpn_toom43_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); + +#define mpn_toom53_mul __MPN(toom53_mul) +__GMP_DECLSPEC void mpn_toom53_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); + +#define mpn_toom54_mul __MPN(toom54_mul) +__GMP_DECLSPEC void mpn_toom54_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); + +#define mpn_toom63_mul __MPN(toom63_mul) +__GMP_DECLSPEC void mpn_toom63_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); + +#define mpn_toom3_sqr __MPN(toom3_sqr) +__GMP_DECLSPEC void mpn_toom3_sqr (mp_ptr, mp_srcptr, mp_size_t, mp_ptr); + +#define mpn_toom44_mul __MPN(toom44_mul) +__GMP_DECLSPEC void mpn_toom44_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); + +#define mpn_toom4_sqr __MPN(toom4_sqr) +__GMP_DECLSPEC void mpn_toom4_sqr (mp_ptr, mp_srcptr, mp_size_t, mp_ptr); + +#define mpn_toom6h_mul __MPN(toom6h_mul) +__GMP_DECLSPEC void mpn_toom6h_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); + +#define mpn_toom6_sqr __MPN(toom6_sqr) +__GMP_DECLSPEC void mpn_toom6_sqr (mp_ptr, mp_srcptr, mp_size_t, mp_ptr); + +#define mpn_toom8h_mul __MPN(toom8h_mul) +__GMP_DECLSPEC void mpn_toom8h_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); + +#define mpn_toom8_sqr __MPN(toom8_sqr) +__GMP_DECLSPEC void mpn_toom8_sqr (mp_ptr, mp_srcptr, mp_size_t, mp_ptr); + +#define mpn_toom42_mulmid __MPN(toom42_mulmid) +__GMP_DECLSPEC void mpn_toom42_mulmid (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t, mp_ptr); + +#define mpn_fft_best_k __MPN(fft_best_k) +__GMP_DECLSPEC int mpn_fft_best_k (mp_size_t, int) ATTRIBUTE_CONST; + +#define mpn_mul_fft __MPN(mul_fft) +__GMP_DECLSPEC mp_limb_t mpn_mul_fft (mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, int); + +#define mpn_mul_fft_full __MPN(mul_fft_full) +__GMP_DECLSPEC void mpn_mul_fft_full (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); + +#define mpn_nussbaumer_mul __MPN(nussbaumer_mul) +__GMP_DECLSPEC void mpn_nussbaumer_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); + +#define mpn_fft_next_size __MPN(fft_next_size) +__GMP_DECLSPEC mp_size_t mpn_fft_next_size (mp_size_t, int) ATTRIBUTE_CONST; + +#define mpn_div_qr_1n_pi1 __MPN(div_qr_1n_pi1) + __GMP_DECLSPEC mp_limb_t mpn_div_qr_1n_pi1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t, mp_limb_t); + +#define mpn_div_qr_2n_pi1 __MPN(div_qr_2n_pi1) + __GMP_DECLSPEC mp_limb_t mpn_div_qr_2n_pi1 (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t, mp_limb_t); + +#define mpn_div_qr_2u_pi1 __MPN(div_qr_2u_pi1) + __GMP_DECLSPEC mp_limb_t mpn_div_qr_2u_pi1 (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t, int, mp_limb_t); + +#define mpn_sbpi1_div_qr __MPN(sbpi1_div_qr) +__GMP_DECLSPEC mp_limb_t mpn_sbpi1_div_qr (mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_sbpi1_div_q __MPN(sbpi1_div_q) +__GMP_DECLSPEC mp_limb_t mpn_sbpi1_div_q (mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_sbpi1_divappr_q __MPN(sbpi1_divappr_q) +__GMP_DECLSPEC mp_limb_t mpn_sbpi1_divappr_q (mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_dcpi1_div_qr __MPN(dcpi1_div_qr) +__GMP_DECLSPEC mp_limb_t mpn_dcpi1_div_qr (mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, gmp_pi1_t *); +#define mpn_dcpi1_div_qr_n __MPN(dcpi1_div_qr_n) +__GMP_DECLSPEC mp_limb_t mpn_dcpi1_div_qr_n (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, gmp_pi1_t *, mp_ptr); + +#define mpn_dcpi1_div_q __MPN(dcpi1_div_q) +__GMP_DECLSPEC mp_limb_t mpn_dcpi1_div_q (mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, gmp_pi1_t *); + +#define mpn_dcpi1_divappr_q __MPN(dcpi1_divappr_q) +__GMP_DECLSPEC mp_limb_t mpn_dcpi1_divappr_q (mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, gmp_pi1_t *); +#define mpn_dcpi1_divappr_q_n __MPN(dcpi1_divappr_q_n) +__GMP_DECLSPEC mp_limb_t mpn_dcpi1_divappr_q_n (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, gmp_pi1_t *, mp_ptr); + +#define mpn_mu_div_qr __MPN(mu_div_qr) +__GMP_DECLSPEC mp_limb_t mpn_mu_div_qr (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_mu_div_qr_itch __MPN(mu_div_qr_itch) +__GMP_DECLSPEC mp_size_t mpn_mu_div_qr_itch (mp_size_t, mp_size_t, int) ATTRIBUTE_CONST; +#define mpn_mu_div_qr_choose_in __MPN(mu_div_qr_choose_in) +__GMP_DECLSPEC mp_size_t mpn_mu_div_qr_choose_in (mp_size_t, mp_size_t, int); + +#define mpn_preinv_mu_div_qr __MPN(preinv_mu_div_qr) +__GMP_DECLSPEC mp_limb_t mpn_preinv_mu_div_qr (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_preinv_mu_div_qr_itch __MPN(preinv_mu_div_qr_itch) +__GMP_DECLSPEC mp_size_t mpn_preinv_mu_div_qr_itch (mp_size_t, mp_size_t, mp_size_t) ATTRIBUTE_CONST; + +#define mpn_mu_divappr_q __MPN(mu_divappr_q) +__GMP_DECLSPEC mp_limb_t mpn_mu_divappr_q (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_mu_divappr_q_itch __MPN(mu_divappr_q_itch) +__GMP_DECLSPEC mp_size_t mpn_mu_divappr_q_itch (mp_size_t, mp_size_t, int) ATTRIBUTE_CONST; +#define mpn_mu_divappr_q_choose_in __MPN(mu_divappr_q_choose_in) +__GMP_DECLSPEC mp_size_t mpn_mu_divappr_q_choose_in (mp_size_t, mp_size_t, int); + +#define mpn_preinv_mu_divappr_q __MPN(preinv_mu_divappr_q) +__GMP_DECLSPEC mp_limb_t mpn_preinv_mu_divappr_q (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); + +#define mpn_mu_div_q __MPN(mu_div_q) +__GMP_DECLSPEC mp_limb_t mpn_mu_div_q (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_mu_div_q_itch __MPN(mu_div_q_itch) +__GMP_DECLSPEC mp_size_t mpn_mu_div_q_itch (mp_size_t, mp_size_t, int) ATTRIBUTE_CONST; + +#define mpn_div_q __MPN(div_q) +__GMP_DECLSPEC void mpn_div_q (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); + +#define mpn_invert __MPN(invert) +__GMP_DECLSPEC void mpn_invert (mp_ptr, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_invert_itch(n) mpn_invertappr_itch(n) + +#define mpn_ni_invertappr __MPN(ni_invertappr) +__GMP_DECLSPEC mp_limb_t mpn_ni_invertappr (mp_ptr, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_invertappr __MPN(invertappr) +__GMP_DECLSPEC mp_limb_t mpn_invertappr (mp_ptr, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_invertappr_itch(n) (2 * (n)) + +#define mpn_binvert __MPN(binvert) +__GMP_DECLSPEC void mpn_binvert (mp_ptr, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_binvert_itch __MPN(binvert_itch) +__GMP_DECLSPEC mp_size_t mpn_binvert_itch (mp_size_t) ATTRIBUTE_CONST; + +#define mpn_bdiv_q_1 __MPN(bdiv_q_1) +__GMP_DECLSPEC mp_limb_t mpn_bdiv_q_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_pi1_bdiv_q_1 __MPN(pi1_bdiv_q_1) +__GMP_DECLSPEC mp_limb_t mpn_pi1_bdiv_q_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t, int); + +#define mpn_sbpi1_bdiv_qr __MPN(sbpi1_bdiv_qr) +__GMP_DECLSPEC mp_limb_t mpn_sbpi1_bdiv_qr (mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_sbpi1_bdiv_q __MPN(sbpi1_bdiv_q) +__GMP_DECLSPEC void mpn_sbpi1_bdiv_q (mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_dcpi1_bdiv_qr __MPN(dcpi1_bdiv_qr) +__GMP_DECLSPEC mp_limb_t mpn_dcpi1_bdiv_qr (mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t); +#define mpn_dcpi1_bdiv_qr_n_itch __MPN(dcpi1_bdiv_qr_n_itch) +__GMP_DECLSPEC mp_size_t mpn_dcpi1_bdiv_qr_n_itch (mp_size_t) ATTRIBUTE_CONST; + +#define mpn_dcpi1_bdiv_qr_n __MPN(dcpi1_bdiv_qr_n) +__GMP_DECLSPEC mp_limb_t mpn_dcpi1_bdiv_qr_n (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_ptr); +#define mpn_dcpi1_bdiv_q __MPN(dcpi1_bdiv_q) +__GMP_DECLSPEC void mpn_dcpi1_bdiv_q (mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_dcpi1_bdiv_q_n __MPN(dcpi1_bdiv_q_n) +__GMP_DECLSPEC void mpn_dcpi1_bdiv_q_n (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_ptr); +#define mpn_dcpi1_bdiv_q_n_itch __MPN(dcpi1_bdiv_q_n_itch) +__GMP_DECLSPEC mp_size_t mpn_dcpi1_bdiv_q_n_itch (mp_size_t) ATTRIBUTE_CONST; + +#define mpn_mu_bdiv_qr __MPN(mu_bdiv_qr) +__GMP_DECLSPEC mp_limb_t mpn_mu_bdiv_qr (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_mu_bdiv_qr_itch __MPN(mu_bdiv_qr_itch) +__GMP_DECLSPEC mp_size_t mpn_mu_bdiv_qr_itch (mp_size_t, mp_size_t) ATTRIBUTE_CONST; + +#define mpn_mu_bdiv_q __MPN(mu_bdiv_q) +__GMP_DECLSPEC void mpn_mu_bdiv_q (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_mu_bdiv_q_itch __MPN(mu_bdiv_q_itch) +__GMP_DECLSPEC mp_size_t mpn_mu_bdiv_q_itch (mp_size_t, mp_size_t) ATTRIBUTE_CONST; + +#define mpn_bdiv_qr __MPN(bdiv_qr) +__GMP_DECLSPEC mp_limb_t mpn_bdiv_qr (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_bdiv_qr_itch __MPN(bdiv_qr_itch) +__GMP_DECLSPEC mp_size_t mpn_bdiv_qr_itch (mp_size_t, mp_size_t) ATTRIBUTE_CONST; + +#define mpn_bdiv_q __MPN(bdiv_q) +__GMP_DECLSPEC void mpn_bdiv_q (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_bdiv_q_itch __MPN(bdiv_q_itch) +__GMP_DECLSPEC mp_size_t mpn_bdiv_q_itch (mp_size_t, mp_size_t) ATTRIBUTE_CONST; + +#define mpn_divexact __MPN(divexact) +__GMP_DECLSPEC void mpn_divexact (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); +#define mpn_divexact_itch __MPN(divexact_itch) +__GMP_DECLSPEC mp_size_t mpn_divexact_itch (mp_size_t, mp_size_t) ATTRIBUTE_CONST; + +#ifndef mpn_bdiv_dbm1c /* if not done with cpuvec in a fat binary */ +#define mpn_bdiv_dbm1c __MPN(bdiv_dbm1c) +__GMP_DECLSPEC mp_limb_t mpn_bdiv_dbm1c (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t); +#endif + +#define mpn_bdiv_dbm1(dst, src, size, divisor) \ + mpn_bdiv_dbm1c (dst, src, size, divisor, __GMP_CAST (mp_limb_t, 0)) + +#define mpn_powm __MPN(powm) +__GMP_DECLSPEC void mpn_powm (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_powlo __MPN(powlo) +__GMP_DECLSPEC void mpn_powlo (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t, mp_size_t, mp_ptr); + +#define mpn_sec_pi1_div_qr __MPN(sec_pi1_div_qr) +__GMP_DECLSPEC mp_limb_t mpn_sec_pi1_div_qr (mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t, mp_ptr); +#define mpn_sec_pi1_div_r __MPN(sec_pi1_div_r) +__GMP_DECLSPEC void mpn_sec_pi1_div_r (mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t, mp_ptr); + + +/* Override mpn_addlsh1_n, mpn_addlsh2_n, mpn_sublsh1_n, etc with mpn_addlsh_n, + etc when !HAVE_NATIVE the former but HAVE_NATIVE_ the latter. We then lie + and say these macros represent native functions, but leave a trace by using + the value 2 rather than 1. */ + +#if HAVE_NATIVE_mpn_addlsh_n && ! HAVE_NATIVE_mpn_addlsh1_n +#undef mpn_addlsh1_n +#define mpn_addlsh1_n(a,b,c,d) mpn_addlsh_n(a,b,c,d,1) +#define HAVE_NATIVE_mpn_addlsh1_n 2 +#endif + +#if HAVE_NATIVE_mpn_addlsh_n && ! HAVE_NATIVE_mpn_addlsh2_n +#undef mpn_addlsh2_n +#define mpn_addlsh2_n(a,b,c,d) mpn_addlsh_n(a,b,c,d,2) +#define HAVE_NATIVE_mpn_addlsh2_n 2 +#endif + +#if HAVE_NATIVE_mpn_sublsh_n && ! HAVE_NATIVE_mpn_sublsh1_n +#undef mpn_sublsh1_n +#define mpn_sublsh1_n(a,b,c,d) mpn_sublsh_n(a,b,c,d,1) +#define HAVE_NATIVE_mpn_sublsh1_n 2 +#endif + +#if HAVE_NATIVE_mpn_sublsh_n && ! HAVE_NATIVE_mpn_sublsh2_n +#undef mpn_sublsh2_n +#define mpn_sublsh2_n(a,b,c,d) mpn_sublsh_n(a,b,c,d,2) +#define HAVE_NATIVE_mpn_sublsh2_n 2 +#endif + +#if HAVE_NATIVE_mpn_rsblsh_n && ! HAVE_NATIVE_mpn_rsblsh1_n +#undef mpn_rsblsh1_n +#define mpn_rsblsh1_n(a,b,c,d) mpn_rsblsh_n(a,b,c,d,1) +#define HAVE_NATIVE_mpn_rsblsh1_n 2 +#endif + +#if HAVE_NATIVE_mpn_rsblsh_n && ! HAVE_NATIVE_mpn_rsblsh2_n +#undef mpn_rsblsh2_n +#define mpn_rsblsh2_n(a,b,c,d) mpn_rsblsh_n(a,b,c,d,2) +#define HAVE_NATIVE_mpn_rsblsh2_n 2 +#endif + + +#ifndef DIVEXACT_BY3_METHOD +#if GMP_NUMB_BITS % 2 == 0 && ! defined (HAVE_NATIVE_mpn_divexact_by3c) +#define DIVEXACT_BY3_METHOD 0 /* default to using mpn_bdiv_dbm1c */ +#else +#define DIVEXACT_BY3_METHOD 1 +#endif +#endif + +#if DIVEXACT_BY3_METHOD == 0 +#undef mpn_divexact_by3 +#define mpn_divexact_by3(dst,src,size) \ + (3 & mpn_bdiv_dbm1 (dst, src, size, __GMP_CAST (mp_limb_t, GMP_NUMB_MASK / 3))) +/* override mpn_divexact_by3c defined in gmp.h */ +/* +#undef mpn_divexact_by3c +#define mpn_divexact_by3c(dst,src,size,cy) \ + (3 & mpn_bdiv_dbm1c (dst, src, size, __GMP_CAST (mp_limb_t, GMP_NUMB_MASK / 3, GMP_NUMB_MASK / 3 * cy))) +*/ +#endif + +#if GMP_NUMB_BITS % 4 == 0 +#define mpn_divexact_by5(dst,src,size) \ + (7 & 3 * mpn_bdiv_dbm1 (dst, src, size, __GMP_CAST (mp_limb_t, GMP_NUMB_MASK / 5))) +#endif + +#if GMP_NUMB_BITS % 3 == 0 +#define mpn_divexact_by7(dst,src,size) \ + (7 & 1 * mpn_bdiv_dbm1 (dst, src, size, __GMP_CAST (mp_limb_t, GMP_NUMB_MASK / 7))) +#endif + +#if GMP_NUMB_BITS % 6 == 0 +#define mpn_divexact_by9(dst,src,size) \ + (15 & 7 * mpn_bdiv_dbm1 (dst, src, size, __GMP_CAST (mp_limb_t, GMP_NUMB_MASK / 9))) +#endif + +#if GMP_NUMB_BITS % 10 == 0 +#define mpn_divexact_by11(dst,src,size) \ + (15 & 5 * mpn_bdiv_dbm1 (dst, src, size, __GMP_CAST (mp_limb_t, GMP_NUMB_MASK / 11))) +#endif + +#if GMP_NUMB_BITS % 12 == 0 +#define mpn_divexact_by13(dst,src,size) \ + (15 & 3 * mpn_bdiv_dbm1 (dst, src, size, __GMP_CAST (mp_limb_t, GMP_NUMB_MASK / 13))) +#endif + +#if GMP_NUMB_BITS % 4 == 0 +#define mpn_divexact_by15(dst,src,size) \ + (15 & 1 * mpn_bdiv_dbm1 (dst, src, size, __GMP_CAST (mp_limb_t, GMP_NUMB_MASK / 15))) +#endif + +#define mpz_divexact_gcd __gmpz_divexact_gcd +__GMP_DECLSPEC void mpz_divexact_gcd (mpz_ptr, mpz_srcptr, mpz_srcptr); + +#define mpz_prodlimbs __gmpz_prodlimbs +__GMP_DECLSPEC mp_size_t mpz_prodlimbs (mpz_ptr, mp_ptr, mp_size_t); + +#define mpz_oddfac_1 __gmpz_oddfac_1 +__GMP_DECLSPEC void mpz_oddfac_1 (mpz_ptr, mp_limb_t, unsigned); + +#define mpz_inp_str_nowhite __gmpz_inp_str_nowhite +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpz_inp_str_nowhite (mpz_ptr, FILE *, int, int, size_t); +#endif + +#define mpn_divisible_p __MPN(divisible_p) +__GMP_DECLSPEC int mpn_divisible_p (mp_srcptr, mp_size_t, mp_srcptr, mp_size_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_rootrem __MPN(rootrem) +__GMP_DECLSPEC mp_size_t mpn_rootrem (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_broot __MPN(broot) +__GMP_DECLSPEC void mpn_broot (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_broot_invm1 __MPN(broot_invm1) +__GMP_DECLSPEC void mpn_broot_invm1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_brootinv __MPN(brootinv) +__GMP_DECLSPEC void mpn_brootinv (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_ptr); + +#define mpn_bsqrt __MPN(bsqrt) +__GMP_DECLSPEC void mpn_bsqrt (mp_ptr, mp_srcptr, mp_bitcnt_t, mp_ptr); + +#define mpn_bsqrtinv __MPN(bsqrtinv) +__GMP_DECLSPEC int mpn_bsqrtinv (mp_ptr, mp_srcptr, mp_bitcnt_t, mp_ptr); + +#if defined (_CRAY) +#define MPN_COPY_INCR(dst, src, n) \ + do { \ + int __i; /* Faster on some Crays with plain int */ \ + _Pragma ("_CRI ivdep"); \ + for (__i = 0; __i < (n); __i++) \ + (dst)[__i] = (src)[__i]; \ + } while (0) +#endif + +/* used by test programs, hence __GMP_DECLSPEC */ +#ifndef mpn_copyi /* if not done with cpuvec in a fat binary */ +#define mpn_copyi __MPN(copyi) +__GMP_DECLSPEC void mpn_copyi (mp_ptr, mp_srcptr, mp_size_t); +#endif + +#if ! defined (MPN_COPY_INCR) && HAVE_NATIVE_mpn_copyi +#define MPN_COPY_INCR(dst, src, size) \ + do { \ + ASSERT ((size) >= 0); \ + ASSERT (MPN_SAME_OR_INCR_P (dst, src, size)); \ + mpn_copyi (dst, src, size); \ + } while (0) +#endif + +/* Copy N limbs from SRC to DST incrementing, N==0 allowed. */ +#if ! defined (MPN_COPY_INCR) +#define MPN_COPY_INCR(dst, src, n) \ + do { \ + ASSERT ((n) >= 0); \ + ASSERT (MPN_SAME_OR_INCR_P (dst, src, n)); \ + if ((n) != 0) \ + { \ + mp_size_t __n = (n) - 1; \ + mp_ptr __dst = (dst); \ + mp_srcptr __src = (src); \ + mp_limb_t __x; \ + __x = *__src++; \ + if (__n != 0) \ + { \ + do \ + { \ + *__dst++ = __x; \ + __x = *__src++; \ + } \ + while (--__n); \ + } \ + *__dst++ = __x; \ + } \ + } while (0) +#endif + + +#if defined (_CRAY) +#define MPN_COPY_DECR(dst, src, n) \ + do { \ + int __i; /* Faster on some Crays with plain int */ \ + _Pragma ("_CRI ivdep"); \ + for (__i = (n) - 1; __i >= 0; __i--) \ + (dst)[__i] = (src)[__i]; \ + } while (0) +#endif + +/* used by test programs, hence __GMP_DECLSPEC */ +#ifndef mpn_copyd /* if not done with cpuvec in a fat binary */ +#define mpn_copyd __MPN(copyd) +__GMP_DECLSPEC void mpn_copyd (mp_ptr, mp_srcptr, mp_size_t); +#endif + +#if ! defined (MPN_COPY_DECR) && HAVE_NATIVE_mpn_copyd +#define MPN_COPY_DECR(dst, src, size) \ + do { \ + ASSERT ((size) >= 0); \ + ASSERT (MPN_SAME_OR_DECR_P (dst, src, size)); \ + mpn_copyd (dst, src, size); \ + } while (0) +#endif + +/* Copy N limbs from SRC to DST decrementing, N==0 allowed. */ +#if ! defined (MPN_COPY_DECR) +#define MPN_COPY_DECR(dst, src, n) \ + do { \ + ASSERT ((n) >= 0); \ + ASSERT (MPN_SAME_OR_DECR_P (dst, src, n)); \ + if ((n) != 0) \ + { \ + mp_size_t __n = (n) - 1; \ + mp_ptr __dst = (dst) + __n; \ + mp_srcptr __src = (src) + __n; \ + mp_limb_t __x; \ + __x = *__src--; \ + if (__n != 0) \ + { \ + do \ + { \ + *__dst-- = __x; \ + __x = *__src--; \ + } \ + while (--__n); \ + } \ + *__dst-- = __x; \ + } \ + } while (0) +#endif + + +#ifndef MPN_COPY +#define MPN_COPY(d,s,n) \ + do { \ + ASSERT (MPN_SAME_OR_SEPARATE_P (d, s, n)); \ + MPN_COPY_INCR (d, s, n); \ + } while (0) +#endif + + +/* Set {dst,size} to the limbs of {src,size} in reverse order. */ +#define MPN_REVERSE(dst, src, size) \ + do { \ + mp_ptr __dst = (dst); \ + mp_size_t __size = (size); \ + mp_srcptr __src = (src) + __size - 1; \ + mp_size_t __i; \ + ASSERT ((size) >= 0); \ + ASSERT (! MPN_OVERLAP_P (dst, size, src, size)); \ + CRAY_Pragma ("_CRI ivdep"); \ + for (__i = 0; __i < __size; __i++) \ + { \ + *__dst = *__src; \ + __dst++; \ + __src--; \ + } \ + } while (0) + + +/* Zero n limbs at dst. + + For power and powerpc we want an inline stu/bdnz loop for zeroing. On + ppc630 for instance this is optimal since it can sustain only 1 store per + cycle. + + gcc 2.95.x (for powerpc64 -maix64, or powerpc32) doesn't recognise the + "for" loop in the generic code below can become stu/bdnz. The do/while + here helps it get to that. The same caveat about plain -mpowerpc64 mode + applies here as to __GMPN_COPY_INCR in gmp.h. + + xlc 3.1 already generates stu/bdnz from the generic C, and does so from + this loop too. + + Enhancement: GLIBC does some trickery with dcbz to zero whole cache lines + at a time. MPN_ZERO isn't all that important in GMP, so it might be more + trouble than it's worth to do the same, though perhaps a call to memset + would be good when on a GNU system. */ + +#if HAVE_HOST_CPU_FAMILY_power || HAVE_HOST_CPU_FAMILY_powerpc +#define MPN_FILL(dst, n, f) \ + do { \ + mp_ptr __dst = (dst) - 1; \ + mp_size_t __n = (n); \ + ASSERT (__n > 0); \ + do \ + *++__dst = (f); \ + while (--__n); \ + } while (0) +#endif + +#ifndef MPN_FILL +#define MPN_FILL(dst, n, f) \ + do { \ + mp_ptr __dst = (dst); \ + mp_size_t __n = (n); \ + ASSERT (__n > 0); \ + do \ + *__dst++ = (f); \ + while (--__n); \ + } while (0) +#endif + +#define MPN_ZERO(dst, n) \ + do { \ + ASSERT ((n) >= 0); \ + if ((n) != 0) \ + MPN_FILL (dst, n, CNST_LIMB (0)); \ + } while (0) + +/* On the x86s repe/scasl doesn't seem useful, since it takes many cycles to + start up and would need to strip a lot of zeros before it'd be faster + than a simple cmpl loop. Here are some times in cycles for + std/repe/scasl/cld and cld/repe/scasl (the latter would be for stripping + low zeros). + + std cld + P5 18 16 + P6 46 38 + K6 36 13 + K7 21 20 +*/ +#ifndef MPN_NORMALIZE +#define MPN_NORMALIZE(DST, NLIMBS) \ + do { \ + while ((NLIMBS) > 0) \ + { \ + if ((DST)[(NLIMBS) - 1] != 0) \ + break; \ + (NLIMBS)--; \ + } \ + } while (0) +#endif +#ifndef MPN_NORMALIZE_NOT_ZERO +#define MPN_NORMALIZE_NOT_ZERO(DST, NLIMBS) \ + do { \ + while (1) \ + { \ + ASSERT ((NLIMBS) >= 1); \ + if ((DST)[(NLIMBS) - 1] != 0) \ + break; \ + (NLIMBS)--; \ + } \ + } while (0) +#endif + +/* Strip least significant zero limbs from {ptr,size} by incrementing ptr + and decrementing size. low should be ptr[0], and will be the new ptr[0] + on returning. The number in {ptr,size} must be non-zero, ie. size!=0 and + somewhere a non-zero limb. */ +#define MPN_STRIP_LOW_ZEROS_NOT_ZERO(ptr, size, low) \ + do { \ + ASSERT ((size) >= 1); \ + ASSERT ((low) == (ptr)[0]); \ + \ + while ((low) == 0) \ + { \ + (size)--; \ + ASSERT ((size) >= 1); \ + (ptr)++; \ + (low) = *(ptr); \ + } \ + } while (0) + +/* Initialize X of type mpz_t with space for NLIMBS limbs. X should be a + temporary variable; it will be automatically cleared out at function + return. We use __x here to make it possible to accept both mpz_ptr and + mpz_t arguments. */ +#define MPZ_TMP_INIT(X, NLIMBS) \ + do { \ + mpz_ptr __x = (X); \ + ASSERT ((NLIMBS) >= 1); \ + __x->_mp_alloc = (NLIMBS); \ + __x->_mp_d = TMP_ALLOC_LIMBS (NLIMBS); \ + } while (0) + +#if WANT_ASSERT +static inline void * +_mpz_newalloc (mpz_ptr z, mp_size_t n) +{ + void * res = _mpz_realloc(z,n); + /* If we are checking the code, force a random change to limbs. */ + ((mp_ptr) res)[0] = ~ ((mp_ptr) res)[ALLOC (z) - 1]; + return res; +} +#else +#define _mpz_newalloc _mpz_realloc +#endif +/* Realloc for an mpz_t WHAT if it has less than NEEDED limbs. */ +#define MPZ_REALLOC(z,n) (UNLIKELY ((n) > ALLOC(z)) \ + ? (mp_ptr) _mpz_realloc(z,n) \ + : PTR(z)) +#define MPZ_NEWALLOC(z,n) (UNLIKELY ((n) > ALLOC(z)) \ + ? (mp_ptr) _mpz_newalloc(z,n) \ + : PTR(z)) + +#define MPZ_EQUAL_1_P(z) (SIZ(z)==1 && PTR(z)[0] == 1) + + +/* MPN_FIB2_SIZE(n) is the size in limbs required by mpn_fib2_ui for fp and + f1p. + + From Knuth vol 1 section 1.2.8, F[n] = phi^n/sqrt(5) rounded to the + nearest integer, where phi=(1+sqrt(5))/2 is the golden ratio. So the + number of bits required is n*log_2((1+sqrt(5))/2) = n*0.6942419. + + The multiplier used is 23/32=0.71875 for efficient calculation on CPUs + without good floating point. There's +2 for rounding up, and a further + +2 since at the last step x limbs are doubled into a 2x+1 limb region + whereas the actual F[2k] value might be only 2x-1 limbs. + + Note that a division is done first, since on a 32-bit system it's at + least conceivable to go right up to n==ULONG_MAX. (F[2^32-1] would be + about 380Mbytes, plus temporary workspace of about 1.2Gbytes here and + whatever a multiply of two 190Mbyte numbers takes.) + + Enhancement: When GMP_NUMB_BITS is not a power of 2 the division could be + worked into the multiplier. */ + +#define MPN_FIB2_SIZE(n) \ + ((mp_size_t) ((n) / 32 * 23 / GMP_NUMB_BITS) + 4) + + +/* FIB_TABLE(n) returns the Fibonacci number F[n]. Must have n in the range + -1 <= n <= FIB_TABLE_LIMIT (that constant in fib_table.h). + + FIB_TABLE_LUCNUM_LIMIT (in fib_table.h) is the largest n for which L[n] = + F[n] + 2*F[n-1] fits in a limb. */ + +__GMP_DECLSPEC extern const mp_limb_t __gmp_fib_table[]; +#define FIB_TABLE(n) (__gmp_fib_table[(n)+1]) + +extern const mp_limb_t __gmp_oddfac_table[]; +extern const mp_limb_t __gmp_odd2fac_table[]; +extern const unsigned char __gmp_fac2cnt_table[]; +extern const mp_limb_t __gmp_limbroots_table[]; + +/* n^log <= GMP_NUMB_MAX, a limb can store log factors less than n */ +static inline unsigned +log_n_max (mp_limb_t n) +{ + unsigned log; + for (log = 8; n > __gmp_limbroots_table[log - 1]; log--); + return log; +} + +#define SIEVESIZE 512 /* FIXME: Allow gmp_init_primesieve to choose */ +typedef struct +{ + unsigned long d; /* current index in s[] */ + unsigned long s0; /* number corresponding to s[0] */ + unsigned long sqrt_s0; /* misnomer for sqrt(s[SIEVESIZE-1]) */ + unsigned char s[SIEVESIZE + 1]; /* sieve table */ +} gmp_primesieve_t; + +#define gmp_init_primesieve __gmp_init_primesieve +__GMP_DECLSPEC void gmp_init_primesieve (gmp_primesieve_t *); + +#define gmp_nextprime __gmp_nextprime +__GMP_DECLSPEC unsigned long int gmp_nextprime (gmp_primesieve_t *); + +#define gmp_primesieve __gmp_primesieve +__GMP_DECLSPEC mp_limb_t gmp_primesieve (mp_ptr, mp_limb_t); + + +#ifndef MUL_TOOM22_THRESHOLD +#define MUL_TOOM22_THRESHOLD 30 +#endif + +#ifndef MUL_TOOM33_THRESHOLD +#define MUL_TOOM33_THRESHOLD 100 +#endif + +#ifndef MUL_TOOM44_THRESHOLD +#define MUL_TOOM44_THRESHOLD 300 +#endif + +#ifndef MUL_TOOM6H_THRESHOLD +#define MUL_TOOM6H_THRESHOLD 350 +#endif + +#ifndef SQR_TOOM6_THRESHOLD +#define SQR_TOOM6_THRESHOLD MUL_TOOM6H_THRESHOLD +#endif + +#ifndef MUL_TOOM8H_THRESHOLD +#define MUL_TOOM8H_THRESHOLD 450 +#endif + +#ifndef SQR_TOOM8_THRESHOLD +#define SQR_TOOM8_THRESHOLD MUL_TOOM8H_THRESHOLD +#endif + +#ifndef MUL_TOOM32_TO_TOOM43_THRESHOLD +#define MUL_TOOM32_TO_TOOM43_THRESHOLD 100 +#endif + +#ifndef MUL_TOOM32_TO_TOOM53_THRESHOLD +#define MUL_TOOM32_TO_TOOM53_THRESHOLD 110 +#endif + +#ifndef MUL_TOOM42_TO_TOOM53_THRESHOLD +#define MUL_TOOM42_TO_TOOM53_THRESHOLD 100 +#endif + +#ifndef MUL_TOOM42_TO_TOOM63_THRESHOLD +#define MUL_TOOM42_TO_TOOM63_THRESHOLD 110 +#endif + +#ifndef MUL_TOOM43_TO_TOOM54_THRESHOLD +#define MUL_TOOM43_TO_TOOM54_THRESHOLD 150 +#endif + +/* MUL_TOOM22_THRESHOLD_LIMIT is the maximum for MUL_TOOM22_THRESHOLD. In a + normal build MUL_TOOM22_THRESHOLD is a constant and we use that. In a fat + binary or tune program build MUL_TOOM22_THRESHOLD is a variable and a + separate hard limit will have been defined. Similarly for TOOM3. */ +#ifndef MUL_TOOM22_THRESHOLD_LIMIT +#define MUL_TOOM22_THRESHOLD_LIMIT MUL_TOOM22_THRESHOLD +#endif +#ifndef MUL_TOOM33_THRESHOLD_LIMIT +#define MUL_TOOM33_THRESHOLD_LIMIT MUL_TOOM33_THRESHOLD +#endif +#ifndef MULLO_BASECASE_THRESHOLD_LIMIT +#define MULLO_BASECASE_THRESHOLD_LIMIT MULLO_BASECASE_THRESHOLD +#endif +#ifndef SQRLO_BASECASE_THRESHOLD_LIMIT +#define SQRLO_BASECASE_THRESHOLD_LIMIT SQRLO_BASECASE_THRESHOLD +#endif +#ifndef SQRLO_DC_THRESHOLD_LIMIT +#define SQRLO_DC_THRESHOLD_LIMIT SQRLO_DC_THRESHOLD +#endif + +/* SQR_BASECASE_THRESHOLD is where mpn_sqr_basecase should take over from + mpn_mul_basecase. Default is to use mpn_sqr_basecase from 0. (Note that we + certainly always want it if there's a native assembler mpn_sqr_basecase.) + + If it turns out that mpn_toom2_sqr becomes faster than mpn_mul_basecase + before mpn_sqr_basecase does, then SQR_BASECASE_THRESHOLD is the toom2 + threshold and SQR_TOOM2_THRESHOLD is 0. This oddity arises more or less + because SQR_TOOM2_THRESHOLD represents the size up to which mpn_sqr_basecase + should be used, and that may be never. */ + +#ifndef SQR_BASECASE_THRESHOLD +#define SQR_BASECASE_THRESHOLD 0 /* never use mpn_mul_basecase */ +#endif + +#ifndef SQR_TOOM2_THRESHOLD +#define SQR_TOOM2_THRESHOLD 50 +#endif + +#ifndef SQR_TOOM3_THRESHOLD +#define SQR_TOOM3_THRESHOLD 120 +#endif + +#ifndef SQR_TOOM4_THRESHOLD +#define SQR_TOOM4_THRESHOLD 400 +#endif + +/* See comments above about MUL_TOOM33_THRESHOLD_LIMIT. */ +#ifndef SQR_TOOM3_THRESHOLD_LIMIT +#define SQR_TOOM3_THRESHOLD_LIMIT SQR_TOOM3_THRESHOLD +#endif + +#ifndef MULMID_TOOM42_THRESHOLD +#define MULMID_TOOM42_THRESHOLD MUL_TOOM22_THRESHOLD +#endif + +#ifndef MULLO_BASECASE_THRESHOLD +#define MULLO_BASECASE_THRESHOLD 0 /* never use mpn_mul_basecase */ +#endif + +#ifndef MULLO_DC_THRESHOLD +#define MULLO_DC_THRESHOLD (2*MUL_TOOM22_THRESHOLD) +#endif + +#ifndef MULLO_MUL_N_THRESHOLD +#define MULLO_MUL_N_THRESHOLD (2*MUL_FFT_THRESHOLD) +#endif + +#ifndef SQRLO_BASECASE_THRESHOLD +#define SQRLO_BASECASE_THRESHOLD 0 /* never use mpn_sqr_basecase */ +#endif + +#ifndef SQRLO_DC_THRESHOLD +#define SQRLO_DC_THRESHOLD (MULLO_DC_THRESHOLD) +#endif + +#ifndef SQRLO_SQR_THRESHOLD +#define SQRLO_SQR_THRESHOLD (MULLO_MUL_N_THRESHOLD) +#endif + +#ifndef DC_DIV_QR_THRESHOLD +#define DC_DIV_QR_THRESHOLD (2*MUL_TOOM22_THRESHOLD) +#endif + +#ifndef DC_DIVAPPR_Q_THRESHOLD +#define DC_DIVAPPR_Q_THRESHOLD 200 +#endif + +#ifndef DC_BDIV_QR_THRESHOLD +#define DC_BDIV_QR_THRESHOLD (2*MUL_TOOM22_THRESHOLD) +#endif + +#ifndef DC_BDIV_Q_THRESHOLD +#define DC_BDIV_Q_THRESHOLD 180 +#endif + +#ifndef DIVEXACT_JEB_THRESHOLD +#define DIVEXACT_JEB_THRESHOLD 25 +#endif + +#ifndef INV_MULMOD_BNM1_THRESHOLD +#define INV_MULMOD_BNM1_THRESHOLD (4*MULMOD_BNM1_THRESHOLD) +#endif + +#ifndef INV_APPR_THRESHOLD +#define INV_APPR_THRESHOLD INV_NEWTON_THRESHOLD +#endif + +#ifndef INV_NEWTON_THRESHOLD +#define INV_NEWTON_THRESHOLD 200 +#endif + +#ifndef BINV_NEWTON_THRESHOLD +#define BINV_NEWTON_THRESHOLD 300 +#endif + +#ifndef MU_DIVAPPR_Q_THRESHOLD +#define MU_DIVAPPR_Q_THRESHOLD 2000 +#endif + +#ifndef MU_DIV_QR_THRESHOLD +#define MU_DIV_QR_THRESHOLD 2000 +#endif + +#ifndef MUPI_DIV_QR_THRESHOLD +#define MUPI_DIV_QR_THRESHOLD 200 +#endif + +#ifndef MU_BDIV_Q_THRESHOLD +#define MU_BDIV_Q_THRESHOLD 2000 +#endif + +#ifndef MU_BDIV_QR_THRESHOLD +#define MU_BDIV_QR_THRESHOLD 2000 +#endif + +#ifndef MULMOD_BNM1_THRESHOLD +#define MULMOD_BNM1_THRESHOLD 16 +#endif + +#ifndef SQRMOD_BNM1_THRESHOLD +#define SQRMOD_BNM1_THRESHOLD 16 +#endif + +#ifndef MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD +#define MUL_TO_MULMOD_BNM1_FOR_2NXN_THRESHOLD (INV_MULMOD_BNM1_THRESHOLD/2) +#endif + +#if HAVE_NATIVE_mpn_addmul_2 || HAVE_NATIVE_mpn_redc_2 + +#ifndef REDC_1_TO_REDC_2_THRESHOLD +#define REDC_1_TO_REDC_2_THRESHOLD 15 +#endif +#ifndef REDC_2_TO_REDC_N_THRESHOLD +#define REDC_2_TO_REDC_N_THRESHOLD 100 +#endif + +#else + +#ifndef REDC_1_TO_REDC_N_THRESHOLD +#define REDC_1_TO_REDC_N_THRESHOLD 100 +#endif + +#endif /* HAVE_NATIVE_mpn_addmul_2 || HAVE_NATIVE_mpn_redc_2 */ + + +/* First k to use for an FFT modF multiply. A modF FFT is an order + log(2^k)/log(2^(k-1)) algorithm, so k=3 is merely 1.5 like karatsuba, + whereas k=4 is 1.33 which is faster than toom3 at 1.485. */ +#define FFT_FIRST_K 4 + +/* Threshold at which FFT should be used to do a modF NxN -> N multiply. */ +#ifndef MUL_FFT_MODF_THRESHOLD +#define MUL_FFT_MODF_THRESHOLD (MUL_TOOM33_THRESHOLD * 3) +#endif +#ifndef SQR_FFT_MODF_THRESHOLD +#define SQR_FFT_MODF_THRESHOLD (SQR_TOOM3_THRESHOLD * 3) +#endif + +/* Threshold at which FFT should be used to do an NxN -> 2N multiply. This + will be a size where FFT is using k=7 or k=8, since an FFT-k used for an + NxN->2N multiply and not recursing into itself is an order + log(2^k)/log(2^(k-2)) algorithm, so it'll be at least k=7 at 1.39 which + is the first better than toom3. */ +#ifndef MUL_FFT_THRESHOLD +#define MUL_FFT_THRESHOLD (MUL_FFT_MODF_THRESHOLD * 10) +#endif +#ifndef SQR_FFT_THRESHOLD +#define SQR_FFT_THRESHOLD (SQR_FFT_MODF_THRESHOLD * 10) +#endif + +/* Table of thresholds for successive modF FFT "k"s. The first entry is + where FFT_FIRST_K+1 should be used, the second FFT_FIRST_K+2, + etc. See mpn_fft_best_k(). */ +#ifndef MUL_FFT_TABLE +#define MUL_FFT_TABLE \ + { MUL_TOOM33_THRESHOLD * 4, /* k=5 */ \ + MUL_TOOM33_THRESHOLD * 8, /* k=6 */ \ + MUL_TOOM33_THRESHOLD * 16, /* k=7 */ \ + MUL_TOOM33_THRESHOLD * 32, /* k=8 */ \ + MUL_TOOM33_THRESHOLD * 96, /* k=9 */ \ + MUL_TOOM33_THRESHOLD * 288, /* k=10 */ \ + 0 } +#endif +#ifndef SQR_FFT_TABLE +#define SQR_FFT_TABLE \ + { SQR_TOOM3_THRESHOLD * 4, /* k=5 */ \ + SQR_TOOM3_THRESHOLD * 8, /* k=6 */ \ + SQR_TOOM3_THRESHOLD * 16, /* k=7 */ \ + SQR_TOOM3_THRESHOLD * 32, /* k=8 */ \ + SQR_TOOM3_THRESHOLD * 96, /* k=9 */ \ + SQR_TOOM3_THRESHOLD * 288, /* k=10 */ \ + 0 } +#endif + +struct fft_table_nk +{ + gmp_uint_least32_t n:27; + gmp_uint_least32_t k:5; +}; + +#ifndef FFT_TABLE_ATTRS +#define FFT_TABLE_ATTRS static const +#endif + +#define MPN_FFT_TABLE_SIZE 16 + + +#ifndef DC_DIV_QR_THRESHOLD +#define DC_DIV_QR_THRESHOLD (3 * MUL_TOOM22_THRESHOLD) +#endif + +#ifndef GET_STR_DC_THRESHOLD +#define GET_STR_DC_THRESHOLD 18 +#endif + +#ifndef GET_STR_PRECOMPUTE_THRESHOLD +#define GET_STR_PRECOMPUTE_THRESHOLD 35 +#endif + +#ifndef SET_STR_DC_THRESHOLD +#define SET_STR_DC_THRESHOLD 750 +#endif + +#ifndef SET_STR_PRECOMPUTE_THRESHOLD +#define SET_STR_PRECOMPUTE_THRESHOLD 2000 +#endif + +#ifndef FAC_ODD_THRESHOLD +#define FAC_ODD_THRESHOLD 35 +#endif + +#ifndef FAC_DSC_THRESHOLD +#define FAC_DSC_THRESHOLD 400 +#endif + +/* Return non-zero if xp,xsize and yp,ysize overlap. + If xp+xsize<=yp there's no overlap, or if yp+ysize<=xp there's no + overlap. If both these are false, there's an overlap. */ +#define MPN_OVERLAP_P(xp, xsize, yp, ysize) \ + ((xp) + (xsize) > (yp) && (yp) + (ysize) > (xp)) +#define MEM_OVERLAP_P(xp, xsize, yp, ysize) \ + ( (char *) (xp) + (xsize) > (char *) (yp) \ + && (char *) (yp) + (ysize) > (char *) (xp)) + +/* Return non-zero if xp,xsize and yp,ysize are either identical or not + overlapping. Return zero if they're partially overlapping. */ +#define MPN_SAME_OR_SEPARATE_P(xp, yp, size) \ + MPN_SAME_OR_SEPARATE2_P(xp, size, yp, size) +#define MPN_SAME_OR_SEPARATE2_P(xp, xsize, yp, ysize) \ + ((xp) == (yp) || ! MPN_OVERLAP_P (xp, xsize, yp, ysize)) + +/* Return non-zero if dst,dsize and src,ssize are either identical or + overlapping in a way suitable for an incrementing/decrementing algorithm. + Return zero if they're partially overlapping in an unsuitable fashion. */ +#define MPN_SAME_OR_INCR2_P(dst, dsize, src, ssize) \ + ((dst) <= (src) || ! MPN_OVERLAP_P (dst, dsize, src, ssize)) +#define MPN_SAME_OR_INCR_P(dst, src, size) \ + MPN_SAME_OR_INCR2_P(dst, size, src, size) +#define MPN_SAME_OR_DECR2_P(dst, dsize, src, ssize) \ + ((dst) >= (src) || ! MPN_OVERLAP_P (dst, dsize, src, ssize)) +#define MPN_SAME_OR_DECR_P(dst, src, size) \ + MPN_SAME_OR_DECR2_P(dst, size, src, size) + + +/* ASSERT() is a private assertion checking scheme, similar to <assert.h>. + ASSERT() does the check only if WANT_ASSERT is selected, ASSERT_ALWAYS() + does it always. Generally assertions are meant for development, but + might help when looking for a problem later too. */ + +#ifdef __LINE__ +#define ASSERT_LINE __LINE__ +#else +#define ASSERT_LINE -1 +#endif + +#ifdef __FILE__ +#define ASSERT_FILE __FILE__ +#else +#define ASSERT_FILE "" +#endif + +__GMP_DECLSPEC void __gmp_assert_header (const char *, int); +__GMP_DECLSPEC void __gmp_assert_fail (const char *, int, const char *) ATTRIBUTE_NORETURN; + +#define ASSERT_FAIL(expr) __gmp_assert_fail (ASSERT_FILE, ASSERT_LINE, #expr) + +#define ASSERT_ALWAYS(expr) \ + do { \ + if (UNLIKELY (!(expr))) \ + ASSERT_FAIL (expr); \ + } while (0) + +#if WANT_ASSERT +#define ASSERT(expr) ASSERT_ALWAYS (expr) +#else +#define ASSERT(expr) do {} while (0) +#endif + + +/* ASSERT_CARRY checks the expression is non-zero, and ASSERT_NOCARRY checks + that it's zero. In both cases if assertion checking is disabled the + expression is still evaluated. These macros are meant for use with + routines like mpn_add_n() where the return value represents a carry or + whatever that should or shouldn't occur in some context. For example, + ASSERT_NOCARRY (mpn_add_n (rp, s1p, s2p, size)); */ +#if WANT_ASSERT +#define ASSERT_CARRY(expr) ASSERT_ALWAYS ((expr) != 0) +#define ASSERT_NOCARRY(expr) ASSERT_ALWAYS ((expr) == 0) +#else +#define ASSERT_CARRY(expr) (expr) +#define ASSERT_NOCARRY(expr) (expr) +#endif + + +/* ASSERT_CODE includes code when assertion checking is wanted. This is the + same as writing "#if WANT_ASSERT", but more compact. */ +#if WANT_ASSERT +#define ASSERT_CODE(expr) expr +#else +#define ASSERT_CODE(expr) +#endif + + +/* Test that an mpq_t is in fully canonical form. This can be used as + protection on routines like mpq_equal which give wrong results on + non-canonical inputs. */ +#if WANT_ASSERT +#define ASSERT_MPQ_CANONICAL(q) \ + do { \ + ASSERT (q->_mp_den._mp_size > 0); \ + if (q->_mp_num._mp_size == 0) \ + { \ + /* zero should be 0/1 */ \ + ASSERT (mpz_cmp_ui (mpq_denref(q), 1L) == 0); \ + } \ + else \ + { \ + /* no common factors */ \ + mpz_t __g; \ + mpz_init (__g); \ + mpz_gcd (__g, mpq_numref(q), mpq_denref(q)); \ + ASSERT (mpz_cmp_ui (__g, 1) == 0); \ + mpz_clear (__g); \ + } \ + } while (0) +#else +#define ASSERT_MPQ_CANONICAL(q) do {} while (0) +#endif + +/* Check that the nail parts are zero. */ +#define ASSERT_ALWAYS_LIMB(limb) \ + do { \ + mp_limb_t __nail = (limb) & GMP_NAIL_MASK; \ + ASSERT_ALWAYS (__nail == 0); \ + } while (0) +#define ASSERT_ALWAYS_MPN(ptr, size) \ + do { \ + /* let whole loop go dead when no nails */ \ + if (GMP_NAIL_BITS != 0) \ + { \ + mp_size_t __i; \ + for (__i = 0; __i < (size); __i++) \ + ASSERT_ALWAYS_LIMB ((ptr)[__i]); \ + } \ + } while (0) +#if WANT_ASSERT +#define ASSERT_LIMB(limb) ASSERT_ALWAYS_LIMB (limb) +#define ASSERT_MPN(ptr, size) ASSERT_ALWAYS_MPN (ptr, size) +#else +#define ASSERT_LIMB(limb) do {} while (0) +#define ASSERT_MPN(ptr, size) do {} while (0) +#endif + + +/* Assert that an mpn region {ptr,size} is zero, or non-zero. + size==0 is allowed, and in that case {ptr,size} considered to be zero. */ +#if WANT_ASSERT +#define ASSERT_MPN_ZERO_P(ptr,size) \ + do { \ + mp_size_t __i; \ + ASSERT ((size) >= 0); \ + for (__i = 0; __i < (size); __i++) \ + ASSERT ((ptr)[__i] == 0); \ + } while (0) +#define ASSERT_MPN_NONZERO_P(ptr,size) \ + do { \ + mp_size_t __i; \ + int __nonzero = 0; \ + ASSERT ((size) >= 0); \ + for (__i = 0; __i < (size); __i++) \ + if ((ptr)[__i] != 0) \ + { \ + __nonzero = 1; \ + break; \ + } \ + ASSERT (__nonzero); \ + } while (0) +#else +#define ASSERT_MPN_ZERO_P(ptr,size) do {} while (0) +#define ASSERT_MPN_NONZERO_P(ptr,size) do {} while (0) +#endif + + +#if ! HAVE_NATIVE_mpn_com +#undef mpn_com +#define mpn_com(d,s,n) \ + do { \ + mp_ptr __d = (d); \ + mp_srcptr __s = (s); \ + mp_size_t __n = (n); \ + ASSERT (__n >= 1); \ + ASSERT (MPN_SAME_OR_SEPARATE_P (__d, __s, __n)); \ + do \ + *__d++ = (~ *__s++) & GMP_NUMB_MASK; \ + while (--__n); \ + } while (0) +#endif + +#define MPN_LOGOPS_N_INLINE(rp, up, vp, n, operation) \ + do { \ + mp_srcptr __up = (up); \ + mp_srcptr __vp = (vp); \ + mp_ptr __rp = (rp); \ + mp_size_t __n = (n); \ + mp_limb_t __a, __b; \ + ASSERT (__n > 0); \ + ASSERT (MPN_SAME_OR_SEPARATE_P (__rp, __up, __n)); \ + ASSERT (MPN_SAME_OR_SEPARATE_P (__rp, __vp, __n)); \ + __up += __n; \ + __vp += __n; \ + __rp += __n; \ + __n = -__n; \ + do { \ + __a = __up[__n]; \ + __b = __vp[__n]; \ + __rp[__n] = operation; \ + } while (++__n); \ + } while (0) + + +#if ! HAVE_NATIVE_mpn_and_n +#undef mpn_and_n +#define mpn_and_n(rp, up, vp, n) \ + MPN_LOGOPS_N_INLINE (rp, up, vp, n, __a & __b) +#endif + +#if ! HAVE_NATIVE_mpn_andn_n +#undef mpn_andn_n +#define mpn_andn_n(rp, up, vp, n) \ + MPN_LOGOPS_N_INLINE (rp, up, vp, n, __a & ~__b) +#endif + +#if ! HAVE_NATIVE_mpn_nand_n +#undef mpn_nand_n +#define mpn_nand_n(rp, up, vp, n) \ + MPN_LOGOPS_N_INLINE (rp, up, vp, n, ~(__a & __b) & GMP_NUMB_MASK) +#endif + +#if ! HAVE_NATIVE_mpn_ior_n +#undef mpn_ior_n +#define mpn_ior_n(rp, up, vp, n) \ + MPN_LOGOPS_N_INLINE (rp, up, vp, n, __a | __b) +#endif + +#if ! HAVE_NATIVE_mpn_iorn_n +#undef mpn_iorn_n +#define mpn_iorn_n(rp, up, vp, n) \ + MPN_LOGOPS_N_INLINE (rp, up, vp, n, (__a | ~__b) & GMP_NUMB_MASK) +#endif + +#if ! HAVE_NATIVE_mpn_nior_n +#undef mpn_nior_n +#define mpn_nior_n(rp, up, vp, n) \ + MPN_LOGOPS_N_INLINE (rp, up, vp, n, ~(__a | __b) & GMP_NUMB_MASK) +#endif + +#if ! HAVE_NATIVE_mpn_xor_n +#undef mpn_xor_n +#define mpn_xor_n(rp, up, vp, n) \ + MPN_LOGOPS_N_INLINE (rp, up, vp, n, __a ^ __b) +#endif + +#if ! HAVE_NATIVE_mpn_xnor_n +#undef mpn_xnor_n +#define mpn_xnor_n(rp, up, vp, n) \ + MPN_LOGOPS_N_INLINE (rp, up, vp, n, ~(__a ^ __b) & GMP_NUMB_MASK) +#endif + +#define mpn_trialdiv __MPN(trialdiv) +__GMP_DECLSPEC mp_limb_t mpn_trialdiv (mp_srcptr, mp_size_t, mp_size_t, int *); + +#define mpn_remove __MPN(remove) +__GMP_DECLSPEC mp_bitcnt_t mpn_remove (mp_ptr, mp_size_t *, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_bitcnt_t); + + +/* ADDC_LIMB sets w=x+y and cout to 0 or 1 for a carry from that addition. */ +#if GMP_NAIL_BITS == 0 +#define ADDC_LIMB(cout, w, x, y) \ + do { \ + mp_limb_t __x = (x); \ + mp_limb_t __y = (y); \ + mp_limb_t __w = __x + __y; \ + (w) = __w; \ + (cout) = __w < __x; \ + } while (0) +#else +#define ADDC_LIMB(cout, w, x, y) \ + do { \ + mp_limb_t __w; \ + ASSERT_LIMB (x); \ + ASSERT_LIMB (y); \ + __w = (x) + (y); \ + (w) = __w & GMP_NUMB_MASK; \ + (cout) = __w >> GMP_NUMB_BITS; \ + } while (0) +#endif + +/* SUBC_LIMB sets w=x-y and cout to 0 or 1 for a borrow from that + subtract. */ +#if GMP_NAIL_BITS == 0 +#define SUBC_LIMB(cout, w, x, y) \ + do { \ + mp_limb_t __x = (x); \ + mp_limb_t __y = (y); \ + mp_limb_t __w = __x - __y; \ + (w) = __w; \ + (cout) = __w > __x; \ + } while (0) +#else +#define SUBC_LIMB(cout, w, x, y) \ + do { \ + mp_limb_t __w = (x) - (y); \ + (w) = __w & GMP_NUMB_MASK; \ + (cout) = __w >> (GMP_LIMB_BITS-1); \ + } while (0) +#endif + + +/* MPN_INCR_U does {ptr,size} += n, MPN_DECR_U does {ptr,size} -= n, both + expecting no carry (or borrow) from that. + + The size parameter is only for the benefit of assertion checking. In a + normal build it's unused and the carry/borrow is just propagated as far + as it needs to go. + + On random data, usually only one or two limbs of {ptr,size} get updated, + so there's no need for any sophisticated looping, just something compact + and sensible. + + FIXME: Switch all code from mpn_{incr,decr}_u to MPN_{INCR,DECR}_U, + declaring their operand sizes, then remove the former. This is purely + for the benefit of assertion checking. */ + +#if defined (__GNUC__) && GMP_NAIL_BITS == 0 && ! defined (NO_ASM) \ + && (defined(HAVE_HOST_CPU_FAMILY_x86) || defined(HAVE_HOST_CPU_FAMILY_x86_64)) \ + && ! WANT_ASSERT +/* Better flags handling than the generic C gives on i386, saving a few + bytes of code and maybe a cycle or two. */ + +#define MPN_IORD_U(ptr, incr, aors) \ + do { \ + mp_ptr __ptr_dummy; \ + if (__builtin_constant_p (incr) && (incr) == 0) \ + { \ + } \ + else if (__builtin_constant_p (incr) && (incr) == 1) \ + { \ + __asm__ __volatile__ \ + ("\n" ASM_L(top) ":\n" \ + "\t" aors "\t$1, (%0)\n" \ + "\tlea\t%c2(%0), %0\n" \ + "\tjc\t" ASM_L(top) \ + : "=r" (__ptr_dummy) \ + : "0" (ptr), "n" (sizeof(mp_limb_t)) \ + : "memory"); \ + } \ + else \ + { \ + __asm__ __volatile__ \ + ( aors "\t%2, (%0)\n" \ + "\tjnc\t" ASM_L(done) "\n" \ + ASM_L(top) ":\n" \ + "\t" aors "\t$1, %c3(%0)\n" \ + "\tlea\t%c3(%0), %0\n" \ + "\tjc\t" ASM_L(top) "\n" \ + ASM_L(done) ":\n" \ + : "=r" (__ptr_dummy) \ + : "0" (ptr), \ + "re" ((mp_limb_t) (incr)), "n" (sizeof(mp_limb_t)) \ + : "memory"); \ + } \ + } while (0) + +#if GMP_LIMB_BITS == 32 +#define MPN_INCR_U(ptr, size, incr) MPN_IORD_U (ptr, incr, "addl") +#define MPN_DECR_U(ptr, size, incr) MPN_IORD_U (ptr, incr, "subl") +#endif +#if GMP_LIMB_BITS == 64 +#define MPN_INCR_U(ptr, size, incr) MPN_IORD_U (ptr, incr, "addq") +#define MPN_DECR_U(ptr, size, incr) MPN_IORD_U (ptr, incr, "subq") +#endif +#define mpn_incr_u(ptr, incr) MPN_INCR_U (ptr, 0, incr) +#define mpn_decr_u(ptr, incr) MPN_DECR_U (ptr, 0, incr) +#endif + +#if GMP_NAIL_BITS == 0 +#ifndef mpn_incr_u +#define mpn_incr_u(p,incr) \ + do { \ + mp_limb_t __x; \ + mp_ptr __p = (p); \ + if (__builtin_constant_p (incr) && (incr) == 1) \ + { \ + while (++(*(__p++)) == 0) \ + ; \ + } \ + else \ + { \ + __x = *__p + (incr); \ + *__p = __x; \ + if (__x < (incr)) \ + while (++(*(++__p)) == 0) \ + ; \ + } \ + } while (0) +#endif +#ifndef mpn_decr_u +#define mpn_decr_u(p,incr) \ + do { \ + mp_limb_t __x; \ + mp_ptr __p = (p); \ + if (__builtin_constant_p (incr) && (incr) == 1) \ + { \ + while ((*(__p++))-- == 0) \ + ; \ + } \ + else \ + { \ + __x = *__p; \ + *__p = __x - (incr); \ + if (__x < (incr)) \ + while ((*(++__p))-- == 0) \ + ; \ + } \ + } while (0) +#endif +#endif + +#if GMP_NAIL_BITS >= 1 +#ifndef mpn_incr_u +#define mpn_incr_u(p,incr) \ + do { \ + mp_limb_t __x; \ + mp_ptr __p = (p); \ + if (__builtin_constant_p (incr) && (incr) == 1) \ + { \ + do \ + { \ + __x = (*__p + 1) & GMP_NUMB_MASK; \ + *__p++ = __x; \ + } \ + while (__x == 0); \ + } \ + else \ + { \ + __x = (*__p + (incr)); \ + *__p++ = __x & GMP_NUMB_MASK; \ + if (__x >> GMP_NUMB_BITS != 0) \ + { \ + do \ + { \ + __x = (*__p + 1) & GMP_NUMB_MASK; \ + *__p++ = __x; \ + } \ + while (__x == 0); \ + } \ + } \ + } while (0) +#endif +#ifndef mpn_decr_u +#define mpn_decr_u(p,incr) \ + do { \ + mp_limb_t __x; \ + mp_ptr __p = (p); \ + if (__builtin_constant_p (incr) && (incr) == 1) \ + { \ + do \ + { \ + __x = *__p; \ + *__p++ = (__x - 1) & GMP_NUMB_MASK; \ + } \ + while (__x == 0); \ + } \ + else \ + { \ + __x = *__p - (incr); \ + *__p++ = __x & GMP_NUMB_MASK; \ + if (__x >> GMP_NUMB_BITS != 0) \ + { \ + do \ + { \ + __x = *__p; \ + *__p++ = (__x - 1) & GMP_NUMB_MASK; \ + } \ + while (__x == 0); \ + } \ + } \ + } while (0) +#endif +#endif + +#ifndef MPN_INCR_U +#if WANT_ASSERT +#define MPN_INCR_U(ptr, size, n) \ + do { \ + ASSERT ((size) >= 1); \ + ASSERT_NOCARRY (mpn_add_1 (ptr, ptr, size, n)); \ + } while (0) +#else +#define MPN_INCR_U(ptr, size, n) mpn_incr_u (ptr, n) +#endif +#endif + +#ifndef MPN_DECR_U +#if WANT_ASSERT +#define MPN_DECR_U(ptr, size, n) \ + do { \ + ASSERT ((size) >= 1); \ + ASSERT_NOCARRY (mpn_sub_1 (ptr, ptr, size, n)); \ + } while (0) +#else +#define MPN_DECR_U(ptr, size, n) mpn_decr_u (ptr, n) +#endif +#endif + + +/* Structure for conversion between internal binary format and strings. */ +struct bases +{ + /* Number of digits in the conversion base that always fits in an mp_limb_t. + For example, for base 10 on a machine where an mp_limb_t has 32 bits this + is 9, since 10**9 is the largest number that fits into an mp_limb_t. */ + int chars_per_limb; + + /* log(2)/log(conversion_base) */ + mp_limb_t logb2; + + /* log(conversion_base)/log(2) */ + mp_limb_t log2b; + + /* base**chars_per_limb, i.e. the biggest number that fits a word, built by + factors of base. Exception: For 2, 4, 8, etc, big_base is log2(base), + i.e. the number of bits used to represent each digit in the base. */ + mp_limb_t big_base; + + /* A GMP_LIMB_BITS bit approximation to 1/big_base, represented as a + fixed-point number. Instead of dividing by big_base an application can + choose to multiply by big_base_inverted. */ + mp_limb_t big_base_inverted; +}; + +#define mp_bases __MPN(bases) +__GMP_DECLSPEC extern const struct bases mp_bases[257]; + + +/* Compute the number of digits in base for nbits bits, making sure the result + is never too small. The two variants of the macro implement the same + function; the GT2 variant below works just for bases > 2. */ +#define DIGITS_IN_BASE_FROM_BITS(res, nbits, b) \ + do { \ + mp_limb_t _ph, _dummy; \ + size_t _nbits = (nbits); \ + umul_ppmm (_ph, _dummy, mp_bases[b].logb2, _nbits); \ + _ph += (_dummy + _nbits < _dummy); \ + res = _ph + 1; \ + } while (0) +#define DIGITS_IN_BASEGT2_FROM_BITS(res, nbits, b) \ + do { \ + mp_limb_t _ph, _dummy; \ + size_t _nbits = (nbits); \ + umul_ppmm (_ph, _dummy, mp_bases[b].logb2 + 1, _nbits); \ + res = _ph + 1; \ + } while (0) + +/* For power of 2 bases this is exact. For other bases the result is either + exact or one too big. + + To be exact always it'd be necessary to examine all the limbs of the + operand, since numbers like 100..000 and 99...999 generally differ only + in the lowest limb. It'd be possible to examine just a couple of high + limbs to increase the probability of being exact, but that doesn't seem + worth bothering with. */ + +#define MPN_SIZEINBASE(result, ptr, size, base) \ + do { \ + int __lb_base, __cnt; \ + size_t __totbits; \ + \ + ASSERT ((size) >= 0); \ + ASSERT ((base) >= 2); \ + ASSERT ((base) < numberof (mp_bases)); \ + \ + /* Special case for X == 0. */ \ + if ((size) == 0) \ + (result) = 1; \ + else \ + { \ + /* Calculate the total number of significant bits of X. */ \ + count_leading_zeros (__cnt, (ptr)[(size)-1]); \ + __totbits = (size_t) (size) * GMP_NUMB_BITS - (__cnt - GMP_NAIL_BITS);\ + \ + if (POW2_P (base)) \ + { \ + __lb_base = mp_bases[base].big_base; \ + (result) = (__totbits + __lb_base - 1) / __lb_base; \ + } \ + else \ + { \ + DIGITS_IN_BASEGT2_FROM_BITS (result, __totbits, base); \ + } \ + } \ + } while (0) + +#define MPN_SIZEINBASE_2EXP(result, ptr, size, base2exp) \ + do { \ + int __cnt; \ + mp_bitcnt_t __totbits; \ + ASSERT ((size) > 0); \ + ASSERT ((ptr)[(size)-1] != 0); \ + count_leading_zeros (__cnt, (ptr)[(size)-1]); \ + __totbits = (mp_bitcnt_t) (size) * GMP_NUMB_BITS - (__cnt - GMP_NAIL_BITS); \ + (result) = (__totbits + (base2exp)-1) / (base2exp); \ + } while (0) + + +/* bit count to limb count, rounding up */ +#define BITS_TO_LIMBS(n) (((n) + (GMP_NUMB_BITS - 1)) / GMP_NUMB_BITS) + +/* MPN_SET_UI sets an mpn (ptr, cnt) to given ui. MPZ_FAKE_UI creates fake + mpz_t from ui. The zp argument must have room for LIMBS_PER_ULONG limbs + in both cases (LIMBS_PER_ULONG is also defined here.) */ +#if BITS_PER_ULONG <= GMP_NUMB_BITS /* need one limb per ulong */ + +#define LIMBS_PER_ULONG 1 +#define MPN_SET_UI(zp, zn, u) \ + (zp)[0] = (u); \ + (zn) = ((zp)[0] != 0); +#define MPZ_FAKE_UI(z, zp, u) \ + (zp)[0] = (u); \ + PTR (z) = (zp); \ + SIZ (z) = ((zp)[0] != 0); \ + ASSERT_CODE (ALLOC (z) = 1); + +#else /* need two limbs per ulong */ + +#define LIMBS_PER_ULONG 2 +#define MPN_SET_UI(zp, zn, u) \ + (zp)[0] = (u) & GMP_NUMB_MASK; \ + (zp)[1] = (u) >> GMP_NUMB_BITS; \ + (zn) = ((zp)[1] != 0 ? 2 : (zp)[0] != 0 ? 1 : 0); +#define MPZ_FAKE_UI(z, zp, u) \ + (zp)[0] = (u) & GMP_NUMB_MASK; \ + (zp)[1] = (u) >> GMP_NUMB_BITS; \ + SIZ (z) = ((zp)[1] != 0 ? 2 : (zp)[0] != 0 ? 1 : 0); \ + PTR (z) = (zp); \ + ASSERT_CODE (ALLOC (z) = 2); + +#endif + + +#if HAVE_HOST_CPU_FAMILY_x86 +#define TARGET_REGISTER_STARVED 1 +#else +#define TARGET_REGISTER_STARVED 0 +#endif + + +/* LIMB_HIGHBIT_TO_MASK(n) examines the high bit of a limb value and turns 1 + or 0 there into a limb 0xFF..FF or 0 respectively. + + On most CPUs this is just an arithmetic right shift by GMP_LIMB_BITS-1, + but C99 doesn't guarantee signed right shifts are arithmetic, so we have + a little compile-time test and a fallback to a "? :" form. The latter is + necessary for instance on Cray vector systems. + + Recent versions of gcc (eg. 3.3) will in fact optimize a "? :" like this + to an arithmetic right shift anyway, but it's good to get the desired + shift on past versions too (in particular since an important use of + LIMB_HIGHBIT_TO_MASK is in udiv_qrnnd_preinv). */ + +#define LIMB_HIGHBIT_TO_MASK(n) \ + (((mp_limb_signed_t) -1 >> 1) < 0 \ + ? (mp_limb_signed_t) (n) >> (GMP_LIMB_BITS - 1) \ + : (n) & GMP_LIMB_HIGHBIT ? MP_LIMB_T_MAX : CNST_LIMB(0)) + + +/* Use a library function for invert_limb, if available. */ +#define mpn_invert_limb __MPN(invert_limb) +__GMP_DECLSPEC mp_limb_t mpn_invert_limb (mp_limb_t) ATTRIBUTE_CONST; +#if ! defined (invert_limb) && HAVE_NATIVE_mpn_invert_limb +#define invert_limb(invxl,xl) \ + do { \ + (invxl) = mpn_invert_limb (xl); \ + } while (0) +#endif + +#ifndef invert_limb +#define invert_limb(invxl,xl) \ + do { \ + mp_limb_t _dummy; \ + ASSERT ((xl) != 0); \ + udiv_qrnnd (invxl, _dummy, ~(xl), ~CNST_LIMB(0), xl); \ + } while (0) +#endif + +#define invert_pi1(dinv, d1, d0) \ + do { \ + mp_limb_t _v, _p, _t1, _t0, _mask; \ + invert_limb (_v, d1); \ + _p = (d1) * _v; \ + _p += (d0); \ + if (_p < (d0)) \ + { \ + _v--; \ + _mask = -(mp_limb_t) (_p >= (d1)); \ + _p -= (d1); \ + _v += _mask; \ + _p -= _mask & (d1); \ + } \ + umul_ppmm (_t1, _t0, d0, _v); \ + _p += _t1; \ + if (_p < _t1) \ + { \ + _v--; \ + if (UNLIKELY (_p >= (d1))) \ + { \ + if (_p > (d1) || _t0 >= (d0)) \ + _v--; \ + } \ + } \ + (dinv).inv32 = _v; \ + } while (0) + + +/* udiv_qrnnd_preinv -- Based on work by Niels Möller and Torbjörn Granlund. + We write things strangely below, to help gcc. A more straightforward + version: + _r = (nl) - _qh * (d); + _t = _r + (d); + if (_r >= _ql) + { + _qh--; + _r = _t; + } + For one operation shorter critical path, one may want to use this form: + _p = _qh * (d) + _s = (nl) + (d); + _r = (nl) - _p; + _t = _s - _p; + if (_r >= _ql) + { + _qh--; + _r = _t; + } +*/ +#define udiv_qrnnd_preinv(q, r, nh, nl, d, di) \ + do { \ + mp_limb_t _qh, _ql, _r, _mask; \ + umul_ppmm (_qh, _ql, (nh), (di)); \ + if (__builtin_constant_p (nl) && (nl) == 0) \ + { \ + _qh += (nh) + 1; \ + _r = - _qh * (d); \ + _mask = -(mp_limb_t) (_r > _ql); /* both > and >= are OK */ \ + _qh += _mask; \ + _r += _mask & (d); \ + } \ + else \ + { \ + add_ssaaaa (_qh, _ql, _qh, _ql, (nh) + 1, (nl)); \ + _r = (nl) - _qh * (d); \ + _mask = -(mp_limb_t) (_r > _ql); /* both > and >= are OK */ \ + _qh += _mask; \ + _r += _mask & (d); \ + if (UNLIKELY (_r >= (d))) \ + { \ + _r -= (d); \ + _qh++; \ + } \ + } \ + (r) = _r; \ + (q) = _qh; \ + } while (0) + +/* Dividing (NH, NL) by D, returning the remainder only. Unlike + udiv_qrnnd_preinv, works also for the case NH == D, where the + quotient doesn't quite fit in a single limb. */ +#define udiv_rnnd_preinv(r, nh, nl, d, di) \ + do { \ + mp_limb_t _qh, _ql, _r, _mask; \ + umul_ppmm (_qh, _ql, (nh), (di)); \ + if (__builtin_constant_p (nl) && (nl) == 0) \ + { \ + _r = ~(_qh + (nh)) * (d); \ + _mask = -(mp_limb_t) (_r > _ql); /* both > and >= are OK */ \ + _r += _mask & (d); \ + } \ + else \ + { \ + add_ssaaaa (_qh, _ql, _qh, _ql, (nh) + 1, (nl)); \ + _r = (nl) - _qh * (d); \ + _mask = -(mp_limb_t) (_r > _ql); /* both > and >= are OK */ \ + _r += _mask & (d); \ + if (UNLIKELY (_r >= (d))) \ + _r -= (d); \ + } \ + (r) = _r; \ + } while (0) + +/* Compute quotient the quotient and remainder for n / d. Requires d + >= B^2 / 2 and n < d B. di is the inverse + + floor ((B^3 - 1) / (d0 + d1 B)) - B. + + NOTE: Output variables are updated multiple times. Only some inputs + and outputs may overlap. +*/ +#define udiv_qr_3by2(q, r1, r0, n2, n1, n0, d1, d0, dinv) \ + do { \ + mp_limb_t _q0, _t1, _t0, _mask; \ + umul_ppmm ((q), _q0, (n2), (dinv)); \ + add_ssaaaa ((q), _q0, (q), _q0, (n2), (n1)); \ + \ + /* Compute the two most significant limbs of n - q'd */ \ + (r1) = (n1) - (d1) * (q); \ + sub_ddmmss ((r1), (r0), (r1), (n0), (d1), (d0)); \ + umul_ppmm (_t1, _t0, (d0), (q)); \ + sub_ddmmss ((r1), (r0), (r1), (r0), _t1, _t0); \ + (q)++; \ + \ + /* Conditionally adjust q and the remainders */ \ + _mask = - (mp_limb_t) ((r1) >= _q0); \ + (q) += _mask; \ + add_ssaaaa ((r1), (r0), (r1), (r0), _mask & (d1), _mask & (d0)); \ + if (UNLIKELY ((r1) >= (d1))) \ + { \ + if ((r1) > (d1) || (r0) >= (d0)) \ + { \ + (q)++; \ + sub_ddmmss ((r1), (r0), (r1), (r0), (d1), (d0)); \ + } \ + } \ + } while (0) + +#ifndef mpn_preinv_divrem_1 /* if not done with cpuvec in a fat binary */ +#define mpn_preinv_divrem_1 __MPN(preinv_divrem_1) +__GMP_DECLSPEC mp_limb_t mpn_preinv_divrem_1 (mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t, int); +#endif + + +/* USE_PREINV_DIVREM_1 is whether to use mpn_preinv_divrem_1, as opposed to the + plain mpn_divrem_1. The default is yes, since the few CISC chips where + preinv is not good have defines saying so. */ +#ifndef USE_PREINV_DIVREM_1 +#define USE_PREINV_DIVREM_1 1 +#endif + +#if USE_PREINV_DIVREM_1 +#define MPN_DIVREM_OR_PREINV_DIVREM_1(qp,xsize,ap,size,d,dinv,shift) \ + mpn_preinv_divrem_1 (qp, xsize, ap, size, d, dinv, shift) +#else +#define MPN_DIVREM_OR_PREINV_DIVREM_1(qp,xsize,ap,size,d,dinv,shift) \ + mpn_divrem_1 (qp, xsize, ap, size, d) +#endif + +#ifndef PREINV_MOD_1_TO_MOD_1_THRESHOLD +#define PREINV_MOD_1_TO_MOD_1_THRESHOLD 10 +#endif + +/* This selection may seem backwards. The reason mpn_mod_1 typically takes + over for larger sizes is that it uses the mod_1_1 function. */ +#define MPN_MOD_OR_PREINV_MOD_1(src,size,divisor,inverse) \ + (BELOW_THRESHOLD (size, PREINV_MOD_1_TO_MOD_1_THRESHOLD) \ + ? mpn_preinv_mod_1 (src, size, divisor, inverse) \ + : mpn_mod_1 (src, size, divisor)) + + +#ifndef mpn_mod_34lsub1 /* if not done with cpuvec in a fat binary */ +#define mpn_mod_34lsub1 __MPN(mod_34lsub1) +__GMP_DECLSPEC mp_limb_t mpn_mod_34lsub1 (mp_srcptr, mp_size_t) __GMP_ATTRIBUTE_PURE; +#endif + + +/* DIVEXACT_1_THRESHOLD is at what size to use mpn_divexact_1, as opposed to + plain mpn_divrem_1. Likewise BMOD_1_TO_MOD_1_THRESHOLD for + mpn_modexact_1_odd against plain mpn_mod_1. On most CPUs divexact and + modexact are faster at all sizes, so the defaults are 0. Those CPUs + where this is not right have a tuned threshold. */ +#ifndef DIVEXACT_1_THRESHOLD +#define DIVEXACT_1_THRESHOLD 0 +#endif +#ifndef BMOD_1_TO_MOD_1_THRESHOLD +#define BMOD_1_TO_MOD_1_THRESHOLD 10 +#endif + +#define MPN_DIVREM_OR_DIVEXACT_1(rp, up, n, d) \ + do { \ + if (BELOW_THRESHOLD (n, DIVEXACT_1_THRESHOLD)) \ + ASSERT_NOCARRY (mpn_divrem_1 (rp, (mp_size_t) 0, up, n, d)); \ + else \ + { \ + ASSERT (mpn_mod_1 (up, n, d) == 0); \ + mpn_divexact_1 (rp, up, n, d); \ + } \ + } while (0) + +#ifndef mpn_modexact_1c_odd /* if not done with cpuvec in a fat binary */ +#define mpn_modexact_1c_odd __MPN(modexact_1c_odd) +__GMP_DECLSPEC mp_limb_t mpn_modexact_1c_odd (mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t) __GMP_ATTRIBUTE_PURE; +#endif + +#if HAVE_NATIVE_mpn_modexact_1_odd +#define mpn_modexact_1_odd __MPN(modexact_1_odd) +__GMP_DECLSPEC mp_limb_t mpn_modexact_1_odd (mp_srcptr, mp_size_t, mp_limb_t) __GMP_ATTRIBUTE_PURE; +#else +#define mpn_modexact_1_odd(src,size,divisor) \ + mpn_modexact_1c_odd (src, size, divisor, CNST_LIMB(0)) +#endif + +#define MPN_MOD_OR_MODEXACT_1_ODD(src,size,divisor) \ + (BELOW_THRESHOLD (size, BMOD_1_TO_MOD_1_THRESHOLD) \ + ? mpn_modexact_1_odd (src, size, divisor) \ + : mpn_mod_1 (src, size, divisor)) + +/* binvert_limb() sets inv to the multiplicative inverse of n modulo + 2^GMP_NUMB_BITS, ie. satisfying inv*n == 1 mod 2^GMP_NUMB_BITS. + n must be odd (otherwise such an inverse doesn't exist). + + This is not to be confused with invert_limb(), which is completely + different. + + The table lookup gives an inverse with the low 8 bits valid, and each + multiply step doubles the number of bits. See Jebelean "An algorithm for + exact division" end of section 4 (reference in gmp.texi). + + Possible enhancement: Could use UHWtype until the last step, if half-size + multiplies are faster (might help under _LONG_LONG_LIMB). + + Alternative: As noted in Granlund and Montgomery "Division by Invariant + Integers using Multiplication" (reference in gmp.texi), n itself gives a + 3-bit inverse immediately, and could be used instead of a table lookup. + A 4-bit inverse can be obtained effectively from xoring bits 1 and 2 into + bit 3, for instance with (((n + 2) & 4) << 1) ^ n. */ + +#define binvert_limb_table __gmp_binvert_limb_table +__GMP_DECLSPEC extern const unsigned char binvert_limb_table[128]; + +#define binvert_limb(inv,n) \ + do { \ + mp_limb_t __n = (n); \ + mp_limb_t __inv; \ + ASSERT ((__n & 1) == 1); \ + \ + __inv = binvert_limb_table[(__n/2) & 0x7F]; /* 8 */ \ + if (GMP_NUMB_BITS > 8) __inv = 2 * __inv - __inv * __inv * __n; \ + if (GMP_NUMB_BITS > 16) __inv = 2 * __inv - __inv * __inv * __n; \ + if (GMP_NUMB_BITS > 32) __inv = 2 * __inv - __inv * __inv * __n; \ + \ + if (GMP_NUMB_BITS > 64) \ + { \ + int __invbits = 64; \ + do { \ + __inv = 2 * __inv - __inv * __inv * __n; \ + __invbits *= 2; \ + } while (__invbits < GMP_NUMB_BITS); \ + } \ + \ + ASSERT ((__inv * __n & GMP_NUMB_MASK) == 1); \ + (inv) = __inv & GMP_NUMB_MASK; \ + } while (0) +#define modlimb_invert binvert_limb /* backward compatibility */ + +/* Multiplicative inverse of 3, modulo 2^GMP_NUMB_BITS. + Eg. 0xAAAAAAAB for 32 bits, 0xAAAAAAAAAAAAAAAB for 64 bits. + GMP_NUMB_MAX/3*2+1 is right when GMP_NUMB_BITS is even, but when it's odd + we need to start from GMP_NUMB_MAX>>1. */ +#define MODLIMB_INVERSE_3 (((GMP_NUMB_MAX >> (GMP_NUMB_BITS % 2)) / 3) * 2 + 1) + +/* ceil(GMP_NUMB_MAX/3) and ceil(2*GMP_NUMB_MAX/3). + These expressions work because GMP_NUMB_MAX%3 != 0 for all GMP_NUMB_BITS. */ +#define GMP_NUMB_CEIL_MAX_DIV3 (GMP_NUMB_MAX / 3 + 1) +#define GMP_NUMB_CEIL_2MAX_DIV3 ((GMP_NUMB_MAX>>1) / 3 + 1 + GMP_NUMB_HIGHBIT) + + +/* Set r to -a mod d. a>=d is allowed. Can give r>d. All should be limbs. + + It's not clear whether this is the best way to do this calculation. + Anything congruent to -a would be fine for the one limb congruence + tests. */ + +#define NEG_MOD(r, a, d) \ + do { \ + ASSERT ((d) != 0); \ + ASSERT_LIMB (a); \ + ASSERT_LIMB (d); \ + \ + if ((a) <= (d)) \ + { \ + /* small a is reasonably likely */ \ + (r) = (d) - (a); \ + } \ + else \ + { \ + unsigned __twos; \ + mp_limb_t __dnorm; \ + count_leading_zeros (__twos, d); \ + __twos -= GMP_NAIL_BITS; \ + __dnorm = (d) << __twos; \ + (r) = ((a) <= __dnorm ? __dnorm : 2*__dnorm) - (a); \ + } \ + \ + ASSERT_LIMB (r); \ + } while (0) + +/* A bit mask of all the least significant zero bits of n, or -1 if n==0. */ +#define LOW_ZEROS_MASK(n) (((n) & -(n)) - 1) + + +/* ULONG_PARITY sets "p" to 1 if there's an odd number of 1 bits in "n", or + to 0 if there's an even number. "n" should be an unsigned long and "p" + an int. */ + +#if defined (__GNUC__) && ! defined (NO_ASM) && HAVE_HOST_CPU_alpha_CIX +#define ULONG_PARITY(p, n) \ + do { \ + int __p; \ + __asm__ ("ctpop %1, %0" : "=r" (__p) : "r" (n)); \ + (p) = __p & 1; \ + } while (0) +#endif + +/* Cray intrinsic _popcnt. */ +#ifdef _CRAY +#define ULONG_PARITY(p, n) \ + do { \ + (p) = _popcnt (n) & 1; \ + } while (0) +#endif + +#if defined (__GNUC__) && ! defined (__INTEL_COMPILER) \ + && ! defined (NO_ASM) && defined (__ia64) +/* unsigned long is either 32 or 64 bits depending on the ABI, zero extend + to a 64 bit unsigned long long for popcnt */ +#define ULONG_PARITY(p, n) \ + do { \ + unsigned long long __n = (unsigned long) (n); \ + int __p; \ + __asm__ ("popcnt %0 = %1" : "=r" (__p) : "r" (__n)); \ + (p) = __p & 1; \ + } while (0) +#endif + +#if defined (__GNUC__) && ! defined (__INTEL_COMPILER) \ + && ! defined (NO_ASM) && HAVE_HOST_CPU_FAMILY_x86 +#if __GMP_GNUC_PREREQ (3,1) +#define __GMP_qm "=Qm" +#define __GMP_q "=Q" +#else +#define __GMP_qm "=qm" +#define __GMP_q "=q" +#endif +#define ULONG_PARITY(p, n) \ + do { \ + char __p; \ + unsigned long __n = (n); \ + __n ^= (__n >> 16); \ + __asm__ ("xorb %h1, %b1\n\t" \ + "setpo %0" \ + : __GMP_qm (__p), __GMP_q (__n) \ + : "1" (__n)); \ + (p) = __p; \ + } while (0) +#endif + +#if ! defined (ULONG_PARITY) +#define ULONG_PARITY(p, n) \ + do { \ + unsigned long __n = (n); \ + int __p = 0; \ + do \ + { \ + __p ^= 0x96696996L >> (__n & 0x1F); \ + __n >>= 5; \ + } \ + while (__n != 0); \ + \ + (p) = __p & 1; \ + } while (0) +#endif + + +/* 3 cycles on 604 or 750 since shifts and rlwimi's can pair. gcc (as of + version 3.1 at least) doesn't seem to know how to generate rlwimi for + anything other than bit-fields, so use "asm". */ +#if defined (__GNUC__) && ! defined (NO_ASM) \ + && HAVE_HOST_CPU_FAMILY_powerpc && GMP_LIMB_BITS == 32 +#define BSWAP_LIMB(dst, src) \ + do { \ + mp_limb_t __bswapl_src = (src); \ + mp_limb_t __tmp1 = __bswapl_src >> 24; /* low byte */ \ + mp_limb_t __tmp2 = __bswapl_src << 24; /* high byte */ \ + __asm__ ("rlwimi %0, %2, 24, 16, 23" /* 2nd low */ \ + : "=r" (__tmp1) : "0" (__tmp1), "r" (__bswapl_src)); \ + __asm__ ("rlwimi %0, %2, 8, 8, 15" /* 3nd high */ \ + : "=r" (__tmp2) : "0" (__tmp2), "r" (__bswapl_src)); \ + (dst) = __tmp1 | __tmp2; /* whole */ \ + } while (0) +#endif + +/* bswap is available on i486 and up and is fast. A combination rorw $8 / + roll $16 / rorw $8 is used in glibc for plain i386 (and in the linux + kernel with xchgb instead of rorw), but this is not done here, because + i386 means generic x86 and mixing word and dword operations will cause + partial register stalls on P6 chips. */ +#if defined (__GNUC__) && ! defined (NO_ASM) \ + && HAVE_HOST_CPU_FAMILY_x86 && ! HAVE_HOST_CPU_i386 \ + && GMP_LIMB_BITS == 32 +#define BSWAP_LIMB(dst, src) \ + do { \ + __asm__ ("bswap %0" : "=r" (dst) : "0" (src)); \ + } while (0) +#endif + +#if defined (__GNUC__) && ! defined (NO_ASM) \ + && defined (__amd64__) && GMP_LIMB_BITS == 64 +#define BSWAP_LIMB(dst, src) \ + do { \ + __asm__ ("bswap %q0" : "=r" (dst) : "0" (src)); \ + } while (0) +#endif + +#if defined (__GNUC__) && ! defined (__INTEL_COMPILER) \ + && ! defined (NO_ASM) && defined (__ia64) && GMP_LIMB_BITS == 64 +#define BSWAP_LIMB(dst, src) \ + do { \ + __asm__ ("mux1 %0 = %1, @rev" : "=r" (dst) : "r" (src)); \ + } while (0) +#endif + +/* As per glibc. */ +#if defined (__GNUC__) && ! defined (NO_ASM) \ + && HAVE_HOST_CPU_FAMILY_m68k && GMP_LIMB_BITS == 32 +#define BSWAP_LIMB(dst, src) \ + do { \ + mp_limb_t __bswapl_src = (src); \ + __asm__ ("ror%.w %#8, %0\n\t" \ + "swap %0\n\t" \ + "ror%.w %#8, %0" \ + : "=d" (dst) \ + : "0" (__bswapl_src)); \ + } while (0) +#endif + +#if ! defined (BSWAP_LIMB) +#if GMP_LIMB_BITS == 8 +#define BSWAP_LIMB(dst, src) \ + do { (dst) = (src); } while (0) +#endif +#if GMP_LIMB_BITS == 16 +#define BSWAP_LIMB(dst, src) \ + do { \ + (dst) = ((src) << 8) + ((src) >> 8); \ + } while (0) +#endif +#if GMP_LIMB_BITS == 32 +#define BSWAP_LIMB(dst, src) \ + do { \ + (dst) = \ + ((src) << 24) \ + + (((src) & 0xFF00) << 8) \ + + (((src) >> 8) & 0xFF00) \ + + ((src) >> 24); \ + } while (0) +#endif +#if GMP_LIMB_BITS == 64 +#define BSWAP_LIMB(dst, src) \ + do { \ + (dst) = \ + ((src) << 56) \ + + (((src) & 0xFF00) << 40) \ + + (((src) & 0xFF0000) << 24) \ + + (((src) & 0xFF000000) << 8) \ + + (((src) >> 8) & 0xFF000000) \ + + (((src) >> 24) & 0xFF0000) \ + + (((src) >> 40) & 0xFF00) \ + + ((src) >> 56); \ + } while (0) +#endif +#endif + +#if ! defined (BSWAP_LIMB) +#define BSWAP_LIMB(dst, src) \ + do { \ + mp_limb_t __bswapl_src = (src); \ + mp_limb_t __dstl = 0; \ + int __i; \ + for (__i = 0; __i < GMP_LIMB_BYTES; __i++) \ + { \ + __dstl = (__dstl << 8) | (__bswapl_src & 0xFF); \ + __bswapl_src >>= 8; \ + } \ + (dst) = __dstl; \ + } while (0) +#endif + + +/* Apparently lwbrx might be slow on some PowerPC chips, so restrict it to + those we know are fast. */ +#if defined (__GNUC__) && ! defined (NO_ASM) \ + && GMP_LIMB_BITS == 32 && HAVE_LIMB_BIG_ENDIAN \ + && (HAVE_HOST_CPU_powerpc604 \ + || HAVE_HOST_CPU_powerpc604e \ + || HAVE_HOST_CPU_powerpc750 \ + || HAVE_HOST_CPU_powerpc7400) +#define BSWAP_LIMB_FETCH(limb, src) \ + do { \ + mp_srcptr __blf_src = (src); \ + mp_limb_t __limb; \ + __asm__ ("lwbrx %0, 0, %1" \ + : "=r" (__limb) \ + : "r" (__blf_src), \ + "m" (*__blf_src)); \ + (limb) = __limb; \ + } while (0) +#endif + +#if ! defined (BSWAP_LIMB_FETCH) +#define BSWAP_LIMB_FETCH(limb, src) BSWAP_LIMB (limb, *(src)) +#endif + + +/* On the same basis that lwbrx might be slow, restrict stwbrx to those we + know are fast. FIXME: Is this necessary? */ +#if defined (__GNUC__) && ! defined (NO_ASM) \ + && GMP_LIMB_BITS == 32 && HAVE_LIMB_BIG_ENDIAN \ + && (HAVE_HOST_CPU_powerpc604 \ + || HAVE_HOST_CPU_powerpc604e \ + || HAVE_HOST_CPU_powerpc750 \ + || HAVE_HOST_CPU_powerpc7400) +#define BSWAP_LIMB_STORE(dst, limb) \ + do { \ + mp_ptr __dst = (dst); \ + mp_limb_t __limb = (limb); \ + __asm__ ("stwbrx %1, 0, %2" \ + : "=m" (*__dst) \ + : "r" (__limb), \ + "r" (__dst)); \ + } while (0) +#endif + +#if ! defined (BSWAP_LIMB_STORE) +#define BSWAP_LIMB_STORE(dst, limb) BSWAP_LIMB (*(dst), limb) +#endif + + +/* Byte swap limbs from {src,size} and store at {dst,size}. */ +#define MPN_BSWAP(dst, src, size) \ + do { \ + mp_ptr __dst = (dst); \ + mp_srcptr __src = (src); \ + mp_size_t __size = (size); \ + mp_size_t __i; \ + ASSERT ((size) >= 0); \ + ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, size)); \ + CRAY_Pragma ("_CRI ivdep"); \ + for (__i = 0; __i < __size; __i++) \ + { \ + BSWAP_LIMB_FETCH (*__dst, __src); \ + __dst++; \ + __src++; \ + } \ + } while (0) + +/* Byte swap limbs from {dst,size} and store in reverse order at {src,size}. */ +#define MPN_BSWAP_REVERSE(dst, src, size) \ + do { \ + mp_ptr __dst = (dst); \ + mp_size_t __size = (size); \ + mp_srcptr __src = (src) + __size - 1; \ + mp_size_t __i; \ + ASSERT ((size) >= 0); \ + ASSERT (! MPN_OVERLAP_P (dst, size, src, size)); \ + CRAY_Pragma ("_CRI ivdep"); \ + for (__i = 0; __i < __size; __i++) \ + { \ + BSWAP_LIMB_FETCH (*__dst, __src); \ + __dst++; \ + __src--; \ + } \ + } while (0) + + +/* No processor claiming to be SPARC v9 compliant seems to + implement the POPC instruction. Disable pattern for now. */ +#if 0 +#if defined __GNUC__ && defined __sparc_v9__ && GMP_LIMB_BITS == 64 +#define popc_limb(result, input) \ + do { \ + DItype __res; \ + __asm__ ("popc %1,%0" : "=r" (result) : "rI" (input)); \ + } while (0) +#endif +#endif + +#if defined (__GNUC__) && ! defined (NO_ASM) && HAVE_HOST_CPU_alpha_CIX +#define popc_limb(result, input) \ + do { \ + __asm__ ("ctpop %1, %0" : "=r" (result) : "r" (input)); \ + } while (0) +#endif + +/* Cray intrinsic. */ +#ifdef _CRAY +#define popc_limb(result, input) \ + do { \ + (result) = _popcnt (input); \ + } while (0) +#endif + +#if defined (__GNUC__) && ! defined (__INTEL_COMPILER) \ + && ! defined (NO_ASM) && defined (__ia64) && GMP_LIMB_BITS == 64 +#define popc_limb(result, input) \ + do { \ + __asm__ ("popcnt %0 = %1" : "=r" (result) : "r" (input)); \ + } while (0) +#endif + +/* Cool population count of an mp_limb_t. + You have to figure out how this works, We won't tell you! + + The constants could also be expressed as: + 0x55... = [2^N / 3] = [(2^N-1)/3] + 0x33... = [2^N / 5] = [(2^N-1)/5] + 0x0f... = [2^N / 17] = [(2^N-1)/17] + (N is GMP_LIMB_BITS, [] denotes truncation.) */ + +#if ! defined (popc_limb) && GMP_LIMB_BITS == 8 +#define popc_limb(result, input) \ + do { \ + mp_limb_t __x = (input); \ + __x -= (__x >> 1) & MP_LIMB_T_MAX/3; \ + __x = ((__x >> 2) & MP_LIMB_T_MAX/5) + (__x & MP_LIMB_T_MAX/5); \ + __x = ((__x >> 4) + __x); \ + (result) = __x & 0x0f; \ + } while (0) +#endif + +#if ! defined (popc_limb) && GMP_LIMB_BITS == 16 +#define popc_limb(result, input) \ + do { \ + mp_limb_t __x = (input); \ + __x -= (__x >> 1) & MP_LIMB_T_MAX/3; \ + __x = ((__x >> 2) & MP_LIMB_T_MAX/5) + (__x & MP_LIMB_T_MAX/5); \ + __x = ((__x >> 4) + __x) & MP_LIMB_T_MAX/17; \ + __x = ((__x >> 8) + __x); \ + (result) = __x & 0xff; \ + } while (0) +#endif + +#if ! defined (popc_limb) && GMP_LIMB_BITS == 32 +#define popc_limb(result, input) \ + do { \ + mp_limb_t __x = (input); \ + __x -= (__x >> 1) & MP_LIMB_T_MAX/3; \ + __x = ((__x >> 2) & MP_LIMB_T_MAX/5) + (__x & MP_LIMB_T_MAX/5); \ + __x = ((__x >> 4) + __x) & MP_LIMB_T_MAX/17; \ + __x = ((__x >> 8) + __x); \ + __x = ((__x >> 16) + __x); \ + (result) = __x & 0xff; \ + } while (0) +#endif + +#if ! defined (popc_limb) && GMP_LIMB_BITS == 64 +#define popc_limb(result, input) \ + do { \ + mp_limb_t __x = (input); \ + __x -= (__x >> 1) & MP_LIMB_T_MAX/3; \ + __x = ((__x >> 2) & MP_LIMB_T_MAX/5) + (__x & MP_LIMB_T_MAX/5); \ + __x = ((__x >> 4) + __x) & MP_LIMB_T_MAX/17; \ + __x = ((__x >> 8) + __x); \ + __x = ((__x >> 16) + __x); \ + __x = ((__x >> 32) + __x); \ + (result) = __x & 0xff; \ + } while (0) +#endif + + +/* Define stuff for longlong.h. */ +#if HAVE_ATTRIBUTE_MODE +typedef unsigned int UQItype __attribute__ ((mode (QI))); +typedef int SItype __attribute__ ((mode (SI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef int DItype __attribute__ ((mode (DI))); +typedef unsigned int UDItype __attribute__ ((mode (DI))); +#else +typedef unsigned char UQItype; +typedef long SItype; +typedef unsigned long USItype; +#if HAVE_LONG_LONG +typedef long long int DItype; +typedef unsigned long long int UDItype; +#else /* Assume `long' gives us a wide enough type. Needed for hppa2.0w. */ +typedef long int DItype; +typedef unsigned long int UDItype; +#endif +#endif + +typedef mp_limb_t UWtype; +typedef unsigned int UHWtype; +#define W_TYPE_SIZE GMP_LIMB_BITS + +/* Define ieee_double_extract and _GMP_IEEE_FLOATS. + + Bit field packing is "implementation defined" according to C99, which + leaves us at the compiler's mercy here. For some systems packing is + defined in the ABI (eg. x86). In any case so far it seems universal that + little endian systems pack from low to high, and big endian from high to + low within the given type. + + Within the fields we rely on the integer endianness being the same as the + float endianness, this is true everywhere we know of and it'd be a fairly + strange system that did anything else. */ + +#if HAVE_DOUBLE_IEEE_LITTLE_SWAPPED +#define _GMP_IEEE_FLOATS 1 +union ieee_double_extract +{ + struct + { + gmp_uint_least32_t manh:20; + gmp_uint_least32_t exp:11; + gmp_uint_least32_t sig:1; + gmp_uint_least32_t manl:32; + } s; + double d; +}; +#endif + +#if HAVE_DOUBLE_IEEE_LITTLE_ENDIAN +#define _GMP_IEEE_FLOATS 1 +union ieee_double_extract +{ + struct + { + gmp_uint_least32_t manl:32; + gmp_uint_least32_t manh:20; + gmp_uint_least32_t exp:11; + gmp_uint_least32_t sig:1; + } s; + double d; +}; +#endif + +#if HAVE_DOUBLE_IEEE_BIG_ENDIAN +#define _GMP_IEEE_FLOATS 1 +union ieee_double_extract +{ + struct + { + gmp_uint_least32_t sig:1; + gmp_uint_least32_t exp:11; + gmp_uint_least32_t manh:20; + gmp_uint_least32_t manl:32; + } s; + double d; +}; +#endif + +#if HAVE_DOUBLE_VAX_D +union double_extract +{ + struct + { + gmp_uint_least32_t man3:7; /* highest 7 bits */ + gmp_uint_least32_t exp:8; /* excess-128 exponent */ + gmp_uint_least32_t sig:1; + gmp_uint_least32_t man2:16; + gmp_uint_least32_t man1:16; + gmp_uint_least32_t man0:16; /* lowest 16 bits */ + } s; + double d; +}; +#endif + +/* Use (4.0 * ...) instead of (2.0 * ...) to work around buggy compilers + that don't convert ulong->double correctly (eg. SunOS 4 native cc). */ +#define MP_BASE_AS_DOUBLE (4.0 * ((mp_limb_t) 1 << (GMP_NUMB_BITS - 2))) +/* Maximum number of limbs it will take to store any `double'. + We assume doubles have 53 mantissa bits. */ +#define LIMBS_PER_DOUBLE ((53 + GMP_NUMB_BITS - 2) / GMP_NUMB_BITS + 1) + +__GMP_DECLSPEC int __gmp_extract_double (mp_ptr, double); + +#define mpn_get_d __gmpn_get_d +__GMP_DECLSPEC double mpn_get_d (mp_srcptr, mp_size_t, mp_size_t, long) __GMP_ATTRIBUTE_PURE; + + +/* DOUBLE_NAN_INF_ACTION executes code a_nan if x is a NaN, or executes + a_inf if x is an infinity. Both are considered unlikely values, for + branch prediction. */ + +#if _GMP_IEEE_FLOATS +#define DOUBLE_NAN_INF_ACTION(x, a_nan, a_inf) \ + do { \ + union ieee_double_extract u; \ + u.d = (x); \ + if (UNLIKELY (u.s.exp == 0x7FF)) \ + { \ + if (u.s.manl == 0 && u.s.manh == 0) \ + { a_inf; } \ + else \ + { a_nan; } \ + } \ + } while (0) +#endif + +#if HAVE_DOUBLE_VAX_D || HAVE_DOUBLE_VAX_G || HAVE_DOUBLE_CRAY_CFP +/* no nans or infs in these formats */ +#define DOUBLE_NAN_INF_ACTION(x, a_nan, a_inf) \ + do { } while (0) +#endif + +#ifndef DOUBLE_NAN_INF_ACTION +/* Unknown format, try something generic. + NaN should be "unordered", so x!=x. + Inf should be bigger than DBL_MAX. */ +#define DOUBLE_NAN_INF_ACTION(x, a_nan, a_inf) \ + do { \ + { \ + if (UNLIKELY ((x) != (x))) \ + { a_nan; } \ + else if (UNLIKELY ((x) > DBL_MAX || (x) < -DBL_MAX)) \ + { a_inf; } \ + } \ + } while (0) +#endif + +/* On m68k, x86 and amd64, gcc (and maybe other compilers) can hold doubles + in the coprocessor, which means a bigger exponent range than normal, and + depending on the rounding mode, a bigger mantissa than normal. (See + "Disappointments" in the gcc manual.) FORCE_DOUBLE stores and fetches + "d" through memory to force any rounding and overflows to occur. + + On amd64, and on x86s with SSE2, gcc (depending on options) uses the xmm + registers, where there's no such extra precision and no need for the + FORCE_DOUBLE. We don't bother to detect this since the present uses for + FORCE_DOUBLE are only in test programs and default generic C code. + + Not quite sure that an "automatic volatile" will use memory, but it does + in gcc. An asm("":"=m"(d):"0"(d)) can't be used to trick gcc, since + apparently matching operands like "0" are only allowed on a register + output. gcc 3.4 warns about this, though in fact it and past versions + seem to put the operand through memory as hoped. */ + +#if (HAVE_HOST_CPU_FAMILY_m68k || HAVE_HOST_CPU_FAMILY_x86 \ + || defined (__amd64__)) +#define FORCE_DOUBLE(d) \ + do { volatile double __gmp_force = (d); (d) = __gmp_force; } while (0) +#else +#define FORCE_DOUBLE(d) do { } while (0) +#endif + + +__GMP_DECLSPEC extern const unsigned char __gmp_digit_value_tab[]; + +__GMP_DECLSPEC extern int __gmp_junk; +__GMP_DECLSPEC extern const int __gmp_0; +__GMP_DECLSPEC void __gmp_exception (int) ATTRIBUTE_NORETURN; +__GMP_DECLSPEC void __gmp_divide_by_zero (void) ATTRIBUTE_NORETURN; +__GMP_DECLSPEC void __gmp_sqrt_of_negative (void) ATTRIBUTE_NORETURN; +__GMP_DECLSPEC void __gmp_invalid_operation (void) ATTRIBUTE_NORETURN; +#define GMP_ERROR(code) __gmp_exception (code) +#define DIVIDE_BY_ZERO __gmp_divide_by_zero () +#define SQRT_OF_NEGATIVE __gmp_sqrt_of_negative () + +#if defined _LONG_LONG_LIMB +#define CNST_LIMB(C) ((mp_limb_t) C##LL) +#else /* not _LONG_LONG_LIMB */ +#define CNST_LIMB(C) ((mp_limb_t) C##L) +#endif /* _LONG_LONG_LIMB */ + +/* Stuff used by mpn/generic/perfsqr.c and mpz/prime_p.c */ +#if GMP_NUMB_BITS == 2 +#define PP 0x3 /* 3 */ +#define PP_FIRST_OMITTED 5 +#endif +#if GMP_NUMB_BITS == 4 +#define PP 0xF /* 3 x 5 */ +#define PP_FIRST_OMITTED 7 +#endif +#if GMP_NUMB_BITS == 8 +#define PP 0x69 /* 3 x 5 x 7 */ +#define PP_FIRST_OMITTED 11 +#endif +#if GMP_NUMB_BITS == 16 +#define PP 0x3AA7 /* 3 x 5 x 7 x 11 x 13 */ +#define PP_FIRST_OMITTED 17 +#endif +#if GMP_NUMB_BITS == 32 +#define PP 0xC0CFD797L /* 3 x 5 x 7 x 11 x ... x 29 */ +#define PP_INVERTED 0x53E5645CL +#define PP_FIRST_OMITTED 31 +#endif +#if GMP_NUMB_BITS == 64 +#define PP CNST_LIMB(0xE221F97C30E94E1D) /* 3 x 5 x 7 x 11 x ... x 53 */ +#define PP_INVERTED CNST_LIMB(0x21CFE6CFC938B36B) +#define PP_FIRST_OMITTED 59 +#endif +#ifndef PP_FIRST_OMITTED +#define PP_FIRST_OMITTED 3 +#endif + +/* BIT1 means a result value in bit 1 (second least significant bit), with a + zero bit representing +1 and a one bit representing -1. Bits other than + bit 1 are garbage. These are meant to be kept in "int"s, and casts are + used to ensure the expressions are "int"s even if a and/or b might be + other types. + + JACOBI_TWOS_U_BIT1 and JACOBI_RECIP_UU_BIT1 are used in mpn_jacobi_base + and their speed is important. Expressions are used rather than + conditionals to accumulate sign changes, which effectively means XORs + instead of conditional JUMPs. */ + +/* (a/0), with a signed; is 1 if a=+/-1, 0 otherwise */ +#define JACOBI_S0(a) (((a) == 1) | ((a) == -1)) + +/* (a/0), with a unsigned; is 1 if a=+/-1, 0 otherwise */ +#define JACOBI_U0(a) ((a) == 1) + +/* FIXME: JACOBI_LS0 and JACOBI_0LS are the same, so delete one and + come up with a better name. */ + +/* (a/0), with a given by low and size; + is 1 if a=+/-1, 0 otherwise */ +#define JACOBI_LS0(alow,asize) \ + (((asize) == 1 || (asize) == -1) && (alow) == 1) + +/* (a/0), with a an mpz_t; + fetch of low limb always valid, even if size is zero */ +#define JACOBI_Z0(a) JACOBI_LS0 (PTR(a)[0], SIZ(a)) + +/* (0/b), with b unsigned; is 1 if b=1, 0 otherwise */ +#define JACOBI_0U(b) ((b) == 1) + +/* (0/b), with b unsigned; is 1 if b=+/-1, 0 otherwise */ +#define JACOBI_0S(b) ((b) == 1 || (b) == -1) + +/* (0/b), with b given by low and size; is 1 if b=+/-1, 0 otherwise */ +#define JACOBI_0LS(blow,bsize) \ + (((bsize) == 1 || (bsize) == -1) && (blow) == 1) + +/* Convert a bit1 to +1 or -1. */ +#define JACOBI_BIT1_TO_PN(result_bit1) \ + (1 - ((int) (result_bit1) & 2)) + +/* (2/b), with b unsigned and odd; + is (-1)^((b^2-1)/8) which is 1 if b==1,7mod8 or -1 if b==3,5mod8 and + hence obtained from (b>>1)^b */ +#define JACOBI_TWO_U_BIT1(b) \ + ((int) (((b) >> 1) ^ (b))) + +/* (2/b)^twos, with b unsigned and odd */ +#define JACOBI_TWOS_U_BIT1(twos, b) \ + ((int) ((twos) << 1) & JACOBI_TWO_U_BIT1 (b)) + +/* (2/b)^twos, with b unsigned and odd */ +#define JACOBI_TWOS_U(twos, b) \ + (JACOBI_BIT1_TO_PN (JACOBI_TWOS_U_BIT1 (twos, b))) + +/* (-1/b), with b odd (signed or unsigned); + is (-1)^((b-1)/2) */ +#define JACOBI_N1B_BIT1(b) \ + ((int) (b)) + +/* (a/b) effect due to sign of a: signed/unsigned, b odd; + is (-1/b) if a<0, or +1 if a>=0 */ +#define JACOBI_ASGN_SU_BIT1(a, b) \ + ((((a) < 0) << 1) & JACOBI_N1B_BIT1(b)) + +/* (a/b) effect due to sign of b: signed/signed; + is -1 if a and b both negative, +1 otherwise */ +#define JACOBI_BSGN_SS_BIT1(a, b) \ + ((((a)<0) & ((b)<0)) << 1) + +/* (a/b) effect due to sign of b: signed/mpz; + is -1 if a and b both negative, +1 otherwise */ +#define JACOBI_BSGN_SZ_BIT1(a, b) \ + JACOBI_BSGN_SS_BIT1 (a, SIZ(b)) + +/* (a/b) effect due to sign of b: mpz/signed; + is -1 if a and b both negative, +1 otherwise */ +#define JACOBI_BSGN_ZS_BIT1(a, b) \ + JACOBI_BSGN_SZ_BIT1 (b, a) + +/* (a/b) reciprocity to switch to (b/a), a,b both unsigned and odd; + is (-1)^((a-1)*(b-1)/4), which means +1 if either a,b==1mod4, or -1 if + both a,b==3mod4, achieved in bit 1 by a&b. No ASSERT()s about a,b odd + because this is used in a couple of places with only bit 1 of a or b + valid. */ +#define JACOBI_RECIP_UU_BIT1(a, b) \ + ((int) ((a) & (b))) + +/* Strip low zero limbs from {b_ptr,b_size} by incrementing b_ptr and + decrementing b_size. b_low should be b_ptr[0] on entry, and will be + updated for the new b_ptr. result_bit1 is updated according to the + factors of 2 stripped, as per (a/2). */ +#define JACOBI_STRIP_LOW_ZEROS(result_bit1, a, b_ptr, b_size, b_low) \ + do { \ + ASSERT ((b_size) >= 1); \ + ASSERT ((b_low) == (b_ptr)[0]); \ + \ + while (UNLIKELY ((b_low) == 0)) \ + { \ + (b_size)--; \ + ASSERT ((b_size) >= 1); \ + (b_ptr)++; \ + (b_low) = *(b_ptr); \ + \ + ASSERT (((a) & 1) != 0); \ + if ((GMP_NUMB_BITS % 2) == 1) \ + (result_bit1) ^= JACOBI_TWO_U_BIT1(a); \ + } \ + } while (0) + +/* Set a_rem to {a_ptr,a_size} reduced modulo b, either using mod_1 or + modexact_1_odd, but in either case leaving a_rem<b. b must be odd and + unsigned. modexact_1_odd effectively calculates -a mod b, and + result_bit1 is adjusted for the factor of -1. + + The way mpn_modexact_1_odd sometimes bases its remainder on a_size and + sometimes on a_size-1 means if GMP_NUMB_BITS is odd we can't know what + factor to introduce into result_bit1, so for that case use mpn_mod_1 + unconditionally. + + FIXME: mpn_modexact_1_odd is more efficient, so some way to get it used + for odd GMP_NUMB_BITS would be good. Perhaps it could mung its result, + or not skip a divide step, or something. */ + +#define JACOBI_MOD_OR_MODEXACT_1_ODD(result_bit1, a_rem, a_ptr, a_size, b) \ + do { \ + mp_srcptr __a_ptr = (a_ptr); \ + mp_size_t __a_size = (a_size); \ + mp_limb_t __b = (b); \ + \ + ASSERT (__a_size >= 1); \ + ASSERT (__b & 1); \ + \ + if ((GMP_NUMB_BITS % 2) != 0 \ + || ABOVE_THRESHOLD (__a_size, BMOD_1_TO_MOD_1_THRESHOLD)) \ + { \ + (a_rem) = mpn_mod_1 (__a_ptr, __a_size, __b); \ + } \ + else \ + { \ + (result_bit1) ^= JACOBI_N1B_BIT1 (__b); \ + (a_rem) = mpn_modexact_1_odd (__a_ptr, __a_size, __b); \ + } \ + } while (0) + +/* State for the Jacobi computation using Lehmer. */ +#define jacobi_table __gmp_jacobi_table +__GMP_DECLSPEC extern const unsigned char jacobi_table[208]; + +/* Bit layout for the initial state. b must be odd. + + 3 2 1 0 + +--+--+--+--+ + |a1|a0|b1| s| + +--+--+--+--+ + + */ +static inline unsigned +mpn_jacobi_init (unsigned a, unsigned b, unsigned s) +{ + ASSERT (b & 1); + ASSERT (s <= 1); + return ((a & 3) << 2) + (b & 2) + s; +} + +static inline int +mpn_jacobi_finish (unsigned bits) +{ + /* (a, b) = (1,0) or (0,1) */ + ASSERT ( (bits & 14) == 0); + + return 1-2*(bits & 1); +} + +static inline unsigned +mpn_jacobi_update (unsigned bits, unsigned denominator, unsigned q) +{ + /* FIXME: Could halve table size by not including the e bit in the + * index, and instead xor when updating. Then the lookup would be + * like + * + * bits ^= table[((bits & 30) << 2) + (denominator << 2) + q]; + */ + + ASSERT (bits < 26); + ASSERT (denominator < 2); + ASSERT (q < 4); + + /* For almost all calls, denominator is constant and quite often q + is constant too. So use addition rather than or, so the compiler + can put the constant part can into the offset of an indexed + addressing instruction. + + With constant denominator, the below table lookup is compiled to + + C Constant q = 1, constant denominator = 1 + movzbl table+5(%eax,8), %eax + + or + + C q in %edx, constant denominator = 1 + movzbl table+4(%edx,%eax,8), %eax + + One could maintain the state preshifted 3 bits, to save a shift + here, but at least on x86, that's no real saving. + */ + return bits = jacobi_table[(bits << 3) + (denominator << 2) + q]; +} + +/* Matrix multiplication */ +#define mpn_matrix22_mul __MPN(matrix22_mul) +__GMP_DECLSPEC void mpn_matrix22_mul (mp_ptr, mp_ptr, mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_srcptr, mp_srcptr, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_matrix22_mul_strassen __MPN(matrix22_mul_strassen) +__GMP_DECLSPEC void mpn_matrix22_mul_strassen (mp_ptr, mp_ptr, mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_srcptr, mp_srcptr, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_matrix22_mul_itch __MPN(matrix22_mul_itch) +__GMP_DECLSPEC mp_size_t mpn_matrix22_mul_itch (mp_size_t, mp_size_t) ATTRIBUTE_CONST; + +#ifndef MATRIX22_STRASSEN_THRESHOLD +#define MATRIX22_STRASSEN_THRESHOLD 30 +#endif + +/* HGCD definitions */ + +/* Extract one numb, shifting count bits left + ________ ________ + |___xh___||___xl___| + |____r____| + >count < + + The count includes any nail bits, so it should work fine if count + is computed using count_leading_zeros. If GMP_NAIL_BITS > 0, all of + xh, xl and r include nail bits. Must have 0 < count < GMP_LIMB_BITS. + + FIXME: Omit masking with GMP_NUMB_MASK, and let callers do that for + those calls where the count high bits of xh may be non-zero. +*/ + +#define MPN_EXTRACT_NUMB(count, xh, xl) \ + ((((xh) << ((count) - GMP_NAIL_BITS)) & GMP_NUMB_MASK) | \ + ((xl) >> (GMP_LIMB_BITS - (count)))) + + +/* The matrix non-negative M = (u, u'; v,v') keeps track of the + reduction (a;b) = M (alpha; beta) where alpha, beta are smaller + than a, b. The determinant must always be one, so that M has an + inverse (v', -u'; -v, u). Elements always fit in GMP_NUMB_BITS - 1 + bits. */ +struct hgcd_matrix1 +{ + mp_limb_t u[2][2]; +}; + +#define mpn_hgcd2 __MPN (hgcd2) +__GMP_DECLSPEC int mpn_hgcd2 (mp_limb_t, mp_limb_t, mp_limb_t, mp_limb_t, struct hgcd_matrix1 *); + +#define mpn_hgcd_mul_matrix1_vector __MPN (hgcd_mul_matrix1_vector) +__GMP_DECLSPEC mp_size_t mpn_hgcd_mul_matrix1_vector (const struct hgcd_matrix1 *, mp_ptr, mp_srcptr, mp_ptr, mp_size_t); + +#define mpn_matrix22_mul1_inverse_vector __MPN (matrix22_mul1_inverse_vector) +__GMP_DECLSPEC mp_size_t mpn_matrix22_mul1_inverse_vector (const struct hgcd_matrix1 *, mp_ptr, mp_srcptr, mp_ptr, mp_size_t); + +#define mpn_hgcd2_jacobi __MPN (hgcd2_jacobi) +__GMP_DECLSPEC int mpn_hgcd2_jacobi (mp_limb_t, mp_limb_t, mp_limb_t, mp_limb_t, struct hgcd_matrix1 *, unsigned *); + +struct hgcd_matrix +{ + mp_size_t alloc; /* for sanity checking only */ + mp_size_t n; + mp_ptr p[2][2]; +}; + +#define MPN_HGCD_MATRIX_INIT_ITCH(n) (4 * ((n+1)/2 + 1)) + +#define mpn_hgcd_matrix_init __MPN (hgcd_matrix_init) +__GMP_DECLSPEC void mpn_hgcd_matrix_init (struct hgcd_matrix *, mp_size_t, mp_ptr); + +#define mpn_hgcd_matrix_update_q __MPN (hgcd_matrix_update_q) +__GMP_DECLSPEC void mpn_hgcd_matrix_update_q (struct hgcd_matrix *, mp_srcptr, mp_size_t, unsigned, mp_ptr); + +#define mpn_hgcd_matrix_mul_1 __MPN (hgcd_matrix_mul_1) +__GMP_DECLSPEC void mpn_hgcd_matrix_mul_1 (struct hgcd_matrix *, const struct hgcd_matrix1 *, mp_ptr); + +#define mpn_hgcd_matrix_mul __MPN (hgcd_matrix_mul) +__GMP_DECLSPEC void mpn_hgcd_matrix_mul (struct hgcd_matrix *, const struct hgcd_matrix *, mp_ptr); + +#define mpn_hgcd_matrix_adjust __MPN (hgcd_matrix_adjust) +__GMP_DECLSPEC mp_size_t mpn_hgcd_matrix_adjust (const struct hgcd_matrix *, mp_size_t, mp_ptr, mp_ptr, mp_size_t, mp_ptr); + +#define mpn_hgcd_step __MPN(hgcd_step) +__GMP_DECLSPEC mp_size_t mpn_hgcd_step (mp_size_t, mp_ptr, mp_ptr, mp_size_t, struct hgcd_matrix *, mp_ptr); + +#define mpn_hgcd_reduce __MPN(hgcd_reduce) +__GMP_DECLSPEC mp_size_t mpn_hgcd_reduce (struct hgcd_matrix *, mp_ptr, mp_ptr, mp_size_t, mp_size_t, mp_ptr); + +#define mpn_hgcd_reduce_itch __MPN(hgcd_reduce_itch) +__GMP_DECLSPEC mp_size_t mpn_hgcd_reduce_itch (mp_size_t, mp_size_t) ATTRIBUTE_CONST; + +#define mpn_hgcd_itch __MPN (hgcd_itch) +__GMP_DECLSPEC mp_size_t mpn_hgcd_itch (mp_size_t) ATTRIBUTE_CONST; + +#define mpn_hgcd __MPN (hgcd) +__GMP_DECLSPEC mp_size_t mpn_hgcd (mp_ptr, mp_ptr, mp_size_t, struct hgcd_matrix *, mp_ptr); + +#define mpn_hgcd_appr_itch __MPN (hgcd_appr_itch) +__GMP_DECLSPEC mp_size_t mpn_hgcd_appr_itch (mp_size_t) ATTRIBUTE_CONST; + +#define mpn_hgcd_appr __MPN (hgcd_appr) +__GMP_DECLSPEC int mpn_hgcd_appr (mp_ptr, mp_ptr, mp_size_t, struct hgcd_matrix *, mp_ptr); + +#define mpn_hgcd_jacobi __MPN (hgcd_jacobi) +__GMP_DECLSPEC mp_size_t mpn_hgcd_jacobi (mp_ptr, mp_ptr, mp_size_t, struct hgcd_matrix *, unsigned *, mp_ptr); + +typedef void gcd_subdiv_step_hook(void *, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, int); + +/* Needs storage for the quotient */ +#define MPN_GCD_SUBDIV_STEP_ITCH(n) (n) + +#define mpn_gcd_subdiv_step __MPN(gcd_subdiv_step) +__GMP_DECLSPEC mp_size_t mpn_gcd_subdiv_step (mp_ptr, mp_ptr, mp_size_t, mp_size_t, gcd_subdiv_step_hook *, void *, mp_ptr); + +struct gcdext_ctx +{ + /* Result parameters. */ + mp_ptr gp; + mp_size_t gn; + mp_ptr up; + mp_size_t *usize; + + /* Cofactors updated in each step. */ + mp_size_t un; + mp_ptr u0, u1, tp; +}; + +#define mpn_gcdext_hook __MPN (gcdext_hook) +gcd_subdiv_step_hook mpn_gcdext_hook; + +#define MPN_GCDEXT_LEHMER_N_ITCH(n) (4*(n) + 3) + +#define mpn_gcdext_lehmer_n __MPN(gcdext_lehmer_n) +__GMP_DECLSPEC mp_size_t mpn_gcdext_lehmer_n (mp_ptr, mp_ptr, mp_size_t *, mp_ptr, mp_ptr, mp_size_t, mp_ptr); + +/* 4*(an + 1) + 4*(bn + 1) + an */ +#define MPN_GCDEXT_LEHMER_ITCH(an, bn) (5*(an) + 4*(bn) + 8) + +#ifndef HGCD_THRESHOLD +#define HGCD_THRESHOLD 400 +#endif + +#ifndef HGCD_APPR_THRESHOLD +#define HGCD_APPR_THRESHOLD 400 +#endif + +#ifndef HGCD_REDUCE_THRESHOLD +#define HGCD_REDUCE_THRESHOLD 1000 +#endif + +#ifndef GCD_DC_THRESHOLD +#define GCD_DC_THRESHOLD 1000 +#endif + +#ifndef GCDEXT_DC_THRESHOLD +#define GCDEXT_DC_THRESHOLD 600 +#endif + +/* Definitions for mpn_set_str and mpn_get_str */ +struct powers +{ + mp_ptr p; /* actual power value */ + mp_size_t n; /* # of limbs at p */ + mp_size_t shift; /* weight of lowest limb, in limb base B */ + size_t digits_in_base; /* number of corresponding digits */ + int base; +}; +typedef struct powers powers_t; +#define mpn_dc_set_str_powtab_alloc(n) ((n) + GMP_LIMB_BITS) +#define mpn_dc_set_str_itch(n) ((n) + GMP_LIMB_BITS) +#define mpn_dc_get_str_powtab_alloc(n) ((n) + 2 * GMP_LIMB_BITS) +#define mpn_dc_get_str_itch(n) ((n) + GMP_LIMB_BITS) + +#define mpn_dc_set_str __MPN(dc_set_str) +__GMP_DECLSPEC mp_size_t mpn_dc_set_str (mp_ptr, const unsigned char *, size_t, const powers_t *, mp_ptr); +#define mpn_bc_set_str __MPN(bc_set_str) +__GMP_DECLSPEC mp_size_t mpn_bc_set_str (mp_ptr, const unsigned char *, size_t, int); +#define mpn_set_str_compute_powtab __MPN(set_str_compute_powtab) +__GMP_DECLSPEC void mpn_set_str_compute_powtab (powers_t *, mp_ptr, mp_size_t, int); + + +/* __GMPF_BITS_TO_PREC applies a minimum 53 bits, rounds upwards to a whole + limb and adds an extra limb. __GMPF_PREC_TO_BITS drops that extra limb, + hence giving back the user's size in bits rounded up. Notice that + converting prec->bits->prec gives an unchanged value. */ +#define __GMPF_BITS_TO_PREC(n) \ + ((mp_size_t) ((__GMP_MAX (53, n) + 2 * GMP_NUMB_BITS - 1) / GMP_NUMB_BITS)) +#define __GMPF_PREC_TO_BITS(n) \ + ((mp_bitcnt_t) (n) * GMP_NUMB_BITS - GMP_NUMB_BITS) + +__GMP_DECLSPEC extern mp_size_t __gmp_default_fp_limb_precision; + +/* Compute the number of base-b digits corresponding to nlimbs limbs, rounding + down. */ +#define DIGITS_IN_BASE_PER_LIMB(res, nlimbs, b) \ + do { \ + mp_limb_t _ph, _dummy; \ + umul_ppmm (_ph, _dummy, \ + mp_bases[b].logb2, GMP_NUMB_BITS * (mp_limb_t) (nlimbs));\ + res = _ph; \ + } while (0) + +/* Compute the number of limbs corresponding to ndigits base-b digits, rounding + up. */ +#define LIMBS_PER_DIGIT_IN_BASE(res, ndigits, b) \ + do { \ + mp_limb_t _ph, _dummy; \ + umul_ppmm (_ph, _dummy, mp_bases[b].log2b, (mp_limb_t) (ndigits)); \ + res = 8 * _ph / GMP_NUMB_BITS + 2; \ + } while (0) + + +/* Set n to the number of significant digits an mpf of the given _mp_prec + field, in the given base. This is a rounded up value, designed to ensure + there's enough digits to reproduce all the guaranteed part of the value. + + There are prec many limbs, but the high might be only "1" so forget it + and just count prec-1 limbs into chars. +1 rounds that upwards, and a + further +1 is because the limbs usually won't fall on digit boundaries. + + FIXME: If base is a power of 2 and the bits per digit divides + GMP_LIMB_BITS then the +2 is unnecessary. This happens always for + base==2, and in base==16 with the current 32 or 64 bit limb sizes. */ + +#define MPF_SIGNIFICANT_DIGITS(n, base, prec) \ + do { \ + size_t rawn; \ + ASSERT (base >= 2 && base < numberof (mp_bases)); \ + DIGITS_IN_BASE_PER_LIMB (rawn, (prec) - 1, base); \ + n = rawn + 2; \ + } while (0) + + +/* Decimal point string, from the current C locale. Needs <langinfo.h> for + nl_langinfo and constants, preferably with _GNU_SOURCE defined to get + DECIMAL_POINT from glibc, and needs <locale.h> for localeconv, each under + their respective #if HAVE_FOO_H. + + GLIBC recommends nl_langinfo because getting only one facet can be + faster, apparently. */ + +/* DECIMAL_POINT seems to need _GNU_SOURCE defined to get it from glibc. */ +#if HAVE_NL_LANGINFO && defined (DECIMAL_POINT) +#define GMP_DECIMAL_POINT (nl_langinfo (DECIMAL_POINT)) +#endif +/* RADIXCHAR is deprecated, still in unix98 or some such. */ +#if HAVE_NL_LANGINFO && defined (RADIXCHAR) && ! defined (GMP_DECIMAL_POINT) +#define GMP_DECIMAL_POINT (nl_langinfo (RADIXCHAR)) +#endif +/* localeconv is slower since it returns all locale stuff */ +#if HAVE_LOCALECONV && ! defined (GMP_DECIMAL_POINT) +#define GMP_DECIMAL_POINT (localeconv()->decimal_point) +#endif +#if ! defined (GMP_DECIMAL_POINT) +#define GMP_DECIMAL_POINT (".") +#endif + + +#define DOPRNT_CONV_FIXED 1 +#define DOPRNT_CONV_SCIENTIFIC 2 +#define DOPRNT_CONV_GENERAL 3 + +#define DOPRNT_JUSTIFY_NONE 0 +#define DOPRNT_JUSTIFY_LEFT 1 +#define DOPRNT_JUSTIFY_RIGHT 2 +#define DOPRNT_JUSTIFY_INTERNAL 3 + +#define DOPRNT_SHOWBASE_YES 1 +#define DOPRNT_SHOWBASE_NO 2 +#define DOPRNT_SHOWBASE_NONZERO 3 + +struct doprnt_params_t { + int base; /* negative for upper case */ + int conv; /* choices above */ + const char *expfmt; /* exponent format */ + int exptimes4; /* exponent multiply by 4 */ + char fill; /* character */ + int justify; /* choices above */ + int prec; /* prec field, or -1 for all digits */ + int showbase; /* choices above */ + int showpoint; /* if radix point always shown */ + int showtrailing; /* if trailing zeros wanted */ + char sign; /* '+', ' ', or '\0' */ + int width; /* width field */ +}; + +#if _GMP_H_HAVE_VA_LIST + +typedef int (*doprnt_format_t) (void *, const char *, va_list); +typedef int (*doprnt_memory_t) (void *, const char *, size_t); +typedef int (*doprnt_reps_t) (void *, int, int); +typedef int (*doprnt_final_t) (void *); + +struct doprnt_funs_t { + doprnt_format_t format; + doprnt_memory_t memory; + doprnt_reps_t reps; + doprnt_final_t final; /* NULL if not required */ +}; + +extern const struct doprnt_funs_t __gmp_fprintf_funs; +extern const struct doprnt_funs_t __gmp_sprintf_funs; +extern const struct doprnt_funs_t __gmp_snprintf_funs; +extern const struct doprnt_funs_t __gmp_obstack_printf_funs; +extern const struct doprnt_funs_t __gmp_ostream_funs; + +/* "buf" is a __gmp_allocate_func block of "alloc" many bytes. The first + "size" of these have been written. "alloc > size" is maintained, so + there's room to store a '\0' at the end. "result" is where the + application wants the final block pointer. */ +struct gmp_asprintf_t { + char **result; + char *buf; + size_t size; + size_t alloc; +}; + +#define GMP_ASPRINTF_T_INIT(d, output) \ + do { \ + (d).result = (output); \ + (d).alloc = 256; \ + (d).buf = (char *) (*__gmp_allocate_func) ((d).alloc); \ + (d).size = 0; \ + } while (0) + +/* If a realloc is necessary, use twice the size actually required, so as to + avoid repeated small reallocs. */ +#define GMP_ASPRINTF_T_NEED(d, n) \ + do { \ + size_t alloc, newsize, newalloc; \ + ASSERT ((d)->alloc >= (d)->size + 1); \ + \ + alloc = (d)->alloc; \ + newsize = (d)->size + (n); \ + if (alloc <= newsize) \ + { \ + newalloc = 2*newsize; \ + (d)->alloc = newalloc; \ + (d)->buf = __GMP_REALLOCATE_FUNC_TYPE ((d)->buf, \ + alloc, newalloc, char); \ + } \ + } while (0) + +__GMP_DECLSPEC int __gmp_asprintf_memory (struct gmp_asprintf_t *, const char *, size_t); +__GMP_DECLSPEC int __gmp_asprintf_reps (struct gmp_asprintf_t *, int, int); +__GMP_DECLSPEC int __gmp_asprintf_final (struct gmp_asprintf_t *); + +/* buf is where to write the next output, and size is how much space is left + there. If the application passed size==0 then that's what we'll have + here, and nothing at all should be written. */ +struct gmp_snprintf_t { + char *buf; + size_t size; +}; + +/* Add the bytes printed by the call to the total retval, or bail out on an + error. */ +#define DOPRNT_ACCUMULATE(call) \ + do { \ + int __ret; \ + __ret = call; \ + if (__ret == -1) \ + goto error; \ + retval += __ret; \ + } while (0) +#define DOPRNT_ACCUMULATE_FUN(fun, params) \ + do { \ + ASSERT ((fun) != NULL); \ + DOPRNT_ACCUMULATE ((*(fun)) params); \ + } while (0) + +#define DOPRNT_FORMAT(fmt, ap) \ + DOPRNT_ACCUMULATE_FUN (funs->format, (data, fmt, ap)) +#define DOPRNT_MEMORY(ptr, len) \ + DOPRNT_ACCUMULATE_FUN (funs->memory, (data, ptr, len)) +#define DOPRNT_REPS(c, n) \ + DOPRNT_ACCUMULATE_FUN (funs->reps, (data, c, n)) + +#define DOPRNT_STRING(str) DOPRNT_MEMORY (str, strlen (str)) + +#define DOPRNT_REPS_MAYBE(c, n) \ + do { \ + if ((n) != 0) \ + DOPRNT_REPS (c, n); \ + } while (0) +#define DOPRNT_MEMORY_MAYBE(ptr, len) \ + do { \ + if ((len) != 0) \ + DOPRNT_MEMORY (ptr, len); \ + } while (0) + +__GMP_DECLSPEC int __gmp_doprnt (const struct doprnt_funs_t *, void *, const char *, va_list); +__GMP_DECLSPEC int __gmp_doprnt_integer (const struct doprnt_funs_t *, void *, const struct doprnt_params_t *, const char *); + +#define __gmp_doprnt_mpf __gmp_doprnt_mpf2 +__GMP_DECLSPEC int __gmp_doprnt_mpf (const struct doprnt_funs_t *, void *, const struct doprnt_params_t *, const char *, mpf_srcptr); + +__GMP_DECLSPEC int __gmp_replacement_vsnprintf (char *, size_t, const char *, va_list); +#endif /* _GMP_H_HAVE_VA_LIST */ + + +typedef int (*gmp_doscan_scan_t) (void *, const char *, ...); +typedef void *(*gmp_doscan_step_t) (void *, int); +typedef int (*gmp_doscan_get_t) (void *); +typedef int (*gmp_doscan_unget_t) (int, void *); + +struct gmp_doscan_funs_t { + gmp_doscan_scan_t scan; + gmp_doscan_step_t step; + gmp_doscan_get_t get; + gmp_doscan_unget_t unget; +}; +extern const struct gmp_doscan_funs_t __gmp_fscanf_funs; +extern const struct gmp_doscan_funs_t __gmp_sscanf_funs; + +#if _GMP_H_HAVE_VA_LIST +__GMP_DECLSPEC int __gmp_doscan (const struct gmp_doscan_funs_t *, void *, const char *, va_list); +#endif + + +/* For testing and debugging. */ +#define MPZ_CHECK_FORMAT(z) \ + do { \ + ASSERT_ALWAYS (SIZ(z) == 0 || PTR(z)[ABSIZ(z) - 1] != 0); \ + ASSERT_ALWAYS (ALLOC(z) >= ABSIZ(z)); \ + ASSERT_ALWAYS_MPN (PTR(z), ABSIZ(z)); \ + } while (0) + +#define MPQ_CHECK_FORMAT(q) \ + do { \ + MPZ_CHECK_FORMAT (mpq_numref (q)); \ + MPZ_CHECK_FORMAT (mpq_denref (q)); \ + ASSERT_ALWAYS (SIZ(mpq_denref(q)) >= 1); \ + \ + if (SIZ(mpq_numref(q)) == 0) \ + { \ + /* should have zero as 0/1 */ \ + ASSERT_ALWAYS (SIZ(mpq_denref(q)) == 1 \ + && PTR(mpq_denref(q))[0] == 1); \ + } \ + else \ + { \ + /* should have no common factors */ \ + mpz_t g; \ + mpz_init (g); \ + mpz_gcd (g, mpq_numref(q), mpq_denref(q)); \ + ASSERT_ALWAYS (mpz_cmp_ui (g, 1) == 0); \ + mpz_clear (g); \ + } \ + } while (0) + +#define MPF_CHECK_FORMAT(f) \ + do { \ + ASSERT_ALWAYS (PREC(f) >= __GMPF_BITS_TO_PREC(53)); \ + ASSERT_ALWAYS (ABSIZ(f) <= PREC(f)+1); \ + if (SIZ(f) == 0) \ + ASSERT_ALWAYS (EXP(f) == 0); \ + if (SIZ(f) != 0) \ + ASSERT_ALWAYS (PTR(f)[ABSIZ(f) - 1] != 0); \ + } while (0) + + +/* Enhancement: The "mod" and "gcd_1" functions below could have + __GMP_ATTRIBUTE_PURE, but currently (gcc 3.3) that's not supported on + function pointers, only actual functions. It probably doesn't make much + difference to the gmp code, since hopefully we arrange calls so there's + no great need for the compiler to move things around. */ + +#if WANT_FAT_BINARY && (HAVE_HOST_CPU_FAMILY_x86 || HAVE_HOST_CPU_FAMILY_x86_64) +/* NOTE: The function pointers in this struct are also in CPUVEC_FUNCS_LIST + in mpn/x86/x86-defs.m4 and mpn/x86_64/x86_64-defs.m4. Be sure to update + those when changing here. */ +struct cpuvec_t { + DECL_add_n ((*add_n)); + DECL_addlsh1_n ((*addlsh1_n)); + DECL_addlsh2_n ((*addlsh2_n)); + DECL_addmul_1 ((*addmul_1)); + DECL_addmul_2 ((*addmul_2)); + DECL_bdiv_dbm1c ((*bdiv_dbm1c)); + DECL_cnd_add_n ((*cnd_add_n)); + DECL_cnd_sub_n ((*cnd_sub_n)); + DECL_com ((*com)); + DECL_copyd ((*copyd)); + DECL_copyi ((*copyi)); + DECL_divexact_1 ((*divexact_1)); + DECL_divrem_1 ((*divrem_1)); + DECL_gcd_1 ((*gcd_1)); + DECL_lshift ((*lshift)); + DECL_lshiftc ((*lshiftc)); + DECL_mod_1 ((*mod_1)); + DECL_mod_1_1p ((*mod_1_1p)); + DECL_mod_1_1p_cps ((*mod_1_1p_cps)); + DECL_mod_1s_2p ((*mod_1s_2p)); + DECL_mod_1s_2p_cps ((*mod_1s_2p_cps)); + DECL_mod_1s_4p ((*mod_1s_4p)); + DECL_mod_1s_4p_cps ((*mod_1s_4p_cps)); + DECL_mod_34lsub1 ((*mod_34lsub1)); + DECL_modexact_1c_odd ((*modexact_1c_odd)); + DECL_mul_1 ((*mul_1)); + DECL_mul_basecase ((*mul_basecase)); + DECL_mullo_basecase ((*mullo_basecase)); + DECL_preinv_divrem_1 ((*preinv_divrem_1)); + DECL_preinv_mod_1 ((*preinv_mod_1)); + DECL_redc_1 ((*redc_1)); + DECL_redc_2 ((*redc_2)); + DECL_rshift ((*rshift)); + DECL_sqr_basecase ((*sqr_basecase)); + DECL_sub_n ((*sub_n)); + DECL_sublsh1_n ((*sublsh1_n)); + DECL_submul_1 ((*submul_1)); + mp_size_t mul_toom22_threshold; + mp_size_t mul_toom33_threshold; + mp_size_t sqr_toom2_threshold; + mp_size_t sqr_toom3_threshold; + mp_size_t bmod_1_to_mod_1_threshold; +}; +__GMP_DECLSPEC extern struct cpuvec_t __gmpn_cpuvec; +__GMP_DECLSPEC extern int __gmpn_cpuvec_initialized; +#endif /* x86 fat binary */ + +__GMP_DECLSPEC void __gmpn_cpuvec_init (void); + +/* Get a threshold "field" from __gmpn_cpuvec, running __gmpn_cpuvec_init() + if that hasn't yet been done (to establish the right values). */ +#define CPUVEC_THRESHOLD(field) \ + ((LIKELY (__gmpn_cpuvec_initialized) ? 0 : (__gmpn_cpuvec_init (), 0)), \ + __gmpn_cpuvec.field) + + +#if HAVE_NATIVE_mpn_add_nc +#define mpn_add_nc __MPN(add_nc) +__GMP_DECLSPEC mp_limb_t mpn_add_nc (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t, mp_limb_t); +#else +static inline +mp_limb_t +mpn_add_nc (mp_ptr rp, mp_srcptr up, mp_srcptr vp, mp_size_t n, mp_limb_t ci) +{ + mp_limb_t co; + co = mpn_add_n (rp, up, vp, n); + co += mpn_add_1 (rp, rp, n, ci); + return co; +} +#endif + +#if HAVE_NATIVE_mpn_sub_nc +#define mpn_sub_nc __MPN(sub_nc) +__GMP_DECLSPEC mp_limb_t mpn_sub_nc (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t, mp_limb_t); +#else +static inline mp_limb_t +mpn_sub_nc (mp_ptr rp, mp_srcptr up, mp_srcptr vp, mp_size_t n, mp_limb_t ci) +{ + mp_limb_t co; + co = mpn_sub_n (rp, up, vp, n); + co += mpn_sub_1 (rp, rp, n, ci); + return co; +} +#endif + +#if TUNE_PROGRAM_BUILD +/* Some extras wanted when recompiling some .c files for use by the tune + program. Not part of a normal build. + + It's necessary to keep these thresholds as #defines (just to an + identically named variable), since various defaults are established based + on #ifdef in the .c files. For some this is not so (the defaults are + instead established above), but all are done this way for consistency. */ + +#undef MUL_TOOM22_THRESHOLD +#define MUL_TOOM22_THRESHOLD mul_toom22_threshold +extern mp_size_t mul_toom22_threshold; + +#undef MUL_TOOM33_THRESHOLD +#define MUL_TOOM33_THRESHOLD mul_toom33_threshold +extern mp_size_t mul_toom33_threshold; + +#undef MUL_TOOM44_THRESHOLD +#define MUL_TOOM44_THRESHOLD mul_toom44_threshold +extern mp_size_t mul_toom44_threshold; + +#undef MUL_TOOM6H_THRESHOLD +#define MUL_TOOM6H_THRESHOLD mul_toom6h_threshold +extern mp_size_t mul_toom6h_threshold; + +#undef MUL_TOOM8H_THRESHOLD +#define MUL_TOOM8H_THRESHOLD mul_toom8h_threshold +extern mp_size_t mul_toom8h_threshold; + +#undef MUL_TOOM32_TO_TOOM43_THRESHOLD +#define MUL_TOOM32_TO_TOOM43_THRESHOLD mul_toom32_to_toom43_threshold +extern mp_size_t mul_toom32_to_toom43_threshold; + +#undef MUL_TOOM32_TO_TOOM53_THRESHOLD +#define MUL_TOOM32_TO_TOOM53_THRESHOLD mul_toom32_to_toom53_threshold +extern mp_size_t mul_toom32_to_toom53_threshold; + +#undef MUL_TOOM42_TO_TOOM53_THRESHOLD +#define MUL_TOOM42_TO_TOOM53_THRESHOLD mul_toom42_to_toom53_threshold +extern mp_size_t mul_toom42_to_toom53_threshold; + +#undef MUL_TOOM42_TO_TOOM63_THRESHOLD +#define MUL_TOOM42_TO_TOOM63_THRESHOLD mul_toom42_to_toom63_threshold +extern mp_size_t mul_toom42_to_toom63_threshold; + +#undef MUL_TOOM43_TO_TOOM54_THRESHOLD +#define MUL_TOOM43_TO_TOOM54_THRESHOLD mul_toom43_to_toom54_threshold; +extern mp_size_t mul_toom43_to_toom54_threshold; + +#undef MUL_FFT_THRESHOLD +#define MUL_FFT_THRESHOLD mul_fft_threshold +extern mp_size_t mul_fft_threshold; + +#undef MUL_FFT_MODF_THRESHOLD +#define MUL_FFT_MODF_THRESHOLD mul_fft_modf_threshold +extern mp_size_t mul_fft_modf_threshold; + +#undef MUL_FFT_TABLE +#define MUL_FFT_TABLE { 0 } + +#undef MUL_FFT_TABLE3 +#define MUL_FFT_TABLE3 { {0,0} } + +/* A native mpn_sqr_basecase is not tuned and SQR_BASECASE_THRESHOLD should + remain as zero (always use it). */ +#if ! HAVE_NATIVE_mpn_sqr_basecase +#undef SQR_BASECASE_THRESHOLD +#define SQR_BASECASE_THRESHOLD sqr_basecase_threshold +extern mp_size_t sqr_basecase_threshold; +#endif + +#if TUNE_PROGRAM_BUILD_SQR +#undef SQR_TOOM2_THRESHOLD +#define SQR_TOOM2_THRESHOLD SQR_TOOM2_MAX_GENERIC +#else +#undef SQR_TOOM2_THRESHOLD +#define SQR_TOOM2_THRESHOLD sqr_toom2_threshold +extern mp_size_t sqr_toom2_threshold; +#endif + +#undef SQR_TOOM3_THRESHOLD +#define SQR_TOOM3_THRESHOLD sqr_toom3_threshold +extern mp_size_t sqr_toom3_threshold; + +#undef SQR_TOOM4_THRESHOLD +#define SQR_TOOM4_THRESHOLD sqr_toom4_threshold +extern mp_size_t sqr_toom4_threshold; + +#undef SQR_TOOM6_THRESHOLD +#define SQR_TOOM6_THRESHOLD sqr_toom6_threshold +extern mp_size_t sqr_toom6_threshold; + +#undef SQR_TOOM8_THRESHOLD +#define SQR_TOOM8_THRESHOLD sqr_toom8_threshold +extern mp_size_t sqr_toom8_threshold; + +#undef SQR_FFT_THRESHOLD +#define SQR_FFT_THRESHOLD sqr_fft_threshold +extern mp_size_t sqr_fft_threshold; + +#undef SQR_FFT_MODF_THRESHOLD +#define SQR_FFT_MODF_THRESHOLD sqr_fft_modf_threshold +extern mp_size_t sqr_fft_modf_threshold; + +#undef SQR_FFT_TABLE +#define SQR_FFT_TABLE { 0 } + +#undef SQR_FFT_TABLE3 +#define SQR_FFT_TABLE3 { {0,0} } + +#undef MULLO_BASECASE_THRESHOLD +#define MULLO_BASECASE_THRESHOLD mullo_basecase_threshold +extern mp_size_t mullo_basecase_threshold; + +#undef MULLO_DC_THRESHOLD +#define MULLO_DC_THRESHOLD mullo_dc_threshold +extern mp_size_t mullo_dc_threshold; + +#undef MULLO_MUL_N_THRESHOLD +#define MULLO_MUL_N_THRESHOLD mullo_mul_n_threshold +extern mp_size_t mullo_mul_n_threshold; + +#undef SQRLO_BASECASE_THRESHOLD +#define SQRLO_BASECASE_THRESHOLD sqrlo_basecase_threshold +extern mp_size_t sqrlo_basecase_threshold; + +#undef SQRLO_DC_THRESHOLD +#define SQRLO_DC_THRESHOLD sqrlo_dc_threshold +extern mp_size_t sqrlo_dc_threshold; + +#undef SQRLO_SQR_THRESHOLD +#define SQRLO_SQR_THRESHOLD sqrlo_sqr_threshold +extern mp_size_t sqrlo_sqr_threshold; + +#undef MULMID_TOOM42_THRESHOLD +#define MULMID_TOOM42_THRESHOLD mulmid_toom42_threshold +extern mp_size_t mulmid_toom42_threshold; + +#undef DIV_QR_2_PI2_THRESHOLD +#define DIV_QR_2_PI2_THRESHOLD div_qr_2_pi2_threshold +extern mp_size_t div_qr_2_pi2_threshold; + +#undef DC_DIV_QR_THRESHOLD +#define DC_DIV_QR_THRESHOLD dc_div_qr_threshold +extern mp_size_t dc_div_qr_threshold; + +#undef DC_DIVAPPR_Q_THRESHOLD +#define DC_DIVAPPR_Q_THRESHOLD dc_divappr_q_threshold +extern mp_size_t dc_divappr_q_threshold; + +#undef DC_BDIV_Q_THRESHOLD +#define DC_BDIV_Q_THRESHOLD dc_bdiv_q_threshold +extern mp_size_t dc_bdiv_q_threshold; + +#undef DC_BDIV_QR_THRESHOLD +#define DC_BDIV_QR_THRESHOLD dc_bdiv_qr_threshold +extern mp_size_t dc_bdiv_qr_threshold; + +#undef MU_DIV_QR_THRESHOLD +#define MU_DIV_QR_THRESHOLD mu_div_qr_threshold +extern mp_size_t mu_div_qr_threshold; + +#undef MU_DIVAPPR_Q_THRESHOLD +#define MU_DIVAPPR_Q_THRESHOLD mu_divappr_q_threshold +extern mp_size_t mu_divappr_q_threshold; + +#undef MUPI_DIV_QR_THRESHOLD +#define MUPI_DIV_QR_THRESHOLD mupi_div_qr_threshold +extern mp_size_t mupi_div_qr_threshold; + +#undef MU_BDIV_QR_THRESHOLD +#define MU_BDIV_QR_THRESHOLD mu_bdiv_qr_threshold +extern mp_size_t mu_bdiv_qr_threshold; + +#undef MU_BDIV_Q_THRESHOLD +#define MU_BDIV_Q_THRESHOLD mu_bdiv_q_threshold +extern mp_size_t mu_bdiv_q_threshold; + +#undef INV_MULMOD_BNM1_THRESHOLD +#define INV_MULMOD_BNM1_THRESHOLD inv_mulmod_bnm1_threshold +extern mp_size_t inv_mulmod_bnm1_threshold; + +#undef INV_NEWTON_THRESHOLD +#define INV_NEWTON_THRESHOLD inv_newton_threshold +extern mp_size_t inv_newton_threshold; + +#undef INV_APPR_THRESHOLD +#define INV_APPR_THRESHOLD inv_appr_threshold +extern mp_size_t inv_appr_threshold; + +#undef BINV_NEWTON_THRESHOLD +#define BINV_NEWTON_THRESHOLD binv_newton_threshold +extern mp_size_t binv_newton_threshold; + +#undef REDC_1_TO_REDC_2_THRESHOLD +#define REDC_1_TO_REDC_2_THRESHOLD redc_1_to_redc_2_threshold +extern mp_size_t redc_1_to_redc_2_threshold; + +#undef REDC_2_TO_REDC_N_THRESHOLD +#define REDC_2_TO_REDC_N_THRESHOLD redc_2_to_redc_n_threshold +extern mp_size_t redc_2_to_redc_n_threshold; + +#undef REDC_1_TO_REDC_N_THRESHOLD +#define REDC_1_TO_REDC_N_THRESHOLD redc_1_to_redc_n_threshold +extern mp_size_t redc_1_to_redc_n_threshold; + +#undef MATRIX22_STRASSEN_THRESHOLD +#define MATRIX22_STRASSEN_THRESHOLD matrix22_strassen_threshold +extern mp_size_t matrix22_strassen_threshold; + +#undef HGCD_THRESHOLD +#define HGCD_THRESHOLD hgcd_threshold +extern mp_size_t hgcd_threshold; + +#undef HGCD_APPR_THRESHOLD +#define HGCD_APPR_THRESHOLD hgcd_appr_threshold +extern mp_size_t hgcd_appr_threshold; + +#undef HGCD_REDUCE_THRESHOLD +#define HGCD_REDUCE_THRESHOLD hgcd_reduce_threshold +extern mp_size_t hgcd_reduce_threshold; + +#undef GCD_DC_THRESHOLD +#define GCD_DC_THRESHOLD gcd_dc_threshold +extern mp_size_t gcd_dc_threshold; + +#undef GCDEXT_DC_THRESHOLD +#define GCDEXT_DC_THRESHOLD gcdext_dc_threshold +extern mp_size_t gcdext_dc_threshold; + +#undef DIV_QR_1N_PI1_METHOD +#define DIV_QR_1N_PI1_METHOD div_qr_1n_pi1_method +extern int div_qr_1n_pi1_method; + +#undef DIV_QR_1_NORM_THRESHOLD +#define DIV_QR_1_NORM_THRESHOLD div_qr_1_norm_threshold +extern mp_size_t div_qr_1_norm_threshold; + +#undef DIV_QR_1_UNNORM_THRESHOLD +#define DIV_QR_1_UNNORM_THRESHOLD div_qr_1_unnorm_threshold +extern mp_size_t div_qr_1_unnorm_threshold; + +#undef DIVREM_1_NORM_THRESHOLD +#define DIVREM_1_NORM_THRESHOLD divrem_1_norm_threshold +extern mp_size_t divrem_1_norm_threshold; + +#undef DIVREM_1_UNNORM_THRESHOLD +#define DIVREM_1_UNNORM_THRESHOLD divrem_1_unnorm_threshold +extern mp_size_t divrem_1_unnorm_threshold; + +#undef MOD_1_NORM_THRESHOLD +#define MOD_1_NORM_THRESHOLD mod_1_norm_threshold +extern mp_size_t mod_1_norm_threshold; + +#undef MOD_1_UNNORM_THRESHOLD +#define MOD_1_UNNORM_THRESHOLD mod_1_unnorm_threshold +extern mp_size_t mod_1_unnorm_threshold; + +#undef MOD_1_1P_METHOD +#define MOD_1_1P_METHOD mod_1_1p_method +extern int mod_1_1p_method; + +#undef MOD_1N_TO_MOD_1_1_THRESHOLD +#define MOD_1N_TO_MOD_1_1_THRESHOLD mod_1n_to_mod_1_1_threshold +extern mp_size_t mod_1n_to_mod_1_1_threshold; + +#undef MOD_1U_TO_MOD_1_1_THRESHOLD +#define MOD_1U_TO_MOD_1_1_THRESHOLD mod_1u_to_mod_1_1_threshold +extern mp_size_t mod_1u_to_mod_1_1_threshold; + +#undef MOD_1_1_TO_MOD_1_2_THRESHOLD +#define MOD_1_1_TO_MOD_1_2_THRESHOLD mod_1_1_to_mod_1_2_threshold +extern mp_size_t mod_1_1_to_mod_1_2_threshold; + +#undef MOD_1_2_TO_MOD_1_4_THRESHOLD +#define MOD_1_2_TO_MOD_1_4_THRESHOLD mod_1_2_to_mod_1_4_threshold +extern mp_size_t mod_1_2_to_mod_1_4_threshold; + +#undef PREINV_MOD_1_TO_MOD_1_THRESHOLD +#define PREINV_MOD_1_TO_MOD_1_THRESHOLD preinv_mod_1_to_mod_1_threshold +extern mp_size_t preinv_mod_1_to_mod_1_threshold; + +#if ! UDIV_PREINV_ALWAYS +#undef DIVREM_2_THRESHOLD +#define DIVREM_2_THRESHOLD divrem_2_threshold +extern mp_size_t divrem_2_threshold; +#endif + +#undef MULMOD_BNM1_THRESHOLD +#define MULMOD_BNM1_THRESHOLD mulmod_bnm1_threshold +extern mp_size_t mulmod_bnm1_threshold; + +#undef SQRMOD_BNM1_THRESHOLD +#define SQRMOD_BNM1_THRESHOLD sqrmod_bnm1_threshold +extern mp_size_t sqrmod_bnm1_threshold; + +#undef GET_STR_DC_THRESHOLD +#define GET_STR_DC_THRESHOLD get_str_dc_threshold +extern mp_size_t get_str_dc_threshold; + +#undef GET_STR_PRECOMPUTE_THRESHOLD +#define GET_STR_PRECOMPUTE_THRESHOLD get_str_precompute_threshold +extern mp_size_t get_str_precompute_threshold; + +#undef SET_STR_DC_THRESHOLD +#define SET_STR_DC_THRESHOLD set_str_dc_threshold +extern mp_size_t set_str_dc_threshold; + +#undef SET_STR_PRECOMPUTE_THRESHOLD +#define SET_STR_PRECOMPUTE_THRESHOLD set_str_precompute_threshold +extern mp_size_t set_str_precompute_threshold; + +#undef FAC_ODD_THRESHOLD +#define FAC_ODD_THRESHOLD fac_odd_threshold +extern mp_size_t fac_odd_threshold; + +#undef FAC_DSC_THRESHOLD +#define FAC_DSC_THRESHOLD fac_dsc_threshold +extern mp_size_t fac_dsc_threshold; + +#undef FFT_TABLE_ATTRS +#define FFT_TABLE_ATTRS +extern mp_size_t mpn_fft_table[2][MPN_FFT_TABLE_SIZE]; +#define FFT_TABLE3_SIZE 2000 /* generous space for tuning */ +extern struct fft_table_nk mpn_fft_table3[2][FFT_TABLE3_SIZE]; + +/* Sizes the tune program tests up to, used in a couple of recompilations. */ +#undef MUL_TOOM22_THRESHOLD_LIMIT +#undef MUL_TOOM33_THRESHOLD_LIMIT +#undef MULLO_BASECASE_THRESHOLD_LIMIT +#undef SQRLO_BASECASE_THRESHOLD_LIMIT +#undef SQRLO_DC_THRESHOLD_LIMIT +#undef SQR_TOOM3_THRESHOLD_LIMIT +#define SQR_TOOM2_MAX_GENERIC 200 +#define MUL_TOOM22_THRESHOLD_LIMIT 700 +#define MUL_TOOM33_THRESHOLD_LIMIT 700 +#define SQR_TOOM3_THRESHOLD_LIMIT 400 +#define MUL_TOOM44_THRESHOLD_LIMIT 1000 +#define SQR_TOOM4_THRESHOLD_LIMIT 1000 +#define MUL_TOOM6H_THRESHOLD_LIMIT 1100 +#define SQR_TOOM6_THRESHOLD_LIMIT 1100 +#define MUL_TOOM8H_THRESHOLD_LIMIT 1200 +#define SQR_TOOM8_THRESHOLD_LIMIT 1200 +#define MULLO_BASECASE_THRESHOLD_LIMIT 200 +#define SQRLO_BASECASE_THRESHOLD_LIMIT 200 +#define SQRLO_DC_THRESHOLD_LIMIT 400 +#define GET_STR_THRESHOLD_LIMIT 150 +#define FAC_DSC_THRESHOLD_LIMIT 2048 + +#endif /* TUNE_PROGRAM_BUILD */ + +#if defined (__cplusplus) +} +#endif + +/* FIXME: Make these itch functions less conservative. Also consider making + them dependent on just 'an', and compute the allocation directly from 'an' + instead of via n. */ + +/* toom22/toom2: Scratch need is 2*(an + k), k is the recursion depth. + k is ths smallest k such that + ceil(an/2^k) < MUL_TOOM22_THRESHOLD. + which implies that + k = bitsize of floor ((an-1)/(MUL_TOOM22_THRESHOLD-1)) + = 1 + floor (log_2 (floor ((an-1)/(MUL_TOOM22_THRESHOLD-1)))) +*/ +#define mpn_toom22_mul_itch(an, bn) \ + (2 * ((an) + GMP_NUMB_BITS)) +#define mpn_toom2_sqr_itch(an) \ + (2 * ((an) + GMP_NUMB_BITS)) + +/* toom33/toom3: Scratch need is 5an/2 + 10k, k is the recursion depth. + We use 3an + C, so that we can use a smaller constant. + */ +#define mpn_toom33_mul_itch(an, bn) \ + (3 * (an) + GMP_NUMB_BITS) +#define mpn_toom3_sqr_itch(an) \ + (3 * (an) + GMP_NUMB_BITS) + +/* toom33/toom3: Scratch need is 8an/3 + 13k, k is the recursion depth. + We use 3an + C, so that we can use a smaller constant. + */ +#define mpn_toom44_mul_itch(an, bn) \ + (3 * (an) + GMP_NUMB_BITS) +#define mpn_toom4_sqr_itch(an) \ + (3 * (an) + GMP_NUMB_BITS) + +#define mpn_toom6_sqr_itch(n) \ + (((n) - SQR_TOOM6_THRESHOLD)*2 + \ + MAX(SQR_TOOM6_THRESHOLD*2 + GMP_NUMB_BITS*6, \ + mpn_toom4_sqr_itch(SQR_TOOM6_THRESHOLD))) + +#define MUL_TOOM6H_MIN \ + ((MUL_TOOM6H_THRESHOLD > MUL_TOOM44_THRESHOLD) ? \ + MUL_TOOM6H_THRESHOLD : MUL_TOOM44_THRESHOLD) +#define mpn_toom6_mul_n_itch(n) \ + (((n) - MUL_TOOM6H_MIN)*2 + \ + MAX(MUL_TOOM6H_MIN*2 + GMP_NUMB_BITS*6, \ + mpn_toom44_mul_itch(MUL_TOOM6H_MIN,MUL_TOOM6H_MIN))) + +static inline mp_size_t +mpn_toom6h_mul_itch (mp_size_t an, mp_size_t bn) { + mp_size_t estimatedN; + estimatedN = (an + bn) / (size_t) 10 + 1; + return mpn_toom6_mul_n_itch (estimatedN * 6); +} + +#define mpn_toom8_sqr_itch(n) \ + ((((n)*15)>>3) - ((SQR_TOOM8_THRESHOLD*15)>>3) + \ + MAX(((SQR_TOOM8_THRESHOLD*15)>>3) + GMP_NUMB_BITS*6, \ + mpn_toom6_sqr_itch(SQR_TOOM8_THRESHOLD))) + +#define MUL_TOOM8H_MIN \ + ((MUL_TOOM8H_THRESHOLD > MUL_TOOM6H_MIN) ? \ + MUL_TOOM8H_THRESHOLD : MUL_TOOM6H_MIN) +#define mpn_toom8_mul_n_itch(n) \ + ((((n)*15)>>3) - ((MUL_TOOM8H_MIN*15)>>3) + \ + MAX(((MUL_TOOM8H_MIN*15)>>3) + GMP_NUMB_BITS*6, \ + mpn_toom6_mul_n_itch(MUL_TOOM8H_MIN))) + +static inline mp_size_t +mpn_toom8h_mul_itch (mp_size_t an, mp_size_t bn) { + mp_size_t estimatedN; + estimatedN = (an + bn) / (size_t) 14 + 1; + return mpn_toom8_mul_n_itch (estimatedN * 8); +} + +static inline mp_size_t +mpn_toom32_mul_itch (mp_size_t an, mp_size_t bn) +{ + mp_size_t n = 1 + (2 * an >= 3 * bn ? (an - 1) / (size_t) 3 : (bn - 1) >> 1); + mp_size_t itch = 2 * n + 1; + + return itch; +} + +static inline mp_size_t +mpn_toom42_mul_itch (mp_size_t an, mp_size_t bn) +{ + mp_size_t n = an >= 2 * bn ? (an + 3) >> 2 : (bn + 1) >> 1; + return 6 * n + 3; +} + +static inline mp_size_t +mpn_toom43_mul_itch (mp_size_t an, mp_size_t bn) +{ + mp_size_t n = 1 + (3 * an >= 4 * bn ? (an - 1) >> 2 : (bn - 1) / (size_t) 3); + + return 6*n + 4; +} + +static inline mp_size_t +mpn_toom52_mul_itch (mp_size_t an, mp_size_t bn) +{ + mp_size_t n = 1 + (2 * an >= 5 * bn ? (an - 1) / (size_t) 5 : (bn - 1) >> 1); + return 6*n + 4; +} + +static inline mp_size_t +mpn_toom53_mul_itch (mp_size_t an, mp_size_t bn) +{ + mp_size_t n = 1 + (3 * an >= 5 * bn ? (an - 1) / (size_t) 5 : (bn - 1) / (size_t) 3); + return 10 * n + 10; +} + +static inline mp_size_t +mpn_toom62_mul_itch (mp_size_t an, mp_size_t bn) +{ + mp_size_t n = 1 + (an >= 3 * bn ? (an - 1) / (size_t) 6 : (bn - 1) >> 1); + return 10 * n + 10; +} + +static inline mp_size_t +mpn_toom63_mul_itch (mp_size_t an, mp_size_t bn) +{ + mp_size_t n = 1 + (an >= 2 * bn ? (an - 1) / (size_t) 6 : (bn - 1) / (size_t) 3); + return 9 * n + 3; +} + +static inline mp_size_t +mpn_toom54_mul_itch (mp_size_t an, mp_size_t bn) +{ + mp_size_t n = 1 + (4 * an >= 5 * bn ? (an - 1) / (size_t) 5 : (bn - 1) / (size_t) 4); + return 9 * n + 3; +} + +/* let S(n) = space required for input size n, + then S(n) = 3 floor(n/2) + 1 + S(floor(n/2)). */ +#define mpn_toom42_mulmid_itch(n) \ + (3 * (n) + GMP_NUMB_BITS) + +#if 0 +#define mpn_fft_mul mpn_mul_fft_full +#else +#define mpn_fft_mul mpn_nussbaumer_mul +#endif + +#ifdef __cplusplus + +/* A little helper for a null-terminated __gmp_allocate_func string. + The destructor ensures it's freed even if an exception is thrown. + The len field is needed by the destructor, and can be used by anyone else + to avoid a second strlen pass over the data. + + Since our input is a C string, using strlen is correct. Perhaps it'd be + more C++-ish style to use std::char_traits<char>::length, but char_traits + isn't available in gcc 2.95.4. */ + +class gmp_allocated_string { + public: + char *str; + size_t len; + gmp_allocated_string(char *arg) + { + str = arg; + len = std::strlen (str); + } + ~gmp_allocated_string() + { + (*__gmp_free_func) (str, len+1); + } +}; + +std::istream &__gmpz_operator_in_nowhite (std::istream &, mpz_ptr, char); +int __gmp_istream_set_base (std::istream &, char &, bool &, bool &); +void __gmp_istream_set_digits (std::string &, std::istream &, char &, bool &, int); +void __gmp_doprnt_params_from_ios (struct doprnt_params_t *, std::ios &); +std::ostream& __gmp_doprnt_integer_ostream (std::ostream &, struct doprnt_params_t *, char *); +extern const struct doprnt_funs_t __gmp_asprintf_funs_noformat; + +#endif /* __cplusplus */ + +#endif /* __GMP_IMPL_H__ */ diff --git a/examples/multiprecision/bench-include/gmp-mparam.h b/examples/multiprecision/bench-include/gmp-mparam.h new file mode 100644 index 0000000000000000000000000000000000000000..7dc057aa0c33d7befa22332ce434892098f9d0a4 --- /dev/null +++ b/examples/multiprecision/bench-include/gmp-mparam.h @@ -0,0 +1,33 @@ +/* Generic C gmp-mparam.h -- Compiler/machine parameter header file. + +Copyright 1991, 1993, 1994, 2000 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + +or + + * the GNU General Public License as published by the Free Software + Foundation; either version 2 of the License, or (at your option) any + later version. + +or both in parallel, as here. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received copies of the GNU General Public License and the +GNU Lesser General Public License along with the GNU MP Library. If not, +see https://www.gnu.org/licenses/. */ + + +/* Values for GMP_LIMB_BITS etc will be determined by ./configure and put + in config.h. */ diff --git a/examples/multiprecision/bench-include/gmp.h b/examples/multiprecision/bench-include/gmp.h new file mode 100644 index 0000000000000000000000000000000000000000..67c56f9f6887d257fa5c950d8c749ef168d03ad0 --- /dev/null +++ b/examples/multiprecision/bench-include/gmp.h @@ -0,0 +1,2329 @@ +/* Definitions for GNU multiple precision functions. -*- mode: c -*- + +Copyright 1991, 1993-1997, 1999-2016 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + +or + + * the GNU General Public License as published by the Free Software + Foundation; either version 2 of the License, or (at your option) any + later version. + +or both in parallel, as here. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received copies of the GNU General Public License and the +GNU Lesser General Public License along with the GNU MP Library. If not, +see https://www.gnu.org/licenses/. */ + +#ifndef __GMP_H__ + +#if defined (__cplusplus) +#include <iosfwd> /* for std::istream, std::ostream, std::string */ +#include <cstdio> +#endif + + +/* Instantiated by configure. */ +#if ! defined (__GMP_WITHIN_CONFIGURE) +#define __GMP_HAVE_HOST_CPU_FAMILY_power 0 +#define __GMP_HAVE_HOST_CPU_FAMILY_powerpc 0 +#define GMP_LIMB_BITS 64 +#define GMP_NAIL_BITS 0 +#endif +#define GMP_NUMB_BITS (GMP_LIMB_BITS - GMP_NAIL_BITS) +#define GMP_NUMB_MASK ((~ __GMP_CAST (mp_limb_t, 0)) >> GMP_NAIL_BITS) +#define GMP_NUMB_MAX GMP_NUMB_MASK +#define GMP_NAIL_MASK (~ GMP_NUMB_MASK) + + +#ifndef __GNU_MP__ +#define __GNU_MP__ 6 + +#include <stddef.h> /* for size_t */ +#include <limits.h> + +/* Instantiated by configure. */ +#if ! defined (__GMP_WITHIN_CONFIGURE) +/* #undef _LONG_LONG_LIMB */ +#define __GMP_LIBGMP_DLL 0 +#endif + + +/* __GMP_DECLSPEC supports Windows DLL versions of libgmp, and is empty in + all other circumstances. + + When compiling objects for libgmp, __GMP_DECLSPEC is an export directive, + or when compiling for an application it's an import directive. The two + cases are differentiated by __GMP_WITHIN_GMP defined by the GMP Makefiles + (and not defined from an application). + + __GMP_DECLSPEC_XX is similarly used for libgmpxx. __GMP_WITHIN_GMPXX + indicates when building libgmpxx, and in that case libgmpxx functions are + exports, but libgmp functions which might get called are imports. + + Libtool DLL_EXPORT define is not used. + + There's no attempt to support GMP built both static and DLL. Doing so + would mean applications would have to tell us which of the two is going + to be used when linking, and that seems very tedious and error prone if + using GMP by hand, and equally tedious from a package since autoconf and + automake don't give much help. + + __GMP_DECLSPEC is required on all documented global functions and + variables, the various internals in gmp-impl.h etc can be left unadorned. + But internals used by the test programs or speed measuring programs + should have __GMP_DECLSPEC, and certainly constants or variables must + have it or the wrong address will be resolved. + + In gcc __declspec can go at either the start or end of a prototype. + + In Microsoft C __declspec must go at the start, or after the type like + void __declspec(...) *foo()". There's no __dllexport or anything to + guard against someone foolish #defining dllexport. _export used to be + available, but no longer. + + In Borland C _export still exists, but needs to go after the type, like + "void _export foo();". Would have to change the __GMP_DECLSPEC syntax to + make use of that. Probably more trouble than it's worth. */ + +#if defined (__GNUC__) +#define __GMP_DECLSPEC_EXPORT __declspec(__dllexport__) +#define __GMP_DECLSPEC_IMPORT __declspec(__dllimport__) +#endif +#if defined (_MSC_VER) || defined (__BORLANDC__) +#define __GMP_DECLSPEC_EXPORT __declspec(dllexport) +#define __GMP_DECLSPEC_IMPORT __declspec(dllimport) +#endif +#ifdef __WATCOMC__ +#define __GMP_DECLSPEC_EXPORT __export +#define __GMP_DECLSPEC_IMPORT __import +#endif +#ifdef __IBMC__ +#define __GMP_DECLSPEC_EXPORT _Export +#define __GMP_DECLSPEC_IMPORT _Import +#endif + +#if __GMP_LIBGMP_DLL +#ifdef __GMP_WITHIN_GMP +/* compiling to go into a DLL libgmp */ +#define __GMP_DECLSPEC __GMP_DECLSPEC_EXPORT +#else +/* compiling to go into an application which will link to a DLL libgmp */ +#define __GMP_DECLSPEC __GMP_DECLSPEC_IMPORT +#endif +#else +/* all other cases */ +#define __GMP_DECLSPEC +#endif + + +#ifdef __GMP_SHORT_LIMB +typedef unsigned int mp_limb_t; +typedef int mp_limb_signed_t; +#else +#ifdef _LONG_LONG_LIMB +typedef unsigned long long int mp_limb_t; +typedef long long int mp_limb_signed_t; +#else +typedef unsigned long int mp_limb_t; +typedef long int mp_limb_signed_t; +#endif +#endif +typedef unsigned long int mp_bitcnt_t; + +/* For reference, note that the name __mpz_struct gets into C++ mangled + function names, which means although the "__" suggests an internal, we + must leave this name for binary compatibility. */ +typedef struct +{ + int _mp_alloc; /* Number of *limbs* allocated and pointed + to by the _mp_d field. */ + int _mp_size; /* abs(_mp_size) is the number of limbs the + last field points to. If _mp_size is + negative this is a negative number. */ + mp_limb_t *_mp_d; /* Pointer to the limbs. */ +} __mpz_struct; + +#endif /* __GNU_MP__ */ + + +typedef __mpz_struct MP_INT; /* gmp 1 source compatibility */ +typedef __mpz_struct mpz_t[1]; + +typedef mp_limb_t * mp_ptr; +typedef const mp_limb_t * mp_srcptr; +#if defined (_CRAY) && ! defined (_CRAYMPP) +/* plain `int' is much faster (48 bits) */ +#define __GMP_MP_SIZE_T_INT 1 +typedef int mp_size_t; +typedef int mp_exp_t; +#else +#define __GMP_MP_SIZE_T_INT 0 +typedef long int mp_size_t; +typedef long int mp_exp_t; +#endif + +typedef struct +{ + __mpz_struct _mp_num; + __mpz_struct _mp_den; +} __mpq_struct; + +typedef __mpq_struct MP_RAT; /* gmp 1 source compatibility */ +typedef __mpq_struct mpq_t[1]; + +typedef struct +{ + int _mp_prec; /* Max precision, in number of `mp_limb_t's. + Set by mpf_init and modified by + mpf_set_prec. The area pointed to by the + _mp_d field contains `prec' + 1 limbs. */ + int _mp_size; /* abs(_mp_size) is the number of limbs the + last field points to. If _mp_size is + negative this is a negative number. */ + mp_exp_t _mp_exp; /* Exponent, in the base of `mp_limb_t'. */ + mp_limb_t *_mp_d; /* Pointer to the limbs. */ +} __mpf_struct; + +/* typedef __mpf_struct MP_FLOAT; */ +typedef __mpf_struct mpf_t[1]; + +/* Available random number generation algorithms. */ +typedef enum +{ + GMP_RAND_ALG_DEFAULT = 0, + GMP_RAND_ALG_LC = GMP_RAND_ALG_DEFAULT /* Linear congruential. */ +} gmp_randalg_t; + +/* Random state struct. */ +typedef struct +{ + mpz_t _mp_seed; /* _mp_d member points to state of the generator. */ + gmp_randalg_t _mp_alg; /* Currently unused. */ + union { + void *_mp_lc; /* Pointer to function pointers structure. */ + } _mp_algdata; +} __gmp_randstate_struct; +typedef __gmp_randstate_struct gmp_randstate_t[1]; + +/* Types for function declarations in gmp files. */ +/* ??? Should not pollute user name space with these ??? */ +typedef const __mpz_struct *mpz_srcptr; +typedef __mpz_struct *mpz_ptr; +typedef const __mpf_struct *mpf_srcptr; +typedef __mpf_struct *mpf_ptr; +typedef const __mpq_struct *mpq_srcptr; +typedef __mpq_struct *mpq_ptr; + + +#if __GMP_LIBGMP_DLL +#ifdef __GMP_WITHIN_GMPXX +/* compiling to go into a DLL libgmpxx */ +#define __GMP_DECLSPEC_XX __GMP_DECLSPEC_EXPORT +#else +/* compiling to go into a application which will link to a DLL libgmpxx */ +#define __GMP_DECLSPEC_XX __GMP_DECLSPEC_IMPORT +#endif +#else +/* all other cases */ +#define __GMP_DECLSPEC_XX +#endif + + +#ifndef __MPN +#define __MPN(x) __gmpn_##x +#endif + +/* For reference, "defined(EOF)" cannot be used here. In g++ 2.95.4, + <iostream> defines EOF but not FILE. */ +#if defined (FILE) \ + || defined (H_STDIO) \ + || defined (_H_STDIO) /* AIX */ \ + || defined (_STDIO_H) /* glibc, Sun, SCO */ \ + || defined (_STDIO_H_) /* BSD, OSF */ \ + || defined (__STDIO_H) /* Borland */ \ + || defined (__STDIO_H__) /* IRIX */ \ + || defined (_STDIO_INCLUDED) /* HPUX */ \ + || defined (__dj_include_stdio_h_) /* DJGPP */ \ + || defined (_FILE_DEFINED) /* Microsoft */ \ + || defined (__STDIO__) /* Apple MPW MrC */ \ + || defined (_MSL_STDIO_H) /* Metrowerks */ \ + || defined (_STDIO_H_INCLUDED) /* QNX4 */ \ + || defined (_ISO_STDIO_ISO_H) /* Sun C++ */ \ + || defined (__STDIO_LOADED) /* VMS */ \ + || defined (__DEFINED_FILE) /* musl */ +#define _GMP_H_HAVE_FILE 1 +#endif + +/* In ISO C, if a prototype involving "struct obstack *" is given without + that structure defined, then the struct is scoped down to just the + prototype, causing a conflict if it's subsequently defined for real. So + only give prototypes if we've got obstack.h. */ +#if defined (_OBSTACK_H) /* glibc <obstack.h> */ +#define _GMP_H_HAVE_OBSTACK 1 +#endif + +/* The prototypes for gmp_vprintf etc are provided only if va_list is defined, + via an application having included <stdarg.h>. Usually va_list is a typedef + so can't be tested directly, but C99 specifies that va_start is a macro. + + <stdio.h> will define some sort of va_list for vprintf and vfprintf, but + let's not bother trying to use that since it's not standard and since + application uses for gmp_vprintf etc will almost certainly require the + whole <stdarg.h> anyway. */ + +#ifdef va_start +#define _GMP_H_HAVE_VA_LIST 1 +#endif + +/* Test for gcc >= maj.min, as per __GNUC_PREREQ in glibc */ +#if defined (__GNUC__) && defined (__GNUC_MINOR__) +#define __GMP_GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +#else +#define __GMP_GNUC_PREREQ(maj, min) 0 +#endif + +/* "pure" is in gcc 2.96 and up, see "(gcc)Function Attributes". Basically + it means a function does nothing but examine its arguments and memory + (global or via arguments) to generate a return value, but changes nothing + and has no side-effects. __GMP_NO_ATTRIBUTE_CONST_PURE lets + tune/common.c etc turn this off when trying to write timing loops. */ +#if __GMP_GNUC_PREREQ (2,96) && ! defined (__GMP_NO_ATTRIBUTE_CONST_PURE) +#define __GMP_ATTRIBUTE_PURE __attribute__ ((__pure__)) +#else +#define __GMP_ATTRIBUTE_PURE +#endif + + +/* __GMP_CAST allows us to use static_cast in C++, so our macros are clean + to "g++ -Wold-style-cast". + + Casts in "extern inline" code within an extern "C" block don't induce + these warnings, so __GMP_CAST only needs to be used on documented + macros. */ + +#ifdef __cplusplus +#define __GMP_CAST(type, expr) (static_cast<type> (expr)) +#else +#define __GMP_CAST(type, expr) ((type) (expr)) +#endif + + +/* An empty "throw ()" means the function doesn't throw any C++ exceptions, + this can save some stack frame info in applications. + + Currently it's given only on functions which never divide-by-zero etc, + don't allocate memory, and are expected to never need to allocate memory. + This leaves open the possibility of a C++ throw from a future GMP + exceptions scheme. + + mpz_set_ui etc are omitted to leave open the lazy allocation scheme + described in doc/tasks.html. mpz_get_d etc are omitted to leave open + exceptions for float overflows. + + Note that __GMP_NOTHROW must be given on any inlines the same as on their + prototypes (for g++ at least, where they're used together). Note also + that g++ 3.0 demands that __GMP_NOTHROW is before other attributes like + __GMP_ATTRIBUTE_PURE. */ + +#if defined (__cplusplus) +#define __GMP_NOTHROW throw () +#else +#define __GMP_NOTHROW +#endif + + +/* PORTME: What other compilers have a useful "extern inline"? "static + inline" would be an acceptable substitute if the compiler (or linker) + discards unused statics. */ + + /* gcc has __inline__ in all modes, including strict ansi. Give a prototype + for an inline too, so as to correctly specify "dllimport" on windows, in + case the function is called rather than inlined. + GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99 + inline semantics, unless -fgnu89-inline is used. */ +#ifdef __GNUC__ +#if (defined __GNUC_STDC_INLINE__) || (__GNUC__ == 4 && __GNUC_MINOR__ == 2) \ + || (defined __GNUC_GNU_INLINE__ && defined __cplusplus) +#define __GMP_EXTERN_INLINE extern __inline__ __attribute__ ((__gnu_inline__)) +#else +#define __GMP_EXTERN_INLINE extern __inline__ +#endif +#define __GMP_INLINE_PROTOTYPES 1 +#endif + +/* DEC C (eg. version 5.9) supports "static __inline foo()", even in -std1 + strict ANSI mode. Inlining is done even when not optimizing (ie. -O0 + mode, which is the default), but an unnecessary local copy of foo is + emitted unless -O is used. "extern __inline" is accepted, but the + "extern" appears to be ignored, ie. it becomes a plain global function + but which is inlined within its file. Don't know if all old versions of + DEC C supported __inline, but as a start let's do the right thing for + current versions. */ +#ifdef __DECC +#define __GMP_EXTERN_INLINE static __inline +#endif + +/* SCO OpenUNIX 8 cc supports "static inline foo()" but not in -Xc strict + ANSI mode (__STDC__ is 1 in that mode). Inlining only actually takes + place under -O. Without -O "foo" seems to be emitted whether it's used + or not, which is wasteful. "extern inline foo()" isn't useful, the + "extern" is apparently ignored, so foo is inlined if possible but also + emitted as a global, which causes multiple definition errors when + building a shared libgmp. */ +#ifdef __SCO_VERSION__ +#if __SCO_VERSION__ > 400000000 && __STDC__ != 1 \ + && ! defined (__GMP_EXTERN_INLINE) +#define __GMP_EXTERN_INLINE static inline +#endif +#endif + +/* Microsoft's C compiler accepts __inline */ +#ifdef _MSC_VER +#define __GMP_EXTERN_INLINE __inline +#endif + +/* Recent enough Sun C compilers want "inline" */ +#if defined (__SUNPRO_C) && __SUNPRO_C >= 0x560 \ + && ! defined (__GMP_EXTERN_INLINE) +#define __GMP_EXTERN_INLINE inline +#endif + +/* Somewhat older Sun C compilers want "static inline" */ +#if defined (__SUNPRO_C) && __SUNPRO_C >= 0x540 \ + && ! defined (__GMP_EXTERN_INLINE) +#define __GMP_EXTERN_INLINE static inline +#endif + + +/* C++ always has "inline" and since it's a normal feature the linker should + discard duplicate non-inlined copies, or if it doesn't then that's a + problem for everyone, not just GMP. */ +#if defined (__cplusplus) && ! defined (__GMP_EXTERN_INLINE) +#define __GMP_EXTERN_INLINE inline +#endif + +/* Don't do any inlining within a configure run, since if the compiler ends + up emitting copies of the code into the object file it can end up + demanding the various support routines (like mpn_popcount) for linking, + making the "alloca" test and perhaps others fail. And on hppa ia64 a + pre-release gcc 3.2 was seen not respecting the "extern" in "extern + __inline__", triggering this problem too. */ +#if defined (__GMP_WITHIN_CONFIGURE) && ! __GMP_WITHIN_CONFIGURE_INLINE +#undef __GMP_EXTERN_INLINE +#endif + +/* By default, don't give a prototype when there's going to be an inline + version. Note in particular that Cray C++ objects to the combination of + prototype and inline. */ +#ifdef __GMP_EXTERN_INLINE +#ifndef __GMP_INLINE_PROTOTYPES +#define __GMP_INLINE_PROTOTYPES 0 +#endif +#else +#define __GMP_INLINE_PROTOTYPES 1 +#endif + + +#define __GMP_ABS(x) ((x) >= 0 ? (x) : -(x)) +#define __GMP_MAX(h,i) ((h) > (i) ? (h) : (i)) + + +/* __builtin_expect is in gcc 3.0, and not in 2.95. */ +#if __GMP_GNUC_PREREQ (3,0) +#define __GMP_LIKELY(cond) __builtin_expect ((cond) != 0, 1) +#define __GMP_UNLIKELY(cond) __builtin_expect ((cond) != 0, 0) +#else +#define __GMP_LIKELY(cond) (cond) +#define __GMP_UNLIKELY(cond) (cond) +#endif + +#ifdef _CRAY +#define __GMP_CRAY_Pragma(str) _Pragma (str) +#else +#define __GMP_CRAY_Pragma(str) +#endif + + +/* Allow direct user access to numerator and denominator of an mpq_t object. */ +#define mpq_numref(Q) (&((Q)->_mp_num)) +#define mpq_denref(Q) (&((Q)->_mp_den)) + + +#if defined (__cplusplus) +extern "C" { +using std::FILE; +#endif + +#define mp_set_memory_functions __gmp_set_memory_functions +__GMP_DECLSPEC void mp_set_memory_functions (void *(*) (size_t), + void *(*) (void *, size_t, size_t), + void (*) (void *, size_t)) __GMP_NOTHROW; + +#define mp_get_memory_functions __gmp_get_memory_functions +__GMP_DECLSPEC void mp_get_memory_functions (void *(**) (size_t), + void *(**) (void *, size_t, size_t), + void (**) (void *, size_t)) __GMP_NOTHROW; + +#define mp_bits_per_limb __gmp_bits_per_limb +__GMP_DECLSPEC extern const int mp_bits_per_limb; + +#define gmp_errno __gmp_errno +__GMP_DECLSPEC extern int gmp_errno; + +#define gmp_version __gmp_version +__GMP_DECLSPEC extern const char * const gmp_version; + + +/**************** Random number routines. ****************/ + +/* obsolete */ +#define gmp_randinit __gmp_randinit +__GMP_DECLSPEC void gmp_randinit (gmp_randstate_t, gmp_randalg_t, ...); + +#define gmp_randinit_default __gmp_randinit_default +__GMP_DECLSPEC void gmp_randinit_default (gmp_randstate_t); + +#define gmp_randinit_lc_2exp __gmp_randinit_lc_2exp +__GMP_DECLSPEC void gmp_randinit_lc_2exp (gmp_randstate_t, mpz_srcptr, unsigned long int, mp_bitcnt_t); + +#define gmp_randinit_lc_2exp_size __gmp_randinit_lc_2exp_size +__GMP_DECLSPEC int gmp_randinit_lc_2exp_size (gmp_randstate_t, mp_bitcnt_t); + +#define gmp_randinit_mt __gmp_randinit_mt +__GMP_DECLSPEC void gmp_randinit_mt (gmp_randstate_t); + +#define gmp_randinit_set __gmp_randinit_set +__GMP_DECLSPEC void gmp_randinit_set (gmp_randstate_t, const __gmp_randstate_struct *); + +#define gmp_randseed __gmp_randseed +__GMP_DECLSPEC void gmp_randseed (gmp_randstate_t, mpz_srcptr); + +#define gmp_randseed_ui __gmp_randseed_ui +__GMP_DECLSPEC void gmp_randseed_ui (gmp_randstate_t, unsigned long int); + +#define gmp_randclear __gmp_randclear +__GMP_DECLSPEC void gmp_randclear (gmp_randstate_t); + +#define gmp_urandomb_ui __gmp_urandomb_ui +__GMP_DECLSPEC unsigned long gmp_urandomb_ui (gmp_randstate_t, unsigned long); + +#define gmp_urandomm_ui __gmp_urandomm_ui +__GMP_DECLSPEC unsigned long gmp_urandomm_ui (gmp_randstate_t, unsigned long); + + +/**************** Formatted output routines. ****************/ + +#define gmp_asprintf __gmp_asprintf +__GMP_DECLSPEC int gmp_asprintf (char **, const char *, ...); + +#define gmp_fprintf __gmp_fprintf +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC int gmp_fprintf (FILE *, const char *, ...); +#endif + +#define gmp_obstack_printf __gmp_obstack_printf +#if defined (_GMP_H_HAVE_OBSTACK) +__GMP_DECLSPEC int gmp_obstack_printf (struct obstack *, const char *, ...); +#endif + +#define gmp_obstack_vprintf __gmp_obstack_vprintf +#if defined (_GMP_H_HAVE_OBSTACK) && defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_obstack_vprintf (struct obstack *, const char *, va_list); +#endif + +#define gmp_printf __gmp_printf +__GMP_DECLSPEC int gmp_printf (const char *, ...); + +#define gmp_snprintf __gmp_snprintf +__GMP_DECLSPEC int gmp_snprintf (char *, size_t, const char *, ...); + +#define gmp_sprintf __gmp_sprintf +__GMP_DECLSPEC int gmp_sprintf (char *, const char *, ...); + +#define gmp_vasprintf __gmp_vasprintf +#if defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_vasprintf (char **, const char *, va_list); +#endif + +#define gmp_vfprintf __gmp_vfprintf +#if defined (_GMP_H_HAVE_FILE) && defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_vfprintf (FILE *, const char *, va_list); +#endif + +#define gmp_vprintf __gmp_vprintf +#if defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_vprintf (const char *, va_list); +#endif + +#define gmp_vsnprintf __gmp_vsnprintf +#if defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_vsnprintf (char *, size_t, const char *, va_list); +#endif + +#define gmp_vsprintf __gmp_vsprintf +#if defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_vsprintf (char *, const char *, va_list); +#endif + + +/**************** Formatted input routines. ****************/ + +#define gmp_fscanf __gmp_fscanf +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC int gmp_fscanf (FILE *, const char *, ...); +#endif + +#define gmp_scanf __gmp_scanf +__GMP_DECLSPEC int gmp_scanf (const char *, ...); + +#define gmp_sscanf __gmp_sscanf +__GMP_DECLSPEC int gmp_sscanf (const char *, const char *, ...); + +#define gmp_vfscanf __gmp_vfscanf +#if defined (_GMP_H_HAVE_FILE) && defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_vfscanf (FILE *, const char *, va_list); +#endif + +#define gmp_vscanf __gmp_vscanf +#if defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_vscanf (const char *, va_list); +#endif + +#define gmp_vsscanf __gmp_vsscanf +#if defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_vsscanf (const char *, const char *, va_list); +#endif + + +/**************** Integer (i.e. Z) routines. ****************/ + +#define _mpz_realloc __gmpz_realloc +#define mpz_realloc __gmpz_realloc +__GMP_DECLSPEC void *_mpz_realloc (mpz_ptr, mp_size_t); + +#define mpz_abs __gmpz_abs +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_abs) +__GMP_DECLSPEC void mpz_abs (mpz_ptr, mpz_srcptr); +#endif + +#define mpz_add __gmpz_add +__GMP_DECLSPEC void mpz_add (mpz_ptr, mpz_srcptr, mpz_srcptr); + +#define mpz_add_ui __gmpz_add_ui +__GMP_DECLSPEC void mpz_add_ui (mpz_ptr, mpz_srcptr, unsigned long int); + +#define mpz_addmul __gmpz_addmul +__GMP_DECLSPEC void mpz_addmul (mpz_ptr, mpz_srcptr, mpz_srcptr); + +#define mpz_addmul_ui __gmpz_addmul_ui +__GMP_DECLSPEC void mpz_addmul_ui (mpz_ptr, mpz_srcptr, unsigned long int); + +#define mpz_and __gmpz_and +__GMP_DECLSPEC void mpz_and (mpz_ptr, mpz_srcptr, mpz_srcptr); + +#define mpz_array_init __gmpz_array_init +__GMP_DECLSPEC void mpz_array_init (mpz_ptr, mp_size_t, mp_size_t); + +#define mpz_bin_ui __gmpz_bin_ui +__GMP_DECLSPEC void mpz_bin_ui (mpz_ptr, mpz_srcptr, unsigned long int); + +#define mpz_bin_uiui __gmpz_bin_uiui +__GMP_DECLSPEC void mpz_bin_uiui (mpz_ptr, unsigned long int, unsigned long int); + +#define mpz_cdiv_q __gmpz_cdiv_q +__GMP_DECLSPEC void mpz_cdiv_q (mpz_ptr, mpz_srcptr, mpz_srcptr); + +#define mpz_cdiv_q_2exp __gmpz_cdiv_q_2exp +__GMP_DECLSPEC void mpz_cdiv_q_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); + +#define mpz_cdiv_q_ui __gmpz_cdiv_q_ui +__GMP_DECLSPEC unsigned long int mpz_cdiv_q_ui (mpz_ptr, mpz_srcptr, unsigned long int); + +#define mpz_cdiv_qr __gmpz_cdiv_qr +__GMP_DECLSPEC void mpz_cdiv_qr (mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr); + +#define mpz_cdiv_qr_ui __gmpz_cdiv_qr_ui +__GMP_DECLSPEC unsigned long int mpz_cdiv_qr_ui (mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int); + +#define mpz_cdiv_r __gmpz_cdiv_r +__GMP_DECLSPEC void mpz_cdiv_r (mpz_ptr, mpz_srcptr, mpz_srcptr); + +#define mpz_cdiv_r_2exp __gmpz_cdiv_r_2exp +__GMP_DECLSPEC void mpz_cdiv_r_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); + +#define mpz_cdiv_r_ui __gmpz_cdiv_r_ui +__GMP_DECLSPEC unsigned long int mpz_cdiv_r_ui (mpz_ptr, mpz_srcptr, unsigned long int); + +#define mpz_cdiv_ui __gmpz_cdiv_ui +__GMP_DECLSPEC unsigned long int mpz_cdiv_ui (mpz_srcptr, unsigned long int) __GMP_ATTRIBUTE_PURE; + +#define mpz_clear __gmpz_clear +__GMP_DECLSPEC void mpz_clear (mpz_ptr); + +#define mpz_clears __gmpz_clears +__GMP_DECLSPEC void mpz_clears (mpz_ptr, ...); + +#define mpz_clrbit __gmpz_clrbit +__GMP_DECLSPEC void mpz_clrbit (mpz_ptr, mp_bitcnt_t); + +#define mpz_cmp __gmpz_cmp +__GMP_DECLSPEC int mpz_cmp (mpz_srcptr, mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_cmp_d __gmpz_cmp_d +__GMP_DECLSPEC int mpz_cmp_d (mpz_srcptr, double) __GMP_ATTRIBUTE_PURE; + +#define _mpz_cmp_si __gmpz_cmp_si +__GMP_DECLSPEC int _mpz_cmp_si (mpz_srcptr, signed long int) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define _mpz_cmp_ui __gmpz_cmp_ui +__GMP_DECLSPEC int _mpz_cmp_ui (mpz_srcptr, unsigned long int) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_cmpabs __gmpz_cmpabs +__GMP_DECLSPEC int mpz_cmpabs (mpz_srcptr, mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_cmpabs_d __gmpz_cmpabs_d +__GMP_DECLSPEC int mpz_cmpabs_d (mpz_srcptr, double) __GMP_ATTRIBUTE_PURE; + +#define mpz_cmpabs_ui __gmpz_cmpabs_ui +__GMP_DECLSPEC int mpz_cmpabs_ui (mpz_srcptr, unsigned long int) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_com __gmpz_com +__GMP_DECLSPEC void mpz_com (mpz_ptr, mpz_srcptr); + +#define mpz_combit __gmpz_combit +__GMP_DECLSPEC void mpz_combit (mpz_ptr, mp_bitcnt_t); + +#define mpz_congruent_p __gmpz_congruent_p +__GMP_DECLSPEC int mpz_congruent_p (mpz_srcptr, mpz_srcptr, mpz_srcptr) __GMP_ATTRIBUTE_PURE; + +#define mpz_congruent_2exp_p __gmpz_congruent_2exp_p +__GMP_DECLSPEC int mpz_congruent_2exp_p (mpz_srcptr, mpz_srcptr, mp_bitcnt_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_congruent_ui_p __gmpz_congruent_ui_p +__GMP_DECLSPEC int mpz_congruent_ui_p (mpz_srcptr, unsigned long, unsigned long) __GMP_ATTRIBUTE_PURE; + +#define mpz_divexact __gmpz_divexact +__GMP_DECLSPEC void mpz_divexact (mpz_ptr, mpz_srcptr, mpz_srcptr); + +#define mpz_divexact_ui __gmpz_divexact_ui +__GMP_DECLSPEC void mpz_divexact_ui (mpz_ptr, mpz_srcptr, unsigned long); + +#define mpz_divisible_p __gmpz_divisible_p +__GMP_DECLSPEC int mpz_divisible_p (mpz_srcptr, mpz_srcptr) __GMP_ATTRIBUTE_PURE; + +#define mpz_divisible_ui_p __gmpz_divisible_ui_p +__GMP_DECLSPEC int mpz_divisible_ui_p (mpz_srcptr, unsigned long) __GMP_ATTRIBUTE_PURE; + +#define mpz_divisible_2exp_p __gmpz_divisible_2exp_p +__GMP_DECLSPEC int mpz_divisible_2exp_p (mpz_srcptr, mp_bitcnt_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_dump __gmpz_dump +__GMP_DECLSPEC void mpz_dump (mpz_srcptr); + +#define mpz_export __gmpz_export +__GMP_DECLSPEC void *mpz_export (void *, size_t *, int, size_t, int, size_t, mpz_srcptr); + +#define mpz_fac_ui __gmpz_fac_ui +__GMP_DECLSPEC void mpz_fac_ui (mpz_ptr, unsigned long int); + +#define mpz_2fac_ui __gmpz_2fac_ui +__GMP_DECLSPEC void mpz_2fac_ui (mpz_ptr, unsigned long int); + +#define mpz_mfac_uiui __gmpz_mfac_uiui +__GMP_DECLSPEC void mpz_mfac_uiui (mpz_ptr, unsigned long int, unsigned long int); + +#define mpz_primorial_ui __gmpz_primorial_ui +__GMP_DECLSPEC void mpz_primorial_ui (mpz_ptr, unsigned long int); + +#define mpz_fdiv_q __gmpz_fdiv_q +__GMP_DECLSPEC void mpz_fdiv_q (mpz_ptr, mpz_srcptr, mpz_srcptr); + +#define mpz_fdiv_q_2exp __gmpz_fdiv_q_2exp +__GMP_DECLSPEC void mpz_fdiv_q_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); + +#define mpz_fdiv_q_ui __gmpz_fdiv_q_ui +__GMP_DECLSPEC unsigned long int mpz_fdiv_q_ui (mpz_ptr, mpz_srcptr, unsigned long int); + +#define mpz_fdiv_qr __gmpz_fdiv_qr +__GMP_DECLSPEC void mpz_fdiv_qr (mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr); + +#define mpz_fdiv_qr_ui __gmpz_fdiv_qr_ui +__GMP_DECLSPEC unsigned long int mpz_fdiv_qr_ui (mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int); + +#define mpz_fdiv_r __gmpz_fdiv_r +__GMP_DECLSPEC void mpz_fdiv_r (mpz_ptr, mpz_srcptr, mpz_srcptr); + +#define mpz_fdiv_r_2exp __gmpz_fdiv_r_2exp +__GMP_DECLSPEC void mpz_fdiv_r_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); + +#define mpz_fdiv_r_ui __gmpz_fdiv_r_ui +__GMP_DECLSPEC unsigned long int mpz_fdiv_r_ui (mpz_ptr, mpz_srcptr, unsigned long int); + +#define mpz_fdiv_ui __gmpz_fdiv_ui +__GMP_DECLSPEC unsigned long int mpz_fdiv_ui (mpz_srcptr, unsigned long int) __GMP_ATTRIBUTE_PURE; + +#define mpz_fib_ui __gmpz_fib_ui +__GMP_DECLSPEC void mpz_fib_ui (mpz_ptr, unsigned long int); + +#define mpz_fib2_ui __gmpz_fib2_ui +__GMP_DECLSPEC void mpz_fib2_ui (mpz_ptr, mpz_ptr, unsigned long int); + +#define mpz_fits_sint_p __gmpz_fits_sint_p +__GMP_DECLSPEC int mpz_fits_sint_p (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_fits_slong_p __gmpz_fits_slong_p +__GMP_DECLSPEC int mpz_fits_slong_p (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_fits_sshort_p __gmpz_fits_sshort_p +__GMP_DECLSPEC int mpz_fits_sshort_p (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_fits_uint_p __gmpz_fits_uint_p +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_fits_uint_p) +__GMP_DECLSPEC int mpz_fits_uint_p (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_fits_ulong_p __gmpz_fits_ulong_p +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_fits_ulong_p) +__GMP_DECLSPEC int mpz_fits_ulong_p (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_fits_ushort_p __gmpz_fits_ushort_p +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_fits_ushort_p) +__GMP_DECLSPEC int mpz_fits_ushort_p (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_gcd __gmpz_gcd +__GMP_DECLSPEC void mpz_gcd (mpz_ptr, mpz_srcptr, mpz_srcptr); + +#define mpz_gcd_ui __gmpz_gcd_ui +__GMP_DECLSPEC unsigned long int mpz_gcd_ui (mpz_ptr, mpz_srcptr, unsigned long int); + +#define mpz_gcdext __gmpz_gcdext +__GMP_DECLSPEC void mpz_gcdext (mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr); + +#define mpz_get_d __gmpz_get_d +__GMP_DECLSPEC double mpz_get_d (mpz_srcptr) __GMP_ATTRIBUTE_PURE; + +#define mpz_get_d_2exp __gmpz_get_d_2exp +__GMP_DECLSPEC double mpz_get_d_2exp (signed long int *, mpz_srcptr); + +#define mpz_get_si __gmpz_get_si +__GMP_DECLSPEC /* signed */ long int mpz_get_si (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_get_str __gmpz_get_str +__GMP_DECLSPEC char *mpz_get_str (char *, int, mpz_srcptr); + +#define mpz_get_ui __gmpz_get_ui +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_get_ui) +__GMP_DECLSPEC unsigned long int mpz_get_ui (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_getlimbn __gmpz_getlimbn +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_getlimbn) +__GMP_DECLSPEC mp_limb_t mpz_getlimbn (mpz_srcptr, mp_size_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_hamdist __gmpz_hamdist +__GMP_DECLSPEC mp_bitcnt_t mpz_hamdist (mpz_srcptr, mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_import __gmpz_import +__GMP_DECLSPEC void mpz_import (mpz_ptr, size_t, int, size_t, int, size_t, const void *); + +#define mpz_init __gmpz_init +__GMP_DECLSPEC void mpz_init (mpz_ptr); + +#define mpz_init2 __gmpz_init2 +__GMP_DECLSPEC void mpz_init2 (mpz_ptr, mp_bitcnt_t); + +#define mpz_inits __gmpz_inits +__GMP_DECLSPEC void mpz_inits (mpz_ptr, ...); + +#define mpz_init_set __gmpz_init_set +__GMP_DECLSPEC void mpz_init_set (mpz_ptr, mpz_srcptr); + +#define mpz_init_set_d __gmpz_init_set_d +__GMP_DECLSPEC void mpz_init_set_d (mpz_ptr, double); + +#define mpz_init_set_si __gmpz_init_set_si +__GMP_DECLSPEC void mpz_init_set_si (mpz_ptr, signed long int); + +#define mpz_init_set_str __gmpz_init_set_str +__GMP_DECLSPEC int mpz_init_set_str (mpz_ptr, const char *, int); + +#define mpz_init_set_ui __gmpz_init_set_ui +__GMP_DECLSPEC void mpz_init_set_ui (mpz_ptr, unsigned long int); + +#define mpz_inp_raw __gmpz_inp_raw +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpz_inp_raw (mpz_ptr, FILE *); +#endif + +#define mpz_inp_str __gmpz_inp_str +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpz_inp_str (mpz_ptr, FILE *, int); +#endif + +#define mpz_invert __gmpz_invert +__GMP_DECLSPEC int mpz_invert (mpz_ptr, mpz_srcptr, mpz_srcptr); + +#define mpz_ior __gmpz_ior +__GMP_DECLSPEC void mpz_ior (mpz_ptr, mpz_srcptr, mpz_srcptr); + +#define mpz_jacobi __gmpz_jacobi +__GMP_DECLSPEC int mpz_jacobi (mpz_srcptr, mpz_srcptr) __GMP_ATTRIBUTE_PURE; + +#define mpz_kronecker mpz_jacobi /* alias */ + +#define mpz_kronecker_si __gmpz_kronecker_si +__GMP_DECLSPEC int mpz_kronecker_si (mpz_srcptr, long) __GMP_ATTRIBUTE_PURE; + +#define mpz_kronecker_ui __gmpz_kronecker_ui +__GMP_DECLSPEC int mpz_kronecker_ui (mpz_srcptr, unsigned long) __GMP_ATTRIBUTE_PURE; + +#define mpz_si_kronecker __gmpz_si_kronecker +__GMP_DECLSPEC int mpz_si_kronecker (long, mpz_srcptr) __GMP_ATTRIBUTE_PURE; + +#define mpz_ui_kronecker __gmpz_ui_kronecker +__GMP_DECLSPEC int mpz_ui_kronecker (unsigned long, mpz_srcptr) __GMP_ATTRIBUTE_PURE; + +#define mpz_lcm __gmpz_lcm +__GMP_DECLSPEC void mpz_lcm (mpz_ptr, mpz_srcptr, mpz_srcptr); + +#define mpz_lcm_ui __gmpz_lcm_ui +__GMP_DECLSPEC void mpz_lcm_ui (mpz_ptr, mpz_srcptr, unsigned long); + +#define mpz_legendre mpz_jacobi /* alias */ + +#define mpz_lucnum_ui __gmpz_lucnum_ui +__GMP_DECLSPEC void mpz_lucnum_ui (mpz_ptr, unsigned long int); + +#define mpz_lucnum2_ui __gmpz_lucnum2_ui +__GMP_DECLSPEC void mpz_lucnum2_ui (mpz_ptr, mpz_ptr, unsigned long int); + +#define mpz_millerrabin __gmpz_millerrabin +__GMP_DECLSPEC int mpz_millerrabin (mpz_srcptr, int) __GMP_ATTRIBUTE_PURE; + +#define mpz_mod __gmpz_mod +__GMP_DECLSPEC void mpz_mod (mpz_ptr, mpz_srcptr, mpz_srcptr); + +#define mpz_mod_ui mpz_fdiv_r_ui /* same as fdiv_r because divisor unsigned */ + +#define mpz_mul __gmpz_mul +__GMP_DECLSPEC void mpz_mul (mpz_ptr, mpz_srcptr, mpz_srcptr); + +#define mpz_mul_2exp __gmpz_mul_2exp +__GMP_DECLSPEC void mpz_mul_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); + +#define mpz_mul_si __gmpz_mul_si +__GMP_DECLSPEC void mpz_mul_si (mpz_ptr, mpz_srcptr, long int); + +#define mpz_mul_ui __gmpz_mul_ui +__GMP_DECLSPEC void mpz_mul_ui (mpz_ptr, mpz_srcptr, unsigned long int); + +#define mpz_neg __gmpz_neg +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_neg) +__GMP_DECLSPEC void mpz_neg (mpz_ptr, mpz_srcptr); +#endif + +#define mpz_nextprime __gmpz_nextprime +__GMP_DECLSPEC void mpz_nextprime (mpz_ptr, mpz_srcptr); + +#define mpz_out_raw __gmpz_out_raw +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpz_out_raw (FILE *, mpz_srcptr); +#endif + +#define mpz_out_str __gmpz_out_str +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpz_out_str (FILE *, int, mpz_srcptr); +#endif + +#define mpz_perfect_power_p __gmpz_perfect_power_p +__GMP_DECLSPEC int mpz_perfect_power_p (mpz_srcptr) __GMP_ATTRIBUTE_PURE; + +#define mpz_perfect_square_p __gmpz_perfect_square_p +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_perfect_square_p) +__GMP_DECLSPEC int mpz_perfect_square_p (mpz_srcptr) __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_popcount __gmpz_popcount +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_popcount) +__GMP_DECLSPEC mp_bitcnt_t mpz_popcount (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_pow_ui __gmpz_pow_ui +__GMP_DECLSPEC void mpz_pow_ui (mpz_ptr, mpz_srcptr, unsigned long int); + +#define mpz_powm __gmpz_powm +__GMP_DECLSPEC void mpz_powm (mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr); + +#define mpz_powm_sec __gmpz_powm_sec +__GMP_DECLSPEC void mpz_powm_sec (mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr); + +#define mpz_powm_ui __gmpz_powm_ui +__GMP_DECLSPEC void mpz_powm_ui (mpz_ptr, mpz_srcptr, unsigned long int, mpz_srcptr); + +#define mpz_probab_prime_p __gmpz_probab_prime_p +__GMP_DECLSPEC int mpz_probab_prime_p (mpz_srcptr, int) __GMP_ATTRIBUTE_PURE; + +#define mpz_random __gmpz_random +__GMP_DECLSPEC void mpz_random (mpz_ptr, mp_size_t); + +#define mpz_random2 __gmpz_random2 +__GMP_DECLSPEC void mpz_random2 (mpz_ptr, mp_size_t); + +#define mpz_realloc2 __gmpz_realloc2 +__GMP_DECLSPEC void mpz_realloc2 (mpz_ptr, mp_bitcnt_t); + +#define mpz_remove __gmpz_remove +__GMP_DECLSPEC mp_bitcnt_t mpz_remove (mpz_ptr, mpz_srcptr, mpz_srcptr); + +#define mpz_root __gmpz_root +__GMP_DECLSPEC int mpz_root (mpz_ptr, mpz_srcptr, unsigned long int); + +#define mpz_rootrem __gmpz_rootrem +__GMP_DECLSPEC void mpz_rootrem (mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int); + +#define mpz_rrandomb __gmpz_rrandomb +__GMP_DECLSPEC void mpz_rrandomb (mpz_ptr, gmp_randstate_t, mp_bitcnt_t); + +#define mpz_scan0 __gmpz_scan0 +__GMP_DECLSPEC mp_bitcnt_t mpz_scan0 (mpz_srcptr, mp_bitcnt_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_scan1 __gmpz_scan1 +__GMP_DECLSPEC mp_bitcnt_t mpz_scan1 (mpz_srcptr, mp_bitcnt_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_set __gmpz_set +__GMP_DECLSPEC void mpz_set (mpz_ptr, mpz_srcptr); + +#define mpz_set_d __gmpz_set_d +__GMP_DECLSPEC void mpz_set_d (mpz_ptr, double); + +#define mpz_set_f __gmpz_set_f +__GMP_DECLSPEC void mpz_set_f (mpz_ptr, mpf_srcptr); + +#define mpz_set_q __gmpz_set_q +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_set_q) +__GMP_DECLSPEC void mpz_set_q (mpz_ptr, mpq_srcptr); +#endif + +#define mpz_set_si __gmpz_set_si +__GMP_DECLSPEC void mpz_set_si (mpz_ptr, signed long int); + +#define mpz_set_str __gmpz_set_str +__GMP_DECLSPEC int mpz_set_str (mpz_ptr, const char *, int); + +#define mpz_set_ui __gmpz_set_ui +__GMP_DECLSPEC void mpz_set_ui (mpz_ptr, unsigned long int); + +#define mpz_setbit __gmpz_setbit +__GMP_DECLSPEC void mpz_setbit (mpz_ptr, mp_bitcnt_t); + +#define mpz_size __gmpz_size +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_size) +__GMP_DECLSPEC size_t mpz_size (mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_sizeinbase __gmpz_sizeinbase +__GMP_DECLSPEC size_t mpz_sizeinbase (mpz_srcptr, int) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_sqrt __gmpz_sqrt +__GMP_DECLSPEC void mpz_sqrt (mpz_ptr, mpz_srcptr); + +#define mpz_sqrtrem __gmpz_sqrtrem +__GMP_DECLSPEC void mpz_sqrtrem (mpz_ptr, mpz_ptr, mpz_srcptr); + +#define mpz_sub __gmpz_sub +__GMP_DECLSPEC void mpz_sub (mpz_ptr, mpz_srcptr, mpz_srcptr); + +#define mpz_sub_ui __gmpz_sub_ui +__GMP_DECLSPEC void mpz_sub_ui (mpz_ptr, mpz_srcptr, unsigned long int); + +#define mpz_ui_sub __gmpz_ui_sub +__GMP_DECLSPEC void mpz_ui_sub (mpz_ptr, unsigned long int, mpz_srcptr); + +#define mpz_submul __gmpz_submul +__GMP_DECLSPEC void mpz_submul (mpz_ptr, mpz_srcptr, mpz_srcptr); + +#define mpz_submul_ui __gmpz_submul_ui +__GMP_DECLSPEC void mpz_submul_ui (mpz_ptr, mpz_srcptr, unsigned long int); + +#define mpz_swap __gmpz_swap +__GMP_DECLSPEC void mpz_swap (mpz_ptr, mpz_ptr) __GMP_NOTHROW; + +#define mpz_tdiv_ui __gmpz_tdiv_ui +__GMP_DECLSPEC unsigned long int mpz_tdiv_ui (mpz_srcptr, unsigned long int) __GMP_ATTRIBUTE_PURE; + +#define mpz_tdiv_q __gmpz_tdiv_q +__GMP_DECLSPEC void mpz_tdiv_q (mpz_ptr, mpz_srcptr, mpz_srcptr); + +#define mpz_tdiv_q_2exp __gmpz_tdiv_q_2exp +__GMP_DECLSPEC void mpz_tdiv_q_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); + +#define mpz_tdiv_q_ui __gmpz_tdiv_q_ui +__GMP_DECLSPEC unsigned long int mpz_tdiv_q_ui (mpz_ptr, mpz_srcptr, unsigned long int); + +#define mpz_tdiv_qr __gmpz_tdiv_qr +__GMP_DECLSPEC void mpz_tdiv_qr (mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr); + +#define mpz_tdiv_qr_ui __gmpz_tdiv_qr_ui +__GMP_DECLSPEC unsigned long int mpz_tdiv_qr_ui (mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int); + +#define mpz_tdiv_r __gmpz_tdiv_r +__GMP_DECLSPEC void mpz_tdiv_r (mpz_ptr, mpz_srcptr, mpz_srcptr); + +#define mpz_tdiv_r_2exp __gmpz_tdiv_r_2exp +__GMP_DECLSPEC void mpz_tdiv_r_2exp (mpz_ptr, mpz_srcptr, mp_bitcnt_t); + +#define mpz_tdiv_r_ui __gmpz_tdiv_r_ui +__GMP_DECLSPEC unsigned long int mpz_tdiv_r_ui (mpz_ptr, mpz_srcptr, unsigned long int); + +#define mpz_tstbit __gmpz_tstbit +__GMP_DECLSPEC int mpz_tstbit (mpz_srcptr, mp_bitcnt_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_ui_pow_ui __gmpz_ui_pow_ui +__GMP_DECLSPEC void mpz_ui_pow_ui (mpz_ptr, unsigned long int, unsigned long int); + +#define mpz_urandomb __gmpz_urandomb +__GMP_DECLSPEC void mpz_urandomb (mpz_ptr, gmp_randstate_t, mp_bitcnt_t); + +#define mpz_urandomm __gmpz_urandomm +__GMP_DECLSPEC void mpz_urandomm (mpz_ptr, gmp_randstate_t, mpz_srcptr); + +#define mpz_xor __gmpz_xor +#define mpz_eor __gmpz_xor +__GMP_DECLSPEC void mpz_xor (mpz_ptr, mpz_srcptr, mpz_srcptr); + +#define mpz_limbs_read __gmpz_limbs_read +__GMP_DECLSPEC mp_srcptr mpz_limbs_read (mpz_srcptr); + +#define mpz_limbs_write __gmpz_limbs_write +__GMP_DECLSPEC mp_ptr mpz_limbs_write (mpz_ptr, mp_size_t); + +#define mpz_limbs_modify __gmpz_limbs_modify +__GMP_DECLSPEC mp_ptr mpz_limbs_modify (mpz_ptr, mp_size_t); + +#define mpz_limbs_finish __gmpz_limbs_finish +__GMP_DECLSPEC void mpz_limbs_finish (mpz_ptr, mp_size_t); + +#define mpz_roinit_n __gmpz_roinit_n +__GMP_DECLSPEC mpz_srcptr mpz_roinit_n (mpz_ptr, mp_srcptr, mp_size_t); + +#define MPZ_ROINIT_N(xp, xs) {{0, (xs),(xp) }} + +/**************** Rational (i.e. Q) routines. ****************/ + +#define mpq_abs __gmpq_abs +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpq_abs) +__GMP_DECLSPEC void mpq_abs (mpq_ptr, mpq_srcptr); +#endif + +#define mpq_add __gmpq_add +__GMP_DECLSPEC void mpq_add (mpq_ptr, mpq_srcptr, mpq_srcptr); + +#define mpq_canonicalize __gmpq_canonicalize +__GMP_DECLSPEC void mpq_canonicalize (mpq_ptr); + +#define mpq_clear __gmpq_clear +__GMP_DECLSPEC void mpq_clear (mpq_ptr); + +#define mpq_clears __gmpq_clears +__GMP_DECLSPEC void mpq_clears (mpq_ptr, ...); + +#define mpq_cmp __gmpq_cmp +__GMP_DECLSPEC int mpq_cmp (mpq_srcptr, mpq_srcptr) __GMP_ATTRIBUTE_PURE; + +#define _mpq_cmp_si __gmpq_cmp_si +__GMP_DECLSPEC int _mpq_cmp_si (mpq_srcptr, long, unsigned long) __GMP_ATTRIBUTE_PURE; + +#define _mpq_cmp_ui __gmpq_cmp_ui +__GMP_DECLSPEC int _mpq_cmp_ui (mpq_srcptr, unsigned long int, unsigned long int) __GMP_ATTRIBUTE_PURE; + +#define mpq_cmp_z __gmpq_cmp_z +__GMP_DECLSPEC int mpq_cmp_z (mpq_srcptr, mpz_srcptr) __GMP_ATTRIBUTE_PURE; + +#define mpq_div __gmpq_div +__GMP_DECLSPEC void mpq_div (mpq_ptr, mpq_srcptr, mpq_srcptr); + +#define mpq_div_2exp __gmpq_div_2exp +__GMP_DECLSPEC void mpq_div_2exp (mpq_ptr, mpq_srcptr, mp_bitcnt_t); + +#define mpq_equal __gmpq_equal +__GMP_DECLSPEC int mpq_equal (mpq_srcptr, mpq_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpq_get_num __gmpq_get_num +__GMP_DECLSPEC void mpq_get_num (mpz_ptr, mpq_srcptr); + +#define mpq_get_den __gmpq_get_den +__GMP_DECLSPEC void mpq_get_den (mpz_ptr, mpq_srcptr); + +#define mpq_get_d __gmpq_get_d +__GMP_DECLSPEC double mpq_get_d (mpq_srcptr) __GMP_ATTRIBUTE_PURE; + +#define mpq_get_str __gmpq_get_str +__GMP_DECLSPEC char *mpq_get_str (char *, int, mpq_srcptr); + +#define mpq_init __gmpq_init +__GMP_DECLSPEC void mpq_init (mpq_ptr); + +#define mpq_inits __gmpq_inits +__GMP_DECLSPEC void mpq_inits (mpq_ptr, ...); + +#define mpq_inp_str __gmpq_inp_str +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpq_inp_str (mpq_ptr, FILE *, int); +#endif + +#define mpq_inv __gmpq_inv +__GMP_DECLSPEC void mpq_inv (mpq_ptr, mpq_srcptr); + +#define mpq_mul __gmpq_mul +__GMP_DECLSPEC void mpq_mul (mpq_ptr, mpq_srcptr, mpq_srcptr); + +#define mpq_mul_2exp __gmpq_mul_2exp +__GMP_DECLSPEC void mpq_mul_2exp (mpq_ptr, mpq_srcptr, mp_bitcnt_t); + +#define mpq_neg __gmpq_neg +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpq_neg) +__GMP_DECLSPEC void mpq_neg (mpq_ptr, mpq_srcptr); +#endif + +#define mpq_out_str __gmpq_out_str +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpq_out_str (FILE *, int, mpq_srcptr); +#endif + +#define mpq_set __gmpq_set +__GMP_DECLSPEC void mpq_set (mpq_ptr, mpq_srcptr); + +#define mpq_set_d __gmpq_set_d +__GMP_DECLSPEC void mpq_set_d (mpq_ptr, double); + +#define mpq_set_den __gmpq_set_den +__GMP_DECLSPEC void mpq_set_den (mpq_ptr, mpz_srcptr); + +#define mpq_set_f __gmpq_set_f +__GMP_DECLSPEC void mpq_set_f (mpq_ptr, mpf_srcptr); + +#define mpq_set_num __gmpq_set_num +__GMP_DECLSPEC void mpq_set_num (mpq_ptr, mpz_srcptr); + +#define mpq_set_si __gmpq_set_si +__GMP_DECLSPEC void mpq_set_si (mpq_ptr, signed long int, unsigned long int); + +#define mpq_set_str __gmpq_set_str +__GMP_DECLSPEC int mpq_set_str (mpq_ptr, const char *, int); + +#define mpq_set_ui __gmpq_set_ui +__GMP_DECLSPEC void mpq_set_ui (mpq_ptr, unsigned long int, unsigned long int); + +#define mpq_set_z __gmpq_set_z +__GMP_DECLSPEC void mpq_set_z (mpq_ptr, mpz_srcptr); + +#define mpq_sub __gmpq_sub +__GMP_DECLSPEC void mpq_sub (mpq_ptr, mpq_srcptr, mpq_srcptr); + +#define mpq_swap __gmpq_swap +__GMP_DECLSPEC void mpq_swap (mpq_ptr, mpq_ptr) __GMP_NOTHROW; + + +/**************** Float (i.e. F) routines. ****************/ + +#define mpf_abs __gmpf_abs +__GMP_DECLSPEC void mpf_abs (mpf_ptr, mpf_srcptr); + +#define mpf_add __gmpf_add +__GMP_DECLSPEC void mpf_add (mpf_ptr, mpf_srcptr, mpf_srcptr); + +#define mpf_add_ui __gmpf_add_ui +__GMP_DECLSPEC void mpf_add_ui (mpf_ptr, mpf_srcptr, unsigned long int); +#define mpf_ceil __gmpf_ceil +__GMP_DECLSPEC void mpf_ceil (mpf_ptr, mpf_srcptr); + +#define mpf_clear __gmpf_clear +__GMP_DECLSPEC void mpf_clear (mpf_ptr); + +#define mpf_clears __gmpf_clears +__GMP_DECLSPEC void mpf_clears (mpf_ptr, ...); + +#define mpf_cmp __gmpf_cmp +__GMP_DECLSPEC int mpf_cmp (mpf_srcptr, mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_cmp_z __gmpf_cmp_z +__GMP_DECLSPEC int mpf_cmp_z (mpf_srcptr, mpz_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_cmp_d __gmpf_cmp_d +__GMP_DECLSPEC int mpf_cmp_d (mpf_srcptr, double) __GMP_ATTRIBUTE_PURE; + +#define mpf_cmp_si __gmpf_cmp_si +__GMP_DECLSPEC int mpf_cmp_si (mpf_srcptr, signed long int) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_cmp_ui __gmpf_cmp_ui +__GMP_DECLSPEC int mpf_cmp_ui (mpf_srcptr, unsigned long int) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_div __gmpf_div +__GMP_DECLSPEC void mpf_div (mpf_ptr, mpf_srcptr, mpf_srcptr); + +#define mpf_div_2exp __gmpf_div_2exp +__GMP_DECLSPEC void mpf_div_2exp (mpf_ptr, mpf_srcptr, mp_bitcnt_t); + +#define mpf_div_ui __gmpf_div_ui +__GMP_DECLSPEC void mpf_div_ui (mpf_ptr, mpf_srcptr, unsigned long int); + +#define mpf_dump __gmpf_dump +__GMP_DECLSPEC void mpf_dump (mpf_srcptr); + +#define mpf_eq __gmpf_eq +__GMP_DECLSPEC int mpf_eq (mpf_srcptr, mpf_srcptr, mp_bitcnt_t) __GMP_ATTRIBUTE_PURE; + +#define mpf_fits_sint_p __gmpf_fits_sint_p +__GMP_DECLSPEC int mpf_fits_sint_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_fits_slong_p __gmpf_fits_slong_p +__GMP_DECLSPEC int mpf_fits_slong_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_fits_sshort_p __gmpf_fits_sshort_p +__GMP_DECLSPEC int mpf_fits_sshort_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_fits_uint_p __gmpf_fits_uint_p +__GMP_DECLSPEC int mpf_fits_uint_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_fits_ulong_p __gmpf_fits_ulong_p +__GMP_DECLSPEC int mpf_fits_ulong_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_fits_ushort_p __gmpf_fits_ushort_p +__GMP_DECLSPEC int mpf_fits_ushort_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_floor __gmpf_floor +__GMP_DECLSPEC void mpf_floor (mpf_ptr, mpf_srcptr); + +#define mpf_get_d __gmpf_get_d +__GMP_DECLSPEC double mpf_get_d (mpf_srcptr) __GMP_ATTRIBUTE_PURE; + +#define mpf_get_d_2exp __gmpf_get_d_2exp +__GMP_DECLSPEC double mpf_get_d_2exp (signed long int *, mpf_srcptr); + +#define mpf_get_default_prec __gmpf_get_default_prec +__GMP_DECLSPEC mp_bitcnt_t mpf_get_default_prec (void) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_get_prec __gmpf_get_prec +__GMP_DECLSPEC mp_bitcnt_t mpf_get_prec (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_get_si __gmpf_get_si +__GMP_DECLSPEC long mpf_get_si (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_get_str __gmpf_get_str +__GMP_DECLSPEC char *mpf_get_str (char *, mp_exp_t *, int, size_t, mpf_srcptr); + +#define mpf_get_ui __gmpf_get_ui +__GMP_DECLSPEC unsigned long mpf_get_ui (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_init __gmpf_init +__GMP_DECLSPEC void mpf_init (mpf_ptr); + +#define mpf_init2 __gmpf_init2 +__GMP_DECLSPEC void mpf_init2 (mpf_ptr, mp_bitcnt_t); + +#define mpf_inits __gmpf_inits +__GMP_DECLSPEC void mpf_inits (mpf_ptr, ...); + +#define mpf_init_set __gmpf_init_set +__GMP_DECLSPEC void mpf_init_set (mpf_ptr, mpf_srcptr); + +#define mpf_init_set_d __gmpf_init_set_d +__GMP_DECLSPEC void mpf_init_set_d (mpf_ptr, double); + +#define mpf_init_set_si __gmpf_init_set_si +__GMP_DECLSPEC void mpf_init_set_si (mpf_ptr, signed long int); + +#define mpf_init_set_str __gmpf_init_set_str +__GMP_DECLSPEC int mpf_init_set_str (mpf_ptr, const char *, int); + +#define mpf_init_set_ui __gmpf_init_set_ui +__GMP_DECLSPEC void mpf_init_set_ui (mpf_ptr, unsigned long int); + +#define mpf_inp_str __gmpf_inp_str +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpf_inp_str (mpf_ptr, FILE *, int); +#endif + +#define mpf_integer_p __gmpf_integer_p +__GMP_DECLSPEC int mpf_integer_p (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_mul __gmpf_mul +__GMP_DECLSPEC void mpf_mul (mpf_ptr, mpf_srcptr, mpf_srcptr); + +#define mpf_mul_2exp __gmpf_mul_2exp +__GMP_DECLSPEC void mpf_mul_2exp (mpf_ptr, mpf_srcptr, mp_bitcnt_t); + +#define mpf_mul_ui __gmpf_mul_ui +__GMP_DECLSPEC void mpf_mul_ui (mpf_ptr, mpf_srcptr, unsigned long int); + +#define mpf_neg __gmpf_neg +__GMP_DECLSPEC void mpf_neg (mpf_ptr, mpf_srcptr); + +#define mpf_out_str __gmpf_out_str +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpf_out_str (FILE *, int, size_t, mpf_srcptr); +#endif + +#define mpf_pow_ui __gmpf_pow_ui +__GMP_DECLSPEC void mpf_pow_ui (mpf_ptr, mpf_srcptr, unsigned long int); + +#define mpf_random2 __gmpf_random2 +__GMP_DECLSPEC void mpf_random2 (mpf_ptr, mp_size_t, mp_exp_t); + +#define mpf_reldiff __gmpf_reldiff +__GMP_DECLSPEC void mpf_reldiff (mpf_ptr, mpf_srcptr, mpf_srcptr); + +#define mpf_set __gmpf_set +__GMP_DECLSPEC void mpf_set (mpf_ptr, mpf_srcptr); + +#define mpf_set_d __gmpf_set_d +__GMP_DECLSPEC void mpf_set_d (mpf_ptr, double); + +#define mpf_set_default_prec __gmpf_set_default_prec +__GMP_DECLSPEC void mpf_set_default_prec (mp_bitcnt_t) __GMP_NOTHROW; + +#define mpf_set_prec __gmpf_set_prec +__GMP_DECLSPEC void mpf_set_prec (mpf_ptr, mp_bitcnt_t); + +#define mpf_set_prec_raw __gmpf_set_prec_raw +__GMP_DECLSPEC void mpf_set_prec_raw (mpf_ptr, mp_bitcnt_t) __GMP_NOTHROW; + +#define mpf_set_q __gmpf_set_q +__GMP_DECLSPEC void mpf_set_q (mpf_ptr, mpq_srcptr); + +#define mpf_set_si __gmpf_set_si +__GMP_DECLSPEC void mpf_set_si (mpf_ptr, signed long int); + +#define mpf_set_str __gmpf_set_str +__GMP_DECLSPEC int mpf_set_str (mpf_ptr, const char *, int); + +#define mpf_set_ui __gmpf_set_ui +__GMP_DECLSPEC void mpf_set_ui (mpf_ptr, unsigned long int); + +#define mpf_set_z __gmpf_set_z +__GMP_DECLSPEC void mpf_set_z (mpf_ptr, mpz_srcptr); + +#define mpf_size __gmpf_size +__GMP_DECLSPEC size_t mpf_size (mpf_srcptr) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_sqrt __gmpf_sqrt +__GMP_DECLSPEC void mpf_sqrt (mpf_ptr, mpf_srcptr); + +#define mpf_sqrt_ui __gmpf_sqrt_ui +__GMP_DECLSPEC void mpf_sqrt_ui (mpf_ptr, unsigned long int); + +#define mpf_sub __gmpf_sub +__GMP_DECLSPEC void mpf_sub (mpf_ptr, mpf_srcptr, mpf_srcptr); + +#define mpf_sub_ui __gmpf_sub_ui +__GMP_DECLSPEC void mpf_sub_ui (mpf_ptr, mpf_srcptr, unsigned long int); + +#define mpf_swap __gmpf_swap +__GMP_DECLSPEC void mpf_swap (mpf_ptr, mpf_ptr) __GMP_NOTHROW; + +#define mpf_trunc __gmpf_trunc +__GMP_DECLSPEC void mpf_trunc (mpf_ptr, mpf_srcptr); + +#define mpf_ui_div __gmpf_ui_div +__GMP_DECLSPEC void mpf_ui_div (mpf_ptr, unsigned long int, mpf_srcptr); + +#define mpf_ui_sub __gmpf_ui_sub +__GMP_DECLSPEC void mpf_ui_sub (mpf_ptr, unsigned long int, mpf_srcptr); + +#define mpf_urandomb __gmpf_urandomb +__GMP_DECLSPEC void mpf_urandomb (mpf_t, gmp_randstate_t, mp_bitcnt_t); + + +/************ Low level positive-integer (i.e. N) routines. ************/ + +/* This is ugly, but we need to make user calls reach the prefixed function. */ + +#define mpn_add __MPN(add) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_add) +__GMP_DECLSPEC mp_limb_t mpn_add (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); +#endif + +#define mpn_add_1 __MPN(add_1) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_add_1) +__GMP_DECLSPEC mp_limb_t mpn_add_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t) __GMP_NOTHROW; +#endif + +#define mpn_add_n __MPN(add_n) +__GMP_DECLSPEC mp_limb_t mpn_add_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); + +#define mpn_addmul_1 __MPN(addmul_1) +__GMP_DECLSPEC mp_limb_t mpn_addmul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_cmp __MPN(cmp) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_cmp) +__GMP_DECLSPEC int mpn_cmp (mp_srcptr, mp_srcptr, mp_size_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpn_zero_p __MPN(zero_p) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_zero_p) +__GMP_DECLSPEC int mpn_zero_p (mp_srcptr, mp_size_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpn_divexact_1 __MPN(divexact_1) +__GMP_DECLSPEC void mpn_divexact_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_divexact_by3(dst,src,size) \ + mpn_divexact_by3c (dst, src, size, __GMP_CAST (mp_limb_t, 0)) + +#define mpn_divexact_by3c __MPN(divexact_by3c) +__GMP_DECLSPEC mp_limb_t mpn_divexact_by3c (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_divmod_1(qp,np,nsize,dlimb) \ + mpn_divrem_1 (qp, __GMP_CAST (mp_size_t, 0), np, nsize, dlimb) + +#define mpn_divrem __MPN(divrem) +__GMP_DECLSPEC mp_limb_t mpn_divrem (mp_ptr, mp_size_t, mp_ptr, mp_size_t, mp_srcptr, mp_size_t); + +#define mpn_divrem_1 __MPN(divrem_1) +__GMP_DECLSPEC mp_limb_t mpn_divrem_1 (mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_divrem_2 __MPN(divrem_2) +__GMP_DECLSPEC mp_limb_t mpn_divrem_2 (mp_ptr, mp_size_t, mp_ptr, mp_size_t, mp_srcptr); + +#define mpn_div_qr_1 __MPN(div_qr_1) +__GMP_DECLSPEC mp_limb_t mpn_div_qr_1 (mp_ptr, mp_limb_t *, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_div_qr_2 __MPN(div_qr_2) +__GMP_DECLSPEC mp_limb_t mpn_div_qr_2 (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_srcptr); + +#define mpn_gcd __MPN(gcd) +__GMP_DECLSPEC mp_size_t mpn_gcd (mp_ptr, mp_ptr, mp_size_t, mp_ptr, mp_size_t); + +#define mpn_gcd_1 __MPN(gcd_1) +__GMP_DECLSPEC mp_limb_t mpn_gcd_1 (mp_srcptr, mp_size_t, mp_limb_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_gcdext_1 __MPN(gcdext_1) +__GMP_DECLSPEC mp_limb_t mpn_gcdext_1 (mp_limb_signed_t *, mp_limb_signed_t *, mp_limb_t, mp_limb_t); + +#define mpn_gcdext __MPN(gcdext) +__GMP_DECLSPEC mp_size_t mpn_gcdext (mp_ptr, mp_ptr, mp_size_t *, mp_ptr, mp_size_t, mp_ptr, mp_size_t); + +#define mpn_get_str __MPN(get_str) +__GMP_DECLSPEC size_t mpn_get_str (unsigned char *, int, mp_ptr, mp_size_t); + +#define mpn_hamdist __MPN(hamdist) +__GMP_DECLSPEC mp_bitcnt_t mpn_hamdist (mp_srcptr, mp_srcptr, mp_size_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpn_lshift __MPN(lshift) +__GMP_DECLSPEC mp_limb_t mpn_lshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int); + +#define mpn_mod_1 __MPN(mod_1) +__GMP_DECLSPEC mp_limb_t mpn_mod_1 (mp_srcptr, mp_size_t, mp_limb_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_mul __MPN(mul) +__GMP_DECLSPEC mp_limb_t mpn_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); + +#define mpn_mul_1 __MPN(mul_1) +__GMP_DECLSPEC mp_limb_t mpn_mul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_mul_n __MPN(mul_n) +__GMP_DECLSPEC void mpn_mul_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); + +#define mpn_sqr __MPN(sqr) +__GMP_DECLSPEC void mpn_sqr (mp_ptr, mp_srcptr, mp_size_t); + +#define mpn_neg __MPN(neg) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_neg) +__GMP_DECLSPEC mp_limb_t mpn_neg (mp_ptr, mp_srcptr, mp_size_t); +#endif + +#define mpn_com __MPN(com) +__GMP_DECLSPEC void mpn_com (mp_ptr, mp_srcptr, mp_size_t); + +#define mpn_perfect_square_p __MPN(perfect_square_p) +__GMP_DECLSPEC int mpn_perfect_square_p (mp_srcptr, mp_size_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_perfect_power_p __MPN(perfect_power_p) +__GMP_DECLSPEC int mpn_perfect_power_p (mp_srcptr, mp_size_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_popcount __MPN(popcount) +__GMP_DECLSPEC mp_bitcnt_t mpn_popcount (mp_srcptr, mp_size_t) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpn_pow_1 __MPN(pow_1) +__GMP_DECLSPEC mp_size_t mpn_pow_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_ptr); + +/* undocumented now, but retained here for upward compatibility */ +#define mpn_preinv_mod_1 __MPN(preinv_mod_1) +__GMP_DECLSPEC mp_limb_t mpn_preinv_mod_1 (mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_random __MPN(random) +__GMP_DECLSPEC void mpn_random (mp_ptr, mp_size_t); + +#define mpn_random2 __MPN(random2) +__GMP_DECLSPEC void mpn_random2 (mp_ptr, mp_size_t); + +#define mpn_rshift __MPN(rshift) +__GMP_DECLSPEC mp_limb_t mpn_rshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int); + +#define mpn_scan0 __MPN(scan0) +__GMP_DECLSPEC mp_bitcnt_t mpn_scan0 (mp_srcptr, mp_bitcnt_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_scan1 __MPN(scan1) +__GMP_DECLSPEC mp_bitcnt_t mpn_scan1 (mp_srcptr, mp_bitcnt_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_set_str __MPN(set_str) +__GMP_DECLSPEC mp_size_t mpn_set_str (mp_ptr, const unsigned char *, size_t, int); + +#define mpn_sizeinbase __MPN(sizeinbase) +__GMP_DECLSPEC size_t mpn_sizeinbase (mp_srcptr, mp_size_t, int); + +#define mpn_sqrtrem __MPN(sqrtrem) +__GMP_DECLSPEC mp_size_t mpn_sqrtrem (mp_ptr, mp_ptr, mp_srcptr, mp_size_t); + +#define mpn_sub __MPN(sub) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_sub) +__GMP_DECLSPEC mp_limb_t mpn_sub (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); +#endif + +#define mpn_sub_1 __MPN(sub_1) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_sub_1) +__GMP_DECLSPEC mp_limb_t mpn_sub_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t) __GMP_NOTHROW; +#endif + +#define mpn_sub_n __MPN(sub_n) +__GMP_DECLSPEC mp_limb_t mpn_sub_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); + +#define mpn_submul_1 __MPN(submul_1) +__GMP_DECLSPEC mp_limb_t mpn_submul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); + +#define mpn_tdiv_qr __MPN(tdiv_qr) +__GMP_DECLSPEC void mpn_tdiv_qr (mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); + +#define mpn_and_n __MPN(and_n) +__GMP_DECLSPEC void mpn_and_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_andn_n __MPN(andn_n) +__GMP_DECLSPEC void mpn_andn_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_nand_n __MPN(nand_n) +__GMP_DECLSPEC void mpn_nand_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_ior_n __MPN(ior_n) +__GMP_DECLSPEC void mpn_ior_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_iorn_n __MPN(iorn_n) +__GMP_DECLSPEC void mpn_iorn_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_nior_n __MPN(nior_n) +__GMP_DECLSPEC void mpn_nior_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_xor_n __MPN(xor_n) +__GMP_DECLSPEC void mpn_xor_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_xnor_n __MPN(xnor_n) +__GMP_DECLSPEC void mpn_xnor_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); + +#define mpn_copyi __MPN(copyi) +__GMP_DECLSPEC void mpn_copyi (mp_ptr, mp_srcptr, mp_size_t); +#define mpn_copyd __MPN(copyd) +__GMP_DECLSPEC void mpn_copyd (mp_ptr, mp_srcptr, mp_size_t); +#define mpn_zero __MPN(zero) +__GMP_DECLSPEC void mpn_zero (mp_ptr, mp_size_t); + +#define mpn_cnd_add_n __MPN(cnd_add_n) +__GMP_DECLSPEC mp_limb_t mpn_cnd_add_n (mp_limb_t, mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +#define mpn_cnd_sub_n __MPN(cnd_sub_n) +__GMP_DECLSPEC mp_limb_t mpn_cnd_sub_n (mp_limb_t, mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); + +#define mpn_sec_add_1 __MPN(sec_add_1) +__GMP_DECLSPEC mp_limb_t mpn_sec_add_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_ptr); +#define mpn_sec_add_1_itch __MPN(sec_add_1_itch) +__GMP_DECLSPEC mp_size_t mpn_sec_add_1_itch (mp_size_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_sec_sub_1 __MPN(sec_sub_1) +__GMP_DECLSPEC mp_limb_t mpn_sec_sub_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_ptr); +#define mpn_sec_sub_1_itch __MPN(sec_sub_1_itch) +__GMP_DECLSPEC mp_size_t mpn_sec_sub_1_itch (mp_size_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_cnd_swap __MPN(cnd_swap) +__GMP_DECLSPEC void mpn_cnd_swap (mp_limb_t, volatile mp_limb_t *, volatile mp_limb_t *, mp_size_t); + +#define mpn_sec_mul __MPN(sec_mul) +__GMP_DECLSPEC void mpn_sec_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_sec_mul_itch __MPN(sec_mul_itch) +__GMP_DECLSPEC mp_size_t mpn_sec_mul_itch (mp_size_t, mp_size_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_sec_sqr __MPN(sec_sqr) +__GMP_DECLSPEC void mpn_sec_sqr (mp_ptr, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_sec_sqr_itch __MPN(sec_sqr_itch) +__GMP_DECLSPEC mp_size_t mpn_sec_sqr_itch (mp_size_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_sec_powm __MPN(sec_powm) +__GMP_DECLSPEC void mpn_sec_powm (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_bitcnt_t, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_sec_powm_itch __MPN(sec_powm_itch) +__GMP_DECLSPEC mp_size_t mpn_sec_powm_itch (mp_size_t, mp_bitcnt_t, mp_size_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_sec_tabselect __MPN(sec_tabselect) +__GMP_DECLSPEC void mpn_sec_tabselect (volatile mp_limb_t *, volatile const mp_limb_t *, mp_size_t, mp_size_t, mp_size_t); + +#define mpn_sec_div_qr __MPN(sec_div_qr) +__GMP_DECLSPEC mp_limb_t mpn_sec_div_qr (mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_sec_div_qr_itch __MPN(sec_div_qr_itch) +__GMP_DECLSPEC mp_size_t mpn_sec_div_qr_itch (mp_size_t, mp_size_t) __GMP_ATTRIBUTE_PURE; +#define mpn_sec_div_r __MPN(sec_div_r) +__GMP_DECLSPEC void mpn_sec_div_r (mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_ptr); +#define mpn_sec_div_r_itch __MPN(sec_div_r_itch) +__GMP_DECLSPEC mp_size_t mpn_sec_div_r_itch (mp_size_t, mp_size_t) __GMP_ATTRIBUTE_PURE; + +#define mpn_sec_invert __MPN(sec_invert) +__GMP_DECLSPEC int mpn_sec_invert (mp_ptr, mp_ptr, mp_srcptr, mp_size_t, mp_bitcnt_t, mp_ptr); +#define mpn_sec_invert_itch __MPN(sec_invert_itch) +__GMP_DECLSPEC mp_size_t mpn_sec_invert_itch (mp_size_t) __GMP_ATTRIBUTE_PURE; + + +/**************** mpz inlines ****************/ + +/* The following are provided as inlines where possible, but always exist as + library functions too, for binary compatibility. + + Within gmp itself this inlining generally isn't relied on, since it + doesn't get done for all compilers, whereas if something is worth + inlining then it's worth arranging always. + + There are two styles of inlining here. When the same bit of code is + wanted for the inline as for the library version, then __GMP_FORCE_foo + arranges for that code to be emitted and the __GMP_EXTERN_INLINE + directive suppressed, eg. mpz_fits_uint_p. When a different bit of code + is wanted for the inline than for the library version, then + __GMP_FORCE_foo arranges the inline to be suppressed, eg. mpz_abs. */ + +#if defined (__GMP_EXTERN_INLINE) && ! defined (__GMP_FORCE_mpz_abs) +__GMP_EXTERN_INLINE void +mpz_abs (mpz_ptr __gmp_w, mpz_srcptr __gmp_u) +{ + if (__gmp_w != __gmp_u) + mpz_set (__gmp_w, __gmp_u); + __gmp_w->_mp_size = __GMP_ABS (__gmp_w->_mp_size); +} +#endif + +#if GMP_NAIL_BITS == 0 +#define __GMPZ_FITS_UTYPE_P(z,maxval) \ + mp_size_t __gmp_n = z->_mp_size; \ + mp_ptr __gmp_p = z->_mp_d; \ + return (__gmp_n == 0 || (__gmp_n == 1 && __gmp_p[0] <= maxval)); +#else +#define __GMPZ_FITS_UTYPE_P(z,maxval) \ + mp_size_t __gmp_n = z->_mp_size; \ + mp_ptr __gmp_p = z->_mp_d; \ + return (__gmp_n == 0 || (__gmp_n == 1 && __gmp_p[0] <= maxval) \ + || (__gmp_n == 2 && __gmp_p[1] <= ((mp_limb_t) maxval >> GMP_NUMB_BITS))); +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_fits_uint_p) +#if ! defined (__GMP_FORCE_mpz_fits_uint_p) +__GMP_EXTERN_INLINE +#endif +int +mpz_fits_uint_p (mpz_srcptr __gmp_z) __GMP_NOTHROW +{ + __GMPZ_FITS_UTYPE_P (__gmp_z, UINT_MAX); +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_fits_ulong_p) +#if ! defined (__GMP_FORCE_mpz_fits_ulong_p) +__GMP_EXTERN_INLINE +#endif +int +mpz_fits_ulong_p (mpz_srcptr __gmp_z) __GMP_NOTHROW +{ + __GMPZ_FITS_UTYPE_P (__gmp_z, ULONG_MAX); +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_fits_ushort_p) +#if ! defined (__GMP_FORCE_mpz_fits_ushort_p) +__GMP_EXTERN_INLINE +#endif +int +mpz_fits_ushort_p (mpz_srcptr __gmp_z) __GMP_NOTHROW +{ + __GMPZ_FITS_UTYPE_P (__gmp_z, USHRT_MAX); +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_get_ui) +#if ! defined (__GMP_FORCE_mpz_get_ui) +__GMP_EXTERN_INLINE +#endif +unsigned long +mpz_get_ui (mpz_srcptr __gmp_z) __GMP_NOTHROW +{ + mp_ptr __gmp_p = __gmp_z->_mp_d; + mp_size_t __gmp_n = __gmp_z->_mp_size; + mp_limb_t __gmp_l = __gmp_p[0]; + /* This is a "#if" rather than a plain "if" so as to avoid gcc warnings + about "<< GMP_NUMB_BITS" exceeding the type size, and to avoid Borland + C++ 6.0 warnings about condition always true for something like + "ULONG_MAX < GMP_NUMB_MASK". */ +#if GMP_NAIL_BITS == 0 || defined (_LONG_LONG_LIMB) + /* limb==long and no nails, or limb==longlong, one limb is enough */ + return (__gmp_n != 0 ? __gmp_l : 0); +#else + /* limb==long and nails, need two limbs when available */ + __gmp_n = __GMP_ABS (__gmp_n); + if (__gmp_n <= 1) + return (__gmp_n != 0 ? __gmp_l : 0); + else + return __gmp_l + (__gmp_p[1] << GMP_NUMB_BITS); +#endif +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_getlimbn) +#if ! defined (__GMP_FORCE_mpz_getlimbn) +__GMP_EXTERN_INLINE +#endif +mp_limb_t +mpz_getlimbn (mpz_srcptr __gmp_z, mp_size_t __gmp_n) __GMP_NOTHROW +{ + mp_limb_t __gmp_result = 0; + if (__GMP_LIKELY (__gmp_n >= 0 && __gmp_n < __GMP_ABS (__gmp_z->_mp_size))) + __gmp_result = __gmp_z->_mp_d[__gmp_n]; + return __gmp_result; +} +#endif + +#if defined (__GMP_EXTERN_INLINE) && ! defined (__GMP_FORCE_mpz_neg) +__GMP_EXTERN_INLINE void +mpz_neg (mpz_ptr __gmp_w, mpz_srcptr __gmp_u) +{ + if (__gmp_w != __gmp_u) + mpz_set (__gmp_w, __gmp_u); + __gmp_w->_mp_size = - __gmp_w->_mp_size; +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_perfect_square_p) +#if ! defined (__GMP_FORCE_mpz_perfect_square_p) +__GMP_EXTERN_INLINE +#endif +int +mpz_perfect_square_p (mpz_srcptr __gmp_a) +{ + mp_size_t __gmp_asize; + int __gmp_result; + + __gmp_asize = __gmp_a->_mp_size; + __gmp_result = (__gmp_asize >= 0); /* zero is a square, negatives are not */ + if (__GMP_LIKELY (__gmp_asize > 0)) + __gmp_result = mpn_perfect_square_p (__gmp_a->_mp_d, __gmp_asize); + return __gmp_result; +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_popcount) +#if ! defined (__GMP_FORCE_mpz_popcount) +__GMP_EXTERN_INLINE +#endif +mp_bitcnt_t +mpz_popcount (mpz_srcptr __gmp_u) __GMP_NOTHROW +{ + mp_size_t __gmp_usize; + mp_bitcnt_t __gmp_result; + + __gmp_usize = __gmp_u->_mp_size; + __gmp_result = (__gmp_usize < 0 ? ULONG_MAX : 0); + if (__GMP_LIKELY (__gmp_usize > 0)) + __gmp_result = mpn_popcount (__gmp_u->_mp_d, __gmp_usize); + return __gmp_result; +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_set_q) +#if ! defined (__GMP_FORCE_mpz_set_q) +__GMP_EXTERN_INLINE +#endif +void +mpz_set_q (mpz_ptr __gmp_w, mpq_srcptr __gmp_u) +{ + mpz_tdiv_q (__gmp_w, mpq_numref (__gmp_u), mpq_denref (__gmp_u)); +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_size) +#if ! defined (__GMP_FORCE_mpz_size) +__GMP_EXTERN_INLINE +#endif +size_t +mpz_size (mpz_srcptr __gmp_z) __GMP_NOTHROW +{ + return __GMP_ABS (__gmp_z->_mp_size); +} +#endif + + +/**************** mpq inlines ****************/ + +#if defined (__GMP_EXTERN_INLINE) && ! defined (__GMP_FORCE_mpq_abs) +__GMP_EXTERN_INLINE void +mpq_abs (mpq_ptr __gmp_w, mpq_srcptr __gmp_u) +{ + if (__gmp_w != __gmp_u) + mpq_set (__gmp_w, __gmp_u); + __gmp_w->_mp_num._mp_size = __GMP_ABS (__gmp_w->_mp_num._mp_size); +} +#endif + +#if defined (__GMP_EXTERN_INLINE) && ! defined (__GMP_FORCE_mpq_neg) +__GMP_EXTERN_INLINE void +mpq_neg (mpq_ptr __gmp_w, mpq_srcptr __gmp_u) +{ + if (__gmp_w != __gmp_u) + mpq_set (__gmp_w, __gmp_u); + __gmp_w->_mp_num._mp_size = - __gmp_w->_mp_num._mp_size; +} +#endif + + +/**************** mpn inlines ****************/ + +/* The comments with __GMPN_ADD_1 below apply here too. + + The test for FUNCTION returning 0 should predict well. If it's assumed + {yp,ysize} will usually have a random number of bits then the high limb + won't be full and a carry out will occur a good deal less than 50% of the + time. + + ysize==0 isn't a documented feature, but is used internally in a few + places. + + Producing cout last stops it using up a register during the main part of + the calculation, though gcc (as of 3.0) on an "if (mpn_add (...))" + doesn't seem able to move the true and false legs of the conditional up + to the two places cout is generated. */ + +#define __GMPN_AORS(cout, wp, xp, xsize, yp, ysize, FUNCTION, TEST) \ + do { \ + mp_size_t __gmp_i; \ + mp_limb_t __gmp_x; \ + \ + /* ASSERT ((ysize) >= 0); */ \ + /* ASSERT ((xsize) >= (ysize)); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE2_P (wp, xsize, xp, xsize)); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE2_P (wp, xsize, yp, ysize)); */ \ + \ + __gmp_i = (ysize); \ + if (__gmp_i != 0) \ + { \ + if (FUNCTION (wp, xp, yp, __gmp_i)) \ + { \ + do \ + { \ + if (__gmp_i >= (xsize)) \ + { \ + (cout) = 1; \ + goto __gmp_done; \ + } \ + __gmp_x = (xp)[__gmp_i]; \ + } \ + while (TEST); \ + } \ + } \ + if ((wp) != (xp)) \ + __GMPN_COPY_REST (wp, xp, xsize, __gmp_i); \ + (cout) = 0; \ + __gmp_done: \ + ; \ + } while (0) + +#define __GMPN_ADD(cout, wp, xp, xsize, yp, ysize) \ + __GMPN_AORS (cout, wp, xp, xsize, yp, ysize, mpn_add_n, \ + (((wp)[__gmp_i++] = (__gmp_x + 1) & GMP_NUMB_MASK) == 0)) +#define __GMPN_SUB(cout, wp, xp, xsize, yp, ysize) \ + __GMPN_AORS (cout, wp, xp, xsize, yp, ysize, mpn_sub_n, \ + (((wp)[__gmp_i++] = (__gmp_x - 1) & GMP_NUMB_MASK), __gmp_x == 0)) + + +/* The use of __gmp_i indexing is designed to ensure a compile time src==dst + remains nice and clear to the compiler, so that __GMPN_COPY_REST can + disappear, and the load/add/store gets a chance to become a + read-modify-write on CISC CPUs. + + Alternatives: + + Using a pair of pointers instead of indexing would be possible, but gcc + isn't able to recognise compile-time src==dst in that case, even when the + pointers are incremented more or less together. Other compilers would + very likely have similar difficulty. + + gcc could use "if (__builtin_constant_p(src==dst) && src==dst)" or + similar to detect a compile-time src==dst. This works nicely on gcc + 2.95.x, it's not good on gcc 3.0 where __builtin_constant_p(p==p) seems + to be always false, for a pointer p. But the current code form seems + good enough for src==dst anyway. + + gcc on x86 as usual doesn't give particularly good flags handling for the + carry/borrow detection. It's tempting to want some multi instruction asm + blocks to help it, and this was tried, but in truth there's only a few + instructions to save and any gain is all too easily lost by register + juggling setting up for the asm. */ + +#if GMP_NAIL_BITS == 0 +#define __GMPN_AORS_1(cout, dst, src, n, v, OP, CB) \ + do { \ + mp_size_t __gmp_i; \ + mp_limb_t __gmp_x, __gmp_r; \ + \ + /* ASSERT ((n) >= 1); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, n)); */ \ + \ + __gmp_x = (src)[0]; \ + __gmp_r = __gmp_x OP (v); \ + (dst)[0] = __gmp_r; \ + if (CB (__gmp_r, __gmp_x, (v))) \ + { \ + (cout) = 1; \ + for (__gmp_i = 1; __gmp_i < (n);) \ + { \ + __gmp_x = (src)[__gmp_i]; \ + __gmp_r = __gmp_x OP 1; \ + (dst)[__gmp_i] = __gmp_r; \ + ++__gmp_i; \ + if (!CB (__gmp_r, __gmp_x, 1)) \ + { \ + if ((src) != (dst)) \ + __GMPN_COPY_REST (dst, src, n, __gmp_i); \ + (cout) = 0; \ + break; \ + } \ + } \ + } \ + else \ + { \ + if ((src) != (dst)) \ + __GMPN_COPY_REST (dst, src, n, 1); \ + (cout) = 0; \ + } \ + } while (0) +#endif + +#if GMP_NAIL_BITS >= 1 +#define __GMPN_AORS_1(cout, dst, src, n, v, OP, CB) \ + do { \ + mp_size_t __gmp_i; \ + mp_limb_t __gmp_x, __gmp_r; \ + \ + /* ASSERT ((n) >= 1); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, n)); */ \ + \ + __gmp_x = (src)[0]; \ + __gmp_r = __gmp_x OP (v); \ + (dst)[0] = __gmp_r & GMP_NUMB_MASK; \ + if (__gmp_r >> GMP_NUMB_BITS != 0) \ + { \ + (cout) = 1; \ + for (__gmp_i = 1; __gmp_i < (n);) \ + { \ + __gmp_x = (src)[__gmp_i]; \ + __gmp_r = __gmp_x OP 1; \ + (dst)[__gmp_i] = __gmp_r & GMP_NUMB_MASK; \ + ++__gmp_i; \ + if (__gmp_r >> GMP_NUMB_BITS == 0) \ + { \ + if ((src) != (dst)) \ + __GMPN_COPY_REST (dst, src, n, __gmp_i); \ + (cout) = 0; \ + break; \ + } \ + } \ + } \ + else \ + { \ + if ((src) != (dst)) \ + __GMPN_COPY_REST (dst, src, n, 1); \ + (cout) = 0; \ + } \ + } while (0) +#endif + +#define __GMPN_ADDCB(r,x,y) ((r) < (y)) +#define __GMPN_SUBCB(r,x,y) ((x) < (y)) + +#define __GMPN_ADD_1(cout, dst, src, n, v) \ + __GMPN_AORS_1(cout, dst, src, n, v, +, __GMPN_ADDCB) +#define __GMPN_SUB_1(cout, dst, src, n, v) \ + __GMPN_AORS_1(cout, dst, src, n, v, -, __GMPN_SUBCB) + + +/* Compare {xp,size} and {yp,size}, setting "result" to positive, zero or + negative. size==0 is allowed. On random data usually only one limb will + need to be examined to get a result, so it's worth having it inline. */ +#define __GMPN_CMP(result, xp, yp, size) \ + do { \ + mp_size_t __gmp_i; \ + mp_limb_t __gmp_x, __gmp_y; \ + \ + /* ASSERT ((size) >= 0); */ \ + \ + (result) = 0; \ + __gmp_i = (size); \ + while (--__gmp_i >= 0) \ + { \ + __gmp_x = (xp)[__gmp_i]; \ + __gmp_y = (yp)[__gmp_i]; \ + if (__gmp_x != __gmp_y) \ + { \ + /* Cannot use __gmp_x - __gmp_y, may overflow an "int" */ \ + (result) = (__gmp_x > __gmp_y ? 1 : -1); \ + break; \ + } \ + } \ + } while (0) + + +#if defined (__GMPN_COPY) && ! defined (__GMPN_COPY_REST) +#define __GMPN_COPY_REST(dst, src, size, start) \ + do { \ + /* ASSERT ((start) >= 0); */ \ + /* ASSERT ((start) <= (size)); */ \ + __GMPN_COPY ((dst)+(start), (src)+(start), (size)-(start)); \ + } while (0) +#endif + +/* Copy {src,size} to {dst,size}, starting at "start". This is designed to + keep the indexing dst[j] and src[j] nice and simple for __GMPN_ADD_1, + __GMPN_ADD, etc. */ +#if ! defined (__GMPN_COPY_REST) +#define __GMPN_COPY_REST(dst, src, size, start) \ + do { \ + mp_size_t __gmp_j; \ + /* ASSERT ((size) >= 0); */ \ + /* ASSERT ((start) >= 0); */ \ + /* ASSERT ((start) <= (size)); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, size)); */ \ + __GMP_CRAY_Pragma ("_CRI ivdep"); \ + for (__gmp_j = (start); __gmp_j < (size); __gmp_j++) \ + (dst)[__gmp_j] = (src)[__gmp_j]; \ + } while (0) +#endif + +/* Enhancement: Use some of the smarter code from gmp-impl.h. Maybe use + mpn_copyi if there's a native version, and if we don't mind demanding + binary compatibility for it (on targets which use it). */ + +#if ! defined (__GMPN_COPY) +#define __GMPN_COPY(dst, src, size) __GMPN_COPY_REST (dst, src, size, 0) +#endif + + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_add) +#if ! defined (__GMP_FORCE_mpn_add) +__GMP_EXTERN_INLINE +#endif +mp_limb_t +mpn_add (mp_ptr __gmp_wp, mp_srcptr __gmp_xp, mp_size_t __gmp_xsize, mp_srcptr __gmp_yp, mp_size_t __gmp_ysize) +{ + mp_limb_t __gmp_c; + __GMPN_ADD (__gmp_c, __gmp_wp, __gmp_xp, __gmp_xsize, __gmp_yp, __gmp_ysize); + return __gmp_c; +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_add_1) +#if ! defined (__GMP_FORCE_mpn_add_1) +__GMP_EXTERN_INLINE +#endif +mp_limb_t +mpn_add_1 (mp_ptr __gmp_dst, mp_srcptr __gmp_src, mp_size_t __gmp_size, mp_limb_t __gmp_n) __GMP_NOTHROW +{ + mp_limb_t __gmp_c; + __GMPN_ADD_1 (__gmp_c, __gmp_dst, __gmp_src, __gmp_size, __gmp_n); + return __gmp_c; +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_cmp) +#if ! defined (__GMP_FORCE_mpn_cmp) +__GMP_EXTERN_INLINE +#endif +int +mpn_cmp (mp_srcptr __gmp_xp, mp_srcptr __gmp_yp, mp_size_t __gmp_size) __GMP_NOTHROW +{ + int __gmp_result; + __GMPN_CMP (__gmp_result, __gmp_xp, __gmp_yp, __gmp_size); + return __gmp_result; +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_zero_p) +#if ! defined (__GMP_FORCE_mpn_zero_p) +__GMP_EXTERN_INLINE +#endif +int +mpn_zero_p (mp_srcptr __gmp_p, mp_size_t __gmp_n) __GMP_NOTHROW +{ + /* if (__GMP_LIKELY (__gmp_n > 0)) */ + do { + if (__gmp_p[--__gmp_n] != 0) + return 0; + } while (__gmp_n != 0); + return 1; +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_sub) +#if ! defined (__GMP_FORCE_mpn_sub) +__GMP_EXTERN_INLINE +#endif +mp_limb_t +mpn_sub (mp_ptr __gmp_wp, mp_srcptr __gmp_xp, mp_size_t __gmp_xsize, mp_srcptr __gmp_yp, mp_size_t __gmp_ysize) +{ + mp_limb_t __gmp_c; + __GMPN_SUB (__gmp_c, __gmp_wp, __gmp_xp, __gmp_xsize, __gmp_yp, __gmp_ysize); + return __gmp_c; +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_sub_1) +#if ! defined (__GMP_FORCE_mpn_sub_1) +__GMP_EXTERN_INLINE +#endif +mp_limb_t +mpn_sub_1 (mp_ptr __gmp_dst, mp_srcptr __gmp_src, mp_size_t __gmp_size, mp_limb_t __gmp_n) __GMP_NOTHROW +{ + mp_limb_t __gmp_c; + __GMPN_SUB_1 (__gmp_c, __gmp_dst, __gmp_src, __gmp_size, __gmp_n); + return __gmp_c; +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_neg) +#if ! defined (__GMP_FORCE_mpn_neg) +__GMP_EXTERN_INLINE +#endif +mp_limb_t +mpn_neg (mp_ptr __gmp_rp, mp_srcptr __gmp_up, mp_size_t __gmp_n) +{ + while (*__gmp_up == 0) /* Low zero limbs are unchanged by negation. */ + { + *__gmp_rp = 0; + if (!--__gmp_n) /* All zero */ + return 0; + ++__gmp_up; ++__gmp_rp; + } + + *__gmp_rp = (- *__gmp_up) & GMP_NUMB_MASK; + + if (--__gmp_n) /* Higher limbs get complemented. */ + mpn_com (++__gmp_rp, ++__gmp_up, __gmp_n); + + return 1; +} +#endif + +#if defined (__cplusplus) +} +#endif + + +/* Allow faster testing for negative, zero, and positive. */ +#define mpz_sgn(Z) ((Z)->_mp_size < 0 ? -1 : (Z)->_mp_size > 0) +#define mpf_sgn(F) ((F)->_mp_size < 0 ? -1 : (F)->_mp_size > 0) +#define mpq_sgn(Q) ((Q)->_mp_num._mp_size < 0 ? -1 : (Q)->_mp_num._mp_size > 0) + +/* When using GCC, optimize certain common comparisons. */ +#if defined (__GNUC__) && __GNUC__ >= 2 +#define mpz_cmp_ui(Z,UI) \ + (__builtin_constant_p (UI) && (UI) == 0 \ + ? mpz_sgn (Z) : _mpz_cmp_ui (Z,UI)) +#define mpz_cmp_si(Z,SI) \ + (__builtin_constant_p ((SI) >= 0) && (SI) >= 0 \ + ? mpz_cmp_ui (Z, __GMP_CAST (unsigned long, SI)) \ + : _mpz_cmp_si (Z,SI)) +#define mpq_cmp_ui(Q,NUI,DUI) \ + (__builtin_constant_p (NUI) && (NUI) == 0 ? mpq_sgn (Q) \ + : __builtin_constant_p ((NUI) == (DUI)) && (NUI) == (DUI) \ + ? mpz_cmp (mpq_numref (Q), mpq_denref (Q)) \ + : _mpq_cmp_ui (Q,NUI,DUI)) +#define mpq_cmp_si(q,n,d) \ + (__builtin_constant_p ((n) >= 0) && (n) >= 0 \ + ? mpq_cmp_ui (q, __GMP_CAST (unsigned long, n), d) \ + : _mpq_cmp_si (q, n, d)) +#else +#define mpz_cmp_ui(Z,UI) _mpz_cmp_ui (Z,UI) +#define mpz_cmp_si(Z,UI) _mpz_cmp_si (Z,UI) +#define mpq_cmp_ui(Q,NUI,DUI) _mpq_cmp_ui (Q,NUI,DUI) +#define mpq_cmp_si(q,n,d) _mpq_cmp_si(q,n,d) +#endif + + +/* Using "&" rather than "&&" means these can come out branch-free. Every + mpz_t has at least one limb allocated, so fetching the low limb is always + allowed. */ +#define mpz_odd_p(z) (((z)->_mp_size != 0) & __GMP_CAST (int, (z)->_mp_d[0])) +#define mpz_even_p(z) (! mpz_odd_p (z)) + + +/**************** C++ routines ****************/ + +#ifdef __cplusplus +__GMP_DECLSPEC_XX std::ostream& operator<< (std::ostream &, mpz_srcptr); +__GMP_DECLSPEC_XX std::ostream& operator<< (std::ostream &, mpq_srcptr); +__GMP_DECLSPEC_XX std::ostream& operator<< (std::ostream &, mpf_srcptr); +__GMP_DECLSPEC_XX std::istream& operator>> (std::istream &, mpz_ptr); +__GMP_DECLSPEC_XX std::istream& operator>> (std::istream &, mpq_ptr); +__GMP_DECLSPEC_XX std::istream& operator>> (std::istream &, mpf_ptr); +#endif + + +/* Source-level compatibility with GMP 2 and earlier. */ +#define mpn_divmod(qp,np,nsize,dp,dsize) \ + mpn_divrem (qp, __GMP_CAST (mp_size_t, 0), np, nsize, dp, dsize) + +/* Source-level compatibility with GMP 1. */ +#define mpz_mdiv mpz_fdiv_q +#define mpz_mdivmod mpz_fdiv_qr +#define mpz_mmod mpz_fdiv_r +#define mpz_mdiv_ui mpz_fdiv_q_ui +#define mpz_mdivmod_ui(q,r,n,d) \ + (((r) == 0) ? mpz_fdiv_q_ui (q,n,d) : mpz_fdiv_qr_ui (q,r,n,d)) +#define mpz_mmod_ui(r,n,d) \ + (((r) == 0) ? mpz_fdiv_ui (n,d) : mpz_fdiv_r_ui (r,n,d)) + +/* Useful synonyms, but not quite compatible with GMP 1. */ +#define mpz_div mpz_fdiv_q +#define mpz_divmod mpz_fdiv_qr +#define mpz_div_ui mpz_fdiv_q_ui +#define mpz_divmod_ui mpz_fdiv_qr_ui +#define mpz_div_2exp mpz_fdiv_q_2exp +#define mpz_mod_2exp mpz_fdiv_r_2exp + +enum +{ + GMP_ERROR_NONE = 0, + GMP_ERROR_UNSUPPORTED_ARGUMENT = 1, + GMP_ERROR_DIVISION_BY_ZERO = 2, + GMP_ERROR_SQRT_OF_NEGATIVE = 4, + GMP_ERROR_INVALID_ARGUMENT = 8 +}; + +/* Define CC and CFLAGS which were used to build this version of GMP */ +#define __GMP_CC "gcc -std=gnu99" +#define __GMP_CFLAGS "-O2 -pedantic -fomit-frame-pointer -m64 -mtune=haswell -march=haswell" + +/* Major version number is the value of __GNU_MP__ too, above. */ +#define __GNU_MP_VERSION 6 +#define __GNU_MP_VERSION_MINOR 1 +#define __GNU_MP_VERSION_PATCHLEVEL 2 +#define __GNU_MP_RELEASE (__GNU_MP_VERSION * 10000 + __GNU_MP_VERSION_MINOR * 100 + __GNU_MP_VERSION_PATCHLEVEL) + +#define __GMP_H__ +#endif /* __GMP_H__ */ diff --git a/examples/multiprecision/bench-include/gmpxx.h b/examples/multiprecision/bench-include/gmpxx.h new file mode 100644 index 0000000000000000000000000000000000000000..58e87005442b2c8de5bc015ff18862c0da33796d --- /dev/null +++ b/examples/multiprecision/bench-include/gmpxx.h @@ -0,0 +1,3434 @@ +/* gmpxx.h -- C++ class wrapper for GMP types. -*- C++ -*- + +Copyright 2001-2003, 2006, 2008, 2011, 2012 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + +or + + * the GNU General Public License as published by the Free Software + Foundation; either version 2 of the License, or (at your option) any + later version. + +or both in parallel, as here. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received copies of the GNU General Public License and the +GNU Lesser General Public License along with the GNU MP Library. If not, +see https://www.gnu.org/licenses/. */ + +#ifndef __GMP_PLUSPLUS__ +#define __GMP_PLUSPLUS__ + +#include <iosfwd> + +#include <cstring> /* for strlen */ +#include <limits> /* numeric_limits */ +#include <utility> +#include <algorithm> /* swap */ +#include <string> +#include <stdexcept> +#include <cfloat> +#include <gmp.h> + +// wrapper for gcc's __builtin_constant_p +// __builtin_constant_p has been in gcc since forever, +// but g++-3.4 miscompiles it. +#if __GMP_GNUC_PREREQ(4, 2) +#define __GMPXX_CONSTANT(X) __builtin_constant_p(X) +#else +#define __GMPXX_CONSTANT(X) false +#endif +#define __GMPXX_CONSTANT_TRUE(X) (__GMPXX_CONSTANT(X) && (X)) + +// Use C++11 features +#ifndef __GMPXX_USE_CXX11 +#if __cplusplus >= 201103L +#define __GMPXX_USE_CXX11 1 +#else +#define __GMPXX_USE_CXX11 0 +#endif +#endif + +#if __GMPXX_USE_CXX11 +#define __GMPXX_NOEXCEPT noexcept +#include <type_traits> // for common_type +#else +#define __GMPXX_NOEXCEPT +#endif + +// Max allocations for plain types when converted to GMP types +#if GMP_NAIL_BITS != 0 && ! defined _LONG_LONG_LIMB +#define __GMPZ_ULI_LIMBS 2 +#else +#define __GMPZ_ULI_LIMBS 1 +#endif + +#define __GMPXX_BITS_TO_LIMBS(n) (((n) + (GMP_NUMB_BITS - 1)) / GMP_NUMB_BITS) +#define __GMPZ_DBL_LIMBS __GMPXX_BITS_TO_LIMBS(DBL_MAX_EXP)+1 +#define __GMPQ_NUM_DBL_LIMBS __GMPZ_DBL_LIMBS +#define __GMPQ_DEN_DBL_LIMBS __GMPXX_BITS_TO_LIMBS(DBL_MANT_DIG+1-DBL_MIN_EXP)+1 +// The final +1s are a security margin. The current implementation of +// mpq_set_d seems to need it for the denominator. + +inline void __mpz_set_ui_safe(mpz_ptr p, unsigned long l) +{ + p->_mp_size = (l != 0); + p->_mp_d[0] = l & GMP_NUMB_MASK; +#if __GMPZ_ULI_LIMBS > 1 + l >>= GMP_NUMB_BITS; + p->_mp_d[1] = l; + p->_mp_size += (l != 0); +#endif +} + +inline void __mpz_set_si_safe(mpz_ptr p, long l) +{ + if(l < 0) + { + __mpz_set_ui_safe(p, -static_cast<unsigned long>(l)); + mpz_neg(p, p); + } + else + __mpz_set_ui_safe(p, l); + // Note: we know the high bit of l is 0 so we could do slightly better +} + +// Fake temporary variables +#define __GMPXX_TMPZ_UI \ + mpz_t temp; \ + mp_limb_t limbs[__GMPZ_ULI_LIMBS]; \ + temp->_mp_d = limbs; \ + __mpz_set_ui_safe (temp, l) +#define __GMPXX_TMPZ_SI \ + mpz_t temp; \ + mp_limb_t limbs[__GMPZ_ULI_LIMBS]; \ + temp->_mp_d = limbs; \ + __mpz_set_si_safe (temp, l) +#define __GMPXX_TMPZ_D \ + mpz_t temp; \ + mp_limb_t limbs[__GMPZ_DBL_LIMBS]; \ + temp->_mp_d = limbs; \ + temp->_mp_alloc = __GMPZ_DBL_LIMBS; \ + mpz_set_d (temp, d) + +#define __GMPXX_TMPQ_UI \ + mpq_t temp; \ + mp_limb_t limbs[__GMPZ_ULI_LIMBS+1]; \ + mpq_numref(temp)->_mp_d = limbs; \ + __mpz_set_ui_safe (mpq_numref(temp), l); \ + mpq_denref(temp)->_mp_d = limbs + __GMPZ_ULI_LIMBS; \ + mpq_denref(temp)->_mp_size = 1; \ + mpq_denref(temp)->_mp_d[0] = 1 +#define __GMPXX_TMPQ_SI \ + mpq_t temp; \ + mp_limb_t limbs[__GMPZ_ULI_LIMBS+1]; \ + mpq_numref(temp)->_mp_d = limbs; \ + __mpz_set_si_safe (mpq_numref(temp), l); \ + mpq_denref(temp)->_mp_d = limbs + __GMPZ_ULI_LIMBS; \ + mpq_denref(temp)->_mp_size = 1; \ + mpq_denref(temp)->_mp_d[0] = 1 +#define __GMPXX_TMPQ_D \ + mpq_t temp; \ + mp_limb_t limbs[__GMPQ_NUM_DBL_LIMBS + __GMPQ_DEN_DBL_LIMBS]; \ + mpq_numref(temp)->_mp_d = limbs; \ + mpq_numref(temp)->_mp_alloc = __GMPQ_NUM_DBL_LIMBS; \ + mpq_denref(temp)->_mp_d = limbs + __GMPQ_NUM_DBL_LIMBS; \ + mpq_denref(temp)->_mp_alloc = __GMPQ_DEN_DBL_LIMBS; \ + mpq_set_d (temp, d) + +inline unsigned long __gmpxx_abs_ui (signed long l) +{ + return l >= 0 ? static_cast<unsigned long>(l) + : -static_cast<unsigned long>(l); +} + +/**************** Function objects ****************/ +/* Any evaluation of a __gmp_expr ends up calling one of these functions + all intermediate functions being inline, the evaluation should optimize + to a direct call to the relevant function, thus yielding no overhead + over the C interface. */ + +struct __gmp_unary_plus +{ + static void eval(mpz_ptr z, mpz_srcptr w) { mpz_set(z, w); } + static void eval(mpq_ptr q, mpq_srcptr r) { mpq_set(q, r); } + static void eval(mpf_ptr f, mpf_srcptr g) { mpf_set(f, g); } +}; + +struct __gmp_unary_minus +{ + static void eval(mpz_ptr z, mpz_srcptr w) { mpz_neg(z, w); } + static void eval(mpq_ptr q, mpq_srcptr r) { mpq_neg(q, r); } + static void eval(mpf_ptr f, mpf_srcptr g) { mpf_neg(f, g); } +}; + +struct __gmp_unary_com +{ + static void eval(mpz_ptr z, mpz_srcptr w) { mpz_com(z, w); } +}; + +struct __gmp_binary_plus +{ + static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) + { mpz_add(z, w, v); } + + static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) + { + // Ideally, those checks should happen earlier so that the tree + // generated for a+0+b would just be sum(a,b). + if (__GMPXX_CONSTANT(l) && l == 0) + { + if (z != w) mpz_set(z, w); + } + else + mpz_add_ui(z, w, l); + } + static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w) + { eval(z, w, l); } + static void eval(mpz_ptr z, mpz_srcptr w, signed long int l) + { + if (l >= 0) + eval(z, w, static_cast<unsigned long>(l)); + else + mpz_sub_ui(z, w, -static_cast<unsigned long>(l)); + } + static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) + { eval(z, w, l); } + static void eval(mpz_ptr z, mpz_srcptr w, double d) + { __GMPXX_TMPZ_D; mpz_add (z, w, temp); } + static void eval(mpz_ptr z, double d, mpz_srcptr w) + { eval(z, w, d); } + + static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s) + { mpq_add(q, r, s); } + + static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l) + { + if (__GMPXX_CONSTANT(l) && l == 0) + { + if (q != r) mpq_set(q, r); + } + else + { + if (q == r) + mpz_addmul_ui(mpq_numref(q), mpq_denref(q), l); + else + { + mpz_mul_ui(mpq_numref(q), mpq_denref(r), l); + mpz_add(mpq_numref(q), mpq_numref(q), mpq_numref(r)); + mpz_set(mpq_denref(q), mpq_denref(r)); + } + } + } + static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r) + { eval(q, r, l); } + static inline void eval(mpq_ptr q, mpq_srcptr r, signed long int l); + // defined after __gmp_binary_minus + static void eval(mpq_ptr q, signed long int l, mpq_srcptr r) + { eval(q, r, l); } + static void eval(mpq_ptr q, mpq_srcptr r, double d) + { __GMPXX_TMPQ_D; mpq_add (q, r, temp); } + static void eval(mpq_ptr q, double d, mpq_srcptr r) + { eval(q, r, d); } + + static void eval(mpq_ptr q, mpq_srcptr r, mpz_srcptr z) + { + if (q == r) + mpz_addmul(mpq_numref(q), mpq_denref(q), z); + else + { + mpz_mul(mpq_numref(q), mpq_denref(r), z); + mpz_add(mpq_numref(q), mpq_numref(q), mpq_numref(r)); + mpz_set(mpq_denref(q), mpq_denref(r)); + } + } + static void eval(mpq_ptr q, mpz_srcptr z, mpq_srcptr r) + { eval(q, r, z); } + + static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h) + { mpf_add(f, g, h); } + + static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l) + { mpf_add_ui(f, g, l); } + static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g) + { mpf_add_ui(f, g, l); } + static void eval(mpf_ptr f, mpf_srcptr g, signed long int l) + { + if (l >= 0) + mpf_add_ui(f, g, l); + else + mpf_sub_ui(f, g, -static_cast<unsigned long>(l)); + } + static void eval(mpf_ptr f, signed long int l, mpf_srcptr g) + { eval(f, g, l); } + static void eval(mpf_ptr f, mpf_srcptr g, double d) + { + mpf_t temp; + mpf_init2(temp, 8*sizeof(double)); + mpf_set_d(temp, d); + mpf_add(f, g, temp); + mpf_clear(temp); + } + static void eval(mpf_ptr f, double d, mpf_srcptr g) + { eval(f, g, d); } +}; + +struct __gmp_binary_minus +{ + static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) + { mpz_sub(z, w, v); } + + static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) + { + if (__GMPXX_CONSTANT(l) && l == 0) + { + if (z != w) mpz_set(z, w); + } + else + mpz_sub_ui(z, w, l); + } + static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w) + { + if (__GMPXX_CONSTANT(l) && l == 0) + { + mpz_neg(z, w); + } + else + mpz_ui_sub(z, l, w); + } + static void eval(mpz_ptr z, mpz_srcptr w, signed long int l) + { + if (l >= 0) + eval(z, w, static_cast<unsigned long>(l)); + else + mpz_add_ui(z, w, -static_cast<unsigned long>(l)); + } + static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) + { + if (l >= 0) + eval(z, static_cast<unsigned long>(l), w); + else + { + mpz_add_ui(z, w, -static_cast<unsigned long>(l)); + mpz_neg(z, z); + } + } + static void eval(mpz_ptr z, mpz_srcptr w, double d) + { __GMPXX_TMPZ_D; mpz_sub (z, w, temp); } + static void eval(mpz_ptr z, double d, mpz_srcptr w) + { __GMPXX_TMPZ_D; mpz_sub (z, temp, w); } + + static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s) + { mpq_sub(q, r, s); } + + static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l) + { + if (__GMPXX_CONSTANT(l) && l == 0) + { + if (q != r) mpq_set(q, r); + } + else + { + if (q == r) + mpz_submul_ui(mpq_numref(q), mpq_denref(q), l); + else + { + mpz_mul_ui(mpq_numref(q), mpq_denref(r), l); + mpz_sub(mpq_numref(q), mpq_numref(r), mpq_numref(q)); + mpz_set(mpq_denref(q), mpq_denref(r)); + } + } + } + static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r) + { eval(q, r, l); mpq_neg(q, q); } + static void eval(mpq_ptr q, mpq_srcptr r, signed long int l) + { + if (l >= 0) + eval(q, r, static_cast<unsigned long>(l)); + else + __gmp_binary_plus::eval(q, r, -static_cast<unsigned long>(l)); + } + static void eval(mpq_ptr q, signed long int l, mpq_srcptr r) + { eval(q, r, l); mpq_neg(q, q); } + static void eval(mpq_ptr q, mpq_srcptr r, double d) + { __GMPXX_TMPQ_D; mpq_sub (q, r, temp); } + static void eval(mpq_ptr q, double d, mpq_srcptr r) + { __GMPXX_TMPQ_D; mpq_sub (q, temp, r); } + + static void eval(mpq_ptr q, mpq_srcptr r, mpz_srcptr z) + { + if (q == r) + mpz_submul(mpq_numref(q), mpq_denref(q), z); + else + { + mpz_mul(mpq_numref(q), mpq_denref(r), z); + mpz_sub(mpq_numref(q), mpq_numref(r), mpq_numref(q)); + mpz_set(mpq_denref(q), mpq_denref(r)); + } + } + static void eval(mpq_ptr q, mpz_srcptr z, mpq_srcptr r) + { eval(q, r, z); mpq_neg(q, q); } + + static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h) + { mpf_sub(f, g, h); } + + static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l) + { mpf_sub_ui(f, g, l); } + static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g) + { mpf_ui_sub(f, l, g); } + static void eval(mpf_ptr f, mpf_srcptr g, signed long int l) + { + if (l >= 0) + mpf_sub_ui(f, g, l); + else + mpf_add_ui(f, g, -static_cast<unsigned long>(l)); + } + static void eval(mpf_ptr f, signed long int l, mpf_srcptr g) + { + if (l >= 0) + mpf_sub_ui(f, g, l); + else + mpf_add_ui(f, g, -static_cast<unsigned long>(l)); + mpf_neg(f, f); + } + static void eval(mpf_ptr f, mpf_srcptr g, double d) + { + mpf_t temp; + mpf_init2(temp, 8*sizeof(double)); + mpf_set_d(temp, d); + mpf_sub(f, g, temp); + mpf_clear(temp); + } + static void eval(mpf_ptr f, double d, mpf_srcptr g) + { + mpf_t temp; + mpf_init2(temp, 8*sizeof(double)); + mpf_set_d(temp, d); + mpf_sub(f, temp, g); + mpf_clear(temp); + } +}; + +// defined here so it can reference __gmp_binary_minus +inline void +__gmp_binary_plus::eval(mpq_ptr q, mpq_srcptr r, signed long int l) +{ + if (l >= 0) + eval(q, r, static_cast<unsigned long>(l)); + else + __gmp_binary_minus::eval(q, r, -static_cast<unsigned long>(l)); +} + +struct __gmp_binary_lshift +{ + static void eval(mpz_ptr z, mpz_srcptr w, mp_bitcnt_t l) + { + if (__GMPXX_CONSTANT(l) && (l == 0)) + { + if (z != w) mpz_set(z, w); + } + else + mpz_mul_2exp(z, w, l); + } + static void eval(mpq_ptr q, mpq_srcptr r, mp_bitcnt_t l) + { + if (__GMPXX_CONSTANT(l) && (l == 0)) + { + if (q != r) mpq_set(q, r); + } + else + mpq_mul_2exp(q, r, l); + } + static void eval(mpf_ptr f, mpf_srcptr g, mp_bitcnt_t l) + { mpf_mul_2exp(f, g, l); } +}; + +struct __gmp_binary_rshift +{ + static void eval(mpz_ptr z, mpz_srcptr w, mp_bitcnt_t l) + { + if (__GMPXX_CONSTANT(l) && (l == 0)) + { + if (z != w) mpz_set(z, w); + } + else + mpz_fdiv_q_2exp(z, w, l); + } + static void eval(mpq_ptr q, mpq_srcptr r, mp_bitcnt_t l) + { + if (__GMPXX_CONSTANT(l) && (l == 0)) + { + if (q != r) mpq_set(q, r); + } + else + mpq_div_2exp(q, r, l); + } + static void eval(mpf_ptr f, mpf_srcptr g, mp_bitcnt_t l) + { mpf_div_2exp(f, g, l); } +}; + +struct __gmp_binary_multiplies +{ + static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) + { mpz_mul(z, w, v); } + + static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) + { +// gcc-3.3 doesn't have __builtin_ctzl. Don't bother optimizing for old gcc. +#if __GMP_GNUC_PREREQ(3, 4) + if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0) + { + if (l == 0) + { + z->_mp_size = 0; + } + else + { + __gmp_binary_lshift::eval(z, w, __builtin_ctzl(l)); + } + } + else +#endif + mpz_mul_ui(z, w, l); + } + static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w) + { eval(z, w, l); } + static void eval(mpz_ptr z, mpz_srcptr w, signed long int l) + { + if (__GMPXX_CONSTANT_TRUE(l >= 0)) + eval(z, w, static_cast<unsigned long>(l)); + else if (__GMPXX_CONSTANT_TRUE(l <= 0)) + { + eval(z, w, -static_cast<unsigned long>(l)); + mpz_neg(z, z); + } + else + mpz_mul_si (z, w, l); + } + static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) + { eval(z, w, l); } + static void eval(mpz_ptr z, mpz_srcptr w, double d) + { __GMPXX_TMPZ_D; mpz_mul (z, w, temp); } + static void eval(mpz_ptr z, double d, mpz_srcptr w) + { eval(z, w, d); } + + static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s) + { mpq_mul(q, r, s); } + + static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l) + { +#if __GMP_GNUC_PREREQ(3, 4) + if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0) + { + if (l == 0) + { + mpq_set_ui(q, 0, 1); + } + else + { + __gmp_binary_lshift::eval(q, r, __builtin_ctzl(l)); + } + } + else +#endif + { + __GMPXX_TMPQ_UI; + mpq_mul (q, r, temp); + } + } + static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r) + { eval(q, r, l); } + static void eval(mpq_ptr q, mpq_srcptr r, signed long int l) + { + if (__GMPXX_CONSTANT_TRUE(l >= 0)) + eval(q, r, static_cast<unsigned long>(l)); + else if (__GMPXX_CONSTANT_TRUE(l <= 0)) + { + eval(q, r, -static_cast<unsigned long>(l)); + mpq_neg(q, q); + } + else + { + __GMPXX_TMPQ_SI; + mpq_mul (q, r, temp); + } + } + static void eval(mpq_ptr q, signed long int l, mpq_srcptr r) + { eval(q, r, l); } + static void eval(mpq_ptr q, mpq_srcptr r, double d) + { __GMPXX_TMPQ_D; mpq_mul (q, r, temp); } + static void eval(mpq_ptr q, double d, mpq_srcptr r) + { eval(q, r, d); } + + static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h) + { mpf_mul(f, g, h); } + + static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l) + { mpf_mul_ui(f, g, l); } + static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g) + { mpf_mul_ui(f, g, l); } + static void eval(mpf_ptr f, mpf_srcptr g, signed long int l) + { + if (l >= 0) + mpf_mul_ui(f, g, l); + else + { + mpf_mul_ui(f, g, -static_cast<unsigned long>(l)); + mpf_neg(f, f); + } + } + static void eval(mpf_ptr f, signed long int l, mpf_srcptr g) + { eval(f, g, l); } + static void eval(mpf_ptr f, mpf_srcptr g, double d) + { + mpf_t temp; + mpf_init2(temp, 8*sizeof(double)); + mpf_set_d(temp, d); + mpf_mul(f, g, temp); + mpf_clear(temp); + } + static void eval(mpf_ptr f, double d, mpf_srcptr g) + { eval(f, g, d); } +}; + +struct __gmp_binary_divides +{ + static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) + { mpz_tdiv_q(z, w, v); } + + static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) + { +#if __GMP_GNUC_PREREQ(3, 4) + // Don't optimize division by 0... + if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0 && l != 0) + { + if (l == 1) + { + if (z != w) mpz_set(z, w); + } + else + mpz_tdiv_q_2exp(z, w, __builtin_ctzl(l)); + // warning: do not use rshift (fdiv) + } + else +#endif + mpz_tdiv_q_ui(z, w, l); + } + static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w) + { + if (mpz_sgn(w) >= 0) + { + if (mpz_fits_ulong_p(w)) + mpz_set_ui(z, l / mpz_get_ui(w)); + else + mpz_set_ui(z, 0); + } + else + { + mpz_neg(z, w); + if (mpz_fits_ulong_p(z)) + { + mpz_set_ui(z, l / mpz_get_ui(z)); + mpz_neg(z, z); + } + else + mpz_set_ui(z, 0); + } + } + static void eval(mpz_ptr z, mpz_srcptr w, signed long int l) + { + if (l >= 0) + eval(z, w, static_cast<unsigned long>(l)); + else + { + eval(z, w, -static_cast<unsigned long>(l)); + mpz_neg(z, z); + } + } + static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) + { + if (mpz_fits_slong_p(w)) + mpz_set_si(z, l / mpz_get_si(w)); + else + { + /* if w is bigger than a long then the quotient must be zero, unless + l==LONG_MIN and w==-LONG_MIN in which case the quotient is -1 */ + mpz_set_si (z, (mpz_cmpabs_ui (w, __gmpxx_abs_ui(l)) == 0 ? -1 : 0)); + } + } + static void eval(mpz_ptr z, mpz_srcptr w, double d) + { __GMPXX_TMPZ_D; mpz_tdiv_q (z, w, temp); } + static void eval(mpz_ptr z, double d, mpz_srcptr w) + { __GMPXX_TMPZ_D; mpz_tdiv_q (z, temp, w); } + + static void eval(mpq_ptr q, mpq_srcptr r, mpq_srcptr s) + { mpq_div(q, r, s); } + + static void eval(mpq_ptr q, mpq_srcptr r, unsigned long int l) + { +#if __GMP_GNUC_PREREQ(3, 4) + if (__GMPXX_CONSTANT(l) && (l & (l-1)) == 0 && l != 0) + __gmp_binary_rshift::eval(q, r, __builtin_ctzl(l)); + else +#endif + { + __GMPXX_TMPQ_UI; + mpq_div (q, r, temp); + } + } + static void eval(mpq_ptr q, unsigned long int l, mpq_srcptr r) + { __GMPXX_TMPQ_UI; mpq_div (q, temp, r); } + static void eval(mpq_ptr q, mpq_srcptr r, signed long int l) + { + if (__GMPXX_CONSTANT_TRUE(l >= 0)) + eval(q, r, static_cast<unsigned long>(l)); + else if (__GMPXX_CONSTANT_TRUE(l <= 0)) + { + eval(q, r, -static_cast<unsigned long>(l)); + mpq_neg(q, q); + } + else + { + __GMPXX_TMPQ_SI; + mpq_div (q, r, temp); + } + } + static void eval(mpq_ptr q, signed long int l, mpq_srcptr r) + { __GMPXX_TMPQ_SI; mpq_div (q, temp, r); } + static void eval(mpq_ptr q, mpq_srcptr r, double d) + { __GMPXX_TMPQ_D; mpq_div (q, r, temp); } + static void eval(mpq_ptr q, double d, mpq_srcptr r) + { __GMPXX_TMPQ_D; mpq_div (q, temp, r); } + + static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h) + { mpf_div(f, g, h); } + + static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l) + { mpf_div_ui(f, g, l); } + static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g) + { mpf_ui_div(f, l, g); } + static void eval(mpf_ptr f, mpf_srcptr g, signed long int l) + { + if (l >= 0) + mpf_div_ui(f, g, l); + else + { + mpf_div_ui(f, g, -static_cast<unsigned long>(l)); + mpf_neg(f, f); + } + } + static void eval(mpf_ptr f, signed long int l, mpf_srcptr g) + { + if (l >= 0) + mpf_ui_div(f, l, g); + else + { + mpf_ui_div(f, -static_cast<unsigned long>(l), g); + mpf_neg(f, f); + } + } + static void eval(mpf_ptr f, mpf_srcptr g, double d) + { + mpf_t temp; + mpf_init2(temp, 8*sizeof(double)); + mpf_set_d(temp, d); + mpf_div(f, g, temp); + mpf_clear(temp); + } + static void eval(mpf_ptr f, double d, mpf_srcptr g) + { + mpf_t temp; + mpf_init2(temp, 8*sizeof(double)); + mpf_set_d(temp, d); + mpf_div(f, temp, g); + mpf_clear(temp); + } +}; + +struct __gmp_binary_modulus +{ + static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) + { mpz_tdiv_r(z, w, v); } + + static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) + { mpz_tdiv_r_ui(z, w, l); } + static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w) + { + if (mpz_sgn(w) >= 0) + { + if (mpz_fits_ulong_p(w)) + mpz_set_ui(z, l % mpz_get_ui(w)); + else + mpz_set_ui(z, l); + } + else + { + mpz_neg(z, w); + if (mpz_fits_ulong_p(z)) + mpz_set_ui(z, l % mpz_get_ui(z)); + else + mpz_set_ui(z, l); + } + } + static void eval(mpz_ptr z, mpz_srcptr w, signed long int l) + { + mpz_tdiv_r_ui (z, w, __gmpxx_abs_ui(l)); + } + static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) + { + if (mpz_fits_slong_p(w)) + mpz_set_si(z, l % mpz_get_si(w)); + else + { + /* if w is bigger than a long then the remainder is l unchanged, + unless l==LONG_MIN and w==-LONG_MIN in which case it's 0 */ + mpz_set_si (z, mpz_cmpabs_ui (w, __gmpxx_abs_ui(l)) == 0 ? 0 : l); + } + } + static void eval(mpz_ptr z, mpz_srcptr w, double d) + { __GMPXX_TMPZ_D; mpz_tdiv_r (z, w, temp); } + static void eval(mpz_ptr z, double d, mpz_srcptr w) + { __GMPXX_TMPZ_D; mpz_tdiv_r (z, temp, w); } +}; + +struct __gmp_binary_and +{ + static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) + { mpz_and(z, w, v); } + + static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) + { __GMPXX_TMPZ_UI; mpz_and (z, w, temp); } + static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w) + { eval(z, w, l); } + static void eval(mpz_ptr z, mpz_srcptr w, signed long int l) + { __GMPXX_TMPZ_SI; mpz_and (z, w, temp); } + static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) + { eval(z, w, l); } + static void eval(mpz_ptr z, mpz_srcptr w, double d) + { __GMPXX_TMPZ_D; mpz_and (z, w, temp); } + static void eval(mpz_ptr z, double d, mpz_srcptr w) + { eval(z, w, d); } +}; + +struct __gmp_binary_ior +{ + static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) + { mpz_ior(z, w, v); } + static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) + { __GMPXX_TMPZ_UI; mpz_ior (z, w, temp); } + static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w) + { eval(z, w, l); } + static void eval(mpz_ptr z, mpz_srcptr w, signed long int l) + { __GMPXX_TMPZ_SI; mpz_ior (z, w, temp); } + static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) + { eval(z, w, l); } + static void eval(mpz_ptr z, mpz_srcptr w, double d) + { __GMPXX_TMPZ_D; mpz_ior (z, w, temp); } + static void eval(mpz_ptr z, double d, mpz_srcptr w) + { eval(z, w, d); } +}; + +struct __gmp_binary_xor +{ + static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) + { mpz_xor(z, w, v); } + static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) + { __GMPXX_TMPZ_UI; mpz_xor (z, w, temp); } + static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w) + { eval(z, w, l); } + static void eval(mpz_ptr z, mpz_srcptr w, signed long int l) + { __GMPXX_TMPZ_SI; mpz_xor (z, w, temp); } + static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) + { eval(z, w, l); } + static void eval(mpz_ptr z, mpz_srcptr w, double d) + { __GMPXX_TMPZ_D; mpz_xor (z, w, temp); } + static void eval(mpz_ptr z, double d, mpz_srcptr w) + { eval(z, w, d); } +}; + +struct __gmp_cmp_function +{ + static int eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w); } + + static int eval(mpz_srcptr z, unsigned long int l) + { return mpz_cmp_ui(z, l); } + static int eval(unsigned long int l, mpz_srcptr z) + { return -mpz_cmp_ui(z, l); } + static int eval(mpz_srcptr z, signed long int l) + { return mpz_cmp_si(z, l); } + static int eval(signed long int l, mpz_srcptr z) + { return -mpz_cmp_si(z, l); } + static int eval(mpz_srcptr z, double d) + { return mpz_cmp_d(z, d); } + static int eval(double d, mpz_srcptr z) + { return -mpz_cmp_d(z, d); } + + static int eval(mpq_srcptr q, mpq_srcptr r) { return mpq_cmp(q, r); } + + static int eval(mpq_srcptr q, unsigned long int l) + { return mpq_cmp_ui(q, l, 1); } + static int eval(unsigned long int l, mpq_srcptr q) + { return -mpq_cmp_ui(q, l, 1); } + static int eval(mpq_srcptr q, signed long int l) + { return mpq_cmp_si(q, l, 1); } + static int eval(signed long int l, mpq_srcptr q) + { return -mpq_cmp_si(q, l, 1); } + static int eval(mpq_srcptr q, double d) + { __GMPXX_TMPQ_D; return mpq_cmp (q, temp); } + static int eval(double d, mpq_srcptr q) + { __GMPXX_TMPQ_D; return mpq_cmp (temp, q); } + static int eval(mpq_srcptr q, mpz_srcptr z) + { return mpq_cmp_z(q, z); } + static int eval(mpz_srcptr z, mpq_srcptr q) + { return -mpq_cmp_z(q, z); } + + static int eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g); } + + static int eval(mpf_srcptr f, unsigned long int l) + { return mpf_cmp_ui(f, l); } + static int eval(unsigned long int l, mpf_srcptr f) + { return -mpf_cmp_ui(f, l); } + static int eval(mpf_srcptr f, signed long int l) + { return mpf_cmp_si(f, l); } + static int eval(signed long int l, mpf_srcptr f) + { return -mpf_cmp_si(f, l); } + static int eval(mpf_srcptr f, double d) + { return mpf_cmp_d(f, d); } + static int eval(double d, mpf_srcptr f) + { return -mpf_cmp_d(f, d); } + static int eval(mpf_srcptr f, mpz_srcptr z) + { return mpf_cmp_z(f, z); } + static int eval(mpz_srcptr z, mpf_srcptr f) + { return -mpf_cmp_z(f, z); } + static int eval(mpf_srcptr f, mpq_srcptr q) + { + mpf_t qf; + mpf_init(qf); /* Should we use the precision of f? */ + mpf_set_q(qf, q); + int ret = eval(f, qf); + mpf_clear(qf); + return ret; + } + static int eval(mpq_srcptr q, mpf_srcptr f) + { return -eval(f, q); } +}; + +struct __gmp_binary_equal +{ + static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) == 0; } + + static bool eval(mpz_srcptr z, unsigned long int l) + { return mpz_cmp_ui(z, l) == 0; } + static bool eval(unsigned long int l, mpz_srcptr z) + { return eval(z, l); } + static bool eval(mpz_srcptr z, signed long int l) + { return mpz_cmp_si(z, l) == 0; } + static bool eval(signed long int l, mpz_srcptr z) + { return eval(z, l); } + static bool eval(mpz_srcptr z, double d) + { return mpz_cmp_d(z, d) == 0; } + static bool eval(double d, mpz_srcptr z) + { return eval(z, d); } + + static bool eval(mpq_srcptr q, mpq_srcptr r) + { return mpq_equal(q, r) != 0; } + + static bool eval(mpq_srcptr q, unsigned long int l) + { return mpq_cmp_ui(q, l, 1) == 0; } + static bool eval(unsigned long int l, mpq_srcptr q) + { return eval(q, l); } + static bool eval(mpq_srcptr q, signed long int l) + { return mpq_cmp_si(q, l, 1) == 0; } + static bool eval(signed long int l, mpq_srcptr q) + { return eval(q, l); } + static bool eval(mpq_srcptr q, double d) + { __GMPXX_TMPQ_D; return mpq_equal (q, temp) != 0; } + static bool eval(double d, mpq_srcptr q) + { return eval(q, d); } + static bool eval(mpq_srcptr q, mpz_srcptr z) + { return mpq_cmp_z(q, z) == 0; } + static bool eval(mpz_srcptr z, mpq_srcptr q) + { return eval(q, z); } + + static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) == 0; } + + static bool eval(mpf_srcptr f, unsigned long int l) + { return mpf_cmp_ui(f, l) == 0; } + static bool eval(unsigned long int l, mpf_srcptr f) + { return eval(f, l); } + static bool eval(mpf_srcptr f, signed long int l) + { return mpf_cmp_si(f, l) == 0; } + static bool eval(signed long int l, mpf_srcptr f) + { return eval(f, l); } + static bool eval(mpf_srcptr f, double d) + { return mpf_cmp_d(f, d) == 0; } + static bool eval(double d, mpf_srcptr f) + { return eval(f, d); } + static bool eval(mpf_srcptr f, mpz_srcptr z) + { return mpf_cmp_z(f, z) == 0; } + static bool eval(mpz_srcptr z, mpf_srcptr f) + { return eval(f, z); } + static bool eval(mpf_srcptr f, mpq_srcptr q) + { return __gmp_cmp_function::eval(f, q) == 0; } + static bool eval(mpq_srcptr q, mpf_srcptr f) + { return eval(f, q); } +}; + +struct __gmp_binary_less +{ + static bool eval(mpz_srcptr z, mpz_srcptr w) { return mpz_cmp(z, w) < 0; } + + static bool eval(mpz_srcptr z, unsigned long int l) + { return mpz_cmp_ui(z, l) < 0; } + static bool eval(unsigned long int l, mpz_srcptr z) + { return mpz_cmp_ui(z, l) > 0; } + static bool eval(mpz_srcptr z, signed long int l) + { return mpz_cmp_si(z, l) < 0; } + static bool eval(signed long int l, mpz_srcptr z) + { return mpz_cmp_si(z, l) > 0; } + static bool eval(mpz_srcptr z, double d) + { return mpz_cmp_d(z, d) < 0; } + static bool eval(double d, mpz_srcptr z) + { return mpz_cmp_d(z, d) > 0; } + + static bool eval(mpq_srcptr q, mpq_srcptr r) { return mpq_cmp(q, r) < 0; } + + static bool eval(mpq_srcptr q, unsigned long int l) + { return mpq_cmp_ui(q, l, 1) < 0; } + static bool eval(unsigned long int l, mpq_srcptr q) + { return mpq_cmp_ui(q, l, 1) > 0; } + static bool eval(mpq_srcptr q, signed long int l) + { return mpq_cmp_si(q, l, 1) < 0; } + static bool eval(signed long int l, mpq_srcptr q) + { return mpq_cmp_si(q, l, 1) > 0; } + static bool eval(mpq_srcptr q, double d) + { __GMPXX_TMPQ_D; return mpq_cmp (q, temp) < 0; } + static bool eval(double d, mpq_srcptr q) + { __GMPXX_TMPQ_D; return mpq_cmp (temp, q) < 0; } + static bool eval(mpq_srcptr q, mpz_srcptr z) + { return mpq_cmp_z(q, z) < 0; } + static bool eval(mpz_srcptr z, mpq_srcptr q) + { return mpq_cmp_z(q, z) > 0; } + + static bool eval(mpf_srcptr f, mpf_srcptr g) { return mpf_cmp(f, g) < 0; } + + static bool eval(mpf_srcptr f, unsigned long int l) + { return mpf_cmp_ui(f, l) < 0; } + static bool eval(unsigned long int l, mpf_srcptr f) + { return mpf_cmp_ui(f, l) > 0; } + static bool eval(mpf_srcptr f, signed long int l) + { return mpf_cmp_si(f, l) < 0; } + static bool eval(signed long int l, mpf_srcptr f) + { return mpf_cmp_si(f, l) > 0; } + static bool eval(mpf_srcptr f, double d) + { return mpf_cmp_d(f, d) < 0; } + static bool eval(double d, mpf_srcptr f) + { return mpf_cmp_d(f, d) > 0; } + static bool eval(mpf_srcptr f, mpz_srcptr z) + { return mpf_cmp_z(f, z) < 0; } + static bool eval(mpz_srcptr z, mpf_srcptr f) + { return mpf_cmp_z(f, z) > 0; } + static bool eval(mpf_srcptr f, mpq_srcptr q) + { return __gmp_cmp_function::eval(f, q) < 0; } + static bool eval(mpq_srcptr q, mpf_srcptr f) + { return __gmp_cmp_function::eval(q, f) < 0; } +}; + +struct __gmp_binary_greater +{ + template <class T, class U> + static inline bool eval(T t, U u) { return __gmp_binary_less::eval(u, t); } +}; + +struct __gmp_unary_increment +{ + static void eval(mpz_ptr z) { mpz_add_ui(z, z, 1); } + static void eval(mpq_ptr q) + { mpz_add(mpq_numref(q), mpq_numref(q), mpq_denref(q)); } + static void eval(mpf_ptr f) { mpf_add_ui(f, f, 1); } +}; + +struct __gmp_unary_decrement +{ + static void eval(mpz_ptr z) { mpz_sub_ui(z, z, 1); } + static void eval(mpq_ptr q) + { mpz_sub(mpq_numref(q), mpq_numref(q), mpq_denref(q)); } + static void eval(mpf_ptr f) { mpf_sub_ui(f, f, 1); } +}; + +struct __gmp_abs_function +{ + static void eval(mpz_ptr z, mpz_srcptr w) { mpz_abs(z, w); } + static void eval(mpq_ptr q, mpq_srcptr r) { mpq_abs(q, r); } + static void eval(mpf_ptr f, mpf_srcptr g) { mpf_abs(f, g); } +}; + +struct __gmp_trunc_function +{ + static void eval(mpf_ptr f, mpf_srcptr g) { mpf_trunc(f, g); } +}; + +struct __gmp_floor_function +{ + static void eval(mpf_ptr f, mpf_srcptr g) { mpf_floor(f, g); } +}; + +struct __gmp_ceil_function +{ + static void eval(mpf_ptr f, mpf_srcptr g) { mpf_ceil(f, g); } +}; + +struct __gmp_sqrt_function +{ + static void eval(mpz_ptr z, mpz_srcptr w) { mpz_sqrt(z, w); } + static void eval(mpf_ptr f, mpf_srcptr g) { mpf_sqrt(f, g); } +}; + +struct __gmp_hypot_function +{ + static void eval(mpf_ptr f, mpf_srcptr g, mpf_srcptr h) + { + mpf_t temp; + mpf_init2(temp, mpf_get_prec(f)); + mpf_mul(temp, g, g); + mpf_mul(f, h, h); + mpf_add(f, f, temp); + mpf_sqrt(f, f); + mpf_clear(temp); + } + + static void eval(mpf_ptr f, mpf_srcptr g, unsigned long int l) + { + mpf_t temp; + mpf_init2(temp, mpf_get_prec(f)); + mpf_mul(temp, g, g); + mpf_set_ui(f, l); + mpf_mul_ui(f, f, l); + mpf_add(f, f, temp); + mpf_clear(temp); + mpf_sqrt(f, f); + } + static void eval(mpf_ptr f, unsigned long int l, mpf_srcptr g) + { eval(f, g, l); } + static void eval(mpf_ptr f, mpf_srcptr g, signed long int l) + { eval(f, g, __gmpxx_abs_ui(l)); } + static void eval(mpf_ptr f, signed long int l, mpf_srcptr g) + { eval(f, g, l); } + static void eval(mpf_ptr f, mpf_srcptr g, double d) + { + mpf_t temp; + mpf_init2(temp, mpf_get_prec(f)); + mpf_mul(temp, g, g); + mpf_set_d(f, d); + mpf_mul(f, f, f); + mpf_add(f, f, temp); + mpf_sqrt(f, f); + mpf_clear(temp); + } + static void eval(mpf_ptr f, double d, mpf_srcptr g) + { eval(f, g, d); } +}; + +struct __gmp_sgn_function +{ + static int eval(mpz_srcptr z) { return mpz_sgn(z); } + static int eval(mpq_srcptr q) { return mpq_sgn(q); } + static int eval(mpf_srcptr f) { return mpf_sgn(f); } +}; + +struct __gmp_gcd_function +{ + static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) + { mpz_gcd(z, w, v); } + static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) + { mpz_gcd_ui(z, w, l); } + static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w) + { eval(z, w, l); } + static void eval(mpz_ptr z, mpz_srcptr w, signed long int l) + { eval(z, w, __gmpxx_abs_ui(l)); } + static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) + { eval(z, w, l); } + static void eval(mpz_ptr z, mpz_srcptr w, double d) + { __GMPXX_TMPZ_D; mpz_gcd (z, w, temp); } + static void eval(mpz_ptr z, double d, mpz_srcptr w) + { eval(z, w, d); } +}; + +struct __gmp_lcm_function +{ + static void eval(mpz_ptr z, mpz_srcptr w, mpz_srcptr v) + { mpz_lcm(z, w, v); } + static void eval(mpz_ptr z, mpz_srcptr w, unsigned long int l) + { mpz_lcm_ui(z, w, l); } + static void eval(mpz_ptr z, unsigned long int l, mpz_srcptr w) + { eval(z, w, l); } + static void eval(mpz_ptr z, mpz_srcptr w, signed long int l) + { eval(z, w, __gmpxx_abs_ui(l)); } + static void eval(mpz_ptr z, signed long int l, mpz_srcptr w) + { eval(z, w, l); } + static void eval(mpz_ptr z, mpz_srcptr w, double d) + { __GMPXX_TMPZ_D; mpz_lcm (z, w, temp); } + static void eval(mpz_ptr z, double d, mpz_srcptr w) + { eval(z, w, d); } +}; + +struct __gmp_rand_function +{ + static void eval(mpz_ptr z, gmp_randstate_t s, mp_bitcnt_t l) + { mpz_urandomb(z, s, l); } + static void eval(mpz_ptr z, gmp_randstate_t s, mpz_srcptr w) + { mpz_urandomm(z, s, w); } + static void eval(mpf_ptr f, gmp_randstate_t s, mp_bitcnt_t prec) + { mpf_urandomb(f, s, prec); } +}; + + +/**************** Auxiliary classes ****************/ + +/* this is much the same as gmp_allocated_string in gmp-impl.h + since gmp-impl.h is not publicly available, I redefine it here + I use a different name to avoid possible clashes */ + +extern "C" { + typedef void (*__gmp_freefunc_t) (void *, size_t); +} +struct __gmp_alloc_cstring +{ + char *str; + __gmp_alloc_cstring(char *s) { str = s; } + ~__gmp_alloc_cstring() + { + __gmp_freefunc_t freefunc; + mp_get_memory_functions (NULL, NULL, &freefunc); + (*freefunc) (str, std::strlen(str)+1); + } +}; + + +// general expression template class +template <class T, class U> +class __gmp_expr; + + +// templates for resolving expression types +template <class T> +struct __gmp_resolve_ref +{ + typedef T ref_type; +}; + +template <class T, class U> +struct __gmp_resolve_ref<__gmp_expr<T, U> > +{ + typedef const __gmp_expr<T, U> & ref_type; +}; + + +template <class T, class U = T> +struct __gmp_resolve_expr; + +template <> +struct __gmp_resolve_expr<mpz_t> +{ + typedef mpz_t value_type; + typedef mpz_ptr ptr_type; + typedef mpz_srcptr srcptr_type; +}; + +template <> +struct __gmp_resolve_expr<mpq_t> +{ + typedef mpq_t value_type; + typedef mpq_ptr ptr_type; + typedef mpq_srcptr srcptr_type; +}; + +template <> +struct __gmp_resolve_expr<mpf_t> +{ + typedef mpf_t value_type; + typedef mpf_ptr ptr_type; + typedef mpf_srcptr srcptr_type; +}; + +template <> +struct __gmp_resolve_expr<mpz_t, mpq_t> +{ + typedef mpq_t value_type; +}; + +template <> +struct __gmp_resolve_expr<mpq_t, mpz_t> +{ + typedef mpq_t value_type; +}; + +template <> +struct __gmp_resolve_expr<mpz_t, mpf_t> +{ + typedef mpf_t value_type; +}; + +template <> +struct __gmp_resolve_expr<mpf_t, mpz_t> +{ + typedef mpf_t value_type; +}; + +template <> +struct __gmp_resolve_expr<mpq_t, mpf_t> +{ + typedef mpf_t value_type; +}; + +template <> +struct __gmp_resolve_expr<mpf_t, mpq_t> +{ + typedef mpf_t value_type; +}; + +#if __GMPXX_USE_CXX11 +namespace std { + template <class T, class U, class V, class W> + struct common_type <__gmp_expr<T, U>, __gmp_expr<V, W> > + { + private: + typedef typename __gmp_resolve_expr<T, V>::value_type X; + public: + typedef __gmp_expr<X, X> type; + }; + + template <class T, class U> + struct common_type <__gmp_expr<T, U> > + { + typedef __gmp_expr<T, T> type; + }; + +#define __GMPXX_DECLARE_COMMON_TYPE(typ) \ + template <class T, class U> \ + struct common_type <__gmp_expr<T, U>, typ > \ + { \ + typedef __gmp_expr<T, T> type; \ + }; \ + \ + template <class T, class U> \ + struct common_type <typ, __gmp_expr<T, U> > \ + { \ + typedef __gmp_expr<T, T> type; \ + } + + __GMPXX_DECLARE_COMMON_TYPE(signed char); + __GMPXX_DECLARE_COMMON_TYPE(unsigned char); + __GMPXX_DECLARE_COMMON_TYPE(signed int); + __GMPXX_DECLARE_COMMON_TYPE(unsigned int); + __GMPXX_DECLARE_COMMON_TYPE(signed short int); + __GMPXX_DECLARE_COMMON_TYPE(unsigned short int); + __GMPXX_DECLARE_COMMON_TYPE(signed long int); + __GMPXX_DECLARE_COMMON_TYPE(unsigned long int); + __GMPXX_DECLARE_COMMON_TYPE(float); + __GMPXX_DECLARE_COMMON_TYPE(double); +#undef __GMPXX_DECLARE_COMMON_TYPE +} +#endif + +// classes for evaluating unary and binary expressions +template <class T, class Op> +struct __gmp_unary_expr +{ + typename __gmp_resolve_ref<T>::ref_type val; + + __gmp_unary_expr(const T &v) : val(v) { } +private: + __gmp_unary_expr(); +}; + +template <class T, class U, class Op> +struct __gmp_binary_expr +{ + typename __gmp_resolve_ref<T>::ref_type val1; + typename __gmp_resolve_ref<U>::ref_type val2; + + __gmp_binary_expr(const T &v1, const U &v2) : val1(v1), val2(v2) { } +private: + __gmp_binary_expr(); +}; + + + +/**************** Macros for in-class declarations ****************/ +/* This is just repetitive code that is easier to maintain if it's written + only once */ + +#define __GMPP_DECLARE_COMPOUND_OPERATOR(fun) \ + template <class T, class U> \ + __gmp_expr<value_type, value_type> & fun(const __gmp_expr<T, U> &); + +#define __GMPN_DECLARE_COMPOUND_OPERATOR(fun) \ + __gmp_expr & fun(signed char); \ + __gmp_expr & fun(unsigned char); \ + __gmp_expr & fun(signed int); \ + __gmp_expr & fun(unsigned int); \ + __gmp_expr & fun(signed short int); \ + __gmp_expr & fun(unsigned short int); \ + __gmp_expr & fun(signed long int); \ + __gmp_expr & fun(unsigned long int); \ + __gmp_expr & fun(float); \ + __gmp_expr & fun(double); \ + /* __gmp_expr & fun(long double); */ + +#define __GMP_DECLARE_COMPOUND_OPERATOR(fun) \ +__GMPP_DECLARE_COMPOUND_OPERATOR(fun) \ +__GMPN_DECLARE_COMPOUND_OPERATOR(fun) + +#define __GMP_DECLARE_COMPOUND_OPERATOR_UI(fun) \ + __gmp_expr & fun(mp_bitcnt_t); + +#define __GMP_DECLARE_INCREMENT_OPERATOR(fun) \ + inline __gmp_expr & fun(); \ + inline __gmp_expr fun(int); + +#define __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS \ + __gmp_expr(signed char c) { init_si(c); } \ + __gmp_expr(unsigned char c) { init_ui(c); } \ + __gmp_expr(signed int i) { init_si(i); } \ + __gmp_expr(unsigned int i) { init_ui(i); } \ + __gmp_expr(signed short int s) { init_si(s); } \ + __gmp_expr(unsigned short int s) { init_ui(s); } \ + __gmp_expr(signed long int l) { init_si(l); } \ + __gmp_expr(unsigned long int l) { init_ui(l); } \ + __gmp_expr(float f) { init_d(f); } \ + __gmp_expr(double d) { init_d(d); } + +#define __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS \ + __gmp_expr & operator=(signed char c) { assign_si(c); return *this; } \ + __gmp_expr & operator=(unsigned char c) { assign_ui(c); return *this; } \ + __gmp_expr & operator=(signed int i) { assign_si(i); return *this; } \ + __gmp_expr & operator=(unsigned int i) { assign_ui(i); return *this; } \ + __gmp_expr & operator=(signed short int s) { assign_si(s); return *this; } \ + __gmp_expr & operator=(unsigned short int s) { assign_ui(s); return *this; } \ + __gmp_expr & operator=(signed long int l) { assign_si(l); return *this; } \ + __gmp_expr & operator=(unsigned long int l) { assign_ui(l); return *this; } \ + __gmp_expr & operator=(float f) { assign_d(f); return *this; } \ + __gmp_expr & operator=(double d) { assign_d(d); return *this; } + +/**************** mpz_class -- wrapper for mpz_t ****************/ + +template <> +class __gmp_expr<mpz_t, mpz_t> +{ +private: + typedef mpz_t value_type; + value_type mp; + + // Helper functions used for all arithmetic types + void assign_ui(unsigned long l) + { + if (__GMPXX_CONSTANT_TRUE(l == 0)) + mp->_mp_size = 0; + else + mpz_set_ui(mp, l); + } + void assign_si(signed long l) + { + if (__GMPXX_CONSTANT_TRUE(l >= 0)) + assign_ui(l); + else if (__GMPXX_CONSTANT_TRUE(l <= 0)) + { + assign_ui(-static_cast<unsigned long>(l)); + mpz_neg(mp, mp); + } + else + mpz_set_si(mp, l); + } + void assign_d (double d) + { + mpz_set_d (mp, d); + } + + void init_ui(unsigned long l) + { + if (__GMPXX_CONSTANT_TRUE(l == 0)) + mpz_init(mp); + else + mpz_init_set_ui(mp, l); + } + void init_si(signed long l) + { + if (__GMPXX_CONSTANT_TRUE(l >= 0)) + init_ui(l); + else if (__GMPXX_CONSTANT_TRUE(l <= 0)) + { + init_ui(-static_cast<unsigned long>(l)); + mpz_neg(mp, mp); + } + else + mpz_init_set_si(mp, l); + } + void init_d (double d) + { + mpz_init_set_d (mp, d); + } + +public: + mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } + + // constructors and destructor + __gmp_expr() { mpz_init(mp); } + + __gmp_expr(const __gmp_expr &z) { mpz_init_set(mp, z.mp); } +#if __GMPXX_USE_CXX11 + __gmp_expr(__gmp_expr &&z) + { *mp = *z.mp; mpz_init(z.mp); } +#endif + template <class T> + __gmp_expr(const __gmp_expr<mpz_t, T> &expr) + { mpz_init(mp); __gmp_set_expr(mp, expr); } + template <class T, class U> + explicit __gmp_expr(const __gmp_expr<T, U> &expr) + { mpz_init(mp); __gmp_set_expr(mp, expr); } + + __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS + + explicit __gmp_expr(const char *s, int base = 0) + { + if (mpz_init_set_str (mp, s, base) != 0) + { + mpz_clear (mp); + throw std::invalid_argument ("mpz_set_str"); + } + } + explicit __gmp_expr(const std::string &s, int base = 0) + { + if (mpz_init_set_str(mp, s.c_str(), base) != 0) + { + mpz_clear (mp); + throw std::invalid_argument ("mpz_set_str"); + } + } + + explicit __gmp_expr(mpz_srcptr z) { mpz_init_set(mp, z); } + + ~__gmp_expr() { mpz_clear(mp); } + + void swap(__gmp_expr& z) __GMPXX_NOEXCEPT { std::swap(*mp, *z.mp); } + + // assignment operators + __gmp_expr & operator=(const __gmp_expr &z) + { mpz_set(mp, z.mp); return *this; } +#if __GMPXX_USE_CXX11 + __gmp_expr & operator=(__gmp_expr &&z) noexcept + { swap(z); return *this; } +#endif + template <class T, class U> + __gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr) + { __gmp_set_expr(mp, expr); return *this; } + + __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS + + __gmp_expr & operator=(const char *s) + { + if (mpz_set_str (mp, s, 0) != 0) + throw std::invalid_argument ("mpz_set_str"); + return *this; + } + __gmp_expr & operator=(const std::string &s) + { + if (mpz_set_str(mp, s.c_str(), 0) != 0) + throw std::invalid_argument ("mpz_set_str"); + return *this; + } + + // string input/output functions + int set_str(const char *s, int base) + { return mpz_set_str(mp, s, base); } + int set_str(const std::string &s, int base) + { return mpz_set_str(mp, s.c_str(), base); } + std::string get_str(int base = 10) const + { + __gmp_alloc_cstring temp(mpz_get_str(0, base, mp)); + return std::string(temp.str); + } + + // conversion functions + mpz_srcptr __get_mp() const { return mp; } + mpz_ptr __get_mp() { return mp; } + mpz_srcptr get_mpz_t() const { return mp; } + mpz_ptr get_mpz_t() { return mp; } + + signed long int get_si() const { return mpz_get_si(mp); } + unsigned long int get_ui() const { return mpz_get_ui(mp); } + double get_d() const { return mpz_get_d(mp); } + + // bool fits_schar_p() const { return mpz_fits_schar_p(mp); } + // bool fits_uchar_p() const { return mpz_fits_uchar_p(mp); } + bool fits_sint_p() const { return mpz_fits_sint_p(mp); } + bool fits_uint_p() const { return mpz_fits_uint_p(mp); } + bool fits_sshort_p() const { return mpz_fits_sshort_p(mp); } + bool fits_ushort_p() const { return mpz_fits_ushort_p(mp); } + bool fits_slong_p() const { return mpz_fits_slong_p(mp); } + bool fits_ulong_p() const { return mpz_fits_ulong_p(mp); } + // bool fits_float_p() const { return mpz_fits_float_p(mp); } + // bool fits_double_p() const { return mpz_fits_double_p(mp); } + // bool fits_ldouble_p() const { return mpz_fits_ldouble_p(mp); } + +#if __GMPXX_USE_CXX11 + explicit operator bool() const { return mp->_mp_size != 0; } +#endif + + // member operators + __GMP_DECLARE_COMPOUND_OPERATOR(operator+=) + __GMP_DECLARE_COMPOUND_OPERATOR(operator-=) + __GMP_DECLARE_COMPOUND_OPERATOR(operator*=) + __GMP_DECLARE_COMPOUND_OPERATOR(operator/=) + __GMP_DECLARE_COMPOUND_OPERATOR(operator%=) + + __GMP_DECLARE_COMPOUND_OPERATOR(operator&=) + __GMP_DECLARE_COMPOUND_OPERATOR(operator|=) + __GMP_DECLARE_COMPOUND_OPERATOR(operator^=) + + __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=) + __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=) + + __GMP_DECLARE_INCREMENT_OPERATOR(operator++) + __GMP_DECLARE_INCREMENT_OPERATOR(operator--) +}; + +typedef __gmp_expr<mpz_t, mpz_t> mpz_class; + + +/**************** mpq_class -- wrapper for mpq_t ****************/ + +template <> +class __gmp_expr<mpq_t, mpq_t> +{ +private: + typedef mpq_t value_type; + value_type mp; + + // Helper functions used for all arithmetic types + void assign_ui(unsigned long l) { mpq_set_ui(mp, l, 1); } + void assign_si(signed long l) + { + if (__GMPXX_CONSTANT_TRUE(l >= 0)) + assign_ui(l); + else + mpq_set_si(mp, l, 1); + } + void assign_d (double d) { mpq_set_d (mp, d); } + + void init_ui(unsigned long l) { mpq_init(mp); get_num() = l; } + void init_si(signed long l) { mpq_init(mp); get_num() = l; } + void init_d (double d) { mpq_init(mp); assign_d (d); } + +public: + mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } + void canonicalize() { mpq_canonicalize(mp); } + + // constructors and destructor + __gmp_expr() { mpq_init(mp); } + + __gmp_expr(const __gmp_expr &q) + { + mpz_init_set(mpq_numref(mp), mpq_numref(q.mp)); + mpz_init_set(mpq_denref(mp), mpq_denref(q.mp)); + } +#if __GMPXX_USE_CXX11 + __gmp_expr(__gmp_expr &&q) + { *mp = *q.mp; mpq_init(q.mp); } +#endif + template <class T> + __gmp_expr(const __gmp_expr<mpz_t, T> &expr) + { mpq_init(mp); __gmp_set_expr(mp, expr); } + template <class T> + __gmp_expr(const __gmp_expr<mpq_t, T> &expr) + { mpq_init(mp); __gmp_set_expr(mp, expr); } + template <class T, class U> + explicit __gmp_expr(const __gmp_expr<T, U> &expr) + { mpq_init(mp); __gmp_set_expr(mp, expr); } + + __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS + + explicit __gmp_expr(const char *s, int base = 0) + { + mpq_init (mp); + // If s is the literal 0, we meant to call another constructor. + // If s just happens to evaluate to 0, we would crash, so whatever. + if (s == 0) + { + // Don't turn mpq_class(0,0) into 0 + mpz_set_si(mpq_denref(mp), base); + } + else if (mpq_set_str(mp, s, base) != 0) + { + mpq_clear (mp); + throw std::invalid_argument ("mpq_set_str"); + } + } + explicit __gmp_expr(const std::string &s, int base = 0) + { + mpq_init(mp); + if (mpq_set_str (mp, s.c_str(), base) != 0) + { + mpq_clear (mp); + throw std::invalid_argument ("mpq_set_str"); + } + } + explicit __gmp_expr(mpq_srcptr q) + { + mpz_init_set(mpq_numref(mp), mpq_numref(q)); + mpz_init_set(mpq_denref(mp), mpq_denref(q)); + } + + __gmp_expr(const mpz_class &num, const mpz_class &den) + { + mpz_init_set(mpq_numref(mp), num.get_mpz_t()); + mpz_init_set(mpq_denref(mp), den.get_mpz_t()); + } + + ~__gmp_expr() { mpq_clear(mp); } + + void swap(__gmp_expr& q) __GMPXX_NOEXCEPT { std::swap(*mp, *q.mp); } + + // assignment operators + __gmp_expr & operator=(const __gmp_expr &q) + { mpq_set(mp, q.mp); return *this; } +#if __GMPXX_USE_CXX11 + __gmp_expr & operator=(__gmp_expr &&q) noexcept + { swap(q); return *this; } + __gmp_expr & operator=(mpz_class &&z) noexcept + { get_num() = std::move(z); get_den() = 1u; return *this; } +#endif + template <class T, class U> + __gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr) + { __gmp_set_expr(mp, expr); return *this; } + + __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS + + __gmp_expr & operator=(const char *s) + { + if (mpq_set_str (mp, s, 0) != 0) + throw std::invalid_argument ("mpq_set_str"); + return *this; + } + __gmp_expr & operator=(const std::string &s) + { + if (mpq_set_str(mp, s.c_str(), 0) != 0) + throw std::invalid_argument ("mpq_set_str"); + return *this; + } + + // string input/output functions + int set_str(const char *s, int base) + { return mpq_set_str(mp, s, base); } + int set_str(const std::string &s, int base) + { return mpq_set_str(mp, s.c_str(), base); } + std::string get_str(int base = 10) const + { + __gmp_alloc_cstring temp(mpq_get_str(0, base, mp)); + return std::string(temp.str); + } + + // conversion functions + + // casting a reference to an mpz_t to mpz_class & is a dirty hack, + // but works because the internal representation of mpz_class is + // exactly an mpz_t + const mpz_class & get_num() const + { return reinterpret_cast<const mpz_class &>(*mpq_numref(mp)); } + mpz_class & get_num() + { return reinterpret_cast<mpz_class &>(*mpq_numref(mp)); } + const mpz_class & get_den() const + { return reinterpret_cast<const mpz_class &>(*mpq_denref(mp)); } + mpz_class & get_den() + { return reinterpret_cast<mpz_class &>(*mpq_denref(mp)); } + + mpq_srcptr __get_mp() const { return mp; } + mpq_ptr __get_mp() { return mp; } + mpq_srcptr get_mpq_t() const { return mp; } + mpq_ptr get_mpq_t() { return mp; } + + mpz_srcptr get_num_mpz_t() const { return mpq_numref(mp); } + mpz_ptr get_num_mpz_t() { return mpq_numref(mp); } + mpz_srcptr get_den_mpz_t() const { return mpq_denref(mp); } + mpz_ptr get_den_mpz_t() { return mpq_denref(mp); } + + double get_d() const { return mpq_get_d(mp); } + +#if __GMPXX_USE_CXX11 + explicit operator bool() const { return mpq_numref(mp)->_mp_size != 0; } +#endif + + // compound assignments + __GMP_DECLARE_COMPOUND_OPERATOR(operator+=) + __GMP_DECLARE_COMPOUND_OPERATOR(operator-=) + __GMP_DECLARE_COMPOUND_OPERATOR(operator*=) + __GMP_DECLARE_COMPOUND_OPERATOR(operator/=) + + __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=) + __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=) + + __GMP_DECLARE_INCREMENT_OPERATOR(operator++) + __GMP_DECLARE_INCREMENT_OPERATOR(operator--) +}; + +typedef __gmp_expr<mpq_t, mpq_t> mpq_class; + + +/**************** mpf_class -- wrapper for mpf_t ****************/ + +template <> +class __gmp_expr<mpf_t, mpf_t> +{ +private: + typedef mpf_t value_type; + value_type mp; + + // Helper functions used for all arithmetic types + void assign_ui(unsigned long l) { mpf_set_ui(mp, l); } + void assign_si(signed long l) + { + if (__GMPXX_CONSTANT_TRUE(l >= 0)) + assign_ui(l); + else + mpf_set_si(mp, l); + } + void assign_d (double d) { mpf_set_d (mp, d); } + + void init_ui(unsigned long l) + { + if (__GMPXX_CONSTANT_TRUE(l == 0)) + mpf_init(mp); + else + mpf_init_set_ui(mp, l); + } + void init_si(signed long l) + { + if (__GMPXX_CONSTANT_TRUE(l >= 0)) + init_ui(l); + else + mpf_init_set_si(mp, l); + } + void init_d (double d) { mpf_init_set_d (mp, d); } + +public: + mp_bitcnt_t get_prec() const { return mpf_get_prec(mp); } + + void set_prec(mp_bitcnt_t prec) { mpf_set_prec(mp, prec); } + void set_prec_raw(mp_bitcnt_t prec) { mpf_set_prec_raw(mp, prec); } + + // constructors and destructor + __gmp_expr() { mpf_init(mp); } + + __gmp_expr(const __gmp_expr &f) + { mpf_init2(mp, f.get_prec()); mpf_set(mp, f.mp); } +#if __GMPXX_USE_CXX11 + __gmp_expr(__gmp_expr &&f) + { *mp = *f.mp; mpf_init2(f.mp, get_prec()); } +#endif + __gmp_expr(const __gmp_expr &f, mp_bitcnt_t prec) + { mpf_init2(mp, prec); mpf_set(mp, f.mp); } + template <class T, class U> + __gmp_expr(const __gmp_expr<T, U> &expr) + { mpf_init2(mp, expr.get_prec()); __gmp_set_expr(mp, expr); } + template <class T, class U> + __gmp_expr(const __gmp_expr<T, U> &expr, mp_bitcnt_t prec) + { mpf_init2(mp, prec); __gmp_set_expr(mp, expr); } + + __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS + + __gmp_expr(signed char c, mp_bitcnt_t prec) + { mpf_init2(mp, prec); mpf_set_si(mp, c); } + __gmp_expr(unsigned char c, mp_bitcnt_t prec) + { mpf_init2(mp, prec); mpf_set_ui(mp, c); } + + __gmp_expr(signed int i, mp_bitcnt_t prec) + { mpf_init2(mp, prec); mpf_set_si(mp, i); } + __gmp_expr(unsigned int i, mp_bitcnt_t prec) + { mpf_init2(mp, prec); mpf_set_ui(mp, i); } + + __gmp_expr(signed short int s, mp_bitcnt_t prec) + { mpf_init2(mp, prec); mpf_set_si(mp, s); } + __gmp_expr(unsigned short int s, mp_bitcnt_t prec) + { mpf_init2(mp, prec); mpf_set_ui(mp, s); } + + __gmp_expr(signed long int l, mp_bitcnt_t prec) + { mpf_init2(mp, prec); mpf_set_si(mp, l); } + __gmp_expr(unsigned long int l, mp_bitcnt_t prec) + { mpf_init2(mp, prec); mpf_set_ui(mp, l); } + + __gmp_expr(float f, mp_bitcnt_t prec) + { mpf_init2(mp, prec); mpf_set_d(mp, f); } + __gmp_expr(double d, mp_bitcnt_t prec) + { mpf_init2(mp, prec); mpf_set_d(mp, d); } + // __gmp_expr(long double ld) { mpf_init_set_d(mp, ld); } + // __gmp_expr(long double ld, mp_bitcnt_t prec) + // { mpf_init2(mp, prec); mpf_set_d(mp, ld); } + + explicit __gmp_expr(const char *s) + { + if (mpf_init_set_str (mp, s, 0) != 0) + { + mpf_clear (mp); + throw std::invalid_argument ("mpf_set_str"); + } + } + __gmp_expr(const char *s, mp_bitcnt_t prec, int base = 0) + { + mpf_init2(mp, prec); + if (mpf_set_str(mp, s, base) != 0) + { + mpf_clear (mp); + throw std::invalid_argument ("mpf_set_str"); + } + } + explicit __gmp_expr(const std::string &s) + { + if (mpf_init_set_str(mp, s.c_str(), 0) != 0) + { + mpf_clear (mp); + throw std::invalid_argument ("mpf_set_str"); + } + } + __gmp_expr(const std::string &s, mp_bitcnt_t prec, int base = 0) + { + mpf_init2(mp, prec); + if (mpf_set_str(mp, s.c_str(), base) != 0) + { + mpf_clear (mp); + throw std::invalid_argument ("mpf_set_str"); + } + } + + explicit __gmp_expr(mpf_srcptr f) + { mpf_init2(mp, mpf_get_prec(f)); mpf_set(mp, f); } + __gmp_expr(mpf_srcptr f, mp_bitcnt_t prec) + { mpf_init2(mp, prec); mpf_set(mp, f); } + + ~__gmp_expr() { mpf_clear(mp); } + + void swap(__gmp_expr& f) __GMPXX_NOEXCEPT { std::swap(*mp, *f.mp); } + + // assignment operators + __gmp_expr & operator=(const __gmp_expr &f) + { mpf_set(mp, f.mp); return *this; } +#if __GMPXX_USE_CXX11 + __gmp_expr & operator=(__gmp_expr &&f) noexcept + { swap(f); return *this; } +#endif + template <class T, class U> + __gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr) + { __gmp_set_expr(mp, expr); return *this; } + + __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS + + __gmp_expr & operator=(const char *s) + { + if (mpf_set_str (mp, s, 0) != 0) + throw std::invalid_argument ("mpf_set_str"); + return *this; + } + __gmp_expr & operator=(const std::string &s) + { + if (mpf_set_str(mp, s.c_str(), 0) != 0) + throw std::invalid_argument ("mpf_set_str"); + return *this; + } + + // string input/output functions + int set_str(const char *s, int base) + { return mpf_set_str(mp, s, base); } + int set_str(const std::string &s, int base) + { return mpf_set_str(mp, s.c_str(), base); } + std::string get_str(mp_exp_t &expo, int base = 10, size_t size = 0) const + { + __gmp_alloc_cstring temp(mpf_get_str(0, &expo, base, size, mp)); + return std::string(temp.str); + } + + // conversion functions + mpf_srcptr __get_mp() const { return mp; } + mpf_ptr __get_mp() { return mp; } + mpf_srcptr get_mpf_t() const { return mp; } + mpf_ptr get_mpf_t() { return mp; } + + signed long int get_si() const { return mpf_get_si(mp); } + unsigned long int get_ui() const { return mpf_get_ui(mp); } + double get_d() const { return mpf_get_d(mp); } + + // bool fits_schar_p() const { return mpf_fits_schar_p(mp); } + // bool fits_uchar_p() const { return mpf_fits_uchar_p(mp); } + bool fits_sint_p() const { return mpf_fits_sint_p(mp); } + bool fits_uint_p() const { return mpf_fits_uint_p(mp); } + bool fits_sshort_p() const { return mpf_fits_sshort_p(mp); } + bool fits_ushort_p() const { return mpf_fits_ushort_p(mp); } + bool fits_slong_p() const { return mpf_fits_slong_p(mp); } + bool fits_ulong_p() const { return mpf_fits_ulong_p(mp); } + // bool fits_float_p() const { return mpf_fits_float_p(mp); } + // bool fits_double_p() const { return mpf_fits_double_p(mp); } + // bool fits_ldouble_p() const { return mpf_fits_ldouble_p(mp); } + +#if __GMPXX_USE_CXX11 + explicit operator bool() const { return mp->_mp_size != 0; } +#endif + + // compound assignments + __GMP_DECLARE_COMPOUND_OPERATOR(operator+=) + __GMP_DECLARE_COMPOUND_OPERATOR(operator-=) + __GMP_DECLARE_COMPOUND_OPERATOR(operator*=) + __GMP_DECLARE_COMPOUND_OPERATOR(operator/=) + + __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator<<=) + __GMP_DECLARE_COMPOUND_OPERATOR_UI(operator>>=) + + __GMP_DECLARE_INCREMENT_OPERATOR(operator++) + __GMP_DECLARE_INCREMENT_OPERATOR(operator--) +}; + +typedef __gmp_expr<mpf_t, mpf_t> mpf_class; + + + +/**************** User-defined literals ****************/ + +#if __GMPXX_USE_CXX11 +inline mpz_class operator"" _mpz(const char* s) +{ + return mpz_class(s); +} + +inline mpq_class operator"" _mpq(const char* s) +{ + mpq_class q; + q.get_num() = s; + return q; +} + +inline mpf_class operator"" _mpf(const char* s) +{ + return mpf_class(s); +} +#endif + +/**************** I/O operators ****************/ + +// these should (and will) be provided separately + +template <class T, class U> +inline std::ostream & operator<< +(std::ostream &o, const __gmp_expr<T, U> &expr) +{ + __gmp_expr<T, T> const& temp(expr); + return o << temp.__get_mp(); +} + +template <class T> +inline std::istream & operator>>(std::istream &i, __gmp_expr<T, T> &expr) +{ + return i >> expr.__get_mp(); +} + +/* +// you might want to uncomment this +inline std::istream & operator>>(std::istream &i, mpq_class &q) +{ + i >> q.get_mpq_t(); + q.canonicalize(); + return i; +} +*/ + + +/**************** Functions for type conversion ****************/ + +inline void __gmp_set_expr(mpz_ptr z, const mpz_class &w) +{ + mpz_set(z, w.get_mpz_t()); +} + +template <class T> +inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<mpz_t, T> &expr) +{ + expr.eval(z); +} + +template <class T> +inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<mpq_t, T> &expr) +{ + mpq_class const& temp(expr); + mpz_set_q(z, temp.get_mpq_t()); +} + +template <class T> +inline void __gmp_set_expr(mpz_ptr z, const __gmp_expr<mpf_t, T> &expr) +{ + mpf_class const& temp(expr); + mpz_set_f(z, temp.get_mpf_t()); +} + +inline void __gmp_set_expr(mpq_ptr q, const mpz_class &z) +{ + mpq_set_z(q, z.get_mpz_t()); +} + +template <class T> +inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<mpz_t, T> &expr) +{ + __gmp_set_expr(mpq_numref(q), expr); + mpz_set_ui(mpq_denref(q), 1); +} + +inline void __gmp_set_expr(mpq_ptr q, const mpq_class &r) +{ + mpq_set(q, r.get_mpq_t()); +} + +template <class T> +inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<mpq_t, T> &expr) +{ + expr.eval(q); +} + +template <class T> +inline void __gmp_set_expr(mpq_ptr q, const __gmp_expr<mpf_t, T> &expr) +{ + mpf_class const& temp(expr); + mpq_set_f(q, temp.get_mpf_t()); +} + +template <class T> +inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<mpz_t, T> &expr) +{ + mpz_class const& temp(expr); + mpf_set_z(f, temp.get_mpz_t()); +} + +template <class T> +inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<mpq_t, T> &expr) +{ + mpq_class const& temp(expr); + mpf_set_q(f, temp.get_mpq_t()); +} + +inline void __gmp_set_expr(mpf_ptr f, const mpf_class &g) +{ + mpf_set(f, g.get_mpf_t()); +} + +template <class T> +inline void __gmp_set_expr(mpf_ptr f, const __gmp_expr<mpf_t, T> &expr) +{ + expr.eval(f); +} + + +/* Temporary objects */ + +template <class T> +class __gmp_temp +{ + __gmp_expr<T, T> val; + public: + template<class U, class V> + __gmp_temp(U const& u, V) : val (u) {} + typename __gmp_resolve_expr<T>::srcptr_type + __get_mp() const { return val.__get_mp(); } +}; + +template <> +class __gmp_temp <mpf_t> +{ + mpf_class val; + public: + template<class U> + __gmp_temp(U const& u, mpf_ptr res) : val (u, mpf_get_prec(res)) {} + mpf_srcptr __get_mp() const { return val.__get_mp(); } +}; + +/**************** Specializations of __gmp_expr ****************/ +/* The eval() method of __gmp_expr<T, U> evaluates the corresponding + expression and assigns the result to its argument, which is either an + mpz_t, mpq_t, or mpf_t as specified by the T argument. + Compound expressions are evaluated recursively (temporaries are created + to hold intermediate values), while for simple expressions the eval() + method of the appropriate function object (available as the Op argument + of either __gmp_unary_expr<T, Op> or __gmp_binary_expr<T, U, Op>) is + called. */ + + +/**************** Unary expressions ****************/ +/* cases: + - simple: argument is mp*_class, that is, __gmp_expr<T, T> + - compound: argument is __gmp_expr<T, U> (with U not equal to T) */ + + +// simple expressions + +template <class T, class Op> +class __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, T>, Op> > +{ +private: + typedef __gmp_expr<T, T> val_type; + + __gmp_unary_expr<val_type, Op> expr; +public: + explicit __gmp_expr(const val_type &val) : expr(val) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p) const + { Op::eval(p, expr.val.__get_mp()); } + const val_type & get_val() const { return expr.val; } + mp_bitcnt_t get_prec() const { return expr.val.get_prec(); } +}; + + +// simple expressions, U is a built-in numerical type + +template <class T, class U, class Op> +class __gmp_expr<T, __gmp_unary_expr<U, Op> > +{ +private: + typedef U val_type; + + __gmp_unary_expr<val_type, Op> expr; +public: + explicit __gmp_expr(const val_type &val) : expr(val) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p) const + { Op::eval(p, expr.val); } + const val_type & get_val() const { return expr.val; } + mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } +}; + + +// compound expressions + +template <class T, class U, class Op> +class __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, Op> > +{ +private: + typedef __gmp_expr<T, U> val_type; + + __gmp_unary_expr<val_type, Op> expr; +public: + explicit __gmp_expr(const val_type &val) : expr(val) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p) const + { expr.val.eval(p); Op::eval(p, p); } + const val_type & get_val() const { return expr.val; } + mp_bitcnt_t get_prec() const { return expr.val.get_prec(); } +}; + + +/**************** Binary expressions ****************/ +/* simple: + - arguments are both mp*_class + - one argument is mp*_class, one is a built-in type + compound: + - one is mp*_class, one is __gmp_expr<T, U> + - one is __gmp_expr<T, U>, one is built-in + - both arguments are __gmp_expr<...> */ + + +// simple expressions + +template <class T, class Op> +class __gmp_expr +<T, __gmp_binary_expr<__gmp_expr<T, T>, __gmp_expr<T, T>, Op> > +{ +private: + typedef __gmp_expr<T, T> val1_type; + typedef __gmp_expr<T, T> val2_type; + + __gmp_binary_expr<val1_type, val2_type, Op> expr; +public: + __gmp_expr(const val1_type &val1, const val2_type &val2) + : expr(val1, val2) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p) const + { Op::eval(p, expr.val1.__get_mp(), expr.val2.__get_mp()); } + const val1_type & get_val1() const { return expr.val1; } + const val2_type & get_val2() const { return expr.val2; } + mp_bitcnt_t get_prec() const + { + mp_bitcnt_t prec1 = expr.val1.get_prec(), + prec2 = expr.val2.get_prec(); + return (prec1 > prec2) ? prec1 : prec2; + } +}; + + +// simple expressions, U is a built-in numerical type + +template <class T, class U, class Op> +class __gmp_expr<T, __gmp_binary_expr<__gmp_expr<T, T>, U, Op> > +{ +private: + typedef __gmp_expr<T, T> val1_type; + typedef U val2_type; + + __gmp_binary_expr<val1_type, val2_type, Op> expr; +public: + __gmp_expr(const val1_type &val1, const val2_type &val2) + : expr(val1, val2) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p) const + { Op::eval(p, expr.val1.__get_mp(), expr.val2); } + const val1_type & get_val1() const { return expr.val1; } + const val2_type & get_val2() const { return expr.val2; } + mp_bitcnt_t get_prec() const { return expr.val1.get_prec(); } +}; + +template <class T, class U, class Op> +class __gmp_expr<T, __gmp_binary_expr<U, __gmp_expr<T, T>, Op> > +{ +private: + typedef U val1_type; + typedef __gmp_expr<T, T> val2_type; + + __gmp_binary_expr<val1_type, val2_type, Op> expr; +public: + __gmp_expr(const val1_type &val1, const val2_type &val2) + : expr(val1, val2) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p) const + { Op::eval(p, expr.val1, expr.val2.__get_mp()); } + const val1_type & get_val1() const { return expr.val1; } + const val2_type & get_val2() const { return expr.val2; } + mp_bitcnt_t get_prec() const { return expr.val2.get_prec(); } +}; + + +// compound expressions, one argument is a subexpression + +template <class T, class U, class V, class Op> +class __gmp_expr +<T, __gmp_binary_expr<__gmp_expr<T, T>, __gmp_expr<U, V>, Op> > +{ +private: + typedef __gmp_expr<T, T> val1_type; + typedef __gmp_expr<U, V> val2_type; + + __gmp_binary_expr<val1_type, val2_type, Op> expr; +public: + __gmp_expr(const val1_type &val1, const val2_type &val2) + : expr(val1, val2) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p) const + { + if(p != expr.val1.__get_mp()) + { + __gmp_set_expr(p, expr.val2); + Op::eval(p, expr.val1.__get_mp(), p); + } + else + { + __gmp_temp<T> temp(expr.val2, p); + Op::eval(p, expr.val1.__get_mp(), temp.__get_mp()); + } + } + const val1_type & get_val1() const { return expr.val1; } + const val2_type & get_val2() const { return expr.val2; } + mp_bitcnt_t get_prec() const + { + mp_bitcnt_t prec1 = expr.val1.get_prec(), + prec2 = expr.val2.get_prec(); + return (prec1 > prec2) ? prec1 : prec2; + } +}; + +template <class T, class U, class V, class Op> +class __gmp_expr +<T, __gmp_binary_expr<__gmp_expr<U, V>, __gmp_expr<T, T>, Op> > +{ +private: + typedef __gmp_expr<U, V> val1_type; + typedef __gmp_expr<T, T> val2_type; + + __gmp_binary_expr<val1_type, val2_type, Op> expr; +public: + __gmp_expr(const val1_type &val1, const val2_type &val2) + : expr(val1, val2) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p) const + { + if(p != expr.val2.__get_mp()) + { + __gmp_set_expr(p, expr.val1); + Op::eval(p, p, expr.val2.__get_mp()); + } + else + { + __gmp_temp<T> temp(expr.val1, p); + Op::eval(p, temp.__get_mp(), expr.val2.__get_mp()); + } + } + const val1_type & get_val1() const { return expr.val1; } + const val2_type & get_val2() const { return expr.val2; } + mp_bitcnt_t get_prec() const + { + mp_bitcnt_t prec1 = expr.val1.get_prec(), + prec2 = expr.val2.get_prec(); + return (prec1 > prec2) ? prec1 : prec2; + } +}; + +template <class T, class U, class Op> +class __gmp_expr +<T, __gmp_binary_expr<__gmp_expr<T, T>, __gmp_expr<T, U>, Op> > +{ +private: + typedef __gmp_expr<T, T> val1_type; + typedef __gmp_expr<T, U> val2_type; + + __gmp_binary_expr<val1_type, val2_type, Op> expr; +public: + __gmp_expr(const val1_type &val1, const val2_type &val2) + : expr(val1, val2) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p) const + { + if(p != expr.val1.__get_mp()) + { + __gmp_set_expr(p, expr.val2); + Op::eval(p, expr.val1.__get_mp(), p); + } + else + { + __gmp_temp<T> temp(expr.val2, p); + Op::eval(p, expr.val1.__get_mp(), temp.__get_mp()); + } + } + const val1_type & get_val1() const { return expr.val1; } + const val2_type & get_val2() const { return expr.val2; } + mp_bitcnt_t get_prec() const + { + mp_bitcnt_t prec1 = expr.val1.get_prec(), + prec2 = expr.val2.get_prec(); + return (prec1 > prec2) ? prec1 : prec2; + } +}; + +template <class T, class U, class Op> +class __gmp_expr +<T, __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<T, T>, Op> > +{ +private: + typedef __gmp_expr<T, U> val1_type; + typedef __gmp_expr<T, T> val2_type; + + __gmp_binary_expr<val1_type, val2_type, Op> expr; +public: + __gmp_expr(const val1_type &val1, const val2_type &val2) + : expr(val1, val2) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p) const + { + if(p != expr.val2.__get_mp()) + { + __gmp_set_expr(p, expr.val1); + Op::eval(p, p, expr.val2.__get_mp()); + } + else + { + __gmp_temp<T> temp(expr.val1, p); + Op::eval(p, temp.__get_mp(), expr.val2.__get_mp()); + } + } + const val1_type & get_val1() const { return expr.val1; } + const val2_type & get_val2() const { return expr.val2; } + mp_bitcnt_t get_prec() const + { + mp_bitcnt_t prec1 = expr.val1.get_prec(), + prec2 = expr.val2.get_prec(); + return (prec1 > prec2) ? prec1 : prec2; + } +}; + + +// one argument is a subexpression, one is a built-in + +template <class T, class U, class V, class Op> +class __gmp_expr<T, __gmp_binary_expr<__gmp_expr<T, U>, V, Op> > +{ +private: + typedef __gmp_expr<T, U> val1_type; + typedef V val2_type; + + __gmp_binary_expr<val1_type, val2_type, Op> expr; +public: + __gmp_expr(const val1_type &val1, const val2_type &val2) + : expr(val1, val2) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p) const + { + expr.val1.eval(p); + Op::eval(p, p, expr.val2); + } + const val1_type & get_val1() const { return expr.val1; } + const val2_type & get_val2() const { return expr.val2; } + mp_bitcnt_t get_prec() const { return expr.val1.get_prec(); } +}; + +template <class T, class U, class V, class Op> +class __gmp_expr<T, __gmp_binary_expr<U, __gmp_expr<T, V>, Op> > +{ +private: + typedef U val1_type; + typedef __gmp_expr<T, V> val2_type; + + __gmp_binary_expr<val1_type, val2_type, Op> expr; +public: + __gmp_expr(const val1_type &val1, const val2_type &val2) + : expr(val1, val2) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p) const + { + expr.val2.eval(p); + Op::eval(p, expr.val1, p); + } + const val1_type & get_val1() const { return expr.val1; } + const val2_type & get_val2() const { return expr.val2; } + mp_bitcnt_t get_prec() const { return expr.val2.get_prec(); } +}; + + +// both arguments are subexpressions + +template <class T, class U, class V, class W, class Op> +class __gmp_expr +<T, __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, Op> > +{ +private: + typedef __gmp_expr<T, U> val1_type; + typedef __gmp_expr<V, W> val2_type; + + __gmp_binary_expr<val1_type, val2_type, Op> expr; +public: + __gmp_expr(const val1_type &val1, const val2_type &val2) + : expr(val1, val2) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p) const + { + __gmp_temp<T> temp2(expr.val2, p); + expr.val1.eval(p); + Op::eval(p, p, temp2.__get_mp()); + } + const val1_type & get_val1() const { return expr.val1; } + const val2_type & get_val2() const { return expr.val2; } + mp_bitcnt_t get_prec() const + { + mp_bitcnt_t prec1 = expr.val1.get_prec(), + prec2 = expr.val2.get_prec(); + return (prec1 > prec2) ? prec1 : prec2; + } +}; + +template <class T, class U, class V, class W, class Op> +class __gmp_expr +<T, __gmp_binary_expr<__gmp_expr<U, V>, __gmp_expr<T, W>, Op> > +{ +private: + typedef __gmp_expr<U, V> val1_type; + typedef __gmp_expr<T, W> val2_type; + + __gmp_binary_expr<val1_type, val2_type, Op> expr; +public: + __gmp_expr(const val1_type &val1, const val2_type &val2) + : expr(val1, val2) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p) const + { + __gmp_temp<T> temp1(expr.val1, p); + expr.val2.eval(p); + Op::eval(p, temp1.__get_mp(), p); + } + const val1_type & get_val1() const { return expr.val1; } + const val2_type & get_val2() const { return expr.val2; } + mp_bitcnt_t get_prec() const + { + mp_bitcnt_t prec1 = expr.val1.get_prec(), + prec2 = expr.val2.get_prec(); + return (prec1 > prec2) ? prec1 : prec2; + } +}; + +template <class T, class U, class V, class Op> +class __gmp_expr +<T, __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<T, V>, Op> > +{ +private: + typedef __gmp_expr<T, U> val1_type; + typedef __gmp_expr<T, V> val2_type; + + __gmp_binary_expr<val1_type, val2_type, Op> expr; +public: + __gmp_expr(const val1_type &val1, const val2_type &val2) + : expr(val1, val2) { } + void eval(typename __gmp_resolve_expr<T>::ptr_type p) const + { + __gmp_temp<T> temp2(expr.val2, p); + expr.val1.eval(p); + Op::eval(p, p, temp2.__get_mp()); + } + const val1_type & get_val1() const { return expr.val1; } + const val2_type & get_val2() const { return expr.val2; } + mp_bitcnt_t get_prec() const + { + mp_bitcnt_t prec1 = expr.val1.get_prec(), + prec2 = expr.val2.get_prec(); + return (prec1 > prec2) ? prec1 : prec2; + } +}; + + +/**************** Special cases ****************/ + +/* Some operations (i.e., add and subtract) with mixed mpz/mpq arguments + can be done directly without first converting the mpz to mpq. + Appropriate specializations of __gmp_expr are required. */ + + +#define __GMPZQ_DEFINE_EXPR(eval_fun) \ + \ +template <> \ +class __gmp_expr<mpq_t, __gmp_binary_expr<mpz_class, mpq_class, eval_fun> > \ +{ \ +private: \ + typedef mpz_class val1_type; \ + typedef mpq_class val2_type; \ + \ + __gmp_binary_expr<val1_type, val2_type, eval_fun> expr; \ +public: \ + __gmp_expr(const val1_type &val1, const val2_type &val2) \ + : expr(val1, val2) { } \ + void eval(mpq_ptr q) const \ + { eval_fun::eval(q, expr.val1.get_mpz_t(), expr.val2.get_mpq_t()); } \ + const val1_type & get_val1() const { return expr.val1; } \ + const val2_type & get_val2() const { return expr.val2; } \ + mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } \ +}; \ + \ +template <> \ +class __gmp_expr<mpq_t, __gmp_binary_expr<mpq_class, mpz_class, eval_fun> > \ +{ \ +private: \ + typedef mpq_class val1_type; \ + typedef mpz_class val2_type; \ + \ + __gmp_binary_expr<val1_type, val2_type, eval_fun> expr; \ +public: \ + __gmp_expr(const val1_type &val1, const val2_type &val2) \ + : expr(val1, val2) { } \ + void eval(mpq_ptr q) const \ + { eval_fun::eval(q, expr.val1.get_mpq_t(), expr.val2.get_mpz_t()); } \ + const val1_type & get_val1() const { return expr.val1; } \ + const val2_type & get_val2() const { return expr.val2; } \ + mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } \ +}; \ + \ +template <class T> \ +class __gmp_expr \ +<mpq_t, __gmp_binary_expr<mpz_class, __gmp_expr<mpq_t, T>, eval_fun> > \ +{ \ +private: \ + typedef mpz_class val1_type; \ + typedef __gmp_expr<mpq_t, T> val2_type; \ + \ + __gmp_binary_expr<val1_type, val2_type, eval_fun> expr; \ +public: \ + __gmp_expr(const val1_type &val1, const val2_type &val2) \ + : expr(val1, val2) { } \ + void eval(mpq_ptr q) const \ + { \ + mpq_class temp(expr.val2); \ + eval_fun::eval(q, expr.val1.get_mpz_t(), temp.get_mpq_t()); \ + } \ + const val1_type & get_val1() const { return expr.val1; } \ + const val2_type & get_val2() const { return expr.val2; } \ + mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } \ +}; \ + \ +template <class T> \ +class __gmp_expr \ +<mpq_t, __gmp_binary_expr<mpq_class, __gmp_expr<mpz_t, T>, eval_fun> > \ +{ \ +private: \ + typedef mpq_class val1_type; \ + typedef __gmp_expr<mpz_t, T> val2_type; \ + \ + __gmp_binary_expr<val1_type, val2_type, eval_fun> expr; \ +public: \ + __gmp_expr(const val1_type &val1, const val2_type &val2) \ + : expr(val1, val2) { } \ + void eval(mpq_ptr q) const \ + { \ + mpz_class temp(expr.val2); \ + eval_fun::eval(q, expr.val1.get_mpq_t(), temp.get_mpz_t()); \ + } \ + const val1_type & get_val1() const { return expr.val1; } \ + const val2_type & get_val2() const { return expr.val2; } \ + mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } \ +}; \ + \ +template <class T> \ +class __gmp_expr \ +<mpq_t, __gmp_binary_expr<__gmp_expr<mpz_t, T>, mpq_class, eval_fun> > \ +{ \ +private: \ + typedef __gmp_expr<mpz_t, T> val1_type; \ + typedef mpq_class val2_type; \ + \ + __gmp_binary_expr<val1_type, val2_type, eval_fun> expr; \ +public: \ + __gmp_expr(const val1_type &val1, const val2_type &val2) \ + : expr(val1, val2) { } \ + void eval(mpq_ptr q) const \ + { \ + mpz_class temp(expr.val1); \ + eval_fun::eval(q, temp.get_mpz_t(), expr.val2.get_mpq_t()); \ + } \ + const val1_type & get_val1() const { return expr.val1; } \ + const val2_type & get_val2() const { return expr.val2; } \ + mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } \ +}; \ + \ +template <class T> \ +class __gmp_expr \ +<mpq_t, __gmp_binary_expr<__gmp_expr<mpq_t, T>, mpz_class, eval_fun> > \ +{ \ +private: \ + typedef __gmp_expr<mpq_t, T> val1_type; \ + typedef mpz_class val2_type; \ + \ + __gmp_binary_expr<val1_type, val2_type, eval_fun> expr; \ +public: \ + __gmp_expr(const val1_type &val1, const val2_type &val2) \ + : expr(val1, val2) { } \ + void eval(mpq_ptr q) const \ + { \ + mpq_class temp(expr.val1); \ + eval_fun::eval(q, temp.get_mpq_t(), expr.val2.get_mpz_t()); \ + } \ + const val1_type & get_val1() const { return expr.val1; } \ + const val2_type & get_val2() const { return expr.val2; } \ + mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } \ +}; \ + \ +template <class T, class U> \ +class __gmp_expr<mpq_t, __gmp_binary_expr \ +<__gmp_expr<mpz_t, T>, __gmp_expr<mpq_t, U>, eval_fun> > \ +{ \ +private: \ + typedef __gmp_expr<mpz_t, T> val1_type; \ + typedef __gmp_expr<mpq_t, U> val2_type; \ + \ + __gmp_binary_expr<val1_type, val2_type, eval_fun> expr; \ +public: \ + __gmp_expr(const val1_type &val1, const val2_type &val2) \ + : expr(val1, val2) { } \ + void eval(mpq_ptr q) const \ + { \ + mpz_class temp1(expr.val1); \ + expr.val2.eval(q); \ + eval_fun::eval(q, temp1.get_mpz_t(), q); \ + } \ + const val1_type & get_val1() const { return expr.val1; } \ + const val2_type & get_val2() const { return expr.val2; } \ + mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } \ +}; \ + \ +template <class T, class U> \ +class __gmp_expr<mpq_t, __gmp_binary_expr \ +<__gmp_expr<mpq_t, T>, __gmp_expr<mpz_t, U>, eval_fun> > \ +{ \ +private: \ + typedef __gmp_expr<mpq_t, T> val1_type; \ + typedef __gmp_expr<mpz_t, U> val2_type; \ + \ + __gmp_binary_expr<val1_type, val2_type, eval_fun> expr; \ +public: \ + __gmp_expr(const val1_type &val1, const val2_type &val2) \ + : expr(val1, val2) { } \ + void eval(mpq_ptr q) const \ + { \ + mpz_class temp2(expr.val2); \ + expr.val1.eval(q); \ + eval_fun::eval(q, q, temp2.get_mpz_t()); \ + } \ + const val1_type & get_val1() const { return expr.val1; } \ + const val2_type & get_val2() const { return expr.val2; } \ + mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } \ +}; + + +__GMPZQ_DEFINE_EXPR(__gmp_binary_plus) +__GMPZQ_DEFINE_EXPR(__gmp_binary_minus) + + + +/**************** Macros for defining functions ****************/ +/* Results of operators and functions are instances of __gmp_expr<T, U>. + T determines the numerical type of the expression: it can be either + mpz_t, mpq_t, or mpf_t. When the arguments of a binary + expression have different numerical types, __gmp_resolve_expr is used + to determine the "larger" type. + U is either __gmp_unary_expr<V, Op> or __gmp_binary_expr<V, W, Op>, + where V and W are the arguments' types -- they can in turn be + expressions, thus allowing to build compound expressions to any + degree of complexity. + Op is a function object that must have an eval() method accepting + appropriate arguments. + Actual evaluation of a __gmp_expr<T, U> object is done when it gets + assigned to an mp*_class ("lazy" evaluation): this is done by calling + its eval() method. */ + + +// non-member unary operators and functions + +#define __GMP_DEFINE_UNARY_FUNCTION(fun, eval_fun) \ + \ +template <class T, class U> \ +inline __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, eval_fun> > \ +fun(const __gmp_expr<T, U> &expr) \ +{ \ + return __gmp_expr<T, __gmp_unary_expr<__gmp_expr<T, U>, eval_fun> >(expr); \ +} + +#define __GMP_DEFINE_UNARY_TYPE_FUNCTION(type, fun, eval_fun) \ + \ +template <class T, class U> \ +inline type fun(const __gmp_expr<T, U> &expr) \ +{ \ + __gmp_expr<T, T> const& temp(expr); \ + return eval_fun::eval(temp.__get_mp()); \ +} + + +// non-member binary operators and functions + +#define __GMPP_DEFINE_BINARY_FUNCTION(fun, eval_fun) \ + \ +template <class T, class U, class V, class W> \ +inline __gmp_expr<typename __gmp_resolve_expr<T, V>::value_type, \ +__gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, eval_fun> > \ +fun(const __gmp_expr<T, U> &expr1, const __gmp_expr<V, W> &expr2) \ +{ \ + return __gmp_expr<typename __gmp_resolve_expr<T, V>::value_type, \ + __gmp_binary_expr<__gmp_expr<T, U>, __gmp_expr<V, W>, eval_fun> > \ + (expr1, expr2); \ +} + +#define __GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, bigtype) \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<__gmp_expr<T, U>, bigtype, eval_fun> > \ +fun(const __gmp_expr<T, U> &expr, type t) \ +{ \ + return __gmp_expr \ + <T, __gmp_binary_expr<__gmp_expr<T, U>, bigtype, eval_fun> >(expr, t); \ +} \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<bigtype, __gmp_expr<T, U>, eval_fun> > \ +fun(type t, const __gmp_expr<T, U> &expr) \ +{ \ + return __gmp_expr \ + <T, __gmp_binary_expr<bigtype, __gmp_expr<T, U>, eval_fun> >(t, expr); \ +} + +#define __GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, type) \ +__GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, signed long int) + +#define __GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, type) \ +__GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, unsigned long int) + +#define __GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, type) \ +__GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, double) + +#define __GMPNLD_DEFINE_BINARY_FUNCTION(fun, eval_fun, type) \ +__GMPNN_DEFINE_BINARY_FUNCTION(fun, eval_fun, type, long double) + +#define __GMPN_DEFINE_BINARY_FUNCTION(fun, eval_fun) \ +__GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed char) \ +__GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned char) \ +__GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed int) \ +__GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned int) \ +__GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed short int) \ +__GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned short int) \ +__GMPNS_DEFINE_BINARY_FUNCTION(fun, eval_fun, signed long int) \ +__GMPNU_DEFINE_BINARY_FUNCTION(fun, eval_fun, unsigned long int) \ +__GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, float) \ +__GMPND_DEFINE_BINARY_FUNCTION(fun, eval_fun, double) \ +/* __GMPNLD_DEFINE_BINARY_FUNCTION(fun, eval_fun, long double) */ + +#define __GMP_DEFINE_BINARY_FUNCTION(fun, eval_fun) \ +__GMPP_DEFINE_BINARY_FUNCTION(fun, eval_fun) \ +__GMPN_DEFINE_BINARY_FUNCTION(fun, eval_fun) + + +#define __GMP_DEFINE_BINARY_FUNCTION_UI(fun, eval_fun) \ + \ +template <class T, class U> \ +inline __gmp_expr \ +<T, __gmp_binary_expr<__gmp_expr<T, U>, mp_bitcnt_t, eval_fun> > \ +fun(const __gmp_expr<T, U> &expr, mp_bitcnt_t l) \ +{ \ + return __gmp_expr<T, __gmp_binary_expr \ + <__gmp_expr<T, U>, mp_bitcnt_t, eval_fun> >(expr, l); \ +} + + +#define __GMPP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun) \ + \ +template <class T, class U, class V, class W> \ +inline type fun(const __gmp_expr<T, U> &expr1, \ + const __gmp_expr<V, W> &expr2) \ +{ \ + __gmp_expr<T, T> const& temp1(expr1); \ + __gmp_expr<V, V> const& temp2(expr2); \ + return eval_fun::eval(temp1.__get_mp(), temp2.__get_mp()); \ +} + +#define __GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, \ + type2, bigtype) \ + \ +template <class T, class U> \ +inline type fun(const __gmp_expr<T, U> &expr, type2 t) \ +{ \ + __gmp_expr<T, T> const& temp(expr); \ + return eval_fun::eval(temp.__get_mp(), static_cast<bigtype>(t)); \ +} \ + \ +template <class T, class U> \ +inline type fun(type2 t, const __gmp_expr<T, U> &expr) \ +{ \ + __gmp_expr<T, T> const& temp(expr); \ + return eval_fun::eval(static_cast<bigtype>(t), temp.__get_mp()); \ +} + +#define __GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \ +__GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, \ + type2, signed long int) + +#define __GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \ +__GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, \ + type2, unsigned long int) + +#define __GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \ +__GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2, double) + +#define __GMPNLD_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2) \ +__GMPNN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, type2, long double) + +#define __GMPN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun) \ +__GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed char) \ +__GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned char) \ +__GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed int) \ +__GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned int) \ +__GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed short int) \ +__GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned short int) \ +__GMPNS_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, signed long int) \ +__GMPNU_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, unsigned long int) \ +__GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, float) \ +__GMPND_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, double) \ +/* __GMPNLD_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun, long double) */ + +#define __GMP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun) \ +__GMPP_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun) \ +__GMPN_DEFINE_BINARY_TYPE_FUNCTION(type, fun, eval_fun) + + +// member operators + +#define __GMPP_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun) \ + \ +template <class T, class U> \ +inline type##_class & type##_class::fun(const __gmp_expr<T, U> &expr) \ +{ \ + __gmp_set_expr(mp, __gmp_expr<type##_t, __gmp_binary_expr \ + <type##_class, __gmp_expr<T, U>, eval_fun> >(*this, expr)); \ + return *this; \ +} + +#define __GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, \ + type2, bigtype) \ + \ +inline type##_class & type##_class::fun(type2 t) \ +{ \ + __gmp_set_expr(mp, __gmp_expr<type##_t, __gmp_binary_expr \ + <type##_class, bigtype, eval_fun> >(*this, t)); \ + return *this; \ +} + +#define __GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \ +__GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, \ + type2, signed long int) + +#define __GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \ +__GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, \ + type2, unsigned long int) + +#define __GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \ +__GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2, double) + +#define __GMPNLD_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2) \ +__GMPNN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, type2, long double) + +#define __GMPN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun) \ +__GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed char) \ +__GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned char) \ +__GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed int) \ +__GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned int) \ +__GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed short int) \ +__GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned short int) \ +__GMPNS_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, signed long int) \ +__GMPNU_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, unsigned long int) \ +__GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, float) \ +__GMPND_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, double) \ +/* __GMPNLD_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun, long double) */ + +#define __GMP_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun) \ +__GMPP_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun) \ +__GMPN_DEFINE_COMPOUND_OPERATOR(type, fun, eval_fun) + +#define __GMPZ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \ +__GMP_DEFINE_COMPOUND_OPERATOR(mpz, fun, eval_fun) + +#define __GMPQ_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \ +__GMP_DEFINE_COMPOUND_OPERATOR(mpq, fun, eval_fun) + +#define __GMPF_DEFINE_COMPOUND_OPERATOR(fun, eval_fun) \ +__GMP_DEFINE_COMPOUND_OPERATOR(mpf, fun, eval_fun) + + + +#define __GMP_DEFINE_COMPOUND_OPERATOR_UI(type, fun, eval_fun) \ + \ +inline type##_class & type##_class::fun(mp_bitcnt_t l) \ +{ \ + __gmp_set_expr(mp, __gmp_expr<type##_t, __gmp_binary_expr \ + <type##_class, mp_bitcnt_t, eval_fun> >(*this, l)); \ + return *this; \ +} + +#define __GMPZ_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \ +__GMP_DEFINE_COMPOUND_OPERATOR_UI(mpz, fun, eval_fun) + +#define __GMPQ_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \ +__GMP_DEFINE_COMPOUND_OPERATOR_UI(mpq, fun, eval_fun) + +#define __GMPF_DEFINE_COMPOUND_OPERATOR_UI(fun, eval_fun) \ +__GMP_DEFINE_COMPOUND_OPERATOR_UI(mpf, fun, eval_fun) + + + +#define __GMP_DEFINE_INCREMENT_OPERATOR(type, fun, eval_fun) \ + \ +inline type##_class & type##_class::fun() \ +{ \ + eval_fun::eval(mp); \ + return *this; \ +} \ + \ +inline type##_class type##_class::fun(int) \ +{ \ + type##_class temp(*this); \ + eval_fun::eval(mp); \ + return temp; \ +} + +#define __GMPZ_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \ +__GMP_DEFINE_INCREMENT_OPERATOR(mpz, fun, eval_fun) + +#define __GMPQ_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \ +__GMP_DEFINE_INCREMENT_OPERATOR(mpq, fun, eval_fun) + +#define __GMPF_DEFINE_INCREMENT_OPERATOR(fun, eval_fun) \ +__GMP_DEFINE_INCREMENT_OPERATOR(mpf, fun, eval_fun) + + + +/**************** Arithmetic operators and functions ****************/ + +// non-member operators and functions + +__GMP_DEFINE_UNARY_FUNCTION(operator+, __gmp_unary_plus) +__GMP_DEFINE_UNARY_FUNCTION(operator-, __gmp_unary_minus) +__GMP_DEFINE_UNARY_FUNCTION(operator~, __gmp_unary_com) + +__GMP_DEFINE_BINARY_FUNCTION(operator+, __gmp_binary_plus) +__GMP_DEFINE_BINARY_FUNCTION(operator-, __gmp_binary_minus) +__GMP_DEFINE_BINARY_FUNCTION(operator*, __gmp_binary_multiplies) +__GMP_DEFINE_BINARY_FUNCTION(operator/, __gmp_binary_divides) +__GMP_DEFINE_BINARY_FUNCTION(operator%, __gmp_binary_modulus) +__GMP_DEFINE_BINARY_FUNCTION(operator&, __gmp_binary_and) +__GMP_DEFINE_BINARY_FUNCTION(operator|, __gmp_binary_ior) +__GMP_DEFINE_BINARY_FUNCTION(operator^, __gmp_binary_xor) + +__GMP_DEFINE_BINARY_FUNCTION_UI(operator<<, __gmp_binary_lshift) +__GMP_DEFINE_BINARY_FUNCTION_UI(operator>>, __gmp_binary_rshift) + +__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator==, __gmp_binary_equal) +__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator!=, ! __gmp_binary_equal) +__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator<, __gmp_binary_less) +__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator<=, ! __gmp_binary_greater) +__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator>, __gmp_binary_greater) +__GMP_DEFINE_BINARY_TYPE_FUNCTION(bool, operator>=, ! __gmp_binary_less) + +__GMP_DEFINE_UNARY_FUNCTION(abs, __gmp_abs_function) +__GMP_DEFINE_UNARY_FUNCTION(trunc, __gmp_trunc_function) +__GMP_DEFINE_UNARY_FUNCTION(floor, __gmp_floor_function) +__GMP_DEFINE_UNARY_FUNCTION(ceil, __gmp_ceil_function) +__GMP_DEFINE_UNARY_FUNCTION(sqrt, __gmp_sqrt_function) +__GMP_DEFINE_BINARY_FUNCTION(hypot, __gmp_hypot_function) +__GMP_DEFINE_BINARY_FUNCTION(gcd, __gmp_gcd_function) +__GMP_DEFINE_BINARY_FUNCTION(lcm, __gmp_lcm_function) + +__GMP_DEFINE_UNARY_TYPE_FUNCTION(int, sgn, __gmp_sgn_function) +__GMP_DEFINE_BINARY_TYPE_FUNCTION(int, cmp, __gmp_cmp_function) + +template <class T> +void swap(__gmp_expr<T, T>& x, __gmp_expr<T, T>& y) __GMPXX_NOEXCEPT +{ x.swap(y); } + +// member operators for mpz_class + +__GMPZ_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus) +__GMPZ_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus) +__GMPZ_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies) +__GMPZ_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides) +__GMPZ_DEFINE_COMPOUND_OPERATOR(operator%=, __gmp_binary_modulus) + +__GMPZ_DEFINE_COMPOUND_OPERATOR(operator&=, __gmp_binary_and) +__GMPZ_DEFINE_COMPOUND_OPERATOR(operator|=, __gmp_binary_ior) +__GMPZ_DEFINE_COMPOUND_OPERATOR(operator^=, __gmp_binary_xor) + +__GMPZ_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift) +__GMPZ_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift) + +__GMPZ_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment) +__GMPZ_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement) + +// member operators for mpq_class + +__GMPQ_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus) +__GMPQ_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus) +__GMPQ_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies) +__GMPQ_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides) + +__GMPQ_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift) +__GMPQ_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift) + +__GMPQ_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment) +__GMPQ_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement) + +// member operators for mpf_class + +__GMPF_DEFINE_COMPOUND_OPERATOR(operator+=, __gmp_binary_plus) +__GMPF_DEFINE_COMPOUND_OPERATOR(operator-=, __gmp_binary_minus) +__GMPF_DEFINE_COMPOUND_OPERATOR(operator*=, __gmp_binary_multiplies) +__GMPF_DEFINE_COMPOUND_OPERATOR(operator/=, __gmp_binary_divides) + +__GMPF_DEFINE_COMPOUND_OPERATOR_UI(operator<<=, __gmp_binary_lshift) +__GMPF_DEFINE_COMPOUND_OPERATOR_UI(operator>>=, __gmp_binary_rshift) + +__GMPF_DEFINE_INCREMENT_OPERATOR(operator++, __gmp_unary_increment) +__GMPF_DEFINE_INCREMENT_OPERATOR(operator--, __gmp_unary_decrement) + + + +/**************** Class wrapper for gmp_randstate_t ****************/ + +class __gmp_urandomb_value { }; +class __gmp_urandomm_value { }; + +template <> +class __gmp_expr<mpz_t, __gmp_urandomb_value> +{ +private: + __gmp_randstate_struct *state; + mp_bitcnt_t bits; +public: + __gmp_expr(gmp_randstate_t s, mp_bitcnt_t l) : state(s), bits(l) { } + void eval(mpz_ptr z) const { __gmp_rand_function::eval(z, state, bits); } + mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } +}; + +template <> +class __gmp_expr<mpz_t, __gmp_urandomm_value> +{ +private: + __gmp_randstate_struct *state; + mpz_class range; +public: + __gmp_expr(gmp_randstate_t s, const mpz_class &z) : state(s), range(z) { } + void eval(mpz_ptr z) const + { __gmp_rand_function::eval(z, state, range.get_mpz_t()); } + mp_bitcnt_t get_prec() const { return mpf_get_default_prec(); } +}; + +template <> +class __gmp_expr<mpf_t, __gmp_urandomb_value> +{ +private: + __gmp_randstate_struct *state; + mp_bitcnt_t bits; +public: + __gmp_expr(gmp_randstate_t s, mp_bitcnt_t l) : state(s), bits(l) { } + void eval(mpf_ptr f) const + { + __gmp_rand_function::eval(f, state, + (bits>0) ? bits : mpf_get_prec(f)); + } + mp_bitcnt_t get_prec() const + { + if (bits == 0) + return mpf_get_default_prec(); + else + return bits; + } +}; + +extern "C" { + typedef void __gmp_randinit_default_t (gmp_randstate_t); + typedef void __gmp_randinit_lc_2exp_t (gmp_randstate_t, mpz_srcptr, unsigned long int, mp_bitcnt_t); + typedef int __gmp_randinit_lc_2exp_size_t (gmp_randstate_t, mp_bitcnt_t); +} + +class gmp_randclass +{ +private: + gmp_randstate_t state; + + // copy construction and assignment not allowed + gmp_randclass(const gmp_randclass &); + void operator=(const gmp_randclass &); +public: + // constructors and destructor + gmp_randclass(gmp_randalg_t alg, unsigned long int size) + { + switch (alg) + { + case GMP_RAND_ALG_LC: // no other cases for now + default: + gmp_randinit(state, alg, size); + break; + } + } + + // gmp_randinit_default + gmp_randclass(__gmp_randinit_default_t* f) { f(state); } + + // gmp_randinit_lc_2exp + gmp_randclass(__gmp_randinit_lc_2exp_t* f, + mpz_class z, unsigned long int l1, mp_bitcnt_t l2) + { f(state, z.get_mpz_t(), l1, l2); } + + // gmp_randinit_lc_2exp_size + gmp_randclass(__gmp_randinit_lc_2exp_size_t* f, + mp_bitcnt_t size) + { + if (f (state, size) == 0) + throw std::length_error ("gmp_randinit_lc_2exp_size"); + } + + ~gmp_randclass() { gmp_randclear(state); } + + // initialize + void seed(); // choose a random seed some way (?) + void seed(unsigned long int s) { gmp_randseed_ui(state, s); } + void seed(const mpz_class &z) { gmp_randseed(state, z.get_mpz_t()); } + + // get random number + __gmp_expr<mpz_t, __gmp_urandomb_value> get_z_bits(mp_bitcnt_t l) + { return __gmp_expr<mpz_t, __gmp_urandomb_value>(state, l); } + __gmp_expr<mpz_t, __gmp_urandomb_value> get_z_bits(const mpz_class &z) + { return get_z_bits(z.get_ui()); } + // FIXME: z.get_bitcnt_t() ? + + __gmp_expr<mpz_t, __gmp_urandomm_value> get_z_range(const mpz_class &z) + { return __gmp_expr<mpz_t, __gmp_urandomm_value>(state, z); } + + __gmp_expr<mpf_t, __gmp_urandomb_value> get_f(mp_bitcnt_t prec = 0) + { return __gmp_expr<mpf_t, __gmp_urandomb_value>(state, prec); } +}; + + +/**************** Specialize std::numeric_limits ****************/ + +namespace std { + template <> class numeric_limits<mpz_class> + { + public: + static const bool is_specialized = true; + static mpz_class min() { return mpz_class(); } + static mpz_class max() { return mpz_class(); } + static mpz_class lowest() { return mpz_class(); } + static const int digits = 0; + static const int digits10 = 0; + static const int max_digits10 = 0; + static const bool is_signed = true; + static const bool is_integer = true; + static const bool is_exact = true; + static const int radix = 2; + static mpz_class epsilon() { return mpz_class(); } + static mpz_class round_error() { return mpz_class(); } + static const int min_exponent = 0; + static const int min_exponent10 = 0; + static const int max_exponent = 0; + static const int max_exponent10 = 0; + static const bool has_infinity = false; + static const bool has_quiet_NaN = false; + static const bool has_signaling_NaN = false; + static const float_denorm_style has_denorm = denorm_absent; + static const bool has_denorm_loss = false; + static mpz_class infinity() { return mpz_class(); } + static mpz_class quiet_NaN() { return mpz_class(); } + static mpz_class signaling_NaN() { return mpz_class(); } + static mpz_class denorm_min() { return mpz_class(); } + static const bool is_iec559 = false; + static const bool is_bounded = false; + static const bool is_modulo = false; + static const bool traps = false; + static const bool tinyness_before = false; + static const float_round_style round_style = round_toward_zero; + }; + + template <> class numeric_limits<mpq_class> + { + public: + static const bool is_specialized = true; + static mpq_class min() { return mpq_class(); } + static mpq_class max() { return mpq_class(); } + static mpq_class lowest() { return mpq_class(); } + static const int digits = 0; + static const int digits10 = 0; + static const int max_digits10 = 0; + static const bool is_signed = true; + static const bool is_integer = false; + static const bool is_exact = true; + static const int radix = 2; + static mpq_class epsilon() { return mpq_class(); } + static mpq_class round_error() { return mpq_class(); } + static const int min_exponent = 0; + static const int min_exponent10 = 0; + static const int max_exponent = 0; + static const int max_exponent10 = 0; + static const bool has_infinity = false; + static const bool has_quiet_NaN = false; + static const bool has_signaling_NaN = false; + static const float_denorm_style has_denorm = denorm_absent; + static const bool has_denorm_loss = false; + static mpq_class infinity() { return mpq_class(); } + static mpq_class quiet_NaN() { return mpq_class(); } + static mpq_class signaling_NaN() { return mpq_class(); } + static mpq_class denorm_min() { return mpq_class(); } + static const bool is_iec559 = false; + static const bool is_bounded = false; + static const bool is_modulo = false; + static const bool traps = false; + static const bool tinyness_before = false; + static const float_round_style round_style = round_toward_zero; + }; + + template <> class numeric_limits<mpf_class> + { + public: + static const bool is_specialized = true; + static mpf_class min() { return mpf_class(); } + static mpf_class max() { return mpf_class(); } + static mpf_class lowest() { return mpf_class(); } + static const int digits = 0; + static const int digits10 = 0; + static const int max_digits10 = 0; + static const bool is_signed = true; + static const bool is_integer = false; + static const bool is_exact = false; + static const int radix = 2; + static mpf_class epsilon() { return mpf_class(); } + static mpf_class round_error() { return mpf_class(); } + static const int min_exponent = 0; + static const int min_exponent10 = 0; + static const int max_exponent = 0; + static const int max_exponent10 = 0; + static const bool has_infinity = false; + static const bool has_quiet_NaN = false; + static const bool has_signaling_NaN = false; + static const float_denorm_style has_denorm = denorm_absent; + static const bool has_denorm_loss = false; + static mpf_class infinity() { return mpf_class(); } + static mpf_class quiet_NaN() { return mpf_class(); } + static mpf_class signaling_NaN() { return mpf_class(); } + static mpf_class denorm_min() { return mpf_class(); } + static const bool is_iec559 = false; + static const bool is_bounded = false; + static const bool is_modulo = false; + static const bool traps = false; + static const bool tinyness_before = false; + static const float_round_style round_style = round_indeterminate; + }; +} + + +/**************** #undef all private macros ****************/ + +#undef __GMPP_DECLARE_COMPOUND_OPERATOR +#undef __GMPN_DECLARE_COMPOUND_OPERATOR +#undef __GMP_DECLARE_COMPOUND_OPERATOR +#undef __GMP_DECLARE_COMPOUND_OPERATOR_UI +#undef __GMP_DECLARE_INCREMENT_OPERATOR +#undef __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS +#undef __GMPXX_DEFINE_ARITHMETIC_ASSIGNMENTS + +#undef __GMPZQ_DEFINE_EXPR + +#undef __GMP_DEFINE_UNARY_FUNCTION +#undef __GMP_DEFINE_UNARY_TYPE_FUNCTION + +#undef __GMPP_DEFINE_BINARY_FUNCTION +#undef __GMPNN_DEFINE_BINARY_FUNCTION +#undef __GMPNS_DEFINE_BINARY_FUNCTION +#undef __GMPNU_DEFINE_BINARY_FUNCTION +#undef __GMPND_DEFINE_BINARY_FUNCTION +#undef __GMPNLD_DEFINE_BINARY_FUNCTION +#undef __GMPN_DEFINE_BINARY_FUNCTION +#undef __GMP_DEFINE_BINARY_FUNCTION + +#undef __GMP_DEFINE_BINARY_FUNCTION_UI + +#undef __GMPP_DEFINE_BINARY_TYPE_FUNCTION +#undef __GMPNN_DEFINE_BINARY_TYPE_FUNCTION +#undef __GMPNS_DEFINE_BINARY_TYPE_FUNCTION +#undef __GMPNU_DEFINE_BINARY_TYPE_FUNCTION +#undef __GMPND_DEFINE_BINARY_TYPE_FUNCTION +#undef __GMPNLD_DEFINE_BINARY_TYPE_FUNCTION +#undef __GMPN_DEFINE_BINARY_TYPE_FUNCTION +#undef __GMP_DEFINE_BINARY_TYPE_FUNCTION + +#undef __GMPZ_DEFINE_COMPOUND_OPERATOR + +#undef __GMPP_DEFINE_COMPOUND_OPERATOR +#undef __GMPNN_DEFINE_COMPOUND_OPERATOR +#undef __GMPNS_DEFINE_COMPOUND_OPERATOR +#undef __GMPNU_DEFINE_COMPOUND_OPERATOR +#undef __GMPND_DEFINE_COMPOUND_OPERATOR +#undef __GMPNLD_DEFINE_COMPOUND_OPERATOR +#undef __GMPN_DEFINE_COMPOUND_OPERATOR +#undef __GMP_DEFINE_COMPOUND_OPERATOR + +#undef __GMPQ_DEFINE_COMPOUND_OPERATOR +#undef __GMPF_DEFINE_COMPOUND_OPERATOR + +#undef __GMP_DEFINE_COMPOUND_OPERATOR_UI +#undef __GMPZ_DEFINE_COMPOUND_OPERATOR_UI +#undef __GMPQ_DEFINE_COMPOUND_OPERATOR_UI +#undef __GMPF_DEFINE_COMPOUND_OPERATOR_UI + +#undef __GMP_DEFINE_INCREMENT_OPERATOR +#undef __GMPZ_DEFINE_INCREMENT_OPERATOR +#undef __GMPQ_DEFINE_INCREMENT_OPERATOR +#undef __GMPF_DEFINE_INCREMENT_OPERATOR + +#undef __GMPXX_CONSTANT_TRUE +#undef __GMPXX_CONSTANT + +#endif /* __GMP_PLUSPLUS__ */ diff --git a/examples/multiprecision/bench-include/longlong.h b/examples/multiprecision/bench-include/longlong.h new file mode 100644 index 0000000000000000000000000000000000000000..96de94042109aa73bbd9cdb48807d58871d284bb --- /dev/null +++ b/examples/multiprecision/bench-include/longlong.h @@ -0,0 +1,2218 @@ +/* longlong.h -- definitions for mixed size 32/64 bit arithmetic. + +Copyright 1991-1994, 1996, 1997, 1999-2005, 2007-2009, 2011-2016 Free Software +Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + +or + + * the GNU General Public License as published by the Free Software + Foundation; either version 2 of the License, or (at your option) any + later version. + +or both in parallel, as here. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received copies of the GNU General Public License and the +GNU Lesser General Public License along with the GNU MP Library. If not, +see https://www.gnu.org/licenses/. */ + +/* You have to define the following before including this file: + + UWtype -- An unsigned type, default type for operations (typically a "word") + UHWtype -- An unsigned type, at least half the size of UWtype + UDWtype -- An unsigned type, at least twice as large a UWtype + W_TYPE_SIZE -- size in bits of UWtype + + SItype, USItype -- Signed and unsigned 32 bit types + DItype, UDItype -- Signed and unsigned 64 bit types + + On a 32 bit machine UWtype should typically be USItype; + on a 64 bit machine, UWtype should typically be UDItype. + + Optionally, define: + + LONGLONG_STANDALONE -- Avoid code that needs machine-dependent support files + NO_ASM -- Disable inline asm + + + CAUTION! Using this version of longlong.h outside of GMP is not safe. You + need to include gmp.h and gmp-impl.h, or certain things might not work as + expected. +*/ + +#define __BITS4 (W_TYPE_SIZE / 4) +#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2)) +#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1)) +#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2)) + +/* This is used to make sure no undesirable sharing between different libraries + that use this file takes place. */ +#ifndef __MPN +#define __MPN(x) __##x +#endif + +/* Define auxiliary asm macros. + + 1) umul_ppmm(high_prod, low_prod, multiplier, multiplicand) multiplies two + UWtype integers MULTIPLIER and MULTIPLICAND, and generates a two UWtype + word product in HIGH_PROD and LOW_PROD. + + 2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a + UDWtype product. This is just a variant of umul_ppmm. + + 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator) divides a UDWtype, composed by the UWtype integers + HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient + in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less + than DENOMINATOR for correct operation. If, in addition, the most + significant bit of DENOMINATOR must be 1, then the pre-processor symbol + UDIV_NEEDS_NORMALIZATION is defined to 1. + + 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator). Like udiv_qrnnd but the numbers are signed. The quotient + is rounded towards 0. + + 5) count_leading_zeros(count, x) counts the number of zero-bits from the + msb to the first non-zero bit in the UWtype X. This is the number of + steps X needs to be shifted left to set the msb. Undefined for X == 0, + unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value. + + 6) count_trailing_zeros(count, x) like count_leading_zeros, but counts + from the least significant end. + + 7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1, + high_addend_2, low_addend_2) adds two UWtype integers, composed by + HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2 + respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow + (i.e. carry out) is not stored anywhere, and is lost. + + 8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend, + high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers, + composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and + LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE + and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere, + and is lost. + + If any of these macros are left undefined for a particular CPU, + C macros are used. + + + Notes: + + For add_ssaaaa the two high and two low addends can both commute, but + unfortunately gcc only supports one "%" commutative in each asm block. + This has always been so but is only documented in recent versions + (eg. pre-release 3.3). Having two or more "%"s can cause an internal + compiler error in certain rare circumstances. + + Apparently it was only the last "%" that was ever actually respected, so + the code has been updated to leave just that. Clearly there's a free + choice whether high or low should get it, if there's a reason to favour + one over the other. Also obviously when the constraints on the two + operands are identical there's no benefit to the reloader in any "%" at + all. + + */ + +/* The CPUs come in alphabetical order below. + + Please add support for more CPUs here, or improve the current support + for the CPUs below! */ + + +/* count_leading_zeros_gcc_clz is count_leading_zeros implemented with gcc + 3.4 __builtin_clzl or __builtin_clzll, according to our limb size. + Similarly count_trailing_zeros_gcc_ctz using __builtin_ctzl or + __builtin_ctzll. + + These builtins are only used when we check what code comes out, on some + chips they're merely libgcc calls, where we will instead want an inline + in that case (either asm or generic C). + + These builtins are better than an asm block of the same insn, since an + asm block doesn't give gcc any information about scheduling or resource + usage. We keep an asm block for use on prior versions of gcc though. + + For reference, __builtin_ffs existed in gcc prior to __builtin_clz, but + it's not used (for count_leading_zeros) because it generally gives extra + code to ensure the result is 0 when the input is 0, which we don't need + or want. */ + +#ifdef _LONG_LONG_LIMB +#define count_leading_zeros_gcc_clz(count,x) \ + do { \ + ASSERT ((x) != 0); \ + (count) = __builtin_clzll (x); \ + } while (0) +#else +#define count_leading_zeros_gcc_clz(count,x) \ + do { \ + ASSERT ((x) != 0); \ + (count) = __builtin_clzl (x); \ + } while (0) +#endif + +#ifdef _LONG_LONG_LIMB +#define count_trailing_zeros_gcc_ctz(count,x) \ + do { \ + ASSERT ((x) != 0); \ + (count) = __builtin_ctzll (x); \ + } while (0) +#else +#define count_trailing_zeros_gcc_ctz(count,x) \ + do { \ + ASSERT ((x) != 0); \ + (count) = __builtin_ctzl (x); \ + } while (0) +#endif + + +/* FIXME: The macros using external routines like __MPN(count_leading_zeros) + don't need to be under !NO_ASM */ +#if ! defined (NO_ASM) + +#if defined (__alpha) && W_TYPE_SIZE == 64 +/* Most alpha-based machines, except Cray systems. */ +#if defined (__GNUC__) +#if __GMP_GNUC_PREREQ (3,3) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDItype __m0 = (m0), __m1 = (m1); \ + (ph) = __builtin_alpha_umulh (__m0, __m1); \ + (pl) = __m0 * __m1; \ + } while (0) +#else +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("umulh %r1,%2,%0" \ + : "=r" (ph) \ + : "%rJ" (__m0), "rI" (__m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#endif +#define UMUL_TIME 18 +#else /* ! __GNUC__ */ +#include <machine/builtins.h> +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDItype __m0 = (m0), __m1 = (m1); \ + (ph) = __UMULH (__m0, __m1); \ + (pl) = __m0 * __m1; \ + } while (0) +#endif +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { UWtype __di; \ + __di = __MPN(invert_limb) (d); \ + udiv_qrnnd_preinv (q, r, n1, n0, d, __di); \ + } while (0) +#define UDIV_PREINV_ALWAYS 1 +#define UDIV_NEEDS_NORMALIZATION 1 +#define UDIV_TIME 220 +#endif /* LONGLONG_STANDALONE */ + +/* clz_tab is required in all configurations, since mpn/alpha/cntlz.asm + always goes into libgmp.so, even when not actually used. */ +#define COUNT_LEADING_ZEROS_NEED_CLZ_TAB + +#if defined (__GNUC__) && HAVE_HOST_CPU_alpha_CIX +#define count_leading_zeros(COUNT,X) \ + __asm__("ctlz %1,%0" : "=r"(COUNT) : "r"(X)) +#define count_trailing_zeros(COUNT,X) \ + __asm__("cttz %1,%0" : "=r"(COUNT) : "r"(X)) +#endif /* clz/ctz using cix */ + +#if ! defined (count_leading_zeros) \ + && defined (__GNUC__) && ! defined (LONGLONG_STANDALONE) +/* ALPHA_CMPBGE_0 gives "cmpbge $31,src,dst", ie. test src bytes == 0. + "$31" is written explicitly in the asm, since an "r" constraint won't + select reg 31. There seems no need to worry about "r31" syntax for cray, + since gcc itself (pre-release 3.4) emits just $31 in various places. */ +#define ALPHA_CMPBGE_0(dst, src) \ + do { asm ("cmpbge $31, %1, %0" : "=r" (dst) : "r" (src)); } while (0) +/* Zero bytes are turned into bits with cmpbge, a __clz_tab lookup counts + them, locating the highest non-zero byte. A second __clz_tab lookup + counts the leading zero bits in that byte, giving the result. */ +#define count_leading_zeros(count, x) \ + do { \ + UWtype __clz__b, __clz__c, __clz__x = (x); \ + ALPHA_CMPBGE_0 (__clz__b, __clz__x); /* zero bytes */ \ + __clz__b = __clz_tab [(__clz__b >> 1) ^ 0x7F]; /* 8 to 1 byte */ \ + __clz__b = __clz__b * 8 - 7; /* 57 to 1 shift */ \ + __clz__x >>= __clz__b; \ + __clz__c = __clz_tab [__clz__x]; /* 8 to 1 bit */ \ + __clz__b = 65 - __clz__b; \ + (count) = __clz__b - __clz__c; \ + } while (0) +#define COUNT_LEADING_ZEROS_NEED_CLZ_TAB +#endif /* clz using cmpbge */ + +#if ! defined (count_leading_zeros) && ! defined (LONGLONG_STANDALONE) +#if HAVE_ATTRIBUTE_CONST +long __MPN(count_leading_zeros) (UDItype) __attribute__ ((const)); +#else +long __MPN(count_leading_zeros) (UDItype); +#endif +#define count_leading_zeros(count, x) \ + ((count) = __MPN(count_leading_zeros) (x)) +#endif /* clz using mpn */ +#endif /* __alpha */ + +#if defined (__AVR) && W_TYPE_SIZE == 8 +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + unsigned short __p = (unsigned short) (m0) * (m1); \ + (ph) = __p >> 8; \ + (pl) = __p; \ + } while (0) +#endif /* AVR */ + +#if defined (_CRAY) && W_TYPE_SIZE == 64 +#include <intrinsics.h> +#define UDIV_PREINV_ALWAYS 1 +#define UDIV_NEEDS_NORMALIZATION 1 +#define UDIV_TIME 220 +long __MPN(count_leading_zeros) (UDItype); +#define count_leading_zeros(count, x) \ + ((count) = _leadz ((UWtype) (x))) +#if defined (_CRAYIEEE) /* I.e., Cray T90/ieee, T3D, and T3E */ +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDItype __m0 = (m0), __m1 = (m1); \ + (ph) = _int_mult_upper (__m0, __m1); \ + (pl) = __m0 * __m1; \ + } while (0) +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { UWtype __di; \ + __di = __MPN(invert_limb) (d); \ + udiv_qrnnd_preinv (q, r, n1, n0, d, __di); \ + } while (0) +#endif /* LONGLONG_STANDALONE */ +#endif /* _CRAYIEEE */ +#endif /* _CRAY */ + +#if defined (__ia64) && W_TYPE_SIZE == 64 +/* This form encourages gcc (pre-release 3.4 at least) to emit predicated + "sub r=r,r" and "sub r=r,r,1", giving a 2 cycle latency. The generic + code using "al<bl" arithmetically comes out making an actual 0 or 1 in a + register, which takes an extra cycle. */ +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) - (bl); \ + if ((al) < (bl)) \ + (sh) = (ah) - (bh) - 1; \ + else \ + (sh) = (ah) - (bh); \ + (sl) = __x; \ + } while (0) +#if defined (__GNUC__) && ! defined (__INTEL_COMPILER) +/* Do both product parts in assembly, since that gives better code with + all gcc versions. Some callers will just use the upper part, and in + that situation we waste an instruction, but not any cycles. */ +#define umul_ppmm(ph, pl, m0, m1) \ + __asm__ ("xma.hu %0 = %2, %3, f0\n\txma.l %1 = %2, %3, f0" \ + : "=&f" (ph), "=f" (pl) \ + : "f" (m0), "f" (m1)) +#define UMUL_TIME 14 +#define count_leading_zeros(count, x) \ + do { \ + UWtype _x = (x), _y, _a, _c; \ + __asm__ ("mux1 %0 = %1, @rev" : "=r" (_y) : "r" (_x)); \ + __asm__ ("czx1.l %0 = %1" : "=r" (_a) : "r" (-_y | _y)); \ + _c = (_a - 1) << 3; \ + _x >>= _c; \ + if (_x >= 1 << 4) \ + _x >>= 4, _c += 4; \ + if (_x >= 1 << 2) \ + _x >>= 2, _c += 2; \ + _c += _x >> 1; \ + (count) = W_TYPE_SIZE - 1 - _c; \ + } while (0) +/* similar to what gcc does for __builtin_ffs, but 0 based rather than 1 + based, and we don't need a special case for x==0 here */ +#define count_trailing_zeros(count, x) \ + do { \ + UWtype __ctz_x = (x); \ + __asm__ ("popcnt %0 = %1" \ + : "=r" (count) \ + : "r" ((__ctz_x-1) & ~__ctz_x)); \ + } while (0) +#endif +#if defined (__INTEL_COMPILER) +#include <ia64intrin.h> +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UWtype __m0 = (m0), __m1 = (m1); \ + ph = _m64_xmahu (__m0, __m1, 0); \ + pl = __m0 * __m1; \ + } while (0) +#endif +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { UWtype __di; \ + __di = __MPN(invert_limb) (d); \ + udiv_qrnnd_preinv (q, r, n1, n0, d, __di); \ + } while (0) +#define UDIV_PREINV_ALWAYS 1 +#define UDIV_NEEDS_NORMALIZATION 1 +#endif +#define UDIV_TIME 220 +#endif + + +#if defined (__GNUC__) + +/* We sometimes need to clobber "cc" with gcc2, but that would not be + understood by gcc1. Use cpp to avoid major code duplication. */ +#if __GNUC__ < 2 +#define __CLOBBER_CC +#define __AND_CLOBBER_CC +#else /* __GNUC__ >= 2 */ +#define __CLOBBER_CC : "cc" +#define __AND_CLOBBER_CC , "cc" +#endif /* __GNUC__ < 2 */ + +#if (defined (__a29k__) || defined (_AM29K)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add %1,%4,%5\n\taddc %0,%2,%3" \ + : "=r" (sh), "=&r" (sl) \ + : "r" (ah), "rI" (bh), "%r" (al), "rI" (bl)) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub %1,%4,%5\n\tsubc %0,%2,%3" \ + : "=r" (sh), "=&r" (sl) \ + : "r" (ah), "rI" (bh), "r" (al), "rI" (bl)) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("multiplu %0,%1,%2" \ + : "=r" (xl) \ + : "r" (__m0), "r" (__m1)); \ + __asm__ ("multmu %0,%1,%2" \ + : "=r" (xh) \ + : "r" (__m0), "r" (__m1)); \ + } while (0) +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("dividu %0,%3,%4" \ + : "=r" (q), "=q" (r) \ + : "1" (n1), "r" (n0), "r" (d)) +#define count_leading_zeros(count, x) \ + __asm__ ("clz %0,%1" \ + : "=r" (count) \ + : "r" (x)) +#define COUNT_LEADING_ZEROS_0 32 +#endif /* __a29k__ */ + +#if defined (__arc__) +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add.f\t%1, %4, %5\n\tadc\t%0, %2, %3" \ + : "=r" (sh), \ + "=&r" (sl) \ + : "r" ((USItype) (ah)), \ + "rICal" ((USItype) (bh)), \ + "%r" ((USItype) (al)), \ + "rICal" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub.f\t%1, %4, %5\n\tsbc\t%0, %2, %3" \ + : "=r" (sh), \ + "=&r" (sl) \ + : "r" ((USItype) (ah)), \ + "rICal" ((USItype) (bh)), \ + "r" ((USItype) (al)), \ + "rICal" ((USItype) (bl))) +#endif + +#if defined (__arm__) && (defined (__thumb2__) || !defined (__thumb__)) \ + && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("adds\t%1, %4, %5\n\tadc\t%0, %2, %3" \ + : "=r" (sh), "=&r" (sl) \ + : "r" (ah), "rI" (bh), "%r" (al), "rI" (bl) __CLOBBER_CC) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (al)) \ + { \ + if (__builtin_constant_p (ah)) \ + __asm__ ("rsbs\t%1, %5, %4\n\trsc\t%0, %3, %2" \ + : "=r" (sh), "=&r" (sl) \ + : "rI" (ah), "r" (bh), "rI" (al), "r" (bl) __CLOBBER_CC); \ + else \ + __asm__ ("rsbs\t%1, %5, %4\n\tsbc\t%0, %2, %3" \ + : "=r" (sh), "=&r" (sl) \ + : "r" (ah), "rI" (bh), "rI" (al), "r" (bl) __CLOBBER_CC); \ + } \ + else if (__builtin_constant_p (ah)) \ + { \ + if (__builtin_constant_p (bl)) \ + __asm__ ("subs\t%1, %4, %5\n\trsc\t%0, %3, %2" \ + : "=r" (sh), "=&r" (sl) \ + : "rI" (ah), "r" (bh), "r" (al), "rI" (bl) __CLOBBER_CC); \ + else \ + __asm__ ("rsbs\t%1, %5, %4\n\trsc\t%0, %3, %2" \ + : "=r" (sh), "=&r" (sl) \ + : "rI" (ah), "r" (bh), "rI" (al), "r" (bl) __CLOBBER_CC); \ + } \ + else if (__builtin_constant_p (bl)) \ + { \ + if (__builtin_constant_p (bh)) \ + __asm__ ("subs\t%1, %4, %5\n\tsbc\t%0, %2, %3" \ + : "=r" (sh), "=&r" (sl) \ + : "r" (ah), "rI" (bh), "r" (al), "rI" (bl) __CLOBBER_CC); \ + else \ + __asm__ ("subs\t%1, %4, %5\n\trsc\t%0, %3, %2" \ + : "=r" (sh), "=&r" (sl) \ + : "rI" (ah), "r" (bh), "r" (al), "rI" (bl) __CLOBBER_CC); \ + } \ + else /* only bh might be a constant */ \ + __asm__ ("subs\t%1, %4, %5\n\tsbc\t%0, %2, %3" \ + : "=r" (sh), "=&r" (sl) \ + : "r" (ah), "rI" (bh), "r" (al), "rI" (bl) __CLOBBER_CC);\ + } while (0) +#if defined (__ARM_ARCH_2__) || defined (__ARM_ARCH_2A__) \ + || defined (__ARM_ARCH_3__) +#define umul_ppmm(xh, xl, a, b) \ + do { \ + register USItype __t0, __t1, __t2; \ + __asm__ ("%@ Inlined umul_ppmm\n" \ + " mov %2, %5, lsr #16\n" \ + " mov %0, %6, lsr #16\n" \ + " bic %3, %5, %2, lsl #16\n" \ + " bic %4, %6, %0, lsl #16\n" \ + " mul %1, %3, %4\n" \ + " mul %4, %2, %4\n" \ + " mul %3, %0, %3\n" \ + " mul %0, %2, %0\n" \ + " adds %3, %4, %3\n" \ + " addcs %0, %0, #65536\n" \ + " adds %1, %1, %3, lsl #16\n" \ + " adc %0, %0, %3, lsr #16" \ + : "=&r" ((USItype) (xh)), "=r" ((USItype) (xl)), \ + "=&r" (__t0), "=&r" (__t1), "=r" (__t2) \ + : "r" ((USItype) (a)), "r" ((USItype) (b)) __CLOBBER_CC); \ + } while (0) +#define UMUL_TIME 20 +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { UWtype __r; \ + (q) = __MPN(udiv_qrnnd) (&__r, (n1), (n0), (d)); \ + (r) = __r; \ + } while (0) +extern UWtype __MPN(udiv_qrnnd) (UWtype *, UWtype, UWtype, UWtype); +#define UDIV_TIME 200 +#endif /* LONGLONG_STANDALONE */ +#else /* ARMv4 or newer */ +#define umul_ppmm(xh, xl, a, b) \ + __asm__ ("umull %0,%1,%2,%3" : "=&r" (xl), "=&r" (xh) : "r" (a), "r" (b)) +#define UMUL_TIME 5 +#define smul_ppmm(xh, xl, a, b) \ + __asm__ ("smull %0,%1,%2,%3" : "=&r" (xl), "=&r" (xh) : "r" (a), "r" (b)) +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { UWtype __di; \ + __di = __MPN(invert_limb) (d); \ + udiv_qrnnd_preinv (q, r, n1, n0, d, __di); \ + } while (0) +#define UDIV_PREINV_ALWAYS 1 +#define UDIV_NEEDS_NORMALIZATION 1 +#define UDIV_TIME 70 +#endif /* LONGLONG_STANDALONE */ +#endif /* defined(__ARM_ARCH_2__) ... */ +#define count_leading_zeros(count, x) count_leading_zeros_gcc_clz(count, x) +#define count_trailing_zeros(count, x) count_trailing_zeros_gcc_ctz(count, x) +#define COUNT_LEADING_ZEROS_0 32 +#endif /* __arm__ */ + +#if defined (__aarch64__) && W_TYPE_SIZE == 64 +/* FIXME: Extend the immediate range for the low word by using both + ADDS and SUBS, since they set carry in the same way. */ +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("adds\t%1, %x4, %5\n\tadc\t%0, %x2, %x3" \ + : "=r" (sh), "=&r" (sl) \ + : "rZ" ((UDItype)(ah)), "rZ" ((UDItype)(bh)), \ + "%r" ((UDItype)(al)), "rI" ((UDItype)(bl)) __CLOBBER_CC) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subs\t%1, %x4, %5\n\tsbc\t%0, %x2, %x3" \ + : "=r,r" (sh), "=&r,&r" (sl) \ + : "rZ,rZ" ((UDItype)(ah)), "rZ,rZ" ((UDItype)(bh)), \ + "r,Z" ((UDItype)(al)), "rI,r" ((UDItype)(bl)) __CLOBBER_CC) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("umulh\t%0, %1, %2" : "=r" (ph) : "r" (__m0), "r" (__m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define count_leading_zeros(count, x) count_leading_zeros_gcc_clz(count, x) +#define count_trailing_zeros(count, x) count_trailing_zeros_gcc_ctz(count, x) +#define COUNT_LEADING_ZEROS_0 64 +#endif /* __aarch64__ */ + +#if defined (__clipper__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __x; \ + __asm__ ("mulwux %2,%0" \ + : "=r" (__x.__ll) \ + : "%0" ((USItype)(u)), "r" ((USItype)(v))); \ + (w1) = __x.__i.__h; (w0) = __x.__i.__l;}) +#define smul_ppmm(w1, w0, u, v) \ + ({union {DItype __ll; \ + struct {SItype __l, __h;} __i; \ + } __x; \ + __asm__ ("mulwx %2,%0" \ + : "=r" (__x.__ll) \ + : "%0" ((SItype)(u)), "r" ((SItype)(v))); \ + (w1) = __x.__i.__h; (w0) = __x.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("mulwux %2,%0" \ + : "=r" (__w) : "%0" ((USItype)(u)), "r" ((USItype)(v))); \ + __w; }) +#endif /* __clipper__ */ + +/* Fujitsu vector computers. */ +#if defined (__uxp__) && W_TYPE_SIZE == 32 +#define umul_ppmm(ph, pl, u, v) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __x; \ + __asm__ ("mult.lu %1,%2,%0" : "=r" (__x.__ll) : "%r" (u), "rK" (v));\ + (ph) = __x.__i.__h; \ + (pl) = __x.__i.__l; \ + } while (0) +#define smul_ppmm(ph, pl, u, v) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __x; \ + __asm__ ("mult.l %1,%2,%0" : "=r" (__x.__ll) : "%r" (u), "rK" (v)); \ + (ph) = __x.__i.__h; \ + (pl) = __x.__i.__l; \ + } while (0) +#endif + +#if defined (__gmicro__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add.w %5,%1\n\taddx %3,%0" \ + : "=g" (sh), "=&g" (sl) \ + : "0" ((USItype)(ah)), "g" ((USItype)(bh)), \ + "%1" ((USItype)(al)), "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub.w %5,%1\n\tsubx %3,%0" \ + : "=g" (sh), "=&g" (sl) \ + : "0" ((USItype)(ah)), "g" ((USItype)(bh)), \ + "1" ((USItype)(al)), "g" ((USItype)(bl))) +#define umul_ppmm(ph, pl, m0, m1) \ + __asm__ ("mulx %3,%0,%1" \ + : "=g" (ph), "=r" (pl) \ + : "%0" ((USItype)(m0)), "g" ((USItype)(m1))) +#define udiv_qrnnd(q, r, nh, nl, d) \ + __asm__ ("divx %4,%0,%1" \ + : "=g" (q), "=r" (r) \ + : "1" ((USItype)(nh)), "0" ((USItype)(nl)), "g" ((USItype)(d))) +#define count_leading_zeros(count, x) \ + __asm__ ("bsch/1 %1,%0" \ + : "=g" (count) : "g" ((USItype)(x)), "0" ((USItype)0)) +#endif + +#if defined (__hppa) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add%I5 %5,%r4,%1\n\taddc %r2,%r3,%0" \ + : "=r" (sh), "=&r" (sl) \ + : "rM" (ah), "rM" (bh), "%rM" (al), "rI" (bl)) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub%I4 %4,%r5,%1\n\tsubb %r2,%r3,%0" \ + : "=r" (sh), "=&r" (sl) \ + : "rM" (ah), "rM" (bh), "rI" (al), "rM" (bl)) +#if defined (_PA_RISC1_1) +#define umul_ppmm(wh, wl, u, v) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __x; \ + __asm__ ("xmpyu %1,%2,%0" : "=*f" (__x.__ll) : "*f" (u), "*f" (v)); \ + (wh) = __x.__i.__h; \ + (wl) = __x.__i.__l; \ + } while (0) +#define UMUL_TIME 8 +#define UDIV_TIME 60 +#else +#define UMUL_TIME 40 +#define UDIV_TIME 80 +#endif +#define count_leading_zeros(count, x) \ + do { \ + USItype __tmp; \ + __asm__ ( \ + "ldi 1,%0\n" \ +" extru,= %1,15,16,%%r0 ; Bits 31..16 zero?\n" \ +" extru,tr %1,15,16,%1 ; No. Shift down, skip add.\n" \ +" ldo 16(%0),%0 ; Yes. Perform add.\n" \ +" extru,= %1,23,8,%%r0 ; Bits 15..8 zero?\n" \ +" extru,tr %1,23,8,%1 ; No. Shift down, skip add.\n" \ +" ldo 8(%0),%0 ; Yes. Perform add.\n" \ +" extru,= %1,27,4,%%r0 ; Bits 7..4 zero?\n" \ +" extru,tr %1,27,4,%1 ; No. Shift down, skip add.\n" \ +" ldo 4(%0),%0 ; Yes. Perform add.\n" \ +" extru,= %1,29,2,%%r0 ; Bits 3..2 zero?\n" \ +" extru,tr %1,29,2,%1 ; No. Shift down, skip add.\n" \ +" ldo 2(%0),%0 ; Yes. Perform add.\n" \ +" extru %1,30,1,%1 ; Extract bit 1.\n" \ +" sub %0,%1,%0 ; Subtract it.\n" \ + : "=r" (count), "=r" (__tmp) : "1" (x)); \ + } while (0) +#endif /* hppa */ + +/* These macros are for ABI=2.0w. In ABI=2.0n they can't be used, since GCC + (3.2) puts longlong into two adjacent 32-bit registers. Presumably this + is just a case of no direct support for 2.0n but treating it like 1.0. */ +#if defined (__hppa) && W_TYPE_SIZE == 64 && ! defined (_LONG_LONG_LIMB) +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add%I5 %5,%r4,%1\n\tadd,dc %r2,%r3,%0" \ + : "=r" (sh), "=&r" (sl) \ + : "rM" (ah), "rM" (bh), "%rM" (al), "rI" (bl)) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub%I4 %4,%r5,%1\n\tsub,db %r2,%r3,%0" \ + : "=r" (sh), "=&r" (sl) \ + : "rM" (ah), "rM" (bh), "rI" (al), "rM" (bl)) +#endif /* hppa */ + +#if (defined (__i370__) || defined (__s390__) || defined (__mvs__)) && W_TYPE_SIZE == 32 +#if defined (__zarch__) || defined (HAVE_HOST_CPU_s390_zarch) +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ +/* if (__builtin_constant_p (bl)) \ + __asm__ ("alfi\t%1,%o5\n\talcr\t%0,%3" \ + : "=r" (sh), "=&r" (sl) \ + : "0" (ah), "r" (bh), "%1" (al), "n" (bl) __CLOBBER_CC);\ + else \ +*/ __asm__ ("alr\t%1,%5\n\talcr\t%0,%3" \ + : "=r" (sh), "=&r" (sl) \ + : "0" (ah), "r" (bh), "%1" (al), "r" (bl)__CLOBBER_CC); \ + } while (0) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ +/* if (__builtin_constant_p (bl)) \ + __asm__ ("slfi\t%1,%o5\n\tslbr\t%0,%3" \ + : "=r" (sh), "=&r" (sl) \ + : "0" (ah), "r" (bh), "1" (al), "n" (bl) __CLOBBER_CC); \ + else \ +*/ __asm__ ("slr\t%1,%5\n\tslbr\t%0,%3" \ + : "=r" (sh), "=&r" (sl) \ + : "0" (ah), "r" (bh), "1" (al), "r" (bl) __CLOBBER_CC); \ + } while (0) +#if __GMP_GNUC_PREREQ (4,5) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __x; \ + __x.__ll = (UDItype) (m0) * (UDItype) (m1); \ + (xh) = __x.__i.__h; (xl) = __x.__i.__l; \ + } while (0) +#else +#if 0 +/* FIXME: this fails if gcc knows about the 64-bit registers. Use only + with a new enough processor pretending we have 32-bit registers. */ +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __x; \ + __asm__ ("mlr\t%0,%2" \ + : "=r" (__x.__ll) \ + : "%0" (m0), "r" (m1)); \ + (xh) = __x.__i.__h; (xl) = __x.__i.__l; \ + } while (0) +#else +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + /* When we have 64-bit regs and gcc is aware of that, we cannot simply use + DImode for the product, since that would be allocated to a single 64-bit + register, whereas mlr uses the low 32-bits of an even-odd register pair. + */ \ + register USItype __r0 __asm__ ("0"); \ + register USItype __r1 __asm__ ("1") = (m0); \ + __asm__ ("mlr\t%0,%3" \ + : "=r" (__r0), "=r" (__r1) \ + : "r" (__r1), "r" (m1)); \ + (xh) = __r0; (xl) = __r1; \ + } while (0) +#endif /* if 0 */ +#endif +#if 0 +/* FIXME: this fails if gcc knows about the 64-bit registers. Use only + with a new enough processor pretending we have 32-bit registers. */ +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __x; \ + __x.__i.__h = n1; __x.__i.__l = n0; \ + __asm__ ("dlr\t%0,%2" \ + : "=r" (__x.__ll) \ + : "0" (__x.__ll), "r" (d)); \ + (q) = __x.__i.__l; (r) = __x.__i.__h; \ + } while (0) +#else +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { \ + register USItype __r0 __asm__ ("0") = (n1); \ + register USItype __r1 __asm__ ("1") = (n0); \ + __asm__ ("dlr\t%0,%4" \ + : "=r" (__r0), "=r" (__r1) \ + : "r" (__r0), "r" (__r1), "r" (d)); \ + (q) = __r1; (r) = __r0; \ + } while (0) +#endif /* if 0 */ +#else /* if __zarch__ */ +/* FIXME: this fails if gcc knows about the 64-bit registers. */ +#define smul_ppmm(xh, xl, m0, m1) \ + do { \ + union {DItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __x; \ + __asm__ ("mr\t%0,%2" \ + : "=r" (__x.__ll) \ + : "%0" (m0), "r" (m1)); \ + (xh) = __x.__i.__h; (xl) = __x.__i.__l; \ + } while (0) +/* FIXME: this fails if gcc knows about the 64-bit registers. */ +#define sdiv_qrnnd(q, r, n1, n0, d) \ + do { \ + union {DItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __x; \ + __x.__i.__h = n1; __x.__i.__l = n0; \ + __asm__ ("dr\t%0,%2" \ + : "=r" (__x.__ll) \ + : "0" (__x.__ll), "r" (d)); \ + (q) = __x.__i.__l; (r) = __x.__i.__h; \ + } while (0) +#endif /* if __zarch__ */ +#endif + +#if defined (__s390x__) && W_TYPE_SIZE == 64 +/* We need to cast operands with register constraints, otherwise their types + will be assumed to be SImode by gcc. For these machines, such operations + will insert a value into the low 32 bits, and leave the high 32 bits with + garbage. */ +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + __asm__ ("algr\t%1,%5\n\talcgr\t%0,%3" \ + : "=r" (sh), "=&r" (sl) \ + : "0" ((UDItype)(ah)), "r" ((UDItype)(bh)), \ + "%1" ((UDItype)(al)), "r" ((UDItype)(bl)) __CLOBBER_CC); \ + } while (0) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + __asm__ ("slgr\t%1,%5\n\tslbgr\t%0,%3" \ + : "=r" (sh), "=&r" (sl) \ + : "0" ((UDItype)(ah)), "r" ((UDItype)(bh)), \ + "1" ((UDItype)(al)), "r" ((UDItype)(bl)) __CLOBBER_CC); \ + } while (0) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {unsigned int __attribute__ ((mode(TI))) __ll; \ + struct {UDItype __h, __l;} __i; \ + } __x; \ + __asm__ ("mlgr\t%0,%2" \ + : "=r" (__x.__ll) \ + : "%0" ((UDItype)(m0)), "r" ((UDItype)(m1))); \ + (xh) = __x.__i.__h; (xl) = __x.__i.__l; \ + } while (0) +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { \ + union {unsigned int __attribute__ ((mode(TI))) __ll; \ + struct {UDItype __h, __l;} __i; \ + } __x; \ + __x.__i.__h = n1; __x.__i.__l = n0; \ + __asm__ ("dlgr\t%0,%2" \ + : "=r" (__x.__ll) \ + : "0" (__x.__ll), "r" ((UDItype)(d))); \ + (q) = __x.__i.__l; (r) = __x.__i.__h; \ + } while (0) +#if 0 /* FIXME: Enable for z10 (?) */ +#define count_leading_zeros(cnt, x) \ + do { \ + union {unsigned int __attribute__ ((mode(TI))) __ll; \ + struct {UDItype __h, __l;} __i; \ + } __clr_cnt; \ + __asm__ ("flogr\t%0,%1" \ + : "=r" (__clr_cnt.__ll) \ + : "r" (x) __CLOBBER_CC); \ + (cnt) = __clr_cnt.__i.__h; \ + } while (0) +#endif +#endif + +/* On x86 and x86_64, every asm implicitly clobbers "flags" and "fpsr", + so we don't need __CLOBBER_CC. */ +#if (defined (__i386__) || defined (__i486__)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addl %5,%k1\n\tadcl %3,%k0" \ + : "=r" (sh), "=&r" (sl) \ + : "0" ((USItype)(ah)), "g" ((USItype)(bh)), \ + "%1" ((USItype)(al)), "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subl %5,%k1\n\tsbbl %3,%k0" \ + : "=r" (sh), "=&r" (sl) \ + : "0" ((USItype)(ah)), "g" ((USItype)(bh)), \ + "1" ((USItype)(al)), "g" ((USItype)(bl))) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mull %3" \ + : "=a" (w0), "=d" (w1) \ + : "%0" ((USItype)(u)), "rm" ((USItype)(v))) +#define udiv_qrnnd(q, r, n1, n0, dx) /* d renamed to dx avoiding "=d" */\ + __asm__ ("divl %4" /* stringification in K&R C */ \ + : "=a" (q), "=d" (r) \ + : "0" ((USItype)(n0)), "1" ((USItype)(n1)), "rm" ((USItype)(dx))) + +#if HAVE_HOST_CPU_i586 || HAVE_HOST_CPU_pentium || HAVE_HOST_CPU_pentiummmx +/* Pentium bsrl takes between 10 and 72 cycles depending where the most + significant 1 bit is, hence the use of the following alternatives. bsfl + is slow too, between 18 and 42 depending where the least significant 1 + bit is, so let the generic count_trailing_zeros below make use of the + count_leading_zeros here too. */ + +#if HAVE_HOST_CPU_pentiummmx && ! defined (LONGLONG_STANDALONE) +/* The following should be a fixed 14 or 15 cycles, but possibly plus an L1 + cache miss reading from __clz_tab. For P55 it's favoured over the float + below so as to avoid mixing MMX and x87, since the penalty for switching + between the two is about 100 cycles. + + The asm block sets __shift to -3 if the high 24 bits are clear, -2 for + 16, -1 for 8, or 0 otherwise. This could be written equivalently as + follows, but as of gcc 2.95.2 it results in conditional jumps. + + __shift = -(__n < 0x1000000); + __shift -= (__n < 0x10000); + __shift -= (__n < 0x100); + + The middle two sbbl and cmpl's pair, and with luck something gcc + generates might pair with the first cmpl and the last sbbl. The "32+1" + constant could be folded into __clz_tab[], but it doesn't seem worth + making a different table just for that. */ + +#define count_leading_zeros(c,n) \ + do { \ + USItype __n = (n); \ + USItype __shift; \ + __asm__ ("cmpl $0x1000000, %1\n" \ + "sbbl %0, %0\n" \ + "cmpl $0x10000, %1\n" \ + "sbbl $0, %0\n" \ + "cmpl $0x100, %1\n" \ + "sbbl $0, %0\n" \ + : "=&r" (__shift) : "r" (__n)); \ + __shift = __shift*8 + 24 + 1; \ + (c) = 32 + 1 - __shift - __clz_tab[__n >> __shift]; \ + } while (0) +#define COUNT_LEADING_ZEROS_NEED_CLZ_TAB +#define COUNT_LEADING_ZEROS_0 31 /* n==0 indistinguishable from n==1 */ + +#else /* ! pentiummmx || LONGLONG_STANDALONE */ +/* The following should be a fixed 14 cycles or so. Some scheduling + opportunities should be available between the float load/store too. This + sort of code is used in gcc 3 for __builtin_ffs (with "n&-n") and is + apparently suggested by the Intel optimizing manual (don't know exactly + where). gcc 2.95 or up will be best for this, so the "double" is + correctly aligned on the stack. */ +#define count_leading_zeros(c,n) \ + do { \ + union { \ + double d; \ + unsigned a[2]; \ + } __u; \ + ASSERT ((n) != 0); \ + __u.d = (UWtype) (n); \ + (c) = 0x3FF + 31 - (__u.a[1] >> 20); \ + } while (0) +#define COUNT_LEADING_ZEROS_0 (0x3FF + 31) +#endif /* pentiummx */ + +#else /* ! pentium */ + +#if __GMP_GNUC_PREREQ (3,4) /* using bsrl */ +#define count_leading_zeros(count,x) count_leading_zeros_gcc_clz(count,x) +#endif /* gcc clz */ + +/* On P6, gcc prior to 3.0 generates a partial register stall for + __cbtmp^31, due to using "xorb $31" instead of "xorl $31", the former + being 1 code byte smaller. "31-__cbtmp" is a workaround, probably at the + cost of one extra instruction. Do this for "i386" too, since that means + generic x86. */ +#if ! defined (count_leading_zeros) && __GNUC__ < 3 \ + && (HAVE_HOST_CPU_i386 \ + || HAVE_HOST_CPU_i686 \ + || HAVE_HOST_CPU_pentiumpro \ + || HAVE_HOST_CPU_pentium2 \ + || HAVE_HOST_CPU_pentium3) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + ASSERT ((x) != 0); \ + __asm__ ("bsrl %1,%0" : "=r" (__cbtmp) : "rm" ((USItype)(x))); \ + (count) = 31 - __cbtmp; \ + } while (0) +#endif /* gcc<3 asm bsrl */ + +#ifndef count_leading_zeros +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + ASSERT ((x) != 0); \ + __asm__ ("bsrl %1,%0" : "=r" (__cbtmp) : "rm" ((USItype)(x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#endif /* asm bsrl */ + +#if __GMP_GNUC_PREREQ (3,4) /* using bsfl */ +#define count_trailing_zeros(count,x) count_trailing_zeros_gcc_ctz(count,x) +#endif /* gcc ctz */ + +#ifndef count_trailing_zeros +#define count_trailing_zeros(count, x) \ + do { \ + ASSERT ((x) != 0); \ + __asm__ ("bsfl %1,%k0" : "=r" (count) : "rm" ((USItype)(x))); \ + } while (0) +#endif /* asm bsfl */ + +#endif /* ! pentium */ + +#ifndef UMUL_TIME +#define UMUL_TIME 10 +#endif +#ifndef UDIV_TIME +#define UDIV_TIME 40 +#endif +#endif /* 80x86 */ + +#if defined (__amd64__) && W_TYPE_SIZE == 64 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addq %5,%q1\n\tadcq %3,%q0" \ + : "=r" (sh), "=&r" (sl) \ + : "0" ((UDItype)(ah)), "rme" ((UDItype)(bh)), \ + "%1" ((UDItype)(al)), "rme" ((UDItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subq %5,%q1\n\tsbbq %3,%q0" \ + : "=r" (sh), "=&r" (sl) \ + : "0" ((UDItype)(ah)), "rme" ((UDItype)(bh)), \ + "1" ((UDItype)(al)), "rme" ((UDItype)(bl))) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mulq %3" \ + : "=a" (w0), "=d" (w1) \ + : "%0" ((UDItype)(u)), "rm" ((UDItype)(v))) +#define udiv_qrnnd(q, r, n1, n0, dx) /* d renamed to dx avoiding "=d" */\ + __asm__ ("divq %4" /* stringification in K&R C */ \ + : "=a" (q), "=d" (r) \ + : "0" ((UDItype)(n0)), "1" ((UDItype)(n1)), "rm" ((UDItype)(dx))) +/* bsrq destination must be a 64-bit register, hence UDItype for __cbtmp. */ +#define count_leading_zeros(count, x) \ + do { \ + UDItype __cbtmp; \ + ASSERT ((x) != 0); \ + __asm__ ("bsrq %1,%0" : "=r" (__cbtmp) : "rm" ((UDItype)(x))); \ + (count) = __cbtmp ^ 63; \ + } while (0) +/* bsfq destination must be a 64-bit register, "%q0" forces this in case + count is only an int. */ +#define count_trailing_zeros(count, x) \ + do { \ + ASSERT ((x) != 0); \ + __asm__ ("bsfq %1,%q0" : "=r" (count) : "rm" ((UDItype)(x))); \ + } while (0) +#endif /* __amd64__ */ + +#if defined (__i860__) && W_TYPE_SIZE == 32 +#define rshift_rhlc(r,h,l,c) \ + __asm__ ("shr %3,r0,r0\;shrd %1,%2,%0" \ + "=r" (r) : "r" (h), "r" (l), "rn" (c)) +#endif /* i860 */ + +#if defined (__i960__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("cmpo 1,0\;addc %5,%4,%1\;addc %3,%2,%0" \ + : "=r" (sh), "=&r" (sl) \ + : "dI" (ah), "dI" (bh), "%dI" (al), "dI" (bl)) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("cmpo 0,0\;subc %5,%4,%1\;subc %3,%2,%0" \ + : "=r" (sh), "=&r" (sl) \ + : "dI" (ah), "dI" (bh), "dI" (al), "dI" (bl)) +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __x; \ + __asm__ ("emul %2,%1,%0" \ + : "=d" (__x.__ll) : "%dI" (u), "dI" (v)); \ + (w1) = __x.__i.__h; (w0) = __x.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("emul %2,%1,%0" : "=d" (__w) : "%dI" (u), "dI" (v)); \ + __w; }) +#define udiv_qrnnd(q, r, nh, nl, d) \ + do { \ + union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __nn; \ + __nn.__i.__h = (nh); __nn.__i.__l = (nl); \ + __asm__ ("ediv %d,%n,%0" \ + : "=d" (__rq.__ll) : "dI" (__nn.__ll), "dI" (d)); \ + (r) = __rq.__i.__l; (q) = __rq.__i.__h; \ + } while (0) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("scanbit %1,%0" : "=r" (__cbtmp) : "r" (x)); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define COUNT_LEADING_ZEROS_0 (-32) /* sic */ +#if defined (__i960mx) /* what is the proper symbol to test??? */ +#define rshift_rhlc(r,h,l,c) \ + do { \ + union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __nn; \ + __nn.__i.__h = (h); __nn.__i.__l = (l); \ + __asm__ ("shre %2,%1,%0" : "=d" (r) : "dI" (__nn.__ll), "dI" (c)); \ + } +#endif /* i960mx */ +#endif /* i960 */ + +#if (defined (__mc68000__) || defined (__mc68020__) || defined(mc68020) \ + || defined (__m68k__) || defined (__mc5200__) || defined (__mc5206e__) \ + || defined (__mc5307__)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add%.l %5,%1\n\taddx%.l %3,%0" \ + : "=d" (sh), "=&d" (sl) \ + : "0" ((USItype)(ah)), "d" ((USItype)(bh)), \ + "%1" ((USItype)(al)), "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub%.l %5,%1\n\tsubx%.l %3,%0" \ + : "=d" (sh), "=&d" (sl) \ + : "0" ((USItype)(ah)), "d" ((USItype)(bh)), \ + "1" ((USItype)(al)), "g" ((USItype)(bl))) +/* The '020, '030, '040 and CPU32 have 32x32->64 and 64/32->32q-32r. */ +#if defined (__mc68020__) || defined(mc68020) \ + || defined (__mc68030__) || defined (mc68030) \ + || defined (__mc68040__) || defined (mc68040) \ + || defined (__mcpu32__) || defined (mcpu32) \ + || defined (__NeXT__) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mulu%.l %3,%1:%0" \ + : "=d" (w0), "=d" (w1) \ + : "%0" ((USItype)(u)), "dmi" ((USItype)(v))) +#define UMUL_TIME 45 +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divu%.l %4,%1:%0" \ + : "=d" (q), "=d" (r) \ + : "0" ((USItype)(n0)), "1" ((USItype)(n1)), "dmi" ((USItype)(d))) +#define UDIV_TIME 90 +#define sdiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divs%.l %4,%1:%0" \ + : "=d" (q), "=d" (r) \ + : "0" ((USItype)(n0)), "1" ((USItype)(n1)), "dmi" ((USItype)(d))) +#else /* for other 68k family members use 16x16->32 multiplication */ +#define umul_ppmm(xh, xl, a, b) \ + do { USItype __umul_tmp1, __umul_tmp2; \ + __asm__ ("| Inlined umul_ppmm\n" \ +" move%.l %5,%3\n" \ +" move%.l %2,%0\n" \ +" move%.w %3,%1\n" \ +" swap %3\n" \ +" swap %0\n" \ +" mulu%.w %2,%1\n" \ +" mulu%.w %3,%0\n" \ +" mulu%.w %2,%3\n" \ +" swap %2\n" \ +" mulu%.w %5,%2\n" \ +" add%.l %3,%2\n" \ +" jcc 1f\n" \ +" add%.l %#0x10000,%0\n" \ +"1: move%.l %2,%3\n" \ +" clr%.w %2\n" \ +" swap %2\n" \ +" swap %3\n" \ +" clr%.w %3\n" \ +" add%.l %3,%1\n" \ +" addx%.l %2,%0\n" \ +" | End inlined umul_ppmm" \ + : "=&d" (xh), "=&d" (xl), \ + "=d" (__umul_tmp1), "=&d" (__umul_tmp2) \ + : "%2" ((USItype)(a)), "d" ((USItype)(b))); \ + } while (0) +#define UMUL_TIME 100 +#define UDIV_TIME 400 +#endif /* not mc68020 */ +/* The '020, '030, '040 and '060 have bitfield insns. + GCC 3.4 defines __mc68020__ when in CPU32 mode, check for __mcpu32__ to + exclude bfffo on that chip (bitfield insns not available). */ +#if (defined (__mc68020__) || defined (mc68020) \ + || defined (__mc68030__) || defined (mc68030) \ + || defined (__mc68040__) || defined (mc68040) \ + || defined (__mc68060__) || defined (mc68060) \ + || defined (__NeXT__)) \ + && ! defined (__mcpu32__) +#define count_leading_zeros(count, x) \ + __asm__ ("bfffo %1{%b2:%b2},%0" \ + : "=d" (count) \ + : "od" ((USItype) (x)), "n" (0)) +#define COUNT_LEADING_ZEROS_0 32 +#endif +#endif /* mc68000 */ + +#if defined (__m88000__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addu.co %1,%r4,%r5\n\taddu.ci %0,%r2,%r3" \ + : "=r" (sh), "=&r" (sl) \ + : "rJ" (ah), "rJ" (bh), "%rJ" (al), "rJ" (bl)) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subu.co %1,%r4,%r5\n\tsubu.ci %0,%r2,%r3" \ + : "=r" (sh), "=&r" (sl) \ + : "rJ" (ah), "rJ" (bh), "rJ" (al), "rJ" (bl)) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("ff1 %0,%1" : "=r" (__cbtmp) : "r" (x)); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define COUNT_LEADING_ZEROS_0 63 /* sic */ +#if defined (__m88110__) +#define umul_ppmm(wh, wl, u, v) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __x; \ + __asm__ ("mulu.d %0,%1,%2" : "=r" (__x.__ll) : "r" (u), "r" (v)); \ + (wh) = __x.__i.__h; \ + (wl) = __x.__i.__l; \ + } while (0) +#define udiv_qrnnd(q, r, n1, n0, d) \ + ({union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __x, __q; \ + __x.__i.__h = (n1); __x.__i.__l = (n0); \ + __asm__ ("divu.d %0,%1,%2" \ + : "=r" (__q.__ll) : "r" (__x.__ll), "r" (d)); \ + (r) = (n0) - __q.__l * (d); (q) = __q.__l; }) +#define UMUL_TIME 5 +#define UDIV_TIME 25 +#else +#define UMUL_TIME 17 +#define UDIV_TIME 150 +#endif /* __m88110__ */ +#endif /* __m88000__ */ + +#if defined (__mips) && W_TYPE_SIZE == 32 +#if __GMP_GNUC_PREREQ (4,4) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UDItype __ll = (UDItype)(u) * (v); \ + w1 = __ll >> 32; \ + w0 = __ll; \ + } while (0) +#endif +#if !defined (umul_ppmm) && __GMP_GNUC_PREREQ (2,7) && !defined (__clang__) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("multu %2,%3" : "=l" (w0), "=h" (w1) : "d" (u), "d" (v)) +#endif +#if !defined (umul_ppmm) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("multu %2,%3\n\tmflo %0\n\tmfhi %1" \ + : "=d" (w0), "=d" (w1) : "d" (u), "d" (v)) +#endif +#define UMUL_TIME 10 +#define UDIV_TIME 100 +#endif /* __mips */ + +#if (defined (__mips) && __mips >= 3) && W_TYPE_SIZE == 64 +#if __GMP_GNUC_PREREQ (4,4) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + typedef unsigned int __ll_UTItype __attribute__((mode(TI))); \ + __ll_UTItype __ll = (__ll_UTItype)(u) * (v); \ + w1 = __ll >> 64; \ + w0 = __ll; \ + } while (0) +#endif +#if !defined (umul_ppmm) && __GMP_GNUC_PREREQ (2,7) && !defined (__clang__) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("dmultu %2,%3" \ + : "=l" (w0), "=h" (w1) \ + : "d" ((UDItype)(u)), "d" ((UDItype)(v))) +#endif +#if !defined (umul_ppmm) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("dmultu %2,%3\n\tmflo %0\n\tmfhi %1" \ + : "=d" (w0), "=d" (w1) \ + : "d" ((UDItype)(u)), "d" ((UDItype)(v))) +#endif +#define UMUL_TIME 20 +#define UDIV_TIME 140 +#endif /* __mips */ + +#if defined (__mmix__) && W_TYPE_SIZE == 64 +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("MULU %0,%2,%3" : "=r" (w0), "=z" (w1) : "r" (u), "r" (v)) +#endif + +#if defined (__ns32000__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __x; \ + __asm__ ("meid %2,%0" \ + : "=g" (__x.__ll) \ + : "%0" ((USItype)(u)), "g" ((USItype)(v))); \ + (w1) = __x.__i.__h; (w0) = __x.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("meid %2,%0" \ + : "=g" (__w) \ + : "%0" ((USItype)(u)), "g" ((USItype)(v))); \ + __w; }) +#define udiv_qrnnd(q, r, n1, n0, d) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __x; \ + __x.__i.__h = (n1); __x.__i.__l = (n0); \ + __asm__ ("deid %2,%0" \ + : "=g" (__x.__ll) \ + : "0" (__x.__ll), "g" ((USItype)(d))); \ + (r) = __x.__i.__l; (q) = __x.__i.__h; }) +#define count_trailing_zeros(count,x) \ + do { \ + __asm__ ("ffsd %2,%0" \ + : "=r" (count) \ + : "0" ((USItype) 0), "r" ((USItype) (x))); \ + } while (0) +#endif /* __ns32000__ */ + +/* In the past we had a block of various #defines tested + _ARCH_PPC - AIX + _ARCH_PWR - AIX + __powerpc__ - gcc + __POWERPC__ - BEOS + __ppc__ - Darwin + PPC - old gcc, GNU/Linux, SysV + The plain PPC test was not good for vxWorks, since PPC is defined on all + CPUs there (eg. m68k too), as a constant one is expected to compare + CPU_FAMILY against. + + At any rate, this was pretty unattractive and a bit fragile. The use of + HAVE_HOST_CPU_FAMILY is designed to cut through it all and be sure of + getting the desired effect. + + ENHANCE-ME: We should test _IBMR2 here when we add assembly support for + the system vendor compilers. (Is that vendor compilers with inline asm, + or what?) */ + +#if (HAVE_HOST_CPU_FAMILY_power || HAVE_HOST_CPU_FAMILY_powerpc) \ + && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("add%I4c %1,%3,%4\n\taddze %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl)); \ + else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0) \ + __asm__ ("add%I4c %1,%3,%4\n\taddme %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl)); \ + else \ + __asm__ ("add%I5c %1,%4,%5\n\tadde %0,%2,%3" \ + : "=r" (sh), "=&r" (sl) \ + : "r" (ah), "r" (bh), "%r" (al), "rI" (bl)); \ + } while (0) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (ah) && (ah) == 0) \ + __asm__ ("subf%I3c %1,%4,%3\n\tsubfze %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (ah) && (ah) == ~(USItype) 0) \ + __asm__ ("subf%I3c %1,%4,%3\n\tsubfme %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("subf%I3c %1,%4,%3\n\taddme %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0) \ + __asm__ ("subf%I3c %1,%4,%3\n\taddze %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else \ + __asm__ ("subf%I4c %1,%5,%4\n\tsubfe %0,%3,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" (ah), "r" (bh), "rI" (al), "r" (bl)); \ + } while (0) +#define count_leading_zeros(count, x) \ + __asm__ ("cntlzw %0,%1" : "=r" (count) : "r" (x)) +#define COUNT_LEADING_ZEROS_0 32 +#if HAVE_HOST_CPU_FAMILY_powerpc +#if __GMP_GNUC_PREREQ (4,4) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UDItype __ll = (UDItype)(u) * (v); \ + w1 = __ll >> 32; \ + w0 = __ll; \ + } while (0) +#endif +#if !defined (umul_ppmm) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhwu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#endif +#define UMUL_TIME 15 +#define smul_ppmm(ph, pl, m0, m1) \ + do { \ + SItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhw %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define SMUL_TIME 14 +#define UDIV_TIME 120 +#else +#define UMUL_TIME 8 +#define smul_ppmm(xh, xl, m0, m1) \ + __asm__ ("mul %0,%2,%3" : "=r" (xh), "=q" (xl) : "r" (m0), "r" (m1)) +#define SMUL_TIME 4 +#define sdiv_qrnnd(q, r, nh, nl, d) \ + __asm__ ("div %0,%2,%4" : "=r" (q), "=q" (r) : "r" (nh), "1" (nl), "r" (d)) +#define UDIV_TIME 100 +#endif +#endif /* 32-bit POWER architecture variants. */ + +/* We should test _IBMR2 here when we add assembly support for the system + vendor compilers. */ +#if HAVE_HOST_CPU_FAMILY_powerpc && W_TYPE_SIZE == 64 +#if !defined (_LONG_LONG_LIMB) +/* _LONG_LONG_LIMB is ABI=mode32 where adde operates on 32-bit values. So + use adde etc only when not _LONG_LONG_LIMB. */ +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("add%I4c %1,%3,%4\n\taddze %0,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" ((UDItype)(ah)), \ + "%r" ((UDItype)(al)), "rI" ((UDItype)(bl))); \ + else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \ + __asm__ ("add%I4c %1,%3,%4\n\taddme %0,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" ((UDItype)(ah)), \ + "%r" ((UDItype)(al)), "rI" ((UDItype)(bl))); \ + else \ + __asm__ ("add%I5c %1,%4,%5\n\tadde %0,%2,%3" \ + : "=r" (sh), "=&r" (sl) \ + : "r" ((UDItype)(ah)), "r" ((UDItype)(bh)), \ + "%r" ((UDItype)(al)), "rI" ((UDItype)(bl))); \ + } while (0) +/* We use "*rI" for the constant operand here, since with just "I", gcc barfs. + This might seem strange, but gcc folds away the dead code late. */ +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (bl) && bl > -0x8000 && bl <= 0x8000) { \ + if (__builtin_constant_p (ah) && (ah) == 0) \ + __asm__ ("addic %1,%3,%4\n\tsubfze %0,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" ((UDItype)(bh)), \ + "rI" ((UDItype)(al)), "*rI" (-((UDItype)(bl)))); \ + else if (__builtin_constant_p (ah) && (ah) == ~(UDItype) 0) \ + __asm__ ("addic %1,%3,%4\n\tsubfme %0,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" ((UDItype)(bh)), \ + "rI" ((UDItype)(al)), "*rI" (-((UDItype)(bl)))); \ + else if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("addic %1,%3,%4\n\taddme %0,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" ((UDItype)(ah)), \ + "rI" ((UDItype)(al)), "*rI" (-((UDItype)(bl)))); \ + else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \ + __asm__ ("addic %1,%3,%4\n\taddze %0,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" ((UDItype)(ah)), \ + "rI" ((UDItype)(al)), "*rI" (-((UDItype)(bl)))); \ + else \ + __asm__ ("addic %1,%4,%5\n\tsubfe %0,%3,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" ((UDItype)(ah)), "r" ((UDItype)(bh)), \ + "rI" ((UDItype)(al)), "*rI" (-((UDItype)(bl)))); \ + } else { \ + if (__builtin_constant_p (ah) && (ah) == 0) \ + __asm__ ("subf%I3c %1,%4,%3\n\tsubfze %0,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" ((UDItype)(bh)), \ + "rI" ((UDItype)(al)), "r" ((UDItype)(bl))); \ + else if (__builtin_constant_p (ah) && (ah) == ~(UDItype) 0) \ + __asm__ ("subf%I3c %1,%4,%3\n\tsubfme %0,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" ((UDItype)(bh)), \ + "rI" ((UDItype)(al)), "r" ((UDItype)(bl))); \ + else if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("subf%I3c %1,%4,%3\n\taddme %0,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" ((UDItype)(ah)), \ + "rI" ((UDItype)(al)), "r" ((UDItype)(bl))); \ + else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \ + __asm__ ("subf%I3c %1,%4,%3\n\taddze %0,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" ((UDItype)(ah)), \ + "rI" ((UDItype)(al)), "r" ((UDItype)(bl))); \ + else \ + __asm__ ("subf%I4c %1,%5,%4\n\tsubfe %0,%3,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" ((UDItype)(ah)), "r" ((UDItype)(bh)), \ + "rI" ((UDItype)(al)), "r" ((UDItype)(bl))); \ + } \ + } while (0) +#endif /* ! _LONG_LONG_LIMB */ +#define count_leading_zeros(count, x) \ + __asm__ ("cntlzd %0,%1" : "=r" (count) : "r" (x)) +#define COUNT_LEADING_ZEROS_0 64 +#if 0 && __GMP_GNUC_PREREQ (4,4) /* Disable, this results in libcalls! */ +#define umul_ppmm(w1, w0, u, v) \ + do { \ + typedef unsigned int __ll_UTItype __attribute__((mode(TI))); \ + __ll_UTItype __ll = (__ll_UTItype)(u) * (v); \ + w1 = __ll >> 64; \ + w0 = __ll; \ + } while (0) +#endif +#if !defined (umul_ppmm) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhdu %0,%1,%2" : "=r" (ph) : "%r" (__m0), "r" (__m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#endif +#define UMUL_TIME 15 +#define smul_ppmm(ph, pl, m0, m1) \ + do { \ + DItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhd %0,%1,%2" : "=r" (ph) : "%r" (__m0), "r" (__m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define SMUL_TIME 14 /* ??? */ +#define UDIV_TIME 120 /* ??? */ +#endif /* 64-bit PowerPC. */ + +#if defined (__pyr__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addw %5,%1\n\taddwc %3,%0" \ + : "=r" (sh), "=&r" (sl) \ + : "0" ((USItype)(ah)), "g" ((USItype)(bh)), \ + "%1" ((USItype)(al)), "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subw %5,%1\n\tsubwb %3,%0" \ + : "=r" (sh), "=&r" (sl) \ + : "0" ((USItype)(ah)), "g" ((USItype)(bh)), \ + "1" ((USItype)(al)), "g" ((USItype)(bl))) +/* This insn works on Pyramids with AP, XP, or MI CPUs, but not with SP. */ +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __x; \ + __asm__ ("movw %1,%R0\n\tuemul %2,%0" \ + : "=&r" (__x.__ll) \ + : "g" ((USItype) (u)), "g" ((USItype)(v))); \ + (w1) = __x.__i.__h; (w0) = __x.__i.__l;}) +#endif /* __pyr__ */ + +#if defined (__ibm032__) /* RT/ROMP */ && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("a %1,%5\n\tae %0,%3" \ + : "=r" (sh), "=&r" (sl) \ + : "0" ((USItype)(ah)), "r" ((USItype)(bh)), \ + "%1" ((USItype)(al)), "r" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("s %1,%5\n\tse %0,%3" \ + : "=r" (sh), "=&r" (sl) \ + : "0" ((USItype)(ah)), "r" ((USItype)(bh)), \ + "1" ((USItype)(al)), "r" ((USItype)(bl))) +#define smul_ppmm(ph, pl, m0, m1) \ + __asm__ ( \ + "s r2,r2\n" \ +" mts r10,%2\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" cas %0,r2,r0\n" \ +" mfs r10,%1" \ + : "=r" (ph), "=r" (pl) \ + : "%r" ((USItype)(m0)), "r" ((USItype)(m1)) \ + : "r2") +#define UMUL_TIME 20 +#define UDIV_TIME 200 +#define count_leading_zeros(count, x) \ + do { \ + if ((x) >= 0x10000) \ + __asm__ ("clz %0,%1" \ + : "=r" (count) : "r" ((USItype)(x) >> 16)); \ + else \ + { \ + __asm__ ("clz %0,%1" \ + : "=r" (count) : "r" ((USItype)(x))); \ + (count) += 16; \ + } \ + } while (0) +#endif /* RT/ROMP */ + +#if (defined (__SH2__) || defined (__SH3__) || defined (__SH4__)) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("dmulu.l %2,%3\n\tsts macl,%1\n\tsts mach,%0" \ + : "=r" (w1), "=r" (w0) : "r" (u), "r" (v) : "macl", "mach") +#define UMUL_TIME 5 +#endif + +#if defined (__sparc__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addcc %r4,%5,%1\n\taddx %r2,%3,%0" \ + : "=r" (sh), "=&r" (sl) \ + : "rJ" (ah), "rI" (bh),"%rJ" (al), "rI" (bl) \ + __CLOBBER_CC) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subcc %r4,%5,%1\n\tsubx %r2,%3,%0" \ + : "=r" (sh), "=&r" (sl) \ + : "rJ" (ah), "rI" (bh), "rJ" (al), "rI" (bl) \ + __CLOBBER_CC) +/* FIXME: When gcc -mcpu=v9 is used on solaris, gcc/config/sol2-sld-64.h + doesn't define anything to indicate that to us, it only sets __sparcv8. */ +#if defined (__sparc_v9__) || defined (__sparcv9) +/* Perhaps we should use floating-point operations here? */ +#if 0 +/* Triggers a bug making mpz/tests/t-gcd.c fail. + Perhaps we simply need explicitly zero-extend the inputs? */ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mulx %2,%3,%%g1; srl %%g1,0,%1; srlx %%g1,32,%0" : \ + "=r" (w1), "=r" (w0) : "r" (u), "r" (v) : "g1") +#else +/* Use v8 umul until above bug is fixed. */ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("umul %2,%3,%1;rd %%y,%0" : "=r" (w1), "=r" (w0) : "r" (u), "r" (v)) +#endif +/* Use a plain v8 divide for v9. */ +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { \ + USItype __q; \ + __asm__ ("mov %1,%%y;nop;nop;nop;udiv %2,%3,%0" \ + : "=r" (__q) : "r" (n1), "r" (n0), "r" (d)); \ + (r) = (n0) - __q * (d); \ + (q) = __q; \ + } while (0) +#else +#if defined (__sparc_v8__) /* gcc normal */ \ + || defined (__sparcv8) /* gcc solaris */ \ + || HAVE_HOST_CPU_supersparc +/* Don't match immediate range because, 1) it is not often useful, + 2) the 'I' flag thinks of the range as a 13 bit signed interval, + while we want to match a 13 bit interval, sign extended to 32 bits, + but INTERPRETED AS UNSIGNED. */ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("umul %2,%3,%1;rd %%y,%0" : "=r" (w1), "=r" (w0) : "r" (u), "r" (v)) +#define UMUL_TIME 5 + +#if HAVE_HOST_CPU_supersparc +#define UDIV_TIME 60 /* SuperSPARC timing */ +#else +/* Don't use this on SuperSPARC because its udiv only handles 53 bit + dividends and will trap to the kernel for the rest. */ +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { \ + USItype __q; \ + __asm__ ("mov %1,%%y;nop;nop;nop;udiv %2,%3,%0" \ + : "=r" (__q) : "r" (n1), "r" (n0), "r" (d)); \ + (r) = (n0) - __q * (d); \ + (q) = __q; \ + } while (0) +#define UDIV_TIME 25 +#endif /* HAVE_HOST_CPU_supersparc */ + +#else /* ! __sparc_v8__ */ +#if defined (__sparclite__) +/* This has hardware multiply but not divide. It also has two additional + instructions scan (ffs from high bit) and divscc. */ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("umul %2,%3,%1;rd %%y,%0" : "=r" (w1), "=r" (w0) : "r" (u), "r" (v)) +#define UMUL_TIME 5 +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("! Inlined udiv_qrnnd\n" \ +" wr %%g0,%2,%%y ! Not a delayed write for sparclite\n" \ +" tst %%g0\n" \ +" divscc %3,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%0\n" \ +" rd %%y,%1\n" \ +" bl,a 1f\n" \ +" add %1,%4,%1\n" \ +"1: ! End of inline udiv_qrnnd" \ + : "=r" (q), "=r" (r) : "r" (n1), "r" (n0), "rI" (d) \ + : "%g1" __AND_CLOBBER_CC) +#define UDIV_TIME 37 +#define count_leading_zeros(count, x) \ + __asm__ ("scan %1,1,%0" : "=r" (count) : "r" (x)) +/* Early sparclites return 63 for an argument of 0, but they warn that future + implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0 + undefined. */ +#endif /* __sparclite__ */ +#endif /* __sparc_v8__ */ +#endif /* __sparc_v9__ */ +/* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd. */ +#ifndef umul_ppmm +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("! Inlined umul_ppmm\n" \ +" wr %%g0,%2,%%y ! SPARC has 0-3 delay insn after a wr\n" \ +" sra %3,31,%%g2 ! Don't move this insn\n" \ +" and %2,%%g2,%%g2 ! Don't move this insn\n" \ +" andcc %%g0,0,%%g1 ! Don't move this insn\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,0,%%g1\n" \ +" add %%g1,%%g2,%0\n" \ +" rd %%y,%1" \ + : "=r" (w1), "=r" (w0) : "%rI" (u), "r" (v) \ + : "%g1", "%g2" __AND_CLOBBER_CC) +#define UMUL_TIME 39 /* 39 instructions */ +#endif +#ifndef udiv_qrnnd +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { UWtype __r; \ + (q) = __MPN(udiv_qrnnd) (&__r, (n1), (n0), (d)); \ + (r) = __r; \ + } while (0) +extern UWtype __MPN(udiv_qrnnd) (UWtype *, UWtype, UWtype, UWtype); +#ifndef UDIV_TIME +#define UDIV_TIME 140 +#endif +#endif /* LONGLONG_STANDALONE */ +#endif /* udiv_qrnnd */ +#endif /* __sparc__ */ + +#if defined (__sparc__) && W_TYPE_SIZE == 64 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ( \ + "addcc %r4,%5,%1\n" \ + " addccc %r6,%7,%%g0\n" \ + " addc %r2,%3,%0" \ + : "=r" (sh), "=&r" (sl) \ + : "rJ" ((UDItype)(ah)), "rI" ((UDItype)(bh)), \ + "%rJ" ((UDItype)(al)), "rI" ((UDItype)(bl)), \ + "%rJ" ((UDItype)(al) >> 32), "rI" ((UDItype)(bl) >> 32) \ + __CLOBBER_CC) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ( \ + "subcc %r4,%5,%1\n" \ + " subccc %r6,%7,%%g0\n" \ + " subc %r2,%3,%0" \ + : "=r" (sh), "=&r" (sl) \ + : "rJ" ((UDItype)(ah)), "rI" ((UDItype)(bh)), \ + "rJ" ((UDItype)(al)), "rI" ((UDItype)(bl)), \ + "rJ" ((UDItype)(al) >> 32), "rI" ((UDItype)(bl) >> 32) \ + __CLOBBER_CC) +#if __VIS__ >= 0x300 +#undef add_ssaaaa +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ( \ + "addcc %r4, %5, %1\n" \ + " addxc %r2, %r3, %0" \ + : "=r" (sh), "=&r" (sl) \ + : "rJ" ((UDItype)(ah)), "rJ" ((UDItype)(bh)), \ + "%rJ" ((UDItype)(al)), "rI" ((UDItype)(bl)) __CLOBBER_CC) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDItype __m0 = (m0), __m1 = (m1); \ + (pl) = __m0 * __m1; \ + __asm__ ("umulxhi\t%2, %1, %0" \ + : "=r" (ph) \ + : "%r" (__m0), "r" (__m1)); \ + } while (0) +#define count_leading_zeros(count, x) \ + __asm__ ("lzd\t%1,%0" : "=r" (count) : "r" (x)) +/* Needed by count_leading_zeros_32 in sparc64.h. */ +#define COUNT_LEADING_ZEROS_NEED_CLZ_TAB +#endif +#endif + +#if (defined (__vax) || defined (__vax__)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addl2 %5,%1\n\tadwc %3,%0" \ + : "=g" (sh), "=&g" (sl) \ + : "0" ((USItype)(ah)), "g" ((USItype)(bh)), \ + "%1" ((USItype)(al)), "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subl2 %5,%1\n\tsbwc %3,%0" \ + : "=g" (sh), "=&g" (sl) \ + : "0" ((USItype)(ah)), "g" ((USItype)(bh)), \ + "1" ((USItype)(al)), "g" ((USItype)(bl))) +#define smul_ppmm(xh, xl, m0, m1) \ + do { \ + union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __x; \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("emul %1,%2,$0,%0" \ + : "=g" (__x.__ll) : "g" (__m0), "g" (__m1)); \ + (xh) = __x.__i.__h; (xl) = __x.__i.__l; \ + } while (0) +#define sdiv_qrnnd(q, r, n1, n0, d) \ + do { \ + union {DItype __ll; \ + struct {SItype __l, __h;} __i; \ + } __x; \ + __x.__i.__h = n1; __x.__i.__l = n0; \ + __asm__ ("ediv %3,%2,%0,%1" \ + : "=g" (q), "=g" (r) : "g" (__x.__ll), "g" (d)); \ + } while (0) +#if 0 +/* FIXME: This instruction appears to be unimplemented on some systems (vax + 8800 maybe). */ +#define count_trailing_zeros(count,x) \ + do { \ + __asm__ ("ffs 0, 31, %1, %0" \ + : "=g" (count) \ + : "g" ((USItype) (x))); \ + } while (0) +#endif +#endif /* vax */ + +#if defined (__z8000__) && W_TYPE_SIZE == 16 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add %H1,%H5\n\tadc %H0,%H3" \ + : "=r" (sh), "=&r" (sl) \ + : "0" ((unsigned int)(ah)), "r" ((unsigned int)(bh)), \ + "%1" ((unsigned int)(al)), "rQR" ((unsigned int)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub %H1,%H5\n\tsbc %H0,%H3" \ + : "=r" (sh), "=&r" (sl) \ + : "0" ((unsigned int)(ah)), "r" ((unsigned int)(bh)), \ + "1" ((unsigned int)(al)), "rQR" ((unsigned int)(bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {long int __ll; \ + struct {unsigned int __h, __l;} __i; \ + } __x; \ + unsigned int __m0 = (m0), __m1 = (m1); \ + __asm__ ("mult %S0,%H3" \ + : "=r" (__x.__i.__h), "=r" (__x.__i.__l) \ + : "%1" (m0), "rQR" (m1)); \ + (xh) = __x.__i.__h; (xl) = __x.__i.__l; \ + (xh) += ((((signed int) __m0 >> 15) & __m1) \ + + (((signed int) __m1 >> 15) & __m0)); \ + } while (0) +#endif /* __z8000__ */ + +#endif /* __GNUC__ */ + +#endif /* NO_ASM */ + + +/* FIXME: "sidi" here is highly doubtful, should sometimes be "diti". */ +#if !defined (umul_ppmm) && defined (__umulsidi3) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDWtype __ll = __umulsidi3 (m0, m1); \ + ph = (UWtype) (__ll >> W_TYPE_SIZE); \ + pl = (UWtype) __ll; \ + } while (0) +#endif + +#if !defined (__umulsidi3) +#define __umulsidi3(u, v) \ + ({UWtype __hi, __lo; \ + umul_ppmm (__hi, __lo, u, v); \ + ((UDWtype) __hi << W_TYPE_SIZE) | __lo; }) +#endif + + +#if defined (__cplusplus) +#define __longlong_h_C "C" +#else +#define __longlong_h_C +#endif + +/* Use mpn_umul_ppmm or mpn_udiv_qrnnd functions, if they exist. The "_r" + forms have "reversed" arguments, meaning the pointer is last, which + sometimes allows better parameter passing, in particular on 64-bit + hppa. */ + +#define mpn_umul_ppmm __MPN(umul_ppmm) +extern __longlong_h_C UWtype mpn_umul_ppmm (UWtype *, UWtype, UWtype); + +#if ! defined (umul_ppmm) && HAVE_NATIVE_mpn_umul_ppmm \ + && ! defined (LONGLONG_STANDALONE) +#define umul_ppmm(wh, wl, u, v) \ + do { \ + UWtype __umul_ppmm__p0; \ + (wh) = mpn_umul_ppmm (&__umul_ppmm__p0, (UWtype) (u), (UWtype) (v));\ + (wl) = __umul_ppmm__p0; \ + } while (0) +#endif + +#define mpn_umul_ppmm_r __MPN(umul_ppmm_r) +extern __longlong_h_C UWtype mpn_umul_ppmm_r (UWtype, UWtype, UWtype *); + +#if ! defined (umul_ppmm) && HAVE_NATIVE_mpn_umul_ppmm_r \ + && ! defined (LONGLONG_STANDALONE) +#define umul_ppmm(wh, wl, u, v) \ + do { \ + UWtype __umul_p0; \ + (wh) = mpn_umul_ppmm_r ((UWtype) (u), (UWtype) (v), &__umul_p0); \ + (wl) = __umul_p0; \ + } while (0) +#endif + +#define mpn_udiv_qrnnd __MPN(udiv_qrnnd) +extern __longlong_h_C UWtype mpn_udiv_qrnnd (UWtype *, UWtype, UWtype, UWtype); + +#if ! defined (udiv_qrnnd) && HAVE_NATIVE_mpn_udiv_qrnnd \ + && ! defined (LONGLONG_STANDALONE) +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { \ + UWtype __udiv_qrnnd_r; \ + (q) = mpn_udiv_qrnnd (&__udiv_qrnnd_r, \ + (UWtype) (n1), (UWtype) (n0), (UWtype) d); \ + (r) = __udiv_qrnnd_r; \ + } while (0) +#endif + +#define mpn_udiv_qrnnd_r __MPN(udiv_qrnnd_r) +extern __longlong_h_C UWtype mpn_udiv_qrnnd_r (UWtype, UWtype, UWtype, UWtype *); + +#if ! defined (udiv_qrnnd) && HAVE_NATIVE_mpn_udiv_qrnnd_r \ + && ! defined (LONGLONG_STANDALONE) +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { \ + UWtype __udiv_qrnnd_r; \ + (q) = mpn_udiv_qrnnd_r ((UWtype) (n1), (UWtype) (n0), (UWtype) d, \ + &__udiv_qrnnd_r); \ + (r) = __udiv_qrnnd_r; \ + } while (0) +#endif + + +/* If this machine has no inline assembler, use C macros. */ + +#if !defined (add_ssaaaa) +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) + (bl); \ + (sh) = (ah) + (bh) + (__x < (al)); \ + (sl) = __x; \ + } while (0) +#endif + +#if !defined (sub_ddmmss) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) - (bl); \ + (sh) = (ah) - (bh) - ((al) < (bl)); \ + (sl) = __x; \ + } while (0) +#endif + +/* If we lack umul_ppmm but have smul_ppmm, define umul_ppmm in terms of + smul_ppmm. */ +#if !defined (umul_ppmm) && defined (smul_ppmm) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UWtype __w1; \ + UWtype __xm0 = (u), __xm1 = (v); \ + smul_ppmm (__w1, w0, __xm0, __xm1); \ + (w1) = __w1 + (-(__xm0 >> (W_TYPE_SIZE - 1)) & __xm1) \ + + (-(__xm1 >> (W_TYPE_SIZE - 1)) & __xm0); \ + } while (0) +#endif + +/* If we still don't have umul_ppmm, define it using plain C. + + For reference, when this code is used for squaring (ie. u and v identical + expressions), gcc recognises __x1 and __x2 are the same and generates 3 + multiplies, not 4. The subsequent additions could be optimized a bit, + but the only place GMP currently uses such a square is mpn_sqr_basecase, + and chips obliged to use this generic C umul will have plenty of worse + performance problems than a couple of extra instructions on the diagonal + of sqr_basecase. */ + +#if !defined (umul_ppmm) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UWtype __x0, __x1, __x2, __x3; \ + UHWtype __ul, __vl, __uh, __vh; \ + UWtype __u = (u), __v = (v); \ + \ + __ul = __ll_lowpart (__u); \ + __uh = __ll_highpart (__u); \ + __vl = __ll_lowpart (__v); \ + __vh = __ll_highpart (__v); \ + \ + __x0 = (UWtype) __ul * __vl; \ + __x1 = (UWtype) __ul * __vh; \ + __x2 = (UWtype) __uh * __vl; \ + __x3 = (UWtype) __uh * __vh; \ + \ + __x1 += __ll_highpart (__x0);/* this can't give carry */ \ + __x1 += __x2; /* but this indeed can */ \ + if (__x1 < __x2) /* did we get it? */ \ + __x3 += __ll_B; /* yes, add it in the proper pos. */ \ + \ + (w1) = __x3 + __ll_highpart (__x1); \ + (w0) = (__x1 << W_TYPE_SIZE/2) + __ll_lowpart (__x0); \ + } while (0) +#endif + +/* If we don't have smul_ppmm, define it using umul_ppmm (which surely will + exist in one form or another. */ +#if !defined (smul_ppmm) +#define smul_ppmm(w1, w0, u, v) \ + do { \ + UWtype __w1; \ + UWtype __xm0 = (u), __xm1 = (v); \ + umul_ppmm (__w1, w0, __xm0, __xm1); \ + (w1) = __w1 - (-(__xm0 >> (W_TYPE_SIZE - 1)) & __xm1) \ + - (-(__xm1 >> (W_TYPE_SIZE - 1)) & __xm0); \ + } while (0) +#endif + +/* Define this unconditionally, so it can be used for debugging. */ +#define __udiv_qrnnd_c(q, r, n1, n0, d) \ + do { \ + UWtype __d1, __d0, __q1, __q0, __r1, __r0, __m; \ + \ + ASSERT ((d) != 0); \ + ASSERT ((n1) < (d)); \ + \ + __d1 = __ll_highpart (d); \ + __d0 = __ll_lowpart (d); \ + \ + __q1 = (n1) / __d1; \ + __r1 = (n1) - __q1 * __d1; \ + __m = __q1 * __d0; \ + __r1 = __r1 * __ll_B | __ll_highpart (n0); \ + if (__r1 < __m) \ + { \ + __q1--, __r1 += (d); \ + if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\ + if (__r1 < __m) \ + __q1--, __r1 += (d); \ + } \ + __r1 -= __m; \ + \ + __q0 = __r1 / __d1; \ + __r0 = __r1 - __q0 * __d1; \ + __m = __q0 * __d0; \ + __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ + if (__r0 < __m) \ + { \ + __q0--, __r0 += (d); \ + if (__r0 >= (d)) \ + if (__r0 < __m) \ + __q0--, __r0 += (d); \ + } \ + __r0 -= __m; \ + \ + (q) = __q1 * __ll_B | __q0; \ + (r) = __r0; \ + } while (0) + +/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through + __udiv_w_sdiv (defined in libgcc or elsewhere). */ +#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd) \ + && ! defined (LONGLONG_STANDALONE) +#define udiv_qrnnd(q, r, nh, nl, d) \ + do { \ + UWtype __r; \ + (q) = __MPN(udiv_w_sdiv) (&__r, nh, nl, d); \ + (r) = __r; \ + } while (0) +__GMP_DECLSPEC UWtype __MPN(udiv_w_sdiv) (UWtype *, UWtype, UWtype, UWtype); +#endif + +/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */ +#if !defined (udiv_qrnnd) +#define UDIV_NEEDS_NORMALIZATION 1 +#define udiv_qrnnd __udiv_qrnnd_c +#endif + +#if !defined (count_leading_zeros) +#define count_leading_zeros(count, x) \ + do { \ + UWtype __xr = (x); \ + UWtype __a; \ + \ + if (W_TYPE_SIZE == 32) \ + { \ + __a = __xr < ((UWtype) 1 << 2*__BITS4) \ + ? (__xr < ((UWtype) 1 << __BITS4) ? 1 : __BITS4 + 1) \ + : (__xr < ((UWtype) 1 << 3*__BITS4) ? 2*__BITS4 + 1 \ + : 3*__BITS4 + 1); \ + } \ + else \ + { \ + for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \ + if (((__xr >> __a) & 0xff) != 0) \ + break; \ + ++__a; \ + } \ + \ + (count) = W_TYPE_SIZE + 1 - __a - __clz_tab[__xr >> __a]; \ + } while (0) +/* This version gives a well-defined value for zero. */ +#define COUNT_LEADING_ZEROS_0 (W_TYPE_SIZE - 1) +#define COUNT_LEADING_ZEROS_NEED_CLZ_TAB +#define COUNT_LEADING_ZEROS_SLOW +#endif + +/* clz_tab needed by mpn/x86/pentium/mod_1.asm in a fat binary */ +#if HAVE_HOST_CPU_FAMILY_x86 && WANT_FAT_BINARY +#define COUNT_LEADING_ZEROS_NEED_CLZ_TAB +#endif + +#ifdef COUNT_LEADING_ZEROS_NEED_CLZ_TAB +extern const unsigned char __GMP_DECLSPEC __clz_tab[129]; +#endif + +#if !defined (count_trailing_zeros) +#if !defined (COUNT_LEADING_ZEROS_SLOW) +/* Define count_trailing_zeros using an asm count_leading_zeros. */ +#define count_trailing_zeros(count, x) \ + do { \ + UWtype __ctz_x = (x); \ + UWtype __ctz_c; \ + ASSERT (__ctz_x != 0); \ + count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x); \ + (count) = W_TYPE_SIZE - 1 - __ctz_c; \ + } while (0) +#else +/* Define count_trailing_zeros in plain C, assuming small counts are common. + We use clz_tab without ado, since the C count_leading_zeros above will have + pulled it in. */ +#define count_trailing_zeros(count, x) \ + do { \ + UWtype __ctz_x = (x); \ + int __ctz_c; \ + \ + if (LIKELY ((__ctz_x & 0xff) != 0)) \ + (count) = __clz_tab[__ctz_x & -__ctz_x] - 2; \ + else \ + { \ + for (__ctz_c = 8 - 2; __ctz_c < W_TYPE_SIZE - 2; __ctz_c += 8) \ + { \ + __ctz_x >>= 8; \ + if (LIKELY ((__ctz_x & 0xff) != 0)) \ + break; \ + } \ + \ + (count) = __ctz_c + __clz_tab[__ctz_x & -__ctz_x]; \ + } \ + } while (0) +#endif +#endif + +#ifndef UDIV_NEEDS_NORMALIZATION +#define UDIV_NEEDS_NORMALIZATION 0 +#endif + +/* Whether udiv_qrnnd is actually implemented with udiv_qrnnd_preinv, and + that hence the latter should always be used. */ +#ifndef UDIV_PREINV_ALWAYS +#define UDIV_PREINV_ALWAYS 0 +#endif + +/* Give defaults for UMUL_TIME and UDIV_TIME. */ +#ifndef UMUL_TIME +#define UMUL_TIME 1 +#endif + +#ifndef UDIV_TIME +#define UDIV_TIME UMUL_TIME +#endif diff --git a/examples/multiprecision/bench-include/mp_bases.h b/examples/multiprecision/bench-include/mp_bases.h new file mode 100644 index 0000000000000000000000000000000000000000..49abbb21c4474f78eff9cc5034fe017ec903f91f --- /dev/null +++ b/examples/multiprecision/bench-include/mp_bases.h @@ -0,0 +1,11 @@ +/* This file generated by gen-bases.c - DO NOT EDIT. */ + +#if GMP_NUMB_BITS != 64 +Error, error, this data is for 64 bits +#endif + +/* mp_bases[10] data, as literal values */ +#define MP_BASES_CHARS_PER_LIMB_10 19 +#define MP_BASES_BIG_BASE_10 CNST_LIMB(0x8ac7230489e80000) +#define MP_BASES_BIG_BASE_INVERTED_10 CNST_LIMB(0xd83c94fb6d2ac34a) +#define MP_BASES_NORMALIZATION_STEPS_10 0 diff --git a/examples/multiprecision/bench-include/trialdivtab.h b/examples/multiprecision/bench-include/trialdivtab.h new file mode 100644 index 0000000000000000000000000000000000000000..eb81d7f0a3d469810a6b3a5ed2cd9bbc9076c70f --- /dev/null +++ b/examples/multiprecision/bench-include/trialdivtab.h @@ -0,0 +1,1214 @@ +#if GMP_LIMB_BITS != 64 +#error This table is for GMP_LIMB_BITS = 64 +#endif + +#if GMP_NAIL_BITS != 0 +#error This table does not support nails +#endif + +#ifdef WANT_dtab + P(3,CNST_LIMB(0xaaaaaaaaaaaaaaab),CNST_LIMB(0x5555555555555555)), + P(5,CNST_LIMB(0xcccccccccccccccd),CNST_LIMB(0x3333333333333333)), + P(7,CNST_LIMB(0x6db6db6db6db6db7),CNST_LIMB(0x2492492492492492)), + P(11,CNST_LIMB(0x2e8ba2e8ba2e8ba3),CNST_LIMB(0x1745d1745d1745d1)), + P(13,CNST_LIMB(0x4ec4ec4ec4ec4ec5),CNST_LIMB(0x13b13b13b13b13b1)), + P(17,CNST_LIMB(0xf0f0f0f0f0f0f0f1),CNST_LIMB(0xf0f0f0f0f0f0f0f)), + P(19,CNST_LIMB(0x86bca1af286bca1b),CNST_LIMB(0xd79435e50d79435)), + P(23,CNST_LIMB(0xd37a6f4de9bd37a7),CNST_LIMB(0xb21642c8590b216)), + P(29,CNST_LIMB(0x34f72c234f72c235),CNST_LIMB(0x8d3dcb08d3dcb08)), + P(31,CNST_LIMB(0xef7bdef7bdef7bdf),CNST_LIMB(0x842108421084210)), + P(37,CNST_LIMB(0x14c1bacf914c1bad),CNST_LIMB(0x6eb3e45306eb3e4)), + P(41,CNST_LIMB(0x8f9c18f9c18f9c19),CNST_LIMB(0x63e7063e7063e70)), + P(43,CNST_LIMB(0x82fa0be82fa0be83),CNST_LIMB(0x5f417d05f417d05)), + P(47,CNST_LIMB(0x51b3bea3677d46cf),CNST_LIMB(0x572620ae4c415c9)), + P(53,CNST_LIMB(0x21cfb2b78c13521d),CNST_LIMB(0x4d4873ecade304d)), + P(59,CNST_LIMB(0xcbeea4e1a08ad8f3),CNST_LIMB(0x456c797dd49c341)), + P(61,CNST_LIMB(0x4fbcda3ac10c9715),CNST_LIMB(0x4325c53ef368eb0)), + P(67,CNST_LIMB(0xf0b7672a07a44c6b),CNST_LIMB(0x3d226357e16ece5)), + P(71,CNST_LIMB(0x193d4bb7e327a977),CNST_LIMB(0x39b0ad12073615a)), + P(73,CNST_LIMB(0x7e3f1f8fc7e3f1f9),CNST_LIMB(0x381c0e070381c0e)), + P(79,CNST_LIMB(0x9b8b577e613716af),CNST_LIMB(0x33d91d2a2067b23)), + P(83,CNST_LIMB(0xa3784a062b2e43db),CNST_LIMB(0x3159721ed7e7534)), + P(89,CNST_LIMB(0xf47e8fd1fa3f47e9),CNST_LIMB(0x2e05c0b81702e05)), + P(97,CNST_LIMB(0xa3a0fd5c5f02a3a1),CNST_LIMB(0x2a3a0fd5c5f02a3)), + P(101,CNST_LIMB(0x3a4c0a237c32b16d),CNST_LIMB(0x288df0cac5b3f5d)), + P(103,CNST_LIMB(0xdab7ec1dd3431b57),CNST_LIMB(0x27c45979c95204f)), + P(107,CNST_LIMB(0x77a04c8f8d28ac43),CNST_LIMB(0x2647c69456217ec)), + P(109,CNST_LIMB(0xa6c0964fda6c0965),CNST_LIMB(0x2593f69b02593f6)), + P(113,CNST_LIMB(0x90fdbc090fdbc091),CNST_LIMB(0x243f6f0243f6f02)), + P(127,CNST_LIMB(0x7efdfbf7efdfbf7f),CNST_LIMB(0x204081020408102)), + P(131,CNST_LIMB(0x3e88cb3c9484e2b),CNST_LIMB(0x1f44659e4a42715)), + P(137,CNST_LIMB(0xe21a291c077975b9),CNST_LIMB(0x1de5d6e3f8868a4)), + P(139,CNST_LIMB(0x3aef6ca970586723),CNST_LIMB(0x1d77b654b82c339)), + P(149,CNST_LIMB(0xdf5b0f768ce2cabd),CNST_LIMB(0x1b7d6c3dda338b2)), + P(151,CNST_LIMB(0x6fe4dfc9bf937f27),CNST_LIMB(0x1b2036406c80d90)), + P(157,CNST_LIMB(0x5b4fe5e92c0685b5),CNST_LIMB(0x1a16d3f97a4b01a)), + P(163,CNST_LIMB(0x1f693a1c451ab30b),CNST_LIMB(0x1920fb49d0e228d)), + P(167,CNST_LIMB(0x8d07aa27db35a717),CNST_LIMB(0x1886e5f0abb0499)), + P(173,CNST_LIMB(0x882383b30d516325),CNST_LIMB(0x17ad2208e0ecc35)), + P(179,CNST_LIMB(0xed6866f8d962ae7b),CNST_LIMB(0x16e1f76b4337c6c)), + P(181,CNST_LIMB(0x3454dca410f8ed9d),CNST_LIMB(0x16a13cd15372904)), + P(191,CNST_LIMB(0x1d7ca632ee936f3f),CNST_LIMB(0x1571ed3c506b39a)), + P(193,CNST_LIMB(0x70bf015390948f41),CNST_LIMB(0x15390948f40feac)), + P(197,CNST_LIMB(0xc96bdb9d3d137e0d),CNST_LIMB(0x14cab88725af6e7)), + P(199,CNST_LIMB(0x2697cc8aef46c0f7),CNST_LIMB(0x149539e3b2d066e)), + P(211,CNST_LIMB(0xc0e8f2a76e68575b),CNST_LIMB(0x13698df3de07479)), + P(223,CNST_LIMB(0x687763dfdb43bb1f),CNST_LIMB(0x125e22708092f11)), + P(227,CNST_LIMB(0x1b10ea929ba144cb),CNST_LIMB(0x120b470c67c0d88)), + P(229,CNST_LIMB(0x1d10c4c0478bbced),CNST_LIMB(0x11e2ef3b3fb8744)), + P(233,CNST_LIMB(0x63fb9aeb1fdcd759),CNST_LIMB(0x119453808ca29c0)), + P(239,CNST_LIMB(0x64afaa4f437b2e0f),CNST_LIMB(0x112358e75d30336)), + P(241,CNST_LIMB(0xf010fef010fef011),CNST_LIMB(0x10fef010fef010f)), + P(251,CNST_LIMB(0x28cbfbeb9a020a33),CNST_LIMB(0x105197f7d734041)), + P(257,CNST_LIMB(0xff00ff00ff00ff01),CNST_LIMB(0xff00ff00ff00ff)), + P(263,CNST_LIMB(0xd624fd1470e99cb7),CNST_LIMB(0xf92fb2211855a8)), + P(269,CNST_LIMB(0x8fb3ddbd6205b5c5),CNST_LIMB(0xf3a0d52cba8723)), + P(271,CNST_LIMB(0xd57da36ca27acdef),CNST_LIMB(0xf1d48bcee0d399)), + P(277,CNST_LIMB(0xee70c03b25e4463d),CNST_LIMB(0xec979118f3fc4d)), + P(281,CNST_LIMB(0xc5b1a6b80749cb29),CNST_LIMB(0xe939651fe2d8d3)), + P(283,CNST_LIMB(0x47768073c9b97113),CNST_LIMB(0xe79372e225fe30)), + P(293,CNST_LIMB(0x2591e94884ce32ad),CNST_LIMB(0xdfac1f74346c57)), + P(307,CNST_LIMB(0xf02806abc74be1fb),CNST_LIMB(0xd578e97c3f5fe5)), + P(311,CNST_LIMB(0x7ec3e8f3a7198487),CNST_LIMB(0xd2ba083b445250)), + P(313,CNST_LIMB(0x58550f8a39409d09),CNST_LIMB(0xd161543e28e502)), + P(317,CNST_LIMB(0xec9e48ae6f71de15),CNST_LIMB(0xcebcf8bb5b4169)), + P(331,CNST_LIMB(0x2ff3a018bfce8063),CNST_LIMB(0xc5fe740317f9d0)), + P(337,CNST_LIMB(0x7f9ec3fcf61fe7b1),CNST_LIMB(0xc2780613c0309e)), + P(347,CNST_LIMB(0x89f5abe570e046d3),CNST_LIMB(0xbcdd535db1cc5b)), + P(349,CNST_LIMB(0xda971b23f1545af5),CNST_LIMB(0xbbc8408cd63069)), + P(353,CNST_LIMB(0x79d5f00b9a7862a1),CNST_LIMB(0xb9a7862a0ff465)), + P(359,CNST_LIMB(0x4dba1df32a128a57),CNST_LIMB(0xb68d31340e4307)), + P(367,CNST_LIMB(0x87530217b7747d8f),CNST_LIMB(0xb2927c29da5519)), + P(373,CNST_LIMB(0x30baae53bb5e06dd),CNST_LIMB(0xafb321a1496fdf)), + P(379,CNST_LIMB(0xee70206c12e9b5b3),CNST_LIMB(0xaceb0f891e6551)), + P(383,CNST_LIMB(0xcdde9462ec9dbe7f),CNST_LIMB(0xab1cbdd3e2970f)), + P(389,CNST_LIMB(0xafb64b05ec41cf4d),CNST_LIMB(0xa87917088e262b)), + P(397,CNST_LIMB(0x2944ff5aec02945),CNST_LIMB(0xa513fd6bb00a51)), + P(401,CNST_LIMB(0x2cb033128382df71),CNST_LIMB(0xa36e71a2cb0331)), + P(409,CNST_LIMB(0x1ccacc0c84b1c2a9),CNST_LIMB(0xa03c1688732b30)), + P(419,CNST_LIMB(0x19a93db575eb3a0b),CNST_LIMB(0x9c69169b30446d)), + P(421,CNST_LIMB(0xcebeef94fa86fe2d),CNST_LIMB(0x9baade8e4a2f6e)), + P(431,CNST_LIMB(0x6faa77fb3f8df54f),CNST_LIMB(0x980e4156201301)), + P(433,CNST_LIMB(0x68a58af00975a751),CNST_LIMB(0x975a750ff68a58)), + P(439,CNST_LIMB(0xd56e36d0c3efac07),CNST_LIMB(0x9548e4979e0829)), + P(443,CNST_LIMB(0xd8b44c47a8299b73),CNST_LIMB(0x93efd1c50e726b)), + P(449,CNST_LIMB(0x2d9ccaf9ba70e41),CNST_LIMB(0x91f5bcb8bb02d9)), + P(457,CNST_LIMB(0x985e1c023d9e879),CNST_LIMB(0x8f67a1e3fdc261)), + P(461,CNST_LIMB(0x2a343316c494d305),CNST_LIMB(0x8e2917e0e702c6)), + P(463,CNST_LIMB(0x70cb7916ab67652f),CNST_LIMB(0x8d8be33f95d715)), + P(467,CNST_LIMB(0xd398f132fb10fe5b),CNST_LIMB(0x8c55841c815ed5)), + P(479,CNST_LIMB(0x6f2a38a6bf54fa1f),CNST_LIMB(0x88d180cd3a4133)), + P(487,CNST_LIMB(0x211df689b98f81d7),CNST_LIMB(0x869222b1acf1ce)), + P(491,CNST_LIMB(0xe994983e90f1ec3),CNST_LIMB(0x85797b917765ab)), + P(499,CNST_LIMB(0xad671e44bed87f3b),CNST_LIMB(0x8355ace3c897db)), + P(503,CNST_LIMB(0xf9623a0516e70fc7),CNST_LIMB(0x824a4e60b3262b)), + P(509,CNST_LIMB(0x4b7129be9dece355),CNST_LIMB(0x80c121b28bd1ba)), + P(521,CNST_LIMB(0x190f3b7473f62c39),CNST_LIMB(0x7dc9f3397d4c29)), + P(523,CNST_LIMB(0x63dacc9aad46f9a3),CNST_LIMB(0x7d4ece8fe88139)), + P(541,CNST_LIMB(0xc1108fda24e8d035),CNST_LIMB(0x79237d65bcce50)), + P(547,CNST_LIMB(0xb77578472319bd8b),CNST_LIMB(0x77cf53c5f7936c)), + P(557,CNST_LIMB(0x473d20a1c7ed9da5),CNST_LIMB(0x75a8accfbdd11e)), + P(563,CNST_LIMB(0xfbe85af0fea2c8fb),CNST_LIMB(0x7467ac557c228e)), + P(569,CNST_LIMB(0x58a1f7e6ce0f4c09),CNST_LIMB(0x732d70ed8db8e9)), + P(571,CNST_LIMB(0x1a00e58c544986f3),CNST_LIMB(0x72c62a24c3797f)), + P(577,CNST_LIMB(0x7194a17f55a10dc1),CNST_LIMB(0x7194a17f55a10d)), + P(587,CNST_LIMB(0x7084944785e33763),CNST_LIMB(0x6fa549b41da7e7)), + P(593,CNST_LIMB(0xba10679bd84886b1),CNST_LIMB(0x6e8419e6f61221)), + P(599,CNST_LIMB(0xebe9c6bb31260967),CNST_LIMB(0x6d68b5356c207b)), + P(601,CNST_LIMB(0x97a3fe4bd1ff25e9),CNST_LIMB(0x6d0b803685c01b)), + P(607,CNST_LIMB(0x6c6388395b84d99f),CNST_LIMB(0x6bf790a8b2d207)), + P(613,CNST_LIMB(0x8c51da6a1335df6d),CNST_LIMB(0x6ae907ef4b96c2)), + P(617,CNST_LIMB(0x46f3234475d5add9),CNST_LIMB(0x6a37991a23aead)), + P(619,CNST_LIMB(0x905605ca3c619a43),CNST_LIMB(0x69dfbdd4295b66)), + P(631,CNST_LIMB(0xcee8dff304767747),CNST_LIMB(0x67dc4c45c8033e)), + P(641,CNST_LIMB(0xff99c27f00663d81),CNST_LIMB(0x663d80ff99c27f)), + P(643,CNST_LIMB(0xacca407f671ddc2b),CNST_LIMB(0x65ec17e3559948)), + P(647,CNST_LIMB(0xe71298bac1e12337),CNST_LIMB(0x654ac835cfba5c)), + P(653,CNST_LIMB(0xfa1e94309cd09045),CNST_LIMB(0x645c854ae10772)), + P(659,CNST_LIMB(0xbebccb8e91496b9b),CNST_LIMB(0x6372990e5f901f)), + P(661,CNST_LIMB(0x312fa30cc7d7b8bd),CNST_LIMB(0x6325913c07beef)), + P(673,CNST_LIMB(0x6160ff9e9f006161),CNST_LIMB(0x6160ff9e9f0061)), + P(677,CNST_LIMB(0x6b03673b5e28152d),CNST_LIMB(0x60cdb520e5e88e)), + P(683,CNST_LIMB(0xfe802ffa00bfe803),CNST_LIMB(0x5ff4017fd005ff)), + P(691,CNST_LIMB(0xe66fe25c9e907c7b),CNST_LIMB(0x5ed79e31a4dccd)), + P(701,CNST_LIMB(0x3f8b236c76528895),CNST_LIMB(0x5d7d42d48ac5ef)), + P(709,CNST_LIMB(0xf6f923bf01ce2c0d),CNST_LIMB(0x5c6f35ccba5028)), + P(719,CNST_LIMB(0x6c3d3d98bed7c42f),CNST_LIMB(0x5b2618ec6ad0a5)), + P(727,CNST_LIMB(0x30981efcd4b010e7),CNST_LIMB(0x5a2553748e42e7)), + P(733,CNST_LIMB(0x6f691fc81ebbe575),CNST_LIMB(0x59686cf744cd5b)), + P(739,CNST_LIMB(0xb10480ddb47b52cb),CNST_LIMB(0x58ae97bab79976)), + P(743,CNST_LIMB(0x74cd59ed64f3f0d7),CNST_LIMB(0x58345f1876865f)), + P(751,CNST_LIMB(0x105cb81316d6c0f),CNST_LIMB(0x5743d5bb24795a)), + P(757,CNST_LIMB(0x9be64c6d91c1195d),CNST_LIMB(0x5692c4d1ab74ab)), + P(761,CNST_LIMB(0x71b3f945a27b1f49),CNST_LIMB(0x561e46a4d5f337)), + P(769,CNST_LIMB(0x77d80d50e508fd01),CNST_LIMB(0x5538ed06533997)), + P(773,CNST_LIMB(0xa5eb778e133551cd),CNST_LIMB(0x54c807f2c0bec2)), + P(787,CNST_LIMB(0x18657d3c2d8a3f1b),CNST_LIMB(0x5345efbc572d36)), + P(797,CNST_LIMB(0x2e40e220c34ad735),CNST_LIMB(0x523a758f941345)), + P(809,CNST_LIMB(0xa76593c70a714919),CNST_LIMB(0x5102370f816c89)), + P(811,CNST_LIMB(0x1eef452124eea383),CNST_LIMB(0x50cf129fb94acf)), + P(821,CNST_LIMB(0x38206dc242ba771d),CNST_LIMB(0x4fd31941cafdd1)), + P(823,CNST_LIMB(0x4cd4c35807772287),CNST_LIMB(0x4fa1704aa75945)), + P(827,CNST_LIMB(0x83de917d5e69ddf3),CNST_LIMB(0x4f3ed6d45a63ad)), + P(829,CNST_LIMB(0x882ef0403b4a6c15),CNST_LIMB(0x4f0de57154ebed)), + P(839,CNST_LIMB(0xf8fb6c51c606b677),CNST_LIMB(0x4e1cae8815f811)), + P(853,CNST_LIMB(0xb4abaac446d3e1fd),CNST_LIMB(0x4cd47ba5f6ff19)), + P(857,CNST_LIMB(0xa9f83bbe484a14e9),CNST_LIMB(0x4c78ae734df709)), + P(859,CNST_LIMB(0xbebbc0d1ce874d3),CNST_LIMB(0x4c4b19ed85cfb8)), + P(863,CNST_LIMB(0xbd418eaf0473189f),CNST_LIMB(0x4bf093221d1218)), + P(877,CNST_LIMB(0x44e3af6f372b7e65),CNST_LIMB(0x4aba3c21dc633f)), + P(881,CNST_LIMB(0xc87fdace4f9e5d91),CNST_LIMB(0x4a6360c344de00)), + P(883,CNST_LIMB(0xec93479c446bd9bb),CNST_LIMB(0x4a383e9f74d68a)), + P(887,CNST_LIMB(0xdac4d592e777c647),CNST_LIMB(0x49e28fbabb9940)), + P(907,CNST_LIMB(0xa63ea8c8f61f0c23),CNST_LIMB(0x48417b57c78cd7)), + P(911,CNST_LIMB(0xe476062ea5cbbb6f),CNST_LIMB(0x47f043713f3a2b)), + P(919,CNST_LIMB(0xdf68761c69daac27),CNST_LIMB(0x474ff2a10281cf)), + P(929,CNST_LIMB(0xb813d737637aa061),CNST_LIMB(0x468b6f9a978f91)), + P(937,CNST_LIMB(0xa3a77aac1fb15099),CNST_LIMB(0x45f13f1caff2e2)), + P(941,CNST_LIMB(0x17f0c3e0712c5825),CNST_LIMB(0x45a5228cec23e9)), + P(947,CNST_LIMB(0xfd912a70ff30637b),CNST_LIMB(0x45342c556c66b9)), + P(953,CNST_LIMB(0xfbb3b5dc01131289),CNST_LIMB(0x44c4a23feeced7)), + P(967,CNST_LIMB(0x856d560a0f5acdf7),CNST_LIMB(0x43c5c20d3c9fe6)), + P(971,CNST_LIMB(0x96472f314d3f89e3),CNST_LIMB(0x437e494b239798)), + P(977,CNST_LIMB(0xa76f5c7ed2253531),CNST_LIMB(0x43142d118e47cb)), + P(983,CNST_LIMB(0x816eae7c7bf69fe7),CNST_LIMB(0x42ab5c73a13458)), + P(991,CNST_LIMB(0xb6a2bea4cfb1781f),CNST_LIMB(0x4221950db0f3db)), + P(997,CNST_LIMB(0xa3900c53318e81ed),CNST_LIMB(0x41bbb2f80a4553)), + P(1009,CNST_LIMB(0x60aa7f5d9f148d11),CNST_LIMB(0x40f391612c6680)), + P(1013,CNST_LIMB(0x6be8c0102c7a505d),CNST_LIMB(0x40b1e94173fefd)), + P(1019,CNST_LIMB(0x8ff3f0ed28728f33),CNST_LIMB(0x4050647d9d0445)), + P(1021,CNST_LIMB(0x680e0a87e5ec7155),CNST_LIMB(0x4030241b144f3b)), + P(1031,CNST_LIMB(0xbbf70fa49fe829b7),CNST_LIMB(0x3f90c2ab542cb1)), + P(1033,CNST_LIMB(0xd69d1e7b6a50ca39),CNST_LIMB(0x3f71412d59f597)), + P(1039,CNST_LIMB(0x1a1e0f46b6d26aef),CNST_LIMB(0x3f137701b98841)), + P(1049,CNST_LIMB(0x7429f9a7a8251829),CNST_LIMB(0x3e79886b60e278)), + P(1051,CNST_LIMB(0xd9c2219d1b863613),CNST_LIMB(0x3e5b1916a7181d)), + P(1061,CNST_LIMB(0x91406c1820d077ad),CNST_LIMB(0x3dc4a50968f524)), + P(1063,CNST_LIMB(0x521f4ec02e3d2b97),CNST_LIMB(0x3da6e4c9550321)), + P(1069,CNST_LIMB(0xbb8283b63dc8eba5),CNST_LIMB(0x3d4e4f06f1def3)), + P(1087,CNST_LIMB(0x431eda153229ebbf),CNST_LIMB(0x3c4a6bdd24f9a4)), + P(1091,CNST_LIMB(0xaf0bf78d7e01686b),CNST_LIMB(0x3c11d54b525c73)), + P(1093,CNST_LIMB(0xa9ced0742c086e8d),CNST_LIMB(0x3bf5b1c5721065)), + P(1097,CNST_LIMB(0xc26458ad9f632df9),CNST_LIMB(0x3bbdb9862f23b4)), + P(1103,CNST_LIMB(0xbbff1255dff892af),CNST_LIMB(0x3b6a8801db5440)), + P(1109,CNST_LIMB(0xcbd49a333f04d8fd),CNST_LIMB(0x3b183cf0fed886)), + P(1117,CNST_LIMB(0xec84ed6f9cfdeff5),CNST_LIMB(0x3aabe394bdc3f4)), + P(1123,CNST_LIMB(0x97980cc40bda9d4b),CNST_LIMB(0x3a5ba3e76156da)), + P(1129,CNST_LIMB(0x777f34d524f5cbd9),CNST_LIMB(0x3a0c3e953378db)), + P(1151,CNST_LIMB(0x2797051d94cbbb7f),CNST_LIMB(0x38f03561320b1e)), + P(1153,CNST_LIMB(0xea769051b4f43b81),CNST_LIMB(0x38d6ecaef5908a)), + P(1163,CNST_LIMB(0xce7910f3034d4323),CNST_LIMB(0x3859cf221e6069)), + P(1171,CNST_LIMB(0x92791d1374f5b99b),CNST_LIMB(0x37f7415dc9588a)), + P(1181,CNST_LIMB(0x89a5645cc68ea1b5),CNST_LIMB(0x377df0d3902626)), + P(1187,CNST_LIMB(0x5f8aacf796c0cf0b),CNST_LIMB(0x373622136907fa)), + P(1193,CNST_LIMB(0xf2e90a15e33edf99),CNST_LIMB(0x36ef0c3b39b92f)), + P(1201,CNST_LIMB(0x8e99e5feb897c451),CNST_LIMB(0x36915f47d55e6d)), + P(1213,CNST_LIMB(0xaca2eda38fb91695),CNST_LIMB(0x36072cf3f866fd)), + P(1217,CNST_LIMB(0x5d9b737be5ea8b41),CNST_LIMB(0x35d9b737be5ea8)), + P(1223,CNST_LIMB(0x4aefe1db93fd7cf7),CNST_LIMB(0x35961559cc81c7)), + P(1229,CNST_LIMB(0xa0994ef20b3f8805),CNST_LIMB(0x35531c897a4592)), + P(1231,CNST_LIMB(0x103890bda912822f),CNST_LIMB(0x353ceebd3e98a4)), + P(1237,CNST_LIMB(0xb441659d13a9147d),CNST_LIMB(0x34fad381585e5e)), + P(1249,CNST_LIMB(0x1e2134440c4c3f21),CNST_LIMB(0x347884d1103130)), + P(1259,CNST_LIMB(0x263a27727a6883c3),CNST_LIMB(0x340dd3ac39bf56)), + P(1277,CNST_LIMB(0x78e221472ab33855),CNST_LIMB(0x3351fdfecc140c)), + P(1279,CNST_LIMB(0x95eac88e82e6faff),CNST_LIMB(0x333d72b089b524)), + P(1283,CNST_LIMB(0xf66c258317be8dab),CNST_LIMB(0x33148d44d6b261)), + P(1289,CNST_LIMB(0x9ee202c7cb91939),CNST_LIMB(0x32d7aef8412458)), + P(1291,CNST_LIMB(0x8d2fca1042a09ea3),CNST_LIMB(0x32c3850e79c0f1)), + P(1297,CNST_LIMB(0x82779c856d8b8bf1),CNST_LIMB(0x328766d59048a2)), + P(1301,CNST_LIMB(0x3879361cba8a223d),CNST_LIMB(0x325fa18cb11833)), + P(1303,CNST_LIMB(0xf23f43639c3182a7),CNST_LIMB(0x324bd659327e22)), + P(1307,CNST_LIMB(0xa03868fc474bcd13),CNST_LIMB(0x32246e784360f4)), + P(1319,CNST_LIMB(0x651e78b8c5311a97),CNST_LIMB(0x31afa5f1a33a08)), + P(1321,CNST_LIMB(0x8ffce639c00c6719),CNST_LIMB(0x319c63ff398e70)), + P(1327,CNST_LIMB(0xf7b460754b0b61cf),CNST_LIMB(0x3162f7519a86a7)), + P(1361,CNST_LIMB(0x7b03f3359b8e63b1),CNST_LIMB(0x30271fc9d3fc3c)), + P(1367,CNST_LIMB(0xa55c5326041eb667),CNST_LIMB(0x2ff104ae89750b)), + P(1373,CNST_LIMB(0x647f88ab896a76f5),CNST_LIMB(0x2fbb62a236d133)), + P(1381,CNST_LIMB(0x8fd971434a55a46d),CNST_LIMB(0x2f74997d2070b4)), + P(1399,CNST_LIMB(0x9fbf969958046447),CNST_LIMB(0x2ed84aa8b6fce3)), + P(1409,CNST_LIMB(0x9986feba69be3a81),CNST_LIMB(0x2e832df7a46dbd)), + P(1423,CNST_LIMB(0xa668b3e6d053796f),CNST_LIMB(0x2e0e0846857cab)), + P(1427,CNST_LIMB(0x97694e6589f4e09b),CNST_LIMB(0x2decfbdfb55ee6)), + P(1429,CNST_LIMB(0x37890c00b7721dbd),CNST_LIMB(0x2ddc876f3ff488)), + P(1433,CNST_LIMB(0x5ac094a235f37ea9),CNST_LIMB(0x2dbbc1d4c482c4)), + P(1439,CNST_LIMB(0x31cff775f2d5d65f),CNST_LIMB(0x2d8af0e0de0556)), + P(1447,CNST_LIMB(0xddad8e6b36505217),CNST_LIMB(0x2d4a7b7d14b30a)), + P(1451,CNST_LIMB(0x5a27df897062cd03),CNST_LIMB(0x2d2a85073bcf4e)), + P(1453,CNST_LIMB(0xe2396fe0fdb5a625),CNST_LIMB(0x2d1a9ab13e8be4)), + P(1459,CNST_LIMB(0xb352a4957e82317b),CNST_LIMB(0x2ceb1eb4b9fd8b)), + P(1471,CNST_LIMB(0xd8ab3f2c60c2ea3f),CNST_LIMB(0x2c8d503a79794c)), + P(1481,CNST_LIMB(0x6893f702f0452479),CNST_LIMB(0x2c404d708784ed)), + P(1483,CNST_LIMB(0x9686fdc182acf7e3),CNST_LIMB(0x2c31066315ec52)), + P(1487,CNST_LIMB(0x6854037173dce12f),CNST_LIMB(0x2c1297d80f2664)), + P(1489,CNST_LIMB(0x7f0ded1685c27331),CNST_LIMB(0x2c037044c55f6b)), + P(1493,CNST_LIMB(0xeeda72e1fe490b7d),CNST_LIMB(0x2be5404cd13086)), + P(1499,CNST_LIMB(0x9e7bfc959a8e6e53),CNST_LIMB(0x2bb845adaf0cce)), + P(1511,CNST_LIMB(0x49b314d6d4753dd7),CNST_LIMB(0x2b5f62c639f16d)), + P(1523,CNST_LIMB(0x2e8f8c5ac4aa1b3b),CNST_LIMB(0x2b07e6734f2b88)), + P(1531,CNST_LIMB(0xb8ef723481163d33),CNST_LIMB(0x2ace569d8342b7)), + P(1543,CNST_LIMB(0x6a2ec96a594287b7),CNST_LIMB(0x2a791d5dbd4dcf)), + P(1549,CNST_LIMB(0xdba41c6d13aab8c5),CNST_LIMB(0x2a4eff8113017c)), + P(1553,CNST_LIMB(0xc2adbe648dc3aaf1),CNST_LIMB(0x2a3319e156df32)), + P(1559,CNST_LIMB(0x87a2bade565f91a7),CNST_LIMB(0x2a0986286526ea)), + P(1567,CNST_LIMB(0x4d6fe8798c01f5df),CNST_LIMB(0x29d29551d91e39)), + P(1571,CNST_LIMB(0x3791310c8c23d98b),CNST_LIMB(0x29b7529e109f0a)), + P(1579,CNST_LIMB(0xf80e446b01228883),CNST_LIMB(0x298137491ea465)), + P(1583,CNST_LIMB(0x9aed1436fbf500cf),CNST_LIMB(0x29665e1eb9f9da)), + P(1597,CNST_LIMB(0x7839b54cc8b24115),CNST_LIMB(0x2909752e019a5e)), + P(1601,CNST_LIMB(0xc128c646ad0309c1),CNST_LIMB(0x28ef35e2e5efb0)), + P(1607,CNST_LIMB(0x14de631624a3c377),CNST_LIMB(0x28c815aa4b8278)), + P(1609,CNST_LIMB(0x3f7b9fe68b0ecbf9),CNST_LIMB(0x28bb1b867199da)), + P(1613,CNST_LIMB(0x284ffd75ec00a285),CNST_LIMB(0x28a13ff5d7b002)), + P(1619,CNST_LIMB(0x37803cb80dea2ddb),CNST_LIMB(0x287ab3f173e755)), + P(1621,CNST_LIMB(0x86b63f7c9ac4c6fd),CNST_LIMB(0x286dead67713bd)), + P(1627,CNST_LIMB(0x8b6851d1bd99b9d3),CNST_LIMB(0x2847bfcda6503e)), + P(1637,CNST_LIMB(0xb62fda77ca343b6d),CNST_LIMB(0x2808c1ea6b4777)), + P(1657,CNST_LIMB(0x1f0dc009e34383c9),CNST_LIMB(0x278d0e0f23ff61)), + P(1663,CNST_LIMB(0x496dc21ddd35b97f),CNST_LIMB(0x2768863c093c7f)), + P(1667,CNST_LIMB(0xb0e96ce17090f82b),CNST_LIMB(0x27505115a73ca8)), + P(1669,CNST_LIMB(0xaadf05acdd7d024d),CNST_LIMB(0x274441a61dc1b9)), + P(1693,CNST_LIMB(0xcb138196746eafb5),CNST_LIMB(0x26b5c166113cf0)), + P(1697,CNST_LIMB(0x347f523736755d61),CNST_LIMB(0x269e65ad07b18e)), + P(1699,CNST_LIMB(0xd14a48a051f7dd0b),CNST_LIMB(0x2692c25f877560)), + P(1709,CNST_LIMB(0x474d71b1ce914d25),CNST_LIMB(0x2658fa7523cd11)), + P(1721,CNST_LIMB(0x386063f5e28c1f89),CNST_LIMB(0x26148710cf0f9e)), + P(1723,CNST_LIMB(0x1db7325e32d04e73),CNST_LIMB(0x2609363b22524f)), + P(1733,CNST_LIMB(0xfef748d3893b880d),CNST_LIMB(0x25d1065a1c1122)), + P(1741,CNST_LIMB(0x2f3351506e935605),CNST_LIMB(0x25a48a382b863f)), + P(1747,CNST_LIMB(0x7a3637fa2376415b),CNST_LIMB(0x25837190eccdbc)), + P(1753,CNST_LIMB(0x4ac525d2baa21969),CNST_LIMB(0x256292e95d510c)), + P(1759,CNST_LIMB(0x3a11c16b42cd351f),CNST_LIMB(0x2541eda98d068c)), + P(1777,CNST_LIMB(0x6c7abde0049c2a11),CNST_LIMB(0x24e15087fed8f5)), + P(1783,CNST_LIMB(0x54dad0303e069ac7),CNST_LIMB(0x24c18b20979e5d)), + P(1787,CNST_LIMB(0xebf1ac9fdfe91433),CNST_LIMB(0x24ac7b336de0c5)), + P(1789,CNST_LIMB(0xfafdda8237cec655),CNST_LIMB(0x24a1fc478c60bb)), + P(1801,CNST_LIMB(0xdce3ff6e71ffb739),CNST_LIMB(0x2463801231c009)), + P(1811,CNST_LIMB(0xbed5737d6286db1b),CNST_LIMB(0x24300fd506ed33)), + P(1823,CNST_LIMB(0xe479e431fe08b4df),CNST_LIMB(0x23f314a494da81)), + P(1831,CNST_LIMB(0x9dd9b0dd7742f897),CNST_LIMB(0x23cadedd2fad3a)), + P(1847,CNST_LIMB(0x8f09d7402c5a5e87),CNST_LIMB(0x237b7ed2664a03)), + P(1861,CNST_LIMB(0x9216d5c4d958738d),CNST_LIMB(0x23372967dbaf1d)), + P(1867,CNST_LIMB(0xb3139ba11d34ca63),CNST_LIMB(0x231a308a371f20)), + P(1871,CNST_LIMB(0x47d54f7ed644afaf),CNST_LIMB(0x2306fa63e1e600)), + P(1873,CNST_LIMB(0x92a81d85cf11a1b1),CNST_LIMB(0x22fd6731575684)), + P(1877,CNST_LIMB(0x754b26533253bdfd),CNST_LIMB(0x22ea507805749c)), + P(1879,CNST_LIMB(0xbbe0efc980bfd467),CNST_LIMB(0x22e0cce8b3d720)), + P(1889,CNST_LIMB(0xc0d8d594f024dca1),CNST_LIMB(0x22b1887857d161)), + P(1901,CNST_LIMB(0x8238d43bcaac1a65),CNST_LIMB(0x227977fcc49cc0)), + P(1907,CNST_LIMB(0x27779c1fae6175bb),CNST_LIMB(0x225db37b5e5f4f)), + P(1913,CNST_LIMB(0xa746ca9af708b2c9),CNST_LIMB(0x22421b91322ed6)), + P(1931,CNST_LIMB(0x93f3cd9f389be823),CNST_LIMB(0x21f05b35f52102)), + P(1933,CNST_LIMB(0x5cb4a4c04c489345),CNST_LIMB(0x21e75de5c70d60)), + P(1949,CNST_LIMB(0xbf6047743e85b6b5),CNST_LIMB(0x21a01d6c19be96)), + P(1951,CNST_LIMB(0x61c147831563545f),CNST_LIMB(0x21974a6615c81a)), + P(1973,CNST_LIMB(0xedb47c0ae62dee9d),CNST_LIMB(0x213767697cf36a)), + P(1979,CNST_LIMB(0xa3824386673a573),CNST_LIMB(0x211d9f7fad35f1)), + P(1987,CNST_LIMB(0xa4a77d19e575a0eb),CNST_LIMB(0x20fb7d9dd36c18)), + P(1993,CNST_LIMB(0xa2bee045e066c279),CNST_LIMB(0x20e2123d661e0e)), + P(1997,CNST_LIMB(0xc23618de8ab43d05),CNST_LIMB(0x20d135b66ae990)), + P(1999,CNST_LIMB(0x266b515216cb9f2f),CNST_LIMB(0x20c8cded4d7a8e)), + P(2003,CNST_LIMB(0xe279edd9e9c2e85b),CNST_LIMB(0x20b80b3f43ddbf)), + P(2011,CNST_LIMB(0xd0c591c221dc9c53),CNST_LIMB(0x2096b9180f46a6)), + P(2017,CNST_LIMB(0x6da8ee9c9ee7c21),CNST_LIMB(0x207de7e28de5da)), + P(2027,CNST_LIMB(0x9dfebcaf4c27e8c3),CNST_LIMB(0x2054dec8cf1fb3)), + P(2029,CNST_LIMB(0x49aeff9f19dd6de5),CNST_LIMB(0x204cb630b3aab5)), + P(2039,CNST_LIMB(0x86976a57a296e9c7),CNST_LIMB(0x202428adc37beb)), + P(2053,CNST_LIMB(0xa3b9abf4872b84cd),CNST_LIMB(0x1fec0c7834def4)), + P(2063,CNST_LIMB(0x34fca6483895e6ef),CNST_LIMB(0x1fc46fae98a1d0)), + P(2069,CNST_LIMB(0x34b5a333988f873d),CNST_LIMB(0x1facda430ff619)), + P(2081,CNST_LIMB(0xd9dd4f19b5f17be1),CNST_LIMB(0x1f7e17dd8e15e5)), + P(2083,CNST_LIMB(0xb935b507fd0ce78b),CNST_LIMB(0x1f765a3556a4ee)), + P(2087,CNST_LIMB(0xb450f5540660e797),CNST_LIMB(0x1f66ea49d802f1)), + P(2089,CNST_LIMB(0x63ff82831ffc1419),CNST_LIMB(0x1f5f3800faf9c0)), + P(2099,CNST_LIMB(0x8992f718c22a32fb),CNST_LIMB(0x1f38f4e6c0f1f9)), + P(2111,CNST_LIMB(0x5f3253ad0d37e7bf),CNST_LIMB(0x1f0b8546752578)), + P(2113,CNST_LIMB(0x7c0ffe0fc007c1),CNST_LIMB(0x1f03ff83f001f0)), + P(2129,CNST_LIMB(0x4d8ebadc0c0640b1),CNST_LIMB(0x1ec853b0a3883c)), + P(2131,CNST_LIMB(0xe2729af831037bdb),CNST_LIMB(0x1ec0ee573723eb)), + P(2137,CNST_LIMB(0xb8f64bf30feebfe9),CNST_LIMB(0x1eaad38e6f6894)), + P(2141,CNST_LIMB(0xda93124b544c0bf5),CNST_LIMB(0x1e9c28a765fe53)), + P(2143,CNST_LIMB(0x9cf7ff0b593c539f),CNST_LIMB(0x1e94d8758c2003)), + P(2153,CNST_LIMB(0xd6bd8861fa0e07d9),CNST_LIMB(0x1e707ba8f65e68)), + P(2161,CNST_LIMB(0x5cfe75c0bd8ab891),CNST_LIMB(0x1e53a2a68f574e)), + P(2179,CNST_LIMB(0x43e808757c2e862b),CNST_LIMB(0x1e1380a56b438d)), + P(2203,CNST_LIMB(0x90caa96d595c9d93),CNST_LIMB(0x1dbf9f513a3802)), + P(2207,CNST_LIMB(0x8fd550625d07135f),CNST_LIMB(0x1db1d1d58bc600)), + P(2213,CNST_LIMB(0x76b010a86e209f2d),CNST_LIMB(0x1d9d358f53de38)), + P(2221,CNST_LIMB(0xecc0426447769b25),CNST_LIMB(0x1d81e6df6165c7)), + P(2237,CNST_LIMB(0xe381339caabe3295),CNST_LIMB(0x1d4bdf7fd40e30)), + P(2239,CNST_LIMB(0xd1b190a2d0c7673f),CNST_LIMB(0x1d452c7a1c958d)), + P(2243,CNST_LIMB(0xc3bce3cf26b0e7eb),CNST_LIMB(0x1d37cf9b902659)), + P(2251,CNST_LIMB(0x5f87e76f56c61ce3),CNST_LIMB(0x1d1d3a5791e97b)), + P(2267,CNST_LIMB(0xc06c6857a124b353),CNST_LIMB(0x1ce89fe6b47416)), + P(2269,CNST_LIMB(0x38c040fcba630f75),CNST_LIMB(0x1ce219f3235071)), + P(2273,CNST_LIMB(0xd078bc4fbd533b21),CNST_LIMB(0x1cd516dcf92139)), + P(2281,CNST_LIMB(0xde8e15c5dd354f59),CNST_LIMB(0x1cbb33bd1c2b8b)), + P(2287,CNST_LIMB(0xca61d53d7414260f),CNST_LIMB(0x1ca7e7d2546688)), + P(2293,CNST_LIMB(0xb56bf5ba8eae635d),CNST_LIMB(0x1c94b5c1b3dbd3)), + P(2297,CNST_LIMB(0x44a72cb0fb6e3949),CNST_LIMB(0x1c87f7f9c241c1)), + P(2309,CNST_LIMB(0x879839a714f45bcd),CNST_LIMB(0x1c6202706c35a9)), + P(2311,CNST_LIMB(0x2a8994fde5314b7),CNST_LIMB(0x1c5bb8a9437632)), + P(2333,CNST_LIMB(0xb971920cf2b90135),CNST_LIMB(0x1c174343b4111e)), + P(2339,CNST_LIMB(0x8a8fd0b7df9a6e8b),CNST_LIMB(0x1c04d0d3e46b42)), + P(2341,CNST_LIMB(0xb31f9a84c1c6eaad),CNST_LIMB(0x1bfeb00fbf4308)), + P(2347,CNST_LIMB(0x92293b02823c6d83),CNST_LIMB(0x1bec5dce0b202d)), + P(2351,CNST_LIMB(0xeee77ff20fe5ddcf),CNST_LIMB(0x1be03444620037)), + P(2357,CNST_LIMB(0xe1ea0f6c496c11d),CNST_LIMB(0x1bce09c66f6fc3)), + P(2371,CNST_LIMB(0xfdf2d3d6f88ccb6b),CNST_LIMB(0x1ba40228d02b30)), + P(2377,CNST_LIMB(0xfa9d74a3457738f9),CNST_LIMB(0x1b9225b1cf8919)), + P(2381,CNST_LIMB(0xefc3ca3db71a5785),CNST_LIMB(0x1b864a2ff3f53f)), + P(2383,CNST_LIMB(0x8e2071718d0d6daf),CNST_LIMB(0x1b80604150e49b)), + P(2389,CNST_LIMB(0xbc0fdbfeb6cfabfd),CNST_LIMB(0x1b6eb1aaeaacf3)), + P(2393,CNST_LIMB(0x1eeab613e5e5aee9),CNST_LIMB(0x1b62f48da3c8cc)), + P(2399,CNST_LIMB(0x2d2388e90e9e929f),CNST_LIMB(0x1b516babe96092)), + P(2411,CNST_LIMB(0x81dbafba588ddb43),CNST_LIMB(0x1b2e9cef1e0c87)), + P(2417,CNST_LIMB(0x52eebc51c4799791),CNST_LIMB(0x1b1d56bedc849b)), + P(2423,CNST_LIMB(0x1c6bc4693b45a047),CNST_LIMB(0x1b0c267546aec0)), + P(2437,CNST_LIMB(0x6eee0974498874d),CNST_LIMB(0x1ae45f62024fa0)), + P(2441,CNST_LIMB(0xd85b7377a9953cb9),CNST_LIMB(0x1ad917631b5f54)), + P(2447,CNST_LIMB(0x4b6df412d4caf56f),CNST_LIMB(0x1ac83d18cb608f)), + P(2459,CNST_LIMB(0x6b8afbbb4a053493),CNST_LIMB(0x1aa6c7ad8c063f)), + P(2467,CNST_LIMB(0xcc5299c96ac7720b),CNST_LIMB(0x1a90a7b1228e2a)), + P(2473,CNST_LIMB(0xadce84b5c710aa99),CNST_LIMB(0x1a8027c03ba059)), + P(2477,CNST_LIMB(0x9d673f5aa3804225),CNST_LIMB(0x1a7533289deb89)), + P(2503,CNST_LIMB(0xe6541268efbce7f7),CNST_LIMB(0x1a2ed7ce16b49f)), + P(2521,CNST_LIMB(0xfcf41e76cf5be669),CNST_LIMB(0x19fefc0a279a73)), + P(2531,CNST_LIMB(0x5c3eb5dc31c383cb),CNST_LIMB(0x19e4b0cd873b5f)), + P(2539,CNST_LIMB(0x301832d11d8ad6c3),CNST_LIMB(0x19cfcdfd60e514)), + P(2543,CNST_LIMB(0x2e9c0942f1ce450f),CNST_LIMB(0x19c56932d66c85)), + P(2549,CNST_LIMB(0x97f3f2be37a39a5d),CNST_LIMB(0x19b5e1ab6fc7c2)), + P(2551,CNST_LIMB(0xe8b7d8a9654187c7),CNST_LIMB(0x19b0b8a62f2a73)), + P(2557,CNST_LIMB(0xb5d024d7da5b1b55),CNST_LIMB(0x19a149fc98942c)), + P(2579,CNST_LIMB(0xb8ba9d6e7ae3501b),CNST_LIMB(0x1969517ec25b85)), + P(2591,CNST_LIMB(0xf50865f71b90f1df),CNST_LIMB(0x194b3083360ba8)), + P(2593,CNST_LIMB(0x739c1682847df9e1),CNST_LIMB(0x194631f4bebdc1)), + P(2609,CNST_LIMB(0xc470a4d842b90ed1),CNST_LIMB(0x191e84127268fd)), + P(2617,CNST_LIMB(0x1fb1be11698cc409),CNST_LIMB(0x190adbb543984f)), + P(2621,CNST_LIMB(0xd8d5512a7cd35d15),CNST_LIMB(0x1901130bd18200)), + P(2633,CNST_LIMB(0xa5496821723e07f9),CNST_LIMB(0x18e3e6b889ac94)), + P(2647,CNST_LIMB(0xbcc8c6d7abaa8167),CNST_LIMB(0x18c233420e1ec1)), + P(2657,CNST_LIMB(0x52c396c95eb619a1),CNST_LIMB(0x18aa5872d92bd6)), + P(2659,CNST_LIMB(0x6eb7e380878ec74b),CNST_LIMB(0x18a5989945ccf9)), + P(2663,CNST_LIMB(0x3d5513b504537157),CNST_LIMB(0x189c1e60b57f60)), + P(2671,CNST_LIMB(0x314391f8862e948f),CNST_LIMB(0x18893fbc8690b9)), + P(2677,CNST_LIMB(0xdc0b17cfcd81f5dd),CNST_LIMB(0x187b2bb3e1041c)), + P(2683,CNST_LIMB(0x2f6bea3ec89044b3),CNST_LIMB(0x186d27c9cdcfb8)), + P(2687,CNST_LIMB(0xce13a05869f1b57f),CNST_LIMB(0x1863d8bf4f2c1c)), + P(2689,CNST_LIMB(0x7593474e8ace3581),CNST_LIMB(0x185f33e2ad7593)), + P(2693,CNST_LIMB(0x7fc329295a05e4d),CNST_LIMB(0x1855ef75973e13)), + P(2699,CNST_LIMB(0xb05377cba4908d23),CNST_LIMB(0x1848160153f134)), + P(2707,CNST_LIMB(0xe7b2131a628aa39b),CNST_LIMB(0x1835b72e6f0656)), + P(2711,CNST_LIMB(0x9031dbed7de01527),CNST_LIMB(0x182c922d83eb39)), + P(2713,CNST_LIMB(0x76844b1c670aa9a9),CNST_LIMB(0x18280243c0365a)), + P(2719,CNST_LIMB(0x6a03f4533b08915f),CNST_LIMB(0x181a5cd5898e73)), + P(2729,CNST_LIMB(0x1dbca579db0a3999),CNST_LIMB(0x1803c0961773aa)), + P(2731,CNST_LIMB(0x2ffe800bffa003),CNST_LIMB(0x17ff4005ffd001)), + P(2741,CNST_LIMB(0x478ab1a3e936139d),CNST_LIMB(0x17e8d670433edb)), + P(2749,CNST_LIMB(0x66e722bc4c5cc095),CNST_LIMB(0x17d7066cf4bb5d)), + P(2753,CNST_LIMB(0x7a8f63c717278541),CNST_LIMB(0x17ce285b806b1f)), + P(2767,CNST_LIMB(0xdf6eee24d292bc2f),CNST_LIMB(0x17af52cdf27e02)), + P(2777,CNST_LIMB(0x9fc20d17237dd569),CNST_LIMB(0x17997d47d01039)), + P(2789,CNST_LIMB(0xcdf9932356bda2ed),CNST_LIMB(0x177f7ec2c6d0ba)), + P(2791,CNST_LIMB(0x97b5e332e80f68d7),CNST_LIMB(0x177b2f3cd00756)), + P(2797,CNST_LIMB(0x46eee26fd875e2e5),CNST_LIMB(0x176e4a22f692a0)), + P(2801,CNST_LIMB(0x3548a8e65157a611),CNST_LIMB(0x1765b94271e11b)), + P(2803,CNST_LIMB(0xc288d03be9b71e3b),CNST_LIMB(0x1761732b044ae4)), + P(2819,CNST_LIMB(0x8151186db38937ab),CNST_LIMB(0x173f7a5300a2bc)), + P(2833,CNST_LIMB(0x7800b910895a45f1),CNST_LIMB(0x1722112b48be1f)), + P(2837,CNST_LIMB(0xaee0b024182eec3d),CNST_LIMB(0x1719b7a16eb843)), + P(2843,CNST_LIMB(0x96323eda173b5713),CNST_LIMB(0x170d3c99cc5052)), + P(2851,CNST_LIMB(0xed0dbd03ae77c8b),CNST_LIMB(0x16fcad7aed3bb6)), + P(2857,CNST_LIMB(0xf73800b7828dc119),CNST_LIMB(0x16f051b8231ffd)), + P(2861,CNST_LIMB(0x1b61715ec22b7ca5),CNST_LIMB(0x16e81beae20643)), + P(2879,CNST_LIMB(0xa8533a991ead64bf),CNST_LIMB(0x16c3721584c1d8)), + P(2887,CNST_LIMB(0x7f6c7290e46c2e77),CNST_LIMB(0x16b34c2ba09663)), + P(2897,CNST_LIMB(0x6325e8d907b01db1),CNST_LIMB(0x169f3ce292ddcd)), + P(2903,CNST_LIMB(0x28909f70152a1067),CNST_LIMB(0x169344b2220a0d)), + P(2909,CNST_LIMB(0xea7077af0997a0f5),CNST_LIMB(0x1687592593c1b1)), + P(2917,CNST_LIMB(0x7e605cad10c32e6d),CNST_LIMB(0x167787f1418ec9)), + P(2927,CNST_LIMB(0x471b33570635b38f),CNST_LIMB(0x1663e190395ff2)), + P(2939,CNST_LIMB(0xab559fa997a61bb3),CNST_LIMB(0x164c7a4b6eb5b3)), + P(2953,CNST_LIMB(0xad4bdae562bddab9),CNST_LIMB(0x16316a061182fd)), + P(2957,CNST_LIMB(0x55e1b2f2ed62f45),CNST_LIMB(0x1629ba914584e4)), + P(2963,CNST_LIMB(0x3cd328b1a2dca9b),CNST_LIMB(0x161e3d57de21b2)), + P(2969,CNST_LIMB(0xd28f4e08733218a9),CNST_LIMB(0x1612cc01b977f0)), + P(2971,CNST_LIMB(0xb6800b077f186293),CNST_LIMB(0x160efe30c525ff)), + P(2999,CNST_LIMB(0x6fbd138c3fd9c207),CNST_LIMB(0x15da45249ec5de)), + P(3001,CNST_LIMB(0xb117ccd12ae88a89),CNST_LIMB(0x15d68ab4acff92)), + P(3011,CNST_LIMB(0x2f1a1a044046bceb),CNST_LIMB(0x15c3f989d1eb15)), + P(3019,CNST_LIMB(0x548aba0b060541e3),CNST_LIMB(0x15b535ad11b8f0)), + P(3023,CNST_LIMB(0xcf4e808cea111b2f),CNST_LIMB(0x15addb3f424ec1)), + P(3037,CNST_LIMB(0xdbec1b4fa855a475),CNST_LIMB(0x159445cb91be6b)), + P(3041,CNST_LIMB(0xe3f794eb600d7821),CNST_LIMB(0x158d0199771e63)), + P(3049,CNST_LIMB(0x34fae0d9a11f7c59),CNST_LIMB(0x157e87d9b69e04)), + P(3061,CNST_LIMB(0xf006b0ccbbac085d),CNST_LIMB(0x1568f58bc01ac3)), + P(3067,CNST_LIMB(0x3f45076dc3114733),CNST_LIMB(0x155e3c993fda9b)), + P(3079,CNST_LIMB(0xeef49bfa58a1a1b7),CNST_LIMB(0x1548eacc5e1e6e)), + P(3083,CNST_LIMB(0x12c4218bea691fa3),CNST_LIMB(0x1541d8f91ba6a7)), + P(3089,CNST_LIMB(0xbc7504e3bd5e64f1),CNST_LIMB(0x153747060cc340)), + P(3109,CNST_LIMB(0x4ee21c292bb92fad),CNST_LIMB(0x1514569f93f7c4)), + P(3119,CNST_LIMB(0x34338b7327a4bacf),CNST_LIMB(0x150309705d3d79)), + P(3121,CNST_LIMB(0x3fe5c0833d6fccd1),CNST_LIMB(0x14ff97020cf5bf)), + P(3137,CNST_LIMB(0xb1e70743535203c1),CNST_LIMB(0x14e42c114cf47e)), + P(3163,CNST_LIMB(0xefbb5dcdfb4e43d3),CNST_LIMB(0x14b835bdcb6447)), + P(3167,CNST_LIMB(0xca68467ca5394f9f),CNST_LIMB(0x14b182b53a9ab7)), + P(3169,CNST_LIMB(0x8c51c081408b97a1),CNST_LIMB(0x14ae2ad094a3d3)), + P(3181,CNST_LIMB(0x3275a899dfa5dd65),CNST_LIMB(0x149a320ea59f96)), + P(3187,CNST_LIMB(0x9e674cb62e1b78bb),CNST_LIMB(0x1490441de1a2fb)), + P(3191,CNST_LIMB(0xa37ff5bb2a998d47),CNST_LIMB(0x1489aacce57200)), + P(3203,CNST_LIMB(0x792a999db131a22b),CNST_LIMB(0x1475f82ad6ff99)), + P(3209,CNST_LIMB(0x1b48841bc30d29b9),CNST_LIMB(0x146c2cfe53204f)), + P(3217,CNST_LIMB(0xf06721d2011d3471),CNST_LIMB(0x145f2ca490d4a1)), + P(3221,CNST_LIMB(0x93fd2386dff85ebd),CNST_LIMB(0x1458b2aae0ec87)), + P(3229,CNST_LIMB(0x4ce72f54c07ed9b5),CNST_LIMB(0x144bcb0a3a3150)), + P(3251,CNST_LIMB(0xd6d0fd3e71dd827b),CNST_LIMB(0x1428a1e65441d4)), + P(3253,CNST_LIMB(0x856405fb1eed819d),CNST_LIMB(0x142575a6c210d7)), + P(3257,CNST_LIMB(0x8ea8aceb7c443989),CNST_LIMB(0x141f2025ba5c46)), + P(3259,CNST_LIMB(0x34a13026f62e5873),CNST_LIMB(0x141bf6e35420fd)), + P(3271,CNST_LIMB(0x1eea0208ec0af4f7),CNST_LIMB(0x1409141d1d313a)), + P(3299,CNST_LIMB(0x63679853cea598cb),CNST_LIMB(0x13dd8bc19c3513)), + P(3301,CNST_LIMB(0xc30b3ebd61f2d0ed),CNST_LIMB(0x13da76f714dc8f)), + P(3307,CNST_LIMB(0x7eb9037bc7f43bc3),CNST_LIMB(0x13d13e50f8f49e)), + P(3313,CNST_LIMB(0xa583e6f6ce016411),CNST_LIMB(0x13c80e37ca3819)), + P(3319,CNST_LIMB(0xf1938d895f1a74c7),CNST_LIMB(0x13bee69fa99ccf)), + P(3323,CNST_LIMB(0x80cf1491c1e81e33),CNST_LIMB(0x13b8d0ede55835)), + P(3329,CNST_LIMB(0x3c0f12886ba8f301),CNST_LIMB(0x13afb7680bb054)), + P(3331,CNST_LIMB(0xe4b786e0dfcc5ab),CNST_LIMB(0x13acb0c3841c96)), + P(3343,CNST_LIMB(0x672684c93f2d41ef),CNST_LIMB(0x139a9c5f434fde)), + P(3347,CNST_LIMB(0xe00757badb35c51b),CNST_LIMB(0x13949cf33a0d9d)), + P(3359,CNST_LIMB(0xd6d84afe66472edf),CNST_LIMB(0x1382b4a00c31b0)), + P(3361,CNST_LIMB(0xfbbc0eedcbbfb6e1),CNST_LIMB(0x137fbbc0eedcbb)), + P(3371,CNST_LIMB(0x250f43aa08a84983),CNST_LIMB(0x1370ecf047b069)), + P(3373,CNST_LIMB(0x4400e927b1acaa5),CNST_LIMB(0x136df9790e3155)), + P(3389,CNST_LIMB(0x56572be34b9d3215),CNST_LIMB(0x13567dd8defd5b)), + P(3391,CNST_LIMB(0x87964ef7781c62bf),CNST_LIMB(0x13539261fdbc34)), + P(3407,CNST_LIMB(0x29ed84051c06e9af),CNST_LIMB(0x133c564292d28a)), + P(3413,CNST_LIMB(0xb00acd11ed3f87fd),CNST_LIMB(0x1333ae178d6388)), + P(3433,CNST_LIMB(0x6307881744152d9),CNST_LIMB(0x13170ad00d1fd7)), + P(3449,CNST_LIMB(0x7a786459f5c1ccc9),CNST_LIMB(0x13005f01db0947)), + P(3457,CNST_LIMB(0x1308125d74563281),CNST_LIMB(0x12f51d40342210)), + P(3461,CNST_LIMB(0x395310a480b3e34d),CNST_LIMB(0x12ef815e4ed950)), + P(3463,CNST_LIMB(0x35985baa8b202837),CNST_LIMB(0x12ecb4abccd827)), + P(3467,CNST_LIMB(0x96304a6e052b3223),CNST_LIMB(0x12e71dc1d3d820)), + P(3469,CNST_LIMB(0xbd8265fc9af8fd45),CNST_LIMB(0x12e45389a16495)), + P(3491,CNST_LIMB(0x1b6d0b383ec58e0b),CNST_LIMB(0x12c5d9226476cc)), + P(3499,CNST_LIMB(0xc21a7c3b68b28503),CNST_LIMB(0x12badc391156fd)), + P(3511,CNST_LIMB(0x236fa180fbfd6007),CNST_LIMB(0x12aa78e412f522)), + P(3517,CNST_LIMB(0xc42accd440ed9595),CNST_LIMB(0x12a251f5f47fd1)), + P(3527,CNST_LIMB(0x7acf7128236ba3f7),CNST_LIMB(0x1294cb85c53534)), + P(3529,CNST_LIMB(0xf909367a987b9c79),CNST_LIMB(0x12921963beb65e)), + P(3533,CNST_LIMB(0xb64efb252bfba705),CNST_LIMB(0x128cb777c69ca8)), + P(3539,CNST_LIMB(0x980d4f5a7e4cd25b),CNST_LIMB(0x1284aa6cf07294)), + P(3541,CNST_LIMB(0xe1ecc4ef27b0c37d),CNST_LIMB(0x1281fcf6ac7f87)), + P(3547,CNST_LIMB(0x9111aebb81d72653),CNST_LIMB(0x1279f937367db9)), + P(3557,CNST_LIMB(0x8951f985cb2c67ed),CNST_LIMB(0x126cad0488be94)), + P(3559,CNST_LIMB(0xc439d4fc54e0b5d7),CNST_LIMB(0x126a06794646a2)), + P(3571,CNST_LIMB(0xe857bf31896d533b),CNST_LIMB(0x125a2f2bcd3e95)), + P(3581,CNST_LIMB(0xb614bb4cb5023755),CNST_LIMB(0x124d108389e6b1)), + P(3583,CNST_LIMB(0x938a89e5473bf1ff),CNST_LIMB(0x124a73083771ac)), + P(3593,CNST_LIMB(0xeac481aca34de039),CNST_LIMB(0x123d6acda0620a)), + P(3607,CNST_LIMB(0x14b961badf4809a7),CNST_LIMB(0x122b4b2917eafd)), + P(3613,CNST_LIMB(0x76784fecba352435),CNST_LIMB(0x122391bfce1e2f)), + P(3617,CNST_LIMB(0xefa689bb58aef5e1),CNST_LIMB(0x121e6f1ea579f2)), + P(3623,CNST_LIMB(0xb2b2c4db9c3a8197),CNST_LIMB(0x1216c09e471568)), + P(3631,CNST_LIMB(0x2503bc992279f8cf),CNST_LIMB(0x120c8cb9d93909)), + P(3637,CNST_LIMB(0xd2ab9aec5ca1541d),CNST_LIMB(0x1204ed58e64ef9)), + P(3643,CNST_LIMB(0x3e78ba1460f99af3),CNST_LIMB(0x11fd546578f00c)), + P(3659,CNST_LIMB(0xa01426572cfcb63),CNST_LIMB(0x11e9310b8b4c9c)), + P(3671,CNST_LIMB(0xbea857968f3cbd67),CNST_LIMB(0x11da3405db9911)), + P(3673,CNST_LIMB(0x78db213eefe659e9),CNST_LIMB(0x11d7b6f4eb055d)), + P(3677,CNST_LIMB(0x963e8541a74d35f5),CNST_LIMB(0x11d2bee748c145)), + P(3691,CNST_LIMB(0x9e22d152776f2e43),CNST_LIMB(0x11c1706ddce7a7)), + P(3697,CNST_LIMB(0x5d10d39d1e1f291),CNST_LIMB(0x11ba0fed2a4f14)), + P(3701,CNST_LIMB(0x374468dccaced1dd),CNST_LIMB(0x11b528538ed64a)), + P(3709,CNST_LIMB(0x8d145c7d110c5ad5),CNST_LIMB(0x11ab61404242ac)), + P(3719,CNST_LIMB(0x3251a39f5acb5737),CNST_LIMB(0x119f378ce81d2f)), + P(3727,CNST_LIMB(0xa66e50171443506f),CNST_LIMB(0x1195889ece79da)), + P(3733,CNST_LIMB(0x124f69ad91dd4cbd),CNST_LIMB(0x118e4c65387077)), + P(3739,CNST_LIMB(0xec24f8f2a61a2793),CNST_LIMB(0x1187161d70e725)), + P(3761,CNST_LIMB(0xb472148e656b7a51),CNST_LIMB(0x116cd6d1c85239)), + P(3767,CNST_LIMB(0xadf9570e1142f07),CNST_LIMB(0x1165bbe7ce86b1)), + P(3769,CNST_LIMB(0x89bf33b065119789),CNST_LIMB(0x11635ee344ce36)), + P(3779,CNST_LIMB(0x8f0149803cb291eb),CNST_LIMB(0x11579767b6d679)), + P(3793,CNST_LIMB(0x8334b63afd190a31),CNST_LIMB(0x114734711e2b54)), + P(3797,CNST_LIMB(0x920908d50d6aba7d),CNST_LIMB(0x11428b90147f05)), + P(3803,CNST_LIMB(0x57d8b018c5a33d53),CNST_LIMB(0x113b92f3021636)), + P(3821,CNST_LIMB(0xea1773092dc27ee5),CNST_LIMB(0x1126cabc886884)), + P(3823,CNST_LIMB(0xcae5f38b7bf2e00f),CNST_LIMB(0x11247eb1b85976)), + P(3833,CNST_LIMB(0x2bd02df34f695349),CNST_LIMB(0x11190bb01efd65)), + P(3847,CNST_LIMB(0xddfecd5be62e2eb7),CNST_LIMB(0x11091de0fd679c)), + P(3851,CNST_LIMB(0xdbf849ebec96c4a3),CNST_LIMB(0x1104963c7e4e0b)), + P(3853,CNST_LIMB(0xda31d4d0187357c5),CNST_LIMB(0x110253516420b0)), + P(3863,CNST_LIMB(0xe34e21cc2d5418a7),CNST_LIMB(0x10f70db7c41797)), + P(3877,CNST_LIMB(0x68ca5137a9e574ad),CNST_LIMB(0x10e75ee2bf9ecd)), + P(3881,CNST_LIMB(0x3eaa0d0f804bfd19),CNST_LIMB(0x10e2e91c6e0676)), + P(3889,CNST_LIMB(0x554fb753cc20e9d1),CNST_LIMB(0x10da049b9d428d)), + P(3907,CNST_LIMB(0x797afcca1300756b),CNST_LIMB(0x10c6248fe3b1a2)), + P(3911,CNST_LIMB(0x8b8d950b52eeea77),CNST_LIMB(0x10c1c03ed690eb)), + P(3917,CNST_LIMB(0xfb6cd166acabc185),CNST_LIMB(0x10bb2e1379e3a2)), + P(3919,CNST_LIMB(0x4eb6c5ed9437a7af),CNST_LIMB(0x10b8fe7f61228e)), + P(3923,CNST_LIMB(0xd1eddbd91b790cdb),CNST_LIMB(0x10b4a10d60a4f7)), + P(3929,CNST_LIMB(0x93d714ea4d8948e9),CNST_LIMB(0x10ae192681ec0f)), + P(3931,CNST_LIMB(0x3ca13ed8145188d3),CNST_LIMB(0x10abecfbe5b0ae)), + P(3943,CNST_LIMB(0x829086016da89c57),CNST_LIMB(0x109eefd568b96d)), + P(3947,CNST_LIMB(0xd7da1f432124a543),CNST_LIMB(0x109a9ff178b40c)), + P(3967,CNST_LIMB(0x7ead5581632fb07f),CNST_LIMB(0x108531e22f9ff9)), + P(3989,CNST_LIMB(0x35443837f63ec3bd),CNST_LIMB(0x106ddec1af4417)), + P(4001,CNST_LIMB(0x89e2b200e5519461),CNST_LIMB(0x10614174a4911d)), + P(4003,CNST_LIMB(0xe9ae44f0b7289c0b),CNST_LIMB(0x105f291f0448e7)), + P(4007,CNST_LIMB(0x94387a277b9fa817),CNST_LIMB(0x105afa0ef32891)), + P(4013,CNST_LIMB(0xc84f1a58abfc2c25),CNST_LIMB(0x1054b777bd2530)), + P(4019,CNST_LIMB(0x71101d8e3c83377b),CNST_LIMB(0x104e79a97fb69e)), + P(4021,CNST_LIMB(0xc024abe5c50ba69d),CNST_LIMB(0x104c661eafd845)), + P(4027,CNST_LIMB(0x15de4eb365a65d73),CNST_LIMB(0x10462ea939c933)), + P(4049,CNST_LIMB(0x9ed28a76bcca931),CNST_LIMB(0x102f8baa442836)), + P(4051,CNST_LIMB(0x816bffbf4a00205b),CNST_LIMB(0x102d7ff7e94004)), + P(4057,CNST_LIMB(0x1f5c71543d558069),CNST_LIMB(0x10275ff9f13c02)), + P(4073,CNST_LIMB(0xf25c64d0ec53b859),CNST_LIMB(0x1017213fcbb4d3)), + P(4079,CNST_LIMB(0x96c02c2ef1e0ff0f),CNST_LIMB(0x101112234579d1)), + P(4091,CNST_LIMB(0x19a804816870a333),CNST_LIMB(0x100501907d271c)), + P(4093,CNST_LIMB(0x6de49add0971c555),CNST_LIMB(0x100300901b0510)), + P(4099,CNST_LIMB(0x528087e684c71aab),CNST_LIMB(0xffd008fe5050f)), + P(4111,CNST_LIMB(0xa94152c269bcdeef),CNST_LIMB(0xff10e02dd5084)), + P(4127,CNST_LIMB(0x379450a3c2b6bdf),CNST_LIMB(0xfe13b9c80c67f)), + P(4129,CNST_LIMB(0xd2cd38bafe5373e1),CNST_LIMB(0xfdf4384be37ad)), + P(4133,CNST_LIMB(0xc29df2bea71d8bad),CNST_LIMB(0xfdb54cbe8766e)), + P(4139,CNST_LIMB(0xc15862775f302e83),CNST_LIMB(0xfd5725ca6ff32)), + P(4153,CNST_LIMB(0x1016af2fe55ede09),CNST_LIMB(0xfc7c84684c6fb)), + P(4157,CNST_LIMB(0x3d26dbd9d1910715),CNST_LIMB(0xfc3e5265dbaa8)), + P(4159,CNST_LIMB(0x621dab2dfaf3dfbf),CNST_LIMB(0xfc1f44e0cae12)), + P(4177,CNST_LIMB(0xb6f1d7ac287338b1),CNST_LIMB(0xfb0921c50a7af)), + P(4201,CNST_LIMB(0x8d9e9f0c3f9e7fd9),CNST_LIMB(0xf999fd70cbc6b)), + P(4211,CNST_LIMB(0x60a93f8762e914bb),CNST_LIMB(0xf9023fd5339d0)), + P(4217,CNST_LIMB(0xb14371f247c159c9),CNST_LIMB(0xf8a78ce671475)), + P(4219,CNST_LIMB(0x6dd3b484471d4eb3),CNST_LIMB(0xf8895fee86574)), + P(4229,CNST_LIMB(0xcd172f4701c1684d),CNST_LIMB(0xf7f2ecb084b10)), + P(4231,CNST_LIMB(0x372e686ed8bb537),CNST_LIMB(0xf7d4eb7d10c29)), + P(4241,CNST_LIMB(0xbc07f7ca65c5b071),CNST_LIMB(0xf73f52277a3c3)), + P(4243,CNST_LIMB(0xab2b6170c3f78d9b),CNST_LIMB(0xf7217c598961c)), + P(4253,CNST_LIMB(0xf3d74f461fe6f5b5),CNST_LIMB(0xf68cbb1448f42)), + P(4259,CNST_LIMB(0xdbc13f4b31f3230b),CNST_LIMB(0xf633d0276e4c5)), + P(4261,CNST_LIMB(0xd1420716e3f1572d),CNST_LIMB(0xf6163ac20ec79)), + P(4271,CNST_LIMB(0xd5be2fd4d805464f),CNST_LIMB(0xf582ba2bc16c6)), + P(4273,CNST_LIMB(0xc68b97c136943851),CNST_LIMB(0xf5654f43290a0)), + P(4283,CNST_LIMB(0x9e27918af7cfb473),CNST_LIMB(0xf4d2a23810bc6)), + P(4289,CNST_LIMB(0x5ec8ab6c36ac7f41),CNST_LIMB(0xf47af4d6a2f27)), + P(4297,CNST_LIMB(0x964076331dd90979),CNST_LIMB(0xf4066f2b6e652)), + P(4327,CNST_LIMB(0x30198eff77b002d7),CNST_LIMB(0xf2555048e3a92)), + P(4337,CNST_LIMB(0x3af7cb9583ece011),CNST_LIMB(0xf1c64588a5bf6)), + P(4339,CNST_LIMB(0x34ce06f643d9883b),CNST_LIMB(0xf1a9be09cb411)), + P(4349,CNST_LIMB(0x79f767e528708c55),CNST_LIMB(0xf11b7d5259d39)), + P(4357,CNST_LIMB(0x185332d2ef2313cd),CNST_LIMB(0xf0aa284e7f802)), + P(4363,CNST_LIMB(0x43b611b84c8332a3),CNST_LIMB(0xf0556e5e3b7f2)), + P(4373,CNST_LIMB(0xc2e215e4f43bb63d),CNST_LIMB(0xefc8bcbc808e5)), + P(4391,CNST_LIMB(0xf94b9dd22ce44e97),CNST_LIMB(0xeecd1a690efbb)), + P(4397,CNST_LIMB(0xd895834a1db166a5),CNST_LIMB(0xee79aed6d65f2)), + P(4409,CNST_LIMB(0x347d2f16d19b8d09),CNST_LIMB(0xedd386114d83a)), + P(4421,CNST_LIMB(0x1b54d4dc45b7d98d),CNST_LIMB(0xed2e44366e5e2)), + P(4423,CNST_LIMB(0x117ac30d9a044877),CNST_LIMB(0xed12cf8e17f64)), + P(4441,CNST_LIMB(0xe10b78a67a526e9),CNST_LIMB(0xec1cd284b2b2d)), + P(4447,CNST_LIMB(0x92da68a818688a9f),CNST_LIMB(0xebcb44cadda1e)), + P(4451,CNST_LIMB(0xcf2b6c87f741f84b),CNST_LIMB(0xeb9505943771d)), + P(4457,CNST_LIMB(0xd264f9bd41e18ed9),CNST_LIMB(0xeb43d57efeadc)), + P(4463,CNST_LIMB(0x733cbeaa97166d8f),CNST_LIMB(0xeaf2dd4c00b03)), + P(4481,CNST_LIMB(0xc9f475b021d22e81),CNST_LIMB(0xea0141c1ba6a6)), + P(4483,CNST_LIMB(0x731f76f2ec4c852b),CNST_LIMB(0xe9e68805f05a7)), + P(4493,CNST_LIMB(0xdaf6f0c978f69945),CNST_LIMB(0xe96142b87e431)), + P(4507,CNST_LIMB(0x749c8ad20c61ec93),CNST_LIMB(0xe8a7acd811b8c)), + P(4513,CNST_LIMB(0x9307ff8bd3c1261),CNST_LIMB(0xe8587db3e001d)), + P(4517,CNST_LIMB(0x334a69fb5a486e2d),CNST_LIMB(0xe823d186d44dc)), + P(4519,CNST_LIMB(0x1f36c7bf31578617),CNST_LIMB(0xe8098463ee194)), + P(4523,CNST_LIMB(0x31ebbcc279ea6103),CNST_LIMB(0xe7d4fbfb3ee1d)), + P(4547,CNST_LIMB(0x42e2aad119f466eb),CNST_LIMB(0xe69bba6981ffa)), + P(4549,CNST_LIMB(0x106ec05a0ab1450d),CNST_LIMB(0xe681c5cf7d707)), + P(4561,CNST_LIMB(0xb1b38db92a99e731),CNST_LIMB(0xe5e684930e334)), + P(4567,CNST_LIMB(0x784ae377e67071e7),CNST_LIMB(0xe5993247dc92d)), + P(4583,CNST_LIMB(0x3e9e1471ba6671d7),CNST_LIMB(0xe4cbfee201016)), + P(4591,CNST_LIMB(0x82c29b59d4d73d0f),CNST_LIMB(0xe465ee7daf979)), + P(4597,CNST_LIMB(0xc23dd07128b5525d),CNST_LIMB(0xe4199de07af5c)), + P(4603,CNST_LIMB(0x4d4e5ce0e9245133),CNST_LIMB(0xe3cd8031d4f40)), + P(4621,CNST_LIMB(0xc8fd1057c09f8cc5),CNST_LIMB(0xe2ea56c157eb2)), + P(4637,CNST_LIMB(0xea1516e94f394035),CNST_LIMB(0xe221e5d4d3c73)), + P(4639,CNST_LIMB(0xb5e3319c564ee9df),CNST_LIMB(0xe208f09a841c7)), + P(4643,CNST_LIMB(0x126a69f90d822d8b),CNST_LIMB(0xe1d716a945161)), + P(4649,CNST_LIMB(0x501ed6348857aa19),CNST_LIMB(0xe18c78ec8fd4d)), + P(4651,CNST_LIMB(0xde344a324eee1c83),CNST_LIMB(0xe173a4a162079)), + P(4657,CNST_LIMB(0x1dd9690cb2c406d1),CNST_LIMB(0xe1294881bb494)), + P(4663,CNST_LIMB(0x8d6c5178d5e4387),CNST_LIMB(0xe0df1d5f24661)), + P(4673,CNST_LIMB(0x4cea4050a3e8fdc1),CNST_LIMB(0xe063ec7f50b1e)), + P(4679,CNST_LIMB(0xc114a06acc83f777),CNST_LIMB(0xe01a4313dc53d)), + P(4691,CNST_LIMB(0x20b060ebc0ea01db),CNST_LIMB(0xdf8780f47c350)), + P(4703,CNST_LIMB(0xfe50045acb78c99f),CNST_LIMB(0xdef57e8eb9666)), + P(4721,CNST_LIMB(0x291a68705b196e91),CNST_LIMB(0xde1bdf3f63d46)), + P(4723,CNST_LIMB(0xc1042c724273e2bb),CNST_LIMB(0xde03cb5099809)), + P(4729,CNST_LIMB(0x2cee680bb165b7c9),CNST_LIMB(0xddbbaecc84bc9)), + P(4733,CNST_LIMB(0xfd2ff9f12e0776d5),CNST_LIMB(0xdd8bb5ca73db6)), + P(4751,CNST_LIMB(0x166a5da63af2cc6f),CNST_LIMB(0xdcb4d529a6e07)), + P(4759,CNST_LIMB(0xedd16a5930408d27),CNST_LIMB(0xdc55da73dea60)), + P(4783,CNST_LIMB(0x2adf30c26528844f),CNST_LIMB(0xdb3ad2585011f)), + P(4787,CNST_LIMB(0x9a48d6572b5eec7b),CNST_LIMB(0xdb0becf636a79)), + P(4789,CNST_LIMB(0x6e8bf2877503cb9d),CNST_LIMB(0xdaf481ca6fefb)), + P(4793,CNST_LIMB(0xea27a191a7045389),CNST_LIMB(0xdac5ba7565dae)), + P(4799,CNST_LIMB(0x6eb091f34dd45d3f),CNST_LIMB(0xda7fb4e419d19)), + P(4801,CNST_LIMB(0xdc8a6cabb2937d41),CNST_LIMB(0xda6867a88d327)), + P(4813,CNST_LIMB(0xbc2f04f254922a05),CNST_LIMB(0xd9dd005f50b02)), + P(4817,CNST_LIMB(0x41431f4d6eb38631),CNST_LIMB(0xd9aeb01f763f7)), + P(4831,CNST_LIMB(0x7bd717435a08291f),CNST_LIMB(0xd90d31dd5804a)), + P(4861,CNST_LIMB(0x4232df9c91fc1a55),CNST_LIMB(0xd7b6453358f31)), + P(4871,CNST_LIMB(0xa4651e1d5382eab7),CNST_LIMB(0xd744e69d900e4)), + P(4877,CNST_LIMB(0x7cfb5409de4cf3c5),CNST_LIMB(0xd7011a317260e)), + P(4889,CNST_LIMB(0xcdd636fb068b9929),CNST_LIMB(0xd67a0126e7c19)), + P(4903,CNST_LIMB(0xee8f95e740462c97),CNST_LIMB(0xd5dd39e775bd7)), + P(4909,CNST_LIMB(0x490f97b3a758b4a5),CNST_LIMB(0xd59a4f2990168)), + P(4919,CNST_LIMB(0x641431563c441287),CNST_LIMB(0xd52b24cb6269d)), + P(4931,CNST_LIMB(0xb743dad3ec45916b),CNST_LIMB(0xd4a6571da4f04)), + P(4933,CNST_LIMB(0x7b188be8f55c878d),CNST_LIMB(0xd49044eac6581)), + P(4937,CNST_LIMB(0xd805648b2ca54ef9),CNST_LIMB(0xd4642e40d1129)), + P(4943,CNST_LIMB(0x76dbe6eef60123af),CNST_LIMB(0xd4222e81fe723)), + P(4951,CNST_LIMB(0x3711525e6a9e8867),CNST_LIMB(0xd3ca6e8c89f41)), + P(4957,CNST_LIMB(0x85c2215cb383d8f5),CNST_LIMB(0xd388ce29d4edc)), + P(4967,CNST_LIMB(0xe58f554c89825857),CNST_LIMB(0xd31bc7b7d8013)), + P(4969,CNST_LIMB(0x8fbd3b17c01dacd9),CNST_LIMB(0xd306071c13fd5)), + P(4973,CNST_LIMB(0x4c8c39dc7aedee65),CNST_LIMB(0xd2da935479b1a)), + P(4987,CNST_LIMB(0x653ac6dda86cd3b3),CNST_LIMB(0xd2430aa043597)), + P(4993,CNST_LIMB(0xd61c6791a9c2c81),CNST_LIMB(0xd2025bc6c7db7)), + P(4999,CNST_LIMB(0xb627a30090354237),CNST_LIMB(0xd1c1d4ad1732b)), + P(5003,CNST_LIMB(0x83a89a539c527c23),CNST_LIMB(0xd196e5f46f8c8)), + P(5009,CNST_LIMB(0x28c8c09330e90d71),CNST_LIMB(0xd156a0c9293e8)), + P(5011,CNST_LIMB(0xee1178d27b1f029b),CNST_LIMB(0xd1413d26e0aee)), + P(5021,CNST_LIMB(0xcecc740b37860ab5),CNST_LIMB(0xd0d68c6a4128f)), + P(5023,CNST_LIMB(0x79736fde910c485f),CNST_LIMB(0xd0c142eaf3837)), + P(5039,CNST_LIMB(0x6873d51f2487234f),CNST_LIMB(0xd01792ab9d70d)), + P(5051,CNST_LIMB(0x2a112180614fb973),CNST_LIMB(0xcf990317775bc)), + P(5059,CNST_LIMB(0xcb04cea98508f4eb),CNST_LIMB(0xcf44f8c38790a)), + P(5077,CNST_LIMB(0xc2fcd2c527e28d7d),CNST_LIMB(0xce88d96d10e45)), + P(5081,CNST_LIMB(0x980203ee10393c69),CNST_LIMB(0xce5f39b07e906)), + P(5087,CNST_LIMB(0x3fa90a1d7d75681f),CNST_LIMB(0xce20e98148847)), + P(5099,CNST_LIMB(0xdbf3bfefef217cc3),CNST_LIMB(0xcda4b9c30ccd7)), + P(5101,CNST_LIMB(0x66a17fd3087b41e5),CNST_LIMB(0xcd9015ae32495)), + P(5107,CNST_LIMB(0x962195d496fbbd3b),CNST_LIMB(0xcd524244aca36)), + P(5113,CNST_LIMB(0xc705a86155443e49),CNST_LIMB(0xcd14940099cf6)), + P(5119,CNST_LIMB(0x3f298ee0be6febff),CNST_LIMB(0xccd70ac089a07)), + P(5147,CNST_LIMB(0xaa99b084e62fa613),CNST_LIMB(0xcbb9c535c4371)), + P(5153,CNST_LIMB(0x1f000cb7d0b46fe1),CNST_LIMB(0xcb7d0b46fe0ff)), + P(5167,CNST_LIMB(0x9ed7858637c9b2cf),CNST_LIMB(0xcaefe5d7135f4)), + P(5171,CNST_LIMB(0x4d871aaf27c106fb),CNST_LIMB(0xcac7b5f00f0cd)), + P(5179,CNST_LIMB(0x2e6a467cdc75a4f3),CNST_LIMB(0xca7785ceddbea)), + P(5189,CNST_LIMB(0xe9d938fb696dde8d),CNST_LIMB(0xca13a2a86e1db)), + P(5197,CNST_LIMB(0x40ec71b0b1554485),CNST_LIMB(0xc9c4009753007)), + P(5209,CNST_LIMB(0x3aae12f861e5f3e9),CNST_LIMB(0xc94d02e64bfab)), + P(5227,CNST_LIMB(0xa97565873959f843),CNST_LIMB(0xc89b8c9c875ef)), + P(5231,CNST_LIMB(0xb5a960c09fbca8f),CNST_LIMB(0xc87447737277e)), + P(5233,CNST_LIMB(0x463fe3d268012c91),CNST_LIMB(0xc860aaa2514e3)), + P(5237,CNST_LIMB(0xe59a6bd5f5ee1bdd),CNST_LIMB(0xc8397c813f1b9)), + P(5261,CNST_LIMB(0x6542e84d7775ce45),CNST_LIMB(0xc74fa805d6d56)), + P(5273,CNST_LIMB(0x8b6eef58fd9effa9),CNST_LIMB(0xc6db8a1f5cdfe)), + P(5279,CNST_LIMB(0x58993dbb9f98075f),CNST_LIMB(0xc6a1add9e2398)), + P(5281,CNST_LIMB(0x2997955a810acf61),CNST_LIMB(0xc68e6be826648)), + P(5297,CNST_LIMB(0x76e3d2f5077db451),CNST_LIMB(0xc5f4e25fc9df0)), + P(5303,CNST_LIMB(0xb37c1d2867e30907),CNST_LIMB(0xc5bb8bf2ad1cd)), + P(5309,CNST_LIMB(0x53ce6e09bd8d8695),CNST_LIMB(0xc58256b316ced)), + P(5323,CNST_LIMB(0x39db291ea2a6b0e3),CNST_LIMB(0xc4fd5ad917b5b)), + P(5333,CNST_LIMB(0xddd265ab9c58847d),CNST_LIMB(0xc49ecb3ea4d7a)), + P(5347,CNST_LIMB(0x5beca8562dddd0cb),CNST_LIMB(0xc41b00b7d950a)), + P(5351,CNST_LIMB(0xb69031c153ddbed7),CNST_LIMB(0xc3f57990b87a1)), + P(5381,CNST_LIMB(0xd03c2271b42a6fcd),CNST_LIMB(0xc2ddcb31250f8)), + P(5387,CNST_LIMB(0xcd6fd19e63e40ea3),CNST_LIMB(0xc2a63b3651432)), + P(5393,CNST_LIMB(0xf7687aa8e4fd7bf1),CNST_LIMB(0xc26ecae1db72e)), + P(5399,CNST_LIMB(0x649dfda112a272a7),CNST_LIMB(0xc2377a18c051e)), + P(5407,CNST_LIMB(0xecf7866a56d526df),CNST_LIMB(0xc1ede9efcec29)), + P(5413,CNST_LIMB(0x72bbf1cfdaebfead),CNST_LIMB(0xc1b6e258d13a0)), + P(5417,CNST_LIMB(0x55f6a48df7055719),CNST_LIMB(0xc19243f5399bb)), + P(5419,CNST_LIMB(0x80060bffcfa00183),CNST_LIMB(0xc17ff9f400305)), + P(5431,CNST_LIMB(0x8a104f309919b087),CNST_LIMB(0xc112865703b94)), + P(5437,CNST_LIMB(0x98fa7db7652f6a15),CNST_LIMB(0xc0dbfaea33225)), + P(5441,CNST_LIMB(0x5d7d1b3df70f7ac1),CNST_LIMB(0xc0b7af12ddfb9)), + P(5443,CNST_LIMB(0x16ab7b5e04cc1f6b),CNST_LIMB(0xc0a58e464462c)), + P(5449,CNST_LIMB(0x78a5bfd2e5ececf9),CNST_LIMB(0xc06f40512eef2)), + P(5471,CNST_LIMB(0x6506392e171d869f),CNST_LIMB(0xbfa9275a2b247)), + P(5477,CNST_LIMB(0xc3fc12e221ef146d),CNST_LIMB(0xbf7367402cdf0)), + P(5479,CNST_LIMB(0xf8aa132822c33657),CNST_LIMB(0xbf61833f4f921)), + P(5483,CNST_LIMB(0x894496574f536f43),CNST_LIMB(0xbf3dc543a74a1)), + P(5501,CNST_LIMB(0x8b2546b08fb4cbd5),CNST_LIMB(0xbe9d9302a7115)), + P(5503,CNST_LIMB(0x43bbb561bd1aa7f),CNST_LIMB(0xbe8bd6e051e01)), + P(5507,CNST_LIMB(0x2412c7cc4ea7a12b),CNST_LIMB(0xbe6868804d5a6)), + P(5519,CNST_LIMB(0x6f0bd406dd71696f),CNST_LIMB(0xbdfe6c4359f0e)), + P(5521,CNST_LIMB(0xad475c6988d54b71),CNST_LIMB(0xbdeccdb0b5c3a)), + P(5527,CNST_LIMB(0xd812e5d48dbbba27),CNST_LIMB(0xbdb8058ee429a)), + P(5531,CNST_LIMB(0x22aaca437ba04893),CNST_LIMB(0xbd94e5c1b371f)), + P(5557,CNST_LIMB(0xdba6ff1fecd5f09d),CNST_LIMB(0xbcb1d293b1af3)), + P(5563,CNST_LIMB(0x13016d3396286773),CNST_LIMB(0xbc7db8db0c1a5)), + P(5569,CNST_LIMB(0xc746494631bcfa41),CNST_LIMB(0xbc49bbdfd2662)), + P(5573,CNST_LIMB(0xd14888565bf6a10d),CNST_LIMB(0xbc2723240f402)), + P(5581,CNST_LIMB(0xc002ef885f0adf05),CNST_LIMB(0xbbe217c2b7c13)), + P(5591,CNST_LIMB(0xe5a04da7fee6ade7),CNST_LIMB(0xbb8c10aab27b2)), + P(5623,CNST_LIMB(0xc114ce5468593bc7),CNST_LIMB(0xba7ad528a7e79)), + P(5639,CNST_LIMB(0xbb6747dd7f577b7),CNST_LIMB(0xb9f3611b48c5e)), + P(5641,CNST_LIMB(0x395ce5a20f285839),CNST_LIMB(0xb9e2806e5e7c4)), + P(5647,CNST_LIMB(0x6eee8be66e8618ef),CNST_LIMB(0xb9aff0c4913fe)), + P(5651,CNST_LIMB(0x52acf64297f1241b),CNST_LIMB(0xb98e4aedd581c)), + P(5653,CNST_LIMB(0x361dcc48a364093d),CNST_LIMB(0xb97d7c94b7dc2)), + P(5657,CNST_LIMB(0x342d6f475d72e629),CNST_LIMB(0xb95be902d9d9e)), + P(5659,CNST_LIMB(0x5e978bd46410d413),CNST_LIMB(0xb94b23c872b90)), + P(5669,CNST_LIMB(0xcc3433d75ba015ad),CNST_LIMB(0xb8f77714d15a1)), + P(5683,CNST_LIMB(0x1c83b7628458d4fb),CNST_LIMB(0xb882d0beff6a1)), + P(5689,CNST_LIMB(0xf9ca45637e38f809),CNST_LIMB(0xb850ff9852703)), + P(5693,CNST_LIMB(0xcbed792ffaf6b115),CNST_LIMB(0xb82fd86db8806)), + P(5701,CNST_LIMB(0x9abd961d8c0e8c8d),CNST_LIMB(0xb7edadd32f76c)), + P(5711,CNST_LIMB(0xe69572fa659340af),CNST_LIMB(0xb79b3b4df3b7b)), + P(5717,CNST_LIMB(0x9187e7483a6436fd),CNST_LIMB(0xb769e6d59833f)), + P(5737,CNST_LIMB(0x1e9c726993bed9d9),CNST_LIMB(0xb6c636b5141ff)), + P(5741,CNST_LIMB(0x243554db91976365),CNST_LIMB(0xb6a59ceae8801)), + P(5743,CNST_LIMB(0x4d06ff994c0088f),CNST_LIMB(0xb6955461e38f7)), + P(5749,CNST_LIMB(0x25b76abcb74889dd),CNST_LIMB(0xb6648c2dc6bc2)), + P(5779,CNST_LIMB(0x3a409642893c779b),CNST_LIMB(0xb572282260209)), + P(5783,CNST_LIMB(0x8f8f620d8bc0c927),CNST_LIMB(0xb552072bde889)), + P(5791,CNST_LIMB(0x6f9f196b3369855f),CNST_LIMB(0xb511e7552f9c4)), + P(5801,CNST_LIMB(0x92a522bb0638ed99),CNST_LIMB(0xb4c1ff34a5c0e)), + P(5807,CNST_LIMB(0x96270f1efdd7004f),CNST_LIMB(0xb4922f58d4aa2)), + P(5813,CNST_LIMB(0xb4844b380fdaa79d),CNST_LIMB(0xb46278c16b967)), + P(5821,CNST_LIMB(0x108936aa5f9c1495),CNST_LIMB(0xb42301cd99b49)), + P(5827,CNST_LIMB(0xb60f606f104c9eb),CNST_LIMB(0xb3f385dd77e4e)), + P(5839,CNST_LIMB(0xc663dfe8263b302f),CNST_LIMB(0xb394d8ef8f0f6)), + P(5843,CNST_LIMB(0xc91a280b9110b15b),CNST_LIMB(0xb375601507c14)), + P(5849,CNST_LIMB(0x904287118d10969),CNST_LIMB(0xb3463f76be376)), + P(5851,CNST_LIMB(0x160d36a5d31bf553),CNST_LIMB(0xb3368f6c4a07c)), + P(5857,CNST_LIMB(0xe84f5fda3c67ad21),CNST_LIMB(0xb3078fc1c25f0)), + P(5861,CNST_LIMB(0xbd85701f72d4b6ed),CNST_LIMB(0xb2e84854e93e5)), + P(5867,CNST_LIMB(0x4c50cf5924dee1c3),CNST_LIMB(0xb2b971aa909a4)), + P(5869,CNST_LIMB(0x2455aaf1633bb6e5),CNST_LIMB(0xb2a9da39d6bc8)), + P(5879,CNST_LIMB(0xd775b39f549b8ac7),CNST_LIMB(0xb25c0dc29a0fc)), + P(5881,CNST_LIMB(0x87fcdda7a252cb49),CNST_LIMB(0xb24c8698449a7)), + P(5897,CNST_LIMB(0x53df2e3bd254a739),CNST_LIMB(0xb1d0ae579aefe)), + P(5903,CNST_LIMB(0x8915e69623a5f7ef),CNST_LIMB(0xb1a2698ea2f9e)), + P(5923,CNST_LIMB(0x1ef24c80742dd08b),CNST_LIMB(0xb108dc4186078)), + P(5927,CNST_LIMB(0xb4d87aaa6fb1e897),CNST_LIMB(0xb0ea463b00212)), + P(5939,CNST_LIMB(0x788573e8b92dbbfb),CNST_LIMB(0xb08ec37007962)), + P(5953,CNST_LIMB(0x2527b137b0878c1),CNST_LIMB(0xb024778cc023c)), + P(5981,CNST_LIMB(0x1870a7c8dee9f4f5),CNST_LIMB(0xaf515df36a88e)), + P(5987,CNST_LIMB(0x39b99e40910a224b),CNST_LIMB(0xaf24635f6561e)), + P(6007,CNST_LIMB(0x45821c0abd4df247),CNST_LIMB(0xae8f1b92baeaf)), + P(6011,CNST_LIMB(0x10fe2b2f50e02fb3),CNST_LIMB(0xae715eee11f8e)), + P(6029,CNST_LIMB(0x5762b90c043f0345),CNST_LIMB(0xadec0b0a3bb36)), + P(6037,CNST_LIMB(0x82a67b9193b27bbd),CNST_LIMB(0xadb10aa4c956f)), + P(6043,CNST_LIMB(0xa6e914e28ec37693),CNST_LIMB(0xad84e49752245)), + P(6047,CNST_LIMB(0x835d9a4facaf445f),CNST_LIMB(0xad6782597f0c2)), + P(6053,CNST_LIMB(0x48def8175884f82d),CNST_LIMB(0xad3b81a0d72fe)), + P(6067,CNST_LIMB(0xae900e2d7c9a6f7b),CNST_LIMB(0xacd52beced79e)), + P(6073,CNST_LIMB(0x1c08431bdd18be89),CNST_LIMB(0xaca9755063254)), + P(6079,CNST_LIMB(0xb370a66d684fd83f),CNST_LIMB(0xac7dd4cafb12a)), + P(6089,CNST_LIMB(0xb4be33e18f93b279),CNST_LIMB(0xac354f80dca44)), + P(6091,CNST_LIMB(0x310c50872a7dd5e3),CNST_LIMB(0xac26d5c2b8ad2)), + P(6101,CNST_LIMB(0x447ab1281276697d),CNST_LIMB(0xabde997dabd3d)), + P(6113,CNST_LIMB(0xc2f122216b2a6c21),CNST_LIMB(0xab883aa1100a0)), + P(6121,CNST_LIMB(0xab99c8b5ae1c3059),CNST_LIMB(0xab4ed637f5a0b)), + P(6131,CNST_LIMB(0xb78e17a2227d593b),CNST_LIMB(0xab074e9febf52)), + P(6133,CNST_LIMB(0xabf97d03f7269c5d),CNST_LIMB(0xaaf90778c2039)), + P(6143,CNST_LIMB(0x867aefc9fdbfe7ff),CNST_LIMB(0xaab1c7684f034)), + P(6151,CNST_LIMB(0xf7f7ad182e47d5b7),CNST_LIMB(0xaa78f20ebbb3e)), + P(6163,CNST_LIMB(0x50dff95a9847721b),CNST_LIMB(0xaa23f8dafd4cc)), + P(6173,CNST_LIMB(0xe4cb8a0e83cb6a35),CNST_LIMB(0xa9dd69cad5934)), + P(6197,CNST_LIMB(0x8da72ecdf9247a1d),CNST_LIMB(0xa935004a07302)), + P(6199,CNST_LIMB(0xc5b04bfc87f31d87),CNST_LIMB(0xa9270690f3d14)), + P(6203,CNST_LIMB(0xe2dcf622ea2b00f3),CNST_LIMB(0xa90b1a0aa5d30)), + P(6211,CNST_LIMB(0xb9ce9f2e4972f46b),CNST_LIMB(0xa8d35c9d731e9)), + P(6217,CNST_LIMB(0x1ed785c911bf59f9),CNST_LIMB(0xa8a9a6a51f16c)), + P(6221,CNST_LIMB(0x4ddb8a4eed70e085),CNST_LIMB(0xa88de370f596b)), + P(6229,CNST_LIMB(0x81e93b4df68c24fd),CNST_LIMB(0xa856786adae36)), + P(6247,CNST_LIMB(0xee0d0812afcd8357),CNST_LIMB(0xa7da4c77d3161)), + P(6257,CNST_LIMB(0xf62e3ba72268a891),CNST_LIMB(0xa7959f863d4a1)), + P(6263,CNST_LIMB(0x3194d367c8154147),CNST_LIMB(0xa76c85e80c195)), + P(6269,CNST_LIMB(0xd096ede8e30c20d5),CNST_LIMB(0xa743806dc44c4)), + P(6271,CNST_LIMB(0xd68624d27b87a77f),CNST_LIMB(0xa735d866dfa0a)), + P(6277,CNST_LIMB(0xb728fcdc11c8204d),CNST_LIMB(0xa70cedb02531e)), + P(6287,CNST_LIMB(0x9d6b6038077e066f),CNST_LIMB(0xa6c8e842c770f)), + P(6299,CNST_LIMB(0xaa732d7a4a360d93),CNST_LIMB(0xa67791215dd74)), + P(6301,CNST_LIMB(0x36af98a423972db5),CNST_LIMB(0xa66a0a51d363d)), + P(6311,CNST_LIMB(0xc31d00da12940f17),CNST_LIMB(0xa626893011861)), + P(6317,CNST_LIMB(0xed85352107410b25),CNST_LIMB(0xa5fe22c55c089)), + P(6323,CNST_LIMB(0x829c85ee6db8567b),CNST_LIMB(0xa5d5cffb77275)), + P(6329,CNST_LIMB(0xef60258952cc6d89),CNST_LIMB(0xa5ad90c4186e5)), + P(6337,CNST_LIMB(0xcf28c2e0da787741),CNST_LIMB(0xa578057e7c2eb)), + P(6343,CNST_LIMB(0x57567d8494af28f7),CNST_LIMB(0xa54ff3bb10e91)), + P(6353,CNST_LIMB(0x2c7c98518f174031),CNST_LIMB(0xa50d5683edc94)), + P(6359,CNST_LIMB(0xb28b363a36825ae7),CNST_LIMB(0xa4e57854b3df4)), + P(6361,CNST_LIMB(0xed1ffeb64f9ae769),CNST_LIMB(0xa4d8328c4b800)), + P(6367,CNST_LIMB(0xcbbb0115e9b9a31f),CNST_LIMB(0xa4b06e01d97b3)), + P(6373,CNST_LIMB(0x8d3c5fecb7f9e4ed),CNST_LIMB(0xa488bca2c4449)), + P(6379,CNST_LIMB(0x816271698195cfc3),CNST_LIMB(0xa4611e6132ed5)), + P(6389,CNST_LIMB(0x9ac939d1c2b1d35d),CNST_LIMB(0xa41f40f39e646)), + P(6397,CNST_LIMB(0xdd9fb7017b0ec455),CNST_LIMB(0xa3eab5c3e44e9)), + P(6421,CNST_LIMB(0xc94cab1e57276e3d),CNST_LIMB(0xa34ddd50561e0)), + P(6427,CNST_LIMB(0x8b8806b117c79913),CNST_LIMB(0xa326d60e94186)), + P(6449,CNST_LIMB(0xa9e63292a3269fd1),CNST_LIMB(0xa2985a81ce614)), + P(6451,CNST_LIMB(0x76da5710f1e989fb),CNST_LIMB(0xa28b72e26f82e)), + P(6469,CNST_LIMB(0xdded6688d83a918d),CNST_LIMB(0xa217aa3479693)), + P(6473,CNST_LIMB(0x4e446b6a305428f9),CNST_LIMB(0xa1fe05c62df4b)), + P(6481,CNST_LIMB(0x4ddaca7a3696cfb1),CNST_LIMB(0xa1cad538aebf9)), + P(6491,CNST_LIMB(0x7eadc4eb87f26ed3),CNST_LIMB(0xa18b05f490083)), + P(6521,CNST_LIMB(0x76c13a0ff04c00c9),CNST_LIMB(0xa0ccc4c28fc31)), + P(6529,CNST_LIMB(0xcbf800504d2a2681),CNST_LIMB(0xa09a544d01ffe)), + P(6547,CNST_LIMB(0x731dada6c4fec9b),CNST_LIMB(0xa0294aa53e9a2)), + P(6551,CNST_LIMB(0xbcb52a664e63f627),CNST_LIMB(0xa01041a6aaed5)), + P(6553,CNST_LIMB(0xf1f9abda071c2aa9),CNST_LIMB(0xa003c01680870)), + P(6563,CNST_LIMB(0xf262ffa620ffe20b),CNST_LIMB(0x9fc5558a971c8)), + P(6569,CNST_LIMB(0x93774a3d57199a99),CNST_LIMB(0x9f9ff9c3c03e5)), + P(6571,CNST_LIMB(0xfb3541cd467a1903),CNST_LIMB(0x9f9389b864ab9)), + P(6577,CNST_LIMB(0x6828cab6b4fe8f51),CNST_LIMB(0x9f6e4534bdca8)), + P(6581,CNST_LIMB(0x12ac03e3d624cc9d),CNST_LIMB(0x9f557687235c2)), + P(6599,CNST_LIMB(0x6363bd1e9bb7d7f7),CNST_LIMB(0x9ee633c0391ab)), + P(6607,CNST_LIMB(0x334cfd676a484d2f),CNST_LIMB(0x9eb4f28e0bb39)), + P(6619,CNST_LIMB(0xd511acd86f143a53),CNST_LIMB(0x9e6b49e92e4bb)), + P(6637,CNST_LIMB(0x73fc2490e0062be5),CNST_LIMB(0x9dfd4ccbd0045)), + P(6653,CNST_LIMB(0x10780dda36b78b55),CNST_LIMB(0x9d9c0828536c1)), + P(6659,CNST_LIMB(0xabf601274064e0ab),CNST_LIMB(0x9d77ad449f777)), + P(6661,CNST_LIMB(0x3ef3e4ca27e4a2cd),CNST_LIMB(0x9d6b92b28ee48)), + P(6673,CNST_LIMB(0x9216a26e690a16f1),CNST_LIMB(0x9d231a476ed51)), + P(6679,CNST_LIMB(0xbae4849e6034bda7),CNST_LIMB(0x9cfef711bf120)), + P(6689,CNST_LIMB(0xf943a0520e01e9e1),CNST_LIMB(0x9cc2e1448b765)), + P(6691,CNST_LIMB(0x7c89958f48f6658b),CNST_LIMB(0x9cb6e26cbc64d)), + P(6701,CNST_LIMB(0xe67128750e0545a5),CNST_LIMB(0x9c7b03b4a9c67)), + P(6703,CNST_LIMB(0xc6c9e1d414516ccf),CNST_LIMB(0x9c6f0fd980ab1)), + P(6709,CNST_LIMB(0x805307f996e9e81d),CNST_LIMB(0x9c4b3f3a30c3f)), + P(6719,CNST_LIMB(0x3eddd2cff46ad5bf),CNST_LIMB(0x9c0fb29436687)), + P(6733,CNST_LIMB(0x35582c1aeb5aae85),CNST_LIMB(0x9bbca025b7aec)), + P(6737,CNST_LIMB(0x4973c88573ef6eb1),CNST_LIMB(0x9ba4f4421e52c)), + P(6761,CNST_LIMB(0x3063f627c1e715d9),CNST_LIMB(0x9b1783809ff03)), + P(6763,CNST_LIMB(0x711ad679a8dcc243),CNST_LIMB(0x9b0bc5b4d2eac)), + P(6779,CNST_LIMB(0x51c224a17a3db4b3),CNST_LIMB(0x9aae172fd8b9c)), + P(6781,CNST_LIMB(0x612325ca50ddaed5),CNST_LIMB(0x9aa26954607ed)), + P(6791,CNST_LIMB(0x9929a7b6b7958b37),CNST_LIMB(0x9a681e758a022)), + P(6793,CNST_LIMB(0xa78d222e5a857bb9),CNST_LIMB(0x9a5c7b284942e)), + P(6803,CNST_LIMB(0x3ad0ffe3198d139b),CNST_LIMB(0x9a2264ecc5558)), + P(6823,CNST_LIMB(0x8b4659ac547ed17),CNST_LIMB(0x99aebb39be56f)), + P(6827,CNST_LIMB(0x1752e8904aff1003),CNST_LIMB(0x9997ae1a9faac)), + P(6829,CNST_LIMB(0x60745c37ee4e5925),CNST_LIMB(0x998c2a22b6900)), + P(6833,CNST_LIMB(0x29e2da1f6557ee51),CNST_LIMB(0x997527603f8a8)), + P(6841,CNST_LIMB(0x80d78c24ac49cb89),CNST_LIMB(0x99473685e4d50)), + P(6857,CNST_LIMB(0xc56c3b495c8d1f79),CNST_LIMB(0x98eba72512a13)), + P(6863,CNST_LIMB(0xcf5bdf9f5088ac2f),CNST_LIMB(0x98c96d8dee9e1)), + P(6869,CNST_LIMB(0x8a44800e4fae4e7d),CNST_LIMB(0x98a743453554e)), + P(6871,CNST_LIMB(0xdd76384277e578e7),CNST_LIMB(0x989be33c9e6bd)), + P(6883,CNST_LIMB(0x20b1562d2703facb),CNST_LIMB(0x9857c692e9a59)), + P(6899,CNST_LIMB(0xef56caf96e9d8e3b),CNST_LIMB(0x97fd540c05c9e)), + P(6907,CNST_LIMB(0xf54061416aede033),CNST_LIMB(0x97d04302ed944)), + P(6911,CNST_LIMB(0xe0bc78c21a26e4ff),CNST_LIMB(0x97b9c48289935)), + P(6917,CNST_LIMB(0x524f92731a179cd),CNST_LIMB(0x9798133ece717)), + P(6947,CNST_LIMB(0x5d3b4ad7deafec8b),CNST_LIMB(0x96f07c683689e)), + P(6949,CNST_LIMB(0x508828f744da88ad),CNST_LIMB(0x96e55d6393fc5)), + P(6959,CNST_LIMB(0x6e82014031710bcf),CNST_LIMB(0x96addad861696)), + P(6961,CNST_LIMB(0xadf3b77a22595dd1),CNST_LIMB(0x96a2c5a2cf0cf)), + P(6967,CNST_LIMB(0xd8f0c03f7ea8a87),CNST_LIMB(0x96818fc825eba)), + P(6971,CNST_LIMB(0x2c49e3483c3a05f3),CNST_LIMB(0x966b74027f48a)), + P(6977,CNST_LIMB(0xccecbc98c91274c1),CNST_LIMB(0x964a56850b8ed)), + P(6983,CNST_LIMB(0x273a08941bb71e77),CNST_LIMB(0x962947990eb36)), + P(6991,CNST_LIMB(0xdead5a1e3f341baf),CNST_LIMB(0x95fd4a4c885e0)), + P(6997,CNST_LIMB(0x83eee092593309fd),CNST_LIMB(0x95dc5d3954fde)), + P(7001,CNST_LIMB(0x4af5f1bd3ae87ce9),CNST_LIMB(0x95c671ddfe516)), + P(7013,CNST_LIMB(0x4ca85ad2301c9e6d),CNST_LIMB(0x9584d6340ddf1)), + P(7019,CNST_LIMB(0x1b19592cd31a3943),CNST_LIMB(0x95641de84afcc)), + P(7027,CNST_LIMB(0x3e7aa05e6dcd81bb),CNST_LIMB(0x953893c386521)), + P(7039,CNST_LIMB(0x86336cecb02ba47f),CNST_LIMB(0x94f7740d87794)), + P(7043,CNST_LIMB(0xa96b30d0c8a44b2b),CNST_LIMB(0x94e1cb70c9ce0)), + P(7057,CNST_LIMB(0xb7c63fa0cfca0571),CNST_LIMB(0x94962ecbcc7ce)), + P(7069,CNST_LIMB(0x8eaf59b405a642b5),CNST_LIMB(0x94559c69059cf)), + P(7079,CNST_LIMB(0xdf29e9cbb536dc17),CNST_LIMB(0x941ff7e640716)), + P(7103,CNST_LIMB(0xed14132c82c1d43f),CNST_LIMB(0x939fd7a24b099)), + P(7109,CNST_LIMB(0xaf68778e34caab0d),CNST_LIMB(0x937ff22c014bd)), + P(7121,CNST_LIMB(0xa4f04a3368941d31),CNST_LIMB(0x934050872c09e)), + P(7127,CNST_LIMB(0xe9960969357c07e7),CNST_LIMB(0x93209446d56f6)), + P(7129,CNST_LIMB(0xeb47b62b7360b469),CNST_LIMB(0x9316033b5bd22)), + P(7151,CNST_LIMB(0x64c653d779ae730f),CNST_LIMB(0x92a22b9a79374)), + P(7159,CNST_LIMB(0x479702d3319915c7),CNST_LIMB(0x927838edba206)), + P(7177,CNST_LIMB(0xef3c3eebc6803239),CNST_LIMB(0x921a2e7112833)), + P(7187,CNST_LIMB(0x93807b1a2e3c0e1b),CNST_LIMB(0x91e623d5660d0)), + P(7193,CNST_LIMB(0x8167e33e3f478029),CNST_LIMB(0x91c6fc0cab8b6)), + P(7207,CNST_LIMB(0x60cb76e38c339397),CNST_LIMB(0x917e7d88028eb)), + P(7211,CNST_LIMB(0xae34788ffe4bc283),CNST_LIMB(0x9169d455585cd)), + P(7213,CNST_LIMB(0x4b6246a0c6c093a5),CNST_LIMB(0x915f81ef2d529)), + P(7219,CNST_LIMB(0x872e594b12b03efb),CNST_LIMB(0x9140938595d3a)), + P(7229,CNST_LIMB(0xbc0ae83ce9045b15),CNST_LIMB(0x910d2360a450e)), + P(7237,CNST_LIMB(0xad30a3917e0968d),CNST_LIMB(0x90e417104eabd)), + P(7243,CNST_LIMB(0x124ef5a4e1c7cd63),CNST_LIMB(0x90c55d0fdea28)), + P(7247,CNST_LIMB(0x5b98fe0e9fe17aaf),CNST_LIMB(0x90b0e84c04f20)), + P(7253,CNST_LIMB(0x414306cfe45400fd),CNST_LIMB(0x909243fac6b70)), + P(7283,CNST_LIMB(0xa06d1b4fd391e8bb),CNST_LIMB(0x8ff9d0440d137)), + P(7297,CNST_LIMB(0x11939803a60c2381),CNST_LIMB(0x8fb3192789d73)), + P(7307,CNST_LIMB(0x668c11cc37ea6b23),CNST_LIMB(0x8f80c0d5031e3)), + P(7309,CNST_LIMB(0x83f9b2089dc10645),CNST_LIMB(0x8f76b3664f164)), + P(7321,CNST_LIMB(0x65dc8ae47af277a9),CNST_LIMB(0x8f3a80550abc3)), + P(7331,CNST_LIMB(0x6e2368b9c685770b),CNST_LIMB(0x8f087c50e00c4)), + P(7333,CNST_LIMB(0x3ea137aeba5a6b2d),CNST_LIMB(0x8efe7fb408cc2)), + P(7349,CNST_LIMB(0x735f57adca48f19d),CNST_LIMB(0x8eaecce5c4fd7)), + P(7351,CNST_LIMB(0x69a8de0ba1b18107),CNST_LIMB(0x8ea4dccaaec0b)), + P(7369,CNST_LIMB(0x8fb84bdf5822bd79),CNST_LIMB(0x8e4ba9fbc2ff0)), + P(7393,CNST_LIMB(0xb8fab3b748562721),CNST_LIMB(0x8dd5688a3b7d6)), + P(7411,CNST_LIMB(0xa6c658ea10a65c3b),CNST_LIMB(0x8d7d3821fd94f)), + P(7417,CNST_LIMB(0xe56381f33ab5e549),CNST_LIMB(0x8d5feb03c31d7)), + P(7433,CNST_LIMB(0xe3c224da14988139),CNST_LIMB(0x8d12033cc9d30)), + P(7451,CNST_LIMB(0x438c253e6d99f513),CNST_LIMB(0x8cbac4dec6a82)), + P(7457,CNST_LIMB(0xc1b99f8841a3a6e1),CNST_LIMB(0x8c9dc80ab604b)), + P(7459,CNST_LIMB(0x63fa18c79c54fa8b),CNST_LIMB(0x8c942115dcc96)), + P(7477,CNST_LIMB(0xe7f6f609619d0d1d),CNST_LIMB(0x8c3d7df67b539)), + P(7481,CNST_LIMB(0x7b39ef3b70afc109),CNST_LIMB(0x8c2a4bc35cb3b)), + P(7487,CNST_LIMB(0x73922c61ca7452bf),CNST_LIMB(0x8c0d8a4f1f264)), + P(7489,CNST_LIMB(0x28d96828332372c1),CNST_LIMB(0x8c03f71cbf906)), + P(7499,CNST_LIMB(0x6b6e92968c4e8463),CNST_LIMB(0x8bd42abd9a107)), + P(7507,CNST_LIMB(0x571861f084962edb),CNST_LIMB(0x8bae051d7f6ff)), + P(7517,CNST_LIMB(0xd935c64f140f1ef5),CNST_LIMB(0x8b7e735068135)), + P(7523,CNST_LIMB(0x96459f8fd72a4c4b),CNST_LIMB(0x8b61f82c5fb08)), + P(7529,CNST_LIMB(0x410ba9a2a18242d9),CNST_LIMB(0x8b4588a74a05a)), + P(7537,CNST_LIMB(0xcf90979f89870391),CNST_LIMB(0x8b1fb0a7ed403)), + P(7541,CNST_LIMB(0x10f94ff26bc00add),CNST_LIMB(0x8b0ccc5d8f5c8)), + P(7547,CNST_LIMB(0xa6619fbb9da139b3),CNST_LIMB(0x8af07f8ac5146)), + P(7549,CNST_LIMB(0x765a23334efb03d5),CNST_LIMB(0x8ae71328ffd49)), + P(7559,CNST_LIMB(0x6f2f613b5e631837),CNST_LIMB(0x8ab8086624822)), + P(7561,CNST_LIMB(0x666b99bfbcd368b9),CNST_LIMB(0x8aaea3ab5ae89)), + P(7573,CNST_LIMB(0x922b78eb01ed45bd),CNST_LIMB(0x8a7661f7020fe)), + P(7577,CNST_LIMB(0x7079a199c31de6a9),CNST_LIMB(0x8a63ab88aa8dd)), + P(7583,CNST_LIMB(0xa181abcda167be5f),CNST_LIMB(0x8a47a35d020f3)), + P(7589,CNST_LIMB(0x2f6dbbcab3a9822d),CNST_LIMB(0x8a2ba68a3cebf)), + P(7591,CNST_LIMB(0xc5a83ff0e43eba17),CNST_LIMB(0x8a2254c852497)), + P(7603,CNST_LIMB(0x28c68613dda7d97b),CNST_LIMB(0x89ea849898bb3)), + P(7607,CNST_LIMB(0x5cf33ed49efa5007),CNST_LIMB(0x89d7f3e285109)), + P(7621,CNST_LIMB(0x9125fdead661590d),CNST_LIMB(0x899720af36739)), + P(7639,CNST_LIMB(0xaee67f478c7325e7),CNST_LIMB(0x89442160d11dc)), + P(7643,CNST_LIMB(0x735b1274a0e89653),CNST_LIMB(0x8931bd5875a22)), + P(7649,CNST_LIMB(0x733b56eae1a4e621),CNST_LIMB(0x891630877aedf)), + P(7669,CNST_LIMB(0x1944ffb316ffe65d),CNST_LIMB(0x88baaad83e38f)), + P(7673,CNST_LIMB(0xf26bc3cfd2a01449),CNST_LIMB(0x88a86b9090aa4)), + P(7681,CNST_LIMB(0xb5827ba68b83e201),CNST_LIMB(0x8883fb99bf244)), + P(7687,CNST_LIMB(0xac139507e48eefb7),CNST_LIMB(0x8868b45e727ee)), + P(7691,CNST_LIMB(0xeb7676b25834fda3),CNST_LIMB(0x88568aef30d47)), + P(7699,CNST_LIMB(0xad898f4763da5c1b),CNST_LIMB(0x8832468f0bcdd)), + P(7703,CNST_LIMB(0xea906f224398f9a7),CNST_LIMB(0x88202b9a4df76)), + P(7717,CNST_LIMB(0xa8aff3caca28cdad),CNST_LIMB(0x87e0f31872e9b)), + P(7723,CNST_LIMB(0x46c53aa36b19b083),CNST_LIMB(0x87c5ecd731f42)), + P(7727,CNST_LIMB(0x9ada32b09603e8cf),CNST_LIMB(0x87b3eea3bb388)), + P(7741,CNST_LIMB(0xd31f842ef5d8e915),CNST_LIMB(0x87751a6c67d78)), + P(7753,CNST_LIMB(0x6124af44730a33f9),CNST_LIMB(0x873f6e2f9d34a)), + P(7757,CNST_LIMB(0x828ec4c2b6e64a85),CNST_LIMB(0x872d938dcfc01)), + P(7759,CNST_LIMB(0x3d6f49df999638af),CNST_LIMB(0x8724a80151dba)), + P(7789,CNST_LIMB(0x7641460a0ea89b65),CNST_LIMB(0x869f677f6cc1a)), + P(7793,CNST_LIMB(0x97703f98fb7fe291),CNST_LIMB(0x868db701df58d)), + P(7817,CNST_LIMB(0xd343c209e3e6b7b9),CNST_LIMB(0x8623f563a7d6d)), + P(7823,CNST_LIMB(0x4e5fc01f6a41406f),CNST_LIMB(0x86099ef0c8886)), + P(7829,CNST_LIMB(0xb78a05b08aa4bcbd),CNST_LIMB(0x85ef52d38fe87)), + P(7841,CNST_LIMB(0x3434a14919d34561),CNST_LIMB(0x85bad981c7847)), + P(7853,CNST_LIMB(0xccead7dee120f525),CNST_LIMB(0x8586893de7cfc)), + P(7867,CNST_LIMB(0xe1375a2bccd87673),CNST_LIMB(0x8549b491e9efe)), + P(7873,CNST_LIMB(0xf727d51420a57141),CNST_LIMB(0x852fb3859bea4)), + P(7877,CNST_LIMB(0x2c3b68cfbcebb00d),CNST_LIMB(0x851e631fc08f8)), + P(7879,CNST_LIMB(0xda91e2f3e17542f7),CNST_LIMB(0x8515bc9cde5f1)), + P(7883,CNST_LIMB(0xb55f6100ae95d6e3),CNST_LIMB(0x850472f6185b3)), + P(7901,CNST_LIMB(0x6a0c608e0bbaa975),CNST_LIMB(0x84b6defbc166b)), + P(7907,CNST_LIMB(0xac5f2fc151c016cb),CNST_LIMB(0x849d17159854b)), + P(7919,CNST_LIMB(0xb1e5af8146e4d00f),CNST_LIMB(0x8469a54a20645)), + P(7927,CNST_LIMB(0x6e283d3b112602c7),CNST_LIMB(0x84476f9401ade)), + P(7933,CNST_LIMB(0xf9a48bcb76c96e55),CNST_LIMB(0x842dd2e2dc25d)), + P(7937,CNST_LIMB(0xa776780ca4c0e101),CNST_LIMB(0x841cc543f58cb)), +#define SMALLEST_OMITTED_PRIME 7949 +#endif +#ifdef WANT_ptab + {CNST_LIMB(0x444437fed9a2349),{CNST_LIMB(0xe00056482545e92a),5,CNST_LIMB(0x2e044fdfbae4),CNST_LIMB(0x2c8f9615733fe6),CNST_LIMB(0x15319a745d44889),CNST_LIMB(0x30314bfee31fe08),CNST_LIMB(0x213845b5eb1d02b)},0,14}, + {CNST_LIMB(0x34091fa96ffdf47b),{CNST_LIMB(0x3adc72bf62f96a49),2,CNST_LIMB(0x2fdb815a40082e14),CNST_LIMB(0xa2fb4713ee182be),CNST_LIMB(0x6691fcc7a3042b5),CNST_LIMB(0xd7baca281bd7bfe),CNST_LIMB(0x31645ad7700b6fe1)},14,10}, + {CNST_LIMB(0x3c47d8d728a77ebb),{CNST_LIMB(0xfcb9aee19f3d0ca),2,CNST_LIMB(0xee09ca35d620514),CNST_LIMB(0x25e3c1639f7dc597),CNST_LIMB(0x176f977d1145f08f),CNST_LIMB(0x4a431b566c292ba),CNST_LIMB(0x100ae9d9482d6937)},24,9}, + {CNST_LIMB(0x77ab7da9d709ea9),{CNST_LIMB(0x11d1e7012ab3aa25),5,CNST_LIMB(0x1b394f7170aed8e),CNST_LIMB(0x546efaf8f3107d0),CNST_LIMB(0x42ed2efa9db39d8),CNST_LIMB(0xcf1c08fc6f825e),CNST_LIMB(0x252dd3fc3932c60)},33,8}, + {CNST_LIMB(0x310df3e7bd4bc897),{CNST_LIMB(0x4dfeef7ace095886),2,CNST_LIMB(0xaba3c794d85150d),CNST_LIMB(0x17a7ea757afc9b41),CNST_LIMB(0x27386bf8f31e3ba7),CNST_LIMB(0x14f913784ca1b09a),CNST_LIMB(0x19a5850266378808)},41,8}, + {CNST_LIMB(0xd997f089e8af1f),{CNST_LIMB(0x2d2f79839e6b7329),8,CNST_LIMB(0x285a2dd96a188d),CNST_LIMB(0x334ffbd384a516),CNST_LIMB(0xd9f5c4d959d8c),CNST_LIMB(0x1a7b0c8f9e2a8),CNST_LIMB(0x51d4df5ea86eca)},49,7}, + {CNST_LIMB(0x2514ab8fece6d79),{CNST_LIMB(0xb9d8ba8530d526d2),6,CNST_LIMB(0x111e482834cf602),CNST_LIMB(0x2099b9b4399ea77),CNST_LIMB(0xa7e65453d2c58b),CNST_LIMB(0x1543e97a71ba902),CNST_LIMB(0x13c9258fa65ea5c)},56,7}, + {CNST_LIMB(0x690efbefde431f9),{CNST_LIMB(0x37e6fe9321e30a89),5,CNST_LIMB(0x67c69a65020950a),CNST_LIMB(0x3d4da34fd3fb29d),CNST_LIMB(0x4481530580bf270),CNST_LIMB(0x53418b541a702fb),CNST_LIMB(0x5a63ba140615695)},63,7}, + {CNST_LIMB(0xf49e199a5f2f371),{CNST_LIMB(0xbe97cf50195e4cf),4,CNST_LIMB(0xb61e665a0d0c8f0),CNST_LIMB(0x12404319392532e),CNST_LIMB(0xc11fa27489010aa),CNST_LIMB(0x9486cdb3a063f1d),CNST_LIMB(0x90fb58fe1716f29)},70,7}, + {CNST_LIMB(0x20e4ce7eee0a5edf),{CNST_LIMB(0xf216910d87cce9ec),2,CNST_LIMB(0x19be5a877db767e7),CNST_LIMB(0x14174edbad8e4db0),CNST_LIMB(0x13aa47a54ebc0ab3),CNST_LIMB(0x34e03d849eed1a0),CNST_LIMB(0x1c348c675b2b87a9)},77,7}, + {CNST_LIMB(0x3c3b299a83e166e5),{CNST_LIMB(0x1004d8385b0845e0),2,CNST_LIMB(0xf135995f07a646c),CNST_LIMB(0x39f996f3e7c62cb6),CNST_LIMB(0x10e385c8b908ec46),CNST_LIMB(0x108780c61cd93a1),CNST_LIMB(0xece590a749ce9e6)},84,7}, + {CNST_LIMB(0x7385117dabf89767),{CNST_LIMB(0x1ba83180cf48fd02),1,CNST_LIMB(0x18f5dd04a80ed132),CNST_LIMB(0x134aacf48cf374fd),CNST_LIMB(0x5f5e8ab304a603e1),CNST_LIMB(0x8196d4d84952f0b),CNST_LIMB(0x27fbce261e06981)},91,7}, + {CNST_LIMB(0x6b1dd94152d113),{CNST_LIMB(0x31e8de86cb665558),9,CNST_LIMB(0x57c2791756ffa7),CNST_LIMB(0x155d1b6359e72e),CNST_LIMB(0x26e2dd434311d6),CNST_LIMB(0x2d6624583bf57f),CNST_LIMB(0x4b3c0311592466)},98,6}, + {CNST_LIMB(0x9bed1488742f9b),{CNST_LIMB(0xa44d3b1c6d785d44),8,CNST_LIMB(0x2f0a502161e5b4),CNST_LIMB(0x9197cc3e5a5b04),CNST_LIMB(0x58ecad625341f6),CNST_LIMB(0x2c8e81222f4972),CNST_LIMB(0x1f80904334e61e)},104,6}, + {CNST_LIMB(0xd851b0362c316b),{CNST_LIMB(0x2ef5b88db4540035),8,CNST_LIMB(0xcfa22017ddb3c6),CNST_LIMB(0x213062fd865691),CNST_LIMB(0x81822846481a0d),CNST_LIMB(0x4b3f5844dfd386),CNST_LIMB(0x746b08e79bff57)},110,6}, + {CNST_LIMB(0x129e6025385b5e9),{CNST_LIMB(0xb7fd23d5247f5d33),7,CNST_LIMB(0x1283c028c9d61ad),CNST_LIMB(0x8a2496a2184268),CNST_LIMB(0x702aa9d6cae97c),CNST_LIMB(0x8700d0e7b38adb),CNST_LIMB(0x562031b42d3873)},116,6}, + {CNST_LIMB(0x1b399405df9e1d9),{CNST_LIMB(0x2ce69e058ed22408),7,CNST_LIMB(0xc43448ef95aada),CNST_LIMB(0x2a35f6f5397332),CNST_LIMB(0x18bba0a2b06f9b5),CNST_LIMB(0x1bf0769bdd0a51),CNST_LIMB(0xdaf86a9dd4f157)},122,6}, + {CNST_LIMB(0x26a9c83b1da0183),{CNST_LIMB(0xa7c312b1de2834bc),6,CNST_LIMB(0x245cdfc0d956145),CNST_LIMB(0xcfb5812fdbb80b),CNST_LIMB(0x7f9bd0fd4d9771),CNST_LIMB(0x206d41f157b339d),CNST_LIMB(0x1597d040f39bed6)},128,6}, + {CNST_LIMB(0x36518f1ed35fae9),{CNST_LIMB(0x2da0bb538e68c61b),6,CNST_LIMB(0x161b11f812f7dbd),CNST_LIMB(0x1912054119f8337),CNST_LIMB(0x28b68baf0254a33),CNST_LIMB(0x1febc2a846ec627),CNST_LIMB(0x106e286e91657ac)},134,6}, + {CNST_LIMB(0x499cea9952ffcb7),{CNST_LIMB(0xbd2398239911cb86),5,CNST_LIMB(0x2f49990f2b0b4af),CNST_LIMB(0x3efc376b6d3879a),CNST_LIMB(0x16bf595684e7cae),CNST_LIMB(0x2096f989291e15a),CNST_LIMB(0x3f877653fe30a29)},140,6}, + {CNST_LIMB(0x603dc1f0578e36b),{CNST_LIMB(0x547a4d1f60bb6de6),5,CNST_LIMB(0x35de2e91a2ab072),CNST_LIMB(0x3ae19a039d933f9),CNST_LIMB(0x49f04fa32aed515),CNST_LIMB(0x49f39ce5e69737b),CNST_LIMB(0x48e7a8d6354cb3f)},146,6}, + {CNST_LIMB(0x822f4ff1bb75c7d),{CNST_LIMB(0xf7684c1a915fd94f),4,CNST_LIMB(0x3c4551ba4cbccdd),CNST_LIMB(0x3e072857c5d22e8),CNST_LIMB(0x757d8256f24de27),CNST_LIMB(0x256d9df09b5df5c),CNST_LIMB(0x19974713584ab80)},152,6}, + {CNST_LIMB(0xacfc9fbdf683023),{CNST_LIMB(0x7ad9852da99412df),4,CNST_LIMB(0x754da5eeda3acdb),CNST_LIMB(0x91f55d002dee623),CNST_LIMB(0x96936cc5e49d5ea),CNST_LIMB(0x766649a4996390),CNST_LIMB(0xaa8c52b8eea17dd)},158,6}, + {CNST_LIMB(0xe09d410f1fe4edb),{CNST_LIMB(0x23c5744aa32cf453),4,CNST_LIMB(0x34f16cefc1e749a),CNST_LIMB(0x2668179180c1b62),CNST_LIMB(0xdb241be2f133397),CNST_LIMB(0xa7c11527a49744e),CNST_LIMB(0x67d18e0669fea5b)},164,6}, + {CNST_LIMB(0x1149424a578f0ce7),{CNST_LIMB(0xd9e7a906d91cf1db),3,CNST_LIMB(0xdfe5fef362d4b5e),CNST_LIMB(0xcf056a84b77c77c),CNST_LIMB(0x985dfab0d2bd76b),CNST_LIMB(0xf57931f6922ec07),CNST_LIMB(0x44b19bfab74d6)},170,6}, + {CNST_LIMB(0x15b025d5fd579777),{CNST_LIMB(0x79b813c3ed8f4fd2),3,CNST_LIMB(0x116e5fce1d3c7de3),CNST_LIMB(0x1468c60d0220a399),CNST_LIMB(0xf10192b1089742d),CNST_LIMB(0xeae0b108eba5be6),CNST_LIMB(0xf0e98ff5e4d57d4)},176,6}, + {CNST_LIMB(0x1a5f81f6e38d3f1d),{CNST_LIMB(0x369eab91d724ae89),3,CNST_LIMB(0x12a46e520008c7fb),CNST_LIMB(0x638a97340d45e81),CNST_LIMB(0x12b4b0c893a62d44),CNST_LIMB(0x1072dcd55e5547d0),CNST_LIMB(0x18ce18c4a086d95f)},182,6}, + {CNST_LIMB(0x23293bf9b6fe2259),{CNST_LIMB(0xd1f849a43b917c65),2,CNST_LIMB(0x9df5c2bff0d0f91),CNST_LIMB(0xff1fdef6c15b8c),CNST_LIMB(0xec1383d93946006),CNST_LIMB(0x20ce6fd4fbbb8838),CNST_LIMB(0x55871453993a979)},188,6}, + {CNST_LIMB(0x2c1eaa6645e21b17),{CNST_LIMB(0x735a473662e09835),2,CNST_LIMB(0x2366ac00a295788d),CNST_LIMB(0xf8778468c26bac6),CNST_LIMB(0x10ecc751d2724c63),CNST_LIMB(0x4882fbd9d3d43e1),CNST_LIMB(0x2de76607a7f1541)},194,6}, + {CNST_LIMB(0x3646542a1110061b),{CNST_LIMB(0x2ddf24b018173a2c),2,CNST_LIMB(0x26e6af57bbbfe794),CNST_LIMB(0x1974e8d33a8f431f),CNST_LIMB(0x34da7258db6f7b4f),CNST_LIMB(0x2af310e921f874f8),CNST_LIMB(0x3cfeed9d4afc97)},200,6}, + {CNST_LIMB(0x4125602df5b7fa0b),{CNST_LIMB(0xf6fe47f7e339f3ce),1,CNST_LIMB(0x3c8fdf761ed811df),CNST_LIMB(0x145648c8769aba41),CNST_LIMB(0x3270209c06bd9a17),CNST_LIMB(0x2c03f98e45b9dca3),CNST_LIMB(0x3341dcfe340ee93e)},206,6}, + {CNST_LIMB(0x4e06bb83aa64f48d),{CNST_LIMB(0xa3f6020ab0b7e0d3),1,CNST_LIMB(0x15ebcd7500d12259),CNST_LIMB(0x786bf28f0081f92),CNST_LIMB(0x15d832d09f03b587),CNST_LIMB(0xaa3e94d54c2a575),CNST_LIMB(0x471850a042d21386)},212,6}, + {CNST_LIMB(0x6953db39a8298d8b),{CNST_LIMB(0x371b0bbe24632f20),1,CNST_LIMB(0x2d58498caface4ea),CNST_LIMB(0x557c399022219340),CNST_LIMB(0x2cb32a1a8fdd68c2),CNST_LIMB(0x122684249d42b9a9),CNST_LIMB(0x13c80507e77a929c)},218,6}, + {CNST_LIMB(0x15fafabe1c1777),{CNST_LIMB(0x74b22475baab0cce),11,CNST_LIMB(0xc763842e2c34d),CNST_LIMB(0x77d3f710b457b),CNST_LIMB(0x155a43f5525196),CNST_LIMB(0x148e30e0a5dee3),CNST_LIMB(0x13aa97836b8150)},224,5}, + {CNST_LIMB(0x18552ab4f8303b),{CNST_LIMB(0x50aaa1ed4d926e62),11,CNST_LIMB(0x815be492ca359),CNST_LIMB(0x1b55fe26d36ad),CNST_LIMB(0x113a54ceb7846),CNST_LIMB(0x1688511dfe47f),CNST_LIMB(0x66ccabff6c6c8)},229,5}, + {CNST_LIMB(0x1a99c2502dda5f),{CNST_LIMB(0x33f675a22ebecef5),11,CNST_LIMB(0x12ab7e96d807ff),CNST_LIMB(0x1d3db891dce3b),CNST_LIMB(0x19511de2e3095c),CNST_LIMB(0x2741e555a0bff),CNST_LIMB(0x51c7d31a19281)},234,5}, + {CNST_LIMB(0x1ebf9e78cd7ecb),{CNST_LIMB(0xa6b5da36fa2470c),11,CNST_LIMB(0xaebd869698c2f),CNST_LIMB(0x18e178fc70e26a),CNST_LIMB(0x64439ec9707b5),CNST_LIMB(0x116d1f70d29f20),CNST_LIMB(0xeea2317a9a585)},239,5}, + {CNST_LIMB(0x2214c7d5d9ce07),{CNST_LIMB(0xe0bc0f6215d26cf9),10,CNST_LIMB(0x1ffbac72c32f72),CNST_LIMB(0x1447f31b055129),CNST_LIMB(0x122d28bd754f9a),CNST_LIMB(0x106685d95b6d85),CNST_LIMB(0x18c9fdf391bdff)},244,5}, + {CNST_LIMB(0x25e2755d49ffa7),{CNST_LIMB(0xb078a0cae16506b6),10,CNST_LIMB(0x218554ef385919),CNST_LIMB(0xe00c975692d8e),CNST_LIMB(0x1afd2511d2f776),CNST_LIMB(0x108b0b031673f7),CNST_LIMB(0x8d919ed067cf0)},249,5}, + {CNST_LIMB(0x2925e3d5425d41),{CNST_LIMB(0x8e2c20d6f8f795ce),10,CNST_LIMB(0x1c5f29cb4c13c8),CNST_LIMB(0x15e11f6e5f634),CNST_LIMB(0xb32166d7982b3),CNST_LIMB(0xa636cf5c4f642),CNST_LIMB(0x28f997d81938bc)},254,5}, + {CNST_LIMB(0x2f39e99d11c26d),{CNST_LIMB(0x5aed08e710697213),10,CNST_LIMB(0x213b4a00c79b71),CNST_LIMB(0x1bd2737e294111),CNST_LIMB(0xd01c8aaaae314),CNST_LIMB(0xb00f1e27ed99e),CNST_LIMB(0x1d21748adab7e4)},259,5}, + {CNST_LIMB(0x3502a3ce62a769),{CNST_LIMB(0x35126ab40383fc5c),10,CNST_LIMB(0xf411f8bafb90c),CNST_LIMB(0x1fa38c975e6347),CNST_LIMB(0xf4058b043df4e),CNST_LIMB(0x2af2733656b159),CNST_LIMB(0x196e94f446c597)},264,5}, + {CNST_LIMB(0x3b357b23b014b1),{CNST_LIMB(0x14b711563eba7d77),10,CNST_LIMB(0x32f1ffd1469b4e),CNST_LIMB(0x197f48859c01a3),CNST_LIMB(0x29509dc5352d40),CNST_LIMB(0x335e5c9ef5d7fe),CNST_LIMB(0x284e1a5376a683)},269,5}, + {CNST_LIMB(0x420d06773114d3),{CNST_LIMB(0xf01a36d7bbf66dfc),9,CNST_LIMB(0xd86f221cf4e60),CNST_LIMB(0x728955d2f4a8d),CNST_LIMB(0x1a631ed35adca5),CNST_LIMB(0x2d592810a2cd39),CNST_LIMB(0x1215b15f856f68)},274,5}, + {CNST_LIMB(0x4c19f733c90d09),{CNST_LIMB(0xae954f9b28df48d8),9,CNST_LIMB(0xcab96d4cf28bb),CNST_LIMB(0x42b5fc3fd6e7ec),CNST_LIMB(0x2b7f897adc30de),CNST_LIMB(0x1a97bb06e110c0),CNST_LIMB(0x304db431256118)},279,5}, + {CNST_LIMB(0x52f224bf890ffd),{CNST_LIMB(0x8b0d84b8653cb09f),9,CNST_LIMB(0x8c298ef08a942),CNST_LIMB(0x2999ac4ebb9e26),CNST_LIMB(0x3dd9eb9ca2c026),CNST_LIMB(0x43401c4563f790),CNST_LIMB(0x38d5e8bf6d2c89)},284,5}, + {CNST_LIMB(0x5bf703dda941b1),{CNST_LIMB(0x644f51d4add132a4),9,CNST_LIMB(0x38fd3f81414bb8),CNST_LIMB(0x20049119d93b7c),CNST_LIMB(0x4e479d97844206),CNST_LIMB(0x294a3066f3b775),CNST_LIMB(0x1c21bda84cf2fc)},289,5}, + {CNST_LIMB(0x68cf321fe6202f),{CNST_LIMB(0x38a4d27caeef8e91),9,CNST_LIMB(0x1e26a01f2b6d41),CNST_LIMB(0x9e9e8993d282b),CNST_LIMB(0x417ad2819cd4fb),CNST_LIMB(0x627fb183ab0b1a),CNST_LIMB(0x278b9f029564e7)},294,5}, + {CNST_LIMB(0x71dad4e06cde9b),{CNST_LIMB(0x1fce1dcd4eb47a27),9,CNST_LIMB(0x457bdbeb7801db),CNST_LIMB(0x1f2b3df5db8f09),CNST_LIMB(0x2149ca25813ef0),CNST_LIMB(0x17d20c710e4487),CNST_LIMB(0x40ceb8ee4ca73d)},299,5}, + {CNST_LIMB(0x7b5e9ca091c63d),{CNST_LIMB(0x99bc23041414782),9,CNST_LIMB(0x1ac11ef1a1cf79),CNST_LIMB(0x313f0652fefffc),CNST_LIMB(0x12f34ea4e7a5db),CNST_LIMB(0x2aa2b3b3300bfd),CNST_LIMB(0x3245caffd0690c)},304,5}, + {CNST_LIMB(0x892f2017af4a77),{CNST_LIMB(0xddb91a666e887a07),8,CNST_LIMB(0x633133de624045),CNST_LIMB(0x7f207860875935),CNST_LIMB(0x702aff29ff7777),CNST_LIMB(0x1cc53fa2f53db9),CNST_LIMB(0x2c5ff88b6e27ee)},309,5}, + {CNST_LIMB(0x93efab3d98e265),{CNST_LIMB(0xbb00736076c6c8fc),8,CNST_LIMB(0x42ac68703b39),CNST_LIMB(0x4d4d015d5d1bd7),CNST_LIMB(0x85c801afb0f411),CNST_LIMB(0x4579d8022d0a69),CNST_LIMB(0x32ea2e520e3d23)},314,5}, + {CNST_LIMB(0x9fd1e9a289b8f9),{CNST_LIMB(0x9a0fb77008192e78),8,CNST_LIMB(0x9cfd1af6dc136),CNST_LIMB(0x23a28bc352c87c),CNST_LIMB(0x582383446e53c2),CNST_LIMB(0x3d52e0695b07e4),CNST_LIMB(0x83c6fc0e7cfd23)},319,5}, + {CNST_LIMB(0xb3ffc82a3b00bb),{CNST_LIMB(0x6c17325c7676de1f),8,CNST_LIMB(0x104f63f41af61c),CNST_LIMB(0x838ff92da5d267),CNST_LIMB(0xb37001a22f0194),CNST_LIMB(0x4487295b668b16),CNST_LIMB(0xa06ce4ed65729d)},324,5}, + {CNST_LIMB(0xc78aab3260ed67),{CNST_LIMB(0x486ec1d048657b5d),8,CNST_LIMB(0x5654a773cfd408),CNST_LIMB(0xb3f20a79edde43),CNST_LIMB(0xaebbd1a69724dd),CNST_LIMB(0x81191f0503a9),CNST_LIMB(0x3b54fc6e1ed034)},329,5}, + {CNST_LIMB(0xd8b06a4b9eddc9),{CNST_LIMB(0x2e7147c081441aeb),8,CNST_LIMB(0x5fe29aca965ce2),CNST_LIMB(0x9cb19caad665ca),CNST_LIMB(0x147b04c65844fd),CNST_LIMB(0x7a1c878be8db45),CNST_LIMB(0x8f4f4d51c80dfd)},334,5}, + {CNST_LIMB(0xe8f35bfe49ae4b),{CNST_LIMB(0x19547b44fa632b82),8,CNST_LIMB(0x4ce005e11fafad),CNST_LIMB(0x57f2d94de4ea00),CNST_LIMB(0xb885b9e976e473),CNST_LIMB(0x1eb25c197e9b39),CNST_LIMB(0xe2c45221f5cdb7)},339,5}, + {CNST_LIMB(0xfcff7f19788a27),{CNST_LIMB(0x3099f4bf7423272),8,CNST_LIMB(0x982693b0c3a8b),CNST_LIMB(0xa6eee9dce0fc63),CNST_LIMB(0xf1290f2b74223c),CNST_LIMB(0x36c85e11826e0b),CNST_LIMB(0xbe15668a4d3771)},344,5}, + {CNST_LIMB(0x10f681c21a80325),{CNST_LIMB(0xe2ef902951d2322d),7,CNST_LIMB(0x7efd8450d50a2b),CNST_LIMB(0x37c115b60abfde),CNST_LIMB(0x4a31517b3a2c0),CNST_LIMB(0x8ee426b2c25e26),CNST_LIMB(0xaf5e09c0582f8)},349,5}, + {CNST_LIMB(0x11ffa8ecf7814fb),{CNST_LIMB(0xc7250b86192832ab),7,CNST_LIMB(0xa4d35e0885656f),CNST_LIMB(0x6d14e9be5101ec),CNST_LIMB(0x93b36726a244a),CNST_LIMB(0xb56f38bde55186),CNST_LIMB(0x11443988cbd610f)},354,5}, + {CNST_LIMB(0x139b8ddf439b133),{CNST_LIMB(0xa1cbe52ffcdca969),7,CNST_LIMB(0x119cba991200690),CNST_LIMB(0xa8a1be12145159),CNST_LIMB(0x49831f7f1eb091),CNST_LIMB(0x5fe3a0bd210422),CNST_LIMB(0x11b90612ebf719f)},359,5}, + {CNST_LIMB(0x15b90aaef040351),{CNST_LIMB(0x791d6da971f79fb1),7,CNST_LIMB(0xc1c278790d9084),CNST_LIMB(0xa6bc771172ca70),CNST_LIMB(0x1219044d36b161b),CNST_LIMB(0x9363a00d9d3f5f),CNST_LIMB(0x14079ec2a37ea93)},364,5}, + {CNST_LIMB(0x17d664f86c88bd3),{CNST_LIMB(0x57a9176de3f40918),7,CNST_LIMB(0x13ca8e0f80a9a0f),CNST_LIMB(0xfc1ecc66c0c93b),CNST_LIMB(0x15be6192051cb1a),CNST_LIMB(0x136f263b7a50fcc),CNST_LIMB(0x3820db8623a7)},369,5}, + {CNST_LIMB(0x1a44cc5ef4c16b5),{CNST_LIMB(0x37da80020a7d1f74),7,CNST_LIMB(0x18584281cee4069),CNST_LIMB(0x178a63d22596ba9),CNST_LIMB(0x6739c7c5ac4f2d),CNST_LIMB(0x14c57a38e4d612a),CNST_LIMB(0x13d2e7fd35623ae)},374,5}, + {CNST_LIMB(0x1ca80b29773de79),{CNST_LIMB(0x1dde9f723a4f55dc),7,CNST_LIMB(0x1ac9ceffdba98e2),CNST_LIMB(0xf4618a5f0fdaa9),CNST_LIMB(0x17b96b4ded53ebb),CNST_LIMB(0x7faf749bdd9cb1),CNST_LIMB(0xfa9d50111fc549)},379,5}, + {CNST_LIMB(0x1e7b019a7fa8931),{CNST_LIMB(0xcc3160c520cdb96),7,CNST_LIMB(0xb9d29212dc305a),CNST_LIMB(0x91586fa7d2facc),CNST_LIMB(0x2638c4c9135f19),CNST_LIMB(0x1c315565816b84a),CNST_LIMB(0xa92e9c918ad70f)},384,5}, + {CNST_LIMB(0x1fd932c2a6c3463),{CNST_LIMB(0x137e41a0c0b8d4f),7,CNST_LIMB(0x13669eac9e5ce80),CNST_LIMB(0x94dc55b30276b5),CNST_LIMB(0x1c52a400cc7dae6),CNST_LIMB(0x1cd876c8023e81b),CNST_LIMB(0x8e06dbbb7e4c2d)},389,5}, + {CNST_LIMB(0x2175e8bd7050e79),{CNST_LIMB(0xe9a698d03a5e604b),6,CNST_LIMB(0xdcf15b87971a56),CNST_LIMB(0x2e9e439e7517fb),CNST_LIMB(0x85bbfca7ac6da9),CNST_LIMB(0x500c9508abde31),CNST_LIMB(0x1c9d7aa292a48b0)},394,5}, + {CNST_LIMB(0x24033b205fe4527),{CNST_LIMB(0xc6f39cee1695e79a),6,CNST_LIMB(0x1a92e6b5ac379c9),CNST_LIMB(0x1f1b86c0e7f8d15),CNST_LIMB(0x1e362d27d79fda9),CNST_LIMB(0x4dcd13ebf2a00a),CNST_LIMB(0x408b8bd354f1b4)},399,5}, + {CNST_LIMB(0x265d2eb09cdc073),{CNST_LIMB(0xab112e468a91ceb0),6,CNST_LIMB(0x1d6aaadf0ce5062),CNST_LIMB(0x8cb5be41003782),CNST_LIMB(0x52b9980c0c4bec),CNST_LIMB(0x2228f2e6cbe8667),CNST_LIMB(0xca6f7400df044e)},404,5}, + {CNST_LIMB(0x2953a0e65ca6a1d),{CNST_LIMB(0x8c7372d9ab5569c1),6,CNST_LIMB(0x4a8c6ea2b8f6c9),CNST_LIMB(0x3588f2393801ce),CNST_LIMB(0x1fce38ab648e336),CNST_LIMB(0x89544c1c4d5e80),CNST_LIMB(0x6e5d409692ed37)},409,5}, + {CNST_LIMB(0x2c67f25a6bc9c63),{CNST_LIMB(0x70f57416f0cce89e),6,CNST_LIMB(0xaa4e781437cc6c),CNST_LIMB(0x1c38f9d456ca8d),CNST_LIMB(0x2682eae3a0afadb),CNST_LIMB(0x2b54835e8a4f4ca),CNST_LIMB(0x1ff894f600fa94f)},414,5}, + {CNST_LIMB(0x2fdd1a7524ae76d),{CNST_LIMB(0x564e31abce2eba47),6,CNST_LIMB(0x1b96371ad2128cf),CNST_LIMB(0x35309a6895ab0d),CNST_LIMB(0x14de5531da96df1),CNST_LIMB(0x3a924ccc42ac90),CNST_LIMB(0x315a6b9b99a595)},419,5}, + {CNST_LIMB(0x33770e6e18aeb53),{CNST_LIMB(0x3e5a14fd0434a100),6,CNST_LIMB(0x1e428c066216163),CNST_LIMB(0x93d03854bffefa),CNST_LIMB(0x77e62b6df8d4a1),CNST_LIMB(0x8a8b138bb2ed69),CNST_LIMB(0x292d249664af8db)},424,5}, + {CNST_LIMB(0x379c7dff6334d3b),{CNST_LIMB(0x269dcc0c8d56e875),6,CNST_LIMB(0x2460122cb5efa2d),CNST_LIMB(0x28e51e3c7265f2e),CNST_LIMB(0x1efacb51926e686),CNST_LIMB(0xfc8248ae79bd5f),CNST_LIMB(0x2f3b91b1fe1f65)},429,5}, + {CNST_LIMB(0x3b82f15f7249c49),{CNST_LIMB(0x134ee332d51f0306),6,CNST_LIMB(0x3137e2a5a467c9c),CNST_LIMB(0x79d488798b4960),CNST_LIMB(0xb436578d1069bb),CNST_LIMB(0x10ad84e585582d0),CNST_LIMB(0x3215616c9b153bf)},434,5}, + {CNST_LIMB(0x3fff4dd17ad4ff9),{CNST_LIMB(0x2c8c1d50d30af),6,CNST_LIMB(0x2c8ba14ac01c0),CNST_LIMB(0x2bd06852b51e327),CNST_LIMB(0x30714e5452d2c1),CNST_LIMB(0x327ff42efc6d9c),CNST_LIMB(0x244bb5001864710)},439,5}, + {CNST_LIMB(0x465670cc294b181),{CNST_LIMB(0xd1ddf947b9d55be0),5,CNST_LIMB(0x106a71bea4fc8c6),CNST_LIMB(0xa255b26c45d27f),CNST_LIMB(0x460d26a6240e466),CNST_LIMB(0x1dda425d1868b60),CNST_LIMB(0x3d6eff8580e97e1)},444,5}, + {CNST_LIMB(0x4aaaab2fe3fee47),{CNST_LIMB(0xb6db6aa7d3a37a63),5,CNST_LIMB(0x3fffe3e5e83bd06),CNST_LIMB(0xa8a65f30809160),CNST_LIMB(0xbfd8fef4142370),CNST_LIMB(0x358c77f78c2a4d0),CNST_LIMB(0x3a89f0ee6796b95)},449,5}, + {CNST_LIMB(0x4f8bbff17c95ef7),{CNST_LIMB(0x9bf032ee57751395),5,CNST_LIMB(0x2728c2e42e214cb),CNST_LIMB(0x37fb2686e89761e),CNST_LIMB(0x4a264029edea029),CNST_LIMB(0x1d504d3aecaaa50),CNST_LIMB(0x45b5a7b35031756)},454,5}, + {CNST_LIMB(0x553ea1ce3216691),{CNST_LIMB(0x806643148e9063ef),5,CNST_LIMB(0x441a9569bcc4d0),CNST_LIMB(0x535ae4be3f071a1),CNST_LIMB(0x545a793067e09d8),CNST_LIMB(0xd5d15c09afe8cd),CNST_LIMB(0x4534c23a01c6a96)},459,5}, + {CNST_LIMB(0x59f7c9a4fefb517),{CNST_LIMB(0x6c37fd6421ef50ed),5,CNST_LIMB(0x2f718dff2dd2af5),CNST_LIMB(0x4aea82d40c5cc72),CNST_LIMB(0x4f7cec2a6861199),CNST_LIMB(0xe868a369a42529),CNST_LIMB(0x40e610cd320b2f7)},464,5}, + {CNST_LIMB(0x5e8d3fa86f95521),{CNST_LIMB(0x5a8fc0667cc240fe),5,CNST_LIMB(0x1e464eb541eb375),CNST_LIMB(0x3892fa43db27fd5),CNST_LIMB(0x4e5c7836ddc791a),CNST_LIMB(0x36e537bed96365e),CNST_LIMB(0x4375094ddcb8820)},469,5}, + {CNST_LIMB(0x64157c62c33e31d),{CNST_LIMB(0x4767bbee2675bc54),5,CNST_LIMB(0x5ca490917e48378),CNST_LIMB(0x11867a67aa79db0),CNST_LIMB(0x6198c4cbcaf84e6),CNST_LIMB(0x4338ebe5ab25fcf),CNST_LIMB(0x11e91c53e48fd1e)},474,5}, + {CNST_LIMB(0x6ceeed4c43f4183),{CNST_LIMB(0x2cced2b1dae4601a),5,CNST_LIMB(0x4177b3fa2db8811),CNST_LIMB(0x2b3db3648dc8a5),CNST_LIMB(0x50f060794aa127),CNST_LIMB(0x4f7cdc200df8c9a),CNST_LIMB(0x4525db055625df3)},479,5}, + {CNST_LIMB(0x7287ee7e5f96919),{CNST_LIMB(0x1e1b2205d593e3a6),5,CNST_LIMB(0x576a64b8ee6a195),CNST_LIMB(0x7bd2ea513c7027),CNST_LIMB(0x17c4152c6d55daa),CNST_LIMB(0x39f7aac6f902f57),CNST_LIMB(0x14765413bf9b5ca)},484,5}, + {CNST_LIMB(0x79886d10dfa5165),{CNST_LIMB(0xd9f57c223f379ca),5,CNST_LIMB(0x5569f0d32bb81fb),CNST_LIMB(0x6f08a7fc8e770a6),CNST_LIMB(0x2c14d325ec8479f),CNST_LIMB(0x4499d22e49d3c7),CNST_LIMB(0x53f1f1eecdc8c2)},489,5}, + {CNST_LIMB(0x7e13347ac1526bf),{CNST_LIMB(0x3e8a375cf0fb774),5,CNST_LIMB(0x3d9970a7d5b2820),CNST_LIMB(0x3664c9d670bba16),CNST_LIMB(0x6ba929ee3cbcd5c),CNST_LIMB(0xd5d262e6d92452),CNST_LIMB(0x2f545142add8d05)},494,5}, + {CNST_LIMB(0x8566f0377d15459),{CNST_LIMB(0xeb44411c1363bcf4),4,CNST_LIMB(0x5defd97f5781d92),CNST_LIMB(0x16eaae98cb00189),CNST_LIMB(0x986f4f6d77c243),CNST_LIMB(0x57c736925ddfd9),CNST_LIMB(0x10a756243dbe4ca)},499,5}, + {CNST_LIMB(0x8bfc83897e6cdaf),{CNST_LIMB(0xd428ea393317b9f2),4,CNST_LIMB(0x2465196cadab32d),CNST_LIMB(0x7594e9e684d904a),CNST_LIMB(0x19cd4a75383b2d1),CNST_LIMB(0x6a0e9c23f177e64),CNST_LIMB(0x56f0f2ae36c5465)},504,5}, + {CNST_LIMB(0x94ad790245385eb),{CNST_LIMB(0xb8cae8ae9a639526),4,CNST_LIMB(0x51b43cc2b30e037),CNST_LIMB(0x4cb133bb88b3adc),CNST_LIMB(0x3ede33df9c5e3e3),CNST_LIMB(0x665226a2d290ac4),CNST_LIMB(0x33db5ce835ec6e4)},509,5}, + {CNST_LIMB(0x9c30734d93b1379),{CNST_LIMB(0xa397f073b55bde0b),4,CNST_LIMB(0x23144a1f00005b6),CNST_LIMB(0x826ad253a3ed324),CNST_LIMB(0x940ad5d52b4806c),CNST_LIMB(0x1729e9d2d022730),CNST_LIMB(0x20a978fb381a6c2)},514,5}, + {CNST_LIMB(0xa57e1fd7a44fbb9),{CNST_LIMB(0x8c0164efd39df203),4,CNST_LIMB(0x7c2d03c898866a8),CNST_LIMB(0x4037558c6f1e4eb),CNST_LIMB(0x6694cdbbb8803c7),CNST_LIMB(0x99396c89bf97452),CNST_LIMB(0x436126c1b000fab)},519,5}, + {CNST_LIMB(0xaf9b9be9c8401d1),{CNST_LIMB(0x7531f66eca55c19b),4,CNST_LIMB(0x3904fdff023d639),CNST_LIMB(0x962f9b532413fb3),CNST_LIMB(0x27ec74df2758058),CNST_LIMB(0x5836483d1e34f66),CNST_LIMB(0x8384a37fad8866d)},524,5}, + {CNST_LIMB(0xb9ba711d6e4a84f),{CNST_LIMB(0x60dc0b5cc82154b3),4,CNST_LIMB(0x9fa47788598936),CNST_LIMB(0x82bd019c1fa5a56),CNST_LIMB(0x50db17c34711736),CNST_LIMB(0x739121f55c5b75d),CNST_LIMB(0x912fe4d49b6d56)},529,5}, + {CNST_LIMB(0xc41a8a6c63a70d1),{CNST_LIMB(0x4e30c99728e3c197),4,CNST_LIMB(0xaded2f8836f2fac),CNST_LIMB(0xab84ac5c6d525d9),CNST_LIMB(0x488aa0b1f301ccb),CNST_LIMB(0x5fdf2905d976ad6),CNST_LIMB(0x5cb75a7adbb8561)},534,5}, + {CNST_LIMB(0xcd79628a71801f7),{CNST_LIMB(0x3ef33887b9ad5b44),4,CNST_LIMB(0xbffdafb9937daab),CNST_LIMB(0x8c3722255b2b8c7),CNST_LIMB(0x63cd1bbc0e9c22a),CNST_LIMB(0xbd17bc2e12ad950),CNST_LIMB(0x15e9799e0d76f1e)},539,5}, + {CNST_LIMB(0xd6f67d4726eaaf5),{CNST_LIMB(0x30df0c865cc92a96),4,CNST_LIMB(0xbb4b3b81c94fd1),CNST_LIMB(0x2a20ca76128ce99),CNST_LIMB(0x4a4022bdd8f612e),CNST_LIMB(0x3bafa50d5be5f8b),CNST_LIMB(0xb86a67f06630908)},544,5}, + {CNST_LIMB(0xe5d3b047627f8e3),{CNST_LIMB(0x1d275ac8c78303ec),4,CNST_LIMB(0xbcf14b4275878ed),CNST_LIMB(0x5ee8b82b0662dd),CNST_LIMB(0x77e3de57e11f662),CNST_LIMB(0x5ed59e5dfb5cd16),CNST_LIMB(0xbe6a6366650aef1)},549,5}, + {CNST_LIMB(0xef42ae515bfb29d),{CNST_LIMB(0x11e922af2e24e769),4,CNST_LIMB(0x1c926c98e452393),CNST_LIMB(0xd26a458c9c34765),CNST_LIMB(0x5da54b52a8aa98a),CNST_LIMB(0xa2ed4f828338df7),CNST_LIMB(0xe69ac190926521a)},554,5}, + {CNST_LIMB(0xfd32459f0b3d4bb),{CNST_LIMB(0x2d5ace688e647e9),4,CNST_LIMB(0x2cdba60f4c2b450),CNST_LIMB(0x2577b742a8ed5db),CNST_LIMB(0x144ef4109272736),CNST_LIMB(0xbe9326c4f15e1a9),CNST_LIMB(0xb96de853277fb4f)},559,5}, + {CNST_LIMB(0x10a16ef6c96a16c7),{CNST_LIMB(0xec9602538c0df011),3,CNST_LIMB(0x68a7f8a32c8aa57),CNST_LIMB(0x1445e7d17b921f3),CNST_LIMB(0x81c8debc8176f0b),CNST_LIMB(0xe3a1c5b816e4a65),CNST_LIMB(0xa52ad5bb93c9f4b)},564,5}, + {CNST_LIMB(0x117c2fec47f5e013),{CNST_LIMB(0xd48355880989be17),3,CNST_LIMB(0xb356114108dbef6),CNST_LIMB(0xe7ddeca9ba6a20c),CNST_LIMB(0xf2d7618ea8a6953),CNST_LIMB(0x412256baaec5c27),CNST_LIMB(0x1f8e16ca6e5c0d7)},569,5}, + {CNST_LIMB(0x129a8c10ae1f364b),{CNST_LIMB(0xb857af53b5b43644),3,CNST_LIMB(0xe26e327286a3e31),CNST_LIMB(0xeef9d55a9d06dbf),CNST_LIMB(0xe61febd3beb02b6),CNST_LIMB(0x10d018a00b7fd6a5),CNST_LIMB(0x32009c46e7c1314)},574,5}, + {CNST_LIMB(0x134631392d507059),{CNST_LIMB(0xa9063d94bb92a978),3,CNST_LIMB(0x56f8018b2ea4b7b),CNST_LIMB(0x1270cb710b035935),CNST_LIMB(0x11033d859716c4f9),CNST_LIMB(0xd45bebac416a68c),CNST_LIMB(0xc08fe72fc6eef84)},579,5}, + {CNST_LIMB(0x13fde7755d5fd9ed),{CNST_LIMB(0x99c48a788248a856),3,CNST_LIMB(0x1019267f9f81c8e4),CNST_LIMB(0x394e4098ea8549),CNST_LIMB(0x33c85c2a1514436),CNST_LIMB(0xa1e569d4432f4bb),CNST_LIMB(0x128bfbc862fb3c58)},584,5}, + {CNST_LIMB(0x15698c0906cc26a5),{CNST_LIMB(0x7e957ed81f600c1e),3,CNST_LIMB(0x1476fb9cb53a56e9),CNST_LIMB(0xeff15504451beab),CNST_LIMB(0xdea55fc79c32599),CNST_LIMB(0x76a982d54d956a1),CNST_LIMB(0x4d131625675abd7)},589,5}, + {CNST_LIMB(0x168a1ee80f6d92f5),{CNST_LIMB(0x6b73459d204359d1),3,CNST_LIMB(0x810ac07564aaf79),CNST_LIMB(0x874d5996e15561a),CNST_LIMB(0xb75c73837694b49),CNST_LIMB(0xd4645617d29779b),CNST_LIMB(0x12af15ef931be940)},594,5}, + {CNST_LIMB(0x17daa6de32466fbf),{CNST_LIMB(0x576bc18853c72908),3,CNST_LIMB(0x11757b52093fa28a),CNST_LIMB(0xff4c0f212559944),CNST_LIMB(0x40af9872004a0a5),CNST_LIMB(0x2b2b7c424c54c2b),CNST_LIMB(0x1a2b7130739c4c7)},599,5}, + {CNST_LIMB(0x18ea5f2dbe212911),{CNST_LIMB(0x48ca86c98010be89),3,CNST_LIMB(0x6d8483692b46556),CNST_LIMB(0x305d89220ec48d2),CNST_LIMB(0x1772200dfc1938dc),CNST_LIMB(0xded80c44ca87607),CNST_LIMB(0xb498b0490dc55dd)},604,5}, + {CNST_LIMB(0x1a0fa1ef47787d1b),{CNST_LIMB(0x3a56b20c2d70e08a),3,CNST_LIMB(0x15734e967cc39a0d),CNST_LIMB(0x8fc968191dc0fd3),CNST_LIMB(0x1680d35f18721f8f),CNST_LIMB(0x197b4a3e18c9e8bc),CNST_LIMB(0xc0ad81d645f40c7)},609,5}, + {CNST_LIMB(0x1b673b66a023a93f),{CNST_LIMB(0x2af150ff9195ac0f),3,CNST_LIMB(0x95ee9645ebf0cc9),CNST_LIMB(0x1717202bbc3e0a78),CNST_LIMB(0x126d365df320adf6),CNST_LIMB(0x137d63165361ab0e),CNST_LIMB(0x19ca69d84cc1417c)},614,5}, + {CNST_LIMB(0x1ce34de10c258111),{CNST_LIMB(0x1b9430b6521be183),3,CNST_LIMB(0x18e590f79ed3f778),CNST_LIMB(0xbcbaeb9ec0a1624),CNST_LIMB(0x18f51ac04296ceb6),CNST_LIMB(0x161b15271d06a3e1),CNST_LIMB(0x5f0a62fb317dd86)},619,5}, + {CNST_LIMB(0x1e19674e354f4667),{CNST_LIMB(0x102a99b0acd64358),3,CNST_LIMB(0xf34c58e5585ccc8),CNST_LIMB(0x15fad9b7ef3a5cbd),CNST_LIMB(0x1874ea34e3e274f9),CNST_LIMB(0x841598977c90581),CNST_LIMB(0x1c04690158b888d)},624,5}, + {CNST_LIMB(0x1f3740adb603b24d),{CNST_LIMB(0x66e52892f80015e),3,CNST_LIMB(0x645fa924fe26d98),CNST_LIMB(0xc022a525d7f5a4f),CNST_LIMB(0x16d7e66846e5d65b),CNST_LIMB(0x10105a92c09c5aa9),CNST_LIMB(0xedddad56d23fc0e)},629,5}, + {CNST_LIMB(0x20e7b3c0e3b73671),{CNST_LIMB(0xf1eabc8c8352c9af),2,CNST_LIMB(0x19aa15b9c5fd82e9),CNST_LIMB(0x10fd7c871bd5d222),CNST_LIMB(0x4ee89a76e1259e0),CNST_LIMB(0x1280d75e6bf3c134),CNST_LIMB(0x85e103f1853c3d)},634,5}, + {CNST_LIMB(0x22b5b4fc40d4c35f),{CNST_LIMB(0xd807362226cc7e50),2,CNST_LIMB(0xd080d1a3a2ea867),CNST_LIMB(0x1f068368adc3fde1),CNST_LIMB(0x178240b1c3cf35a9),CNST_LIMB(0x1dc077b2ed00fd8c),CNST_LIMB(0x2e6e64a07f9c833)},639,5}, + {CNST_LIMB(0x23cff30e6fb8f7fd),{CNST_LIMB(0xc97f150b60a9e71b),2,CNST_LIMB(0x5505a9af1f13815),CNST_LIMB(0x22434bb477153d47),CNST_LIMB(0x87670d53a068a58),CNST_LIMB(0x21b754fa0ae7b745),CNST_LIMB(0x2182750984e9f50b)},644,5}, + {CNST_LIMB(0x266a30ee37cc7341),{CNST_LIMB(0xaa808f26b38df4ef),2,CNST_LIMB(0x1982da6ab1354c7a),CNST_LIMB(0xfda1381ca806f81),CNST_LIMB(0x1a31d30d06bd5b7b),CNST_LIMB(0xbc65e21d25000c6),CNST_LIMB(0x132d8167c6a0973b)},649,5}, + {CNST_LIMB(0x283e6bddfbebab6d),{CNST_LIMB(0x971e4733b2e0d2bf),2,CNST_LIMB(0xe8978cc1879fb72),CNST_LIMB(0x1c9e26afc4d767da),CNST_LIMB(0x1e376fcf488c8249),CNST_LIMB(0x977e63f145b0e1d),CNST_LIMB(0xe2db9891e737aa1)},654,5}, + {CNST_LIMB(0x298d29c47d06f16b),{CNST_LIMB(0x8a4e7f92da9842e7),2,CNST_LIMB(0x6b1056511d6577e),CNST_LIMB(0x592f6f3bbda49cc),CNST_LIMB(0x2692769f01fb0a5b),CNST_LIMB(0x5f3e5623e91d30d),CNST_LIMB(0x2104d5242a92b48d)},659,5}, + {CNST_LIMB(0x2afa8c16de374c13),{CNST_LIMB(0x7d364b6556c2b905),2,CNST_LIMB(0x291b438da8eb83a1),CNST_LIMB(0x14222ff3cbf7d671),CNST_LIMB(0x126ac7f90facd4d3),CNST_LIMB(0x46d452f540a8d2),CNST_LIMB(0xb0b0fc23426b0b7)},664,5}, + {CNST_LIMB(0x2c44b3413ab0dee7),{CNST_LIMB(0x721b37f337583151),2,CNST_LIMB(0x22a87fb9da8ba57d),CNST_LIMB(0x26943e2ad67b49d6),CNST_LIMB(0x1ef6cfa904bef1cd),CNST_LIMB(0x18e7d1baf5588938),CNST_LIMB(0x1ad24c5276c66d2f)},669,5}, + {CNST_LIMB(0x2e88fa7433ac7823),{CNST_LIMB(0x60141b17275393e2),2,CNST_LIMB(0x17531bbafda1a751),CNST_LIMB(0xf3ea18441a36068),CNST_LIMB(0x130110257a01259a),CNST_LIMB(0x14122cf2cde8eecc),CNST_LIMB(0x24d25acd522c56b7)},674,5}, + {CNST_LIMB(0x303fb77cc2bfe62b),{CNST_LIMB(0x539292e31ed6db25),2,CNST_LIMB(0xec16a9032408129),CNST_LIMB(0x22483ceeb16c18a3),CNST_LIMB(0x1dd1cf7128399e5a),CNST_LIMB(0x11b3d478af2cbe42),CNST_LIMB(0x2a86cb29ac9873d3)},679,5}, + {CNST_LIMB(0x32eeac8f8d221e55),{CNST_LIMB(0x41ae89b9e560d65a),2,CNST_LIMB(0x156a1323e556857),CNST_LIMB(0x865eccdcf192078),CNST_LIMB(0x29e9014382ce253e),CNST_LIMB(0x737a633527d55ef),CNST_LIMB(0xe3223c22b887658)},684,5}, + {CNST_LIMB(0x354d75b3270eaedd),{CNST_LIMB(0x336093f2bc204c55),2,CNST_LIMB(0x2aca293363c5448c),CNST_LIMB(0x17160152eb4aa39f),CNST_LIMB(0x16b50b70fa80acee),CNST_LIMB(0x2493bd25f34e1536),CNST_LIMB(0x18f710cf9496617c)},689,5}, + {CNST_LIMB(0x37b26a3f703f6027),{CNST_LIMB(0x2629d54caca5a93b),2,CNST_LIMB(0x213657023f027f64),CNST_LIMB(0x257ed9007720600c),CNST_LIMB(0xaf3dcc0f043ce98),CNST_LIMB(0x115787f3ada80173),CNST_LIMB(0x7071885da2772a7)},694,5}, + {CNST_LIMB(0x3a2d837d37f39e39),{CNST_LIMB(0x199e982941bda182),2,CNST_LIMB(0x1749f20b2031871c),CNST_LIMB(0x153d7d45eae3fbc6),CNST_LIMB(0x3035b3e81047b52f),CNST_LIMB(0x3096ed6d9a28fa5a),CNST_LIMB(0x221887c4142d7434)},699,5}, + {CNST_LIMB(0x3d6201596c85db3f),{CNST_LIMB(0xaea3e9ef4bf14aa),2,CNST_LIMB(0xa77fa9a4de89304),CNST_LIMB(0x140df851fb641569),CNST_LIMB(0x275b27f619d2cffb),CNST_LIMB(0x16df2d5134102662),CNST_LIMB(0x10ab318b9b8a8aef)},704,5}, + {CNST_LIMB(0x401080f68635f765),{CNST_LIMB(0xff7c1a4f020138fa),1,CNST_LIMB(0x3fce7d1c6d5e19d1),CNST_LIMB(0x1feb2b2abf929ebc),CNST_LIMB(0x279cb7a4291af740),CNST_LIMB(0x384bce4293f19637),CNST_LIMB(0x168a9776844c9b6f)},709,5}, + {CNST_LIMB(0x41c3dea2c7c4509b),{CNST_LIMB(0xf2421126ad7a2852),1,CNST_LIMB(0x3ab46417a8b30e2f),CNST_LIMB(0x35206295938b9c19),CNST_LIMB(0x317d8909a9980afe),CNST_LIMB(0x195b889376db752f),CNST_LIMB(0xeb8a8f47083a08e)},714,5}, + {CNST_LIMB(0x441255580dcabef7),{CNST_LIMB(0xe1601977719c2988),1,CNST_LIMB(0x33c8fff7d69fc31b),CNST_LIMB(0x3aa78ab59c61fb90),CNST_LIMB(0x3c41600b3a070fd7),CNST_LIMB(0x121266b65d774473),CNST_LIMB(0x5812c8f46959e7)},719,5}, + {CNST_LIMB(0x467e90ff075dfa77),{CNST_LIMB(0xd0d4ccbfd7fdb2ae),1,CNST_LIMB(0x2c844d02e9e6109b),CNST_LIMB(0x395a6f0c5abc0a3c),CNST_LIMB(0x30393c08245d18c3),CNST_LIMB(0xac042a1b1191d06),CNST_LIMB(0x1d0c88b0cc347eed)},724,5}, + {CNST_LIMB(0x35b7e6a52de6b),{CNST_LIMB(0x30ff8515bed6fc1f),14,CNST_LIMB(0x2f4533b937fab),CNST_LIMB(0xeb33cd2951b7),CNST_LIMB(0x28ce28b5e1739),CNST_LIMB(0x30d609f6bade3),CNST_LIMB(0x249a87bc9957)},729,4}, + {CNST_LIMB(0x4b9237b1fac55af1),{CNST_LIMB(0xb19ac3ed68fa0441),1,CNST_LIMB(0x1d4958ea0fafef2d),CNST_LIMB(0x4ba7c350e3c499e),CNST_LIMB(0xe26c59f6a4a42e5),CNST_LIMB(0x4acd391ac5c14c62),CNST_LIMB(0x38a0169051f4a371)},733,5}, + {CNST_LIMB(0x4fa265b31b73c6df),{CNST_LIMB(0x9b7b0be2fb2dbf62),1,CNST_LIMB(0x1118cee6ada4ab63),CNST_LIMB(0x2b4fe57f0434fb44),CNST_LIMB(0x2cffeb10b15bf6),CNST_LIMB(0xe12f06864906a7b),CNST_LIMB(0x2a0824475f11f823)},738,5}, + {CNST_LIMB(0x516d33f3efe608d5),{CNST_LIMB(0x926c85237f2dc355),1,CNST_LIMB(0xbb86424304de581),CNST_LIMB(0x3ec190a9cee7a48e),CNST_LIMB(0xd7d8bfe60d52602),CNST_LIMB(0xdff7561c9c07756),CNST_LIMB(0x3c1d2db82b327710)},743,5}, + {CNST_LIMB(0x545e342d68fbf683),{CNST_LIMB(0x8464ceb2fdd80297),1,CNST_LIMB(0x2e56377c50c1c77),CNST_LIMB(0x474ec2f4bd92576),CNST_LIMB(0x2a5da9663350db1),CNST_LIMB(0x220077cd63148dd2),CNST_LIMB(0x280dcbaf0c2ad61c)},748,5}, + {CNST_LIMB(0x57e94c457826bd6b),{CNST_LIMB(0x74bd3fdb5c8280eb),1,CNST_LIMB(0x502d67750fb2852a),CNST_LIMB(0x45149579eaa28023),CNST_LIMB(0x3bb53a4c0c4db579),CNST_LIMB(0x3a96a3180f221b2),CNST_LIMB(0x27f9af8526a8cf70)},753,5}, + {CNST_LIMB(0x5b9b45655ebf3b79),{CNST_LIMB(0x65b42a0f00510df2),1,CNST_LIMB(0x48c975354281890e),CNST_LIMB(0x2929df87cfd7453c),CNST_LIMB(0x1b6bb026965ae7ed),CNST_LIMB(0x52659a85b7df96c2),CNST_LIMB(0x21db715c0f72134)},758,5}, + {CNST_LIMB(0x5e6ad0d2eaa14c25),{CNST_LIMB(0x5b0e2387ccda26c3),1,CNST_LIMB(0x432a5e5a2abd67b6),CNST_LIMB(0x14b7571d1a05b77d),CNST_LIMB(0x498547c0b3350ce8),CNST_LIMB(0x9d4e28ce05c6c27),CNST_LIMB(0x4913b5ba5c5edc8)},763,5}, + {CNST_LIMB(0x60704759208cd21d),{CNST_LIMB(0x53c7ef8bdf16795b),1,CNST_LIMB(0x3f1f714dbee65bc6),CNST_LIMB(0x25fc61d1a473562),CNST_LIMB(0x158a2ce0171d5fd),CNST_LIMB(0x2f3bdc4b8520f24c),CNST_LIMB(0x4081386865e00703)},768,5}, + {CNST_LIMB(0x63bc6b32a19c883b),{CNST_LIMB(0x488c1dcdc113150a),1,CNST_LIMB(0x3887299abcc6ef8a),CNST_LIMB(0x2aab5731e10d2529),CNST_LIMB(0x5eeeb60320f0bef4),CNST_LIMB(0x18e4d9f1c279596e),CNST_LIMB(0xf478370d7e2465f)},773,5}, + {CNST_LIMB(0x47f6a9e8dab75),{CNST_LIMB(0xc7577d2a861d140e),13,CNST_LIMB(0x435dc14ffaf0e),CNST_LIMB(0x2557057e3745b),CNST_LIMB(0x450b5149277a6),CNST_LIMB(0xda1fae30c112),CNST_LIMB(0x3951ca3221a2d)},778,4}, + {CNST_LIMB(0x6e373b550764872f),{CNST_LIMB(0x294ecadbf29bc1cb),1,CNST_LIMB(0x23918955f136f1a2),CNST_LIMB(0x29cffcf11c6e3647),CNST_LIMB(0x4af7d1191966b3e0),CNST_LIMB(0x38ebd581ce6f80c6),CNST_LIMB(0x14ebbbc9200a6d59)},782,5}, + {CNST_LIMB(0x4ca8ed991d8b9),{CNST_LIMB(0xab7251b581f8c74d),13,CNST_LIMB(0x1639351769382),CNST_LIMB(0x3145f1b0a8e59),CNST_LIMB(0xff20704d1793),CNST_LIMB(0x1cd9e54d284e),CNST_LIMB(0x1602f3ac7db9c)},787,4}, + {CNST_LIMB(0x74b13dc12b016dc1),{CNST_LIMB(0x18ce87a5c4d39e85),1,CNST_LIMB(0x169d847da9fd247e),CNST_LIMB(0x286e093dede24bb5),CNST_LIMB(0x1854fa948ad9109d),CNST_LIMB(0x6b81a8b81781577c),CNST_LIMB(0xad44a3d15bc6be5)},791,5}, + {CNST_LIMB(0x78b0c5ae997e31ef),{CNST_LIMB(0xf811cf8a4bb1f80),1,CNST_LIMB(0xe9e74a2cd039c22),CNST_LIMB(0x30a04d242d0dfd11),CNST_LIMB(0x128fe81eea336414),CNST_LIMB(0x3639736d1defa144),CNST_LIMB(0x5eeb71b0497f58ff)},796,5}, + {CNST_LIMB(0x7dcf3e856f4612d7),{CNST_LIMB(0x47509bc7743383b),1,CNST_LIMB(0x46182f52173da52),CNST_LIMB(0x430e9fd64eeb40e6),CNST_LIMB(0x2774902fd5f53d5b),CNST_LIMB(0x4f5c0d7033943d05),CNST_LIMB(0x3be559075217f3a8)},801,5}, + {CNST_LIMB(0x550e24ca1a54b),{CNST_LIMB(0x81416693b884d74c),13,CNST_LIMB(0xee45b7c01c48),CNST_LIMB(0x3848946d8aec8),CNST_LIMB(0x541aec862a3ac),CNST_LIMB(0x4f2e818315dbc),CNST_LIMB(0xa8197f5fb2b)},806,4}, + {CNST_LIMB(0x573c8f376a18d),{CNST_LIMB(0x779f50fc3a19a6c9),13,CNST_LIMB(0x4fc81955d5129),CNST_LIMB(0xe80abe2896a1),CNST_LIMB(0x3a505801c159e),CNST_LIMB(0x162eeea75d4cd),CNST_LIMB(0x20dd0efbe8570)},810,4}, + {CNST_LIMB(0x589c3c614e917),{CNST_LIMB(0x71cc8c064f8788ee),13,CNST_LIMB(0x325d12375f7e1),CNST_LIMB(0x514f8f320e7d3),CNST_LIMB(0x55cf104cf51d3),CNST_LIMB(0x23278b29858c6),CNST_LIMB(0x3b956eecbdd30)},814,4}, + {CNST_LIMB(0x5a494bafe993d),{CNST_LIMB(0x6aef2ee9b04422dc),13,CNST_LIMB(0x5111950929bd7),CNST_LIMB(0x2c3779cd17b37),CNST_LIMB(0x2b7f886fc6966),CNST_LIMB(0x4f0b47ffa902d),CNST_LIMB(0x10bd268a51d6c)},818,4}, + {CNST_LIMB(0x5bdea84b0b73f),{CNST_LIMB(0x64adca063056bccb),13,CNST_LIMB(0x427b265a68455),CNST_LIMB(0x2ef4f15ac34a6),CNST_LIMB(0x493c4fd89b0ce),CNST_LIMB(0x7e61acb14b3a),CNST_LIMB(0x20d0328207c83)},822,4}, + {CNST_LIMB(0x5d4c55a25a945),{CNST_LIMB(0x5f37ce4e679bb0c3),13,CNST_LIMB(0x5b08caebb5502),CNST_LIMB(0x3d0eab29a51f1),CNST_LIMB(0x3c9ac2f5a187d),CNST_LIMB(0x29304bdf75a79),CNST_LIMB(0x14d681f7ea1f0)},826,4}, + {CNST_LIMB(0x5f286a042b527),{CNST_LIMB(0x585aa50035c6eb19),13,CNST_LIMB(0x1f74be8b4aa53),CNST_LIMB(0x47290f02b2679),CNST_LIMB(0x44c4bd1ee1378),CNST_LIMB(0x51286cbc40de1),CNST_LIMB(0xc379e189a860)},830,4}, + {CNST_LIMB(0x62521adc68615),{CNST_LIMB(0x4d46d1e25221a4ef),13,CNST_LIMB(0x53d112a3ea538),CNST_LIMB(0x26e6ad330e6d8),CNST_LIMB(0x56830d4191021),CNST_LIMB(0xed06536bee19),CNST_LIMB(0x5ba5998aa1cbd)},834,4}, + {CNST_LIMB(0x64f0108522a4b),{CNST_LIMB(0x44a2bea99b1fe52b),13,CNST_LIMB(0x22a1a59e3d4a4),CNST_LIMB(0x55422d57d71a4),CNST_LIMB(0x48b99527500ba),CNST_LIMB(0x5dffbfb3a890f),CNST_LIMB(0x618de61d17b82)},838,4}, + {CNST_LIMB(0x684eced8d04ad),{CNST_LIMB(0x3a25a4304e45cd70),13,CNST_LIMB(0x498e06ad4670c),CNST_LIMB(0x6397605c9b1d3),CNST_LIMB(0x1107048baaf16),CNST_LIMB(0x6292ac8aeb164),CNST_LIMB(0x4def8ba3a7552)},842,4}, + {CNST_LIMB(0x69e938da0b6b9),{CNST_LIMB(0x35644b98f3e9b802),13,CNST_LIMB(0x38dd6fce5c5b4),CNST_LIMB(0x6307e2db6000d),CNST_LIMB(0x56835d316819f),CNST_LIMB(0x2b1da7eb24a08),CNST_LIMB(0xf110b6d6a913)},846,4}, + {CNST_LIMB(0x6bf4be42947af),{CNST_LIMB(0x2f87eee6ccd631e7),13,CNST_LIMB(0x6b0e021f080f0),CNST_LIMB(0x4b469e0f2c53a),CNST_LIMB(0x50664c269b5e3),CNST_LIMB(0x4139b73b961d6),CNST_LIMB(0x13dc91bdbee0f)},850,4}, + {CNST_LIMB(0x6f54dbd6ccf57),{CNST_LIMB(0x26540878c92cd039),13,CNST_LIMB(0x382053afc295a),CNST_LIMB(0x2c8c19e89353d),CNST_LIMB(0x534384d9aa927),CNST_LIMB(0x249d03e328fc1),CNST_LIMB(0x2c57702938274)},854,4}, + {CNST_LIMB(0x71632fdcf6c15),{CNST_LIMB(0x20fdcdbf333d83af),13,CNST_LIMB(0x5242218aef575),CNST_LIMB(0x9ab7cecd8cd3),CNST_LIMB(0x4ea4e8bc18b4d),CNST_LIMB(0x16d9320fd98f4),CNST_LIMB(0x2d2b50a730c10)},858,4}, + {CNST_LIMB(0x7317fb257e1e1),{CNST_LIMB(0x1cb50c1361edfd6e),13,CNST_LIMB(0x489cb7c9fe32a),CNST_LIMB(0x258cf78a73422),CNST_LIMB(0x560fbee8c2cf2),CNST_LIMB(0x467156be8e294),CNST_LIMB(0xc593edc4d71f)},862,4}, + {CNST_LIMB(0x75e5d5c5e4577),{CNST_LIMB(0x15ef86e1cee16113),13,CNST_LIMB(0x6eece492ce925),CNST_LIMB(0x561b9134c02bf),CNST_LIMB(0x596b2a81ab56d),CNST_LIMB(0x296835004dd20),CNST_LIMB(0x3160915ef8c65)},866,4}, + {CNST_LIMB(0x788a813bc2fb1),{CNST_LIMB(0xfd74e4e944c107b),13,CNST_LIMB(0x6e15178139c26),CNST_LIMB(0x7828db84f90d2),CNST_LIMB(0x3e1e0cdc0bb1c),CNST_LIMB(0x4bbcd0685b013),CNST_LIMB(0x60b28bb37de31)},870,4}, + {CNST_LIMB(0x7b02c02e67beb),{CNST_LIMB(0xa621b97c2ae6cdb),13,CNST_LIMB(0x2068f6d99eb3c),CNST_LIMB(0x4ba3bacf8ed2f),CNST_LIMB(0x79baf6516f06a),CNST_LIMB(0x34fac2ffdfb3b),CNST_LIMB(0x601bda55ddca3)},874,4}, + {CNST_LIMB(0x7d0b0166731df),{CNST_LIMB(0x60dcab2ebe68654),13,CNST_LIMB(0x5a87235f786e1),CNST_LIMB(0x498c71a4f2c04),CNST_LIMB(0x6c4cf93aac90f),CNST_LIMB(0x2fc43a717ef2e),CNST_LIMB(0x61100c40f26dc)},878,4}, + {CNST_LIMB(0x7f65827009e4b),{CNST_LIMB(0x13671d16472022c),13,CNST_LIMB(0x66a0a221f20de),CNST_LIMB(0x1863cc32757a5),CNST_LIMB(0x72205d2b707de),CNST_LIMB(0x41eb3856479f4),CNST_LIMB(0x62a869dadecf2)},882,4}, + {CNST_LIMB(0x826267aca5d6b),{CNST_LIMB(0xf6a307f100c87643),12,CNST_LIMB(0x18b32a6e55cb2),CNST_LIMB(0x800c79d089746),CNST_LIMB(0x4df069eb6014f),CNST_LIMB(0xa67afd1d0f6b),CNST_LIMB(0x39654bc96e516)},886,4}, + {CNST_LIMB(0x854fadbb02f0d),{CNST_LIMB(0xeb99f80c181c04d8),12,CNST_LIMB(0x530f8982a799b),CNST_LIMB(0x488a5468d8f30),CNST_LIMB(0xcb498b28c81),CNST_LIMB(0x1d791c8466f6a),CNST_LIMB(0x583d384518de9)},890,4}, + {CNST_LIMB(0x86f75f67e5373),{CNST_LIMB(0xe592b4846fa38885),12,CNST_LIMB(0x16d1a804d8305),CNST_LIMB(0x3a9f7db1defba),CNST_LIMB(0x53fa43529d63d),CNST_LIMB(0x380980122856a),CNST_LIMB(0x59320408536cb)},894,4}, + {CNST_LIMB(0x89110415e014b),{CNST_LIMB(0xde220b6a3ca63611),12,CNST_LIMB(0x1183ea4dd5cca),CNST_LIMB(0x6cd0a51299316),CNST_LIMB(0x2c53d4f8b0ee6),CNST_LIMB(0x39ef54aed56eb),CNST_LIMB(0x7f71b2a9bf0fd)},898,4}, + {CNST_LIMB(0x8bbeefef93d97),{CNST_LIMB(0xd4f7338df110e1c1),12,CNST_LIMB(0x3ee5d151be367),CNST_LIMB(0x2e6b9dfc4bbcb),CNST_LIMB(0x225349b2e386e),CNST_LIMB(0x492ce15456b18),CNST_LIMB(0x856a0d6e68759)},902,4}, + {CNST_LIMB(0x8fa29248f38e9),{CNST_LIMB(0xc84479a2d3ad73b2),12,CNST_LIMB(0x282c97bed2bdc),CNST_LIMB(0x86b44220fa8e0),CNST_LIMB(0x497c548d39ada),CNST_LIMB(0x6928a8433805d),CNST_LIMB(0x1d2f77b091c29)},906,4}, + {CNST_LIMB(0x9311da8eb3ea1),{CNST_LIMB(0xbd9c9989aacc578d),12,CNST_LIMB(0x73d0b00fcee87),CNST_LIMB(0x44acd3ec00c9b),CNST_LIMB(0x3b8ead35b82f4),CNST_LIMB(0x7a1ca1fa55a8c),CNST_LIMB(0x98634149273d)},910,4}, + {CNST_LIMB(0x96fc1b51999b5),{CNST_LIMB(0xb20e950936df3d71),12,CNST_LIMB(0x899afa996b260),CNST_LIMB(0x2d7d06dae3233),CNST_LIMB(0x143e323027e28),CNST_LIMB(0x8483b9a26498e),CNST_LIMB(0x689b7b1e2fc91)},914,4}, + {CNST_LIMB(0x99d2dc5aa820b),{CNST_LIMB(0xaa0bd71d4333c056),12,CNST_LIMB(0x71d5124399b20),CNST_LIMB(0x62e94421a897f),CNST_LIMB(0x892c96c6ff4dc),CNST_LIMB(0x54dc6420d0ec4),CNST_LIMB(0x43a10331ebf4f)},918,4}, + {CNST_LIMB(0x9c18c1a21f755),{CNST_LIMB(0xa3d7a1305040e509),12,CNST_LIMB(0x4a6f652c96ebf),CNST_LIMB(0x92a1dbc9a1bc4),CNST_LIMB(0x7856fe0adb2e7),CNST_LIMB(0x65020d02f02aa),CNST_LIMB(0x7983e2f6dcbd)},922,4}, + {CNST_LIMB(0xa019a0d84ce05),{CNST_LIMB(0x99580856e1c2e36b),12,CNST_LIMB(0x5060429959a17),CNST_LIMB(0x8af3dd6c8fedb),CNST_LIMB(0x8521b97cefc72),CNST_LIMB(0x7289dc3848291),CNST_LIMB(0x51cb410c11cef)},926,4}, + {CNST_LIMB(0xa3837104af50b),{CNST_LIMB(0x90cc816ca127f31c),12,CNST_LIMB(0x7fcd3ea8e707c),CNST_LIMB(0x1ea9bdca73534),CNST_LIMB(0x3d0d37ad79bcf),CNST_LIMB(0x78befa2ea5ef8),CNST_LIMB(0x8c7846571c14b)},930,4}, + {CNST_LIMB(0xa74ba276e925b),{CNST_LIMB(0x87bcf3ca6aa1f420),12,CNST_LIMB(0x876dcb0272647),CNST_LIMB(0x63761f150b253),CNST_LIMB(0xa347a550c386b),CNST_LIMB(0xb7438cfe5ad4),CNST_LIMB(0x7bca2b8c0aabf)},934,4}, + {CNST_LIMB(0xad0c05b3ae661),{CNST_LIMB(0x7ab7cf1782b58dcf),12,CNST_LIMB(0x54750c4f56635),CNST_LIMB(0x2eac67167559c),CNST_LIMB(0x563c222f2aff7),CNST_LIMB(0x7b738313b7ac1),CNST_LIMB(0x65d997bccd9d9)},938,4}, + {CNST_LIMB(0xb0da5211cc3e7),{CNST_LIMB(0x72916ab867f7595c),12,CNST_LIMB(0xfa941ccadf01),CNST_LIMB(0x8d756d36295ea),CNST_LIMB(0x4f9f479e132fd),CNST_LIMB(0x18526df562fde),CNST_LIMB(0x434f07e1d9d33)},942,4}, + {CNST_LIMB(0xb36ca8c3991af),{CNST_LIMB(0x6d41bd767e129ba0),12,CNST_LIMB(0x13836edce5114),CNST_LIMB(0xa52c71bc138ab),CNST_LIMB(0x339d5f264e899),CNST_LIMB(0x65473fc2cfa57),CNST_LIMB(0x4714fd9da5ac0)},946,4}, + {CNST_LIMB(0xb6694790c60df),{CNST_LIMB(0x6746add17a9a2fee),12,CNST_LIMB(0x4c2521610f0f4),CNST_LIMB(0x1ef55755cab96),CNST_LIMB(0x3bb413c494cbb),CNST_LIMB(0x59bedca68abba),CNST_LIMB(0x618c95ba5598b)},950,4}, + {CNST_LIMB(0xb89a345c48d7d),{CNST_LIMB(0x6302ff6c309d06ee),12,CNST_LIMB(0x2296406fcba90),CNST_LIMB(0x4d697f4e83909),CNST_LIMB(0xa16067eedb775),CNST_LIMB(0xa50f824607f2b),CNST_LIMB(0x3d3946b54c9f9)},954,4}, + {CNST_LIMB(0xbb02a8b8a132b),{CNST_LIMB(0x5e70bfded3b337fc),12,CNST_LIMB(0x8c29c2d62d33),CNST_LIMB(0x3f082e296ef8f),CNST_LIMB(0x49afe57a19b90),CNST_LIMB(0xb7bd5be58da15),CNST_LIMB(0x8de61bd7e627f)},958,4}, + {CNST_LIMB(0xbd6468bb171ff),{CNST_LIMB(0x5a0880d51b052fd7),12,CNST_LIMB(0x64a7322bed5a0),CNST_LIMB(0x3f94ed2b89267),CNST_LIMB(0x980b9bde44b2d),CNST_LIMB(0x4a6676c0e7d13),CNST_LIMB(0xb24baad1f0c40)},962,4}, + {CNST_LIMB(0xc17671b548641),{CNST_LIMB(0x52c0b00a813a011e),12,CNST_LIMB(0x85095e7597d4),CNST_LIMB(0x55524352a702c),CNST_LIMB(0x868164742fab5),CNST_LIMB(0x3b3bcfdffb2cf),CNST_LIMB(0xab11b067d542f)},966,4}, + {CNST_LIMB(0xc57f07d496e1b),{CNST_LIMB(0x4bd58ed22f4b2aac),12,CNST_LIMB(0x449a9c42f9a11),CNST_LIMB(0x2b9c2279a88de),CNST_LIMB(0xa905cf41733e1),CNST_LIMB(0x206b2bfa8b896),CNST_LIMB(0xb378d16c66efd)},970,4}, + {CNST_LIMB(0xc814b88200ac3),{CNST_LIMB(0x478c251716699c98),12,CNST_LIMB(0x97df5b023b898),CNST_LIMB(0x5507d796eedc1),CNST_LIMB(0xb4a34312d58e3),CNST_LIMB(0x4324fc6d4f6f2),CNST_LIMB(0x29d3a7f3d88da)},974,4}, + {CNST_LIMB(0xcb958ba8e9259),{CNST_LIMB(0x41e93d5390ce4a3c),12,CNST_LIMB(0x75906ffdbe592),CNST_LIMB(0x35d1e8b619b02),CNST_LIMB(0x5535c122a3ba7),CNST_LIMB(0xb2c9d287f29c8),CNST_LIMB(0x7f9a7f1adf9d9)},978,4}, + {CNST_LIMB(0xcfaa956d67517),{CNST_LIMB(0x3b9549c76b39f2a8),12,CNST_LIMB(0x44a2e5454ad61),CNST_LIMB(0xa8d0541bab05b),CNST_LIMB(0x801e8693083d4),CNST_LIMB(0xc17c6af57bddf),CNST_LIMB(0xc7b4d9a0870d9)},982,4}, + {CNST_LIMB(0xd56380a0e8273),{CNST_LIMB(0x331ecd3feca3d608),12,CNST_LIMB(0xc5686ff8a7efd),CNST_LIMB(0x61e35c54a4f3f),CNST_LIMB(0x4bf5dc73ede0f),CNST_LIMB(0x2bf7f029f09a5),CNST_LIMB(0x718dc3463c882)},986,4}, + {CNST_LIMB(0xd9c8b65d94f5b),{CNST_LIMB(0x2cec062e71d179c4),12,CNST_LIMB(0xa3aaac38dbec6),CNST_LIMB(0x78cabf09fa56c),CNST_LIMB(0xcaf0fccc6b30b),CNST_LIMB(0xce30344eb1fac),CNST_LIMB(0x4ba46e5575b11)},990,4}, + {CNST_LIMB(0xdc90a482debcb),{CNST_LIMB(0x2920b89d6fc02e7f),12,CNST_LIMB(0x9f0f9b3b403a),CNST_LIMB(0x619327b332542),CNST_LIMB(0xa75eae1f8ff9f),CNST_LIMB(0x62350a1cba491),CNST_LIMB(0x22ac2e8eb19f9)},994,4}, + {CNST_LIMB(0xe0ac9922e6235),{CNST_LIMB(0x23b187206556b5c4),12,CNST_LIMB(0x157440c67a3c9),CNST_LIMB(0x696b5be3cc464),CNST_LIMB(0x2ebcde890e790),CNST_LIMB(0xae767f93832de),CNST_LIMB(0xcb1eade2d80a8)},998,4} +#endif diff --git a/examples/multiprecision/mini-gmp/mini-gmp.c b/examples/multiprecision/mini-gmp/mini-gmp.c new file mode 100644 index 0000000000000000000000000000000000000000..04bed3f51ddbcce15d2ee1765fc5e3bc1b5b2fb1 --- /dev/null +++ b/examples/multiprecision/mini-gmp/mini-gmp.c @@ -0,0 +1,4412 @@ +/* mini-gmp, a minimalistic implementation of a GNU GMP subset. + + Contributed to the GNU project by Niels Möller + +Copyright 1991-1997, 1999-2016 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + +or + + * the GNU General Public License as published by the Free Software + Foundation; either version 2 of the License, or (at your option) any + later version. + +or both in parallel, as here. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received copies of the GNU General Public License and the +GNU Lesser General Public License along with the GNU MP Library. If not, +see https://www.gnu.org/licenses/. */ + +/* NOTE: All functions in this file which are not declared in + mini-gmp.h are internal, and are not intended to be compatible + neither with GMP nor with future versions of mini-gmp. */ + +/* Much of the material copied from GMP files, including: gmp-impl.h, + longlong.h, mpn/generic/add_n.c, mpn/generic/addmul_1.c, + mpn/generic/lshift.c, mpn/generic/mul_1.c, + mpn/generic/mul_basecase.c, mpn/generic/rshift.c, + mpn/generic/sbpi1_div_qr.c, mpn/generic/sub_n.c, + mpn/generic/submul_1.c. */ + +#include <assert.h> +#include <ctype.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "mini-gmp.h" + + +/* Macros */ +#define GMP_LIMB_BITS (sizeof(mp_limb_t) * CHAR_BIT) + +#define GMP_LIMB_MAX (~ (mp_limb_t) 0) +#define GMP_LIMB_HIGHBIT ((mp_limb_t) 1 << (GMP_LIMB_BITS - 1)) + +#define GMP_HLIMB_BIT ((mp_limb_t) 1 << (GMP_LIMB_BITS / 2)) +#define GMP_LLIMB_MASK (GMP_HLIMB_BIT - 1) + +#define GMP_ULONG_BITS (sizeof(unsigned long) * CHAR_BIT) +#define GMP_ULONG_HIGHBIT ((unsigned long) 1 << (GMP_ULONG_BITS - 1)) + +#define GMP_ABS(x) ((x) >= 0 ? (x) : -(x)) +#define GMP_NEG_CAST(T,x) (-((T)((x) + 1) - 1)) + +#define GMP_MIN(a, b) ((a) < (b) ? (a) : (b)) +#define GMP_MAX(a, b) ((a) > (b) ? (a) : (b)) + +#define GMP_CMP(a,b) (((a) > (b)) - ((a) < (b))) + +#define gmp_assert_nocarry(x) do { \ + mp_limb_t __cy = (x); \ + assert (__cy == 0); \ + } while (0) + +#define gmp_clz(count, x) do { \ + mp_limb_t __clz_x = (x); \ + unsigned __clz_c; \ + for (__clz_c = 0; \ + (__clz_x & ((mp_limb_t) 0xff << (GMP_LIMB_BITS - 8))) == 0; \ + __clz_c += 8) \ + __clz_x <<= 8; \ + for (; (__clz_x & GMP_LIMB_HIGHBIT) == 0; __clz_c++) \ + __clz_x <<= 1; \ + (count) = __clz_c; \ + } while (0) + +#define gmp_ctz(count, x) do { \ + mp_limb_t __ctz_x = (x); \ + unsigned __ctz_c = 0; \ + gmp_clz (__ctz_c, __ctz_x & - __ctz_x); \ + (count) = GMP_LIMB_BITS - 1 - __ctz_c; \ + } while (0) + +#define gmp_add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + mp_limb_t __x; \ + __x = (al) + (bl); \ + (sh) = (ah) + (bh) + (__x < (al)); \ + (sl) = __x; \ + } while (0) + +#define gmp_sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + mp_limb_t __x; \ + __x = (al) - (bl); \ + (sh) = (ah) - (bh) - ((al) < (bl)); \ + (sl) = __x; \ + } while (0) + +#define gmp_umul_ppmm(w1, w0, u, v) \ + do { \ + mp_limb_t __x0, __x1, __x2, __x3; \ + unsigned __ul, __vl, __uh, __vh; \ + mp_limb_t __u = (u), __v = (v); \ + \ + __ul = __u & GMP_LLIMB_MASK; \ + __uh = __u >> (GMP_LIMB_BITS / 2); \ + __vl = __v & GMP_LLIMB_MASK; \ + __vh = __v >> (GMP_LIMB_BITS / 2); \ + \ + __x0 = (mp_limb_t) __ul * __vl; \ + __x1 = (mp_limb_t) __ul * __vh; \ + __x2 = (mp_limb_t) __uh * __vl; \ + __x3 = (mp_limb_t) __uh * __vh; \ + \ + __x1 += __x0 >> (GMP_LIMB_BITS / 2);/* this can't give carry */ \ + __x1 += __x2; /* but this indeed can */ \ + if (__x1 < __x2) /* did we get it? */ \ + __x3 += GMP_HLIMB_BIT; /* yes, add it in the proper pos. */ \ + \ + (w1) = __x3 + (__x1 >> (GMP_LIMB_BITS / 2)); \ + (w0) = (__x1 << (GMP_LIMB_BITS / 2)) + (__x0 & GMP_LLIMB_MASK); \ + } while (0) + +#define gmp_udiv_qrnnd_preinv(q, r, nh, nl, d, di) \ + do { \ + mp_limb_t _qh, _ql, _r, _mask; \ + gmp_umul_ppmm (_qh, _ql, (nh), (di)); \ + gmp_add_ssaaaa (_qh, _ql, _qh, _ql, (nh) + 1, (nl)); \ + _r = (nl) - _qh * (d); \ + _mask = -(mp_limb_t) (_r > _ql); /* both > and >= are OK */ \ + _qh += _mask; \ + _r += _mask & (d); \ + if (_r >= (d)) \ + { \ + _r -= (d); \ + _qh++; \ + } \ + \ + (r) = _r; \ + (q) = _qh; \ + } while (0) + +#define gmp_udiv_qr_3by2(q, r1, r0, n2, n1, n0, d1, d0, dinv) \ + do { \ + mp_limb_t _q0, _t1, _t0, _mask; \ + gmp_umul_ppmm ((q), _q0, (n2), (dinv)); \ + gmp_add_ssaaaa ((q), _q0, (q), _q0, (n2), (n1)); \ + \ + /* Compute the two most significant limbs of n - q'd */ \ + (r1) = (n1) - (d1) * (q); \ + gmp_sub_ddmmss ((r1), (r0), (r1), (n0), (d1), (d0)); \ + gmp_umul_ppmm (_t1, _t0, (d0), (q)); \ + gmp_sub_ddmmss ((r1), (r0), (r1), (r0), _t1, _t0); \ + (q)++; \ + \ + /* Conditionally adjust q and the remainders */ \ + _mask = - (mp_limb_t) ((r1) >= _q0); \ + (q) += _mask; \ + gmp_add_ssaaaa ((r1), (r0), (r1), (r0), _mask & (d1), _mask & (d0)); \ + if ((r1) >= (d1)) \ + { \ + if ((r1) > (d1) || (r0) >= (d0)) \ + { \ + (q)++; \ + gmp_sub_ddmmss ((r1), (r0), (r1), (r0), (d1), (d0)); \ + } \ + } \ + } while (0) + +/* Swap macros. */ +#define MP_LIMB_T_SWAP(x, y) \ + do { \ + mp_limb_t __mp_limb_t_swap__tmp = (x); \ + (x) = (y); \ + (y) = __mp_limb_t_swap__tmp; \ + } while (0) +#define MP_SIZE_T_SWAP(x, y) \ + do { \ + mp_size_t __mp_size_t_swap__tmp = (x); \ + (x) = (y); \ + (y) = __mp_size_t_swap__tmp; \ + } while (0) +#define MP_BITCNT_T_SWAP(x,y) \ + do { \ + mp_bitcnt_t __mp_bitcnt_t_swap__tmp = (x); \ + (x) = (y); \ + (y) = __mp_bitcnt_t_swap__tmp; \ + } while (0) +#define MP_PTR_SWAP(x, y) \ + do { \ + mp_ptr __mp_ptr_swap__tmp = (x); \ + (x) = (y); \ + (y) = __mp_ptr_swap__tmp; \ + } while (0) +#define MP_SRCPTR_SWAP(x, y) \ + do { \ + mp_srcptr __mp_srcptr_swap__tmp = (x); \ + (x) = (y); \ + (y) = __mp_srcptr_swap__tmp; \ + } while (0) + +#define MPN_PTR_SWAP(xp,xs, yp,ys) \ + do { \ + MP_PTR_SWAP (xp, yp); \ + MP_SIZE_T_SWAP (xs, ys); \ + } while(0) +#define MPN_SRCPTR_SWAP(xp,xs, yp,ys) \ + do { \ + MP_SRCPTR_SWAP (xp, yp); \ + MP_SIZE_T_SWAP (xs, ys); \ + } while(0) + +#define MPZ_PTR_SWAP(x, y) \ + do { \ + mpz_ptr __mpz_ptr_swap__tmp = (x); \ + (x) = (y); \ + (y) = __mpz_ptr_swap__tmp; \ + } while (0) +#define MPZ_SRCPTR_SWAP(x, y) \ + do { \ + mpz_srcptr __mpz_srcptr_swap__tmp = (x); \ + (x) = (y); \ + (y) = __mpz_srcptr_swap__tmp; \ + } while (0) + +const int mp_bits_per_limb = GMP_LIMB_BITS; + + +/* Memory allocation and other helper functions. */ +static void +gmp_die (const char *msg) +{ + fprintf (stderr, "%s\n", msg); + abort(); +} + +static void * +gmp_default_alloc (size_t size) +{ + void *p; + + assert (size > 0); + + p = malloc (size); + if (!p) + gmp_die("gmp_default_alloc: Virtual memory exhausted."); + + return p; +} + +static void * +gmp_default_realloc (void *old, size_t old_size, size_t new_size) +{ + void * p; + + p = realloc (old, new_size); + + if (!p) + gmp_die("gmp_default_realloc: Virtual memory exhausted."); + + return p; +} + +static void +gmp_default_free (void *p, size_t size) +{ + free (p); +} + +static void * (*gmp_allocate_func) (size_t) = gmp_default_alloc; +static void * (*gmp_reallocate_func) (void *, size_t, size_t) = gmp_default_realloc; +static void (*gmp_free_func) (void *, size_t) = gmp_default_free; + +void +mp_get_memory_functions (void *(**alloc_func) (size_t), + void *(**realloc_func) (void *, size_t, size_t), + void (**free_func) (void *, size_t)) +{ + if (alloc_func) + *alloc_func = gmp_allocate_func; + + if (realloc_func) + *realloc_func = gmp_reallocate_func; + + if (free_func) + *free_func = gmp_free_func; +} + +void +mp_set_memory_functions (void *(*alloc_func) (size_t), + void *(*realloc_func) (void *, size_t, size_t), + void (*free_func) (void *, size_t)) +{ + if (!alloc_func) + alloc_func = gmp_default_alloc; + if (!realloc_func) + realloc_func = gmp_default_realloc; + if (!free_func) + free_func = gmp_default_free; + + gmp_allocate_func = alloc_func; + gmp_reallocate_func = realloc_func; + gmp_free_func = free_func; +} + +#define gmp_xalloc(size) ((*gmp_allocate_func)((size))) +#define gmp_free(p) ((*gmp_free_func) ((p), 0)) + +static mp_ptr +gmp_xalloc_limbs (mp_size_t size) +{ + return (mp_ptr) gmp_xalloc (size * sizeof (mp_limb_t)); +} + +static mp_ptr +gmp_xrealloc_limbs (mp_ptr old, mp_size_t size) +{ + assert (size > 0); + return (mp_ptr) (*gmp_reallocate_func) (old, 0, size * sizeof (mp_limb_t)); +} + + +/* MPN interface */ + +void +mpn_copyi (mp_ptr d, mp_srcptr s, mp_size_t n) +{ + mp_size_t i; + for (i = 0; i < n; i++) + d[i] = s[i]; +} + +void +mpn_copyd (mp_ptr d, mp_srcptr s, mp_size_t n) +{ + while (--n >= 0) + d[n] = s[n]; +} + +int +mpn_cmp (mp_srcptr ap, mp_srcptr bp, mp_size_t n) +{ + while (--n >= 0) + { + if (ap[n] != bp[n]) + return ap[n] > bp[n] ? 1 : -1; + } + return 0; +} + +static int +mpn_cmp4 (mp_srcptr ap, mp_size_t an, mp_srcptr bp, mp_size_t bn) +{ + if (an != bn) + return an < bn ? -1 : 1; + else + return mpn_cmp (ap, bp, an); +} + +static mp_size_t +mpn_normalized_size (mp_srcptr xp, mp_size_t n) +{ + while (n > 0 && xp[n-1] == 0) + --n; + return n; +} + +int +mpn_zero_p(mp_srcptr rp, mp_size_t n) +{ + return mpn_normalized_size (rp, n) == 0; +} + +void +mpn_zero (mp_ptr rp, mp_size_t n) +{ + while (--n >= 0) + rp[n] = 0; +} + +mp_limb_t +mpn_add_1 (mp_ptr rp, mp_srcptr ap, mp_size_t n, mp_limb_t b) +{ + mp_size_t i; + + assert (n > 0); + i = 0; + do + { + mp_limb_t r = ap[i] + b; + /* Carry out */ + b = (r < b); + rp[i] = r; + } + while (++i < n); + + return b; +} + +mp_limb_t +mpn_add_n (mp_ptr rp, mp_srcptr ap, mp_srcptr bp, mp_size_t n) +{ + mp_size_t i; + mp_limb_t cy; + + for (i = 0, cy = 0; i < n; i++) + { + mp_limb_t a, b, r; + a = ap[i]; b = bp[i]; + r = a + cy; + cy = (r < cy); + r += b; + cy += (r < b); + rp[i] = r; + } + return cy; +} + +mp_limb_t +mpn_add (mp_ptr rp, mp_srcptr ap, mp_size_t an, mp_srcptr bp, mp_size_t bn) +{ + mp_limb_t cy; + + assert (an >= bn); + + cy = mpn_add_n (rp, ap, bp, bn); + if (an > bn) + cy = mpn_add_1 (rp + bn, ap + bn, an - bn, cy); + return cy; +} + +mp_limb_t +mpn_sub_1 (mp_ptr rp, mp_srcptr ap, mp_size_t n, mp_limb_t b) +{ + mp_size_t i; + + assert (n > 0); + + i = 0; + do + { + mp_limb_t a = ap[i]; + /* Carry out */ + mp_limb_t cy = a < b; + rp[i] = a - b; + b = cy; + } + while (++i < n); + + return b; +} + +mp_limb_t +mpn_sub_n (mp_ptr rp, mp_srcptr ap, mp_srcptr bp, mp_size_t n) +{ + mp_size_t i; + mp_limb_t cy; + + for (i = 0, cy = 0; i < n; i++) + { + mp_limb_t a, b; + a = ap[i]; b = bp[i]; + b += cy; + cy = (b < cy); + cy += (a < b); + rp[i] = a - b; + } + return cy; +} + +mp_limb_t +mpn_sub (mp_ptr rp, mp_srcptr ap, mp_size_t an, mp_srcptr bp, mp_size_t bn) +{ + mp_limb_t cy; + + assert (an >= bn); + + cy = mpn_sub_n (rp, ap, bp, bn); + if (an > bn) + cy = mpn_sub_1 (rp + bn, ap + bn, an - bn, cy); + return cy; +} + +mp_limb_t +mpn_mul_1 (mp_ptr rp, mp_srcptr up, mp_size_t n, mp_limb_t vl) +{ + mp_limb_t ul, cl, hpl, lpl; + + assert (n >= 1); + + cl = 0; + do + { + ul = *up++; + gmp_umul_ppmm (hpl, lpl, ul, vl); + + lpl += cl; + cl = (lpl < cl) + hpl; + + *rp++ = lpl; + } + while (--n != 0); + + return cl; +} + +mp_limb_t +mpn_addmul_1 (mp_ptr rp, mp_srcptr up, mp_size_t n, mp_limb_t vl) +{ + mp_limb_t ul, cl, hpl, lpl, rl; + + assert (n >= 1); + + cl = 0; + do + { + ul = *up++; + gmp_umul_ppmm (hpl, lpl, ul, vl); + + lpl += cl; + cl = (lpl < cl) + hpl; + + rl = *rp; + lpl = rl + lpl; + cl += lpl < rl; + *rp++ = lpl; + } + while (--n != 0); + + return cl; +} + +mp_limb_t +mpn_submul_1 (mp_ptr rp, mp_srcptr up, mp_size_t n, mp_limb_t vl) +{ + mp_limb_t ul, cl, hpl, lpl, rl; + + assert (n >= 1); + + cl = 0; + do + { + ul = *up++; + gmp_umul_ppmm (hpl, lpl, ul, vl); + + lpl += cl; + cl = (lpl < cl) + hpl; + + rl = *rp; + lpl = rl - lpl; + cl += lpl > rl; + *rp++ = lpl; + } + while (--n != 0); + + return cl; +} + +mp_limb_t +mpn_mul (mp_ptr rp, mp_srcptr up, mp_size_t un, mp_srcptr vp, mp_size_t vn) +{ + assert (un >= vn); + assert (vn >= 1); + + /* We first multiply by the low order limb. This result can be + stored, not added, to rp. We also avoid a loop for zeroing this + way. */ + + rp[un] = mpn_mul_1 (rp, up, un, vp[0]); + + /* Now accumulate the product of up[] and the next higher limb from + vp[]. */ + + while (--vn >= 1) + { + rp += 1, vp += 1; + rp[un] = mpn_addmul_1 (rp, up, un, vp[0]); + } + return rp[un]; +} + +void +mpn_mul_n (mp_ptr rp, mp_srcptr ap, mp_srcptr bp, mp_size_t n) +{ + mpn_mul (rp, ap, n, bp, n); +} + +void +mpn_sqr (mp_ptr rp, mp_srcptr ap, mp_size_t n) +{ + mpn_mul (rp, ap, n, ap, n); +} + +mp_limb_t +mpn_lshift (mp_ptr rp, mp_srcptr up, mp_size_t n, unsigned int cnt) +{ + mp_limb_t high_limb, low_limb; + unsigned int tnc; + mp_limb_t retval; + + assert (n >= 1); + assert (cnt >= 1); + assert (cnt < GMP_LIMB_BITS); + + up += n; + rp += n; + + tnc = GMP_LIMB_BITS - cnt; + low_limb = *--up; + retval = low_limb >> tnc; + high_limb = (low_limb << cnt); + + while (--n != 0) + { + low_limb = *--up; + *--rp = high_limb | (low_limb >> tnc); + high_limb = (low_limb << cnt); + } + *--rp = high_limb; + + return retval; +} + +mp_limb_t +mpn_rshift (mp_ptr rp, mp_srcptr up, mp_size_t n, unsigned int cnt) +{ + mp_limb_t high_limb, low_limb; + unsigned int tnc; + mp_limb_t retval; + + assert (n >= 1); + assert (cnt >= 1); + assert (cnt < GMP_LIMB_BITS); + + tnc = GMP_LIMB_BITS - cnt; + high_limb = *up++; + retval = (high_limb << tnc); + low_limb = high_limb >> cnt; + + while (--n != 0) + { + high_limb = *up++; + *rp++ = low_limb | (high_limb << tnc); + low_limb = high_limb >> cnt; + } + *rp = low_limb; + + return retval; +} + +static mp_bitcnt_t +mpn_common_scan (mp_limb_t limb, mp_size_t i, mp_srcptr up, mp_size_t un, + mp_limb_t ux) +{ + unsigned cnt; + + assert (ux == 0 || ux == GMP_LIMB_MAX); + assert (0 <= i && i <= un ); + + while (limb == 0) + { + i++; + if (i == un) + return (ux == 0 ? ~(mp_bitcnt_t) 0 : un * GMP_LIMB_BITS); + limb = ux ^ up[i]; + } + gmp_ctz (cnt, limb); + return (mp_bitcnt_t) i * GMP_LIMB_BITS + cnt; +} + +mp_bitcnt_t +mpn_scan1 (mp_srcptr ptr, mp_bitcnt_t bit) +{ + mp_size_t i; + i = bit / GMP_LIMB_BITS; + + return mpn_common_scan ( ptr[i] & (GMP_LIMB_MAX << (bit % GMP_LIMB_BITS)), + i, ptr, i, 0); +} + +mp_bitcnt_t +mpn_scan0 (mp_srcptr ptr, mp_bitcnt_t bit) +{ + mp_size_t i; + i = bit / GMP_LIMB_BITS; + + return mpn_common_scan (~ptr[i] & (GMP_LIMB_MAX << (bit % GMP_LIMB_BITS)), + i, ptr, i, GMP_LIMB_MAX); +} + +void +mpn_com (mp_ptr rp, mp_srcptr up, mp_size_t n) +{ + while (--n >= 0) + *rp++ = ~ *up++; +} + +mp_limb_t +mpn_neg (mp_ptr rp, mp_srcptr up, mp_size_t n) +{ + while (*up == 0) + { + *rp = 0; + if (!--n) + return 0; + ++up; ++rp; + } + *rp = - *up; + mpn_com (++rp, ++up, --n); + return 1; +} + + +/* MPN division interface. */ + +/* The 3/2 inverse is defined as + + m = floor( (B^3-1) / (B u1 + u0)) - B +*/ +mp_limb_t +mpn_invert_3by2 (mp_limb_t u1, mp_limb_t u0) +{ + mp_limb_t r, p, m, ql; + unsigned ul, uh, qh; + + assert (u1 >= GMP_LIMB_HIGHBIT); + + /* For notation, let b denote the half-limb base, so that B = b^2. + Split u1 = b uh + ul. */ + ul = u1 & GMP_LLIMB_MASK; + uh = u1 >> (GMP_LIMB_BITS / 2); + + /* Approximation of the high half of quotient. Differs from the 2/1 + inverse of the half limb uh, since we have already subtracted + u0. */ + qh = ~u1 / uh; + + /* Adjust to get a half-limb 3/2 inverse, i.e., we want + + qh' = floor( (b^3 - 1) / u) - b = floor ((b^3 - b u - 1) / u + = floor( (b (~u) + b-1) / u), + + and the remainder + + r = b (~u) + b-1 - qh (b uh + ul) + = b (~u - qh uh) + b-1 - qh ul + + Subtraction of qh ul may underflow, which implies adjustments. + But by normalization, 2 u >= B > qh ul, so we need to adjust by + at most 2. + */ + + r = ((~u1 - (mp_limb_t) qh * uh) << (GMP_LIMB_BITS / 2)) | GMP_LLIMB_MASK; + + p = (mp_limb_t) qh * ul; + /* Adjustment steps taken from udiv_qrnnd_c */ + if (r < p) + { + qh--; + r += u1; + if (r >= u1) /* i.e. we didn't get carry when adding to r */ + if (r < p) + { + qh--; + r += u1; + } + } + r -= p; + + /* Low half of the quotient is + + ql = floor ( (b r + b-1) / u1). + + This is a 3/2 division (on half-limbs), for which qh is a + suitable inverse. */ + + p = (r >> (GMP_LIMB_BITS / 2)) * qh + r; + /* Unlike full-limb 3/2, we can add 1 without overflow. For this to + work, it is essential that ql is a full mp_limb_t. */ + ql = (p >> (GMP_LIMB_BITS / 2)) + 1; + + /* By the 3/2 trick, we don't need the high half limb. */ + r = (r << (GMP_LIMB_BITS / 2)) + GMP_LLIMB_MASK - ql * u1; + + if (r >= (p << (GMP_LIMB_BITS / 2))) + { + ql--; + r += u1; + } + m = ((mp_limb_t) qh << (GMP_LIMB_BITS / 2)) + ql; + if (r >= u1) + { + m++; + r -= u1; + } + + /* Now m is the 2/1 invers of u1. If u0 > 0, adjust it to become a + 3/2 inverse. */ + if (u0 > 0) + { + mp_limb_t th, tl; + r = ~r; + r += u0; + if (r < u0) + { + m--; + if (r >= u1) + { + m--; + r -= u1; + } + r -= u1; + } + gmp_umul_ppmm (th, tl, u0, m); + r += th; + if (r < th) + { + m--; + m -= ((r > u1) | ((r == u1) & (tl > u0))); + } + } + + return m; +} + +struct gmp_div_inverse +{ + /* Normalization shift count. */ + unsigned shift; + /* Normalized divisor (d0 unused for mpn_div_qr_1) */ + mp_limb_t d1, d0; + /* Inverse, for 2/1 or 3/2. */ + mp_limb_t di; +}; + +static void +mpn_div_qr_1_invert (struct gmp_div_inverse *inv, mp_limb_t d) +{ + unsigned shift; + + assert (d > 0); + gmp_clz (shift, d); + inv->shift = shift; + inv->d1 = d << shift; + inv->di = mpn_invert_limb (inv->d1); +} + +static void +mpn_div_qr_2_invert (struct gmp_div_inverse *inv, + mp_limb_t d1, mp_limb_t d0) +{ + unsigned shift; + + assert (d1 > 0); + gmp_clz (shift, d1); + inv->shift = shift; + if (shift > 0) + { + d1 = (d1 << shift) | (d0 >> (GMP_LIMB_BITS - shift)); + d0 <<= shift; + } + inv->d1 = d1; + inv->d0 = d0; + inv->di = mpn_invert_3by2 (d1, d0); +} + +static void +mpn_div_qr_invert (struct gmp_div_inverse *inv, + mp_srcptr dp, mp_size_t dn) +{ + assert (dn > 0); + + if (dn == 1) + mpn_div_qr_1_invert (inv, dp[0]); + else if (dn == 2) + mpn_div_qr_2_invert (inv, dp[1], dp[0]); + else + { + unsigned shift; + mp_limb_t d1, d0; + + d1 = dp[dn-1]; + d0 = dp[dn-2]; + assert (d1 > 0); + gmp_clz (shift, d1); + inv->shift = shift; + if (shift > 0) + { + d1 = (d1 << shift) | (d0 >> (GMP_LIMB_BITS - shift)); + d0 = (d0 << shift) | (dp[dn-3] >> (GMP_LIMB_BITS - shift)); + } + inv->d1 = d1; + inv->d0 = d0; + inv->di = mpn_invert_3by2 (d1, d0); + } +} + +/* Not matching current public gmp interface, rather corresponding to + the sbpi1_div_* functions. */ +static mp_limb_t +mpn_div_qr_1_preinv (mp_ptr qp, mp_srcptr np, mp_size_t nn, + const struct gmp_div_inverse *inv) +{ + mp_limb_t d, di; + mp_limb_t r; + mp_ptr tp = NULL; + + if (inv->shift > 0) + { + tp = gmp_xalloc_limbs (nn); + r = mpn_lshift (tp, np, nn, inv->shift); + np = tp; + } + else + r = 0; + + d = inv->d1; + di = inv->di; + while (--nn >= 0) + { + mp_limb_t q; + + gmp_udiv_qrnnd_preinv (q, r, r, np[nn], d, di); + if (qp) + qp[nn] = q; + } + if (inv->shift > 0) + gmp_free (tp); + + return r >> inv->shift; +} + +static mp_limb_t +mpn_div_qr_1 (mp_ptr qp, mp_srcptr np, mp_size_t nn, mp_limb_t d) +{ + assert (d > 0); + + /* Special case for powers of two. */ + if ((d & (d-1)) == 0) + { + mp_limb_t r = np[0] & (d-1); + if (qp) + { + if (d <= 1) + mpn_copyi (qp, np, nn); + else + { + unsigned shift; + gmp_ctz (shift, d); + mpn_rshift (qp, np, nn, shift); + } + } + return r; + } + else + { + struct gmp_div_inverse inv; + mpn_div_qr_1_invert (&inv, d); + return mpn_div_qr_1_preinv (qp, np, nn, &inv); + } +} + +static void +mpn_div_qr_2_preinv (mp_ptr qp, mp_ptr rp, mp_srcptr np, mp_size_t nn, + const struct gmp_div_inverse *inv) +{ + unsigned shift; + mp_size_t i; + mp_limb_t d1, d0, di, r1, r0; + mp_ptr tp; + + assert (nn >= 2); + shift = inv->shift; + d1 = inv->d1; + d0 = inv->d0; + di = inv->di; + + if (shift > 0) + { + tp = gmp_xalloc_limbs (nn); + r1 = mpn_lshift (tp, np, nn, shift); + np = tp; + } + else + r1 = 0; + + r0 = np[nn - 1]; + + i = nn - 2; + do + { + mp_limb_t n0, q; + n0 = np[i]; + gmp_udiv_qr_3by2 (q, r1, r0, r1, r0, n0, d1, d0, di); + + if (qp) + qp[i] = q; + } + while (--i >= 0); + + if (shift > 0) + { + assert ((r0 << (GMP_LIMB_BITS - shift)) == 0); + r0 = (r0 >> shift) | (r1 << (GMP_LIMB_BITS - shift)); + r1 >>= shift; + + gmp_free (tp); + } + + rp[1] = r1; + rp[0] = r0; +} + +#if 0 +static void +mpn_div_qr_2 (mp_ptr qp, mp_ptr rp, mp_srcptr np, mp_size_t nn, + mp_limb_t d1, mp_limb_t d0) +{ + struct gmp_div_inverse inv; + assert (nn >= 2); + + mpn_div_qr_2_invert (&inv, d1, d0); + mpn_div_qr_2_preinv (qp, rp, np, nn, &inv); +} +#endif + +static void +mpn_div_qr_pi1 (mp_ptr qp, + mp_ptr np, mp_size_t nn, mp_limb_t n1, + mp_srcptr dp, mp_size_t dn, + mp_limb_t dinv) +{ + mp_size_t i; + + mp_limb_t d1, d0; + mp_limb_t cy, cy1; + mp_limb_t q; + + assert (dn > 2); + assert (nn >= dn); + + d1 = dp[dn - 1]; + d0 = dp[dn - 2]; + + assert ((d1 & GMP_LIMB_HIGHBIT) != 0); + /* Iteration variable is the index of the q limb. + * + * We divide <n1, np[dn-1+i], np[dn-2+i], np[dn-3+i],..., np[i]> + * by <d1, d0, dp[dn-3], ..., dp[0] > + */ + + i = nn - dn; + do + { + mp_limb_t n0 = np[dn-1+i]; + + if (n1 == d1 && n0 == d0) + { + q = GMP_LIMB_MAX; + mpn_submul_1 (np+i, dp, dn, q); + n1 = np[dn-1+i]; /* update n1, last loop's value will now be invalid */ + } + else + { + gmp_udiv_qr_3by2 (q, n1, n0, n1, n0, np[dn-2+i], d1, d0, dinv); + + cy = mpn_submul_1 (np + i, dp, dn-2, q); + + cy1 = n0 < cy; + n0 = n0 - cy; + cy = n1 < cy1; + n1 = n1 - cy1; + np[dn-2+i] = n0; + + if (cy != 0) + { + n1 += d1 + mpn_add_n (np + i, np + i, dp, dn - 1); + q--; + } + } + + if (qp) + qp[i] = q; + } + while (--i >= 0); + + np[dn - 1] = n1; +} + +static void +mpn_div_qr_preinv (mp_ptr qp, mp_ptr np, mp_size_t nn, + mp_srcptr dp, mp_size_t dn, + const struct gmp_div_inverse *inv) +{ + assert (dn > 0); + assert (nn >= dn); + + if (dn == 1) + np[0] = mpn_div_qr_1_preinv (qp, np, nn, inv); + else if (dn == 2) + mpn_div_qr_2_preinv (qp, np, np, nn, inv); + else + { + mp_limb_t nh; + unsigned shift; + + assert (inv->d1 == dp[dn-1]); + assert (inv->d0 == dp[dn-2]); + assert ((inv->d1 & GMP_LIMB_HIGHBIT) != 0); + + shift = inv->shift; + if (shift > 0) + nh = mpn_lshift (np, np, nn, shift); + else + nh = 0; + + mpn_div_qr_pi1 (qp, np, nn, nh, dp, dn, inv->di); + + if (shift > 0) + gmp_assert_nocarry (mpn_rshift (np, np, dn, shift)); + } +} + +static void +mpn_div_qr (mp_ptr qp, mp_ptr np, mp_size_t nn, mp_srcptr dp, mp_size_t dn) +{ + struct gmp_div_inverse inv; + mp_ptr tp = NULL; + + assert (dn > 0); + assert (nn >= dn); + + mpn_div_qr_invert (&inv, dp, dn); + if (dn > 2 && inv.shift > 0) + { + tp = gmp_xalloc_limbs (dn); + gmp_assert_nocarry (mpn_lshift (tp, dp, dn, inv.shift)); + dp = tp; + } + mpn_div_qr_preinv (qp, np, nn, dp, dn, &inv); + if (tp) + gmp_free (tp); +} + + +/* MPN base conversion. */ +static unsigned +mpn_base_power_of_two_p (unsigned b) +{ + switch (b) + { + case 2: return 1; + case 4: return 2; + case 8: return 3; + case 16: return 4; + case 32: return 5; + case 64: return 6; + case 128: return 7; + case 256: return 8; + default: return 0; + } +} + +struct mpn_base_info +{ + /* bb is the largest power of the base which fits in one limb, and + exp is the corresponding exponent. */ + unsigned exp; + mp_limb_t bb; +}; + +static void +mpn_get_base_info (struct mpn_base_info *info, mp_limb_t b) +{ + mp_limb_t m; + mp_limb_t p; + unsigned exp; + + m = GMP_LIMB_MAX / b; + for (exp = 1, p = b; p <= m; exp++) + p *= b; + + info->exp = exp; + info->bb = p; +} + +static mp_bitcnt_t +mpn_limb_size_in_base_2 (mp_limb_t u) +{ + unsigned shift; + + assert (u > 0); + gmp_clz (shift, u); + return GMP_LIMB_BITS - shift; +} + +static size_t +mpn_get_str_bits (unsigned char *sp, unsigned bits, mp_srcptr up, mp_size_t un) +{ + unsigned char mask; + size_t sn, j; + mp_size_t i; + unsigned shift; + + sn = ((un - 1) * GMP_LIMB_BITS + mpn_limb_size_in_base_2 (up[un-1]) + + bits - 1) / bits; + + mask = (1U << bits) - 1; + + for (i = 0, j = sn, shift = 0; j-- > 0;) + { + unsigned char digit = up[i] >> shift; + + shift += bits; + + if (shift >= GMP_LIMB_BITS && ++i < un) + { + shift -= GMP_LIMB_BITS; + digit |= up[i] << (bits - shift); + } + sp[j] = digit & mask; + } + return sn; +} + +/* We generate digits from the least significant end, and reverse at + the end. */ +static size_t +mpn_limb_get_str (unsigned char *sp, mp_limb_t w, + const struct gmp_div_inverse *binv) +{ + mp_size_t i; + for (i = 0; w > 0; i++) + { + mp_limb_t h, l, r; + + h = w >> (GMP_LIMB_BITS - binv->shift); + l = w << binv->shift; + + gmp_udiv_qrnnd_preinv (w, r, h, l, binv->d1, binv->di); + assert ( (r << (GMP_LIMB_BITS - binv->shift)) == 0); + r >>= binv->shift; + + sp[i] = r; + } + return i; +} + +static size_t +mpn_get_str_other (unsigned char *sp, + int base, const struct mpn_base_info *info, + mp_ptr up, mp_size_t un) +{ + struct gmp_div_inverse binv; + size_t sn; + size_t i; + + mpn_div_qr_1_invert (&binv, base); + + sn = 0; + + if (un > 1) + { + struct gmp_div_inverse bbinv; + mpn_div_qr_1_invert (&bbinv, info->bb); + + do + { + mp_limb_t w; + size_t done; + w = mpn_div_qr_1_preinv (up, up, un, &bbinv); + un -= (up[un-1] == 0); + done = mpn_limb_get_str (sp + sn, w, &binv); + + for (sn += done; done < info->exp; done++) + sp[sn++] = 0; + } + while (un > 1); + } + sn += mpn_limb_get_str (sp + sn, up[0], &binv); + + /* Reverse order */ + for (i = 0; 2*i + 1 < sn; i++) + { + unsigned char t = sp[i]; + sp[i] = sp[sn - i - 1]; + sp[sn - i - 1] = t; + } + + return sn; +} + +size_t +mpn_get_str (unsigned char *sp, int base, mp_ptr up, mp_size_t un) +{ + unsigned bits; + + assert (un > 0); + assert (up[un-1] > 0); + + bits = mpn_base_power_of_two_p (base); + if (bits) + return mpn_get_str_bits (sp, bits, up, un); + else + { + struct mpn_base_info info; + + mpn_get_base_info (&info, base); + return mpn_get_str_other (sp, base, &info, up, un); + } +} + +static mp_size_t +mpn_set_str_bits (mp_ptr rp, const unsigned char *sp, size_t sn, + unsigned bits) +{ + mp_size_t rn; + size_t j; + unsigned shift; + + for (j = sn, rn = 0, shift = 0; j-- > 0; ) + { + if (shift == 0) + { + rp[rn++] = sp[j]; + shift += bits; + } + else + { + rp[rn-1] |= (mp_limb_t) sp[j] << shift; + shift += bits; + if (shift >= GMP_LIMB_BITS) + { + shift -= GMP_LIMB_BITS; + if (shift > 0) + rp[rn++] = (mp_limb_t) sp[j] >> (bits - shift); + } + } + } + rn = mpn_normalized_size (rp, rn); + return rn; +} + +/* Result is usually normalized, except for all-zero input, in which + case a single zero limb is written at *RP, and 1 is returned. */ +static mp_size_t +mpn_set_str_other (mp_ptr rp, const unsigned char *sp, size_t sn, + mp_limb_t b, const struct mpn_base_info *info) +{ + mp_size_t rn; + mp_limb_t w; + unsigned k; + size_t j; + + assert (sn > 0); + + k = 1 + (sn - 1) % info->exp; + + j = 0; + w = sp[j++]; + while (--k != 0) + w = w * b + sp[j++]; + + rp[0] = w; + + for (rn = 1; j < sn;) + { + mp_limb_t cy; + + w = sp[j++]; + for (k = 1; k < info->exp; k++) + w = w * b + sp[j++]; + + cy = mpn_mul_1 (rp, rp, rn, info->bb); + cy += mpn_add_1 (rp, rp, rn, w); + if (cy > 0) + rp[rn++] = cy; + } + assert (j == sn); + + return rn; +} + +mp_size_t +mpn_set_str (mp_ptr rp, const unsigned char *sp, size_t sn, int base) +{ + unsigned bits; + + if (sn == 0) + return 0; + + bits = mpn_base_power_of_two_p (base); + if (bits) + return mpn_set_str_bits (rp, sp, sn, bits); + else + { + struct mpn_base_info info; + + mpn_get_base_info (&info, base); + return mpn_set_str_other (rp, sp, sn, base, &info); + } +} + + +/* MPZ interface */ +void +mpz_init (mpz_t r) +{ + static const mp_limb_t dummy_limb = 0xc1a0; + + r->_mp_alloc = 0; + r->_mp_size = 0; + r->_mp_d = (mp_ptr) &dummy_limb; +} + +/* The utility of this function is a bit limited, since many functions + assigns the result variable using mpz_swap. */ +void +mpz_init2 (mpz_t r, mp_bitcnt_t bits) +{ + mp_size_t rn; + + bits -= (bits != 0); /* Round down, except if 0 */ + rn = 1 + bits / GMP_LIMB_BITS; + + r->_mp_alloc = rn; + r->_mp_size = 0; + r->_mp_d = gmp_xalloc_limbs (rn); +} + +void +mpz_clear (mpz_t r) +{ + if (r->_mp_alloc) + gmp_free (r->_mp_d); +} + +static mp_ptr +mpz_realloc (mpz_t r, mp_size_t size) +{ + size = GMP_MAX (size, 1); + + if (r->_mp_alloc) + r->_mp_d = gmp_xrealloc_limbs (r->_mp_d, size); + else + r->_mp_d = gmp_xalloc_limbs (size); + r->_mp_alloc = size; + + if (GMP_ABS (r->_mp_size) > size) + r->_mp_size = 0; + + return r->_mp_d; +} + +/* Realloc for an mpz_t WHAT if it has less than NEEDED limbs. */ +#define MPZ_REALLOC(z,n) ((n) > (z)->_mp_alloc \ + ? mpz_realloc(z,n) \ + : (z)->_mp_d) + +/* MPZ assignment and basic conversions. */ +void +mpz_set_si (mpz_t r, signed long int x) +{ + if (x >= 0) + mpz_set_ui (r, x); + else /* (x < 0) */ + { + r->_mp_size = -1; + MPZ_REALLOC (r, 1)[0] = GMP_NEG_CAST (unsigned long int, x); + } +} + +void +mpz_set_ui (mpz_t r, unsigned long int x) +{ + if (x > 0) + { + r->_mp_size = 1; + MPZ_REALLOC (r, 1)[0] = x; + } + else + r->_mp_size = 0; +} + +void +mpz_set (mpz_t r, const mpz_t x) +{ + /* Allow the NOP r == x */ + if (r != x) + { + mp_size_t n; + mp_ptr rp; + + n = GMP_ABS (x->_mp_size); + rp = MPZ_REALLOC (r, n); + + mpn_copyi (rp, x->_mp_d, n); + r->_mp_size = x->_mp_size; + } +} + +void +mpz_init_set_si (mpz_t r, signed long int x) +{ + mpz_init (r); + mpz_set_si (r, x); +} + +void +mpz_init_set_ui (mpz_t r, unsigned long int x) +{ + mpz_init (r); + mpz_set_ui (r, x); +} + +void +mpz_init_set (mpz_t r, const mpz_t x) +{ + mpz_init (r); + mpz_set (r, x); +} + +int +mpz_fits_slong_p (const mpz_t u) +{ + mp_size_t us = u->_mp_size; + + if (us == 1) + return u->_mp_d[0] < GMP_LIMB_HIGHBIT; + else if (us == -1) + return u->_mp_d[0] <= GMP_LIMB_HIGHBIT; + else + return (us == 0); +} + +int +mpz_fits_ulong_p (const mpz_t u) +{ + mp_size_t us = u->_mp_size; + + return (us == (us > 0)); +} + +long int +mpz_get_si (const mpz_t u) +{ + if (u->_mp_size < 0) + /* This expression is necessary to properly handle 0x80000000 */ + return -1 - (long) ((u->_mp_d[0] - 1) & ~GMP_LIMB_HIGHBIT); + else + return (long) (mpz_get_ui (u) & ~GMP_LIMB_HIGHBIT); +} + +unsigned long int +mpz_get_ui (const mpz_t u) +{ + return u->_mp_size == 0 ? 0 : u->_mp_d[0]; +} + +size_t +mpz_size (const mpz_t u) +{ + return GMP_ABS (u->_mp_size); +} + +mp_limb_t +mpz_getlimbn (const mpz_t u, mp_size_t n) +{ + if (n >= 0 && n < GMP_ABS (u->_mp_size)) + return u->_mp_d[n]; + else + return 0; +} + +void +mpz_realloc2 (mpz_t x, mp_bitcnt_t n) +{ + mpz_realloc (x, 1 + (n - (n != 0)) / GMP_LIMB_BITS); +} + +mp_srcptr +mpz_limbs_read (mpz_srcptr x) +{ + return x->_mp_d; +} + +mp_ptr +mpz_limbs_modify (mpz_t x, mp_size_t n) +{ + assert (n > 0); + return MPZ_REALLOC (x, n); +} + +mp_ptr +mpz_limbs_write (mpz_t x, mp_size_t n) +{ + return mpz_limbs_modify (x, n); +} + +void +mpz_limbs_finish (mpz_t x, mp_size_t xs) +{ + mp_size_t xn; + xn = mpn_normalized_size (x->_mp_d, GMP_ABS (xs)); + x->_mp_size = xs < 0 ? -xn : xn; +} + +mpz_srcptr +mpz_roinit_n (mpz_t x, mp_srcptr xp, mp_size_t xs) +{ + x->_mp_alloc = 0; + x->_mp_d = (mp_ptr) xp; + mpz_limbs_finish (x, xs); + return x; +} + + +/* Conversions and comparison to double. */ +void +mpz_set_d (mpz_t r, double x) +{ + int sign; + mp_ptr rp; + mp_size_t rn, i; + double B; + double Bi; + mp_limb_t f; + + /* x != x is true when x is a NaN, and x == x * 0.5 is true when x is + zero or infinity. */ + if (x != x || x == x * 0.5) + { + r->_mp_size = 0; + return; + } + + sign = x < 0.0 ; + if (sign) + x = - x; + + if (x < 1.0) + { + r->_mp_size = 0; + return; + } + B = 2.0 * (double) GMP_LIMB_HIGHBIT; + Bi = 1.0 / B; + for (rn = 1; x >= B; rn++) + x *= Bi; + + rp = MPZ_REALLOC (r, rn); + + f = (mp_limb_t) x; + x -= f; + assert (x < 1.0); + i = rn-1; + rp[i] = f; + while (--i >= 0) + { + x = B * x; + f = (mp_limb_t) x; + x -= f; + assert (x < 1.0); + rp[i] = f; + } + + r->_mp_size = sign ? - rn : rn; +} + +void +mpz_init_set_d (mpz_t r, double x) +{ + mpz_init (r); + mpz_set_d (r, x); +} + +double +mpz_get_d (const mpz_t u) +{ + mp_size_t un; + double x; + double B = 2.0 * (double) GMP_LIMB_HIGHBIT; + + un = GMP_ABS (u->_mp_size); + + if (un == 0) + return 0.0; + + x = u->_mp_d[--un]; + while (un > 0) + x = B*x + u->_mp_d[--un]; + + if (u->_mp_size < 0) + x = -x; + + return x; +} + +int +mpz_cmpabs_d (const mpz_t x, double d) +{ + mp_size_t xn; + double B, Bi; + mp_size_t i; + + xn = x->_mp_size; + d = GMP_ABS (d); + + if (xn != 0) + { + xn = GMP_ABS (xn); + + B = 2.0 * (double) GMP_LIMB_HIGHBIT; + Bi = 1.0 / B; + + /* Scale d so it can be compared with the top limb. */ + for (i = 1; i < xn; i++) + d *= Bi; + + if (d >= B) + return -1; + + /* Compare floor(d) to top limb, subtract and cancel when equal. */ + for (i = xn; i-- > 0;) + { + mp_limb_t f, xl; + + f = (mp_limb_t) d; + xl = x->_mp_d[i]; + if (xl > f) + return 1; + else if (xl < f) + return -1; + d = B * (d - f); + } + } + return - (d > 0.0); +} + +int +mpz_cmp_d (const mpz_t x, double d) +{ + if (x->_mp_size < 0) + { + if (d >= 0.0) + return -1; + else + return -mpz_cmpabs_d (x, d); + } + else + { + if (d < 0.0) + return 1; + else + return mpz_cmpabs_d (x, d); + } +} + + +/* MPZ comparisons and the like. */ +int +mpz_sgn (const mpz_t u) +{ + return GMP_CMP (u->_mp_size, 0); +} + +int +mpz_cmp_si (const mpz_t u, long v) +{ + mp_size_t usize = u->_mp_size; + + if (usize < -1) + return -1; + else if (v >= 0) + return mpz_cmp_ui (u, v); + else if (usize >= 0) + return 1; + else /* usize == -1 */ + return GMP_CMP (GMP_NEG_CAST (mp_limb_t, v), u->_mp_d[0]); +} + +int +mpz_cmp_ui (const mpz_t u, unsigned long v) +{ + mp_size_t usize = u->_mp_size; + + if (usize > 1) + return 1; + else if (usize < 0) + return -1; + else + return GMP_CMP (mpz_get_ui (u), v); +} + +int +mpz_cmp (const mpz_t a, const mpz_t b) +{ + mp_size_t asize = a->_mp_size; + mp_size_t bsize = b->_mp_size; + + if (asize != bsize) + return (asize < bsize) ? -1 : 1; + else if (asize >= 0) + return mpn_cmp (a->_mp_d, b->_mp_d, asize); + else + return mpn_cmp (b->_mp_d, a->_mp_d, -asize); +} + +int +mpz_cmpabs_ui (const mpz_t u, unsigned long v) +{ + if (GMP_ABS (u->_mp_size) > 1) + return 1; + else + return GMP_CMP (mpz_get_ui (u), v); +} + +int +mpz_cmpabs (const mpz_t u, const mpz_t v) +{ + return mpn_cmp4 (u->_mp_d, GMP_ABS (u->_mp_size), + v->_mp_d, GMP_ABS (v->_mp_size)); +} + +void +mpz_abs (mpz_t r, const mpz_t u) +{ + mpz_set (r, u); + r->_mp_size = GMP_ABS (r->_mp_size); +} + +void +mpz_neg (mpz_t r, const mpz_t u) +{ + mpz_set (r, u); + r->_mp_size = -r->_mp_size; +} + +void +mpz_swap (mpz_t u, mpz_t v) +{ + MP_SIZE_T_SWAP (u->_mp_size, v->_mp_size); + MP_SIZE_T_SWAP (u->_mp_alloc, v->_mp_alloc); + MP_PTR_SWAP (u->_mp_d, v->_mp_d); +} + + +/* MPZ addition and subtraction */ + +/* Adds to the absolute value. Returns new size, but doesn't store it. */ +static mp_size_t +mpz_abs_add_ui (mpz_t r, const mpz_t a, unsigned long b) +{ + mp_size_t an; + mp_ptr rp; + mp_limb_t cy; + + an = GMP_ABS (a->_mp_size); + if (an == 0) + { + MPZ_REALLOC (r, 1)[0] = b; + return b > 0; + } + + rp = MPZ_REALLOC (r, an + 1); + + cy = mpn_add_1 (rp, a->_mp_d, an, b); + rp[an] = cy; + an += cy; + + return an; +} + +/* Subtract from the absolute value. Returns new size, (or -1 on underflow), + but doesn't store it. */ +static mp_size_t +mpz_abs_sub_ui (mpz_t r, const mpz_t a, unsigned long b) +{ + mp_size_t an = GMP_ABS (a->_mp_size); + mp_ptr rp; + + if (an == 0) + { + MPZ_REALLOC (r, 1)[0] = b; + return -(b > 0); + } + rp = MPZ_REALLOC (r, an); + if (an == 1 && a->_mp_d[0] < b) + { + rp[0] = b - a->_mp_d[0]; + return -1; + } + else + { + gmp_assert_nocarry (mpn_sub_1 (rp, a->_mp_d, an, b)); + return mpn_normalized_size (rp, an); + } +} + +void +mpz_add_ui (mpz_t r, const mpz_t a, unsigned long b) +{ + if (a->_mp_size >= 0) + r->_mp_size = mpz_abs_add_ui (r, a, b); + else + r->_mp_size = -mpz_abs_sub_ui (r, a, b); +} + +void +mpz_sub_ui (mpz_t r, const mpz_t a, unsigned long b) +{ + if (a->_mp_size < 0) + r->_mp_size = -mpz_abs_add_ui (r, a, b); + else + r->_mp_size = mpz_abs_sub_ui (r, a, b); +} + +void +mpz_ui_sub (mpz_t r, unsigned long a, const mpz_t b) +{ + if (b->_mp_size < 0) + r->_mp_size = mpz_abs_add_ui (r, b, a); + else + r->_mp_size = -mpz_abs_sub_ui (r, b, a); +} + +static mp_size_t +mpz_abs_add (mpz_t r, const mpz_t a, const mpz_t b) +{ + mp_size_t an = GMP_ABS (a->_mp_size); + mp_size_t bn = GMP_ABS (b->_mp_size); + mp_ptr rp; + mp_limb_t cy; + + if (an < bn) + { + MPZ_SRCPTR_SWAP (a, b); + MP_SIZE_T_SWAP (an, bn); + } + + rp = MPZ_REALLOC (r, an + 1); + cy = mpn_add (rp, a->_mp_d, an, b->_mp_d, bn); + + rp[an] = cy; + + return an + cy; +} + +static mp_size_t +mpz_abs_sub (mpz_t r, const mpz_t a, const mpz_t b) +{ + mp_size_t an = GMP_ABS (a->_mp_size); + mp_size_t bn = GMP_ABS (b->_mp_size); + int cmp; + mp_ptr rp; + + cmp = mpn_cmp4 (a->_mp_d, an, b->_mp_d, bn); + if (cmp > 0) + { + rp = MPZ_REALLOC (r, an); + gmp_assert_nocarry (mpn_sub (rp, a->_mp_d, an, b->_mp_d, bn)); + return mpn_normalized_size (rp, an); + } + else if (cmp < 0) + { + rp = MPZ_REALLOC (r, bn); + gmp_assert_nocarry (mpn_sub (rp, b->_mp_d, bn, a->_mp_d, an)); + return -mpn_normalized_size (rp, bn); + } + else + return 0; +} + +void +mpz_add (mpz_t r, const mpz_t a, const mpz_t b) +{ + mp_size_t rn; + + if ( (a->_mp_size ^ b->_mp_size) >= 0) + rn = mpz_abs_add (r, a, b); + else + rn = mpz_abs_sub (r, a, b); + + r->_mp_size = a->_mp_size >= 0 ? rn : - rn; +} + +void +mpz_sub (mpz_t r, const mpz_t a, const mpz_t b) +{ + mp_size_t rn; + + if ( (a->_mp_size ^ b->_mp_size) >= 0) + rn = mpz_abs_sub (r, a, b); + else + rn = mpz_abs_add (r, a, b); + + r->_mp_size = a->_mp_size >= 0 ? rn : - rn; +} + + +/* MPZ multiplication */ +void +mpz_mul_si (mpz_t r, const mpz_t u, long int v) +{ + if (v < 0) + { + mpz_mul_ui (r, u, GMP_NEG_CAST (unsigned long int, v)); + mpz_neg (r, r); + } + else + mpz_mul_ui (r, u, (unsigned long int) v); +} + +void +mpz_mul_ui (mpz_t r, const mpz_t u, unsigned long int v) +{ + mp_size_t un, us; + mp_ptr tp; + mp_limb_t cy; + + us = u->_mp_size; + + if (us == 0 || v == 0) + { + r->_mp_size = 0; + return; + } + + un = GMP_ABS (us); + + tp = MPZ_REALLOC (r, un + 1); + cy = mpn_mul_1 (tp, u->_mp_d, un, v); + tp[un] = cy; + + un += (cy > 0); + r->_mp_size = (us < 0) ? - un : un; +} + +void +mpz_mul (mpz_t r, const mpz_t u, const mpz_t v) +{ + int sign; + mp_size_t un, vn, rn; + mpz_t t; + mp_ptr tp; + + un = u->_mp_size; + vn = v->_mp_size; + + if (un == 0 || vn == 0) + { + r->_mp_size = 0; + return; + } + + sign = (un ^ vn) < 0; + + un = GMP_ABS (un); + vn = GMP_ABS (vn); + + mpz_init2 (t, (un + vn) * GMP_LIMB_BITS); + + tp = t->_mp_d; + if (un >= vn) + mpn_mul (tp, u->_mp_d, un, v->_mp_d, vn); + else + mpn_mul (tp, v->_mp_d, vn, u->_mp_d, un); + + rn = un + vn; + rn -= tp[rn-1] == 0; + + t->_mp_size = sign ? - rn : rn; + mpz_swap (r, t); + mpz_clear (t); +} + +void +mpz_mul_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t bits) +{ + mp_size_t un, rn; + mp_size_t limbs; + unsigned shift; + mp_ptr rp; + + un = GMP_ABS (u->_mp_size); + if (un == 0) + { + r->_mp_size = 0; + return; + } + + limbs = bits / GMP_LIMB_BITS; + shift = bits % GMP_LIMB_BITS; + + rn = un + limbs + (shift > 0); + rp = MPZ_REALLOC (r, rn); + if (shift > 0) + { + mp_limb_t cy = mpn_lshift (rp + limbs, u->_mp_d, un, shift); + rp[rn-1] = cy; + rn -= (cy == 0); + } + else + mpn_copyd (rp + limbs, u->_mp_d, un); + + mpn_zero (rp, limbs); + + r->_mp_size = (u->_mp_size < 0) ? - rn : rn; +} + +void +mpz_addmul_ui (mpz_t r, const mpz_t u, unsigned long int v) +{ + mpz_t t; + mpz_init (t); + mpz_mul_ui (t, u, v); + mpz_add (r, r, t); + mpz_clear (t); +} + +void +mpz_submul_ui (mpz_t r, const mpz_t u, unsigned long int v) +{ + mpz_t t; + mpz_init (t); + mpz_mul_ui (t, u, v); + mpz_sub (r, r, t); + mpz_clear (t); +} + +void +mpz_addmul (mpz_t r, const mpz_t u, const mpz_t v) +{ + mpz_t t; + mpz_init (t); + mpz_mul (t, u, v); + mpz_add (r, r, t); + mpz_clear (t); +} + +void +mpz_submul (mpz_t r, const mpz_t u, const mpz_t v) +{ + mpz_t t; + mpz_init (t); + mpz_mul (t, u, v); + mpz_sub (r, r, t); + mpz_clear (t); +} + + +/* MPZ division */ +enum mpz_div_round_mode { GMP_DIV_FLOOR, GMP_DIV_CEIL, GMP_DIV_TRUNC }; + +/* Allows q or r to be zero. Returns 1 iff remainder is non-zero. */ +static int +mpz_div_qr (mpz_t q, mpz_t r, + const mpz_t n, const mpz_t d, enum mpz_div_round_mode mode) +{ + mp_size_t ns, ds, nn, dn, qs; + ns = n->_mp_size; + ds = d->_mp_size; + + if (ds == 0) + gmp_die("mpz_div_qr: Divide by zero."); + + if (ns == 0) + { + if (q) + q->_mp_size = 0; + if (r) + r->_mp_size = 0; + return 0; + } + + nn = GMP_ABS (ns); + dn = GMP_ABS (ds); + + qs = ds ^ ns; + + if (nn < dn) + { + if (mode == GMP_DIV_CEIL && qs >= 0) + { + /* q = 1, r = n - d */ + if (r) + mpz_sub (r, n, d); + if (q) + mpz_set_ui (q, 1); + } + else if (mode == GMP_DIV_FLOOR && qs < 0) + { + /* q = -1, r = n + d */ + if (r) + mpz_add (r, n, d); + if (q) + mpz_set_si (q, -1); + } + else + { + /* q = 0, r = d */ + if (r) + mpz_set (r, n); + if (q) + q->_mp_size = 0; + } + return 1; + } + else + { + mp_ptr np, qp; + mp_size_t qn, rn; + mpz_t tq, tr; + + mpz_init_set (tr, n); + np = tr->_mp_d; + + qn = nn - dn + 1; + + if (q) + { + mpz_init2 (tq, qn * GMP_LIMB_BITS); + qp = tq->_mp_d; + } + else + qp = NULL; + + mpn_div_qr (qp, np, nn, d->_mp_d, dn); + + if (qp) + { + qn -= (qp[qn-1] == 0); + + tq->_mp_size = qs < 0 ? -qn : qn; + } + rn = mpn_normalized_size (np, dn); + tr->_mp_size = ns < 0 ? - rn : rn; + + if (mode == GMP_DIV_FLOOR && qs < 0 && rn != 0) + { + if (q) + mpz_sub_ui (tq, tq, 1); + if (r) + mpz_add (tr, tr, d); + } + else if (mode == GMP_DIV_CEIL && qs >= 0 && rn != 0) + { + if (q) + mpz_add_ui (tq, tq, 1); + if (r) + mpz_sub (tr, tr, d); + } + + if (q) + { + mpz_swap (tq, q); + mpz_clear (tq); + } + if (r) + mpz_swap (tr, r); + + mpz_clear (tr); + + return rn != 0; + } +} + +void +mpz_cdiv_qr (mpz_t q, mpz_t r, const mpz_t n, const mpz_t d) +{ + mpz_div_qr (q, r, n, d, GMP_DIV_CEIL); +} + +void +mpz_fdiv_qr (mpz_t q, mpz_t r, const mpz_t n, const mpz_t d) +{ + mpz_div_qr (q, r, n, d, GMP_DIV_FLOOR); +} + +void +mpz_tdiv_qr (mpz_t q, mpz_t r, const mpz_t n, const mpz_t d) +{ + mpz_div_qr (q, r, n, d, GMP_DIV_TRUNC); +} + +void +mpz_cdiv_q (mpz_t q, const mpz_t n, const mpz_t d) +{ + mpz_div_qr (q, NULL, n, d, GMP_DIV_CEIL); +} + +void +mpz_fdiv_q (mpz_t q, const mpz_t n, const mpz_t d) +{ + mpz_div_qr (q, NULL, n, d, GMP_DIV_FLOOR); +} + +void +mpz_tdiv_q (mpz_t q, const mpz_t n, const mpz_t d) +{ + mpz_div_qr (q, NULL, n, d, GMP_DIV_TRUNC); +} + +void +mpz_cdiv_r (mpz_t r, const mpz_t n, const mpz_t d) +{ + mpz_div_qr (NULL, r, n, d, GMP_DIV_CEIL); +} + +void +mpz_fdiv_r (mpz_t r, const mpz_t n, const mpz_t d) +{ + mpz_div_qr (NULL, r, n, d, GMP_DIV_FLOOR); +} + +void +mpz_tdiv_r (mpz_t r, const mpz_t n, const mpz_t d) +{ + mpz_div_qr (NULL, r, n, d, GMP_DIV_TRUNC); +} + +void +mpz_mod (mpz_t r, const mpz_t n, const mpz_t d) +{ + mpz_div_qr (NULL, r, n, d, d->_mp_size >= 0 ? GMP_DIV_FLOOR : GMP_DIV_CEIL); +} + +static void +mpz_div_q_2exp (mpz_t q, const mpz_t u, mp_bitcnt_t bit_index, + enum mpz_div_round_mode mode) +{ + mp_size_t un, qn; + mp_size_t limb_cnt; + mp_ptr qp; + int adjust; + + un = u->_mp_size; + if (un == 0) + { + q->_mp_size = 0; + return; + } + limb_cnt = bit_index / GMP_LIMB_BITS; + qn = GMP_ABS (un) - limb_cnt; + bit_index %= GMP_LIMB_BITS; + + if (mode == ((un > 0) ? GMP_DIV_CEIL : GMP_DIV_FLOOR)) /* un != 0 here. */ + /* Note: Below, the final indexing at limb_cnt is valid because at + that point we have qn > 0. */ + adjust = (qn <= 0 + || !mpn_zero_p (u->_mp_d, limb_cnt) + || (u->_mp_d[limb_cnt] + & (((mp_limb_t) 1 << bit_index) - 1))); + else + adjust = 0; + + if (qn <= 0) + qn = 0; + else + { + qp = MPZ_REALLOC (q, qn); + + if (bit_index != 0) + { + mpn_rshift (qp, u->_mp_d + limb_cnt, qn, bit_index); + qn -= qp[qn - 1] == 0; + } + else + { + mpn_copyi (qp, u->_mp_d + limb_cnt, qn); + } + } + + q->_mp_size = qn; + + if (adjust) + mpz_add_ui (q, q, 1); + if (un < 0) + mpz_neg (q, q); +} + +static void +mpz_div_r_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t bit_index, + enum mpz_div_round_mode mode) +{ + mp_size_t us, un, rn; + mp_ptr rp; + mp_limb_t mask; + + us = u->_mp_size; + if (us == 0 || bit_index == 0) + { + r->_mp_size = 0; + return; + } + rn = (bit_index + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS; + assert (rn > 0); + + rp = MPZ_REALLOC (r, rn); + un = GMP_ABS (us); + + mask = GMP_LIMB_MAX >> (rn * GMP_LIMB_BITS - bit_index); + + if (rn > un) + { + /* Quotient (with truncation) is zero, and remainder is + non-zero */ + if (mode == ((us > 0) ? GMP_DIV_CEIL : GMP_DIV_FLOOR)) /* us != 0 here. */ + { + /* Have to negate and sign extend. */ + mp_size_t i; + + gmp_assert_nocarry (! mpn_neg (rp, u->_mp_d, un)); + for (i = un; i < rn - 1; i++) + rp[i] = GMP_LIMB_MAX; + + rp[rn-1] = mask; + us = -us; + } + else + { + /* Just copy */ + if (r != u) + mpn_copyi (rp, u->_mp_d, un); + + rn = un; + } + } + else + { + if (r != u) + mpn_copyi (rp, u->_mp_d, rn - 1); + + rp[rn-1] = u->_mp_d[rn-1] & mask; + + if (mode == ((us > 0) ? GMP_DIV_CEIL : GMP_DIV_FLOOR)) /* us != 0 here. */ + { + /* If r != 0, compute 2^{bit_count} - r. */ + mpn_neg (rp, rp, rn); + + rp[rn-1] &= mask; + + /* us is not used for anything else, so we can modify it + here to indicate flipped sign. */ + us = -us; + } + } + rn = mpn_normalized_size (rp, rn); + r->_mp_size = us < 0 ? -rn : rn; +} + +void +mpz_cdiv_q_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt) +{ + mpz_div_q_2exp (r, u, cnt, GMP_DIV_CEIL); +} + +void +mpz_fdiv_q_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt) +{ + mpz_div_q_2exp (r, u, cnt, GMP_DIV_FLOOR); +} + +void +mpz_tdiv_q_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt) +{ + mpz_div_q_2exp (r, u, cnt, GMP_DIV_TRUNC); +} + +void +mpz_cdiv_r_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt) +{ + mpz_div_r_2exp (r, u, cnt, GMP_DIV_CEIL); +} + +void +mpz_fdiv_r_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt) +{ + mpz_div_r_2exp (r, u, cnt, GMP_DIV_FLOOR); +} + +void +mpz_tdiv_r_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt) +{ + mpz_div_r_2exp (r, u, cnt, GMP_DIV_TRUNC); +} + +void +mpz_divexact (mpz_t q, const mpz_t n, const mpz_t d) +{ + gmp_assert_nocarry (mpz_div_qr (q, NULL, n, d, GMP_DIV_TRUNC)); +} + +int +mpz_divisible_p (const mpz_t n, const mpz_t d) +{ + return mpz_div_qr (NULL, NULL, n, d, GMP_DIV_TRUNC) == 0; +} + +int +mpz_congruent_p (const mpz_t a, const mpz_t b, const mpz_t m) +{ + mpz_t t; + int res; + + /* a == b (mod 0) iff a == b */ + if (mpz_sgn (m) == 0) + return (mpz_cmp (a, b) == 0); + + mpz_init (t); + mpz_sub (t, a, b); + res = mpz_divisible_p (t, m); + mpz_clear (t); + + return res; +} + +static unsigned long +mpz_div_qr_ui (mpz_t q, mpz_t r, + const mpz_t n, unsigned long d, enum mpz_div_round_mode mode) +{ + mp_size_t ns, qn; + mp_ptr qp; + mp_limb_t rl; + mp_size_t rs; + + ns = n->_mp_size; + if (ns == 0) + { + if (q) + q->_mp_size = 0; + if (r) + r->_mp_size = 0; + return 0; + } + + qn = GMP_ABS (ns); + if (q) + qp = MPZ_REALLOC (q, qn); + else + qp = NULL; + + rl = mpn_div_qr_1 (qp, n->_mp_d, qn, d); + assert (rl < d); + + rs = rl > 0; + rs = (ns < 0) ? -rs : rs; + + if (rl > 0 && ( (mode == GMP_DIV_FLOOR && ns < 0) + || (mode == GMP_DIV_CEIL && ns >= 0))) + { + if (q) + gmp_assert_nocarry (mpn_add_1 (qp, qp, qn, 1)); + rl = d - rl; + rs = -rs; + } + + if (r) + { + MPZ_REALLOC (r, 1)[0] = rl; + r->_mp_size = rs; + } + if (q) + { + qn -= (qp[qn-1] == 0); + assert (qn == 0 || qp[qn-1] > 0); + + q->_mp_size = (ns < 0) ? - qn : qn; + } + + return rl; +} + +unsigned long +mpz_cdiv_qr_ui (mpz_t q, mpz_t r, const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (q, r, n, d, GMP_DIV_CEIL); +} + +unsigned long +mpz_fdiv_qr_ui (mpz_t q, mpz_t r, const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (q, r, n, d, GMP_DIV_FLOOR); +} + +unsigned long +mpz_tdiv_qr_ui (mpz_t q, mpz_t r, const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (q, r, n, d, GMP_DIV_TRUNC); +} + +unsigned long +mpz_cdiv_q_ui (mpz_t q, const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (q, NULL, n, d, GMP_DIV_CEIL); +} + +unsigned long +mpz_fdiv_q_ui (mpz_t q, const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (q, NULL, n, d, GMP_DIV_FLOOR); +} + +unsigned long +mpz_tdiv_q_ui (mpz_t q, const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (q, NULL, n, d, GMP_DIV_TRUNC); +} + +unsigned long +mpz_cdiv_r_ui (mpz_t r, const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (NULL, r, n, d, GMP_DIV_CEIL); +} +unsigned long +mpz_fdiv_r_ui (mpz_t r, const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (NULL, r, n, d, GMP_DIV_FLOOR); +} +unsigned long +mpz_tdiv_r_ui (mpz_t r, const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (NULL, r, n, d, GMP_DIV_TRUNC); +} + +unsigned long +mpz_cdiv_ui (const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (NULL, NULL, n, d, GMP_DIV_CEIL); +} + +unsigned long +mpz_fdiv_ui (const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (NULL, NULL, n, d, GMP_DIV_FLOOR); +} + +unsigned long +mpz_tdiv_ui (const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (NULL, NULL, n, d, GMP_DIV_TRUNC); +} + +unsigned long +mpz_mod_ui (mpz_t r, const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (NULL, r, n, d, GMP_DIV_FLOOR); +} + +void +mpz_divexact_ui (mpz_t q, const mpz_t n, unsigned long d) +{ + gmp_assert_nocarry (mpz_div_qr_ui (q, NULL, n, d, GMP_DIV_TRUNC)); +} + +int +mpz_divisible_ui_p (const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (NULL, NULL, n, d, GMP_DIV_TRUNC) == 0; +} + + +/* GCD */ +static mp_limb_t +mpn_gcd_11 (mp_limb_t u, mp_limb_t v) +{ + unsigned shift; + + assert ( (u | v) > 0); + + if (u == 0) + return v; + else if (v == 0) + return u; + + gmp_ctz (shift, u | v); + + u >>= shift; + v >>= shift; + + if ( (u & 1) == 0) + MP_LIMB_T_SWAP (u, v); + + while ( (v & 1) == 0) + v >>= 1; + + while (u != v) + { + if (u > v) + { + u -= v; + do + u >>= 1; + while ( (u & 1) == 0); + } + else + { + v -= u; + do + v >>= 1; + while ( (v & 1) == 0); + } + } + return u << shift; +} + +unsigned long +mpz_gcd_ui (mpz_t g, const mpz_t u, unsigned long v) +{ + mp_size_t un; + + if (v == 0) + { + if (g) + mpz_abs (g, u); + } + else + { + un = GMP_ABS (u->_mp_size); + if (un != 0) + v = mpn_gcd_11 (mpn_div_qr_1 (NULL, u->_mp_d, un, v), v); + + if (g) + mpz_set_ui (g, v); + } + + return v; +} + +static mp_bitcnt_t +mpz_make_odd (mpz_t r) +{ + mp_bitcnt_t shift; + + assert (r->_mp_size > 0); + /* Count trailing zeros, equivalent to mpn_scan1, because we know that there is a 1 */ + shift = mpn_common_scan (r->_mp_d[0], 0, r->_mp_d, 0, 0); + mpz_tdiv_q_2exp (r, r, shift); + + return shift; +} + +void +mpz_gcd (mpz_t g, const mpz_t u, const mpz_t v) +{ + mpz_t tu, tv; + mp_bitcnt_t uz, vz, gz; + + if (u->_mp_size == 0) + { + mpz_abs (g, v); + return; + } + if (v->_mp_size == 0) + { + mpz_abs (g, u); + return; + } + + mpz_init (tu); + mpz_init (tv); + + mpz_abs (tu, u); + uz = mpz_make_odd (tu); + mpz_abs (tv, v); + vz = mpz_make_odd (tv); + gz = GMP_MIN (uz, vz); + + if (tu->_mp_size < tv->_mp_size) + mpz_swap (tu, tv); + + mpz_tdiv_r (tu, tu, tv); + if (tu->_mp_size == 0) + { + mpz_swap (g, tv); + } + else + for (;;) + { + int c; + + mpz_make_odd (tu); + c = mpz_cmp (tu, tv); + if (c == 0) + { + mpz_swap (g, tu); + break; + } + if (c < 0) + mpz_swap (tu, tv); + + if (tv->_mp_size == 1) + { + mp_limb_t vl = tv->_mp_d[0]; + mp_limb_t ul = mpz_tdiv_ui (tu, vl); + mpz_set_ui (g, mpn_gcd_11 (ul, vl)); + break; + } + mpz_sub (tu, tu, tv); + } + mpz_clear (tu); + mpz_clear (tv); + mpz_mul_2exp (g, g, gz); +} + +void +mpz_gcdext (mpz_t g, mpz_t s, mpz_t t, const mpz_t u, const mpz_t v) +{ + mpz_t tu, tv, s0, s1, t0, t1; + mp_bitcnt_t uz, vz, gz; + mp_bitcnt_t power; + + if (u->_mp_size == 0) + { + /* g = 0 u + sgn(v) v */ + signed long sign = mpz_sgn (v); + mpz_abs (g, v); + if (s) + mpz_set_ui (s, 0); + if (t) + mpz_set_si (t, sign); + return; + } + + if (v->_mp_size == 0) + { + /* g = sgn(u) u + 0 v */ + signed long sign = mpz_sgn (u); + mpz_abs (g, u); + if (s) + mpz_set_si (s, sign); + if (t) + mpz_set_ui (t, 0); + return; + } + + mpz_init (tu); + mpz_init (tv); + mpz_init (s0); + mpz_init (s1); + mpz_init (t0); + mpz_init (t1); + + mpz_abs (tu, u); + uz = mpz_make_odd (tu); + mpz_abs (tv, v); + vz = mpz_make_odd (tv); + gz = GMP_MIN (uz, vz); + + uz -= gz; + vz -= gz; + + /* Cofactors corresponding to odd gcd. gz handled later. */ + if (tu->_mp_size < tv->_mp_size) + { + mpz_swap (tu, tv); + MPZ_SRCPTR_SWAP (u, v); + MPZ_PTR_SWAP (s, t); + MP_BITCNT_T_SWAP (uz, vz); + } + + /* Maintain + * + * u = t0 tu + t1 tv + * v = s0 tu + s1 tv + * + * where u and v denote the inputs with common factors of two + * eliminated, and det (s0, t0; s1, t1) = 2^p. Then + * + * 2^p tu = s1 u - t1 v + * 2^p tv = -s0 u + t0 v + */ + + /* After initial division, tu = q tv + tu', we have + * + * u = 2^uz (tu' + q tv) + * v = 2^vz tv + * + * or + * + * t0 = 2^uz, t1 = 2^uz q + * s0 = 0, s1 = 2^vz + */ + + mpz_setbit (t0, uz); + mpz_tdiv_qr (t1, tu, tu, tv); + mpz_mul_2exp (t1, t1, uz); + + mpz_setbit (s1, vz); + power = uz + vz; + + if (tu->_mp_size > 0) + { + mp_bitcnt_t shift; + shift = mpz_make_odd (tu); + mpz_mul_2exp (t0, t0, shift); + mpz_mul_2exp (s0, s0, shift); + power += shift; + + for (;;) + { + int c; + c = mpz_cmp (tu, tv); + if (c == 0) + break; + + if (c < 0) + { + /* tv = tv' + tu + * + * u = t0 tu + t1 (tv' + tu) = (t0 + t1) tu + t1 tv' + * v = s0 tu + s1 (tv' + tu) = (s0 + s1) tu + s1 tv' */ + + mpz_sub (tv, tv, tu); + mpz_add (t0, t0, t1); + mpz_add (s0, s0, s1); + + shift = mpz_make_odd (tv); + mpz_mul_2exp (t1, t1, shift); + mpz_mul_2exp (s1, s1, shift); + } + else + { + mpz_sub (tu, tu, tv); + mpz_add (t1, t0, t1); + mpz_add (s1, s0, s1); + + shift = mpz_make_odd (tu); + mpz_mul_2exp (t0, t0, shift); + mpz_mul_2exp (s0, s0, shift); + } + power += shift; + } + } + + /* Now tv = odd part of gcd, and -s0 and t0 are corresponding + cofactors. */ + + mpz_mul_2exp (tv, tv, gz); + mpz_neg (s0, s0); + + /* 2^p g = s0 u + t0 v. Eliminate one factor of two at a time. To + adjust cofactors, we need u / g and v / g */ + + mpz_divexact (s1, v, tv); + mpz_abs (s1, s1); + mpz_divexact (t1, u, tv); + mpz_abs (t1, t1); + + while (power-- > 0) + { + /* s0 u + t0 v = (s0 - v/g) u - (t0 + u/g) v */ + if (mpz_odd_p (s0) || mpz_odd_p (t0)) + { + mpz_sub (s0, s0, s1); + mpz_add (t0, t0, t1); + } + mpz_divexact_ui (s0, s0, 2); + mpz_divexact_ui (t0, t0, 2); + } + + /* Arrange so that |s| < |u| / 2g */ + mpz_add (s1, s0, s1); + if (mpz_cmpabs (s0, s1) > 0) + { + mpz_swap (s0, s1); + mpz_sub (t0, t0, t1); + } + if (u->_mp_size < 0) + mpz_neg (s0, s0); + if (v->_mp_size < 0) + mpz_neg (t0, t0); + + mpz_swap (g, tv); + if (s) + mpz_swap (s, s0); + if (t) + mpz_swap (t, t0); + + mpz_clear (tu); + mpz_clear (tv); + mpz_clear (s0); + mpz_clear (s1); + mpz_clear (t0); + mpz_clear (t1); +} + +void +mpz_lcm (mpz_t r, const mpz_t u, const mpz_t v) +{ + mpz_t g; + + if (u->_mp_size == 0 || v->_mp_size == 0) + { + r->_mp_size = 0; + return; + } + + mpz_init (g); + + mpz_gcd (g, u, v); + mpz_divexact (g, u, g); + mpz_mul (r, g, v); + + mpz_clear (g); + mpz_abs (r, r); +} + +void +mpz_lcm_ui (mpz_t r, const mpz_t u, unsigned long v) +{ + if (v == 0 || u->_mp_size == 0) + { + r->_mp_size = 0; + return; + } + + v /= mpz_gcd_ui (NULL, u, v); + mpz_mul_ui (r, u, v); + + mpz_abs (r, r); +} + +int +mpz_invert (mpz_t r, const mpz_t u, const mpz_t m) +{ + mpz_t g, tr; + int invertible; + + if (u->_mp_size == 0 || mpz_cmpabs_ui (m, 1) <= 0) + return 0; + + mpz_init (g); + mpz_init (tr); + + mpz_gcdext (g, tr, NULL, u, m); + invertible = (mpz_cmp_ui (g, 1) == 0); + + if (invertible) + { + if (tr->_mp_size < 0) + { + if (m->_mp_size >= 0) + mpz_add (tr, tr, m); + else + mpz_sub (tr, tr, m); + } + mpz_swap (r, tr); + } + + mpz_clear (g); + mpz_clear (tr); + return invertible; +} + + +/* Higher level operations (sqrt, pow and root) */ + +void +mpz_pow_ui (mpz_t r, const mpz_t b, unsigned long e) +{ + unsigned long bit; + mpz_t tr; + mpz_init_set_ui (tr, 1); + + bit = GMP_ULONG_HIGHBIT; + do + { + mpz_mul (tr, tr, tr); + if (e & bit) + mpz_mul (tr, tr, b); + bit >>= 1; + } + while (bit > 0); + + mpz_swap (r, tr); + mpz_clear (tr); +} + +void +mpz_ui_pow_ui (mpz_t r, unsigned long blimb, unsigned long e) +{ + mpz_t b; + mpz_pow_ui (r, mpz_roinit_n (b, &blimb, 1), e); +} + +void +mpz_powm (mpz_t r, const mpz_t b, const mpz_t e, const mpz_t m) +{ + mpz_t tr; + mpz_t base; + mp_size_t en, mn; + mp_srcptr mp; + struct gmp_div_inverse minv; + unsigned shift; + mp_ptr tp = NULL; + + en = GMP_ABS (e->_mp_size); + mn = GMP_ABS (m->_mp_size); + if (mn == 0) + gmp_die ("mpz_powm: Zero modulo."); + + if (en == 0) + { + mpz_set_ui (r, 1); + return; + } + + mp = m->_mp_d; + mpn_div_qr_invert (&minv, mp, mn); + shift = minv.shift; + + if (shift > 0) + { + /* To avoid shifts, we do all our reductions, except the final + one, using a *normalized* m. */ + minv.shift = 0; + + tp = gmp_xalloc_limbs (mn); + gmp_assert_nocarry (mpn_lshift (tp, mp, mn, shift)); + mp = tp; + } + + mpz_init (base); + + if (e->_mp_size < 0) + { + if (!mpz_invert (base, b, m)) + gmp_die ("mpz_powm: Negative exponent and non-invertible base."); + } + else + { + mp_size_t bn; + mpz_abs (base, b); + + bn = base->_mp_size; + if (bn >= mn) + { + mpn_div_qr_preinv (NULL, base->_mp_d, base->_mp_size, mp, mn, &minv); + bn = mn; + } + + /* We have reduced the absolute value. Now take care of the + sign. Note that we get zero represented non-canonically as + m. */ + if (b->_mp_size < 0) + { + mp_ptr bp = MPZ_REALLOC (base, mn); + gmp_assert_nocarry (mpn_sub (bp, mp, mn, bp, bn)); + bn = mn; + } + base->_mp_size = mpn_normalized_size (base->_mp_d, bn); + } + mpz_init_set_ui (tr, 1); + + while (--en >= 0) + { + mp_limb_t w = e->_mp_d[en]; + mp_limb_t bit; + + bit = GMP_LIMB_HIGHBIT; + do + { + mpz_mul (tr, tr, tr); + if (w & bit) + mpz_mul (tr, tr, base); + if (tr->_mp_size > mn) + { + mpn_div_qr_preinv (NULL, tr->_mp_d, tr->_mp_size, mp, mn, &minv); + tr->_mp_size = mpn_normalized_size (tr->_mp_d, mn); + } + bit >>= 1; + } + while (bit > 0); + } + + /* Final reduction */ + if (tr->_mp_size >= mn) + { + minv.shift = shift; + mpn_div_qr_preinv (NULL, tr->_mp_d, tr->_mp_size, mp, mn, &minv); + tr->_mp_size = mpn_normalized_size (tr->_mp_d, mn); + } + if (tp) + gmp_free (tp); + + mpz_swap (r, tr); + mpz_clear (tr); + mpz_clear (base); +} + +void +mpz_powm_ui (mpz_t r, const mpz_t b, unsigned long elimb, const mpz_t m) +{ + mpz_t e; + mpz_powm (r, b, mpz_roinit_n (e, &elimb, 1), m); +} + +/* x=trunc(y^(1/z)), r=y-x^z */ +void +mpz_rootrem (mpz_t x, mpz_t r, const mpz_t y, unsigned long z) +{ + int sgn; + mpz_t t, u; + + sgn = y->_mp_size < 0; + if ((~z & sgn) != 0) + gmp_die ("mpz_rootrem: Negative argument, with even root."); + if (z == 0) + gmp_die ("mpz_rootrem: Zeroth root."); + + if (mpz_cmpabs_ui (y, 1) <= 0) { + if (x) + mpz_set (x, y); + if (r) + r->_mp_size = 0; + return; + } + + mpz_init (u); + mpz_init (t); + mpz_setbit (t, mpz_sizeinbase (y, 2) / z + 1); + + if (z == 2) /* simplify sqrt loop: z-1 == 1 */ + do { + mpz_swap (u, t); /* u = x */ + mpz_tdiv_q (t, y, u); /* t = y/x */ + mpz_add (t, t, u); /* t = y/x + x */ + mpz_tdiv_q_2exp (t, t, 1); /* x'= (y/x + x)/2 */ + } while (mpz_cmpabs (t, u) < 0); /* |x'| < |x| */ + else /* z != 2 */ { + mpz_t v; + + mpz_init (v); + if (sgn) + mpz_neg (t, t); + + do { + mpz_swap (u, t); /* u = x */ + mpz_pow_ui (t, u, z - 1); /* t = x^(z-1) */ + mpz_tdiv_q (t, y, t); /* t = y/x^(z-1) */ + mpz_mul_ui (v, u, z - 1); /* v = x*(z-1) */ + mpz_add (t, t, v); /* t = y/x^(z-1) + x*(z-1) */ + mpz_tdiv_q_ui (t, t, z); /* x'=(y/x^(z-1) + x*(z-1))/z */ + } while (mpz_cmpabs (t, u) < 0); /* |x'| < |x| */ + + mpz_clear (v); + } + + if (r) { + mpz_pow_ui (t, u, z); + mpz_sub (r, y, t); + } + if (x) + mpz_swap (x, u); + mpz_clear (u); + mpz_clear (t); +} + +int +mpz_root (mpz_t x, const mpz_t y, unsigned long z) +{ + int res; + mpz_t r; + + mpz_init (r); + mpz_rootrem (x, r, y, z); + res = r->_mp_size == 0; + mpz_clear (r); + + return res; +} + +/* Compute s = floor(sqrt(u)) and r = u - s^2. Allows r == NULL */ +void +mpz_sqrtrem (mpz_t s, mpz_t r, const mpz_t u) +{ + mpz_rootrem (s, r, u, 2); +} + +void +mpz_sqrt (mpz_t s, const mpz_t u) +{ + mpz_rootrem (s, NULL, u, 2); +} + +int +mpz_perfect_square_p (const mpz_t u) +{ + if (u->_mp_size <= 0) + return (u->_mp_size == 0); + else + return mpz_root (NULL, u, 2); +} + +int +mpn_perfect_square_p (mp_srcptr p, mp_size_t n) +{ + mpz_t t; + + assert (n > 0); + assert (p [n-1] != 0); + return mpz_root (NULL, mpz_roinit_n (t, p, n), 2); +} + +mp_size_t +mpn_sqrtrem (mp_ptr sp, mp_ptr rp, mp_srcptr p, mp_size_t n) +{ + mpz_t s, r, u; + mp_size_t res; + + assert (n > 0); + assert (p [n-1] != 0); + + mpz_init (r); + mpz_init (s); + mpz_rootrem (s, r, mpz_roinit_n (u, p, n), 2); + + assert (s->_mp_size == (n+1)/2); + mpn_copyd (sp, s->_mp_d, s->_mp_size); + mpz_clear (s); + res = r->_mp_size; + if (rp) + mpn_copyd (rp, r->_mp_d, res); + mpz_clear (r); + return res; +} + +/* Combinatorics */ + +void +mpz_fac_ui (mpz_t x, unsigned long n) +{ + mpz_set_ui (x, n + (n == 0)); + while (n > 2) + mpz_mul_ui (x, x, --n); +} + +void +mpz_bin_uiui (mpz_t r, unsigned long n, unsigned long k) +{ + mpz_t t; + + mpz_set_ui (r, k <= n); + + if (k > (n >> 1)) + k = (k <= n) ? n - k : 0; + + mpz_init (t); + mpz_fac_ui (t, k); + + for (; k > 0; k--) + mpz_mul_ui (r, r, n--); + + mpz_divexact (r, r, t); + mpz_clear (t); +} + + +/* Primality testing */ +static int +gmp_millerrabin (const mpz_t n, const mpz_t nm1, mpz_t y, + const mpz_t q, mp_bitcnt_t k) +{ + assert (k > 0); + + /* Caller must initialize y to the base. */ + mpz_powm (y, y, q, n); + + if (mpz_cmp_ui (y, 1) == 0 || mpz_cmp (y, nm1) == 0) + return 1; + + while (--k > 0) + { + mpz_powm_ui (y, y, 2, n); + if (mpz_cmp (y, nm1) == 0) + return 1; + /* y == 1 means that the previous y was a non-trivial square root + of 1 (mod n). y == 0 means that n is a power of the base. + In either case, n is not prime. */ + if (mpz_cmp_ui (y, 1) <= 0) + return 0; + } + return 0; +} + +/* This product is 0xc0cfd797, and fits in 32 bits. */ +#define GMP_PRIME_PRODUCT \ + (3UL*5UL*7UL*11UL*13UL*17UL*19UL*23UL*29UL) + +/* Bit (p+1)/2 is set, for each odd prime <= 61 */ +#define GMP_PRIME_MASK 0xc96996dcUL + +int +mpz_probab_prime_p (const mpz_t n, int reps) +{ + mpz_t nm1; + mpz_t q; + mpz_t y; + mp_bitcnt_t k; + int is_prime; + int j; + + /* Note that we use the absolute value of n only, for compatibility + with the real GMP. */ + if (mpz_even_p (n)) + return (mpz_cmpabs_ui (n, 2) == 0) ? 2 : 0; + + /* Above test excludes n == 0 */ + assert (n->_mp_size != 0); + + if (mpz_cmpabs_ui (n, 64) < 0) + return (GMP_PRIME_MASK >> (n->_mp_d[0] >> 1)) & 2; + + if (mpz_gcd_ui (NULL, n, GMP_PRIME_PRODUCT) != 1) + return 0; + + /* All prime factors are >= 31. */ + if (mpz_cmpabs_ui (n, 31*31) < 0) + return 2; + + /* Use Miller-Rabin, with a deterministic sequence of bases, a[j] = + j^2 + j + 41 using Euler's polynomial. We potentially stop early, + if a[j] >= n - 1. Since n >= 31*31, this can happen only if reps > + 30 (a[30] == 971 > 31*31 == 961). */ + + mpz_init (nm1); + mpz_init (q); + mpz_init (y); + + /* Find q and k, where q is odd and n = 1 + 2**k * q. */ + nm1->_mp_size = mpz_abs_sub_ui (nm1, n, 1); + k = mpz_scan1 (nm1, 0); + mpz_tdiv_q_2exp (q, nm1, k); + + for (j = 0, is_prime = 1; is_prime & (j < reps); j++) + { + mpz_set_ui (y, (unsigned long) j*j+j+41); + if (mpz_cmp (y, nm1) >= 0) + { + /* Don't try any further bases. This "early" break does not affect + the result for any reasonable reps value (<=5000 was tested) */ + assert (j >= 30); + break; + } + is_prime = gmp_millerrabin (n, nm1, y, q, k); + } + mpz_clear (nm1); + mpz_clear (q); + mpz_clear (y); + + return is_prime; +} + + +/* Logical operations and bit manipulation. */ + +/* Numbers are treated as if represented in two's complement (and + infinitely sign extended). For a negative values we get the two's + complement from -x = ~x + 1, where ~ is bitwise complement. + Negation transforms + + xxxx10...0 + + into + + yyyy10...0 + + where yyyy is the bitwise complement of xxxx. So least significant + bits, up to and including the first one bit, are unchanged, and + the more significant bits are all complemented. + + To change a bit from zero to one in a negative number, subtract the + corresponding power of two from the absolute value. This can never + underflow. To change a bit from one to zero, add the corresponding + power of two, and this might overflow. E.g., if x = -001111, the + two's complement is 110001. Clearing the least significant bit, we + get two's complement 110000, and -010000. */ + +int +mpz_tstbit (const mpz_t d, mp_bitcnt_t bit_index) +{ + mp_size_t limb_index; + unsigned shift; + mp_size_t ds; + mp_size_t dn; + mp_limb_t w; + int bit; + + ds = d->_mp_size; + dn = GMP_ABS (ds); + limb_index = bit_index / GMP_LIMB_BITS; + if (limb_index >= dn) + return ds < 0; + + shift = bit_index % GMP_LIMB_BITS; + w = d->_mp_d[limb_index]; + bit = (w >> shift) & 1; + + if (ds < 0) + { + /* d < 0. Check if any of the bits below is set: If so, our bit + must be complemented. */ + if (shift > 0 && (w << (GMP_LIMB_BITS - shift)) > 0) + return bit ^ 1; + while (--limb_index >= 0) + if (d->_mp_d[limb_index] > 0) + return bit ^ 1; + } + return bit; +} + +static void +mpz_abs_add_bit (mpz_t d, mp_bitcnt_t bit_index) +{ + mp_size_t dn, limb_index; + mp_limb_t bit; + mp_ptr dp; + + dn = GMP_ABS (d->_mp_size); + + limb_index = bit_index / GMP_LIMB_BITS; + bit = (mp_limb_t) 1 << (bit_index % GMP_LIMB_BITS); + + if (limb_index >= dn) + { + mp_size_t i; + /* The bit should be set outside of the end of the number. + We have to increase the size of the number. */ + dp = MPZ_REALLOC (d, limb_index + 1); + + dp[limb_index] = bit; + for (i = dn; i < limb_index; i++) + dp[i] = 0; + dn = limb_index + 1; + } + else + { + mp_limb_t cy; + + dp = d->_mp_d; + + cy = mpn_add_1 (dp + limb_index, dp + limb_index, dn - limb_index, bit); + if (cy > 0) + { + dp = MPZ_REALLOC (d, dn + 1); + dp[dn++] = cy; + } + } + + d->_mp_size = (d->_mp_size < 0) ? - dn : dn; +} + +static void +mpz_abs_sub_bit (mpz_t d, mp_bitcnt_t bit_index) +{ + mp_size_t dn, limb_index; + mp_ptr dp; + mp_limb_t bit; + + dn = GMP_ABS (d->_mp_size); + dp = d->_mp_d; + + limb_index = bit_index / GMP_LIMB_BITS; + bit = (mp_limb_t) 1 << (bit_index % GMP_LIMB_BITS); + + assert (limb_index < dn); + + gmp_assert_nocarry (mpn_sub_1 (dp + limb_index, dp + limb_index, + dn - limb_index, bit)); + dn = mpn_normalized_size (dp, dn); + d->_mp_size = (d->_mp_size < 0) ? - dn : dn; +} + +void +mpz_setbit (mpz_t d, mp_bitcnt_t bit_index) +{ + if (!mpz_tstbit (d, bit_index)) + { + if (d->_mp_size >= 0) + mpz_abs_add_bit (d, bit_index); + else + mpz_abs_sub_bit (d, bit_index); + } +} + +void +mpz_clrbit (mpz_t d, mp_bitcnt_t bit_index) +{ + if (mpz_tstbit (d, bit_index)) + { + if (d->_mp_size >= 0) + mpz_abs_sub_bit (d, bit_index); + else + mpz_abs_add_bit (d, bit_index); + } +} + +void +mpz_combit (mpz_t d, mp_bitcnt_t bit_index) +{ + if (mpz_tstbit (d, bit_index) ^ (d->_mp_size < 0)) + mpz_abs_sub_bit (d, bit_index); + else + mpz_abs_add_bit (d, bit_index); +} + +void +mpz_com (mpz_t r, const mpz_t u) +{ + mpz_neg (r, u); + mpz_sub_ui (r, r, 1); +} + +void +mpz_and (mpz_t r, const mpz_t u, const mpz_t v) +{ + mp_size_t un, vn, rn, i; + mp_ptr up, vp, rp; + + mp_limb_t ux, vx, rx; + mp_limb_t uc, vc, rc; + mp_limb_t ul, vl, rl; + + un = GMP_ABS (u->_mp_size); + vn = GMP_ABS (v->_mp_size); + if (un < vn) + { + MPZ_SRCPTR_SWAP (u, v); + MP_SIZE_T_SWAP (un, vn); + } + if (vn == 0) + { + r->_mp_size = 0; + return; + } + + uc = u->_mp_size < 0; + vc = v->_mp_size < 0; + rc = uc & vc; + + ux = -uc; + vx = -vc; + rx = -rc; + + /* If the smaller input is positive, higher limbs don't matter. */ + rn = vx ? un : vn; + + rp = MPZ_REALLOC (r, rn + (mp_size_t) rc); + + up = u->_mp_d; + vp = v->_mp_d; + + i = 0; + do + { + ul = (up[i] ^ ux) + uc; + uc = ul < uc; + + vl = (vp[i] ^ vx) + vc; + vc = vl < vc; + + rl = ( (ul & vl) ^ rx) + rc; + rc = rl < rc; + rp[i] = rl; + } + while (++i < vn); + assert (vc == 0); + + for (; i < rn; i++) + { + ul = (up[i] ^ ux) + uc; + uc = ul < uc; + + rl = ( (ul & vx) ^ rx) + rc; + rc = rl < rc; + rp[i] = rl; + } + if (rc) + rp[rn++] = rc; + else + rn = mpn_normalized_size (rp, rn); + + r->_mp_size = rx ? -rn : rn; +} + +void +mpz_ior (mpz_t r, const mpz_t u, const mpz_t v) +{ + mp_size_t un, vn, rn, i; + mp_ptr up, vp, rp; + + mp_limb_t ux, vx, rx; + mp_limb_t uc, vc, rc; + mp_limb_t ul, vl, rl; + + un = GMP_ABS (u->_mp_size); + vn = GMP_ABS (v->_mp_size); + if (un < vn) + { + MPZ_SRCPTR_SWAP (u, v); + MP_SIZE_T_SWAP (un, vn); + } + if (vn == 0) + { + mpz_set (r, u); + return; + } + + uc = u->_mp_size < 0; + vc = v->_mp_size < 0; + rc = uc | vc; + + ux = -uc; + vx = -vc; + rx = -rc; + + /* If the smaller input is negative, by sign extension higher limbs + don't matter. */ + rn = vx ? vn : un; + + rp = MPZ_REALLOC (r, rn + (mp_size_t) rc); + + up = u->_mp_d; + vp = v->_mp_d; + + i = 0; + do + { + ul = (up[i] ^ ux) + uc; + uc = ul < uc; + + vl = (vp[i] ^ vx) + vc; + vc = vl < vc; + + rl = ( (ul | vl) ^ rx) + rc; + rc = rl < rc; + rp[i] = rl; + } + while (++i < vn); + assert (vc == 0); + + for (; i < rn; i++) + { + ul = (up[i] ^ ux) + uc; + uc = ul < uc; + + rl = ( (ul | vx) ^ rx) + rc; + rc = rl < rc; + rp[i] = rl; + } + if (rc) + rp[rn++] = rc; + else + rn = mpn_normalized_size (rp, rn); + + r->_mp_size = rx ? -rn : rn; +} + +void +mpz_xor (mpz_t r, const mpz_t u, const mpz_t v) +{ + mp_size_t un, vn, i; + mp_ptr up, vp, rp; + + mp_limb_t ux, vx, rx; + mp_limb_t uc, vc, rc; + mp_limb_t ul, vl, rl; + + un = GMP_ABS (u->_mp_size); + vn = GMP_ABS (v->_mp_size); + if (un < vn) + { + MPZ_SRCPTR_SWAP (u, v); + MP_SIZE_T_SWAP (un, vn); + } + if (vn == 0) + { + mpz_set (r, u); + return; + } + + uc = u->_mp_size < 0; + vc = v->_mp_size < 0; + rc = uc ^ vc; + + ux = -uc; + vx = -vc; + rx = -rc; + + rp = MPZ_REALLOC (r, un + (mp_size_t) rc); + + up = u->_mp_d; + vp = v->_mp_d; + + i = 0; + do + { + ul = (up[i] ^ ux) + uc; + uc = ul < uc; + + vl = (vp[i] ^ vx) + vc; + vc = vl < vc; + + rl = (ul ^ vl ^ rx) + rc; + rc = rl < rc; + rp[i] = rl; + } + while (++i < vn); + assert (vc == 0); + + for (; i < un; i++) + { + ul = (up[i] ^ ux) + uc; + uc = ul < uc; + + rl = (ul ^ ux) + rc; + rc = rl < rc; + rp[i] = rl; + } + if (rc) + rp[un++] = rc; + else + un = mpn_normalized_size (rp, un); + + r->_mp_size = rx ? -un : un; +} + +static unsigned +gmp_popcount_limb (mp_limb_t x) +{ + unsigned c; + + /* Do 16 bits at a time, to avoid limb-sized constants. */ + for (c = 0; x > 0; x >>= 16) + { + unsigned w = ((x >> 1) & 0x5555) + (x & 0x5555); + w = ((w >> 2) & 0x3333) + (w & 0x3333); + w = ((w >> 4) & 0x0f0f) + (w & 0x0f0f); + w = (w >> 8) + (w & 0x00ff); + c += w; + } + return c; +} + +mp_bitcnt_t +mpn_popcount (mp_srcptr p, mp_size_t n) +{ + mp_size_t i; + mp_bitcnt_t c; + + for (c = 0, i = 0; i < n; i++) + c += gmp_popcount_limb (p[i]); + + return c; +} + +mp_bitcnt_t +mpz_popcount (const mpz_t u) +{ + mp_size_t un; + + un = u->_mp_size; + + if (un < 0) + return ~(mp_bitcnt_t) 0; + + return mpn_popcount (u->_mp_d, un); +} + +mp_bitcnt_t +mpz_hamdist (const mpz_t u, const mpz_t v) +{ + mp_size_t un, vn, i; + mp_limb_t uc, vc, ul, vl, comp; + mp_srcptr up, vp; + mp_bitcnt_t c; + + un = u->_mp_size; + vn = v->_mp_size; + + if ( (un ^ vn) < 0) + return ~(mp_bitcnt_t) 0; + + comp = - (uc = vc = (un < 0)); + if (uc) + { + assert (vn < 0); + un = -un; + vn = -vn; + } + + up = u->_mp_d; + vp = v->_mp_d; + + if (un < vn) + MPN_SRCPTR_SWAP (up, un, vp, vn); + + for (i = 0, c = 0; i < vn; i++) + { + ul = (up[i] ^ comp) + uc; + uc = ul < uc; + + vl = (vp[i] ^ comp) + vc; + vc = vl < vc; + + c += gmp_popcount_limb (ul ^ vl); + } + assert (vc == 0); + + for (; i < un; i++) + { + ul = (up[i] ^ comp) + uc; + uc = ul < uc; + + c += gmp_popcount_limb (ul ^ comp); + } + + return c; +} + +mp_bitcnt_t +mpz_scan1 (const mpz_t u, mp_bitcnt_t starting_bit) +{ + mp_ptr up; + mp_size_t us, un, i; + mp_limb_t limb, ux; + + us = u->_mp_size; + un = GMP_ABS (us); + i = starting_bit / GMP_LIMB_BITS; + + /* Past the end there's no 1 bits for u>=0, or an immediate 1 bit + for u<0. Notice this test picks up any u==0 too. */ + if (i >= un) + return (us >= 0 ? ~(mp_bitcnt_t) 0 : starting_bit); + + up = u->_mp_d; + ux = 0; + limb = up[i]; + + if (starting_bit != 0) + { + if (us < 0) + { + ux = mpn_zero_p (up, i); + limb = ~ limb + ux; + ux = - (mp_limb_t) (limb >= ux); + } + + /* Mask to 0 all bits before starting_bit, thus ignoring them. */ + limb &= (GMP_LIMB_MAX << (starting_bit % GMP_LIMB_BITS)); + } + + return mpn_common_scan (limb, i, up, un, ux); +} + +mp_bitcnt_t +mpz_scan0 (const mpz_t u, mp_bitcnt_t starting_bit) +{ + mp_ptr up; + mp_size_t us, un, i; + mp_limb_t limb, ux; + + us = u->_mp_size; + ux = - (mp_limb_t) (us >= 0); + un = GMP_ABS (us); + i = starting_bit / GMP_LIMB_BITS; + + /* When past end, there's an immediate 0 bit for u>=0, or no 0 bits for + u<0. Notice this test picks up all cases of u==0 too. */ + if (i >= un) + return (ux ? starting_bit : ~(mp_bitcnt_t) 0); + + up = u->_mp_d; + limb = up[i] ^ ux; + + if (ux == 0) + limb -= mpn_zero_p (up, i); /* limb = ~(~limb + zero_p) */ + + /* Mask all bits before starting_bit, thus ignoring them. */ + limb &= (GMP_LIMB_MAX << (starting_bit % GMP_LIMB_BITS)); + + return mpn_common_scan (limb, i, up, un, ux); +} + + +/* MPZ base conversion. */ + +size_t +mpz_sizeinbase (const mpz_t u, int base) +{ + mp_size_t un; + mp_srcptr up; + mp_ptr tp; + mp_bitcnt_t bits; + struct gmp_div_inverse bi; + size_t ndigits; + + assert (base >= 2); + assert (base <= 36); + + un = GMP_ABS (u->_mp_size); + if (un == 0) + return 1; + + up = u->_mp_d; + + bits = (un - 1) * GMP_LIMB_BITS + mpn_limb_size_in_base_2 (up[un-1]); + switch (base) + { + case 2: + return bits; + case 4: + return (bits + 1) / 2; + case 8: + return (bits + 2) / 3; + case 16: + return (bits + 3) / 4; + case 32: + return (bits + 4) / 5; + /* FIXME: Do something more clever for the common case of base + 10. */ + } + + tp = gmp_xalloc_limbs (un); + mpn_copyi (tp, up, un); + mpn_div_qr_1_invert (&bi, base); + + ndigits = 0; + do + { + ndigits++; + mpn_div_qr_1_preinv (tp, tp, un, &bi); + un -= (tp[un-1] == 0); + } + while (un > 0); + + gmp_free (tp); + return ndigits; +} + +char * +mpz_get_str (char *sp, int base, const mpz_t u) +{ + unsigned bits; + const char *digits; + mp_size_t un; + size_t i, sn; + + if (base >= 0) + { + digits = "0123456789abcdefghijklmnopqrstuvwxyz"; + } + else + { + base = -base; + digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + } + if (base <= 1) + base = 10; + if (base > 36) + return NULL; + + sn = 1 + mpz_sizeinbase (u, base); + if (!sp) + sp = (char *) gmp_xalloc (1 + sn); + + un = GMP_ABS (u->_mp_size); + + if (un == 0) + { + sp[0] = '0'; + sp[1] = '\0'; + return sp; + } + + i = 0; + + if (u->_mp_size < 0) + sp[i++] = '-'; + + bits = mpn_base_power_of_two_p (base); + + if (bits) + /* Not modified in this case. */ + sn = i + mpn_get_str_bits ((unsigned char *) sp + i, bits, u->_mp_d, un); + else + { + struct mpn_base_info info; + mp_ptr tp; + + mpn_get_base_info (&info, base); + tp = gmp_xalloc_limbs (un); + mpn_copyi (tp, u->_mp_d, un); + + sn = i + mpn_get_str_other ((unsigned char *) sp + i, base, &info, tp, un); + gmp_free (tp); + } + + for (; i < sn; i++) + sp[i] = digits[(unsigned char) sp[i]]; + + sp[sn] = '\0'; + return sp; +} + +int +mpz_set_str (mpz_t r, const char *sp, int base) +{ + unsigned bits; + mp_size_t rn, alloc; + mp_ptr rp; + size_t dn; + int sign; + unsigned char *dp; + + assert (base == 0 || (base >= 2 && base <= 36)); + + while (isspace( (unsigned char) *sp)) + sp++; + + sign = (*sp == '-'); + sp += sign; + + if (base == 0) + { + if (sp[0] == '0') + { + if (sp[1] == 'x' || sp[1] == 'X') + { + base = 16; + sp += 2; + } + else if (sp[1] == 'b' || sp[1] == 'B') + { + base = 2; + sp += 2; + } + else + base = 8; + } + else + base = 10; + } + + if (!*sp) + { + r->_mp_size = 0; + return -1; + } + dp = (unsigned char *) gmp_xalloc (strlen (sp)); + + for (dn = 0; *sp; sp++) + { + unsigned digit; + + if (isspace ((unsigned char) *sp)) + continue; + else if (*sp >= '0' && *sp <= '9') + digit = *sp - '0'; + else if (*sp >= 'a' && *sp <= 'z') + digit = *sp - 'a' + 10; + else if (*sp >= 'A' && *sp <= 'Z') + digit = *sp - 'A' + 10; + else + digit = base; /* fail */ + + if (digit >= (unsigned) base) + { + gmp_free (dp); + r->_mp_size = 0; + return -1; + } + + dp[dn++] = digit; + } + + if (!dn) + { + gmp_free (dp); + r->_mp_size = 0; + return -1; + } + bits = mpn_base_power_of_two_p (base); + + if (bits > 0) + { + alloc = (dn * bits + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS; + rp = MPZ_REALLOC (r, alloc); + rn = mpn_set_str_bits (rp, dp, dn, bits); + } + else + { + struct mpn_base_info info; + mpn_get_base_info (&info, base); + alloc = (dn + info.exp - 1) / info.exp; + rp = MPZ_REALLOC (r, alloc); + rn = mpn_set_str_other (rp, dp, dn, base, &info); + /* Normalization, needed for all-zero input. */ + assert (rn > 0); + rn -= rp[rn-1] == 0; + } + assert (rn <= alloc); + gmp_free (dp); + + r->_mp_size = sign ? - rn : rn; + + return 0; +} + +int +mpz_init_set_str (mpz_t r, const char *sp, int base) +{ + mpz_init (r); + return mpz_set_str (r, sp, base); +} + +size_t +mpz_out_str (FILE *stream, int base, const mpz_t x) +{ + char *str; + size_t len; + + str = mpz_get_str (NULL, base, x); + len = strlen (str); + len = fwrite (str, 1, len, stream); + gmp_free (str); + return len; +} + + +static int +gmp_detect_endian (void) +{ + static const int i = 2; + const unsigned char *p = (const unsigned char *) &i; + return 1 - *p; +} + +/* Import and export. Does not support nails. */ +void +mpz_import (mpz_t r, size_t count, int order, size_t size, int endian, + size_t nails, const void *src) +{ + const unsigned char *p; + ptrdiff_t word_step; + mp_ptr rp; + mp_size_t rn; + + /* The current (partial) limb. */ + mp_limb_t limb; + /* The number of bytes already copied to this limb (starting from + the low end). */ + size_t bytes; + /* The index where the limb should be stored, when completed. */ + mp_size_t i; + + if (nails != 0) + gmp_die ("mpz_import: Nails not supported."); + + assert (order == 1 || order == -1); + assert (endian >= -1 && endian <= 1); + + if (endian == 0) + endian = gmp_detect_endian (); + + p = (unsigned char *) src; + + word_step = (order != endian) ? 2 * size : 0; + + /* Process bytes from the least significant end, so point p at the + least significant word. */ + if (order == 1) + { + p += size * (count - 1); + word_step = - word_step; + } + + /* And at least significant byte of that word. */ + if (endian == 1) + p += (size - 1); + + rn = (size * count + sizeof(mp_limb_t) - 1) / sizeof(mp_limb_t); + rp = MPZ_REALLOC (r, rn); + + for (limb = 0, bytes = 0, i = 0; count > 0; count--, p += word_step) + { + size_t j; + for (j = 0; j < size; j++, p -= (ptrdiff_t) endian) + { + limb |= (mp_limb_t) *p << (bytes++ * CHAR_BIT); + if (bytes == sizeof(mp_limb_t)) + { + rp[i++] = limb; + bytes = 0; + limb = 0; + } + } + } + assert (i + (bytes > 0) == rn); + if (limb != 0) + rp[i++] = limb; + else + i = mpn_normalized_size (rp, i); + + r->_mp_size = i; +} + +void * +mpz_export (void *r, size_t *countp, int order, size_t size, int endian, + size_t nails, const mpz_t u) +{ + size_t count; + mp_size_t un; + + if (nails != 0) + gmp_die ("mpz_import: Nails not supported."); + + assert (order == 1 || order == -1); + assert (endian >= -1 && endian <= 1); + assert (size > 0 || u->_mp_size == 0); + + un = u->_mp_size; + count = 0; + if (un != 0) + { + size_t k; + unsigned char *p; + ptrdiff_t word_step; + /* The current (partial) limb. */ + mp_limb_t limb; + /* The number of bytes left to to in this limb. */ + size_t bytes; + /* The index where the limb was read. */ + mp_size_t i; + + un = GMP_ABS (un); + + /* Count bytes in top limb. */ + limb = u->_mp_d[un-1]; + assert (limb != 0); + + k = 0; + do { + k++; limb >>= CHAR_BIT; + } while (limb != 0); + + count = (k + (un-1) * sizeof (mp_limb_t) + size - 1) / size; + + if (!r) + r = gmp_xalloc (count * size); + + if (endian == 0) + endian = gmp_detect_endian (); + + p = (unsigned char *) r; + + word_step = (order != endian) ? 2 * size : 0; + + /* Process bytes from the least significant end, so point p at the + least significant word. */ + if (order == 1) + { + p += size * (count - 1); + word_step = - word_step; + } + + /* And at least significant byte of that word. */ + if (endian == 1) + p += (size - 1); + + for (bytes = 0, i = 0, k = 0; k < count; k++, p += word_step) + { + size_t j; + for (j = 0; j < size; j++, p -= (ptrdiff_t) endian) + { + if (bytes == 0) + { + if (i < un) + limb = u->_mp_d[i++]; + bytes = sizeof (mp_limb_t); + } + *p = limb; + limb >>= CHAR_BIT; + bytes--; + } + } + assert (i == un); + assert (k == count); + } + + if (countp) + *countp = count; + + return r; +} diff --git a/examples/multiprecision/mini-gmp/mini-gmp.h b/examples/multiprecision/mini-gmp/mini-gmp.h new file mode 100644 index 0000000000000000000000000000000000000000..bb5c6371d93e66e28519c627f893b8d474146a57 --- /dev/null +++ b/examples/multiprecision/mini-gmp/mini-gmp.h @@ -0,0 +1,298 @@ +/* mini-gmp, a minimalistic implementation of a GNU GMP subset. + +Copyright 2011-2015 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + +or + + * the GNU General Public License as published by the Free Software + Foundation; either version 2 of the License, or (at your option) any + later version. + +or both in parallel, as here. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received copies of the GNU General Public License and the +GNU Lesser General Public License along with the GNU MP Library. If not, +see https://www.gnu.org/licenses/. */ + +/* About mini-gmp: This is a minimal implementation of a subset of the + GMP interface. It is intended for inclusion into applications which + have modest bignums needs, as a fallback when the real GMP library + is not installed. + + This file defines the public interface. */ + +#ifndef __MINI_GMP_H__ +#define __MINI_GMP_H__ + +/* For size_t */ +#include <stddef.h> + +#if defined (__cplusplus) +extern "C" { +#endif + +void mp_set_memory_functions (void *(*) (size_t), + void *(*) (void *, size_t, size_t), + void (*) (void *, size_t)); + +void mp_get_memory_functions (void *(**) (size_t), + void *(**) (void *, size_t, size_t), + void (**) (void *, size_t)); + +typedef unsigned long mp_limb_t; +typedef long mp_size_t; +typedef unsigned long mp_bitcnt_t; + +typedef mp_limb_t *mp_ptr; +typedef const mp_limb_t *mp_srcptr; + +typedef struct +{ + int _mp_alloc; /* Number of *limbs* allocated and pointed + to by the _mp_d field. */ + int _mp_size; /* abs(_mp_size) is the number of limbs the + last field points to. If _mp_size is + negative this is a negative number. */ + mp_limb_t *_mp_d; /* Pointer to the limbs. */ +} __mpz_struct; + +typedef __mpz_struct mpz_t[1]; + +typedef __mpz_struct *mpz_ptr; +typedef const __mpz_struct *mpz_srcptr; + +extern const int mp_bits_per_limb; + +void mpn_copyi (mp_ptr, mp_srcptr, mp_size_t); +void mpn_copyd (mp_ptr, mp_srcptr, mp_size_t); +void mpn_zero (mp_ptr, mp_size_t); + +int mpn_cmp (mp_srcptr, mp_srcptr, mp_size_t); +int mpn_zero_p (mp_srcptr, mp_size_t); + +mp_limb_t mpn_add_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); +mp_limb_t mpn_add_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +mp_limb_t mpn_add (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); + +mp_limb_t mpn_sub_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); +mp_limb_t mpn_sub_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +mp_limb_t mpn_sub (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); + +mp_limb_t mpn_mul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); +mp_limb_t mpn_addmul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); +mp_limb_t mpn_submul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); + +mp_limb_t mpn_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); +void mpn_mul_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +void mpn_sqr (mp_ptr, mp_srcptr, mp_size_t); +int mpn_perfect_square_p (mp_srcptr, mp_size_t); +mp_size_t mpn_sqrtrem (mp_ptr, mp_ptr, mp_srcptr, mp_size_t); + +mp_limb_t mpn_lshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int); +mp_limb_t mpn_rshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int); + +mp_bitcnt_t mpn_scan0 (mp_srcptr, mp_bitcnt_t); +mp_bitcnt_t mpn_scan1 (mp_srcptr, mp_bitcnt_t); + +void mpn_com (mp_ptr, mp_srcptr, mp_size_t); +mp_limb_t mpn_neg (mp_ptr, mp_srcptr, mp_size_t); + +mp_bitcnt_t mpn_popcount (mp_srcptr, mp_size_t); + +mp_limb_t mpn_invert_3by2 (mp_limb_t, mp_limb_t); +#define mpn_invert_limb(x) mpn_invert_3by2 ((x), 0) + +size_t mpn_get_str (unsigned char *, int, mp_ptr, mp_size_t); +mp_size_t mpn_set_str (mp_ptr, const unsigned char *, size_t, int); + +void mpz_init (mpz_t); +void mpz_init2 (mpz_t, mp_bitcnt_t); +void mpz_clear (mpz_t); + +#define mpz_odd_p(z) (((z)->_mp_size != 0) & (int) (z)->_mp_d[0]) +#define mpz_even_p(z) (! mpz_odd_p (z)) + +int mpz_sgn (const mpz_t); +int mpz_cmp_si (const mpz_t, long); +int mpz_cmp_ui (const mpz_t, unsigned long); +int mpz_cmp (const mpz_t, const mpz_t); +int mpz_cmpabs_ui (const mpz_t, unsigned long); +int mpz_cmpabs (const mpz_t, const mpz_t); +int mpz_cmp_d (const mpz_t, double); +int mpz_cmpabs_d (const mpz_t, double); + +void mpz_abs (mpz_t, const mpz_t); +void mpz_neg (mpz_t, const mpz_t); +void mpz_swap (mpz_t, mpz_t); + +void mpz_add_ui (mpz_t, const mpz_t, unsigned long); +void mpz_add (mpz_t, const mpz_t, const mpz_t); +void mpz_sub_ui (mpz_t, const mpz_t, unsigned long); +void mpz_ui_sub (mpz_t, unsigned long, const mpz_t); +void mpz_sub (mpz_t, const mpz_t, const mpz_t); + +void mpz_mul_si (mpz_t, const mpz_t, long int); +void mpz_mul_ui (mpz_t, const mpz_t, unsigned long int); +void mpz_mul (mpz_t, const mpz_t, const mpz_t); +void mpz_mul_2exp (mpz_t, const mpz_t, mp_bitcnt_t); +void mpz_addmul_ui (mpz_t, const mpz_t, unsigned long int); +void mpz_addmul (mpz_t, const mpz_t, const mpz_t); +void mpz_submul_ui (mpz_t, const mpz_t, unsigned long int); +void mpz_submul (mpz_t, const mpz_t, const mpz_t); + +void mpz_cdiv_qr (mpz_t, mpz_t, const mpz_t, const mpz_t); +void mpz_fdiv_qr (mpz_t, mpz_t, const mpz_t, const mpz_t); +void mpz_tdiv_qr (mpz_t, mpz_t, const mpz_t, const mpz_t); +void mpz_cdiv_q (mpz_t, const mpz_t, const mpz_t); +void mpz_fdiv_q (mpz_t, const mpz_t, const mpz_t); +void mpz_tdiv_q (mpz_t, const mpz_t, const mpz_t); +void mpz_cdiv_r (mpz_t, const mpz_t, const mpz_t); +void mpz_fdiv_r (mpz_t, const mpz_t, const mpz_t); +void mpz_tdiv_r (mpz_t, const mpz_t, const mpz_t); + +void mpz_cdiv_q_2exp (mpz_t, const mpz_t, mp_bitcnt_t); +void mpz_fdiv_q_2exp (mpz_t, const mpz_t, mp_bitcnt_t); +void mpz_tdiv_q_2exp (mpz_t, const mpz_t, mp_bitcnt_t); +void mpz_cdiv_r_2exp (mpz_t, const mpz_t, mp_bitcnt_t); +void mpz_fdiv_r_2exp (mpz_t, const mpz_t, mp_bitcnt_t); +void mpz_tdiv_r_2exp (mpz_t, const mpz_t, mp_bitcnt_t); + +void mpz_mod (mpz_t, const mpz_t, const mpz_t); + +void mpz_divexact (mpz_t, const mpz_t, const mpz_t); + +int mpz_divisible_p (const mpz_t, const mpz_t); +int mpz_congruent_p (const mpz_t, const mpz_t, const mpz_t); + +unsigned long mpz_cdiv_qr_ui (mpz_t, mpz_t, const mpz_t, unsigned long); +unsigned long mpz_fdiv_qr_ui (mpz_t, mpz_t, const mpz_t, unsigned long); +unsigned long mpz_tdiv_qr_ui (mpz_t, mpz_t, const mpz_t, unsigned long); +unsigned long mpz_cdiv_q_ui (mpz_t, const mpz_t, unsigned long); +unsigned long mpz_fdiv_q_ui (mpz_t, const mpz_t, unsigned long); +unsigned long mpz_tdiv_q_ui (mpz_t, const mpz_t, unsigned long); +unsigned long mpz_cdiv_r_ui (mpz_t, const mpz_t, unsigned long); +unsigned long mpz_fdiv_r_ui (mpz_t, const mpz_t, unsigned long); +unsigned long mpz_tdiv_r_ui (mpz_t, const mpz_t, unsigned long); +unsigned long mpz_cdiv_ui (const mpz_t, unsigned long); +unsigned long mpz_fdiv_ui (const mpz_t, unsigned long); +unsigned long mpz_tdiv_ui (const mpz_t, unsigned long); + +unsigned long mpz_mod_ui (mpz_t, const mpz_t, unsigned long); + +void mpz_divexact_ui (mpz_t, const mpz_t, unsigned long); + +int mpz_divisible_ui_p (const mpz_t, unsigned long); + +unsigned long mpz_gcd_ui (mpz_t, const mpz_t, unsigned long); +void mpz_gcd (mpz_t, const mpz_t, const mpz_t); +void mpz_gcdext (mpz_t, mpz_t, mpz_t, const mpz_t, const mpz_t); +void mpz_lcm_ui (mpz_t, const mpz_t, unsigned long); +void mpz_lcm (mpz_t, const mpz_t, const mpz_t); +int mpz_invert (mpz_t, const mpz_t, const mpz_t); + +void mpz_sqrtrem (mpz_t, mpz_t, const mpz_t); +void mpz_sqrt (mpz_t, const mpz_t); +int mpz_perfect_square_p (const mpz_t); + +void mpz_pow_ui (mpz_t, const mpz_t, unsigned long); +void mpz_ui_pow_ui (mpz_t, unsigned long, unsigned long); +void mpz_powm (mpz_t, const mpz_t, const mpz_t, const mpz_t); +void mpz_powm_ui (mpz_t, const mpz_t, unsigned long, const mpz_t); + +void mpz_rootrem (mpz_t, mpz_t, const mpz_t, unsigned long); +int mpz_root (mpz_t, const mpz_t, unsigned long); + +void mpz_fac_ui (mpz_t, unsigned long); +void mpz_bin_uiui (mpz_t, unsigned long, unsigned long); + +int mpz_probab_prime_p (const mpz_t, int); + +int mpz_tstbit (const mpz_t, mp_bitcnt_t); +void mpz_setbit (mpz_t, mp_bitcnt_t); +void mpz_clrbit (mpz_t, mp_bitcnt_t); +void mpz_combit (mpz_t, mp_bitcnt_t); + +void mpz_com (mpz_t, const mpz_t); +void mpz_and (mpz_t, const mpz_t, const mpz_t); +void mpz_ior (mpz_t, const mpz_t, const mpz_t); +void mpz_xor (mpz_t, const mpz_t, const mpz_t); + +mp_bitcnt_t mpz_popcount (const mpz_t); +mp_bitcnt_t mpz_hamdist (const mpz_t, const mpz_t); +mp_bitcnt_t mpz_scan0 (const mpz_t, mp_bitcnt_t); +mp_bitcnt_t mpz_scan1 (const mpz_t, mp_bitcnt_t); + +int mpz_fits_slong_p (const mpz_t); +int mpz_fits_ulong_p (const mpz_t); +long int mpz_get_si (const mpz_t); +unsigned long int mpz_get_ui (const mpz_t); +double mpz_get_d (const mpz_t); +size_t mpz_size (const mpz_t); +mp_limb_t mpz_getlimbn (const mpz_t, mp_size_t); + +void mpz_realloc2 (mpz_t, mp_bitcnt_t); +mp_srcptr mpz_limbs_read (mpz_srcptr); +mp_ptr mpz_limbs_modify (mpz_t, mp_size_t); +mp_ptr mpz_limbs_write (mpz_t, mp_size_t); +void mpz_limbs_finish (mpz_t, mp_size_t); +mpz_srcptr mpz_roinit_n (mpz_t, mp_srcptr, mp_size_t); + +#define MPZ_ROINIT_N(xp, xs) {{0, (xs),(xp) }} + +void mpz_set_si (mpz_t, signed long int); +void mpz_set_ui (mpz_t, unsigned long int); +void mpz_set (mpz_t, const mpz_t); +void mpz_set_d (mpz_t, double); + +void mpz_init_set_si (mpz_t, signed long int); +void mpz_init_set_ui (mpz_t, unsigned long int); +void mpz_init_set (mpz_t, const mpz_t); +void mpz_init_set_d (mpz_t, double); + +size_t mpz_sizeinbase (const mpz_t, int); +char *mpz_get_str (char *, int, const mpz_t); +int mpz_set_str (mpz_t, const char *, int); +int mpz_init_set_str (mpz_t, const char *, int); + +/* This long list taken from gmp.h. */ +/* For reference, "defined(EOF)" cannot be used here. In g++ 2.95.4, + <iostream> defines EOF but not FILE. */ +#if defined (FILE) \ + || defined (H_STDIO) \ + || defined (_H_STDIO) /* AIX */ \ + || defined (_STDIO_H) /* glibc, Sun, SCO */ \ + || defined (_STDIO_H_) /* BSD, OSF */ \ + || defined (__STDIO_H) /* Borland */ \ + || defined (__STDIO_H__) /* IRIX */ \ + || defined (_STDIO_INCLUDED) /* HPUX */ \ + || defined (__dj_include_stdio_h_) /* DJGPP */ \ + || defined (_FILE_DEFINED) /* Microsoft */ \ + || defined (__STDIO__) /* Apple MPW MrC */ \ + || defined (_MSL_STDIO_H) /* Metrowerks */ \ + || defined (_STDIO_H_INCLUDED) /* QNX4 */ \ + || defined (_ISO_STDIO_ISO_H) /* Sun C++ */ \ + || defined (__STDIO_LOADED) /* VMS */ +size_t mpz_out_str (FILE *, int, const mpz_t); +#endif + +void mpz_import (mpz_t, size_t, int, size_t, int, size_t, const void *); +void *mpz_export (void *, size_t *, int, size_t, int, size_t, const mpz_t); + +#if defined (__cplusplus) +} +#endif +#endif /* __MINI_GMP_H__ */ diff --git a/examples/multiprecision/random/mt19937-64.c b/examples/multiprecision/random/mt19937-64.c new file mode 100644 index 0000000000000000000000000000000000000000..006421daa74ae2554887c2a54991c7d931f62275 --- /dev/null +++ b/examples/multiprecision/random/mt19937-64.c @@ -0,0 +1,166 @@ +/* + A C-program for MT19937-64 (2004/9/29 version). + Coded by Takuji Nishimura and Makoto Matsumoto. + + This is a 64-bit version of Mersenne Twister pseudorandom number + generator. + + Before using, initialize the state by using init_genrand64(seed) + or init_by_array64(init_key, key_length). + + Copyright (C) 2004, Makoto Matsumoto and Takuji Nishimura, + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + References: + T. Nishimura, ``Tables of 64-bit Mersenne Twisters'' + ACM Transactions on Modeling and + Computer Simulation 10. (2000) 348--357. + M. Matsumoto and T. Nishimura, + ``Mersenne Twister: a 623-dimensionally equidistributed + uniform pseudorandom number generator'' + ACM Transactions on Modeling and + Computer Simulation 8. (Jan. 1998) 3--30. + + Any feedback is very welcome. + http://www.math.hiroshima-u.ac.jp/~m-mat/MT/emt.html + email: m-mat @ math.sci.hiroshima-u.ac.jp (remove spaces) +*/ + + +#include <stdio.h> + +#define NN 312 +#define MM 156 +#define MATRIX_A 0xB5026F5AA96619E9ULL +#define UM 0xFFFFFFFF80000000ULL /* Most significant 33 bits */ +#define LM 0x7FFFFFFFULL /* Least significant 31 bits */ + + +/* The array for the state vector */ +static unsigned long long mt[NN]; +/* mti==NN+1 means mt[NN] is not initialized */ +static int mti=NN+1; + +/* initializes mt[NN] with a seed */ +void init_genrand64(unsigned long long seed) +{ + mt[0] = seed; + for (mti=1; mti<NN; mti++) + mt[mti] = (6364136223846793005ULL * (mt[mti-1] ^ (mt[mti-1] >> 62)) + mti); +} + +/* initialize by an array with array-length */ +/* init_key is the array for initializing keys */ +/* key_length is its length */ +void init_by_array64(unsigned long long init_key[], + unsigned long long key_length) +{ + unsigned long long i, j, k; + init_genrand64(19650218ULL); + i=1; j=0; + k = (NN>key_length ? NN : key_length); + for (; k; k--) { + mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 62)) * 3935559000370003845ULL)) + + init_key[j] + j; /* non linear */ + i++; j++; + if (i>=NN) { mt[0] = mt[NN-1]; i=1; } + if (j>=key_length) j=0; + } + for (k=NN-1; k; k--) { + mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 62)) * 2862933555777941757ULL)) + - i; /* non linear */ + i++; + if (i>=NN) { mt[0] = mt[NN-1]; i=1; } + } + + mt[0] = 1ULL << 63; /* MSB is 1; assuring non-zero initial array */ +} + +/* generates a random number on [0, 2^64-1]-interval */ +unsigned long long genrand64_int64(void) +{ + int i; + unsigned long long x; + static unsigned long long mag01[2]={0ULL, MATRIX_A}; + + if (mti >= NN) { /* generate NN words at one time */ + + /* if init_genrand64() has not been called, */ + /* a default initial seed is used */ + if (mti == NN+1) + init_genrand64(5489ULL); + + for (i=0;i<NN-MM;i++) { + x = (mt[i]&UM)|(mt[i+1]&LM); + mt[i] = mt[i+MM] ^ (x>>1) ^ mag01[(int)(x&1ULL)]; + } + for (;i<NN-1;i++) { + x = (mt[i]&UM)|(mt[i+1]&LM); + mt[i] = mt[i+(MM-NN)] ^ (x>>1) ^ mag01[(int)(x&1ULL)]; + } + x = (mt[NN-1]&UM)|(mt[0]&LM); + mt[NN-1] = mt[MM-1] ^ (x>>1) ^ mag01[(int)(x&1ULL)]; + + mti = 0; + } + + x = mt[mti++]; + + x ^= (x >> 29) & 0x5555555555555555ULL; + x ^= (x << 17) & 0x71D67FFFEDA60000ULL; + x ^= (x << 37) & 0xFFF7EEE000000000ULL; + x ^= (x >> 43); + + return x; +} + +/* generates a random number on [0, 2^63-1]-interval */ +long long genrand64_int63(void) +{ + return (long long)(genrand64_int64() >> 1); +} + +/* generates a random number on [0,1]-real-interval */ +double genrand64_real1(void) +{ + return (genrand64_int64() >> 11) * (1.0/9007199254740991.0); +} + +/* generates a random number on [0,1)-real-interval */ +double genrand64_real2(void) +{ + return (genrand64_int64() >> 11) * (1.0/9007199254740992.0); +} + +/* generates a random number on (0,1)-real-interval */ +double genrand64_real3(void) +{ + return ((genrand64_int64() >> 12) + 0.5) * (1.0/4503599627370496.0); +} diff --git a/examples/multiprecision/tests.c b/examples/multiprecision/tests.c new file mode 100644 index 0000000000000000000000000000000000000000..ee36ab29bd1fd702b1677d4724c8fe926529d5d9 --- /dev/null +++ b/examples/multiprecision/tests.c @@ -0,0 +1,290 @@ +#if defined(TEST_GMP) || defined(TEST_WHY3) || defined(TEST_MINIGMP) +#define BENCH +#else +#define COMPARE +#ifdef COMPARE_MINI +#define TEST_MINIGMP +#else +#define TEST_GMP +#endif +#define TEST_WHY3 +#define TEST_ADD +#define TEST_MUL +#define TEST_DIV +#endif + +#ifdef TEST_MINIGMP +#include "mini-gmp.c" +#else +#include <gmp.h> +#endif + +#include "mt19937-64.c" +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/time.h> +#include <time.h> + +uint64_t add(uint64_t * r3, uint64_t * x4, uint64_t * y3, int32_t sx, int32_t + sy); + +void mul(uint64_t * r10, uint64_t * x11, uint64_t * y10, int32_t sx2, int32_t + sy2); + +void tdiv_qr(uint64_t * q, uint64_t * r, uint64_t * x, uint64_t * y, + int32_t sx, int32_t sy); + +#define TMP_ALLOC_LIMBS(n) malloc((n) * 8) + +void mpn_dump(mp_ptr ap, mp_size_t an) { + for (mp_size_t i = 0; i != an; ++i) + printf("%016lx ", ap[i]); + printf("\n"); +} + + + +void init_valid (mp_ptr ap, mp_ptr bp, mp_size_t an, mp_size_t bn) { + for (int i = 0; i <= an; i++) + ap[i] = genrand64_int64(); + for (int i = 0; i <= bn; i++) + bp[i] = genrand64_int64(); + while (bp[bn-1]==0) + bp[bn-1] = genrand64_int64(); + return; +} + +int main () { + mp_ptr ap, bp, rp, refp, rq, rr, refq, refr; + mp_size_t max_n, an, bn, rn; +#ifdef BENCH + struct timeval begin, end; + double elapsed; +#endif + uint64_t c, refc; + //gmp_randstate_t rands; + //TMP_DECL; + //TMP_MARK; + + //tests_start (); + //TESTS_REPS (reps, argv, argc); + + //gmp_randinit_default(rands); + //gmp_randseed_ui(rands, 42); + /* Re-interpret reps argument as a size argument. */ + + init_genrand64((unsigned long long)time(NULL)); + max_n = 20; + + ap = TMP_ALLOC_LIMBS (max_n + 1); + bp = TMP_ALLOC_LIMBS (max_n + 1); + /* nap = TMP_ALLOC_LIMBS (max_n + 1); */ + /* nbp = TMP_ALLOC_LIMBS (max_n + 1); */ + rp = TMP_ALLOC_LIMBS (2 * max_n); + refp = TMP_ALLOC_LIMBS (2 * max_n); + rq = TMP_ALLOC_LIMBS (max_n + 1); + rr = TMP_ALLOC_LIMBS (max_n + 1); + refq = TMP_ALLOC_LIMBS (max_n + 1); + refr = TMP_ALLOC_LIMBS (max_n + 1); + +#ifdef TEST_ADD +#ifdef BENCH + printf ("#an bn t(s)\n"); +#endif + for (an = 2; an <= max_n; an += 1) + { + for (bn = 1; bn <= an; bn += 1) + { + init_valid (ap, bp, an, bn); +#ifdef BENCH + elapsed = 0; + for (int iter = 0; iter != 10000; ++iter) { + init_valid (ap, bp, an, bn); + gettimeofday(&begin, NULL); + for (int i = 0; i != 1000; ++i) + { +#endif + +#if defined(TEST_GMP) || defined(TEST_MINIGMP) + c = mpn_add (refp, ap, an, bp, bn); +#endif +#ifdef TEST_WHY3 + refc = add (rp, ap, bp, an, bn); +#endif + +#ifdef BENCH + } + gettimeofday(&end, NULL); + elapsed += + (end.tv_sec - begin.tv_sec) + + ((end.tv_usec - begin.tv_usec)/1000000.0); + } + printf ("%d %d %f\n", an, bn, elapsed); + if (an==bn) + printf ("\n"); //for gnuplot +#endif +#ifdef COMPARE + rn = an; + if (mpn_cmp (refp, rp, rn)) + { + printf ("ERROR, an = %d, bn = %d, rn = %d\n", + (int) an, (int) bn, (int) rn); + printf ("a: "); mpn_dump (ap, an); + printf ("b: "); mpn_dump (bp, bn); + printf ("r: "); mpn_dump (rp, rn); + printf ("ref: "); mpn_dump (refp, rn); + abort(); + } + if (c != refc) + { + printf ("ERROR, an = %d, bn = %d, rn = %d\n", + (int) an, (int) bn, (int) rn); + printf ("a: "); mpn_dump (ap, an); + printf ("b: "); mpn_dump (bp, bn); + printf ("c: %016lx\n", c); + printf ("refc: %016lx\n", refc); + abort(); + } +#endif + } + } +#ifdef COMPARE + printf ("addition ok\n"); +#endif +#endif +#ifdef TEST_MUL +#ifdef BENCH + printf ("#an bn t(s)\n"); +#endif + for (an = 2; an <= max_n; an += 1) + { + for (bn = 1; bn <= an; bn += 1) + { + init_valid (ap, bp, an, bn); +#ifdef BENCH + elapsed = 0; + for (int iter = 0; iter != 5000; ++iter) { + init_valid (ap, bp, an, bn); + gettimeofday(&begin, NULL); + for (int i = 0; i != 1000; ++i) + { +#endif +#if defined(TEST_GMP) || defined(TEST_MINIGMP) + mpn_mul (refp, ap, an, bp, bn); +#endif +#ifdef TEST_WHY3 + mul (rp, ap, bp, an, bn); +#endif + +#ifdef BENCH + } + gettimeofday(&end, NULL); + elapsed += + (end.tv_sec - begin.tv_sec) + + ((end.tv_usec - begin.tv_usec)/1000000.0); + } + printf ("%d %d %f\n", an, bn, elapsed); + if (an==bn) + printf ("\n"); //for gnuplot +#endif +#ifdef COMPARE + rn = an + bn; + if (mpn_cmp (refp, rp, rn)) + { + printf ("ERROR, an = %d, bn = %d, rn = %d\n", + (int) an, (int) bn, (int) rn); + printf ("a: "); mpn_dump (ap, an); + printf ("b: "); mpn_dump (bp, bn); + printf ("r: "); mpn_dump (rp, rn); + printf ("ref: "); mpn_dump (refp, rn); + abort(); + } +#endif + } + } +#ifdef COMPARE + printf ("multiplication ok\n"); +#endif +#endif +#ifdef TEST_DIV +#ifdef BENCH + printf ("#an bn t(s)\n"); +#endif + for (an = 2; an <= max_n; an += 1) + { + for (bn = 1; bn <= an; bn += 1) + { + init_valid (ap, bp, an, bn); +#ifdef TEST_MINIGMP + mpn_copyi(refr, ap, an); +#endif + +#ifdef BENCH + elapsed = 0; + for (int iter = 0; iter != 10000; ++iter) { + init_valid (ap, bp, an, bn); +#ifdef TEST_MINIGMP + mpn_copyi(refr, ap, an); +#endif + gettimeofday(&begin, NULL); + for (int i = 0; i != 1000; ++i) + { +#endif +#ifdef TEST_GMP + mpn_tdiv_qr(refq, refr, 0, ap, an, bp, bn); +#endif +#ifdef TEST_MINIGMP + mpn_div_qr (refq, refr, an, bp, bn); +#endif +#ifdef TEST_WHY3 + tdiv_qr(rq, rr, ap, bp, an, bn); +#endif + +#ifdef BENCH + } + gettimeofday(&end, NULL); + elapsed += + (end.tv_sec - begin.tv_sec) + + ((end.tv_usec - begin.tv_usec)/1000000.0); + } + printf ("%d %d %f\n", an, bn, elapsed); + if (an==bn) + printf ("\n"); //for gnuplot +#endif +#ifdef COMPARE + rn = bn; + if (mpn_cmp (refr, rr, rn)) + { + printf ("ERROR, an = %d, bn = %d, rn = %d\n", + (int) an, (int) bn, (int) rn); + printf ("a: "); mpn_dump (ap, an); + printf ("b: "); mpn_dump (bp, bn); + printf ("q: "); mpn_dump (rq, an-bn+2); + printf ("refq: "); mpn_dump (refq, an-bn+2); + printf ("r: "); mpn_dump (rr, rn); + printf ("refr: "); mpn_dump (refr, rn); + abort(); + } + rn = an - bn + 1; + if (mpn_cmp (refq, rq, rn)) + { + printf ("ERROR, an = %d, bn = %d, qn = %d\n", + (int) an, (int) bn, (int) rn); + printf ("a: "); mpn_dump (ap, an); + printf ("b: "); mpn_dump (bp, bn); + printf ("q: "); mpn_dump (rq, rn); + printf ("refq: "); mpn_dump (refq, rn); + abort(); + } +#endif + } + } +#endif +#ifdef COMPARE + printf ("division ok\n"); +#endif + //TMP_FREE; + //tests_end (); + return 0; + } diff --git a/src/core/printer.ml b/src/core/printer.ml index 35d9872194e70c04f08da072d6e8a14bf33c470d..8e78dbc158ba3e624922257d545d0b33d7245d0a 100644 --- a/src/core/printer.ml +++ b/src/core/printer.ml @@ -24,6 +24,8 @@ open Task type prelude = string list type prelude_map = prelude Mid.t +type interface = string list +type interface_map = interface Mid.t type blacklist = string list type 'a pp = Pp.formatter -> 'a -> unit @@ -320,6 +322,8 @@ let print_prelude fmt pl = let println fmt s = fprintf fmt "%s@\n" s in print_list nothing println fmt pl +let print_interface = print_prelude + let print_prelude_of_theories th_used fmt pm = let ht = Hid.create 5 in List.iter (fun { th_name = id } -> diff --git a/src/core/printer.mli b/src/core/printer.mli index 011a5938b3fd76270a396c5bdead40f98d32675f..9ced4d4fe7791f61b3b02a84509fc861c8034532 100644 --- a/src/core/printer.mli +++ b/src/core/printer.mli @@ -21,6 +21,8 @@ open Task type prelude = string list type prelude_map = prelude Mid.t +type interface = string list +type interface_map = interface Mid.t type blacklist = string list (* Makes it possible to estabilish traceability from names @@ -59,6 +61,7 @@ val list_printers : unit -> (string * Pp.formatted) list val print_prelude : prelude Pp.pp val print_th_prelude : task -> prelude_map Pp.pp +val print_interface : interface Pp.pp val meta_syntax_type : meta val meta_syntax_logic : meta diff --git a/src/driver/driver_ast.ml b/src/driver/driver_ast.ml index a41d1757d477dca2305eff53ace8508b65cda282..047552c1563bee1ef419f0a65f254714d59f8b8f 100644 --- a/src/driver/driver_ast.ml +++ b/src/driver/driver_ast.ml @@ -44,6 +44,7 @@ type theory_rules = { type mo_rule = | MRtheory of th_rule + | MRinterface of string | MRexception of qualid * string | MRval of qualid * string diff --git a/src/driver/driver_lexer.mll b/src/driver/driver_lexer.mll index f4195bc67b6118e88c238f7c1c32174c03469654..39830de338261ae5e2e4aa57c1d2e4806695b5ff 100644 --- a/src/driver/driver_lexer.mll +++ b/src/driver/driver_lexer.mll @@ -24,6 +24,7 @@ "remove", REMOVE; "meta", META; "prelude", PRELUDE; + "interface", INTERFACE; "printer", PRINTER; "steps", STEPS; "model_parser", MODEL_PARSER; diff --git a/src/driver/driver_parser.mly b/src/driver/driver_parser.mly index ee1b51a547b2e0d58eb8534617eceb837c19f639..b34e49ac8ffc606488969765ed392bdffeec60bd 100644 --- a/src/driver/driver_parser.mly +++ b/src/driver/driver_parser.mly @@ -20,6 +20,7 @@ %token <string> OPERATOR %token <string> INPUT (* never reaches the parser *) %token THEORY END SYNTAX REMOVE META PRELUDE PRINTER MODEL_PARSER OVERRIDING +%token INTERFACE %token VALID INVALID UNKNOWN FAIL %token TIMEOUT OUTOFMEMORY STEPLIMITEXCEEDED TIME STEPS %token UNDERSCORE LEFTPAR RIGHTPAR DOT DOTDOT QUOTE EOF @@ -29,7 +30,7 @@ %token COMMA CONSTANT %token LEFTSQ RIGHTSQ LARROW -%nonassoc SYNTAX REMOVE PRELUDE +%nonassoc SYNTAX REMOVE PRELUDE INTERFACE %nonassoc prec_pty %start <Driver_ast.file> file @@ -118,6 +119,7 @@ ident: | SYNTAX { "syntax" } | REMOVE { "remove" } | PRELUDE { "prelude" } +| INTERFACE { "interface" } | BLACKLIST { "blacklist" } | PRINTER { "printer" } | STEPS { "steps" } @@ -199,6 +201,7 @@ module_: mrule: | trule { MRtheory $1 } +| INTERFACE STRING { MRinterface ($2) } | SYNTAX EXCEPTION qualid STRING { MRexception ($3, $4) } | SYNTAX VAL qualid STRING { MRval ($3, $4) } diff --git a/src/mlw/cakeml_printer.ml b/src/mlw/cakeml_printer.ml index 5e6e11c07829ffa1f81b23d1b6ada5c90287ef74..50d617f79ad3e43743555a8a6e3d65b2e5802b21 100644 --- a/src/mlw/cakeml_printer.ml +++ b/src/mlw/cakeml_printer.ml @@ -474,13 +474,29 @@ let fg_cml ?fname m = let path = m.mod_theory.th_path in (module_name ?fname path mod_name) ^ ".cml" -let () = Pdriver.register_printer "cakeml" - ~desc:"printer for CakeML code" fg_cml print_decl +open Pdriver + +let cml_printer = + { desc = "printer for CakeML code"; + file_gen = fg_cml; + decl_printer = print_decl; + interf_gen = None; + interf_printer = None; + prelude_printer = print_empty_prelude } + +let () = Pdriver.register_printer "cakeml" cml_printer let fg_sml ?fname m = let mod_name = m.mod_theory.th_name.id_string in let path = m.mod_theory.th_path in (module_name ?fname path mod_name) ^ ".sml" -let () = Pdriver.register_printer "sml" - ~desc:"printer for SML code" fg_sml print_decl +let sml_printer = + { desc = "printer for SML code"; + file_gen = fg_sml; + decl_printer = print_decl; + interf_gen = None; + interf_printer = None; + prelude_printer = print_empty_prelude } + +let () = Pdriver.register_printer "sml" sml_printer diff --git a/src/mlw/cprinter.ml b/src/mlw/cprinter.ml index da6fc1db1878fecf61e804be6956dae5962783a9..3827cbb9c9ca35f7ec5ecfd3dfb42cc451d47d40 100644 --- a/src/mlw/cprinter.ml +++ b/src/mlw/cprinter.ml @@ -79,9 +79,10 @@ module C = struct | Sbreak | Sreturn of expr + and include_kind = Sys | Proj (* include <...> vs. include "..." *) and definition = | Dfun of ident * proto * body - | Dinclude of ident + | Dinclude of ident * include_kind | Dproto of ident * proto | Ddecl of names | Dstruct of struct_def @@ -206,7 +207,7 @@ module C = struct | Ddecl (ty,l) -> let l,b = aux l in Ddecl (ty, l), b - | Dinclude i -> Dinclude i, true + | Dinclude (i,k) -> Dinclude (i,k), true | Dstruct _ -> raise (Unsupported "struct declaration inside function") | Dfun _ -> raise (Unsupported "nested function") | Dtypedef _ -> raise (Unsupported "typedef inside function") @@ -362,6 +363,7 @@ type info = Pdriver.printer_args = private { env : Env.env; prelude : Printer.prelude; thprelude : Printer.prelude_map; + thinterface : Printer.interface_map; blacklist : Printer.blacklist; syntax : Printer.syntax_map; converter : Printer.syntax_map; @@ -386,6 +388,7 @@ module Print = struct let () = assert (List.length c_keywords = 32) let sanitizer = sanitizer char_to_lalpha char_to_alnumus + let sanitizer s = String.lowercase (sanitizer s) let printer = create_ident_printer c_keywords ~sanitizer let print_ident fmt id = fprintf fmt "%s" (id_unique printer id) @@ -518,41 +521,50 @@ module Print = struct and print_def fmt def = try match def with | Dfun (id,(rt,args),body) -> - fprintf fmt "%a %a(@[%a@])@ @[<hov>{@;<1 2>@[<hov>%a@]@\n}@\n@]" + let s = sprintf "%a %a(@[%a@])@ @[<hov>{@;<1 2>@[<hov>%a@]@\n}@\n@]" (print_ty ~paren:false) rt print_ident id (print_list comma (print_pair_delim nothing space nothing (print_ty ~paren:false) print_ident)) args - print_body body + print_body body in + (* print into string first to print nothing in case of exception *) + fprintf fmt "%s" s | Dproto (id, (rt, args)) -> - fprintf fmt "%a %a(@[%a@]);@;" - (print_ty ~paren:false) rt - print_ident id - (print_list comma - (print_pair_delim nothing space nothing - (print_ty ~paren:false) print_ident)) - args + let s = sprintf "%a %a(@[%a@]);@;" + (print_ty ~paren:false) rt + print_ident id + (print_list comma + (print_pair_delim nothing space nothing + (print_ty ~paren:false) print_ident)) + args in + fprintf fmt "%s" s | Ddecl (ty, lie) -> let nb, ty = extract_stars ty in assert (nb=0); - fprintf fmt "%a @[<hov>%a@];" - (print_ty ~paren:false) ty - (print_list comma (print_id_init ~stars:nb)) lie + let s = sprintf "%a @[<hov>%a@];" + (print_ty ~paren:false) ty + (print_list comma (print_id_init ~stars:nb)) lie in + fprintf fmt "%s" s | Dstruct (s, lf) -> - fprintf fmt "struct %s@ @[<hov>{@;<1 2>@[<hov>%a@]@\n};@\n@]" - s - (print_list newline - (fun fmt (s,ty) -> fprintf fmt "%a %s;" - (print_ty ~paren:false) ty s)) - lf - | Dinclude id -> - fprintf fmt "#include<%a.h>@;" print_ident id + let s = sprintf "struct %s@ @[<hov>{@;<1 2>@[<hov>%a@]@\n};@\n@]" + s + (print_list newline + (fun fmt (s,ty) -> fprintf fmt "%a %s;" + (print_ty ~paren:false) ty s)) + lf in + fprintf fmt "%s" s + | Dinclude (id, Sys) -> + fprintf fmt "#include <%s.h>@;" (sanitizer id.id_string) + | Dinclude (id, Proj) -> + fprintf fmt "#include \"%s.h\"@;" (sanitizer id.id_string) | Dtypedef (ty,id) -> - fprintf fmt "@[<hov>typedef@ %a@;%a;@]" - (print_ty ~paren:false) ty print_ident id - with Unprinted s -> Format.printf "Missed a def because : %s@." s + let s = sprintf "@[<hov>typedef@ %a@;%a;@]" + (print_ty ~paren:false) ty print_ident id in + fprintf fmt "%s" s + with Unprinted s -> + Debug.dprintf debug_c_extraction "Missed a def because : %s@." s and print_body fmt (def, s) = if def = [] @@ -563,6 +575,33 @@ module Print = struct (print_stmt ~braces:true) fmt (def,s) + let print_header_def fmt def = + try match def with + | Dfun (id,(rt,args),_) | Dproto (id, (rt, args)) -> + let s = sprintf "%a %a(@[%a@]);@;" + (print_ty ~paren:false) rt + print_ident id + (print_list comma + (print_pair_delim nothing space nothing + (print_ty ~paren:false) print_ident)) + args in + fprintf fmt "%s" s + | Dstruct (s, lf) -> + let s = sprintf "struct %s@ @[<hov>{@;<1 2>@[<hov>%a@]@\n};@\n@]" + s + (print_list newline + (fun fmt (s,ty) -> fprintf fmt "%a %s;" + (print_ty ~paren:false) ty s)) + lf in + fprintf fmt "%s" s + | Dinclude _ | Ddecl _ -> () + | Dtypedef (ty,id) -> + let s = sprintf "@[<hov>typedef@ %a@;%a;@]" + (print_ty ~paren:false) ty print_ident id in + fprintf fmt "%s" s + with Unprinted s -> + Debug.dprintf debug_c_extraction "Missed a def because : %s@." s + let print_file fmt info ast = Mid.iter (fun _ sl -> List.iter (fprintf fmt "%s\n") sl) info.thprelude; newline fmt (); @@ -570,7 +609,8 @@ module Print = struct end -(*TODO simplifications : propagate constants, collapse blocks with only a statement and no def*) +(*TODO simplifications : propagate constants, collapse blocks with + only a statement and no def*) module MLToC = struct @@ -927,7 +967,8 @@ module MLToC = struct | Eraise (xs, Some r) when Sid.mem xs.xs_name env.returns -> Debug.dprintf debug_c_extraction "RETURN@."; expr info {env with computes_return_value = true} r - | Eraise (_, None) -> assert false (* nothing to pass to return *) + | Eraise (xs, None) when Sid.mem xs.xs_name env.returns -> + assert false (* nothing to pass to return *) | Eraise _ -> raise (Unsupported "non break/return exception raised") | Efor (i, sb, dir, eb, body) -> begin match i.pv_vs.vs_ty.ty_node with @@ -1022,12 +1063,12 @@ module MLToC = struct let translate_decl (info:info) (d:decl) : C.definition list = - match d with - | Dlet (Lsym(rs, _, vl, e)) -> - if rs_ghost rs - then begin Debug.dprintf debug_c_extraction "is ghost@."; [] end - else - begin try + try + begin match d with + | Dlet (Lsym(rs, _, vl, e)) -> + if rs_ghost rs + then begin Debug.dprintf debug_c_extraction "is ghost@."; [] end + else let params = List.map (fun (id, ty, _gh) -> (ty_of_mlty info ty, id)) (List.filter (fun (_,_, gh) -> not gh) vl) in @@ -1069,24 +1110,25 @@ module MLToC = struct let s = C.elim_nop s in let s = C.elim_empty_blocks s in sdecls@[C.Dfun (rs.rs_name, (rtype,params), (d,s))] - with Unsupported s -> - Format.printf "Unsupported : %s@." s; [] + | Dtype [{its_name=id; its_def=idef}] -> + Debug.dprintf debug_c_extraction "PDtype %s@." id.id_string; + begin + match idef with + | Some (Dalias _ty) -> [] (*[C.Dtypedef (ty_of_mlty info ty, id)] *) + | Some _ -> raise (Unsupported "Ddata/Drecord@.") + | None -> + begin match query_syntax info.syntax id with + | Some _ -> [] + | None -> + raise (Unsupported + ("type declaration without syntax or alias: " + ^id.id_string)) + end end - | Dtype [{its_name=id; its_def=idef}] -> - Debug.dprintf debug_c_extraction "PDtype %s@." id.id_string; - begin - match idef with - | Some (Dalias ty) -> [C.Dtypedef (ty_of_mlty info ty, id)] - | Some _ -> raise (Unsupported "Ddata/Drecord@.") - | None -> - begin match query_syntax info.syntax id with - | Some _ -> [] - | None -> - raise (Unsupported ("type declaration without syntax or alias: "^id.id_string)) - end - end - | _ -> [] (*TODO exn ? *) + | _ -> [] (*TODO exn ? *) end + with Unsupported s -> + Debug.dprintf debug_c_extraction "Unsupported : %s@." s; [] let translate_decl (info:info) (d:Mltree.decl) : C.definition list = @@ -1105,29 +1147,57 @@ module MLToC = struct end -let fg ?fname m = +let name_gen suffix ?fname m = let n = m.Pmodule.mod_theory.Theory.th_name.Ident.id_string in - match fname with - | None -> n ^ ".c" - | Some f -> f ^ "__" ^ n ^ ".c" -(* -let pr args ?old ?fname ~flat m fmt _d = - ignore(old); - let ast = Translate.translate args m in - try Print.print_file fmt args ast - with Print.Unprinted s -> (Format.printf "Could not print: %s@." s; - Format.fprintf fmt "/* Dummy file */@.") -*) + let n = Print.sanitizer n in + let r = match fname with + | None -> n ^ suffix + | Some f -> f ^ "__" ^ n ^ suffix in + String.lowercase r + +let file_gen = name_gen ".c" +let header_gen = name_gen ".h" + +let print_header_decl args ?old ?fname ~flat m fmt d = + ignore old; + ignore fname; + ignore flat; + ignore m; + let cds = MLToC.translate_decl args d in + List.iter (Format.fprintf fmt "%a@." Print.print_header_def) cds + +let print_prelude args ?old ?fname ~flat deps fmt pm = + ignore old; + ignore fname; + ignore flat; + ignore pm; + ignore args; + let add_include id = + Format.fprintf fmt "%a@." Print.print_def C.(Dinclude (id,Proj)) in + List.iter + (fun m -> + let id = m.Pmodule.mod_theory.Theory.th_name in + add_include id) + (List.rev deps) + let print_decl args ?old ?fname ~flat m fmt d = ignore old; ignore fname; - ignore flat; (*FIXME*) + ignore flat; ignore m; let cds = MLToC.translate_decl args d in List.iter (Format.fprintf fmt "%a@." Print.print_def) cds +let c_printer = Pdriver.{ + desc = "printer for C code"; + file_gen = file_gen; + decl_printer = print_decl; + interf_gen = Some header_gen; + interf_printer = Some print_header_decl; + prelude_printer = print_prelude } + let () = - Pdriver.register_printer "c" ~desc:"printer for C code" fg print_decl + Pdriver.register_printer "c" c_printer (* Local Variables: diff --git a/src/mlw/ocaml_printer.ml b/src/mlw/ocaml_printer.ml index 6ae1114f4075c0695b01f367a4259efd99251d01..c6d1559b66fa55f45fa67db0337ce0a1dbd31d42 100644 --- a/src/mlw/ocaml_printer.ml +++ b/src/mlw/ocaml_printer.ml @@ -693,10 +693,22 @@ let print_decl = if not (Hashtbl.mem memo d) then begin Hashtbl.add memo d (); Print.print_decl info fmt d end -let fg ?fname m = +let ng suffix ?fname m = let mod_name = m.mod_theory.th_name.id_string in let path = m.mod_theory.th_path in - (module_name ?fname path mod_name) ^ ".ml" + (module_name ?fname path mod_name) ^ suffix -let () = Pdriver.register_printer "ocaml" - ~desc:"printer for OCaml code" fg print_decl +let file_gen = ng ".ml" +let mli_gen = ng ".mli" + +open Pdriver + +let ocaml_printer = + { desc = "printer for Ocaml code"; + file_gen = file_gen; + decl_printer = print_decl; + interf_gen = Some mli_gen; + interf_printer = None; + prelude_printer = print_empty_prelude } + +let () = Pdriver.register_printer "ocaml" ocaml_printer diff --git a/src/mlw/pdriver.ml b/src/mlw/pdriver.ml index 6e4ba1d95363c13d3bd20baa34332a4943a90b96..4164663d9db2f4510f7175cef8074610faaa9998 100644 --- a/src/mlw/pdriver.ml +++ b/src/mlw/pdriver.ml @@ -24,6 +24,7 @@ type driver = { drv_printer : string option; drv_prelude : Printer.prelude; drv_thprelude : Printer.prelude_map; + drv_thinterface : Printer.interface_map; drv_blacklist : Printer.blacklist; drv_syntax : Printer.syntax_map; drv_converter : Printer.syntax_map; @@ -34,6 +35,7 @@ type printer_args = { env : Env.env; prelude : Printer.prelude; thprelude : Printer.prelude_map; + thinterface : Printer.interface_map; blacklist : Printer.blacklist; syntax : Printer.syntax_map; converter : Printer.syntax_map; @@ -85,6 +87,7 @@ let load_driver env file extra_files = List.iter add_global f.fe_global; let thprelude = ref Mid.empty in + let thinterface = ref Mid.empty in let syntax_map = ref Mid.empty in let converter_map = ref Mid.empty in let literal_map = ref Mid.empty in @@ -179,6 +182,10 @@ let load_driver env file extra_files = with Not_found -> Loc.error ~loc (UnknownExn (!qualid,q)) in let add_local_module loc m = function + | MRinterface s -> + let th = m.mod_theory in + let l = Mid.find_def [] th.th_name !thinterface in + thinterface := Mid.add th.th_name (s::l) !thinterface | MRexception (q,s) -> let xs = find_xs m q in add_syntax xs.Ity.xs_name s false @@ -218,6 +225,7 @@ let load_driver env file extra_files = drv_printer = !printer; drv_prelude = List.rev !prelude; drv_thprelude = Mid.map List.rev !thprelude; + drv_thinterface = Mid.map List.rev !thinterface; drv_blacklist = Queue.fold (fun l s -> s :: l) [] blacklist; drv_syntax = !syntax_map; drv_converter = !converter_map; @@ -229,22 +237,40 @@ let load_driver env file extra_files = open Wstdlib type filename_generator = ?fname:string -> Pmodule.pmodule -> string +type interface_generator = ?fname:string -> Pmodule.pmodule -> string -type printer = +type interf_printer = + printer_args -> ?old:in_channel -> ?fname:string -> flat:bool + -> Pmodule.pmodule -> Mltree.decl Pp.pp + +type prelude_printer = + printer_args -> ?old:in_channel -> ?fname:string -> flat:bool + -> Pmodule.pmodule list -> Pmodule.pmodule Pp.pp + +let print_empty_prelude _ ?old:_ ?fname:_ ~flat:_ _ _ _ = () + +type decl_printer = printer_args -> ?old:in_channel -> ?fname:string -> flat:bool -> Pmodule.pmodule -> Mltree.decl Pp.pp -type reg_printer = Pp.formatted * filename_generator * printer +type printer = + { desc : Pp.formatted; + file_gen : filename_generator; + decl_printer : decl_printer; + interf_gen : interface_generator option; + interf_printer : interf_printer option; + prelude_printer : prelude_printer; } + -let printers : reg_printer Hstr.t = Hstr.create 17 +let printers : printer Hstr.t = Hstr.create 17 exception KnownPrinter of string exception UnknownPrinter of string exception NoPrinter -let register_printer ~desc s fg p = +let register_printer s p = if Hstr.mem printers s then raise (KnownPrinter s); - Hstr.replace printers s (desc, fg, p) + Hstr.replace printers s p let lookup_printer drv = let p = match drv.drv_printer with @@ -255,6 +281,7 @@ let lookup_printer drv = env = drv.drv_env; prelude = drv.drv_prelude; thprelude = drv.drv_thprelude; + thinterface = drv.drv_thinterface; blacklist = drv.drv_blacklist; syntax = drv.drv_syntax; converter = drv.drv_converter; @@ -262,11 +289,11 @@ let lookup_printer drv = } in try - let (_,fg,p) = Hstr.find printers p in (fg,printer_args,p) + let printer = Hstr.find printers p in printer_args, printer with Not_found -> raise (UnknownPrinter p) let list_printers () = - Hstr.fold (fun k (desc,_,_) acc -> (k,desc)::acc) printers [] + Hstr.fold (fun k { desc = desc; _ } acc -> (k,desc)::acc) printers [] (* exception report *) diff --git a/src/mlw/pdriver.mli b/src/mlw/pdriver.mli index c92efdabd826941e5b3d946eedddee3d6555c7b6..87c48bf55c64a5b5ecd7e525e3b22b31e4f81e3b 100644 --- a/src/mlw/pdriver.mli +++ b/src/mlw/pdriver.mli @@ -16,6 +16,7 @@ type driver = private { drv_printer : string option; drv_prelude : Printer.prelude; drv_thprelude : Printer.prelude_map; + drv_thinterface : Printer.interface_map; drv_blacklist : Printer.blacklist; drv_syntax : Printer.syntax_map; drv_converter : Printer.syntax_map; @@ -27,6 +28,7 @@ type printer_args = private { env : Env.env; prelude : Printer.prelude; thprelude : Printer.prelude_map; + thinterface : Printer.interface_map; blacklist : Printer.blacklist; syntax : Printer.syntax_map; converter : Printer.syntax_map; @@ -39,16 +41,36 @@ val load_driver : Env.env -> string -> string list -> driver @param string driver file name @param string list additional drivers containing only theories/modules *) -type printer = +type filename_generator = ?fname:string -> Pmodule.pmodule -> string + +type interface_generator = ?fname:string -> Pmodule.pmodule -> string +type interf_printer = + printer_args -> ?old:in_channel -> ?fname:string -> flat:bool + -> Pmodule.pmodule -> Mltree.decl Pp.pp + +(** Things to do at the beginning of a module, e.g. open/#include. + Only used in modular extraction. *) +type prelude_printer = + printer_args -> ?old:in_channel -> ?fname:string -> flat:bool + -> Pmodule.pmodule list -> Pmodule.pmodule Pp.pp + +val print_empty_prelude: prelude_printer + +type decl_printer = printer_args -> ?old:in_channel -> ?fname:string -> flat:bool -> Pmodule.pmodule -> Mltree.decl Pp.pp -type filename_generator = ?fname:string -> Pmodule.pmodule -> string +type printer = + { desc : Pp.formatted; + file_gen : filename_generator; + decl_printer : decl_printer; + interf_gen : interface_generator option; + interf_printer : interf_printer option; + prelude_printer : prelude_printer; } -val register_printer : - desc:Pp.formatted -> string -> filename_generator -> printer -> unit +val register_printer : string -> printer -> unit -val lookup_printer : driver -> filename_generator * printer_args * printer +val lookup_printer : driver -> printer_args * printer val list_printers : unit -> (string * Pp.formatted) list diff --git a/src/tools/why3extract.ml b/src/tools/why3extract.ml index d7601508ffefe61d163d9009b07eedcfe9e75e01..cc4b529db6b2f2957b7b77a376364cd5c23835dd 100644 --- a/src/tools/why3extract.ml +++ b/src/tools/why3extract.ml @@ -40,6 +40,7 @@ type flat_modular = Flat | Modular let opt_modu_flat = ref Flat let is_uppercase = Strings.char_is_uppercase +let opt_interface = ref false let add_opt_file x = let invalid_path () = Format.eprintf "invalid path: %s@." x; exit 1 in @@ -74,6 +75,8 @@ let option_list = [ " perform a flat extraction (default option)"; "--modular", Arg.Unit (fun () -> opt_modu_flat := Modular), " perform a modular extraction"; + "--interface", Arg.Unit (fun () -> opt_interface := true), + " also extract interface files (requires modular extraction)"; "-o", Arg.String (fun s -> opt_output := Some s), "<file|dir> destination of extracted code"; "--output", Arg.String (fun s -> opt_output := Some s), @@ -143,23 +146,52 @@ let print_preludes = let l = List.fold_left add [] th_pm in Printer.print_prelude fmt l -let print_mdecls ?fname m mdecls = - let (fg,pargs,pr) = Pdriver.lookup_printer opt_driver in +let print_mdecls ?fname m mdecls deps = + let pargs, printer = Pdriver.lookup_printer opt_driver in + let fg = printer.Pdriver.file_gen in + let pr = printer.Pdriver.decl_printer in let test_decl_not_driver decl = let decl_name = Mltree.get_decl_name decl in let test_id_not_driver id = Printer.query_syntax pargs.Pdriver.syntax id = None in List.exists test_id_not_driver decl_name in - if List.exists test_decl_not_driver mdecls then begin + let prelude_exists = + Ident.Mid.mem m.mod_theory.Theory.th_name pargs.Pdriver.thprelude in + if List.exists test_decl_not_driver mdecls || prelude_exists + then begin + let flat = opt_modu_flat = Flat in + let thname = m.mod_theory.Theory.th_name in + (* print interface file *) + if !opt_interface then begin + match printer.Pdriver.interf_gen, printer.Pdriver.interf_printer with + | None, _ | _, None -> + eprintf "Driver does not support interface extraction.@."; + exit 1 + | Some ig, Some ipr -> + let iout, old = get_cout_old ig m ?fname in + let ifmt = formatter_of_out_channel iout in + Printer.print_prelude ifmt pargs.Pdriver.prelude; + let inter_p = Ident.Mid.find_def [] thname pargs.Pdriver.thinterface in + Printer.print_interface ifmt inter_p; + (* printer.Pdriver.prelude_printer pargs ?old ?fname ~flat deps ifmt m;*) + let pr_idecl fmt d = + fprintf fmt "%a" (ipr pargs ?old ?fname ~flat m) d in + Pp.print_list Pp.nothing pr_idecl ifmt mdecls; + if iout <> stdout then close_out iout end; let cout, old = get_cout_old fg m ?fname in let fmt = formatter_of_out_channel cout in + (* print module prelude *) + printer.Pdriver.prelude_printer pargs ?old ?fname ~flat deps fmt m; (* print driver prelude *) + Printer.print_prelude fmt pargs.Pdriver.prelude; let pm = pargs.Pdriver.thprelude in - print_preludes m.mod_theory.Theory.th_name fmt pm; - let flat = opt_modu_flat = Flat in + print_preludes thname fmt pm; + (* print decls *) let pr_decl fmt d = fprintf fmt "%a" (pr pargs ?old ?fname ~flat m) d in Pp.print_list Pp.nothing pr_decl fmt mdecls; - if cout <> stdout then close_out cout end + if cout <> stdout then close_out cout; + true end + else false let find_module_path mm path m = match path with | [] -> Mstr.find m mm @@ -185,24 +217,27 @@ let is_not_extractable_theory = let h = Hstr.create 16 in List.iter (fun s -> Hstr.add h s ()) not_extractable_theories; Hstr.mem h - let extract_to = let memo = Ident.Hid.create 16 in - fun ?fname ?decl m -> + fun ?fname ?decl m deps -> match m.mod_theory.Theory.th_path with - | t::_ when is_not_extractable_theory t -> () + | t::_ when is_not_extractable_theory t -> false | _ -> let name = m.mod_theory.Theory.th_name in if not (Ident.Hid.mem memo name) then begin - Ident.Hid.add memo name (); let mdecls = match decl with | None -> (translate_module m).Mltree.mod_decl | Some d -> Translate.pdecl_m m d in - print_mdecls ?fname m mdecls - end - -let rec use_iter f l = - List.iter - (function Uuse t -> f t | Uscope (_,l) -> use_iter f l | _ -> ()) l + let file_exists = print_mdecls ?fname m mdecls deps in + Ident.Hid.add memo name file_exists; + file_exists + end + else Ident.Hid.find memo name + +let rec use_fold f l = + List.fold_left + (fun acc -> function | Uuse t -> if f t then t::acc else acc + | Uscope (_,l) -> (use_fold f l)@acc + | _ -> acc) [] l let rec do_extract_module ?fname m = let extract_use m' = @@ -210,11 +245,12 @@ let rec do_extract_module ?fname m = if m'.mod_theory.Theory.th_path = [] then fname else None in do_extract_module ?fname m' in - begin match opt_rec_single with - | Recursive -> use_iter extract_use m.mod_units - | Single -> () - end; - extract_to ?fname m + let deps = + match opt_rec_single with + | Recursive -> use_fold extract_use m.mod_units + | Single -> [] + in + extract_to ?fname m deps let do_extract_module_from fname mm m = try @@ -264,16 +300,16 @@ let do_modular target = match target with | File fname -> let mm = read_mlw_file ?format env fname in - let do_m _ m = do_extract_module ~fname m in + let do_m _ m = ignore (do_extract_module ~fname m) in Mstr.iter do_m mm | Module (path, m) -> let mm = Mstr.empty in let m = find_module_path mm path m in - do_extract_module m + ignore (do_extract_module m) | Symbol (path, m, s) -> let mm = Mstr.empty in let m = find_module_path mm path m in - do_extract_symbol_from m s + ignore (do_extract_symbol_from m s []) (* FIXME empty deps ? *) type extract_info = { info_rec : bool; @@ -330,43 +366,45 @@ let () = try match opt_modu_flat with | Modular -> Queue.iter do_modular opt_queue - | Flat -> let mm = Queue.fold flat_extraction Mstr.empty opt_queue in - let (_fg, pargs, pr) = Pdriver.lookup_printer opt_driver in - let cout = match opt_output with - | None -> stdout - | Some file -> open_out file in - let fmt = formatter_of_out_channel cout in - let thprelude = pargs.Pdriver.thprelude in - let print_prelude = List.iter (fun s -> fprintf fmt "%s@\n@." s) in - let rec do_preludes id = - (try - let m = find_module_id mm id in - Ident.Sid.iter do_preludes m.mod_used - with Not_found -> ()); - print_preludes id fmt thprelude - in - print_prelude pargs.Pdriver.prelude; - let visit_m _ m = - do_preludes m.mod_theory.Theory.th_name; - let tm = translate_module m in - let visit_id id _ = visit ~recurs:true mm id in - Ident.Mid.iter visit_id tm.Mltree.mod_known; - in - Mstr.iter visit_m mm; - let extract fmt { info_id = id } = - let pm = find_module_id mm id in - let m = translate_module pm in - let d = Ident.Mid.find id m.Mltree.mod_known in - pr pargs ~flat:true pm fmt d in - let idl = List.rev !toextract in - let is_local { info_id = id; info_rec = r } = - let (path, m, _) = Pmodule.restore_path id in - path = [] || Mstr.mem m mm || not r in - let idl = match opt_rec_single with - | Single -> List.filter is_local idl - | Recursive -> idl in - Pp.print_list Pp.nothing extract fmt idl; - if cout <> stdout then close_out cout + | Flat -> + let mm = Queue.fold flat_extraction Mstr.empty opt_queue in + let (pargs, printer) = Pdriver.lookup_printer opt_driver in + let pr = printer.Pdriver.decl_printer in + let cout = match opt_output with + | None -> stdout + | Some file -> open_out file in + let fmt = formatter_of_out_channel cout in + let thprelude = pargs.Pdriver.thprelude in + let print_prelude = List.iter (fun s -> fprintf fmt "%s@\n@." s) in + let rec do_preludes id = + (try + let m = find_module_id mm id in + Ident.Sid.iter do_preludes m.mod_used + with Not_found -> ()); + print_preludes id fmt thprelude + in + print_prelude pargs.Pdriver.prelude; + let visit_m _ m = + do_preludes m.mod_theory.Theory.th_name; + let tm = translate_module m in + let visit_id id _ = visit ~recurs:true mm id in + Ident.Mid.iter visit_id tm.Mltree.mod_known; + in + Mstr.iter visit_m mm; + let extract fmt { info_id = id } = + let pm = find_module_id mm id in + let m = translate_module pm in + let d = Ident.Mid.find id m.Mltree.mod_known in + pr pargs ~flat:true pm fmt d in + let idl = List.rev !toextract in + let is_local { info_id = id; info_rec = r } = + let (path, m, _) = Pmodule.restore_path id in + path = [] || Mstr.mem m mm || not r in + let idl = match opt_rec_single with + | Single -> List.filter is_local idl + | Recursive -> idl in + Pp.print_list Pp.nothing extract fmt idl; + if cout <> stdout then close_out cout with e when not (Debug.test_flag Debug.stack_trace) -> eprintf "%a@." Exn_printer.exn_printer e; exit 1