From a89a14ef5da44684a16b204e7a70460cc8c4922a Mon Sep 17 00:00:00 2001 From: Thomas Voss Date: Fri, 21 Jun 2024 23:36:36 +0200 Subject: Basic constant folding implementation --- vendor/gmp-6.3.0/tests/devel/Makefile.am | 47 + vendor/gmp-6.3.0/tests/devel/Makefile.in | 673 ++++ vendor/gmp-6.3.0/tests/devel/README | 37 + vendor/gmp-6.3.0/tests/devel/gen-test-longlong_h.c | 140 + vendor/gmp-6.3.0/tests/devel/primes.c | 424 +++ vendor/gmp-6.3.0/tests/devel/sqrtrem_1_2.c | 401 +++ vendor/gmp-6.3.0/tests/devel/try.c | 3658 ++++++++++++++++++++ 7 files changed, 5380 insertions(+) create mode 100644 vendor/gmp-6.3.0/tests/devel/Makefile.am create mode 100644 vendor/gmp-6.3.0/tests/devel/Makefile.in create mode 100644 vendor/gmp-6.3.0/tests/devel/README create mode 100644 vendor/gmp-6.3.0/tests/devel/gen-test-longlong_h.c create mode 100644 vendor/gmp-6.3.0/tests/devel/primes.c create mode 100644 vendor/gmp-6.3.0/tests/devel/sqrtrem_1_2.c create mode 100644 vendor/gmp-6.3.0/tests/devel/try.c (limited to 'vendor/gmp-6.3.0/tests/devel') diff --git a/vendor/gmp-6.3.0/tests/devel/Makefile.am b/vendor/gmp-6.3.0/tests/devel/Makefile.am new file mode 100644 index 0000000..6c939a5 --- /dev/null +++ b/vendor/gmp-6.3.0/tests/devel/Makefile.am @@ -0,0 +1,47 @@ +## Process this file with automake to generate Makefile.in + +# Copyright 2000-2002, 2018 Free Software Foundation, Inc. +# +# This file is part of the GNU MP Library test suite. +# +# The GNU MP Library test suite is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3 of the License, +# or (at your option) any later version. +# +# The GNU MP Library test suite 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 a copy of the GNU General Public License along with +# the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. + + +AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/tests +AM_LDFLAGS = -no-install +LDADD = $(top_builddir)/tests/libtests.la $(top_builddir)/libgmp.la + +EXTRA_PROGRAMS = \ + sqrtrem_1_2 primes try test-add_ssaaaa test-sub_ddmmss + +EXTRA_DIST = gen-test-longlong_h.c + +allprogs: $(EXTRA_PROGRAMS) + +CLEANFILES = $(EXTRA_PROGRAMS) + +$(top_builddir)/tests/libtests.la: + cd $(top_builddir)/tests; $(MAKE) $(AM_MAKEFLAGS) libtests.la + +test-add_ssaaaa.c: gen-test-longlong_h$(EXEEXT_FOR_BUILD) + ./gen-test-longlong_h add >test-add_ssaaaa.c || (rm -f test-add_ssaaaa.c; exit 1) +CLEANFILES += test-add_ssaaaa.c + +test-sub_ddmmss.c: gen-test-longlong_h$(EXEEXT_FOR_BUILD) + ./gen-test-longlong_h sub >test-sub_ddmmss.c || (rm -f test-sub_ddmmss.c; exit 1) +CLEANFILES += test-sub_ddmmss.c + +gen-test-longlong_h$(EXEEXT_FOR_BUILD): gen-test-longlong_h.c + $(CC_FOR_BUILD) `test -f 'gen-test-longlong_h.c' || echo '$(srcdir)/'`gen-test-longlong_h.c -o gen-test-longlong_h$(EXEEXT_FOR_BUILD) +CLEANFILES += gen-test-longlong_h$(EXEEXT_FOR_BUILD) diff --git a/vendor/gmp-6.3.0/tests/devel/Makefile.in b/vendor/gmp-6.3.0/tests/devel/Makefile.in new file mode 100644 index 0000000..b299954 --- /dev/null +++ b/vendor/gmp-6.3.0/tests/devel/Makefile.in @@ -0,0 +1,673 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Copyright 2000-2002, 2018 Free Software Foundation, Inc. +# +# This file is part of the GNU MP Library test suite. +# +# The GNU MP Library test suite is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3 of the License, +# or (at your option) any later version. +# +# The GNU MP Library test suite 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 a copy of the GNU General Public License along with +# the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +EXTRA_PROGRAMS = sqrtrem_1_2$(EXEEXT) primes$(EXEEXT) try$(EXEEXT) \ + test-add_ssaaaa$(EXEEXT) test-sub_ddmmss$(EXEEXT) +subdir = tests/devel +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +primes_SOURCES = primes.c +primes_OBJECTS = primes.$(OBJEXT) +primes_LDADD = $(LDADD) +primes_DEPENDENCIES = $(top_builddir)/tests/libtests.la \ + $(top_builddir)/libgmp.la +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +sqrtrem_1_2_SOURCES = sqrtrem_1_2.c +sqrtrem_1_2_OBJECTS = sqrtrem_1_2.$(OBJEXT) +sqrtrem_1_2_LDADD = $(LDADD) +sqrtrem_1_2_DEPENDENCIES = $(top_builddir)/tests/libtests.la \ + $(top_builddir)/libgmp.la +test_add_ssaaaa_SOURCES = test-add_ssaaaa.c +test_add_ssaaaa_OBJECTS = test-add_ssaaaa.$(OBJEXT) +test_add_ssaaaa_LDADD = $(LDADD) +test_add_ssaaaa_DEPENDENCIES = $(top_builddir)/tests/libtests.la \ + $(top_builddir)/libgmp.la +test_sub_ddmmss_SOURCES = test-sub_ddmmss.c +test_sub_ddmmss_OBJECTS = test-sub_ddmmss.$(OBJEXT) +test_sub_ddmmss_LDADD = $(LDADD) +test_sub_ddmmss_DEPENDENCIES = $(top_builddir)/tests/libtests.la \ + $(top_builddir)/libgmp.la +try_SOURCES = try.c +try_OBJECTS = try.$(OBJEXT) +try_LDADD = $(LDADD) +try_DEPENDENCIES = $(top_builddir)/tests/libtests.la \ + $(top_builddir)/libgmp.la +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = +am__depfiles_maybe = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = primes.c sqrtrem_1_2.c test-add_ssaaaa.c test-sub_ddmmss.c \ + try.c +DIST_SOURCES = primes.c sqrtrem_1_2.c test-add_ssaaaa.c \ + test-sub_ddmmss.c try.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ABI = @ABI@ +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +ASMFLAGS = @ASMFLAGS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CALLING_CONVENTIONS_OBJS = @CALLING_CONVENTIONS_OBJS@ +CC = @CC@ +CCAS = @CCAS@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFN_LONG_LONG_LIMB = @DEFN_LONG_LONG_LIMB@ +DEFS = @DEFS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +EXEEXT_FOR_BUILD = @EXEEXT_FOR_BUILD@ +FGREP = @FGREP@ +GMP_LDFLAGS = @GMP_LDFLAGS@ +GMP_LIMB_BITS = @GMP_LIMB_BITS@ +GMP_NAIL_BITS = @GMP_NAIL_BITS@ +GREP = @GREP@ +HAVE_CLOCK_01 = @HAVE_CLOCK_01@ +HAVE_CPUTIME_01 = @HAVE_CPUTIME_01@ +HAVE_GETRUSAGE_01 = @HAVE_GETRUSAGE_01@ +HAVE_GETTIMEOFDAY_01 = @HAVE_GETTIMEOFDAY_01@ +HAVE_HOST_CPU_FAMILY_power = @HAVE_HOST_CPU_FAMILY_power@ +HAVE_HOST_CPU_FAMILY_powerpc = @HAVE_HOST_CPU_FAMILY_powerpc@ +HAVE_SIGACTION_01 = @HAVE_SIGACTION_01@ +HAVE_SIGALTSTACK_01 = @HAVE_SIGALTSTACK_01@ +HAVE_SIGSTACK_01 = @HAVE_SIGSTACK_01@ +HAVE_STACK_T_01 = @HAVE_STACK_T_01@ +HAVE_SYS_RESOURCE_H_01 = @HAVE_SYS_RESOURCE_H_01@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBCURSES = @LIBCURSES@ +LIBGMPXX_LDFLAGS = @LIBGMPXX_LDFLAGS@ +LIBGMP_DLL = @LIBGMP_DLL@ +LIBGMP_LDFLAGS = @LIBGMP_LDFLAGS@ +LIBM = @LIBM@ +LIBM_FOR_BUILD = @LIBM_FOR_BUILD@ +LIBOBJS = @LIBOBJS@ +LIBREADLINE = @LIBREADLINE@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +M4 = @M4@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPEED_CYCLECOUNTER_OBJ = @SPEED_CYCLECOUNTER_OBJ@ +STRIP = @STRIP@ +TAL_OBJECT = @TAL_OBJECT@ +TUNE_LIBS = @TUNE_LIBS@ +TUNE_SQR_OBJ = @TUNE_SQR_OBJ@ +U_FOR_BUILD = @U_FOR_BUILD@ +VERSION = @VERSION@ +WITH_READLINE_01 = @WITH_READLINE_01@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gmp_srclinks = @gmp_srclinks@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +mpn_objects = @mpn_objects@ +mpn_objs_in_libgmp = @mpn_objs_in_libgmp@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/tests +AM_LDFLAGS = -no-install +LDADD = $(top_builddir)/tests/libtests.la $(top_builddir)/libgmp.la +EXTRA_DIST = gen-test-longlong_h.c +CLEANFILES = $(EXTRA_PROGRAMS) test-add_ssaaaa.c test-sub_ddmmss.c \ + gen-test-longlong_h$(EXEEXT_FOR_BUILD) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu --ignore-deps tests/devel/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu --ignore-deps tests/devel/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +primes$(EXEEXT): $(primes_OBJECTS) $(primes_DEPENDENCIES) $(EXTRA_primes_DEPENDENCIES) + @rm -f primes$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(primes_OBJECTS) $(primes_LDADD) $(LIBS) + +sqrtrem_1_2$(EXEEXT): $(sqrtrem_1_2_OBJECTS) $(sqrtrem_1_2_DEPENDENCIES) $(EXTRA_sqrtrem_1_2_DEPENDENCIES) + @rm -f sqrtrem_1_2$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(sqrtrem_1_2_OBJECTS) $(sqrtrem_1_2_LDADD) $(LIBS) + +test-add_ssaaaa$(EXEEXT): $(test_add_ssaaaa_OBJECTS) $(test_add_ssaaaa_DEPENDENCIES) $(EXTRA_test_add_ssaaaa_DEPENDENCIES) + @rm -f test-add_ssaaaa$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_add_ssaaaa_OBJECTS) $(test_add_ssaaaa_LDADD) $(LIBS) + +test-sub_ddmmss$(EXEEXT): $(test_sub_ddmmss_OBJECTS) $(test_sub_ddmmss_DEPENDENCIES) $(EXTRA_test_sub_ddmmss_DEPENDENCIES) + @rm -f test-sub_ddmmss$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_sub_ddmmss_OBJECTS) $(test_sub_ddmmss_LDADD) $(LIBS) + +try$(EXEEXT): $(try_OBJECTS) $(try_DEPENDENCIES) $(EXTRA_try_DEPENDENCIES) + @rm -f try$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(try_OBJECTS) $(try_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(AM_V_CC)$(COMPILE) -c -o $@ $< + +.c.obj: + $(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: + $(AM_V_CC)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +allprogs: $(EXTRA_PROGRAMS) + +$(top_builddir)/tests/libtests.la: + cd $(top_builddir)/tests; $(MAKE) $(AM_MAKEFLAGS) libtests.la + +test-add_ssaaaa.c: gen-test-longlong_h$(EXEEXT_FOR_BUILD) + ./gen-test-longlong_h add >test-add_ssaaaa.c || (rm -f test-add_ssaaaa.c; exit 1) + +test-sub_ddmmss.c: gen-test-longlong_h$(EXEEXT_FOR_BUILD) + ./gen-test-longlong_h sub >test-sub_ddmmss.c || (rm -f test-sub_ddmmss.c; exit 1) + +gen-test-longlong_h$(EXEEXT_FOR_BUILD): gen-test-longlong_h.c + $(CC_FOR_BUILD) `test -f 'gen-test-longlong_h.c' || echo '$(srcdir)/'`gen-test-longlong_h.c -o gen-test-longlong_h$(EXEEXT_FOR_BUILD) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/vendor/gmp-6.3.0/tests/devel/README b/vendor/gmp-6.3.0/tests/devel/README new file mode 100644 index 0000000..77fa65d --- /dev/null +++ b/vendor/gmp-6.3.0/tests/devel/README @@ -0,0 +1,37 @@ +Copyright 2000, 2001 Free Software Foundation, Inc. + +This file is part of the GNU MP Library test suite. + +The GNU MP Library test suite is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 3 of the License, +or (at your option) any later version. + +The GNU MP Library test suite 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 a copy of the GNU General Public License along with +the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. + + + + + DEVELOPMENT TEST PROGRAMS + + +This directory contains various programs used during development. Casual +GMP users are unlikely to find anything of interest. + +Nothing here is built or installed, nor even run in a "make check", but +there's Makefile rules to build each program, or "allprogs" to build +everything. + + + +---------------- +Local variables: +mode: text +fill-column: 76 +End: diff --git a/vendor/gmp-6.3.0/tests/devel/gen-test-longlong_h.c b/vendor/gmp-6.3.0/tests/devel/gen-test-longlong_h.c new file mode 100644 index 0000000..939c3f2 --- /dev/null +++ b/vendor/gmp-6.3.0/tests/devel/gen-test-longlong_h.c @@ -0,0 +1,140 @@ +/* +Copyright 2020 Free Software Foundation, Inc. + +This file is part of the GNU MP Library test suite. + +The GNU MP Library test suite is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 3 of the License, +or (at your option) any later version. + +The GNU MP Library test suite 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 a copy of the GNU General Public License along with +the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */ + +#include +#include +#include + +typedef unsigned long mp_limb_t; /* neat */ + +void +one (const char *op, size_t ind, mp_limb_t m0, mp_limb_t s0) +{ + printf ("static void f%zu(mp_limb_t*r1p,mp_limb_t*r0p){", ind); + printf ("mp_limb_t r1,r0;"); + printf ("%s(r1,r0,0,%ld,0,%ld);", op, (long) m0, (long) s0); + printf ("*r1p=r1;*r0p=r0;"); + printf ("}\n"); +} + +mp_limb_t ops[1000]; + +enum what_t {ADD, SUB}; + +int +main (int argc, char **argv) +{ + size_t n_operands = 0; + size_t n_functions = 0; + const char *op; + enum what_t what; + + if (argc == 2 && strcmp (argv[1], "add") == 0) + { + op = "add_ssaaaa"; + what = ADD; + } + else if (argc == 2 && strcmp (argv[1], "sub") == 0) + { + op = "sub_ddmmss"; + what = SUB; + } + else + { + fprintf (stderr, "what do yuo want me to do?\n"); + exit (1); + } + + for (int i = 0; i < 16; i++) + { + ops[n_operands++] = 1 << i; + ops[n_operands++] = -(1 << i); + ops[n_operands++] = (1 << i) - 1; + ops[n_operands++] = -(1 << i) - 1; + } + + printf ("#include \n"); + printf ("#include \n"); + printf ("#include \"gmp-impl.h\"\n"); + printf ("#include \"longlong.h\"\n"); + + /* Print out ops[] definition. */ + printf ("static const int ops[%zu] = {\n", n_operands); + for (int i = 0; i < n_operands; i++) + { + printf ("%ld,", (long) ops[i]); + if ((i + 1) % 4 == 0) + puts (""); + } + printf ("};\n"); + + /* Generate functions and print them. */ + for (int i = 0; i < n_operands; i++) + { + for (int j = 0; j < n_operands; j++) + { + one (op, n_functions++, ops[i], ops[j]); + } + } + + /* Print out function pointer table. */ + printf ("typedef void (*func_t) (mp_limb_t*, mp_limb_t*);\n"); + printf ("static const func_t funcs[%zu] = {\n", n_functions); + for (size_t i = 0; i < n_functions; i++) + { + printf ("f%zu,", i); + if ((i + 1) % 16 == 0) + puts (""); + } + printf ("};\n"); + + /* Print out table of reference results. */ + printf ("static const int ref[%zu][2] = {\n", n_functions); + for (int i = 0; i < n_operands; i++) + { + for (int j = 0; j < n_operands; j++) + { + if (what == ADD) + printf ("{%6ld,%2ld},", (long) ( ops[i] + ops[j]), (long) ((mp_limb_t) ((ops[i] + ops[j]) < ops[i]))); + else /* SUB */ + printf ("{%6ld,%2ld},", (long) ( ops[i] - ops[j]), (long) (-(mp_limb_t) (ops[i] < ops[j]))); + if ((i * n_operands + j) % 8 == 0) + puts (""); + } + } + printf ("};\n"); + + printf ("int main ()\n{\n"); + printf (" mp_limb_t r1, r0;\n"); + printf (" int err = 0;\n"); + printf (" size_t ind = 0;\n"); + printf (" for (size_t i = 0; i < %zu; i++)\n", n_functions); + printf (" {\n"); + printf (" int ii = i / %zu, jj = i %% %zu;\n", n_operands, n_operands); + printf (" funcs[i](&r1, &r0);\n"); + printf (" if (r0 != (mp_limb_signed_t) ref[ind][0] || r1 != (mp_limb_signed_t) ref[ind][1]) {\n"); + printf (" printf (\"error for f%%zu(%%d,%%d): want (%%d,%%d) got (%%d,%%d)\\n\", i, (int) ops[ii], (int) ops[jj], ref[ind][1], ref[ind][0], (int) r1, (int) r0);\n"); + printf (" err++;\n"); + printf (" }\n"); + printf (" ind++;\n"); + printf (" }\n"); + + printf (" return err != 0;\n"); + printf ("}\n"); + return 0; +} diff --git a/vendor/gmp-6.3.0/tests/devel/primes.c b/vendor/gmp-6.3.0/tests/devel/primes.c new file mode 100644 index 0000000..8e58962 --- /dev/null +++ b/vendor/gmp-6.3.0/tests/devel/primes.c @@ -0,0 +1,424 @@ +/* +Copyright 2018-2020 Free Software Foundation, Inc. + +This file is part of the GNU MP Library test suite. + +The GNU MP Library test suite is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 3 of the License, +or (at your option) any later version. + +The GNU MP Library test suite 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 a copy of the GNU General Public License along with +the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */ + +/* Usage: + + ./primes [p|c] [n0] + + Checks mpz_probab_prime_p(n, r) exhaustively, starting from n=n0 + up to nMax. + If n0 * n0 > nMax, the intervall is sieved piecewise, else the + full intervall [0..nMax] is sieved at once. + With the parameter "p" (or nothing), tests all numbers. With "c" + only composites are tested. + + ./primes n|N [n0] + + Checks mpz_nextprime() exhaustively, starting from n=n0 up to + nMax. With "n", only the sequence of primes is checked, with "N" + the function is tested on every number in the interval. + + WARNING: The full intervall [0..nMax] is sieved at once, even if + only a piece is needed. This may require a lot of memory! + + */ + +#include +#include +#include "gmp-impl.h" +#include "longlong.h" +#include "tests.h" +#define STOP(x) return (x) +/* #define STOP(x) x */ +#define REPS 10 +/* #define TRACE(x,n) if ((n)>1) {x;} */ +#define TRACE(x,n) + +/* The full primesieve.c is included, just for block_resieve, that + is not exported ... */ +#undef gmp_primesieve +#include "../../primesieve.c" + +#ifndef BLOCK_SIZE +#define BLOCK_SIZE 2048 +#endif + +/*********************************************************/ +/* Section sieve: sieving functions and tools for primes */ +/*********************************************************/ + +static mp_size_t +primesieve_size (mp_limb_t n) { return n_fto_bit(n) / GMP_LIMB_BITS + 1; } + +/*************************************************************/ +/* Section macros: common macros, for swing/fac/bin (&sieve) */ +/*************************************************************/ + +#define LOOP_ON_SIEVE_CONTINUE(prime,end) \ + __max_i = (end); \ + \ + do { \ + ++__i; \ + if ((*__sieve & __mask) == 0) \ + { \ + mp_limb_t prime; \ + prime = id_to_n(__i) + +#define LOOP_ON_SIEVE_BEGIN(prime,start,end,off,sieve) \ + do { \ + mp_limb_t __mask, *__sieve, __max_i, __i; \ + \ + __i = (start)-(off); \ + __sieve = (sieve) + __i / GMP_LIMB_BITS; \ + __mask = CNST_LIMB(1) << (__i % GMP_LIMB_BITS); \ + __i += (off); \ + \ + LOOP_ON_SIEVE_CONTINUE(prime,end) + +#define LOOP_ON_SIEVE_STOP \ + } \ + __mask = __mask << 1 | __mask >> (GMP_LIMB_BITS-1); \ + __sieve += __mask & 1; \ + } while (__i <= __max_i) + +#define LOOP_ON_SIEVE_END \ + LOOP_ON_SIEVE_STOP; \ + } while (0) + +mpz_t g; + +int something_wrong (mpz_t er, int exp) +{ + fprintf (stderr, "value = %lu , expected = %i\n", mpz_get_ui (er), exp); + return -1; +} + +int +check_pprime (unsigned long begin, unsigned long end, int composites) +{ + begin = (begin / 6U) * 6U; + for (;(begin < 2) & (begin <= end); ++begin) + { + *(g->_mp_d) = begin; + TRACE(printf ("-%li ", begin),1); + if (mpz_probab_prime_p (g, REPS)) + STOP (something_wrong (g, 0)); + } + for (;(begin < 4) & (begin <= end); ++begin) + { + *(g->_mp_d) = begin; + TRACE(printf ("+%li ", begin),2); + if (!composites && !mpz_probab_prime_p (g, REPS)) + STOP (something_wrong (g, 1)); + } + if (end > 4) { + if ((end > 10000) && (begin > end / begin)) + { + mp_limb_t *sieve, *primes; + mp_size_t size_s, size_p, off; + unsigned long start; + + mpz_set_ui (g, end); + mpz_sqrt (g, g); + start = mpz_get_ui (g) + GMP_LIMB_BITS; + size_p = primesieve_size (start); + + primes = __GMP_ALLOCATE_FUNC_LIMBS (size_p); + gmp_primesieve (primes, start); + + size_s = BLOCK_SIZE * 2; + sieve = __GMP_ALLOCATE_FUNC_LIMBS (size_s); + off = n_cto_bit(begin); + + do { + TRACE (printf ("off =%li\n", off),3); + block_resieve (sieve, BLOCK_SIZE, off, primes); + TRACE (printf ("LOOP =%li - %li\n", id_to_n (off+1), id_to_n (off + BLOCK_SIZE * GMP_LIMB_BITS)),3); + LOOP_ON_SIEVE_BEGIN (prime, off, off + BLOCK_SIZE * GMP_LIMB_BITS - 1, + off, sieve); + + do { + *(g->_mp_d) = begin; + TRACE(printf ("-%li ", begin),1); + if (mpz_probab_prime_p (g, REPS)) + STOP (something_wrong (g, 0)); + if ((begin & 0xff) == 0) + { + spinner(); + if ((begin & 0xfffffff) == 0) + printf ("%li (0x%lx)\n", begin, begin); + } + } while (++begin < prime); + + *(g->_mp_d) = begin; + TRACE(printf ("+%li ", begin),2); + if (!composites && ! mpz_probab_prime_p (g, REPS)) + STOP (something_wrong (g, 1)); + ++begin; + + LOOP_ON_SIEVE_END; + off += BLOCK_SIZE * GMP_LIMB_BITS; + } while (begin < end); + + __GMP_FREE_FUNC_LIMBS (sieve, size_s); + __GMP_FREE_FUNC_LIMBS (primes, size_p); + } + else + { + mp_limb_t *sieve; + mp_size_t size; + unsigned long start; + + size = primesieve_size (end); + + sieve = __GMP_ALLOCATE_FUNC_LIMBS (size); + gmp_primesieve (sieve, end); + start = MAX (begin, 5) | 1; + LOOP_ON_SIEVE_BEGIN (prime, n_cto_bit(start), + n_fto_bit (end), 0, sieve); + + do { + *(g->_mp_d) = begin; + TRACE(printf ("-%li ", begin),1); + if (mpz_probab_prime_p (g, REPS)) + STOP (something_wrong (g, 0)); + if ((begin & 0xff) == 0) + { + spinner(); + if ((begin & 0xfffffff) == 0) + printf ("%li (0x%lx)\n", begin, begin); + } + } while (++begin < prime); + + *(g->_mp_d) = begin; + TRACE(printf ("+%li ", begin),2); + if (!composites && ! mpz_probab_prime_p (g, REPS)) + STOP (something_wrong (g, 1)); + ++begin; + + LOOP_ON_SIEVE_END; + + __GMP_FREE_FUNC_LIMBS (sieve, size); + } + } + + for (;begin < end; ++begin) + { + *(g->_mp_d) = begin; + TRACE(printf ("-%li ", begin),1); + if (mpz_probab_prime_p (g, REPS)) + STOP (something_wrong (g, 0)); + } + + gmp_printf ("%Zd\n", g); + return 0; +} + +int +check_nprime (unsigned long begin, unsigned long end) +{ + if (begin < 2) + { + *(g->_mp_d) = begin; + g->_mp_size = begin; + TRACE(printf ("%li ", begin),1); + mpz_nextprime (g, g); + if (mpz_cmp_ui (g, 2) != 0) + STOP (something_wrong (g, 2)); + begin = mpz_get_ui (g); + } + if (begin < 3) + { + *(g->_mp_d) = begin; + TRACE(printf ("%li ", begin),1); + mpz_nextprime (g, g); + if (mpz_cmp_ui (g, 3) != 0) + STOP (something_wrong (g, 3)); + begin = mpz_get_ui (g); + } + if (end > 4) + { + mp_limb_t *sieve; + mp_size_t size; + unsigned long start; + + size = primesieve_size (end); + + sieve = __GMP_ALLOCATE_FUNC_LIMBS (size); + gmp_primesieve (sieve, end); + start = MAX (begin, 5) | 1; + *(g->_mp_d) = begin; + LOOP_ON_SIEVE_BEGIN (prime, n_cto_bit(start), + n_fto_bit (end), 0, sieve); + + mpz_nextprime (g, g); + if (mpz_cmp_ui (g, prime) != 0) + STOP (something_wrong (g, prime)); + + if (prime - start > 200) + { + start = prime; + spinner(); + if (prime - begin > 0xfffffff) + { + begin = prime; + printf ("%li (0x%lx)\n", begin, begin); + } + } + + LOOP_ON_SIEVE_END; + + __GMP_FREE_FUNC_LIMBS (sieve, size); + } + + if (mpz_cmp_ui (g, end) < 0) + { + mpz_nextprime (g, g); + if (mpz_cmp_ui (g, end) <= 0) + STOP (something_wrong (g, -1)); + } + + gmp_printf ("%Zd\n", g); + return 0; +} + +int +check_Nprime (unsigned long begin, unsigned long end) +{ + mpz_t op; + mpz_init_set_ui (op, end); + + for (;begin < 2; ++begin) + { + *(op->_mp_d) = begin; + op->_mp_size = begin; + TRACE(printf ("%li ", begin),1); + mpz_nextprime (g, op); + if (mpz_cmp_ui (g, 2) != 0) + STOP (something_wrong (g, 2)); + } + if (begin < 3) + { + *(op->_mp_d) = begin; + TRACE(printf ("%li ", begin),1); + mpz_nextprime (g, op); + if (mpz_cmp_ui (g, 3) != 0) + STOP (something_wrong (g, 3)); + begin = 3; + } + if (end > 4) + { + mp_limb_t *sieve; + mp_size_t size; + unsigned long start; + unsigned long opl; + + size = primesieve_size (end); + + sieve = __GMP_ALLOCATE_FUNC_LIMBS (size); + gmp_primesieve (sieve, end); + start = MAX (begin, 5) | 1; + opl = begin; + LOOP_ON_SIEVE_BEGIN (prime, n_cto_bit(start), + n_fto_bit (end), 0, sieve); + + do { + *(op->_mp_d) = opl; + mpz_nextprime (g, op); + if (mpz_cmp_ui (g, prime) != 0) + STOP (something_wrong (g, prime)); + ++opl; + } while (opl < prime); + + if (prime - start > 200) + { + start = prime; + spinner(); + if (prime - begin > 0xfffffff) + { + begin = prime; + printf ("%li (0x%lx)\n", begin, begin); + } + } + + LOOP_ON_SIEVE_END; + + __GMP_FREE_FUNC_LIMBS (sieve, size); + } + + if (mpz_cmp_ui (g, end) < 0) + { + mpz_nextprime (g, g); + if (mpz_cmp_ui (g, end) <= 0) + STOP (something_wrong (g, -1)); + } + + gmp_printf ("%Zd\n", g); + return 0; +} + +int +main (int argc, char **argv) +{ + int ret, mode = 0; + unsigned long begin = 0, end = 0; + + for (;argc > 1;--argc,++argv) + switch (*argv[1]) { + case 'p': + mode = 0; + break; + case 'c': + mode = 2; + break; + case 'n': + mode = 1; + break; + case 'N': + mode = 3; + break; + default: + begin = end; + end = atol (argv[1]); + } + + if (begin >= end) + { + fprintf (stderr, "usage: primes [N|n|p|c] [n0] \n"); + exit (1); + } + + mpz_init_set_ui (g, ULONG_MAX); + + switch (mode) { + case 1: + ret = check_nprime (begin, end); + break; + case 3: + ret = check_Nprime (begin, end); + break; + default: + ret = check_pprime (begin, end, mode); + } + + mpz_clear (g); + + if (ret == 0) + printf ("Prime tests checked in [%lu - %lu] [0x%lx - 0x%lx].\n", begin, end, begin, end); + return ret; +} diff --git a/vendor/gmp-6.3.0/tests/devel/sqrtrem_1_2.c b/vendor/gmp-6.3.0/tests/devel/sqrtrem_1_2.c new file mode 100644 index 0000000..3951191 --- /dev/null +++ b/vendor/gmp-6.3.0/tests/devel/sqrtrem_1_2.c @@ -0,0 +1,401 @@ +/* +Copyright 2017 Free Software Foundation, Inc. + +This file is part of the GNU MP Library test suite. + +The GNU MP Library test suite is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 3 of the License, +or (at your option) any later version. + +The GNU MP Library test suite 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 a copy of the GNU General Public License along with +the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */ + +/* Usage: + + ./sqrtrem_1_2 x + + Checks mpn_sqrtrem() exhaustively, starting from 0, incrementing + the operand by a single unit, until all values handled by + mpn_sqrtrem{1,2} are tested. SLOW. + + ./sqrtrem_1_2 s 1 + + Checks some special cases for mpn_sqrtrem(). I.e. values of the form + 2^k*i and 2^k*(i+1)-1, with k=2^n and 0 +#include +#include "gmp-impl.h" +#include "longlong.h" +#include "tests.h" +#define STOP(x) return (x) +/* #define STOP(x) x */ +#define SPINNER(v) \ + do { \ + MPN_SIZEINBASE_2EXP (spinner_count, q, v, 1); \ + --spinner_count; \ + spinner(); \ + } while (0) + +int something_wrong (mp_limb_t er, mp_limb_t ec, mp_limb_t es) +{ + fprintf (stderr, "root = %lu , rem = {%lu , %lu}\n", (long unsigned) es,(long unsigned) ec,(long unsigned) er); + return -1; +} + +int +check_all_values (int justone, int quick) +{ + mp_limb_t es, mer, er, s[1], r[2], q[2]; + mp_size_t x; + unsigned bits; + + es=1; + if (quick) { + printf ("Quick, skipping some... (%u)\n", GMP_NUMB_BITS - 2); + es <<= GMP_NUMB_BITS / 2 - 1; + } + er=0; + mer= es << 1; + *q = es * es; + printf ("All values tested, up to bits:\n"); + do { + x = mpn_sqrtrem (s, r, q, 1); + if (UNLIKELY (x != (er != 0)) || UNLIKELY (*s != es) + || UNLIKELY ((x == 1) && (er != *r))) + STOP (something_wrong (er, 0, es)); + + if (UNLIKELY (er == mer)) { + ++es; + if (UNLIKELY ((es & 0xff) == 0)) + SPINNER(1); + mer +=2; /* mer = es * 2 */ + er = 0; + } else + ++er; + ++*q; + } while (*q != 0); + q[1] = 1; + SPINNER(2); + printf ("\nValues of a single limb, tested.\n"); + if (justone) return 0; + printf ("All values tested, up to bits:\n"); + do { + x = mpn_sqrtrem (s, r, q, 2); + if (UNLIKELY (x != (er != 0)) || UNLIKELY (*s != es) + || UNLIKELY ((x == 1) && (er != *r))) + STOP (something_wrong (er, 0, es)); + + if (UNLIKELY (er == mer)) { + ++es; + if (UNLIKELY ((es & 0x7f) == 0)) + SPINNER(2); + mer +=2; /* mer = es * 2 */ + if (UNLIKELY (mer == 0)) + break; + er = 0; + } else + ++er; + q[1] += (++*q == 0); + } while (1); + SPINNER(2); + printf ("\nValues with at most a limb for reminder, tested.\n"); + printf ("Testing more values not supported, jet.\n"); + return 0; +} + +mp_limb_t +upd (mp_limb_t *s, mp_limb_t k) +{ + mp_limb_t _s = *s; + + while (k > _s * 2) + { + k -= _s * 2 + 1; + ++_s; + } + *s = _s; + return k; +} + +mp_limb_t +upd1 (mp_limb_t *s, mp_limb_t k) +{ + mp_limb_t _s = *s; + + if (LIKELY (k < _s * 2)) return k + 1; + *s = _s + 1; + return k - _s * 2; +} + +int +check_some_values (int justone, int quick) +{ + mp_limb_t es, her, er, k, s[1], r[2], q[2]; + mp_size_t x; + unsigned bits; + + es = 1 << 1; + if (quick) { + es <<= GMP_NUMB_BITS / 4 - 1; + printf ("Quick, skipping some... (%u)\n", GMP_NUMB_BITS / 2); + } + er = 0; + *q = es * es; + printf ("High-half values tested, up to bits:\n"); + do { + k = *q - 1; + do { + x = mpn_sqrtrem (s, r, q, 1); + if (UNLIKELY (x != (er != 0)) || UNLIKELY (*s != es) + || UNLIKELY ((x == 1) && (er != *r))) + STOP (something_wrong (er, 0, es)); + + if (UNLIKELY ((es & 0xffff) == 0)) + SPINNER(1); + if ((*q & k) == 0) { + *q |= k; + er = upd (&es, k + er); + } else { + ++*q; + er = upd1 (&es, er); + } + } while (es & k); + } while (*q != 0); + q[1] = 1; + SPINNER(2); + printf ("\nValues of a single limb, tested.\n"); + if (justone) return 0; + if (quick) { + es <<= GMP_NUMB_BITS / 2 - 1; + q[1] <<= GMP_NUMB_BITS - 2; + printf ("Quick, skipping some... (%u)\n", GMP_NUMB_BITS - 2); + } + printf ("High-half values tested, up to bits:\n"); + do { + x = mpn_sqrtrem (s, r, q, 2); + if (UNLIKELY (x != (er != 0)) || UNLIKELY (*s != es) + || UNLIKELY ((x == 1) && (er != *r))) + STOP (something_wrong (er, 0, es)); + + if (*q == 0) { + *q = GMP_NUMB_MAX; + if (UNLIKELY ((es & 0xffff) == 0)) { + if (UNLIKELY (es == GMP_NUMB_HIGHBIT)) + break; + SPINNER(2); + } + /* er = er + GMP_NUMB_MAX - 1 - es*2 // postponed */ + ++es; + /* er = er + GMP_NUMB_MAX - 1 - 2*(es-1) = + = er +(GMP_NUMB_MAX + 1)- 2* es = er - 2*es */ + er = upd (&es, er - 2 * es); + } else { + *q = 0; + ++q[1]; + er = upd1 (&es, er); + } + } while (1); + SPINNER(2); + printf ("\nValues with at most a limb for reminder, tested.\n"); + er = GMP_NUMB_MAX; her = 0; + + printf ("High-half values tested, up to bits:\n"); + do { + x = mpn_sqrtrem (s, r, q, 2); + if (UNLIKELY (x != (her?2:(er != 0))) || UNLIKELY (*s != es) + || UNLIKELY ((x != 0) && ((er != *r) || ((x == 2) && (r[1] != 1))))) + STOP (something_wrong (er, her, es)); + + if (*q == 0) { + *q = GMP_NUMB_MAX; + if (UNLIKELY ((es & 0xffff) == 0)) { + SPINNER(2); + } + if (her) { + ++es; + her = 0; + er = er - 2 * es; + } else { + her = --er != GMP_NUMB_MAX; + if (her & (er > es * 2)) { + er -= es * 2 + 1; + her = 0; + ++es; + } + } + } else { + *q = 0; + if (++q[1] == 0) break; + if ((her == 0) | (er < es * 2)) { + her += ++er == 0; + } else { + er -= es * 2; + her = 0; + ++es; + } + } + } while (1); + printf ("| %u\nValues of at most two limbs, tested.\n", GMP_NUMB_BITS*2); + return 0; +} + +int +check_corner_cases (int justone, int quick) +{ + mp_limb_t es, er, s[1], r[2], q[2]; + mp_size_t x; + unsigned bits; + + es = 1; + if (quick) { + es <<= GMP_NUMB_BITS / 2 - 1; + printf ("Quick, skipping some... (%u)\n", GMP_NUMB_BITS - 2); + } + er = 0; + *q = es*es; + printf ("Corner cases tested, up to bits:\n"); + do { + x = mpn_sqrtrem (s, r, q, 1); + if (UNLIKELY (x != (er != 0)) || UNLIKELY (*s != es) + || UNLIKELY ((x == 1) && (er != *r))) + STOP (something_wrong (er, 0, es)); + + if (er != 0) { + ++es; + if (UNLIKELY ((es & 0xffff) == 0)) + SPINNER(1); + er = 0; + ++*q; + } else { + er = es * 2; + *q += er; + } + } while (*q != 0); + q[1] = 1; + SPINNER(2); + printf ("\nValues of a single limb, tested.\n"); + if (justone) return 0; + if (quick) { + es <<= GMP_NUMB_BITS / 2 - 1; + q[1] <<= GMP_NUMB_BITS - 2; + printf ("Quick, skipping some... (%u)\n", GMP_NUMB_BITS - 2); + --es; + --q[1]; + q[0] -= es*2+1; + } + printf ("Corner cases tested, up to bits:\n"); + do { + x = mpn_sqrtrem (s, r, q, 2); + if (UNLIKELY (x != (er != 0)) || UNLIKELY (*s != es) + || UNLIKELY ((x == 1) && (er != *r))) + STOP (something_wrong (er, 0, es)); + + if (er != 0) { + ++es; + if (UNLIKELY ((es & 0xff) == 0)) + SPINNER(2); + er = 0; + q[1] += (++*q == 0); + if (UNLIKELY (es == GMP_NUMB_HIGHBIT)) + break; + } else { + er = es * 2; + add_ssaaaa (q[1], *q, q[1], *q, 0, er); + } + } while (1); + SPINNER(2); + printf ("\nValues with at most a limb for reminder, tested.\nCorner cases tested, up to bits:\n"); + x = mpn_sqrtrem (s, r, q, 2); + if ((*s != es) || (x != 0)) + STOP (something_wrong (0, 0, es)); + q[1] += 1; + x = mpn_sqrtrem (s, r, q, 2); + if ((*s != es) || (x != 2) || (*r != 0) || (r[1] != 1)) + STOP (something_wrong (0, 1, es)); + ++es; + q[1] += (++*q == 0); + do { + x = mpn_sqrtrem (s, r, q, 2); + if (UNLIKELY (x != (er != 0) * 2) || UNLIKELY (*s != es) + || UNLIKELY ((x == 2) && ((er != *r) || (r[1] != 1)))) + STOP (something_wrong (er, er != 0, es)); + + if (er != 0) { + ++es; + if (UNLIKELY (es == 0)) + break; + if (UNLIKELY ((es & 0xff) == 0)) + SPINNER(2); + er = 0; + q[1] += (++*q == 0); + } else { + er = es * 2; + add_ssaaaa (q[1], *q, q[1], *q, 1, er); + } + } while (1); + printf ("| %u\nValues of at most two limbs, tested.\n", GMP_NUMB_BITS*2); + return 0; +} + +int +main (int argc, char **argv) +{ + int mode = 0; + int justone = 0; + int quick = 0; + + for (;argc > 1;--argc,++argv) + switch (*argv[1]) { + default: + fprintf (stderr, "usage: sqrtrem_1_2 [x|c|s] [1|2] [q]\n"); + exit (1); + case 'x': + mode = 0; + break; + case 'c': + mode = 1; + break; + case 's': + mode = 2; + break; + case 'q': + quick = 1; + break; + case '1': + justone = 1; + break; + case '2': + justone = 0; + } + + switch (mode) { + default: + return check_all_values (justone, quick); + case 1: + return check_corner_cases (justone, quick); + case 2: + return check_some_values (justone, quick); + } +} diff --git a/vendor/gmp-6.3.0/tests/devel/try.c b/vendor/gmp-6.3.0/tests/devel/try.c new file mode 100644 index 0000000..f8f4a1c --- /dev/null +++ b/vendor/gmp-6.3.0/tests/devel/try.c @@ -0,0 +1,3658 @@ +/* Run some tests on various mpn routines. + + THIS IS A TEST PROGRAM USED ONLY FOR DEVELOPMENT. IT'S ALMOST CERTAIN TO + BE SUBJECT TO INCOMPATIBLE CHANGES IN FUTURE VERSIONS OF GMP. + +Copyright 2000-2006, 2008, 2009, 2011, 2012 Free Software Foundation, Inc. + +This file is part of the GNU MP Library test suite. + +The GNU MP Library test suite is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 3 of the License, +or (at your option) any later version. + +The GNU MP Library test suite 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 a copy of the GNU General Public License along with +the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */ + + +/* Usage: try [options] ... + + For example, "./try mpn_add_n" to run tests of that function. + + Combinations of alignments and overlaps are tested, with redzones above + or below the destinations, and with the sources write-protected. + + The number of tests performed becomes ridiculously large with all the + combinations, and for that reason this can't be a part of a "make check", + it's meant only for development. The code isn't very pretty either. + + During development it can help to disable the redzones, since seeing the + rest of the destination written can show where the wrong part is, or if + the dst pointers are off by 1 or whatever. The magic DEADVAL initial + fill (see below) will show locations never written. + + The -s option can be used to test only certain size operands, which is + useful if some new code doesn't yet support say sizes less than the + unrolling, or whatever. + + When a problem occurs it'll of course be necessary to run the program + under gdb to find out quite where, how and why it's going wrong. Disable + the spinner with the -W option when doing this, or single stepping won't + work. Using the "-1" option to run with simple data can be useful. + + New functions to test can be added in try_array[]. If a new TYPE is + required then add it to the existing constants, set up its parameters in + param_init(), and add it to the call() function. Extra parameter fields + can be added if necessary, or further interpretations given to existing + fields. + + + Portability: + + This program is not designed for use on Cray vector systems under Unicos, + it will fail to compile due to missing _SC_PAGE_SIZE. Those systems + don't really have pages or mprotect. We could arrange to run the tests + without the redzones, but we haven't bothered currently. + + + Enhancements: + + umul_ppmm support is not very good, lots of source data is generated + whereas only two limbs are needed. + + Make a little scheme for interpreting the "SIZE" selections uniformly. + + Make tr->size==SIZE_2 work, for the benefit of find_a which wants just 2 + source limbs. Possibly increase the default repetitions in that case. + + Automatically detect gdb and disable the spinner (use -W for now). + + Make a way to re-run a failing case in the debugger. Have an option to + snapshot each test case before it's run so the data is available if a + segv occurs. (This should be more reliable than the current print_all() + in the signal handler.) + + When alignment means a dst isn't hard against the redzone, check the + space in between remains unchanged. + + When a source overlaps a destination, don't run both s[i].high 0 and 1, + as s[i].high has no effect. Maybe encode s[i].high into overlap->s[i]. + + When partial overlaps aren't done, don't loop over source alignments + during overlaps. + + Try to make the looping code a bit less horrible. Right now it's pretty + hard to see what iterations are actually done. + + Perhaps specific setups and loops for each style of function under test + would be clearer than a parameterized general loop. There's lots of + stuff common to all functions, but the exceptions get messy. + + When there's no overlap, run with both src>dst and src +#include +#include +#include +#include +#include +#include + +#if HAVE_UNISTD_H +#include +#endif + +#if HAVE_SYS_MMAN_H +#include +#endif + +#include "gmp-impl.h" +#include "longlong.h" +#include "tests.h" + + +#if !HAVE_DECL_OPTARG +extern char *optarg; +extern int optind, opterr; +#endif + +#if ! HAVE_DECL_SYS_NERR +extern int sys_nerr; +#endif + +#if ! HAVE_DECL_SYS_ERRLIST +extern char *sys_errlist[]; +#endif + +#if ! HAVE_STRERROR +char * +strerror (int n) +{ + if (n < 0 || n >= sys_nerr) + return "errno out of range"; + else + return sys_errlist[n]; +} +#endif + +/* Rumour has it some systems lack a define of PROT_NONE. */ +#ifndef PROT_NONE +#define PROT_NONE 0 +#endif + +/* Dummy defines for when mprotect doesn't exist. */ +#ifndef PROT_READ +#define PROT_READ 0 +#endif +#ifndef PROT_WRITE +#define PROT_WRITE 0 +#endif + +/* _SC_PAGESIZE is standard, but hpux 9 and possibly other systems have + _SC_PAGE_SIZE instead. */ +#if defined (_SC_PAGE_SIZE) && ! defined (_SC_PAGESIZE) +#define _SC_PAGESIZE _SC_PAGE_SIZE +#endif + + +#ifdef EXTRA_PROTOS +EXTRA_PROTOS +#endif +#ifdef EXTRA_PROTOS2 +EXTRA_PROTOS2 +#endif + + +#define DEFAULT_REPETITIONS 10 + +int option_repetitions = DEFAULT_REPETITIONS; +int option_spinner = 1; +int option_redzones = 1; +int option_firstsize = 0; +int option_lastsize = 500; +int option_firstsize2 = 0; + +#define ALIGNMENTS 4 +#define OVERLAPS 4 +#define CARRY_RANDOMS 5 +#define MULTIPLIER_RANDOMS 5 +#define DIVISOR_RANDOMS 5 +#define FRACTION_COUNT 4 + +int option_print = 0; + +#define DATA_TRAND 0 +#define DATA_ZEROS 1 +#define DATA_SEQ 2 +#define DATA_FFS 3 +#define DATA_2FD 4 +int option_data = DATA_TRAND; + + +mp_size_t pagesize; +#define PAGESIZE_LIMBS (pagesize / GMP_LIMB_BYTES) + +/* must be a multiple of the page size */ +#define REDZONE_BYTES (pagesize * 16) +#define REDZONE_LIMBS (REDZONE_BYTES / GMP_LIMB_BYTES) + + +#define MAX3(x,y,z) (MAX (x, MAX (y, z))) + +#if GMP_LIMB_BITS == 32 +#define DEADVAL CNST_LIMB(0xDEADBEEF) +#else +#define DEADVAL CNST_LIMB(0xDEADBEEFBADDCAFE) +#endif + + +struct region_t { + mp_ptr ptr; + mp_size_t size; +}; + + +#define TRAP_NOWHERE 0 +#define TRAP_REF 1 +#define TRAP_FUN 2 +#define TRAP_SETUPS 3 +int trap_location = TRAP_NOWHERE; + + +#define NUM_SOURCES 5 +#define NUM_DESTS 2 + +struct source_t { + struct region_t region; + int high; + mp_size_t align; + mp_ptr p; +}; + +struct source_t s[NUM_SOURCES]; + +struct dest_t { + int high; + mp_size_t align; + mp_size_t size; +}; + +struct dest_t d[NUM_DESTS]; + +struct source_each_t { + mp_ptr p; +}; + +struct dest_each_t { + struct region_t region; + mp_ptr p; +}; + +mp_size_t size; +mp_size_t size2; +unsigned long shift; +mp_limb_t carry; +mp_limb_t divisor; +mp_limb_t multiplier; +mp_limb_t multiplier_N[8]; + +struct each_t { + const char *name; + struct dest_each_t d[NUM_DESTS]; + struct source_each_t s[NUM_SOURCES]; + mp_limb_t retval; +}; + +struct each_t ref = { "Ref" }; +struct each_t fun = { "Fun" }; + +#define SRC_SIZE(n) ((n) == 1 && tr->size2 ? size2 : size) + +void validate_fail (void); + + +#if HAVE_TRY_NEW_C +#include "try-new.c" +#endif + + +typedef mp_limb_t (*tryfun_t) (ANYARGS); + +struct try_t { + char retval; + + char src[NUM_SOURCES]; + char dst[NUM_DESTS]; + +#define SIZE_YES 1 +#define SIZE_ALLOW_ZERO 2 +#define SIZE_1 3 /* 1 limb */ +#define SIZE_2 4 /* 2 limbs */ +#define SIZE_3 5 /* 3 limbs */ +#define SIZE_4 6 /* 4 limbs */ +#define SIZE_6 7 /* 6 limbs */ +#define SIZE_FRACTION 8 /* size2 is fraction for divrem etc */ +#define SIZE_SIZE2 9 +#define SIZE_PLUS_1 10 +#define SIZE_SUM 11 +#define SIZE_DIFF 12 +#define SIZE_DIFF_PLUS_1 13 +#define SIZE_DIFF_PLUS_3 14 +#define SIZE_RETVAL 15 +#define SIZE_CEIL_HALF 16 +#define SIZE_GET_STR 17 +#define SIZE_PLUS_MSIZE_SUB_1 18 /* size+msize-1 */ +#define SIZE_ODD 19 + char size; + char size2; + char dst_size[NUM_DESTS]; + + /* multiplier_N size in limbs */ + mp_size_t msize; + + char dst_bytes[NUM_DESTS]; + + char dst0_from_src1; + +#define CARRY_BIT 1 /* single bit 0 or 1 */ +#define CARRY_3 2 /* 0, 1, 2 */ +#define CARRY_4 3 /* 0 to 3 */ +#define CARRY_LIMB 4 /* any limb value */ +#define CARRY_DIVISOR 5 /* carry= 1); + + got = fun.retval; + got_mod = got % CNST_34LSUB1; + + want = refmpn_mod_34lsub1 (ptr, size); + want_mod = want % CNST_34LSUB1; + + if (got_mod != want_mod) + { + gmp_printf ("got 0x%MX reduced from 0x%MX\n", got_mod, got); + gmp_printf ("want 0x%MX reduced from 0x%MX\n", want_mod, want); + error = 1; + } + + if (error) + validate_fail (); +} + +void +validate_divexact_1 (void) +{ + mp_srcptr src = s[0].p; + mp_srcptr dst = fun.d[0].p; + int error = 0; + + ASSERT (size >= 1); + + { + mp_ptr tp = refmpn_malloc_limbs (size); + mp_limb_t rem; + + rem = refmpn_divrem_1 (tp, 0, src, size, divisor); + if (rem != 0) + { + gmp_printf ("Remainder a%%d == 0x%MX, mpn_divexact_1 undefined\n", rem); + error = 1; + } + if (! refmpn_equal_anynail (tp, dst, size)) + { + printf ("Quotient a/d wrong\n"); + mpn_trace ("fun ", dst, size); + mpn_trace ("want", tp, size); + error = 1; + } + free (tp); + } + + if (error) + validate_fail (); +} + +void +validate_bdiv_q_1 + (void) +{ + mp_srcptr src = s[0].p; + mp_srcptr dst = fun.d[0].p; + int error = 0; + + ASSERT (size >= 1); + + { + mp_ptr tp = refmpn_malloc_limbs (size + 1); + + refmpn_mul_1 (tp, dst, size, divisor); + /* Set ignored low bits */ + tp[0] |= (src[0] & LOW_ZEROS_MASK (divisor)); + if (! refmpn_equal_anynail (tp, src, size)) + { + printf ("Bdiv wrong: res * divisor != src (mod B^size)\n"); + mpn_trace ("res ", dst, size); + mpn_trace ("src ", src, size); + error = 1; + } + free (tp); + } + + if (error) + validate_fail (); +} + + +void +validate_modexact_1c_odd (void) +{ + mp_srcptr ptr = s[0].p; + mp_limb_t r = fun.retval; + int error = 0; + + ASSERT (size >= 1); + ASSERT (divisor & 1); + + if ((r & GMP_NAIL_MASK) != 0) + printf ("r has non-zero nail\n"); + + if (carry < divisor) + { + if (! (r < divisor)) + { + printf ("Don't have r < divisor\n"); + error = 1; + } + } + else /* carry >= divisor */ + { + if (! (r <= divisor)) + { + printf ("Don't have r <= divisor\n"); + error = 1; + } + } + + { + mp_limb_t c = carry % divisor; + mp_ptr tp = refmpn_malloc_limbs (size+1); + mp_size_t k; + + for (k = size-1; k <= size; k++) + { + /* set {tp,size+1} to r*b^k + a - c */ + refmpn_copyi (tp, ptr, size); + tp[size] = 0; + ASSERT_NOCARRY (refmpn_add_1 (tp+k, tp+k, size+1-k, r)); + if (refmpn_sub_1 (tp, tp, size+1, c)) + ASSERT_CARRY (mpn_add_1 (tp, tp, size+1, divisor)); + + if (refmpn_mod_1 (tp, size+1, divisor) == 0) + goto good_remainder; + } + printf ("Remainder matches neither r*b^(size-1) nor r*b^size\n"); + error = 1; + + good_remainder: + free (tp); + } + + if (error) + validate_fail (); +} + +void +validate_modexact_1_odd (void) +{ + carry = 0; + validate_modexact_1c_odd (); +} + +void +validate_div_qr_1_pi1 (void) +{ + mp_srcptr up = ref.s[0].p; + mp_size_t un = size; + mp_size_t uh = ref.s[1].p[0]; + mp_srcptr qp = fun.d[0].p; + mp_limb_t r = fun.retval; + mp_limb_t cy; + int cmp; + mp_ptr tp; + if (r >= divisor) + { + gmp_printf ("Bad remainder %Md, d = %Md\n", r, divisor); + validate_fail (); + } + tp = refmpn_malloc_limbs (un); + cy = refmpn_mul_1 (tp, qp, un, divisor); + cy += refmpn_add_1 (tp, tp, un, r); + if (cy != uh || refmpn_cmp (tp, up, un) != 0) + { + gmp_printf ("Incorrect result, size %ld.\n" + "d = %Mx, u = %Mx, %Nx\n" + "got: r = %Mx, q = %Nx\n" + "q d + r = %Mx, %Nx", + (long) un, + divisor, uh, up, un, + r, qp, un, + cy, tp, un); + validate_fail (); + } + free (tp); +} + + +void +validate_sqrtrem (void) +{ + mp_srcptr orig_ptr = s[0].p; + mp_size_t orig_size = size; + mp_size_t root_size = (size+1)/2; + mp_srcptr root_ptr = fun.d[0].p; + mp_size_t rem_size = fun.retval; + mp_srcptr rem_ptr = fun.d[1].p; + mp_size_t prod_size = 2*root_size; + mp_ptr p; + int error = 0; + + if (rem_size < 0 || rem_size > size) + { + printf ("Bad remainder size retval %ld\n", (long) rem_size); + validate_fail (); + } + + p = refmpn_malloc_limbs (prod_size); + + p[root_size] = refmpn_lshift (p, root_ptr, root_size, 1); + if (refmpn_cmp_twosizes (p,root_size+1, rem_ptr,rem_size) < 0) + { + printf ("Remainder bigger than 2*root\n"); + error = 1; + } + + refmpn_sqr (p, root_ptr, root_size); + if (rem_size != 0) + refmpn_add (p, p, prod_size, rem_ptr, rem_size); + if (refmpn_cmp_twosizes (p,prod_size, orig_ptr,orig_size) != 0) + { + printf ("root^2+rem != original\n"); + mpn_trace ("prod", p, prod_size); + error = 1; + } + free (p); + + if (error) + validate_fail (); +} + +void +validate_sqrt (void) +{ + mp_srcptr orig_ptr = s[0].p; + mp_size_t orig_size = size; + mp_size_t root_size = (size+1)/2; + mp_srcptr root_ptr = fun.d[0].p; + int perf_pow = (fun.retval == 0); + mp_size_t prod_size = 2*root_size; + mp_ptr p; + int error = 0; + + p = refmpn_malloc_limbs (prod_size); + + refmpn_sqr (p, root_ptr, root_size); + MPN_NORMALIZE (p, prod_size); + if (refmpn_cmp_twosizes (p,prod_size, orig_ptr,orig_size) != - !perf_pow) + { + printf ("root^2 bigger than original, or wrong return value.\n"); + mpn_trace ("prod...", p, prod_size); + error = 1; + } + + refmpn_sub (p, orig_ptr,orig_size, p,prod_size); + MPN_NORMALIZE (p, prod_size); + if (prod_size >= root_size && + refmpn_sub (p, p,prod_size, root_ptr, root_size) == 0 && + refmpn_cmp_twosizes (p, prod_size, root_ptr, root_size) > 0) + { + printf ("(root+1)^2 smaller than original.\n"); + mpn_trace ("prod", p, prod_size); + error = 1; + } + free (p); + + if (error) + validate_fail (); +} + + +/* These types are indexes into the param[] array and are arbitrary so long + as they're all distinct and within the size of param[]. Renumber + whenever necessary or desired. */ + +enum { + TYPE_ADD = 1, TYPE_ADD_N, TYPE_ADD_NC, TYPE_SUB, TYPE_SUB_N, TYPE_SUB_NC, + + TYPE_ADD_ERR1_N, TYPE_ADD_ERR2_N, TYPE_ADD_ERR3_N, + TYPE_SUB_ERR1_N, TYPE_SUB_ERR2_N, TYPE_SUB_ERR3_N, + + TYPE_MUL_1, TYPE_MUL_1C, + + TYPE_MUL_2, TYPE_MUL_3, TYPE_MUL_4, TYPE_MUL_5, TYPE_MUL_6, + + TYPE_ADDMUL_1, TYPE_ADDMUL_1C, TYPE_SUBMUL_1, TYPE_SUBMUL_1C, + + TYPE_ADDMUL_2, TYPE_ADDMUL_3, TYPE_ADDMUL_4, TYPE_ADDMUL_5, TYPE_ADDMUL_6, + TYPE_ADDMUL_7, TYPE_ADDMUL_8, + + TYPE_ADDSUB_N, TYPE_ADDSUB_NC, + + TYPE_RSHIFT, TYPE_LSHIFT, TYPE_LSHIFTC, + + TYPE_COPY, TYPE_COPYI, TYPE_COPYD, TYPE_COM, + + TYPE_ADDLSH1_N, TYPE_ADDLSH2_N, TYPE_ADDLSH_N, + TYPE_ADDLSH1_N_IP1, TYPE_ADDLSH2_N_IP1, TYPE_ADDLSH_N_IP1, + TYPE_ADDLSH1_N_IP2, TYPE_ADDLSH2_N_IP2, TYPE_ADDLSH_N_IP2, + TYPE_SUBLSH1_N, TYPE_SUBLSH2_N, TYPE_SUBLSH_N, + TYPE_SUBLSH1_N_IP1, TYPE_SUBLSH2_N_IP1, TYPE_SUBLSH_N_IP1, + TYPE_RSBLSH1_N, TYPE_RSBLSH2_N, TYPE_RSBLSH_N, + TYPE_RSH1ADD_N, TYPE_RSH1SUB_N, + + TYPE_ADDLSH1_NC, TYPE_ADDLSH2_NC, TYPE_ADDLSH_NC, + TYPE_SUBLSH1_NC, TYPE_SUBLSH2_NC, TYPE_SUBLSH_NC, + TYPE_RSBLSH1_NC, TYPE_RSBLSH2_NC, TYPE_RSBLSH_NC, + + TYPE_ADDCND_N, TYPE_SUBCND_N, + + TYPE_MOD_1, TYPE_MOD_1C, TYPE_DIVMOD_1, TYPE_DIVMOD_1C, TYPE_DIVREM_1, + TYPE_DIVREM_1C, TYPE_PREINV_DIVREM_1, TYPE_DIVREM_2, TYPE_PREINV_MOD_1, + TYPE_DIV_QR_1N_PI1, + TYPE_MOD_34LSUB1, TYPE_UDIV_QRNND, TYPE_UDIV_QRNND_R, + + TYPE_DIVEXACT_1, TYPE_BDIV_Q_1, TYPE_DIVEXACT_BY3, TYPE_DIVEXACT_BY3C, + TYPE_MODEXACT_1_ODD, TYPE_MODEXACT_1C_ODD, + + TYPE_INVERT, TYPE_BINVERT, + + TYPE_GCD, TYPE_GCD_1, TYPE_GCD_FINDA, TYPE_MPZ_JACOBI, TYPE_MPZ_KRONECKER, + TYPE_MPZ_KRONECKER_UI, TYPE_MPZ_KRONECKER_SI, TYPE_MPZ_UI_KRONECKER, + TYPE_MPZ_SI_KRONECKER, TYPE_MPZ_LEGENDRE, + + TYPE_AND_N, TYPE_NAND_N, TYPE_ANDN_N, TYPE_IOR_N, TYPE_IORN_N, TYPE_NIOR_N, + TYPE_XOR_N, TYPE_XNOR_N, + + TYPE_MUL_MN, TYPE_MUL_N, TYPE_SQR, TYPE_UMUL_PPMM, TYPE_UMUL_PPMM_R, + TYPE_MULLO_N, TYPE_SQRLO, TYPE_MULMID_MN, TYPE_MULMID_N, + + TYPE_SBPI1_DIV_QR, TYPE_TDIV_QR, + + TYPE_SQRTREM, TYPE_SQRT, TYPE_ZERO, TYPE_GET_STR, TYPE_POPCOUNT, TYPE_HAMDIST, + + TYPE_EXTRA +}; + +struct try_t param[TYPE_EXTRA]; + + +void +param_init (void) +{ + struct try_t *p; + +#define COPY(index) memcpy (p, ¶m[index], sizeof (*p)) + +#define REFERENCE(fun) \ + p->reference = (tryfun_t) fun; \ + p->reference_name = #fun +#define VALIDATE(fun) \ + p->validate = fun; \ + p->validate_name = #fun + + + p = ¶m[TYPE_ADD_N]; + p->retval = 1; + p->dst[0] = 1; + p->src[0] = 1; + p->src[1] = 1; + REFERENCE (refmpn_add_n); + + p = ¶m[TYPE_ADD_NC]; + COPY (TYPE_ADD_N); + p->carry = CARRY_BIT; + REFERENCE (refmpn_add_nc); + + p = ¶m[TYPE_SUB_N]; + COPY (TYPE_ADD_N); + REFERENCE (refmpn_sub_n); + + p = ¶m[TYPE_SUB_NC]; + COPY (TYPE_ADD_NC); + REFERENCE (refmpn_sub_nc); + + p = ¶m[TYPE_ADD]; + COPY (TYPE_ADD_N); + p->size = SIZE_ALLOW_ZERO; + p->size2 = 1; + REFERENCE (refmpn_add); + + p = ¶m[TYPE_SUB]; + COPY (TYPE_ADD); + REFERENCE (refmpn_sub); + + + p = ¶m[TYPE_ADD_ERR1_N]; + p->retval = 1; + p->dst[0] = 1; + p->dst[1] = 1; + p->src[0] = 1; + p->src[1] = 1; + p->src[2] = 1; + p->dst_size[1] = SIZE_2; + p->carry = CARRY_BIT; + p->overlap = OVERLAP_NOT_DST2; + REFERENCE (refmpn_add_err1_n); + + p = ¶m[TYPE_SUB_ERR1_N]; + COPY (TYPE_ADD_ERR1_N); + REFERENCE (refmpn_sub_err1_n); + + p = ¶m[TYPE_ADD_ERR2_N]; + COPY (TYPE_ADD_ERR1_N); + p->src[3] = 1; + p->dst_size[1] = SIZE_4; + REFERENCE (refmpn_add_err2_n); + + p = ¶m[TYPE_SUB_ERR2_N]; + COPY (TYPE_ADD_ERR2_N); + REFERENCE (refmpn_sub_err2_n); + + p = ¶m[TYPE_ADD_ERR3_N]; + COPY (TYPE_ADD_ERR2_N); + p->src[4] = 1; + p->dst_size[1] = SIZE_6; + REFERENCE (refmpn_add_err3_n); + + p = ¶m[TYPE_SUB_ERR3_N]; + COPY (TYPE_ADD_ERR3_N); + REFERENCE (refmpn_sub_err3_n); + + p = ¶m[TYPE_ADDCND_N]; + COPY (TYPE_ADD_N); + p->carry = CARRY_BIT; + REFERENCE (refmpn_cnd_add_n); + + p = ¶m[TYPE_SUBCND_N]; + COPY (TYPE_ADD_N); + p->carry = CARRY_BIT; + REFERENCE (refmpn_cnd_sub_n); + + + p = ¶m[TYPE_MUL_1]; + p->retval = 1; + p->dst[0] = 1; + p->src[0] = 1; + p->multiplier = 1; + p->overlap = OVERLAP_LOW_TO_HIGH; + REFERENCE (refmpn_mul_1); + + p = ¶m[TYPE_MUL_1C]; + COPY (TYPE_MUL_1); + p->carry = CARRY_LIMB; + REFERENCE (refmpn_mul_1c); + + + p = ¶m[TYPE_MUL_2]; + p->retval = 1; + p->dst[0] = 1; + p->dst_size[0] = SIZE_PLUS_MSIZE_SUB_1; + p->src[0] = 1; + p->src[1] = 1; + p->msize = 2; + p->overlap = OVERLAP_NOT_SRC2; + REFERENCE (refmpn_mul_2); + + p = ¶m[TYPE_MUL_3]; + COPY (TYPE_MUL_2); + p->msize = 3; + REFERENCE (refmpn_mul_3); + + p = ¶m[TYPE_MUL_4]; + COPY (TYPE_MUL_2); + p->msize = 4; + REFERENCE (refmpn_mul_4); + + p = ¶m[TYPE_MUL_5]; + COPY (TYPE_MUL_2); + p->msize = 5; + REFERENCE (refmpn_mul_5); + + p = ¶m[TYPE_MUL_6]; + COPY (TYPE_MUL_2); + p->msize = 6; + REFERENCE (refmpn_mul_6); + + + p = ¶m[TYPE_ADDMUL_1]; + p->retval = 1; + p->dst[0] = 1; + p->src[0] = 1; + p->multiplier = 1; + p->dst0_from_src1 = 1; + REFERENCE (refmpn_addmul_1); + + p = ¶m[TYPE_ADDMUL_1C]; + COPY (TYPE_ADDMUL_1); + p->carry = CARRY_LIMB; + REFERENCE (refmpn_addmul_1c); + + p = ¶m[TYPE_SUBMUL_1]; + COPY (TYPE_ADDMUL_1); + REFERENCE (refmpn_submul_1); + + p = ¶m[TYPE_SUBMUL_1C]; + COPY (TYPE_ADDMUL_1C); + REFERENCE (refmpn_submul_1c); + + + p = ¶m[TYPE_ADDMUL_2]; + p->retval = 1; + p->dst[0] = 1; + p->dst_size[0] = SIZE_PLUS_MSIZE_SUB_1; + p->src[0] = 1; + p->src[1] = 1; + p->msize = 2; + p->dst0_from_src1 = 1; + p->overlap = OVERLAP_NONE; + REFERENCE (refmpn_addmul_2); + + p = ¶m[TYPE_ADDMUL_3]; + COPY (TYPE_ADDMUL_2); + p->msize = 3; + REFERENCE (refmpn_addmul_3); + + p = ¶m[TYPE_ADDMUL_4]; + COPY (TYPE_ADDMUL_2); + p->msize = 4; + REFERENCE (refmpn_addmul_4); + + p = ¶m[TYPE_ADDMUL_5]; + COPY (TYPE_ADDMUL_2); + p->msize = 5; + REFERENCE (refmpn_addmul_5); + + p = ¶m[TYPE_ADDMUL_6]; + COPY (TYPE_ADDMUL_2); + p->msize = 6; + REFERENCE (refmpn_addmul_6); + + p = ¶m[TYPE_ADDMUL_7]; + COPY (TYPE_ADDMUL_2); + p->msize = 7; + REFERENCE (refmpn_addmul_7); + + p = ¶m[TYPE_ADDMUL_8]; + COPY (TYPE_ADDMUL_2); + p->msize = 8; + REFERENCE (refmpn_addmul_8); + + + p = ¶m[TYPE_AND_N]; + p->dst[0] = 1; + p->src[0] = 1; + p->src[1] = 1; + REFERENCE (refmpn_and_n); + + p = ¶m[TYPE_ANDN_N]; + COPY (TYPE_AND_N); + REFERENCE (refmpn_andn_n); + + p = ¶m[TYPE_NAND_N]; + COPY (TYPE_AND_N); + REFERENCE (refmpn_nand_n); + + p = ¶m[TYPE_IOR_N]; + COPY (TYPE_AND_N); + REFERENCE (refmpn_ior_n); + + p = ¶m[TYPE_IORN_N]; + COPY (TYPE_AND_N); + REFERENCE (refmpn_iorn_n); + + p = ¶m[TYPE_NIOR_N]; + COPY (TYPE_AND_N); + REFERENCE (refmpn_nior_n); + + p = ¶m[TYPE_XOR_N]; + COPY (TYPE_AND_N); + REFERENCE (refmpn_xor_n); + + p = ¶m[TYPE_XNOR_N]; + COPY (TYPE_AND_N); + REFERENCE (refmpn_xnor_n); + + + p = ¶m[TYPE_ADDSUB_N]; + p->retval = 1; + p->dst[0] = 1; + p->dst[1] = 1; + p->src[0] = 1; + p->src[1] = 1; + REFERENCE (refmpn_add_n_sub_n); + + p = ¶m[TYPE_ADDSUB_NC]; + COPY (TYPE_ADDSUB_N); + p->carry = CARRY_4; + REFERENCE (refmpn_add_n_sub_nc); + + + p = ¶m[TYPE_COPY]; + p->dst[0] = 1; + p->src[0] = 1; + p->overlap = OVERLAP_NONE; + p->size = SIZE_ALLOW_ZERO; + REFERENCE (refmpn_copy); + + p = ¶m[TYPE_COPYI]; + p->dst[0] = 1; + p->src[0] = 1; + p->overlap = OVERLAP_LOW_TO_HIGH; + p->size = SIZE_ALLOW_ZERO; + REFERENCE (refmpn_copyi); + + p = ¶m[TYPE_COPYD]; + p->dst[0] = 1; + p->src[0] = 1; + p->overlap = OVERLAP_HIGH_TO_LOW; + p->size = SIZE_ALLOW_ZERO; + REFERENCE (refmpn_copyd); + + p = ¶m[TYPE_COM]; + p->dst[0] = 1; + p->src[0] = 1; + REFERENCE (refmpn_com); + + + p = ¶m[TYPE_ADDLSH1_N]; + COPY (TYPE_ADD_N); + REFERENCE (refmpn_addlsh1_n); + + p = ¶m[TYPE_ADDLSH2_N]; + COPY (TYPE_ADD_N); + REFERENCE (refmpn_addlsh2_n); + + p = ¶m[TYPE_ADDLSH_N]; + COPY (TYPE_ADD_N); + p->shift = 1; + REFERENCE (refmpn_addlsh_n); + + p = ¶m[TYPE_ADDLSH1_N_IP1]; + p->retval = 1; + p->dst[0] = 1; + p->src[0] = 1; + p->dst0_from_src1 = 1; + REFERENCE (refmpn_addlsh1_n_ip1); + + p = ¶m[TYPE_ADDLSH2_N_IP1]; + COPY (TYPE_ADDLSH1_N_IP1); + REFERENCE (refmpn_addlsh2_n_ip1); + + p = ¶m[TYPE_ADDLSH_N_IP1]; + COPY (TYPE_ADDLSH1_N_IP1); + p->shift = 1; + REFERENCE (refmpn_addlsh_n_ip1); + + p = ¶m[TYPE_ADDLSH1_N_IP2]; + COPY (TYPE_ADDLSH1_N_IP1); + REFERENCE (refmpn_addlsh1_n_ip2); + + p = ¶m[TYPE_ADDLSH2_N_IP2]; + COPY (TYPE_ADDLSH1_N_IP1); + REFERENCE (refmpn_addlsh2_n_ip2); + + p = ¶m[TYPE_ADDLSH_N_IP2]; + COPY (TYPE_ADDLSH_N_IP1); + REFERENCE (refmpn_addlsh_n_ip2); + + p = ¶m[TYPE_SUBLSH1_N]; + COPY (TYPE_ADD_N); + REFERENCE (refmpn_sublsh1_n); + + p = ¶m[TYPE_SUBLSH2_N]; + COPY (TYPE_ADD_N); + REFERENCE (refmpn_sublsh2_n); + + p = ¶m[TYPE_SUBLSH_N]; + COPY (TYPE_ADDLSH_N); + REFERENCE (refmpn_sublsh_n); + + p = ¶m[TYPE_SUBLSH1_N_IP1]; + COPY (TYPE_ADDLSH1_N_IP1); + REFERENCE (refmpn_sublsh1_n_ip1); + + p = ¶m[TYPE_SUBLSH2_N_IP1]; + COPY (TYPE_ADDLSH1_N_IP1); + REFERENCE (refmpn_sublsh2_n_ip1); + + p = ¶m[TYPE_SUBLSH_N_IP1]; + COPY (TYPE_ADDLSH_N_IP1); + REFERENCE (refmpn_sublsh_n_ip1); + + p = ¶m[TYPE_RSBLSH1_N]; + COPY (TYPE_ADD_N); + REFERENCE (refmpn_rsblsh1_n); + + p = ¶m[TYPE_RSBLSH2_N]; + COPY (TYPE_ADD_N); + REFERENCE (refmpn_rsblsh2_n); + + p = ¶m[TYPE_RSBLSH_N]; + COPY (TYPE_ADDLSH_N); + REFERENCE (refmpn_rsblsh_n); + + p = ¶m[TYPE_RSH1ADD_N]; + COPY (TYPE_ADD_N); + REFERENCE (refmpn_rsh1add_n); + + p = ¶m[TYPE_RSH1SUB_N]; + COPY (TYPE_ADD_N); + REFERENCE (refmpn_rsh1sub_n); + + + p = ¶m[TYPE_ADDLSH1_NC]; + COPY (TYPE_ADDLSH1_N); + p->carry = CARRY_3; + REFERENCE (refmpn_addlsh1_nc); + + p = ¶m[TYPE_ADDLSH2_NC]; + COPY (TYPE_ADDLSH2_N); + p->carry = CARRY_4; /* FIXME */ + REFERENCE (refmpn_addlsh2_nc); + + p = ¶m[TYPE_ADDLSH_NC]; + COPY (TYPE_ADDLSH_N); + p->carry = CARRY_BIT; /* FIXME */ + REFERENCE (refmpn_addlsh_nc); + + p = ¶m[TYPE_SUBLSH1_NC]; + COPY (TYPE_ADDLSH1_NC); + REFERENCE (refmpn_sublsh1_nc); + + p = ¶m[TYPE_SUBLSH2_NC]; + COPY (TYPE_ADDLSH2_NC); + REFERENCE (refmpn_sublsh2_nc); + + p = ¶m[TYPE_SUBLSH_NC]; + COPY (TYPE_ADDLSH_NC); + REFERENCE (refmpn_sublsh_nc); + + p = ¶m[TYPE_RSBLSH1_NC]; + COPY (TYPE_RSBLSH1_N); + p->carry = CARRY_BIT; /* FIXME */ + REFERENCE (refmpn_rsblsh1_nc); + + p = ¶m[TYPE_RSBLSH2_NC]; + COPY (TYPE_RSBLSH2_N); + p->carry = CARRY_4; /* FIXME */ + REFERENCE (refmpn_rsblsh2_nc); + + p = ¶m[TYPE_RSBLSH_NC]; + COPY (TYPE_RSBLSH_N); + p->carry = CARRY_BIT; /* FIXME */ + REFERENCE (refmpn_rsblsh_nc); + + + p = ¶m[TYPE_MOD_1]; + p->retval = 1; + p->src[0] = 1; + p->size = SIZE_ALLOW_ZERO; + p->divisor = DIVISOR_LIMB; + REFERENCE (refmpn_mod_1); + + p = ¶m[TYPE_MOD_1C]; + COPY (TYPE_MOD_1); + p->carry = CARRY_DIVISOR; + REFERENCE (refmpn_mod_1c); + + p = ¶m[TYPE_DIVMOD_1]; + COPY (TYPE_MOD_1); + p->dst[0] = 1; + REFERENCE (refmpn_divmod_1); + + p = ¶m[TYPE_DIVMOD_1C]; + COPY (TYPE_DIVMOD_1); + p->carry = CARRY_DIVISOR; + REFERENCE (refmpn_divmod_1c); + + p = ¶m[TYPE_DIVREM_1]; + COPY (TYPE_DIVMOD_1); + p->size2 = SIZE_FRACTION; + p->dst_size[0] = SIZE_SUM; + REFERENCE (refmpn_divrem_1); + + p = ¶m[TYPE_DIVREM_1C]; + COPY (TYPE_DIVREM_1); + p->carry = CARRY_DIVISOR; + REFERENCE (refmpn_divrem_1c); + + p = ¶m[TYPE_PREINV_DIVREM_1]; + COPY (TYPE_DIVREM_1); + p->size = SIZE_YES; /* ie. no size==0 */ + REFERENCE (refmpn_preinv_divrem_1); + + p = ¶m[TYPE_DIV_QR_1N_PI1]; + p->retval = 1; + p->src[0] = 1; + p->src[1] = 1; + /* SIZE_1 not supported. Always uses low limb only. */ + p->size2 = 1; + p->dst[0] = 1; + p->divisor = DIVISOR_NORM; + p->data = DATA_DIV_QR_1; + VALIDATE (validate_div_qr_1_pi1); + + p = ¶m[TYPE_PREINV_MOD_1]; + p->retval = 1; + p->src[0] = 1; + p->divisor = DIVISOR_NORM; + REFERENCE (refmpn_preinv_mod_1); + + p = ¶m[TYPE_MOD_34LSUB1]; + p->retval = 1; + p->src[0] = 1; + VALIDATE (validate_mod_34lsub1); + + p = ¶m[TYPE_UDIV_QRNND]; + p->retval = 1; + p->src[0] = 1; + p->dst[0] = 1; + p->dst_size[0] = SIZE_1; + p->divisor = UDIV_NEEDS_NORMALIZATION ? DIVISOR_NORM : DIVISOR_LIMB; + p->data = DATA_UDIV_QRNND; + p->overlap = OVERLAP_NONE; + REFERENCE (refmpn_udiv_qrnnd); + + p = ¶m[TYPE_UDIV_QRNND_R]; + COPY (TYPE_UDIV_QRNND); + REFERENCE (refmpn_udiv_qrnnd_r); + + + p = ¶m[TYPE_DIVEXACT_1]; + p->dst[0] = 1; + p->src[0] = 1; + p->divisor = DIVISOR_LIMB; + p->data = DATA_MULTIPLE_DIVISOR; + VALIDATE (validate_divexact_1); + REFERENCE (refmpn_divmod_1); + + p = ¶m[TYPE_BDIV_Q_1]; + p->dst[0] = 1; + p->src[0] = 1; + p->divisor = DIVISOR_LIMB; + VALIDATE (validate_bdiv_q_1); + + p = ¶m[TYPE_DIVEXACT_BY3]; + p->retval = 1; + p->dst[0] = 1; + p->src[0] = 1; + REFERENCE (refmpn_divexact_by3); + + p = ¶m[TYPE_DIVEXACT_BY3C]; + COPY (TYPE_DIVEXACT_BY3); + p->carry = CARRY_3; + REFERENCE (refmpn_divexact_by3c); + + + p = ¶m[TYPE_MODEXACT_1_ODD]; + p->retval = 1; + p->src[0] = 1; + p->divisor = DIVISOR_ODD; + VALIDATE (validate_modexact_1_odd); + + p = ¶m[TYPE_MODEXACT_1C_ODD]; + COPY (TYPE_MODEXACT_1_ODD); + p->carry = CARRY_LIMB; + VALIDATE (validate_modexact_1c_odd); + + + p = ¶m[TYPE_GCD_1]; + p->retval = 1; + p->src[0] = 1; + p->data = DATA_NON_ZERO; + p->divisor = DIVISOR_LIMB; + REFERENCE (refmpn_gcd_1); + + p = ¶m[TYPE_GCD]; + p->retval = 1; + p->dst[0] = 1; + p->src[0] = 1; + p->src[1] = 1; + p->size2 = 1; + p->dst_size[0] = SIZE_RETVAL; + p->overlap = OVERLAP_NOT_SRCS; + p->data = DATA_GCD; + REFERENCE (refmpn_gcd); + + + p = ¶m[TYPE_MPZ_LEGENDRE]; + p->retval = 1; + p->src[0] = 1; + p->size = SIZE_ALLOW_ZERO; + p->src[1] = 1; + p->data = DATA_SRC1_ODD_PRIME; + p->size2 = 1; + p->carry = CARRY_BIT; + p->carry_sign = 1; + REFERENCE (refmpz_legendre); + + p = ¶m[TYPE_MPZ_JACOBI]; + p->retval = 1; + p->src[0] = 1; + p->size = SIZE_ALLOW_ZERO; + p->src[1] = 1; + p->data = DATA_SRC1_ODD; + p->size2 = 1; + p->carry = CARRY_BIT; + p->carry_sign = 1; + REFERENCE (refmpz_jacobi); + + p = ¶m[TYPE_MPZ_KRONECKER]; + p->retval = 1; + p->src[0] = 1; + p->size = SIZE_ALLOW_ZERO; + p->src[1] = 1; + p->data = 0; + p->size2 = 1; + p->carry = CARRY_4; + p->carry_sign = 1; + REFERENCE (refmpz_kronecker); + + + p = ¶m[TYPE_MPZ_KRONECKER_UI]; + p->retval = 1; + p->src[0] = 1; + p->size = SIZE_ALLOW_ZERO; + p->multiplier = 1; + p->carry = CARRY_BIT; + REFERENCE (refmpz_kronecker_ui); + + p = ¶m[TYPE_MPZ_KRONECKER_SI]; + COPY (TYPE_MPZ_KRONECKER_UI); + REFERENCE (refmpz_kronecker_si); + + p = ¶m[TYPE_MPZ_UI_KRONECKER]; + COPY (TYPE_MPZ_KRONECKER_UI); + REFERENCE (refmpz_ui_kronecker); + + p = ¶m[TYPE_MPZ_SI_KRONECKER]; + COPY (TYPE_MPZ_KRONECKER_UI); + REFERENCE (refmpz_si_kronecker); + + + p = ¶m[TYPE_SQR]; + p->dst[0] = 1; + p->src[0] = 1; + p->dst_size[0] = SIZE_SUM; + p->overlap = OVERLAP_NONE; + REFERENCE (refmpn_sqr); + + p = ¶m[TYPE_MUL_N]; + COPY (TYPE_SQR); + p->src[1] = 1; + REFERENCE (refmpn_mul_n); + + p = ¶m[TYPE_MULLO_N]; + COPY (TYPE_MUL_N); + p->dst_size[0] = 0; + REFERENCE (refmpn_mullo_n); + + p = ¶m[TYPE_SQRLO]; + COPY (TYPE_SQR); + p->dst_size[0] = 0; + REFERENCE (refmpn_sqrlo); + + p = ¶m[TYPE_MUL_MN]; + COPY (TYPE_MUL_N); + p->size2 = 1; + REFERENCE (refmpn_mul_basecase); + + p = ¶m[TYPE_MULMID_MN]; + COPY (TYPE_MUL_MN); + p->dst_size[0] = SIZE_DIFF_PLUS_3; + REFERENCE (refmpn_mulmid_basecase); + + p = ¶m[TYPE_MULMID_N]; + COPY (TYPE_MUL_N); + p->size = SIZE_ODD; + p->size2 = SIZE_CEIL_HALF; + p->dst_size[0] = SIZE_DIFF_PLUS_3; + REFERENCE (refmpn_mulmid_n); + + p = ¶m[TYPE_UMUL_PPMM]; + p->retval = 1; + p->src[0] = 1; + p->dst[0] = 1; + p->dst_size[0] = SIZE_1; + p->overlap = OVERLAP_NONE; + REFERENCE (refmpn_umul_ppmm); + + p = ¶m[TYPE_UMUL_PPMM_R]; + COPY (TYPE_UMUL_PPMM); + REFERENCE (refmpn_umul_ppmm_r); + + + p = ¶m[TYPE_RSHIFT]; + p->retval = 1; + p->dst[0] = 1; + p->src[0] = 1; + p->shift = 1; + p->overlap = OVERLAP_LOW_TO_HIGH; + REFERENCE (refmpn_rshift); + + p = ¶m[TYPE_LSHIFT]; + COPY (TYPE_RSHIFT); + p->overlap = OVERLAP_HIGH_TO_LOW; + REFERENCE (refmpn_lshift); + + p = ¶m[TYPE_LSHIFTC]; + COPY (TYPE_RSHIFT); + p->overlap = OVERLAP_HIGH_TO_LOW; + REFERENCE (refmpn_lshiftc); + + + p = ¶m[TYPE_POPCOUNT]; + p->retval = 1; + p->src[0] = 1; + REFERENCE (refmpn_popcount); + + p = ¶m[TYPE_HAMDIST]; + COPY (TYPE_POPCOUNT); + p->src[1] = 1; + REFERENCE (refmpn_hamdist); + + + p = ¶m[TYPE_SBPI1_DIV_QR]; + p->retval = 1; + p->dst[0] = 1; + p->dst[1] = 1; + p->src[0] = 1; + p->src[1] = 1; + p->data = DATA_SRC1_HIGHBIT; + p->size2 = 1; + p->dst_size[0] = SIZE_DIFF; + p->overlap = OVERLAP_NONE; + REFERENCE (refmpn_sb_div_qr); + + p = ¶m[TYPE_TDIV_QR]; + p->dst[0] = 1; + p->dst[1] = 1; + p->src[0] = 1; + p->src[1] = 1; + p->size2 = 1; + p->dst_size[0] = SIZE_DIFF_PLUS_1; + p->dst_size[1] = SIZE_SIZE2; + p->overlap = OVERLAP_NONE; + REFERENCE (refmpn_tdiv_qr); + + p = ¶m[TYPE_SQRTREM]; + p->retval = 1; + p->dst[0] = 1; + p->dst[1] = 1; + p->src[0] = 1; + p->dst_size[0] = SIZE_CEIL_HALF; + p->dst_size[1] = SIZE_RETVAL; + p->overlap = OVERLAP_NONE; + VALIDATE (validate_sqrtrem); + REFERENCE (refmpn_sqrtrem); + + p = ¶m[TYPE_SQRT]; + p->retval = 1; + p->dst[0] = 1; + p->dst[1] = 0; + p->src[0] = 1; + p->dst_size[0] = SIZE_CEIL_HALF; + p->overlap = OVERLAP_NONE; + VALIDATE (validate_sqrt); + + p = ¶m[TYPE_ZERO]; + p->dst[0] = 1; + p->size = SIZE_ALLOW_ZERO; + REFERENCE (refmpn_zero); + + p = ¶m[TYPE_GET_STR]; + p->retval = 1; + p->src[0] = 1; + p->size = SIZE_ALLOW_ZERO; + p->dst[0] = 1; + p->dst[1] = 1; + p->dst_size[0] = SIZE_GET_STR; + p->dst_bytes[0] = 1; + p->overlap = OVERLAP_NONE; + REFERENCE (refmpn_get_str); + + p = ¶m[TYPE_BINVERT]; + p->dst[0] = 1; + p->src[0] = 1; + p->data = DATA_SRC0_ODD; + p->overlap = OVERLAP_NONE; + REFERENCE (refmpn_binvert); + + p = ¶m[TYPE_INVERT]; + p->dst[0] = 1; + p->src[0] = 1; + p->data = DATA_SRC0_HIGHBIT; + p->overlap = OVERLAP_NONE; + REFERENCE (refmpn_invert); + +#ifdef EXTRA_PARAM_INIT + EXTRA_PARAM_INIT +#endif +} + + +/* The following are macros if there's no native versions, so wrap them in + functions that can be in try_array[]. */ + +void +MPN_COPY_fun (mp_ptr rp, mp_srcptr sp, mp_size_t size) +{ MPN_COPY (rp, sp, size); } + +void +MPN_COPY_INCR_fun (mp_ptr rp, mp_srcptr sp, mp_size_t size) +{ MPN_COPY_INCR (rp, sp, size); } + +void +MPN_COPY_DECR_fun (mp_ptr rp, mp_srcptr sp, mp_size_t size) +{ MPN_COPY_DECR (rp, sp, size); } + +void +__GMPN_COPY_fun (mp_ptr rp, mp_srcptr sp, mp_size_t size) +{ __GMPN_COPY (rp, sp, size); } + +#ifdef __GMPN_COPY_INCR +void +__GMPN_COPY_INCR_fun (mp_ptr rp, mp_srcptr sp, mp_size_t size) +{ __GMPN_COPY_INCR (rp, sp, size); } +#endif + +void +mpn_com_fun (mp_ptr rp, mp_srcptr sp, mp_size_t size) +{ mpn_com (rp, sp, size); } + +void +mpn_and_n_fun (mp_ptr rp, mp_srcptr s1, mp_srcptr s2, mp_size_t size) +{ mpn_and_n (rp, s1, s2, size); } + +void +mpn_andn_n_fun (mp_ptr rp, mp_srcptr s1, mp_srcptr s2, mp_size_t size) +{ mpn_andn_n (rp, s1, s2, size); } + +void +mpn_nand_n_fun (mp_ptr rp, mp_srcptr s1, mp_srcptr s2, mp_size_t size) +{ mpn_nand_n (rp, s1, s2, size); } + +void +mpn_ior_n_fun (mp_ptr rp, mp_srcptr s1, mp_srcptr s2, mp_size_t size) +{ mpn_ior_n (rp, s1, s2, size); } + +void +mpn_iorn_n_fun (mp_ptr rp, mp_srcptr s1, mp_srcptr s2, mp_size_t size) +{ mpn_iorn_n (rp, s1, s2, size); } + +void +mpn_nior_n_fun (mp_ptr rp, mp_srcptr s1, mp_srcptr s2, mp_size_t size) +{ mpn_nior_n (rp, s1, s2, size); } + +void +mpn_xor_n_fun (mp_ptr rp, mp_srcptr s1, mp_srcptr s2, mp_size_t size) +{ mpn_xor_n (rp, s1, s2, size); } + +void +mpn_xnor_n_fun (mp_ptr rp, mp_srcptr s1, mp_srcptr s2, mp_size_t size) +{ mpn_xnor_n (rp, s1, s2, size); } + +mp_limb_t +udiv_qrnnd_fun (mp_limb_t *remptr, mp_limb_t n1, mp_limb_t n0, mp_limb_t d) +{ + mp_limb_t q; + udiv_qrnnd (q, *remptr, n1, n0, d); + return q; +} + +mp_limb_t +mpn_divexact_by3_fun (mp_ptr rp, mp_srcptr sp, mp_size_t size) +{ + return mpn_divexact_by3 (rp, sp, size); +} + +#if HAVE_NATIVE_mpn_addlsh1_n_ip1 +mp_limb_t +mpn_addlsh1_n_ip1_fun (mp_ptr rp, mp_srcptr sp, mp_size_t size) +{ + return mpn_addlsh1_n_ip1 (rp, sp, size); +} +#endif +#if HAVE_NATIVE_mpn_addlsh2_n_ip1 +mp_limb_t +mpn_addlsh2_n_ip1_fun (mp_ptr rp, mp_srcptr sp, mp_size_t size) +{ + return mpn_addlsh2_n_ip1 (rp, sp, size); +} +#endif +#if HAVE_NATIVE_mpn_addlsh_n_ip1 +mp_limb_t +mpn_addlsh_n_ip1_fun (mp_ptr rp, mp_srcptr sp, mp_size_t size, unsigned int sh) +{ + return mpn_addlsh_n_ip1 (rp, sp, size, sh); +} +#endif +#if HAVE_NATIVE_mpn_addlsh1_n_ip2 +mp_limb_t +mpn_addlsh1_n_ip2_fun (mp_ptr rp, mp_srcptr sp, mp_size_t size) +{ + return mpn_addlsh1_n_ip2 (rp, sp, size); +} +#endif +#if HAVE_NATIVE_mpn_addlsh2_n_ip2 +mp_limb_t +mpn_addlsh2_n_ip2_fun (mp_ptr rp, mp_srcptr sp, mp_size_t size) +{ + return mpn_addlsh2_n_ip2 (rp, sp, size); +} +#endif +#if HAVE_NATIVE_mpn_addlsh_n_ip2 +mp_limb_t +mpn_addlsh_n_ip2_fun (mp_ptr rp, mp_srcptr sp, mp_size_t size, unsigned int sh) +{ + return mpn_addlsh_n_ip2 (rp, sp, size, sh); +} +#endif +#if HAVE_NATIVE_mpn_sublsh1_n_ip1 +mp_limb_t +mpn_sublsh1_n_ip1_fun (mp_ptr rp, mp_srcptr sp, mp_size_t size) +{ + return mpn_sublsh1_n_ip1 (rp, sp, size); +} +#endif +#if HAVE_NATIVE_mpn_sublsh2_n_ip1 +mp_limb_t +mpn_sublsh2_n_ip1_fun (mp_ptr rp, mp_srcptr sp, mp_size_t size) +{ + return mpn_sublsh2_n_ip1 (rp, sp, size); +} +#endif +#if HAVE_NATIVE_mpn_sublsh_n_ip1 +mp_limb_t +mpn_sublsh_n_ip1_fun (mp_ptr rp, mp_srcptr sp, mp_size_t size, unsigned int sh) +{ + return mpn_sublsh_n_ip1 (rp, sp, size, sh); +} +#endif + +mp_limb_t +mpn_modexact_1_odd_fun (mp_srcptr ptr, mp_size_t size, mp_limb_t divisor) +{ + return mpn_modexact_1_odd (ptr, size, divisor); +} + +void +mpn_toom22_mul_fun (mp_ptr dst, mp_srcptr src1, mp_srcptr src2, mp_size_t size) +{ + mp_ptr tspace; + TMP_DECL; + TMP_MARK; + tspace = TMP_ALLOC_LIMBS (mpn_toom22_mul_itch (size, size)); + mpn_toom22_mul (dst, src1, size, src2, size, tspace); + TMP_FREE; +} +void +mpn_toom2_sqr_fun (mp_ptr dst, mp_srcptr src, mp_size_t size) +{ + mp_ptr tspace; + TMP_DECL; + TMP_MARK; + tspace = TMP_ALLOC_LIMBS (mpn_toom2_sqr_itch (size)); + mpn_toom2_sqr (dst, src, size, tspace); + TMP_FREE; +} +void +mpn_toom33_mul_fun (mp_ptr dst, mp_srcptr src1, mp_srcptr src2, mp_size_t size) +{ + mp_ptr tspace; + TMP_DECL; + TMP_MARK; + tspace = TMP_ALLOC_LIMBS (mpn_toom33_mul_itch (size, size)); + mpn_toom33_mul (dst, src1, size, src2, size, tspace); + TMP_FREE; +} +void +mpn_toom3_sqr_fun (mp_ptr dst, mp_srcptr src, mp_size_t size) +{ + mp_ptr tspace; + TMP_DECL; + TMP_MARK; + tspace = TMP_ALLOC_LIMBS (mpn_toom3_sqr_itch (size)); + mpn_toom3_sqr (dst, src, size, tspace); + TMP_FREE; +} +void +mpn_toom44_mul_fun (mp_ptr dst, mp_srcptr src1, mp_srcptr src2, mp_size_t size) +{ + mp_ptr tspace; + TMP_DECL; + TMP_MARK; + tspace = TMP_ALLOC_LIMBS (mpn_toom44_mul_itch (size, size)); + mpn_toom44_mul (dst, src1, size, src2, size, tspace); + TMP_FREE; +} +void +mpn_toom4_sqr_fun (mp_ptr dst, mp_srcptr src, mp_size_t size) +{ + mp_ptr tspace; + TMP_DECL; + TMP_MARK; + tspace = TMP_ALLOC_LIMBS (mpn_toom4_sqr_itch (size)); + mpn_toom4_sqr (dst, src, size, tspace); + TMP_FREE; +} + +void +mpn_toom42_mulmid_fun (mp_ptr dst, mp_srcptr src1, mp_srcptr src2, + mp_size_t size) +{ + mp_ptr tspace; + mp_size_t n; + TMP_DECL; + TMP_MARK; + tspace = TMP_ALLOC_LIMBS (mpn_toom42_mulmid_itch (size)); + mpn_toom42_mulmid (dst, src1, src2, size, tspace); + TMP_FREE; +} + +mp_limb_t +umul_ppmm_fun (mp_limb_t *lowptr, mp_limb_t m1, mp_limb_t m2) +{ + mp_limb_t high; + umul_ppmm (high, *lowptr, m1, m2); + return high; +} + +void +MPN_ZERO_fun (mp_ptr ptr, mp_size_t size) +{ MPN_ZERO (ptr, size); } + +mp_size_t +mpn_sqrt_fun (mp_ptr dst, mp_srcptr src, mp_size_t size) +{ return mpn_sqrtrem (dst, NULL, src, size); } + +struct choice_t { + const char *name; + tryfun_t function; + int type; + mp_size_t minsize; +}; + +#define TRY(fun) #fun, (tryfun_t) fun +#define TRY_FUNFUN(fun) #fun, (tryfun_t) fun##_fun + +const struct choice_t choice_array[] = { + { TRY(mpn_add), TYPE_ADD }, + { TRY(mpn_sub), TYPE_SUB }, + + { TRY(mpn_add_n), TYPE_ADD_N }, + { TRY(mpn_sub_n), TYPE_SUB_N }, + +#if HAVE_NATIVE_mpn_add_nc + { TRY(mpn_add_nc), TYPE_ADD_NC }, +#endif +#if HAVE_NATIVE_mpn_sub_nc + { TRY(mpn_sub_nc), TYPE_SUB_NC }, +#endif + +#if HAVE_NATIVE_mpn_add_n_sub_n + { TRY(mpn_add_n_sub_n), TYPE_ADDSUB_N }, +#endif +#if HAVE_NATIVE_mpn_add_n_sub_nc + { TRY(mpn_add_n_sub_nc), TYPE_ADDSUB_NC }, +#endif + + { TRY(mpn_add_err1_n), TYPE_ADD_ERR1_N }, + { TRY(mpn_sub_err1_n), TYPE_SUB_ERR1_N }, + { TRY(mpn_add_err2_n), TYPE_ADD_ERR2_N }, + { TRY(mpn_sub_err2_n), TYPE_SUB_ERR2_N }, + { TRY(mpn_add_err3_n), TYPE_ADD_ERR3_N }, + { TRY(mpn_sub_err3_n), TYPE_SUB_ERR3_N }, + + { TRY(mpn_addmul_1), TYPE_ADDMUL_1 }, + { TRY(mpn_submul_1), TYPE_SUBMUL_1 }, +#if HAVE_NATIVE_mpn_addmul_1c + { TRY(mpn_addmul_1c), TYPE_ADDMUL_1C }, +#endif +#if HAVE_NATIVE_mpn_submul_1c + { TRY(mpn_submul_1c), TYPE_SUBMUL_1C }, +#endif + +#if HAVE_NATIVE_mpn_addmul_2 + { TRY(mpn_addmul_2), TYPE_ADDMUL_2, 2 }, +#endif +#if HAVE_NATIVE_mpn_addmul_3 + { TRY(mpn_addmul_3), TYPE_ADDMUL_3, 3 }, +#endif +#if HAVE_NATIVE_mpn_addmul_4 + { TRY(mpn_addmul_4), TYPE_ADDMUL_4, 4 }, +#endif +#if HAVE_NATIVE_mpn_addmul_5 + { TRY(mpn_addmul_5), TYPE_ADDMUL_5, 5 }, +#endif +#if HAVE_NATIVE_mpn_addmul_6 + { TRY(mpn_addmul_6), TYPE_ADDMUL_6, 6 }, +#endif +#if HAVE_NATIVE_mpn_addmul_7 + { TRY(mpn_addmul_7), TYPE_ADDMUL_7, 7 }, +#endif +#if HAVE_NATIVE_mpn_addmul_8 + { TRY(mpn_addmul_8), TYPE_ADDMUL_8, 8 }, +#endif + + { TRY_FUNFUN(mpn_com), TYPE_COM }, + + { TRY_FUNFUN(MPN_COPY), TYPE_COPY }, + { TRY_FUNFUN(MPN_COPY_INCR), TYPE_COPYI }, + { TRY_FUNFUN(MPN_COPY_DECR), TYPE_COPYD }, + + { TRY_FUNFUN(__GMPN_COPY), TYPE_COPY }, +#ifdef __GMPN_COPY_INCR + { TRY_FUNFUN(__GMPN_COPY_INCR), TYPE_COPYI }, +#endif + +#if HAVE_NATIVE_mpn_copyi + { TRY(mpn_copyi), TYPE_COPYI }, +#endif +#if HAVE_NATIVE_mpn_copyd + { TRY(mpn_copyd), TYPE_COPYD }, +#endif + + { TRY(mpn_cnd_add_n), TYPE_ADDCND_N }, + { TRY(mpn_cnd_sub_n), TYPE_SUBCND_N }, +#if HAVE_NATIVE_mpn_addlsh1_n == 1 + { TRY(mpn_addlsh1_n), TYPE_ADDLSH1_N }, +#endif +#if HAVE_NATIVE_mpn_addlsh2_n == 1 + { TRY(mpn_addlsh2_n), TYPE_ADDLSH2_N }, +#endif +#if HAVE_NATIVE_mpn_addlsh_n + { TRY(mpn_addlsh_n), TYPE_ADDLSH_N }, +#endif +#if HAVE_NATIVE_mpn_addlsh1_n_ip1 + { TRY_FUNFUN(mpn_addlsh1_n_ip1), TYPE_ADDLSH1_N_IP1 }, +#endif +#if HAVE_NATIVE_mpn_addlsh2_n_ip1 + { TRY_FUNFUN(mpn_addlsh2_n_ip1), TYPE_ADDLSH2_N_IP1 }, +#endif +#if HAVE_NATIVE_mpn_addlsh_n_ip1 + { TRY_FUNFUN(mpn_addlsh_n_ip1), TYPE_ADDLSH_N_IP1 }, +#endif +#if HAVE_NATIVE_mpn_addlsh1_n_ip2 + { TRY_FUNFUN(mpn_addlsh1_n_ip2), TYPE_ADDLSH1_N_IP2 }, +#endif +#if HAVE_NATIVE_mpn_addlsh2_n_ip2 + { TRY_FUNFUN(mpn_addlsh2_n_ip2), TYPE_ADDLSH2_N_IP2 }, +#endif +#if HAVE_NATIVE_mpn_addlsh_n_ip2 + { TRY_FUNFUN(mpn_addlsh_n_ip2), TYPE_ADDLSH_N_IP2 }, +#endif +#if HAVE_NATIVE_mpn_sublsh1_n == 1 + { TRY(mpn_sublsh1_n), TYPE_SUBLSH1_N }, +#endif +#if HAVE_NATIVE_mpn_sublsh2_n == 1 + { TRY(mpn_sublsh2_n), TYPE_SUBLSH2_N }, +#endif +#if HAVE_NATIVE_mpn_sublsh_n + { TRY(mpn_sublsh_n), TYPE_SUBLSH_N }, +#endif +#if HAVE_NATIVE_mpn_sublsh1_n_ip1 + { TRY_FUNFUN(mpn_sublsh1_n_ip1), TYPE_SUBLSH1_N_IP1 }, +#endif +#if HAVE_NATIVE_mpn_sublsh2_n_ip1 + { TRY_FUNFUN(mpn_sublsh2_n_ip1), TYPE_SUBLSH2_N_IP1 }, +#endif +#if HAVE_NATIVE_mpn_sublsh_n_ip1 + { TRY_FUNFUN(mpn_sublsh_n_ip1), TYPE_SUBLSH_N_IP1 }, +#endif +#if HAVE_NATIVE_mpn_rsblsh1_n == 1 + { TRY(mpn_rsblsh1_n), TYPE_RSBLSH1_N }, +#endif +#if HAVE_NATIVE_mpn_rsblsh2_n == 1 + { TRY(mpn_rsblsh2_n), TYPE_RSBLSH2_N }, +#endif +#if HAVE_NATIVE_mpn_rsblsh_n + { TRY(mpn_rsblsh_n), TYPE_RSBLSH_N }, +#endif +#if HAVE_NATIVE_mpn_rsh1add_n + { TRY(mpn_rsh1add_n), TYPE_RSH1ADD_N }, +#endif +#if HAVE_NATIVE_mpn_rsh1sub_n + { TRY(mpn_rsh1sub_n), TYPE_RSH1SUB_N }, +#endif + +#if HAVE_NATIVE_mpn_addlsh1_nc == 1 + { TRY(mpn_addlsh1_nc), TYPE_ADDLSH1_NC }, +#endif +#if HAVE_NATIVE_mpn_addlsh2_nc == 1 + { TRY(mpn_addlsh2_nc), TYPE_ADDLSH2_NC }, +#endif +#if HAVE_NATIVE_mpn_addlsh_nc + { TRY(mpn_addlsh_nc), TYPE_ADDLSH_NC }, +#endif +#if HAVE_NATIVE_mpn_sublsh1_nc == 1 + { TRY(mpn_sublsh1_nc), TYPE_SUBLSH1_NC }, +#endif +#if HAVE_NATIVE_mpn_sublsh2_nc == 1 + { TRY(mpn_sublsh2_nc), TYPE_SUBLSH2_NC }, +#endif +#if HAVE_NATIVE_mpn_sublsh_nc + { TRY(mpn_sublsh_nc), TYPE_SUBLSH_NC }, +#endif +#if HAVE_NATIVE_mpn_rsblsh1_nc + { TRY(mpn_rsblsh1_nc), TYPE_RSBLSH1_NC }, +#endif +#if HAVE_NATIVE_mpn_rsblsh2_nc + { TRY(mpn_rsblsh2_nc), TYPE_RSBLSH2_NC }, +#endif +#if HAVE_NATIVE_mpn_rsblsh_nc + { TRY(mpn_rsblsh_nc), TYPE_RSBLSH_NC }, +#endif + + { TRY_FUNFUN(mpn_and_n), TYPE_AND_N }, + { TRY_FUNFUN(mpn_andn_n), TYPE_ANDN_N }, + { TRY_FUNFUN(mpn_nand_n), TYPE_NAND_N }, + { TRY_FUNFUN(mpn_ior_n), TYPE_IOR_N }, + { TRY_FUNFUN(mpn_iorn_n), TYPE_IORN_N }, + { TRY_FUNFUN(mpn_nior_n), TYPE_NIOR_N }, + { TRY_FUNFUN(mpn_xor_n), TYPE_XOR_N }, + { TRY_FUNFUN(mpn_xnor_n), TYPE_XNOR_N }, + + { TRY(mpn_divrem_1), TYPE_DIVREM_1 }, +#if USE_PREINV_DIVREM_1 + { TRY(mpn_preinv_divrem_1), TYPE_PREINV_DIVREM_1 }, +#endif + { TRY(mpn_mod_1), TYPE_MOD_1 }, +#if USE_PREINV_MOD_1 + { TRY(mpn_preinv_mod_1), TYPE_PREINV_MOD_1 }, +#endif +#if HAVE_NATIVE_mpn_divrem_1c + { TRY(mpn_divrem_1c), TYPE_DIVREM_1C }, +#endif +#if HAVE_NATIVE_mpn_mod_1c + { TRY(mpn_mod_1c), TYPE_MOD_1C }, +#endif + { TRY(mpn_div_qr_1n_pi1), TYPE_DIV_QR_1N_PI1 }, +#if GMP_NUMB_BITS % 4 == 0 + { TRY(mpn_mod_34lsub1), TYPE_MOD_34LSUB1 }, +#endif + + { TRY_FUNFUN(udiv_qrnnd), TYPE_UDIV_QRNND, 2 }, +#if HAVE_NATIVE_mpn_udiv_qrnnd + { TRY(mpn_udiv_qrnnd), TYPE_UDIV_QRNND, 2 }, +#endif +#if HAVE_NATIVE_mpn_udiv_qrnnd_r + { TRY(mpn_udiv_qrnnd_r), TYPE_UDIV_QRNND_R, 2 }, +#endif + + { TRY(mpn_divexact_1), TYPE_DIVEXACT_1 }, + { TRY(mpn_bdiv_q_1), TYPE_BDIV_Q_1 }, + { TRY_FUNFUN(mpn_divexact_by3), TYPE_DIVEXACT_BY3 }, + { TRY(mpn_divexact_by3c), TYPE_DIVEXACT_BY3C }, + + { TRY_FUNFUN(mpn_modexact_1_odd), TYPE_MODEXACT_1_ODD }, + { TRY(mpn_modexact_1c_odd), TYPE_MODEXACT_1C_ODD }, + + + { TRY(mpn_sbpi1_div_qr), TYPE_SBPI1_DIV_QR, 3}, + { TRY(mpn_tdiv_qr), TYPE_TDIV_QR }, + + { TRY(mpn_mul_1), TYPE_MUL_1 }, +#if HAVE_NATIVE_mpn_mul_1c + { TRY(mpn_mul_1c), TYPE_MUL_1C }, +#endif +#if HAVE_NATIVE_mpn_mul_2 + { TRY(mpn_mul_2), TYPE_MUL_2, 2 }, +#endif +#if HAVE_NATIVE_mpn_mul_3 + { TRY(mpn_mul_3), TYPE_MUL_3, 3 }, +#endif +#if HAVE_NATIVE_mpn_mul_4 + { TRY(mpn_mul_4), TYPE_MUL_4, 4 }, +#endif +#if HAVE_NATIVE_mpn_mul_5 + { TRY(mpn_mul_5), TYPE_MUL_5, 5 }, +#endif +#if HAVE_NATIVE_mpn_mul_6 + { TRY(mpn_mul_6), TYPE_MUL_6, 6 }, +#endif + + { TRY(mpn_rshift), TYPE_RSHIFT }, + { TRY(mpn_lshift), TYPE_LSHIFT }, + { TRY(mpn_lshiftc), TYPE_LSHIFTC }, + + + { TRY(mpn_mul_basecase), TYPE_MUL_MN }, + { TRY(mpn_mulmid_basecase), TYPE_MULMID_MN }, + { TRY(mpn_mullo_basecase), TYPE_MULLO_N }, + { TRY(mpn_sqrlo_basecase), TYPE_SQRLO }, + { TRY(mpn_sqrlo), TYPE_SQRLO }, +#if SQR_TOOM2_THRESHOLD > 0 + { TRY(mpn_sqr_basecase), TYPE_SQR }, +#endif + + { TRY(mpn_mul), TYPE_MUL_MN }, + { TRY(mpn_mul_n), TYPE_MUL_N }, + { TRY(mpn_sqr), TYPE_SQR }, + + { TRY_FUNFUN(umul_ppmm), TYPE_UMUL_PPMM, 2 }, +#if HAVE_NATIVE_mpn_umul_ppmm + { TRY(mpn_umul_ppmm), TYPE_UMUL_PPMM, 2 }, +#endif +#if HAVE_NATIVE_mpn_umul_ppmm_r + { TRY(mpn_umul_ppmm_r), TYPE_UMUL_PPMM_R, 2 }, +#endif + + { TRY_FUNFUN(mpn_toom22_mul), TYPE_MUL_N, MPN_TOOM22_MUL_MINSIZE }, + { TRY_FUNFUN(mpn_toom2_sqr), TYPE_SQR, MPN_TOOM2_SQR_MINSIZE }, + { TRY_FUNFUN(mpn_toom33_mul), TYPE_MUL_N, MPN_TOOM33_MUL_MINSIZE }, + { TRY_FUNFUN(mpn_toom3_sqr), TYPE_SQR, MPN_TOOM3_SQR_MINSIZE }, + { TRY_FUNFUN(mpn_toom44_mul), TYPE_MUL_N, MPN_TOOM44_MUL_MINSIZE }, + { TRY_FUNFUN(mpn_toom4_sqr), TYPE_SQR, MPN_TOOM4_SQR_MINSIZE }, + + { TRY(mpn_mulmid_n), TYPE_MULMID_N, 1 }, + { TRY(mpn_mulmid), TYPE_MULMID_MN, 1 }, + { TRY_FUNFUN(mpn_toom42_mulmid), TYPE_MULMID_N, + (2 * MPN_TOOM42_MULMID_MINSIZE - 1) }, + + { TRY(mpn_gcd_1), TYPE_GCD_1 }, + { TRY(mpn_gcd), TYPE_GCD }, + { TRY(mpz_legendre), TYPE_MPZ_LEGENDRE }, + { TRY(mpz_jacobi), TYPE_MPZ_JACOBI }, + { TRY(mpz_kronecker), TYPE_MPZ_KRONECKER }, + { TRY(mpz_kronecker_ui), TYPE_MPZ_KRONECKER_UI }, + { TRY(mpz_kronecker_si), TYPE_MPZ_KRONECKER_SI }, + { TRY(mpz_ui_kronecker), TYPE_MPZ_UI_KRONECKER }, + { TRY(mpz_si_kronecker), TYPE_MPZ_SI_KRONECKER }, + + { TRY(mpn_popcount), TYPE_POPCOUNT }, + { TRY(mpn_hamdist), TYPE_HAMDIST }, + + { TRY(mpn_sqrtrem), TYPE_SQRTREM }, + { TRY_FUNFUN(mpn_sqrt), TYPE_SQRT }, + + { TRY_FUNFUN(MPN_ZERO), TYPE_ZERO }, + + { TRY(mpn_get_str), TYPE_GET_STR }, + + { TRY(mpn_binvert), TYPE_BINVERT }, + { TRY(mpn_invert), TYPE_INVERT }, + +#ifdef EXTRA_ROUTINES + EXTRA_ROUTINES +#endif +}; + +const struct choice_t *choice = NULL; + + +void +mprotect_maybe (void *addr, size_t len, int prot) +{ + if (!option_redzones) + return; + +#if HAVE_MPROTECT + if (mprotect (addr, len, prot) != 0) + { + fprintf (stderr, "Cannot mprotect %p 0x%X 0x%X: %s\n", + addr, (unsigned) len, prot, strerror (errno)); + exit (1); + } +#else + { + static int warned = 0; + if (!warned) + { + fprintf (stderr, + "mprotect not available, bounds testing not performed\n"); + warned = 1; + } + } +#endif +} + +/* round "a" up to a multiple of "m" */ +size_t +round_up_multiple (size_t a, size_t m) +{ + unsigned long r; + + r = a % m; + if (r == 0) + return a; + else + return a + (m - r); +} + + +/* On some systems it seems that only an mmap'ed region can be mprotect'ed, + for instance HP-UX 10. + + mmap will almost certainly return a pointer already aligned to a page + boundary, but it's easy enough to share the alignment handling with the + malloc case. */ + +void +malloc_region (struct region_t *r, mp_size_t n) +{ + mp_ptr p; + size_t nbytes; + + ASSERT ((pagesize % GMP_LIMB_BYTES) == 0); + + n = round_up_multiple (n, PAGESIZE_LIMBS); + r->size = n; + + nbytes = n*GMP_LIMB_BYTES + 2*REDZONE_BYTES + pagesize; + +#if defined (MAP_ANONYMOUS) && ! defined (MAP_ANON) +#define MAP_ANON MAP_ANONYMOUS +#endif + +#if HAVE_MMAP && defined (MAP_ANON) + /* note must pass fd=-1 for MAP_ANON on BSD */ + p = (mp_ptr) mmap (NULL, nbytes, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); + if (p == (void *) -1) + { + fprintf (stderr, "Cannot mmap %#x anon bytes: %s\n", + (unsigned) nbytes, strerror (errno)); + exit (1); + } +#else + p = (mp_ptr) malloc (nbytes); + ASSERT_ALWAYS (p != NULL); +#endif + + p = (mp_ptr) align_pointer (p, pagesize); + + mprotect_maybe (p, REDZONE_BYTES, PROT_NONE); + p += REDZONE_LIMBS; + r->ptr = p; + + mprotect_maybe (p + n, REDZONE_BYTES, PROT_NONE); +} + +void +mprotect_region (const struct region_t *r, int prot) +{ + mprotect_maybe (r->ptr, r->size, prot); +} + + +/* First four entries must be 0,1,2,3 for the benefit of CARRY_BIT, CARRY_3, + and CARRY_4 */ +mp_limb_t carry_array[] = { + 0, 1, 2, 3, + 4, + CNST_LIMB(1) << 8, + CNST_LIMB(1) << 16, + GMP_NUMB_MAX +}; +int carry_index; + +#define CARRY_COUNT \ + ((tr->carry == CARRY_BIT) ? 2 \ + : tr->carry == CARRY_3 ? 3 \ + : tr->carry == CARRY_4 ? 4 \ + : (tr->carry == CARRY_LIMB || tr->carry == CARRY_DIVISOR) \ + ? numberof(carry_array) + CARRY_RANDOMS \ + : 1) + +#define MPN_RANDOM_ALT(index,dst,size) \ + (((index) & 1) ? refmpn_random (dst, size) : refmpn_random2 (dst, size)) + +/* The dummy value after MPN_RANDOM_ALT ensures both sides of the ":" have + the same type */ +#define CARRY_ITERATION \ + for (carry_index = 0; \ + (carry_index < numberof (carry_array) \ + ? (carry = carry_array[carry_index]) \ + : (MPN_RANDOM_ALT (carry_index, &carry, 1), (mp_limb_t) 0)), \ + (tr->carry == CARRY_DIVISOR ? carry %= divisor : 0), \ + carry_index < CARRY_COUNT; \ + carry_index++) + + +mp_limb_t multiplier_array[] = { + 0, 1, 2, 3, + CNST_LIMB(1) << 8, + CNST_LIMB(1) << 16, + GMP_NUMB_MAX - 2, + GMP_NUMB_MAX - 1, + GMP_NUMB_MAX +}; +int multiplier_index; + +mp_limb_t divisor_array[] = { + 1, 2, 3, + CNST_LIMB(1) << 8, + CNST_LIMB(1) << 16, + CNST_LIMB(1) << (GMP_NUMB_BITS/2 - 1), + GMP_NUMB_MAX >> (GMP_NUMB_BITS/2), + GMP_NUMB_HIGHBIT, + GMP_NUMB_HIGHBIT + 1, + GMP_NUMB_MAX - 2, + GMP_NUMB_MAX - 1, + GMP_NUMB_MAX +}; + +int divisor_index; + +/* The dummy value after MPN_RANDOM_ALT ensures both sides of the ":" have + the same type */ +#define ARRAY_ITERATION(var, index, limit, array, randoms, cond) \ + for (index = 0; \ + (index < numberof (array) \ + ? (var = array[index]) \ + : (MPN_RANDOM_ALT (index, &var, 1), (mp_limb_t) 0)), \ + index < limit; \ + index++) + +#define MULTIPLIER_COUNT \ + (tr->multiplier \ + ? numberof (multiplier_array) + MULTIPLIER_RANDOMS \ + : 1) + +#define MULTIPLIER_ITERATION \ + ARRAY_ITERATION(multiplier, multiplier_index, MULTIPLIER_COUNT, \ + multiplier_array, MULTIPLIER_RANDOMS, TRY_MULTIPLIER) + +#define DIVISOR_COUNT \ + (tr->divisor \ + ? numberof (divisor_array) + DIVISOR_RANDOMS \ + : 1) + +#define DIVISOR_ITERATION \ + ARRAY_ITERATION(divisor, divisor_index, DIVISOR_COUNT, divisor_array, \ + DIVISOR_RANDOMS, TRY_DIVISOR) + + +/* overlap_array[].s[i] is where s[i] should be, 0 or 1 means overlapping + d[0] or d[1] respectively, -1 means a separate (write-protected) + location. */ + +struct overlap_t { + int s[NUM_SOURCES]; +} overlap_array[] = { + { { -1, -1, -1, -1, -1 } }, + { { 0, -1, -1, -1, -1 } }, + { { -1, 0, -1, -1, -1 } }, + { { 0, 0, -1, -1, -1 } }, + { { 1, -1, -1, -1, -1 } }, + { { -1, 1, -1, -1, -1 } }, + { { 1, 1, -1, -1, -1 } }, + { { 0, 1, -1, -1, -1 } }, + { { 1, 0, -1, -1, -1 } }, +}; + +struct overlap_t *overlap, *overlap_limit; + +#define OVERLAP_COUNT \ + (tr->overlap & OVERLAP_NONE ? 1 \ + : tr->overlap & OVERLAP_NOT_SRCS ? 3 \ + : tr->overlap & OVERLAP_NOT_SRC2 ? 2 \ + : tr->overlap & OVERLAP_NOT_DST2 ? 4 \ + : tr->dst[1] ? 9 \ + : tr->src[1] ? 4 \ + : tr->dst[0] ? 2 \ + : 1) + +#define OVERLAP_ITERATION \ + for (overlap = &overlap_array[0], \ + overlap_limit = &overlap_array[OVERLAP_COUNT]; \ + overlap < overlap_limit; \ + overlap++) + + +int base = 10; + +#define T_RAND_COUNT 2 +int t_rand; + +void +t_random (mp_ptr ptr, mp_size_t n) +{ + if (n == 0) + return; + + switch (option_data) { + case DATA_TRAND: + switch (t_rand) { + case 0: refmpn_random (ptr, n); break; + case 1: refmpn_random2 (ptr, n); break; + default: abort(); + } + break; + case DATA_SEQ: + { + static mp_limb_t counter = 0; + mp_size_t i; + for (i = 0; i < n; i++) + ptr[i] = ++counter; + } + break; + case DATA_ZEROS: + refmpn_zero (ptr, n); + break; + case DATA_FFS: + refmpn_fill (ptr, n, GMP_NUMB_MAX); + break; + case DATA_2FD: + /* Special value 0x2FFF...FFFD, which divided by 3 gives 0xFFF...FFF, + inducing the q1_ff special case in the mul-by-inverse part of some + versions of divrem_1 and mod_1. */ + refmpn_fill (ptr, n, (mp_limb_t) -1); + ptr[n-1] = 2; + ptr[0] -= 2; + break; + + default: + abort(); + } +} +#define T_RAND_ITERATION \ + for (t_rand = 0; t_rand < T_RAND_COUNT; t_rand++) + + +void +print_each (const struct each_t *e) +{ + int i; + + printf ("%s %s\n", e->name, e == &ref ? tr->reference_name : choice->name); + if (tr->retval) + mpn_trace (" retval", &e->retval, 1); + + for (i = 0; i < NUM_DESTS; i++) + { + if (tr->dst[i]) + { + if (tr->dst_bytes[i]) + byte_tracen (" d[%d]", i, e->d[i].p, d[i].size); + else + mpn_tracen (" d[%d]", i, e->d[i].p, d[i].size); + printf (" located %p\n", (void *) (e->d[i].p)); + } + } + + for (i = 0; i < NUM_SOURCES; i++) + if (tr->src[i]) + printf (" s[%d] located %p\n", i, (void *) (e->s[i].p)); +} + + +void +print_all (void) +{ + int i; + + printf ("\n"); + printf ("size %ld\n", (long) size); + if (tr->size2) + printf ("size2 %ld\n", (long) size2); + + for (i = 0; i < NUM_DESTS; i++) + if (d[i].size != size) + printf ("d[%d].size %ld\n", i, (long) d[i].size); + + if (tr->multiplier) + mpn_trace (" multiplier", &multiplier, 1); + if (tr->divisor) + mpn_trace (" divisor", &divisor, 1); + if (tr->shift) + printf (" shift %lu\n", shift); + if (tr->carry) + mpn_trace (" carry", &carry, 1); + if (tr->msize) + mpn_trace (" multiplier_N", multiplier_N, tr->msize); + + for (i = 0; i < NUM_DESTS; i++) + if (tr->dst[i]) + printf (" d[%d] %s, align %ld, size %ld\n", + i, d[i].high ? "high" : "low", + (long) d[i].align, (long) d[i].size); + + for (i = 0; i < NUM_SOURCES; i++) + { + if (tr->src[i]) + { + printf (" s[%d] %s, align %ld, ", + i, s[i].high ? "high" : "low", (long) s[i].align); + switch (overlap->s[i]) { + case -1: + printf ("no overlap\n"); + break; + default: + printf ("==d[%d]%s\n", + overlap->s[i], + tr->overlap == OVERLAP_LOW_TO_HIGH ? "+a" + : tr->overlap == OVERLAP_HIGH_TO_LOW ? "-a" + : ""); + break; + } + printf (" s[%d]=", i); + if (tr->carry_sign && (carry & (1 << i))) + printf ("-"); + mpn_trace (NULL, s[i].p, SRC_SIZE(i)); + } + } + + if (tr->dst0_from_src1) + mpn_trace (" d[0]", s[1].region.ptr, size); + + if (tr->reference) + print_each (&ref); + print_each (&fun); +} + +void +compare (void) +{ + int error = 0; + int i; + + if (tr->retval && ref.retval != fun.retval) + { + gmp_printf ("Different return values (%Mu, %Mu)\n", + ref.retval, fun.retval); + error = 1; + } + + for (i = 0; i < NUM_DESTS; i++) + { + switch (tr->dst_size[i]) { + case SIZE_RETVAL: + case SIZE_GET_STR: + d[i].size = ref.retval; + break; + } + } + + for (i = 0; i < NUM_DESTS; i++) + { + if (! tr->dst[i]) + continue; + + if (tr->dst_bytes[i]) + { + if (memcmp (ref.d[i].p, fun.d[i].p, d[i].size) != 0) + { + printf ("Different d[%d] data results, low diff at %ld, high diff at %ld\n", + i, + (long) byte_diff_lowest (ref.d[i].p, fun.d[i].p, d[i].size), + (long) byte_diff_highest (ref.d[i].p, fun.d[i].p, d[i].size)); + error = 1; + } + } + else + { + if (d[i].size != 0 + && ! refmpn_equal_anynail (ref.d[i].p, fun.d[i].p, d[i].size)) + { + printf ("Different d[%d] data results, low diff at %ld, high diff at %ld\n", + i, + (long) mpn_diff_lowest (ref.d[i].p, fun.d[i].p, d[i].size), + (long) mpn_diff_highest (ref.d[i].p, fun.d[i].p, d[i].size)); + error = 1; + } + } + } + + if (error) + { + print_all(); + abort(); + } +} + + +/* The functions are cast if the return value should be a long rather than + the default mp_limb_t. This is necessary under _LONG_LONG_LIMB. This + might not be enough if some actual calling conventions checking is + implemented on a long long limb system. */ + +void +call (struct each_t *e, tryfun_t function) +{ + switch (choice->type) { + case TYPE_ADD: + case TYPE_SUB: + e->retval = CALLING_CONVENTIONS (function) + (e->d[0].p, e->s[0].p, size, e->s[1].p, size2); + break; + + case TYPE_ADD_N: + case TYPE_SUB_N: + case TYPE_ADDLSH1_N: + case TYPE_ADDLSH2_N: + case TYPE_SUBLSH1_N: + case TYPE_SUBLSH2_N: + case TYPE_RSBLSH1_N: + case TYPE_RSBLSH2_N: + case TYPE_RSH1ADD_N: + case TYPE_RSH1SUB_N: + e->retval = CALLING_CONVENTIONS (function) + (e->d[0].p, e->s[0].p, e->s[1].p, size); + break; + case TYPE_ADDLSH_N: + case TYPE_SUBLSH_N: + case TYPE_RSBLSH_N: + e->retval = CALLING_CONVENTIONS (function) + (e->d[0].p, e->s[0].p, e->s[1].p, size, shift); + break; + case TYPE_ADDLSH_NC: + case TYPE_SUBLSH_NC: + case TYPE_RSBLSH_NC: + e->retval = CALLING_CONVENTIONS (function) + (e->d[0].p, e->s[0].p, e->s[1].p, size, shift, carry); + break; + case TYPE_ADDLSH1_NC: + case TYPE_ADDLSH2_NC: + case TYPE_SUBLSH1_NC: + case TYPE_SUBLSH2_NC: + case TYPE_RSBLSH1_NC: + case TYPE_RSBLSH2_NC: + case TYPE_ADD_NC: + case TYPE_SUB_NC: + e->retval = CALLING_CONVENTIONS (function) + (e->d[0].p, e->s[0].p, e->s[1].p, size, carry); + break; + case TYPE_ADDCND_N: + case TYPE_SUBCND_N: + e->retval = CALLING_CONVENTIONS (function) + (carry, e->d[0].p, e->s[0].p, e->s[1].p, size); + break; + case TYPE_ADD_ERR1_N: + case TYPE_SUB_ERR1_N: + e->retval = CALLING_CONVENTIONS (function) + (e->d[0].p, e->s[0].p, e->s[1].p, e->d[1].p, e->s[2].p, size, carry); + break; + case TYPE_ADD_ERR2_N: + case TYPE_SUB_ERR2_N: + e->retval = CALLING_CONVENTIONS (function) + (e->d[0].p, e->s[0].p, e->s[1].p, e->d[1].p, e->s[2].p, e->s[3].p, size, carry); + break; + case TYPE_ADD_ERR3_N: + case TYPE_SUB_ERR3_N: + e->retval = CALLING_CONVENTIONS (function) + (e->d[0].p, e->s[0].p, e->s[1].p, e->d[1].p, e->s[2].p, e->s[3].p, e->s[4].p, size, carry); + break; + + case TYPE_MUL_1: + case TYPE_ADDMUL_1: + case TYPE_SUBMUL_1: + e->retval = CALLING_CONVENTIONS (function) + (e->d[0].p, e->s[0].p, size, multiplier); + break; + case TYPE_MUL_1C: + case TYPE_ADDMUL_1C: + case TYPE_SUBMUL_1C: + e->retval = CALLING_CONVENTIONS (function) + (e->d[0].p, e->s[0].p, size, multiplier, carry); + break; + + case TYPE_MUL_2: + case TYPE_MUL_3: + case TYPE_MUL_4: + case TYPE_MUL_5: + case TYPE_MUL_6: + if (size == 1) + abort (); + e->retval = CALLING_CONVENTIONS (function) + (e->d[0].p, e->s[0].p, size, multiplier_N); + break; + + case TYPE_ADDMUL_2: + case TYPE_ADDMUL_3: + case TYPE_ADDMUL_4: + case TYPE_ADDMUL_5: + case TYPE_ADDMUL_6: + case TYPE_ADDMUL_7: + case TYPE_ADDMUL_8: + if (size == 1) + abort (); + e->retval = CALLING_CONVENTIONS (function) + (e->d[0].p, e->s[0].p, size, multiplier_N); + break; + + case TYPE_AND_N: + case TYPE_ANDN_N: + case TYPE_NAND_N: + case TYPE_IOR_N: + case TYPE_IORN_N: + case TYPE_NIOR_N: + case TYPE_XOR_N: + case TYPE_XNOR_N: + CALLING_CONVENTIONS (function) (e->d[0].p, e->s[0].p, e->s[1].p, size); + break; + + case TYPE_ADDSUB_N: + e->retval = CALLING_CONVENTIONS (function) + (e->d[0].p, e->d[1].p, e->s[0].p, e->s[1].p, size); + break; + case TYPE_ADDSUB_NC: + e->retval = CALLING_CONVENTIONS (function) + (e->d[0].p, e->d[1].p, e->s[0].p, e->s[1].p, size, carry); + break; + + case TYPE_COPY: + case TYPE_COPYI: + case TYPE_COPYD: + case TYPE_COM: + CALLING_CONVENTIONS (function) (e->d[0].p, e->s[0].p, size); + break; + + case TYPE_ADDLSH1_N_IP1: + case TYPE_ADDLSH2_N_IP1: + case TYPE_ADDLSH1_N_IP2: + case TYPE_ADDLSH2_N_IP2: + case TYPE_SUBLSH1_N_IP1: + case TYPE_SUBLSH2_N_IP1: + case TYPE_DIVEXACT_BY3: + e->retval = CALLING_CONVENTIONS (function) (e->d[0].p, e->s[0].p, size); + break; + case TYPE_DIVEXACT_BY3C: + e->retval = CALLING_CONVENTIONS (function) (e->d[0].p, e->s[0].p, size, + carry); + break; + + + case TYPE_DIVMOD_1: + case TYPE_DIVEXACT_1: + case TYPE_BDIV_Q_1: + e->retval = CALLING_CONVENTIONS (function) + (e->d[0].p, e->s[0].p, size, divisor); + break; + case TYPE_DIVMOD_1C: + e->retval = CALLING_CONVENTIONS (function) + (e->d[0].p, e->s[0].p, size, divisor, carry); + break; + case TYPE_DIVREM_1: + e->retval = CALLING_CONVENTIONS (function) + (e->d[0].p, size2, e->s[0].p, size, divisor); + break; + case TYPE_DIVREM_1C: + e->retval = CALLING_CONVENTIONS (function) + (e->d[0].p, size2, e->s[0].p, size, divisor, carry); + break; + case TYPE_PREINV_DIVREM_1: + { + mp_limb_t dinv; + unsigned shift; + shift = refmpn_count_leading_zeros (divisor); + dinv = refmpn_invert_limb (divisor << shift); + e->retval = CALLING_CONVENTIONS (function) + (e->d[0].p, size2, e->s[0].p, size, divisor, dinv, shift); + } + break; + case TYPE_MOD_1: + case TYPE_MODEXACT_1_ODD: + e->retval = CALLING_CONVENTIONS (function) + (e->s[0].p, size, divisor); + break; + case TYPE_MOD_1C: + case TYPE_MODEXACT_1C_ODD: + e->retval = CALLING_CONVENTIONS (function) + (e->s[0].p, size, divisor, carry); + break; + case TYPE_PREINV_MOD_1: + e->retval = CALLING_CONVENTIONS (function) + (e->s[0].p, size, divisor, refmpn_invert_limb (divisor)); + break; + case TYPE_DIV_QR_1N_PI1: + { + mp_limb_t dinv = refmpn_invert_limb (divisor); + e->retval = CALLING_CONVENTIONS (function) + (e->d[0].p, e->s[0].p, size, e->s[1].p[0], divisor, dinv); + break; + } + + case TYPE_MOD_34LSUB1: + e->retval = CALLING_CONVENTIONS (function) (e->s[0].p, size); + break; + + case TYPE_UDIV_QRNND: + e->retval = CALLING_CONVENTIONS (function) + (e->d[0].p, e->s[0].p[1], e->s[0].p[0], divisor); + break; + case TYPE_UDIV_QRNND_R: + e->retval = CALLING_CONVENTIONS (function) + (e->s[0].p[1], e->s[0].p[0], divisor, e->d[0].p); + break; + + case TYPE_SBPI1_DIV_QR: + { + gmp_pi1_t dinv; + invert_pi1 (dinv, e->s[1].p[size2-1], e->s[1].p[size2-2]); /* FIXME: use refinvert_pi1 */ + refmpn_copyi (e->d[1].p, e->s[0].p, size); /* dividend */ + refmpn_fill (e->d[0].p, size-size2, 0x98765432); /* quotient */ + e->retval = CALLING_CONVENTIONS (function) + (e->d[0].p, e->d[1].p, size, e->s[1].p, size2, dinv.inv32); + refmpn_zero (e->d[1].p+size2, size-size2); /* excess over remainder */ + } + break; + + case TYPE_TDIV_QR: + CALLING_CONVENTIONS (function) (e->d[0].p, e->d[1].p, 0, + e->s[0].p, size, e->s[1].p, size2); + break; + + case TYPE_GCD_1: + /* Must have a non-zero src, but this probably isn't the best way to do + it. */ + if (refmpn_zero_p (e->s[0].p, size)) + e->retval = 0; + else + e->retval = CALLING_CONVENTIONS (function) (e->s[0].p, size, divisor); + break; + + case TYPE_GCD: + /* Sources are destroyed, so they're saved and replaced, but a general + approach to this might be better. Note that it's still e->s[0].p and + e->s[1].p that are passed, to get the desired alignments. */ + { + mp_ptr s0 = refmpn_malloc_limbs (size); + mp_ptr s1 = refmpn_malloc_limbs (size2); + refmpn_copyi (s0, e->s[0].p, size); + refmpn_copyi (s1, e->s[1].p, size2); + + mprotect_region (&s[0].region, PROT_READ|PROT_WRITE); + mprotect_region (&s[1].region, PROT_READ|PROT_WRITE); + e->retval = CALLING_CONVENTIONS (function) (e->d[0].p, + e->s[0].p, size, + e->s[1].p, size2); + refmpn_copyi (e->s[0].p, s0, size); + refmpn_copyi (e->s[1].p, s1, size2); + free (s0); + free (s1); + } + break; + + case TYPE_GCD_FINDA: + { + /* FIXME: do this with a flag */ + mp_limb_t c[2]; + c[0] = e->s[0].p[0]; + c[0] += (c[0] == 0); + c[1] = e->s[0].p[0]; + c[1] += (c[1] == 0); + e->retval = CALLING_CONVENTIONS (function) (c); + } + break; + + case TYPE_MPZ_LEGENDRE: + case TYPE_MPZ_JACOBI: + { + mpz_t a, b; + PTR(a) = e->s[0].p; SIZ(a) = (carry==0 ? size : -size); + PTR(b) = e->s[1].p; SIZ(b) = size2; + e->retval = CALLING_CONVENTIONS (function) (a, b); + } + break; + case TYPE_MPZ_KRONECKER: + { + mpz_t a, b; + PTR(a) = e->s[0].p; SIZ(a) = ((carry&1)==0 ? size : -size); + PTR(b) = e->s[1].p; SIZ(b) = ((carry&2)==0 ? size2 : -size2); + e->retval = CALLING_CONVENTIONS (function) (a, b); + } + break; + case TYPE_MPZ_KRONECKER_UI: + { + mpz_t a; + PTR(a) = e->s[0].p; SIZ(a) = (carry==0 ? size : -size); + e->retval = CALLING_CONVENTIONS(function) (a, (unsigned long)multiplier); + } + break; + case TYPE_MPZ_KRONECKER_SI: + { + mpz_t a; + PTR(a) = e->s[0].p; SIZ(a) = (carry==0 ? size : -size); + e->retval = CALLING_CONVENTIONS (function) (a, (long) multiplier); + } + break; + case TYPE_MPZ_UI_KRONECKER: + { + mpz_t b; + PTR(b) = e->s[0].p; SIZ(b) = (carry==0 ? size : -size); + e->retval = CALLING_CONVENTIONS(function) ((unsigned long)multiplier, b); + } + break; + case TYPE_MPZ_SI_KRONECKER: + { + mpz_t b; + PTR(b) = e->s[0].p; SIZ(b) = (carry==0 ? size : -size); + e->retval = CALLING_CONVENTIONS (function) ((long) multiplier, b); + } + break; + + case TYPE_MUL_MN: + case TYPE_MULMID_MN: + CALLING_CONVENTIONS (function) + (e->d[0].p, e->s[0].p, size, e->s[1].p, size2); + break; + case TYPE_MUL_N: + case TYPE_MULLO_N: + CALLING_CONVENTIONS (function) (e->d[0].p, e->s[0].p, e->s[1].p, size); + break; + case TYPE_MULMID_N: + CALLING_CONVENTIONS (function) (e->d[0].p, e->s[0].p, e->s[1].p, + (size + 1) / 2); + break; + case TYPE_SQR: + case TYPE_SQRLO: + CALLING_CONVENTIONS (function) (e->d[0].p, e->s[0].p, size); + break; + + case TYPE_UMUL_PPMM: + e->retval = CALLING_CONVENTIONS (function) + (e->d[0].p, e->s[0].p[0], e->s[0].p[1]); + break; + case TYPE_UMUL_PPMM_R: + e->retval = CALLING_CONVENTIONS (function) + (e->s[0].p[0], e->s[0].p[1], e->d[0].p); + break; + + case TYPE_ADDLSH_N_IP1: + case TYPE_ADDLSH_N_IP2: + case TYPE_SUBLSH_N_IP1: + case TYPE_LSHIFT: + case TYPE_LSHIFTC: + case TYPE_RSHIFT: + e->retval = CALLING_CONVENTIONS (function) + (e->d[0].p, e->s[0].p, size, shift); + break; + + case TYPE_POPCOUNT: + e->retval = (* (unsigned long (*)(ANYARGS)) + CALLING_CONVENTIONS (function)) (e->s[0].p, size); + break; + case TYPE_HAMDIST: + e->retval = (* (unsigned long (*)(ANYARGS)) + CALLING_CONVENTIONS (function)) (e->s[0].p, e->s[1].p, size); + break; + + case TYPE_SQRTREM: + e->retval = (* (long (*)(ANYARGS)) CALLING_CONVENTIONS (function)) + (e->d[0].p, e->d[1].p, e->s[0].p, size); + break; + + case TYPE_SQRT: + e->retval = (* (long (*)(ANYARGS)) CALLING_CONVENTIONS (function)) + (e->d[0].p, e->s[0].p, size); + break; + + case TYPE_ZERO: + CALLING_CONVENTIONS (function) (e->d[0].p, size); + break; + + case TYPE_GET_STR: + { + size_t sizeinbase, fill; + char *dst; + MPN_SIZEINBASE (sizeinbase, e->s[0].p, size, base); + ASSERT_ALWAYS (sizeinbase <= d[0].size); + fill = d[0].size - sizeinbase; + if (d[0].high) + { + memset (e->d[0].p, 0xBA, fill); + dst = (char *) e->d[0].p + fill; + } + else + { + dst = (char *) e->d[0].p; + memset (dst + sizeinbase, 0xBA, fill); + } + if (POW2_P (base)) + { + e->retval = CALLING_CONVENTIONS (function) (dst, base, + e->s[0].p, size); + } + else + { + refmpn_copy (e->d[1].p, e->s[0].p, size); + e->retval = CALLING_CONVENTIONS (function) (dst, base, + e->d[1].p, size); + } + refmpn_zero (e->d[1].p, size); /* clobbered or unused */ + } + break; + + case TYPE_INVERT: + { + mp_ptr scratch; + TMP_DECL; + TMP_MARK; + scratch = TMP_ALLOC_LIMBS (mpn_invert_itch (size)); + CALLING_CONVENTIONS (function) (e->d[0].p, e->s[0].p, size, scratch); + TMP_FREE; + } + break; + case TYPE_BINVERT: + { + mp_ptr scratch; + TMP_DECL; + TMP_MARK; + scratch = TMP_ALLOC_LIMBS (mpn_binvert_itch (size)); + CALLING_CONVENTIONS (function) (e->d[0].p, e->s[0].p, size, scratch); + TMP_FREE; + } + break; + +#ifdef EXTRA_CALL + EXTRA_CALL +#endif + + default: + printf ("Unknown routine type %d\n", choice->type); + abort (); + break; + } +} + + +void +pointer_setup (struct each_t *e) +{ + int i, j; + + for (i = 0; i < NUM_DESTS; i++) + { + switch (tr->dst_size[i]) { + case 0: + case SIZE_RETVAL: /* will be adjusted later */ + d[i].size = size; + break; + + case SIZE_1: + d[i].size = 1; + break; + case SIZE_2: + d[i].size = 2; + break; + case SIZE_3: + d[i].size = 3; + break; + case SIZE_4: + d[i].size = 4; + break; + case SIZE_6: + d[i].size = 6; + break; + + case SIZE_PLUS_1: + d[i].size = size+1; + break; + case SIZE_PLUS_MSIZE_SUB_1: + d[i].size = size + tr->msize - 1; + break; + + case SIZE_SUM: + if (tr->size2) + d[i].size = size + size2; + else + d[i].size = 2*size; + break; + + case SIZE_SIZE2: + d[i].size = size2; + break; + + case SIZE_DIFF: + d[i].size = size - size2; + break; + + case SIZE_DIFF_PLUS_1: + d[i].size = size - size2 + 1; + break; + + case SIZE_DIFF_PLUS_3: + d[i].size = size - size2 + 3; + break; + + case SIZE_CEIL_HALF: + d[i].size = (size+1)/2; + break; + + case SIZE_GET_STR: + { + mp_limb_t ff = GMP_NUMB_MAX; + MPN_SIZEINBASE (d[i].size, &ff - (size-1), size, base); + } + break; + + default: + printf ("Unrecognised dst_size type %d\n", tr->dst_size[i]); + abort (); + } + } + + /* establish e->d[].p destinations */ + for (i = 0; i < NUM_DESTS; i++) + { + mp_size_t offset = 0; + + /* possible room for overlapping sources */ + for (j = 0; j < numberof (overlap->s); j++) + if (overlap->s[j] == i) + offset = MAX (offset, s[j].align); + + if (d[i].high) + { + if (tr->dst_bytes[i]) + { + e->d[i].p = (mp_ptr) + ((char *) (e->d[i].region.ptr + e->d[i].region.size) + - d[i].size - d[i].align); + } + else + { + e->d[i].p = e->d[i].region.ptr + e->d[i].region.size + - d[i].size - d[i].align; + if (tr->overlap == OVERLAP_LOW_TO_HIGH) + e->d[i].p -= offset; + } + } + else + { + if (tr->dst_bytes[i]) + { + e->d[i].p = (mp_ptr) ((char *) e->d[i].region.ptr + d[i].align); + } + else + { + e->d[i].p = e->d[i].region.ptr + d[i].align; + if (tr->overlap == OVERLAP_HIGH_TO_LOW) + e->d[i].p += offset; + } + } + } + + /* establish e->s[].p sources */ + for (i = 0; i < NUM_SOURCES; i++) + { + int o = overlap->s[i]; + switch (o) { + case -1: + /* no overlap */ + e->s[i].p = s[i].p; + break; + case 0: + case 1: + /* overlap with d[o] */ + if (tr->overlap == OVERLAP_HIGH_TO_LOW) + e->s[i].p = e->d[o].p - s[i].align; + else if (tr->overlap == OVERLAP_LOW_TO_HIGH) + e->s[i].p = e->d[o].p + s[i].align; + else if (tr->size2 == SIZE_FRACTION) + e->s[i].p = e->d[o].p + size2; + else + e->s[i].p = e->d[o].p; + break; + default: + abort(); + break; + } + } +} + + +void +validate_fail (void) +{ + if (tr->reference) + { + trap_location = TRAP_REF; + call (&ref, tr->reference); + trap_location = TRAP_NOWHERE; + } + + print_all(); + abort(); +} + + +void +try_one (void) +{ + int i; + + if (option_spinner) + spinner(); + spinner_count++; + + trap_location = TRAP_SETUPS; + + if (tr->divisor == DIVISOR_NORM) + divisor |= GMP_NUMB_HIGHBIT; + if (tr->divisor == DIVISOR_ODD) + divisor |= 1; + + for (i = 0; i < NUM_SOURCES; i++) + { + if (s[i].high) + s[i].p = s[i].region.ptr + s[i].region.size - SRC_SIZE(i) - s[i].align; + else + s[i].p = s[i].region.ptr + s[i].align; + } + + pointer_setup (&ref); + pointer_setup (&fun); + + ref.retval = 0x04152637; + fun.retval = 0x8C9DAEBF; + + t_random (multiplier_N, tr->msize); + + for (i = 0; i < NUM_SOURCES; i++) + { + if (! tr->src[i]) + continue; + + mprotect_region (&s[i].region, PROT_READ|PROT_WRITE); + t_random (s[i].p, SRC_SIZE(i)); + + switch (tr->data) { + case DATA_NON_ZERO: + if (refmpn_zero_p (s[i].p, SRC_SIZE(i))) + s[i].p[0] = 1; + break; + + case DATA_MULTIPLE_DIVISOR: + /* same number of low zero bits as divisor */ + s[i].p[0] &= ~ LOW_ZEROS_MASK (divisor); + refmpn_sub_1 (s[i].p, s[i].p, size, + refmpn_mod_1 (s[i].p, size, divisor)); + break; + + case DATA_GCD: + /* s[1] no more bits than s[0] */ + if (i == 1 && size2 == size) + s[1].p[size-1] &= refmpn_msbone_mask (s[0].p[size-1]); + + /* high limb non-zero */ + s[i].p[SRC_SIZE(i)-1] += (s[i].p[SRC_SIZE(i)-1] == 0); + + /* odd */ + s[i].p[0] |= 1; + break; + + case DATA_SRC0_ODD: + if (i == 0) + s[i].p[0] |= 1; + break; + + case DATA_SRC1_ODD: + if (i == 1) + s[i].p[0] |= 1; + break; + + case DATA_SRC1_ODD_PRIME: + if (i == 1) + { + if (refmpn_zero_p (s[i].p+1, SRC_SIZE(i)-1) + && s[i].p[0] <=3) + s[i].p[0] = 3; + else + { + mpz_t p; + mpz_init (p); + for (;;) + { + _mpz_realloc (p, SRC_SIZE(i)); + MPN_COPY (PTR(p), s[i].p, SRC_SIZE(i)); + SIZ(p) = SRC_SIZE(i); + MPN_NORMALIZE (PTR(p), SIZ(p)); + mpz_nextprime (p, p); + if (mpz_size (p) <= SRC_SIZE(i)) + break; + + t_random (s[i].p, SRC_SIZE(i)); + } + MPN_COPY (s[i].p, PTR(p), SIZ(p)); + if (SIZ(p) < SRC_SIZE(i)) + MPN_ZERO (s[i].p + SIZ(p), SRC_SIZE(i) - SIZ(p)); + mpz_clear (p); + } + } + break; + + case DATA_SRC1_HIGHBIT: + if (i == 1) + { + if (tr->size2) + s[i].p[size2-1] |= GMP_NUMB_HIGHBIT; + else + s[i].p[size-1] |= GMP_NUMB_HIGHBIT; + } + break; + + case DATA_SRC0_HIGHBIT: + if (i == 0) + { + s[i].p[size-1] |= GMP_NUMB_HIGHBIT; + } + break; + + case DATA_UDIV_QRNND: + s[i].p[1] %= divisor; + break; + case DATA_DIV_QR_1: + if (i == 1) + s[i].p[0] %= divisor; + break; + } + + mprotect_region (&s[i].region, PROT_READ); + } + + for (i = 0; i < NUM_DESTS; i++) + { + if (! tr->dst[i]) + continue; + + if (tr->dst0_from_src1 && i==0) + { + mp_size_t copy = MIN (d[0].size, SRC_SIZE(1)); + mp_size_t fill = MAX (0, d[0].size - copy); + MPN_COPY (fun.d[0].p, s[1].region.ptr, copy); + MPN_COPY (ref.d[0].p, s[1].region.ptr, copy); + refmpn_fill (fun.d[0].p + copy, fill, DEADVAL); + refmpn_fill (ref.d[0].p + copy, fill, DEADVAL); + } + else if (tr->dst_bytes[i]) + { + memset (ref.d[i].p, 0xBA, d[i].size); + memset (fun.d[i].p, 0xBA, d[i].size); + } + else + { + refmpn_fill (ref.d[i].p, d[i].size, DEADVAL); + refmpn_fill (fun.d[i].p, d[i].size, DEADVAL); + } + } + + for (i = 0; i < NUM_SOURCES; i++) + { + if (! tr->src[i]) + continue; + + if (ref.s[i].p != s[i].p) + { + refmpn_copyi (ref.s[i].p, s[i].p, SRC_SIZE(i)); + refmpn_copyi (fun.s[i].p, s[i].p, SRC_SIZE(i)); + } + } + + if (option_print) + print_all(); + + if (tr->validate != NULL) + { + trap_location = TRAP_FUN; + call (&fun, choice->function); + trap_location = TRAP_NOWHERE; + + if (! CALLING_CONVENTIONS_CHECK ()) + { + print_all(); + abort(); + } + + (*tr->validate) (); + } + else + { + trap_location = TRAP_REF; + call (&ref, tr->reference); + trap_location = TRAP_FUN; + call (&fun, choice->function); + trap_location = TRAP_NOWHERE; + + if (! CALLING_CONVENTIONS_CHECK ()) + { + print_all(); + abort(); + } + + compare (); + } +} + + +#define SIZE_ITERATION \ + for (size = MAX3 (option_firstsize, \ + choice->minsize, \ + (tr->size == SIZE_ALLOW_ZERO) ? 0 : 1), \ + size += (tr->size == SIZE_ODD) && !(size & 1); \ + size <= option_lastsize; \ + size += (tr->size == SIZE_ODD) ? 2 : 1) + +#define SIZE2_FIRST \ + (tr->size2 == SIZE_2 ? 2 \ + : tr->size2 == SIZE_FRACTION ? option_firstsize2 \ + : tr->size2 == SIZE_CEIL_HALF ? ((size + 1) / 2) \ + : tr->size2 ? \ + MAX (choice->minsize, (option_firstsize2 != 0 \ + ? option_firstsize2 : 1)) \ + : 0) + +#define SIZE2_LAST \ + (tr->size2 == SIZE_2 ? 2 \ + : tr->size2 == SIZE_FRACTION ? FRACTION_COUNT-1 \ + : tr->size2 == SIZE_CEIL_HALF ? ((size + 1) / 2) \ + : tr->size2 ? size \ + : 0) + +#define SIZE2_ITERATION \ + for (size2 = SIZE2_FIRST; size2 <= SIZE2_LAST; size2++) + +#define ALIGN_COUNT(cond) ((cond) ? ALIGNMENTS : 1) +#define ALIGN_ITERATION(w,n,cond) \ + for (w[n].align = 0; w[n].align < ALIGN_COUNT(cond); w[n].align++) + +#define HIGH_LIMIT(cond) ((cond) != 0) +#define HIGH_COUNT(cond) (HIGH_LIMIT (cond) + 1) +#define HIGH_ITERATION(w,n,cond) \ + for (w[n].high = 0; w[n].high <= HIGH_LIMIT(cond); w[n].high++) + +#define SHIFT_LIMIT \ + ((unsigned long) (tr->shift ? GMP_NUMB_BITS -1 : 1)) + +#define SHIFT_ITERATION \ + for (shift = 1; shift <= SHIFT_LIMIT; shift++) + + +void +try_many (void) +{ + int i; + + { + unsigned long total = 1; + + total *= option_repetitions; + total *= option_lastsize; + if (tr->size2 == SIZE_FRACTION) total *= FRACTION_COUNT; + else if (tr->size2) total *= (option_lastsize+1)/2; + + total *= SHIFT_LIMIT; + total *= MULTIPLIER_COUNT; + total *= DIVISOR_COUNT; + total *= CARRY_COUNT; + total *= T_RAND_COUNT; + + total *= HIGH_COUNT (tr->dst[0]); + total *= HIGH_COUNT (tr->dst[1]); + total *= HIGH_COUNT (tr->src[0]); + total *= HIGH_COUNT (tr->src[1]); + + total *= ALIGN_COUNT (tr->dst[0]); + total *= ALIGN_COUNT (tr->dst[1]); + total *= ALIGN_COUNT (tr->src[0]); + total *= ALIGN_COUNT (tr->src[1]); + + total *= OVERLAP_COUNT; + + printf ("%s %lu\n", choice->name, total); + } + + spinner_count = 0; + + for (i = 0; i < option_repetitions; i++) + SIZE_ITERATION + SIZE2_ITERATION + + SHIFT_ITERATION + MULTIPLIER_ITERATION + DIVISOR_ITERATION + CARRY_ITERATION /* must be after divisor */ + T_RAND_ITERATION + + HIGH_ITERATION(d,0, tr->dst[0]) + HIGH_ITERATION(d,1, tr->dst[1]) + HIGH_ITERATION(s,0, tr->src[0]) + HIGH_ITERATION(s,1, tr->src[1]) + + ALIGN_ITERATION(d,0, tr->dst[0]) + ALIGN_ITERATION(d,1, tr->dst[1]) + ALIGN_ITERATION(s,0, tr->src[0]) + ALIGN_ITERATION(s,1, tr->src[1]) + + OVERLAP_ITERATION + try_one(); + + printf("\n"); +} + + +/* Usually print_all() doesn't show much, but it might give a hint as to + where the function was up to when it died. */ +void +trap (int sig) +{ + const char *name = "noname"; + + switch (sig) { + case SIGILL: name = "SIGILL"; break; +#ifdef SIGBUS + case SIGBUS: name = "SIGBUS"; break; +#endif + case SIGSEGV: name = "SIGSEGV"; break; + case SIGFPE: name = "SIGFPE"; break; + } + + printf ("\n\nSIGNAL TRAP: %s\n", name); + + switch (trap_location) { + case TRAP_REF: + printf (" in reference function: %s\n", tr->reference_name); + break; + case TRAP_FUN: + printf (" in test function: %s\n", choice->name); + print_all (); + break; + case TRAP_SETUPS: + printf (" in parameter setups\n"); + print_all (); + break; + default: + printf (" somewhere unknown\n"); + break; + } + exit (1); +} + + +void +try_init (void) +{ +#if HAVE_GETPAGESIZE + /* Prefer getpagesize() over sysconf(), since on SunOS 4 sysconf() doesn't + know _SC_PAGESIZE. */ + pagesize = getpagesize (); +#else +#if HAVE_SYSCONF + if ((pagesize = sysconf (_SC_PAGESIZE)) == -1) + { + /* According to the linux man page, sysconf doesn't set errno */ + fprintf (stderr, "Cannot get sysconf _SC_PAGESIZE\n"); + exit (1); + } +#else +Error, error, cannot get page size +#endif +#endif + + printf ("pagesize is 0x%lX bytes\n", pagesize); + + signal (SIGILL, trap); +#ifdef SIGBUS + signal (SIGBUS, trap); +#endif + signal (SIGSEGV, trap); + signal (SIGFPE, trap); + + { + int i; + + for (i = 0; i < NUM_SOURCES; i++) + { + malloc_region (&s[i].region, 2*option_lastsize+ALIGNMENTS-1); + printf ("s[%d] %p to %p (0x%lX bytes)\n", + i, (void *) (s[i].region.ptr), + (void *) (s[i].region.ptr + s[i].region.size), + (long) s[i].region.size * GMP_LIMB_BYTES); + } + +#define INIT_EACH(e,es) \ + for (i = 0; i < NUM_DESTS; i++) \ + { \ + malloc_region (&e.d[i].region, 2*option_lastsize+ALIGNMENTS-1); \ + printf ("%s d[%d] %p to %p (0x%lX bytes)\n", \ + es, i, (void *) (e.d[i].region.ptr), \ + (void *) (e.d[i].region.ptr + e.d[i].region.size), \ + (long) e.d[i].region.size * GMP_LIMB_BYTES); \ + } + + INIT_EACH(ref, "ref"); + INIT_EACH(fun, "fun"); + } +} + +int +strmatch_wild (const char *pattern, const char *str) +{ + size_t plen, slen; + + /* wildcard at start */ + if (pattern[0] == '*') + { + pattern++; + plen = strlen (pattern); + slen = strlen (str); + return (plen == 0 + || (slen >= plen && memcmp (pattern, str+slen-plen, plen) == 0)); + } + + /* wildcard at end */ + plen = strlen (pattern); + if (plen >= 1 && pattern[plen-1] == '*') + return (memcmp (pattern, str, plen-1) == 0); + + /* no wildcards */ + return (strcmp (pattern, str) == 0); +} + +void +try_name (const char *name) +{ + int found = 0; + int i; + + for (i = 0; i < numberof (choice_array); i++) + { + if (strmatch_wild (name, choice_array[i].name)) + { + choice = &choice_array[i]; + tr = ¶m[choice->type]; + try_many (); + found = 1; + } + } + + if (!found) + { + printf ("%s unknown\n", name); + /* exit (1); */ + } +} + + +void +usage (const char *prog) +{ + int col = 0; + int i; + + printf ("Usage: %s [options] function...\n", prog); + printf (" -1 use limb data 1,2,3,etc\n"); + printf (" -9 use limb data all 0xFF..FFs\n"); + printf (" -a zeros use limb data all zeros\n"); + printf (" -a ffs use limb data all 0xFF..FFs (same as -9)\n"); + printf (" -a 2fd use data 0x2FFF...FFFD\n"); + printf (" -p print each case tried (try this if seg faulting)\n"); + printf (" -R seed random numbers from time()\n"); + printf (" -r reps set repetitions (default %d)\n", DEFAULT_REPETITIONS); + printf (" -s size starting size to test\n"); + printf (" -S size2 starting size2 to test\n"); + printf (" -s s1-s2 range of sizes to test\n"); + printf (" -W don't show the spinner (use this in gdb)\n"); + printf (" -z disable mprotect() redzones\n"); + printf ("Default data is refmpn_random() and refmpn_random2().\n"); + printf ("\n"); + printf ("Functions that can be tested:\n"); + + for (i = 0; i < numberof (choice_array); i++) + { + if (col + 1 + strlen (choice_array[i].name) > 79) + { + printf ("\n"); + col = 0; + } + printf (" %s", choice_array[i].name); + col += 1 + strlen (choice_array[i].name); + } + printf ("\n"); + + exit(1); +} + + +int +main (int argc, char *argv[]) +{ + int i; + + /* unbuffered output */ + setbuf (stdout, NULL); + setbuf (stderr, NULL); + + /* default trace in hex, and in upper-case so can paste into bc */ + mp_trace_base = -16; + + param_init (); + + { + unsigned long seed = 123; + int opt; + + while ((opt = getopt(argc, argv, "19a:b:E:pRr:S:s:Wz")) != EOF) + { + switch (opt) { + case '1': + /* use limb data values 1, 2, 3, ... etc */ + option_data = DATA_SEQ; + break; + case '9': + /* use limb data values 0xFFF...FFF always */ + option_data = DATA_FFS; + break; + case 'a': + if (strcmp (optarg, "zeros") == 0) option_data = DATA_ZEROS; + else if (strcmp (optarg, "seq") == 0) option_data = DATA_SEQ; + else if (strcmp (optarg, "ffs") == 0) option_data = DATA_FFS; + else if (strcmp (optarg, "2fd") == 0) option_data = DATA_2FD; + else + { + fprintf (stderr, "unrecognised data option: %s\n", optarg); + exit (1); + } + break; + case 'b': + mp_trace_base = atoi (optarg); + break; + case 'E': + /* re-seed */ + sscanf (optarg, "%lu", &seed); + printf ("Re-seeding with %lu\n", seed); + break; + case 'p': + option_print = 1; + break; + case 'R': + /* randomize */ + seed = time (NULL); + printf ("Seeding with %lu, re-run using \"-E %lu\"\n", seed, seed); + break; + case 'r': + option_repetitions = atoi (optarg); + break; + case 's': + { + char *p; + option_firstsize = strtol (optarg, 0, 0); + if ((p = strchr (optarg, '-')) != NULL) + option_lastsize = strtol (p+1, 0, 0); + } + break; + case 'S': + /* -S sets the starting size for the second of a two size + routine (like mpn_mul_basecase) */ + option_firstsize2 = strtol (optarg, 0, 0); + break; + case 'W': + /* use this when running in the debugger */ + option_spinner = 0; + break; + case 'z': + /* disable redzones */ + option_redzones = 0; + break; + case '?': + usage (argv[0]); + break; + } + } + + gmp_randinit_default (__gmp_rands); + __gmp_rands_initialized = 1; + gmp_randseed_ui (__gmp_rands, seed); + } + + try_init(); + + if (argc <= optind) + usage (argv[0]); + + for (i = optind; i < argc; i++) + try_name (argv[i]); + + return 0; +} -- cgit v1.2.3