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