aboutsummaryrefslogtreecommitdiff
path: root/vendor/gmp-6.3.0/demos/expr
diff options
context:
space:
mode:
authorThomas Voss <mail@thomasvoss.com> 2024-06-21 23:36:36 +0200
committerThomas Voss <mail@thomasvoss.com> 2024-06-21 23:42:26 +0200
commita89a14ef5da44684a16b204e7a70460cc8c4922a (patch)
treeb23b4c6b155977909ef508fdae2f48d33d802813 /vendor/gmp-6.3.0/demos/expr
parent1db63fcedab0b288820d66e100b1877b1a5a8851 (diff)
Basic constant folding implementation
Diffstat (limited to 'vendor/gmp-6.3.0/demos/expr')
-rw-r--r--vendor/gmp-6.3.0/demos/expr/Makefile.am54
-rw-r--r--vendor/gmp-6.3.0/demos/expr/Makefile.in666
-rw-r--r--vendor/gmp-6.3.0/demos/expr/README501
-rw-r--r--vendor/gmp-6.3.0/demos/expr/expr-impl.h125
-rw-r--r--vendor/gmp-6.3.0/demos/expr/expr.c834
-rw-r--r--vendor/gmp-6.3.0/demos/expr/expr.h142
-rw-r--r--vendor/gmp-6.3.0/demos/expr/exprf.c123
-rw-r--r--vendor/gmp-6.3.0/demos/expr/exprfa.c191
-rw-r--r--vendor/gmp-6.3.0/demos/expr/exprq.c155
-rw-r--r--vendor/gmp-6.3.0/demos/expr/exprqa.c100
-rw-r--r--vendor/gmp-6.3.0/demos/expr/exprv.c57
-rw-r--r--vendor/gmp-6.3.0/demos/expr/exprz.c206
-rw-r--r--vendor/gmp-6.3.0/demos/expr/exprza.c108
-rw-r--r--vendor/gmp-6.3.0/demos/expr/run-expr.c242
-rw-r--r--vendor/gmp-6.3.0/demos/expr/t-expr.c510
15 files changed, 4014 insertions, 0 deletions
diff --git a/vendor/gmp-6.3.0/demos/expr/Makefile.am b/vendor/gmp-6.3.0/demos/expr/Makefile.am
new file mode 100644
index 0000000..252300a
--- /dev/null
+++ b/vendor/gmp-6.3.0/demos/expr/Makefile.am
@@ -0,0 +1,54 @@
+## Process this file with automake to generate Makefile.in
+
+# Copyright 2001-2004 Free Software Foundation, Inc.
+#
+# This file is part of the GNU MP Library.
+#
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of either:
+#
+# * the GNU Lesser General Public License as published by the Free
+# Software Foundation; either version 3 of the License, or (at your
+# option) any later version.
+#
+# or
+#
+# * the GNU General Public License as published by the Free Software
+# Foundation; either version 2 of the License, or (at your option) any
+# later version.
+#
+# or both in parallel, as here.
+#
+# The GNU MP Library is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received copies of the GNU General Public License and the
+# GNU Lesser General Public License along with the GNU MP Library. If not,
+# see https://www.gnu.org/licenses/.
+
+
+AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/tests
+
+# FIXME: This is a workaround for a bug in automake 1.8.4. When the only
+# library is in EXTRA_LIBRARIES, $(ARFLAGS) is used but no default setting
+# for that variable is established. We give an explicit ARFLAGS=cru the
+# same as generated for lib_LIBRARIES or noinst_LIBRARIES.
+#
+ARFLAGS = cru
+
+EXTRA_LIBRARIES = libexpr.a
+libexpr_a_SOURCES = expr.h expr-impl.h \
+ expr.c exprv.c exprz.c exprza.c exprq.c exprqa.c exprf.c exprfa.c
+
+EXTRA_PROGRAMS = run-expr t-expr
+LDADD = libexpr.a $(top_builddir)/libgmp.la
+t_expr_LDADD = $(top_builddir)/tests/libtests.la $(LDADD)
+
+CLEANFILES = $(EXTRA_PROGRAMS) $(EXTRA_LIBRARIES)
+
+allprogs: $(EXTRA_PROGRAMS)
+
+$(top_builddir)/tests/libtests.la:
+ cd $(top_builddir)/tests; $(MAKE) $(AM_MAKEFLAGS) libtests.la
diff --git a/vendor/gmp-6.3.0/demos/expr/Makefile.in b/vendor/gmp-6.3.0/demos/expr/Makefile.in
new file mode 100644
index 0000000..354e239
--- /dev/null
+++ b/vendor/gmp-6.3.0/demos/expr/Makefile.in
@@ -0,0 +1,666 @@
+# 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 2001-2004 Free Software Foundation, Inc.
+#
+# This file is part of the GNU MP Library.
+#
+# The GNU MP Library is free software; you can redistribute it and/or modify
+# it under the terms of either:
+#
+# * the GNU Lesser General Public License as published by the Free
+# Software Foundation; either version 3 of the License, or (at your
+# option) any later version.
+#
+# or
+#
+# * the GNU General Public License as published by the Free Software
+# Foundation; either version 2 of the License, or (at your option) any
+# later version.
+#
+# or both in parallel, as here.
+#
+# The GNU MP Library is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received copies of the GNU General Public License and the
+# GNU Lesser General Public License along with the GNU MP Library. If not,
+# see https://www.gnu.org/licenses/.
+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 = run-expr$(EXEEXT) t-expr$(EXEEXT)
+subdir = demos/expr
+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 =
+AM_V_AR = $(am__v_AR_@AM_V@)
+am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@)
+am__v_AR_0 = @echo " AR " $@;
+am__v_AR_1 =
+libexpr_a_AR = $(AR) $(ARFLAGS)
+libexpr_a_LIBADD =
+am_libexpr_a_OBJECTS = expr.$(OBJEXT) exprv.$(OBJEXT) exprz.$(OBJEXT) \
+ exprza.$(OBJEXT) exprq.$(OBJEXT) exprqa.$(OBJEXT) \
+ exprf.$(OBJEXT) exprfa.$(OBJEXT)
+libexpr_a_OBJECTS = $(am_libexpr_a_OBJECTS)
+run_expr_SOURCES = run-expr.c
+run_expr_OBJECTS = run-expr.$(OBJEXT)
+run_expr_LDADD = $(LDADD)
+run_expr_DEPENDENCIES = libexpr.a $(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 =
+t_expr_SOURCES = t-expr.c
+t_expr_OBJECTS = t-expr.$(OBJEXT)
+t_expr_DEPENDENCIES = $(top_builddir)/tests/libtests.la $(LDADD)
+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 = $(libexpr_a_SOURCES) run-expr.c t-expr.c
+DIST_SOURCES = $(libexpr_a_SOURCES) run-expr.c t-expr.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
+
+# FIXME: This is a workaround for a bug in automake 1.8.4. When the only
+# library is in EXTRA_LIBRARIES, $(ARFLAGS) is used but no default setting
+# for that variable is established. We give an explicit ARFLAGS=cru the
+# same as generated for lib_LIBRARIES or noinst_LIBRARIES.
+#
+ARFLAGS = cru
+EXTRA_LIBRARIES = libexpr.a
+libexpr_a_SOURCES = expr.h expr-impl.h \
+ expr.c exprv.c exprz.c exprza.c exprq.c exprqa.c exprf.c exprfa.c
+
+LDADD = libexpr.a $(top_builddir)/libgmp.la
+t_expr_LDADD = $(top_builddir)/tests/libtests.la $(LDADD)
+CLEANFILES = $(EXTRA_PROGRAMS) $(EXTRA_LIBRARIES)
+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 demos/expr/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu --ignore-deps demos/expr/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):
+
+libexpr.a: $(libexpr_a_OBJECTS) $(libexpr_a_DEPENDENCIES) $(EXTRA_libexpr_a_DEPENDENCIES)
+ $(AM_V_at)-rm -f libexpr.a
+ $(AM_V_AR)$(libexpr_a_AR) libexpr.a $(libexpr_a_OBJECTS) $(libexpr_a_LIBADD)
+ $(AM_V_at)$(RANLIB) libexpr.a
+
+run-expr$(EXEEXT): $(run_expr_OBJECTS) $(run_expr_DEPENDENCIES) $(EXTRA_run_expr_DEPENDENCIES)
+ @rm -f run-expr$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(run_expr_OBJECTS) $(run_expr_LDADD) $(LIBS)
+
+t-expr$(EXEEXT): $(t_expr_OBJECTS) $(t_expr_DEPENDENCIES) $(EXTRA_t_expr_DEPENDENCIES)
+ @rm -f t-expr$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(t_expr_OBJECTS) $(t_expr_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
+
+# 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/demos/expr/README b/vendor/gmp-6.3.0/demos/expr/README
new file mode 100644
index 0000000..a54fe42
--- /dev/null
+++ b/vendor/gmp-6.3.0/demos/expr/README
@@ -0,0 +1,501 @@
+Copyright 2001, 2004 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+or
+
+ * the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any
+ later version.
+
+or both in parallel, as here.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received copies of the GNU General Public License and the
+GNU Lesser General Public License along with the GNU MP Library. If not,
+see https://www.gnu.org/licenses/.
+
+
+
+
+
+
+ GMP EXPRESSION EVALUATION
+ -------------------------
+
+
+
+THIS CODE IS PRELIMINARY AND MAY BE SUBJECT TO INCOMPATIBLE CHANGES IN
+FUTURE VERSIONS OF GMP.
+
+
+
+The files in this directory implement a simple scheme of string based
+expression parsing and evaluation, supporting mpz, mpq and mpf.
+
+This will be slower than direct GMP library calls, but may be convenient in
+various circumstances, such as while prototyping, or for letting a user
+enter values in symbolic form. "2**5723-7" for example is a lot easier to
+enter or maintain than the equivalent written out in decimal.
+
+
+
+BUILDING
+
+Nothing in this directory is a normal part of libgmp, and nothing is built
+or installed, but various Makefile rules are available to compile
+everything.
+
+All the functions are available through a little library (there's no shared
+library since upward binary compatibility is not guaranteed).
+
+ make libexpr.a
+
+In a program, prototypes are available using
+
+ #include "expr.h"
+
+run-expr.c is a sample program doing evaluations from the command line.
+
+ make run-expr
+ ./run-expr '1+2*3'
+
+t-expr.c is self-test program, it prints nothing if successful.
+
+ make t-expr
+ ./t-expr
+
+The expr*.c sources don't depend on gmp-impl.h and can be compiled with just
+a standard installed GMP. This isn't true of t-expr though, since it uses
+some of the internal tests/libtests.la.
+
+
+
+SIMPLE USAGE
+
+int mpz_expr (mpz_t res, int base, const char *e, ...);
+int mpq_expr (mpq_t res, int base, const char *e, ...);
+int mpf_expr (mpf_t res, int base, const char *e, ...);
+
+These functions evaluate simple arithmetic expressions. For example,
+
+ mpz_expr (result, 0, "123+456", NULL);
+
+Numbers are parsed by mpz_expr and mpq_expr the same as mpz_set_str with the
+given base. mpf_expr follows mpf_set_str, but supporting an "0x" prefix for
+hex when base==0.
+
+ mpz_expr (result, 0, "0xAAAA * 0x5555", NULL);
+
+White space, as indicated by <ctype.h> isspace(), is ignored except for the
+purpose of separating tokens.
+
+Variables can be included in expressions by putting them in the stdarg list
+after the string. "a", "b", "c" etc in the expression string designate
+those values. For example,
+
+ mpq_t foo, bar;
+ ...
+ mpq_expr (q, 10, "2/3 + 1/a + b/2", foo, bar, NULL);
+
+Here "a" will be the value from foo and "b" from bar. Up to 26 variables
+can be included this way. The NULL must be present to indicate the end of
+the list.
+
+Variables can also be written "$a", "$b" etc. This is necessary when using
+bases greater than 10 since plain "a", "b" etc will otherwise be interpreted
+as numbers. For example,
+
+ mpf_t quux;
+ mpf_expr (f, 16, "F00F@-6 * $a", quux, NULL);
+
+All the standard C operators are available, with the usual precedences, plus
+"**" for exponentiation at the highest precedence (and right associative).
+
+ Operators Precedence
+ ** 220
+ ~ ! - (unary) 210
+ * / % 200
+ + - 190
+ << >> 180
+ <= < >= > 170
+ == != 160
+ & 150
+ ^ 140
+ | 130
+ && 120
+ || 110
+ ? : 100/101
+
+Currently only mpz_expr has the bitwise ~ % & ^ and | operators. The
+precedence numbers are of interest in the advanced usage described below.
+
+Various functions are available too. For example,
+
+ mpz_expr (res, 10, "gcd(123,456,789) * abs(a)", var, NULL);
+
+The following is the full set of functions,
+
+ mpz_expr
+ abs bin clrbit cmp cmpabs congruent_p divisible_p even_p fib fac
+ gcd hamdist invert jacobi kronecker lcm lucnum max min nextprime
+ odd_p perfect_power_p perfect_square_p popcount powm
+ probab_prime_p root scan0 scan1 setbit sgn sqrt
+
+ mpq_expr
+ abs, cmp, den, max, min, num, sgn
+
+ mpf_expr
+ abs, ceil, cmp, eq, floor, integer_p, max, min, reldiff, sgn,
+ sqrt, trunc
+
+All these are the same as the GMP library functions, except that min and max
+don't exist in the library. Note also that min, max, gcd and lcm take any
+number of arguments, not just two.
+
+mpf_expr does all calculations to the precision of the destination variable.
+
+
+Expression parsing can succeed or fail. The return value indicates this,
+and will be one of the following
+
+ MPEXPR_RESULT_OK
+ MPEXPR_RESULT_BAD_VARIABLE
+ MPEXPR_RESULT_BAD_TABLE
+ MPEXPR_RESULT_PARSE_ERROR
+ MPEXPR_RESULT_NOT_UI
+
+BAD_VARIABLE is when a variable is referenced that hasn't been provided.
+For example if "c" is used when only two parameters have been passed.
+BAD_TABLE is applicable to the advanced usage described below.
+
+PARSE_ERROR is a general syntax error, returned for any mal-formed input
+string.
+
+NOT_UI is returned when an attempt is made to use an operand that's bigger
+than an "unsigned long" with a function that's restricted to that range.
+For example "fib" is mpz_fib_ui and only accepts an "unsigned long".
+
+
+
+
+ADVANCED USAGE
+
+int mpz_expr_a (const struct mpexpr_operator_t *table,
+ mpz_ptr res, int base, const char *e, size_t elen,
+ mpz_srcptr var[26])
+int mpq_expr_a (const struct mpexpr_operator_t *table,
+ mpq_ptr res, int base, const char *e, size_t elen,
+ mpq_srcptr var[26])
+int mpf_expr_a (const struct mpexpr_operator_t *table,
+ mpf_ptr res, int base, unsigned long prec,
+ const char *e, size_t elen,
+ mpf_srcptr var[26])
+
+These functions are an advanced interface to expression parsing.
+
+The string is taken as pointer and length. This makes it possible to parse
+an expression in the middle of somewhere without copying and null
+terminating it.
+
+Variables are an array of 26 pointers to the appropriate operands, or NULL
+for variables that are not available. Any combination of variables can be
+given, for example just "x" and "y" (var[23] and var[24]) could be set.
+
+Operators and functions are specified with a table. This makes it possible
+to provide additional operators or functions, or to completely change the
+syntax. The standard tables used by the simple functions above are
+available as
+
+ const struct mpexpr_operator_t * const mpz_expr_standard_table;
+ const struct mpexpr_operator_t * const mpq_expr_standard_table;
+ const struct mpexpr_operator_t * const mpf_expr_standard_table;
+
+struct mpexpr_operator_t is the following
+
+ struct mpexpr_operator_t {
+ const char *name;
+ mpexpr_fun_t fun;
+ int type;
+ int precedence;
+ };
+
+ typedef void (*mpexpr_fun_t) (void);
+
+As an example, the standard mpz_expr table entry for multiplication is as
+follows. See the source code for the full set of standard entries.
+
+ { "*", (mpexpr_fun_t) mpz_mul, MPEXPR_TYPE_BINARY, 200 },
+
+"name" is the string to parse, "fun" is the function to call for it, "type"
+indicates what parameters the function takes (among other things), and
+"precedence" sets its operator precedence.
+
+A NULL for "name" indicates the end of the table, so for example an mpf
+table with nothing but addition could be
+
+ struct mpexpr_operator_t table[] = {
+ { "+", (mpexpr_fun_t) mpf_add, MPEXPR_TYPE_BINARY, 190 },
+ { NULL }
+ };
+
+A special type MPEXPR_TYPE_NEW_TABLE makes it possible to chain from one
+table to another. For example the following would add a "mod" operator to
+the standard mpz table,
+
+ struct mpexpr_operator_t table[] = {
+ { "mod", (mpexpr_fun_t) mpz_fdiv_r, MPEXPR_TYPE_BINARY, 125 },
+ { (const char *) mpz_expr_standard_table, NULL, MPEXPR_TYPE_NEW_TABLE }
+ };
+
+Notice the low precedence on "mod", so that for instance "45+26 mod 7"
+parses as "(45+26)mod7".
+
+
+Functions are designated by a precedence of 0. They always occur as
+"foo(expr)" and so have no need for a precedence level. mpq_abs in the
+standard mpq table is
+
+ { "abs", (mpexpr_fun_t) mpq_abs, MPEXPR_TYPE_UNARY },
+
+Functions expecting no arguments as in "foo()" can be given with
+MPEXPR_TYPE_0ARY, or actual constants to be parsed as just "foo" are
+MPEXPR_TYPE_CONSTANT. For example if a "void mpf_const_pi(mpf_t f)"
+function existed (which it doesn't) it could be,
+
+ { "pi", (mpexpr_fun_t) mpf_const_pi, MPEXPR_TYPE_CONSTANT },
+
+
+Parsing of operator names is done by seeking the table entry with the
+longest matching name. So for instance operators "<" and "<=" exist, and
+when presented with "x <= y" the parser matches "<=" because it's longer.
+
+Parsing of function names, on the other hand, is done by requiring a whole
+alphanumeric word to match. For example presented with "fib2zz(5)" the
+parser will attempt to find a function called "fib2zz". A function "fib"
+wouldn't be used because it doesn't match the whole word.
+
+The flag MPEXPR_TYPE_WHOLEWORD can be ORed into an operator type to override
+the default parsing style. Similarly MPEXPR_TYPE_OPERATOR into a function.
+
+
+Binary operators are left associative by default, meaning they're evaluated
+from left to right, so for example "1+2+3" is treated as "(1+2)+3".
+MPEXPR_TYPE_RIGHTASSOC can be ORed into the operator type to work from right
+to left as in "1+(2+3)". This is generally what's wanted for
+exponentiation, and for example the standard mpz table has
+
+ { "**", (mpexpr_fun_t) mpz_pow_ui,
+ MPEXPR_TYPE_BINARY_UI | MPEXPR_TYPE_RIGHTASSOC, 220 }
+
+Unary operators are postfix by default. For example a factorial to be used
+as "123!" might be
+
+ { "!", (mpexpr_fun_t) mpz_fac_ui, MPEXPR_TYPE_UNARY_UI, 215 }
+
+MPEXPR_TYPE_PREFIX can be ORed into the type to get a prefix operator. For
+instance negation (unary minus) in the standard mpf table is
+
+ { "-", (mpexpr_fun_t) mpf_neg,
+ MPEXPR_TYPE_UNARY | MPEXPR_TYPE_PREFIX, 210 },
+
+
+The same operator can exist as a prefix unary and a binary, or as a prefix
+and postfix unary, simply by putting two entries in the table. While
+parsing the context determines which style is sought. But note that the
+same operator can't be both a postfix unary and a binary, since the parser
+doesn't try to look ahead to decide which ought to be used.
+
+When there's two entries for an operator, both prefix or both postfix (or
+binary), then the first in the table will be used. This makes it possible
+to override an entry in a standard table, for example to change the function
+it calls, or perhaps its precedence level. The following would change mpz
+division from tdiv to cdiv,
+
+ struct mpexpr_operator_t table[] = {
+ { "/", (mpexpr_fun_t) mpz_cdiv_q, MPEXPR_TYPE_BINARY, 200 },
+ { "%", (mpexpr_fun_t) mpz_cdiv_r, MPEXPR_TYPE_BINARY, 200 },
+ { (char *) mpz_expr_standard_table, NULL, MPEXPR_TYPE_NEW_TABLE }
+ };
+
+
+The type field indicates what parameters the given function expects. The
+following styles of functions are supported. mpz_t is shown, but of course
+this is mpq_t for mpq_expr_a, mpf_t for mpf_expr_a, etc.
+
+ MPEXPR_TYPE_CONSTANT void func (mpz_t result);
+
+ MPEXPR_TYPE_0ARY void func (mpz_t result);
+ MPEXPR_TYPE_I_0ARY int func (void);
+
+ MPEXPR_TYPE_UNARY void func (mpz_t result, mpz_t op);
+ MPEXPR_TYPE_UNARY_UI void func (mpz_t result, unsigned long op);
+ MPEXPR_TYPE_I_UNARY int func (mpz_t op);
+ MPEXPR_TYPE_I_UNARY_UI int func (unsigned long op);
+
+ MPEXPR_TYPE_BINARY void func (mpz_t result, mpz_t op1, mpz_t op2);
+ MPEXPR_TYPE_BINARY_UI void func (mpz_t result,
+ mpz_t op1, unsigned long op2);
+ MPEXPR_TYPE_I_BINARY int func (mpz_t op1, mpz_t op2);
+ MPEXPR_TYPE_I_BINARY_UI int func (mpz_t op1, unsigned long op2);
+
+ MPEXPR_TYPE_TERNARY void func (mpz_t result,
+ mpz_t op1, mpz_t op2, mpz_t op3);
+ MPEXPR_TYPE_TERNARY_UI void func (mpz_t result, mpz_t op1, mpz_t op2,
+ unsigned long op3);
+ MPEXPR_TYPE_I_TERNARY int func (mpz_t op1, mpz_t op2, mpz_t op3);
+ MPEXPR_TYPE_I_TERNARY_UI int func (mpz_t op1, mpz_t op2,
+ unsigned long op3);
+
+Notice the pattern of "UI" for the last parameter as an unsigned long, or
+"I" for the result as an "int" return value.
+
+It's important that the declared type for an operator or function matches
+the function pointer given. Any mismatch will have unpredictable results.
+
+For binary functions, a further type attribute is MPEXPR_TYPE_PAIRWISE which
+indicates that any number of arguments should be accepted, and evaluated by
+applying the given binary function to them pairwise. This is used by gcd,
+lcm, min and max. For example the standard mpz gcd is
+
+ { "gcd", (mpexpr_fun_t) mpz_gcd,
+ MPEXPR_TYPE_BINARY | MPEXPR_TYPE_PAIRWISE },
+
+Some special types exist for comparison operators (or functions).
+MPEXPR_TYPE_CMP_LT through MPEXPR_TYPE_CMP_GE expect an MPEXPR_TYPE_I_BINARY
+function, returning positive, negative or zero like mpz_cmp and similar.
+For example the standard mpf "!=" operator is
+
+ { "!=", (mpexpr_fun_t) mpf_cmp, MPEXPR_TYPE_CMP_NE, 160 },
+
+But there's no obligation to use these types, for instance the standard mpq
+table just uses a plain MPEXPR_TYPE_I_BINARY and mpq_equal for "==".
+
+Further special types MPEXPR_TYPE_MIN and MPEXPR_TYPE_MAX exist to implement
+the min and max functions, and they take a function like mpf_cmp similarly.
+The standard mpf max function is
+
+ { "max", (mpexpr_fun_t) mpf_cmp,
+ MPEXPR_TYPE_MAX | MPEXPR_TYPE_PAIRWISE },
+
+These can be used as operators too, for instance the following would be the
+>? operator which is a feature of GNU C++,
+
+ { ">?", (mpexpr_fun_t) mpf_cmp, MPEXPR_TYPE_MAX, 175 },
+
+Other special types are used to define "(" ")" parentheses, "," function
+argument separator, "!" through "||" logical booleans, ternary "?" ":", and
+the "$" which introduces variables. See the sources for how they should be
+used.
+
+
+User definable operator tables will have various uses. For example,
+
+ - a subset of the C operators, to be rid of infrequently used things
+ - a more mathematical syntax like "." for multiply, "^" for powering,
+ and "!" for factorial
+ - a boolean evaluator with "^" for AND, "v" for OR
+ - variables introduced with "%" instead of "$"
+ - brackets as "[" and "]" instead of "(" and ")"
+
+The only fixed parts of the parsing are the treatment of numbers, whitespace
+and the two styles of operator/function name recognition.
+
+As a final example, the following would be a complete mpz table implementing
+some operators with a more mathematical syntax. Notice there's no need to
+preserve the standard precedence values, anything can be used so long as
+they're in the desired relation to each other. There's also no need to have
+entries in precedence order, but it's convenient to do so to show what comes
+where.
+
+ static const struct mpexpr_operator_t table[] = {
+ { "^", (mpexpr_fun_t) mpz_pow_ui,
+ MPEXPR_TYPE_BINARY_UI | MPEXPR_TYPE_RIGHTASSOC, 9 },
+
+ { "!", (mpexpr_fun_t) mpz_fac_ui, MPEXPR_TYPE_UNARY_UI, 8 },
+ { "-", (mpexpr_fun_t) mpz_neg,
+ MPEXPR_TYPE_UNARY | MPEXPR_TYPE_PREFIX, 7 },
+
+ { "*", (mpexpr_fun_t) mpz_mul, MPEXPR_TYPE_BINARY, 6 },
+ { "/", (mpexpr_fun_t) mpz_fdiv_q, MPEXPR_TYPE_BINARY, 6 },
+
+ { "+", (mpexpr_fun_t) mpz_add, MPEXPR_TYPE_BINARY, 5 },
+ { "-", (mpexpr_fun_t) mpz_sub, MPEXPR_TYPE_BINARY, 5 },
+
+ { "mod", (mpexpr_fun_t) mpz_mod, MPEXPR_TYPE_BINARY, 6 },
+
+ { ")", NULL, MPEXPR_TYPE_CLOSEPAREN, 4 },
+ { "(", NULL, MPEXPR_TYPE_OPENPAREN, 3 },
+ { ",", NULL, MPEXPR_TYPE_ARGSEP, 2 },
+
+ { "$", NULL, MPEXPR_TYPE_VARIABLE, 1 },
+ { NULL }
+ };
+
+
+
+
+INTERNALS
+
+Operator precedence is implemented using a control and data stack, there's
+no C recursion. When an expression like 1+2*3 is read the "+" is held on
+the control stack and 1 on the data stack until "*" has been parsed and
+applied to 2 and 3. This happens any time a higher precedence operator
+follows a lower one, or when a right-associative operator like "**" is
+repeated.
+
+Parentheses are handled by making "(" a special prefix unary with a low
+precedence so a whole following expression is read. The special operator
+")" knows to discard the pending "(". Function arguments are handled
+similarly, with the function pretending to be a low precedence prefix unary
+operator, and with "," allowed within functions. The same special ")"
+operator recognises a pending function and will invoke it appropriately.
+
+The ternary "? :" operator is also handled using precedences. ":" is one
+level higher than "?", so when a valid a?b:c is parsed the ":" finds a "?"
+on the control stack. It's a parse error for ":" to find anything else.
+
+
+
+FUTURE
+
+The ternary "?:" operator evaluates the "false" side of its pair, which is
+wasteful, though it ought to be harmless. It'd be better if it could
+evaluate only the "true" side. Similarly for the logical booleans "&&" and
+"||" if they know their result already.
+
+Functions like MPEXPR_TYPE_BINARY could return a status indicating operand
+out of range or whatever, to get an error back through mpz_expr etc. That
+would want to be just an option, since plain mpz_add etc have no such
+return.
+
+Could have assignments like "a = b*c" modifying the input variables.
+Assignment could be an operator attribute, making it expect an lvalue.
+There would want to be a standard table without assignments available
+though, so user input could be safely parsed.
+
+The closing parenthesis table entry could specify the type of open paren it
+expects, so that "(" and ")" could match and "[" and "]" match but not a
+mixture of the two. Currently "[" and "]" can be added, but there's no
+error on writing a mixed expression like "2*(3+4]". Maybe also there could
+be a way to say that functions can only be written with one or the other
+style of parens.
+
+
+
+----------------
+Local variables:
+mode: text
+fill-column: 76
+End:
diff --git a/vendor/gmp-6.3.0/demos/expr/expr-impl.h b/vendor/gmp-6.3.0/demos/expr/expr-impl.h
new file mode 100644
index 0000000..9b6458f
--- /dev/null
+++ b/vendor/gmp-6.3.0/demos/expr/expr-impl.h
@@ -0,0 +1,125 @@
+/* Implementation specifics for expression evaluation.
+
+Copyright 2000-2002, 2004 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+or
+
+ * the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any
+ later version.
+
+or both in parallel, as here.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received copies of the GNU General Public License and the
+GNU Lesser General Public License along with the GNU MP Library. If not,
+see https://www.gnu.org/licenses/. */
+
+#include <stdarg.h>
+
+#include "expr.h"
+
+
+#define isasciidigit(c) (isascii (c) && isdigit (c))
+#define isasciicsym(c) (isascii (c) && (isalnum(c) || (c) == '_'))
+
+#define isasciidigit_in_base(c,base) \
+ (isascii (c) \
+ && ((isdigit (c) && (c)-'0' < (base)) \
+ || (isupper (c) && (c)-'A'+10 < (base)) \
+ || (islower (c) && (c)-'a'+10 < (base))))
+
+
+union mpX_t {
+ mpz_t z;
+ mpq_t q;
+ mpf_t f;
+};
+
+typedef union mpX_t *mpX_ptr;
+typedef const union mpX_t *mpX_srcptr;
+
+typedef void (*mpexpr_fun_one_t) (mpX_ptr);
+typedef unsigned long (*mpexpr_fun_ui_one_t) (mpX_ptr);
+
+typedef void (*mpexpr_fun_0ary_t) (mpX_ptr);
+typedef int (*mpexpr_fun_i_0ary_t) (void);
+
+typedef void (*mpexpr_fun_unary_t) (mpX_ptr, mpX_srcptr);
+typedef void (*mpexpr_fun_unary_ui_t) (mpX_ptr, unsigned long);
+typedef int (*mpexpr_fun_i_unary_t) (mpX_srcptr);
+typedef int (*mpexpr_fun_i_unary_ui_t) (unsigned long);
+
+typedef void (*mpexpr_fun_binary_t) (mpX_ptr, mpX_srcptr, mpX_srcptr);
+typedef void (*mpexpr_fun_binary_ui_t) (mpX_ptr, mpX_srcptr, unsigned long);
+typedef int (*mpexpr_fun_i_binary_t) (mpX_srcptr, mpX_srcptr);
+typedef int (*mpexpr_fun_i_binary_ui_t) (mpX_srcptr, unsigned long);
+
+typedef void (*mpexpr_fun_ternary_t) (mpX_ptr, mpX_srcptr, mpX_srcptr, mpX_srcptr);
+typedef void (*mpexpr_fun_ternary_ui_t) (mpX_ptr, mpX_srcptr, mpX_srcptr, unsigned long);
+typedef int (*mpexpr_fun_i_ternary_t) (mpX_srcptr, mpX_srcptr, mpX_srcptr);
+typedef int (*mpexpr_fun_i_ternary_ui_t) (mpX_srcptr, mpX_srcptr, unsigned long);
+
+typedef size_t (*mpexpr_fun_number_t) (mpX_ptr, const char *str, size_t len, int base);
+typedef void (*mpexpr_fun_swap_t) (mpX_ptr, mpX_ptr);
+typedef unsigned long (*mpexpr_fun_get_ui_t) (mpX_srcptr);
+typedef void (*mpexpr_fun_set_si_t) (mpX_srcptr, long);
+
+struct mpexpr_control_t {
+ const struct mpexpr_operator_t *op;
+ int argcount;
+};
+
+#define MPEXPR_VARIABLES 26
+
+struct mpexpr_parse_t {
+ const struct mpexpr_operator_t *table;
+
+ mpX_ptr res;
+ int base;
+ unsigned long prec;
+ const char *e;
+ size_t elen;
+ mpX_srcptr *var;
+ int error_code;
+
+ int token;
+ const struct mpexpr_operator_t *token_op;
+
+ union mpX_t *data_stack;
+ int data_top;
+ int data_alloc;
+ int data_inited;
+
+ struct mpexpr_control_t *control_stack;
+ int control_top;
+ int control_alloc;
+
+ mpexpr_fun_0ary_t mpX_clear;
+ mpexpr_fun_i_unary_t mpX_ulong_p;
+ mpexpr_fun_get_ui_t mpX_get_ui;
+ mpexpr_fun_unary_ui_t mpX_init;
+ mpexpr_fun_number_t mpX_number;
+ mpexpr_fun_unary_t mpX_set;
+ mpexpr_fun_unary_t mpX_set_or_swap;
+ mpexpr_fun_set_si_t mpX_set_si;
+ mpexpr_fun_swap_t mpX_swap;
+};
+
+
+int mpexpr_evaluate (struct mpexpr_parse_t *p);
+int mpexpr_va_to_var (void *var[], va_list ap);
+size_t mpexpr_mpz_number (mpz_ptr res, const char *e, size_t elen, int base);
diff --git a/vendor/gmp-6.3.0/demos/expr/expr.c b/vendor/gmp-6.3.0/demos/expr/expr.c
new file mode 100644
index 0000000..42dd796
--- /dev/null
+++ b/vendor/gmp-6.3.0/demos/expr/expr.c
@@ -0,0 +1,834 @@
+/* mpexpr_evaluate -- shared code for simple expression evaluation
+
+Copyright 2000-2002, 2004 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+or
+
+ * the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any
+ later version.
+
+or both in parallel, as here.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received copies of the GNU General Public License and the
+GNU Lesser General Public License along with the GNU MP Library. If not,
+see https://www.gnu.org/licenses/. */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "gmp.h"
+#include "expr-impl.h"
+
+
+/* Change this to "#define TRACE(x) x" to get some traces. The trace
+ printfs junk up the code a bit, but it's very hard to tell what's going
+ on without them. Set MPX_TRACE to a suitable output function for the
+ mpz/mpq/mpf being run (if you have the wrong trace function it'll
+ probably segv). */
+
+#define TRACE(x)
+#define MPX_TRACE mpz_trace
+
+
+/* A few helper macros copied from gmp-impl.h */
+#define ALLOCATE_FUNC_TYPE(n,type) \
+ ((type *) (*allocate_func) ((n) * sizeof (type)))
+#define ALLOCATE_FUNC_LIMBS(n) ALLOCATE_FUNC_TYPE (n, mp_limb_t)
+#define REALLOCATE_FUNC_TYPE(p, old_size, new_size, type) \
+ ((type *) (*reallocate_func) \
+ (p, (old_size) * sizeof (type), (new_size) * sizeof (type)))
+#define REALLOCATE_FUNC_LIMBS(p, old_size, new_size) \
+ REALLOCATE_FUNC_TYPE(p, old_size, new_size, mp_limb_t)
+#define FREE_FUNC_TYPE(p,n,type) (*free_func) (p, (n) * sizeof (type))
+#define FREE_FUNC_LIMBS(p,n) FREE_FUNC_TYPE (p, n, mp_limb_t)
+#define ASSERT(x)
+
+
+
+/* All the error strings are just for diagnostic traces. Only the error
+ code is actually returned. */
+#define ERROR(str,code) \
+ { \
+ TRACE (printf ("%s\n", str)); \
+ p->error_code = (code); \
+ goto done; \
+ }
+
+
+#define REALLOC(ptr, alloc, incr, type) \
+ do { \
+ int new_alloc = (alloc) + (incr); \
+ ptr = REALLOCATE_FUNC_TYPE (ptr, alloc, new_alloc, type); \
+ (alloc) = new_alloc; \
+ } while (0)
+
+
+/* data stack top element */
+#define SP (p->data_stack + p->data_top)
+
+/* Make sure there's room for another data element above current top.
+ reallocate_func is fetched for when this macro is used in lookahead(). */
+#define DATA_SPACE() \
+ do { \
+ if (p->data_top + 1 >= p->data_alloc) \
+ { \
+ void *(*reallocate_func) (void *, size_t, size_t); \
+ mp_get_memory_functions (NULL, &reallocate_func, NULL); \
+ TRACE (printf ("grow stack from %d\n", p->data_alloc)); \
+ REALLOC (p->data_stack, p->data_alloc, 20, union mpX_t); \
+ } \
+ ASSERT (p->data_top + 1 <= p->data_inited); \
+ if (p->data_top + 1 == p->data_inited) \
+ { \
+ TRACE (printf ("initialize %d\n", p->data_top + 1)); \
+ (*p->mpX_init) (&p->data_stack[p->data_top + 1], p->prec); \
+ p->data_inited++; \
+ } \
+ } while (0)
+
+#define DATA_PUSH() \
+ do { \
+ p->data_top++; \
+ ASSERT (p->data_top < p->data_alloc); \
+ ASSERT (p->data_top < p->data_inited); \
+ } while (0)
+
+/* the last stack entry is never popped, so top>=0 will be true */
+#define DATA_POP(n) \
+ do { \
+ p->data_top -= (n); \
+ ASSERT (p->data_top >= 0); \
+ } while (0)
+
+
+/* lookahead() parses the next token. Return 1 if successful, with some
+ extra data. Return 0 if fail, with reason in p->error_code.
+
+ "prefix" is MPEXPR_TYPE_PREFIX if an operator with that attribute is
+ preferred, or 0 if an operator without is preferred. */
+
+#define TOKEN_EOF -1 /* no extra data */
+#define TOKEN_VALUE -2 /* pushed onto data stack */
+#define TOKEN_OPERATOR -3 /* stored in p->token_op */
+#define TOKEN_FUNCTION -4 /* stored in p->token_op */
+
+#define TOKEN_NAME(n) \
+ ((n) == TOKEN_EOF ? "TOKEN_EOF" \
+ : (n) == TOKEN_VALUE ? "TOKEN_VALUE" \
+ : (n) == TOKEN_OPERATOR ? "TOKEN_OPERATOR" \
+ : (n) == TOKEN_VALUE ? "TOKEN_FUNCTION" \
+ : "UNKNOWN TOKEN")
+
+/* Functions default to being parsed as whole words, operators to match just
+ at the start of the string. The type flags override this. */
+#define WHOLEWORD(op) \
+ (op->precedence == 0 \
+ ? (! (op->type & MPEXPR_TYPE_OPERATOR)) \
+ : (op->type & MPEXPR_TYPE_WHOLEWORD))
+
+#define isasciispace(c) (isascii (c) && isspace (c))
+
+static int
+lookahead (struct mpexpr_parse_t *p, int prefix)
+{
+ const struct mpexpr_operator_t *op, *op_found;
+ size_t oplen, oplen_found, wlen;
+ int i;
+
+ /* skip white space */
+ while (p->elen > 0 && isasciispace (*p->e))
+ p->e++, p->elen--;
+
+ if (p->elen == 0)
+ {
+ TRACE (printf ("lookahead EOF\n"));
+ p->token = TOKEN_EOF;
+ return 1;
+ }
+
+ DATA_SPACE ();
+
+ /* Get extent of whole word. */
+ for (wlen = 0; wlen < p->elen; wlen++)
+ if (! isasciicsym (p->e[wlen]))
+ break;
+
+ TRACE (printf ("lookahead at: \"%.*s\" length %u, word %u\n",
+ (int) p->elen, p->e, p->elen, wlen));
+
+ op_found = NULL;
+ oplen_found = 0;
+ for (op = p->table; op->name != NULL; op++)
+ {
+ if (op->type == MPEXPR_TYPE_NEW_TABLE)
+ {
+ printf ("new\n");
+ op = (struct mpexpr_operator_t *) op->name - 1;
+ continue;
+ }
+
+ oplen = strlen (op->name);
+ if (! ((WHOLEWORD (op) ? wlen == oplen : p->elen >= oplen)
+ && memcmp (p->e, op->name, oplen) == 0))
+ continue;
+
+ /* Shorter matches don't replace longer previous ones. */
+ if (op_found && oplen < oplen_found)
+ continue;
+
+ /* On a match of equal length to a previous one, the old match isn't
+ replaced if it has the preferred prefix, and if it doesn't then
+ it's not replaced if the new one also doesn't. */
+ if (op_found && oplen == oplen_found
+ && ((op_found->type & MPEXPR_TYPE_PREFIX) == prefix
+ || (op->type & MPEXPR_TYPE_PREFIX) != prefix))
+ continue;
+
+ /* This is now either the first match seen, or a longer than previous
+ match, or an equal to previous one but with a preferred prefix. */
+ op_found = op;
+ oplen_found = oplen;
+ }
+
+ if (op_found)
+ {
+ p->e += oplen_found, p->elen -= oplen_found;
+
+ if (op_found->type == MPEXPR_TYPE_VARIABLE)
+ {
+ if (p->elen == 0)
+ ERROR ("end of string expecting a variable",
+ MPEXPR_RESULT_PARSE_ERROR);
+ i = p->e[0] - 'a';
+ if (i < 0 || i >= MPEXPR_VARIABLES)
+ ERROR ("bad variable name", MPEXPR_RESULT_BAD_VARIABLE);
+ goto variable;
+ }
+
+ if (op_found->precedence == 0)
+ {
+ TRACE (printf ("lookahead function: %s\n", op_found->name));
+ p->token = TOKEN_FUNCTION;
+ p->token_op = op_found;
+ return 1;
+ }
+ else
+ {
+ TRACE (printf ("lookahead operator: %s\n", op_found->name));
+ p->token = TOKEN_OPERATOR;
+ p->token_op = op_found;
+ return 1;
+ }
+ }
+
+ oplen = (*p->mpX_number) (SP+1, p->e, p->elen, p->base);
+ if (oplen != 0)
+ {
+ p->e += oplen, p->elen -= oplen;
+ p->token = TOKEN_VALUE;
+ DATA_PUSH ();
+ TRACE (MPX_TRACE ("lookahead number", SP));
+ return 1;
+ }
+
+ /* Maybe an unprefixed one character variable */
+ i = p->e[0] - 'a';
+ if (wlen == 1 && i >= 0 && i < MPEXPR_VARIABLES)
+ {
+ variable:
+ p->e++, p->elen--;
+ if (p->var[i] == NULL)
+ ERROR ("NULL variable", MPEXPR_RESULT_BAD_VARIABLE);
+ TRACE (printf ("lookahead variable: var[%d] = ", i);
+ MPX_TRACE ("", p->var[i]));
+ p->token = TOKEN_VALUE;
+ DATA_PUSH ();
+ (*p->mpX_set) (SP, p->var[i]);
+ return 1;
+ }
+
+ ERROR ("no token matched", MPEXPR_RESULT_PARSE_ERROR);
+
+ done:
+ return 0;
+}
+
+
+/* control stack current top element */
+#define CP (p->control_stack + p->control_top)
+
+/* make sure there's room for another control element above current top */
+#define CONTROL_SPACE() \
+ do { \
+ if (p->control_top + 1 >= p->control_alloc) \
+ { \
+ TRACE (printf ("grow control stack from %d\n", p->control_alloc)); \
+ REALLOC (p->control_stack, p->control_alloc, 20, \
+ struct mpexpr_control_t); \
+ } \
+ } while (0)
+
+/* Push an operator on the control stack, claiming currently to have the
+ given number of args ready. Local variable "op" is used in case opptr is
+ a reference through CP. */
+#define CONTROL_PUSH(opptr,args) \
+ do { \
+ const struct mpexpr_operator_t *op = opptr; \
+ struct mpexpr_control_t *cp; \
+ CONTROL_SPACE (); \
+ p->control_top++; \
+ ASSERT (p->control_top < p->control_alloc); \
+ cp = CP; \
+ cp->op = op; \
+ cp->argcount = (args); \
+ TRACE_CONTROL("control stack push:"); \
+ } while (0)
+
+/* The special operator_done is never popped, so top>=0 will hold. */
+#define CONTROL_POP() \
+ do { \
+ p->control_top--; \
+ ASSERT (p->control_top >= 0); \
+ TRACE_CONTROL ("control stack pop:"); \
+ } while (0)
+
+#define TRACE_CONTROL(str) \
+ TRACE ({ \
+ int i; \
+ printf ("%s depth %d:", str, p->control_top); \
+ for (i = 0; i <= p->control_top; i++) \
+ printf (" \"%s\"(%d)", \
+ p->control_stack[i].op->name, \
+ p->control_stack[i].argcount); \
+ printf ("\n"); \
+ });
+
+
+#define LOOKAHEAD(prefix) \
+ do { \
+ if (! lookahead (p, prefix)) \
+ goto done; \
+ } while (0)
+
+#define CHECK_UI(n) \
+ do { \
+ if (! (*p->mpX_ulong_p) (n)) \
+ ERROR ("operand doesn't fit ulong", MPEXPR_RESULT_NOT_UI); \
+ } while (0)
+
+#define CHECK_ARGCOUNT(str,n) \
+ do { \
+ if (CP->argcount != (n)) \
+ { \
+ TRACE (printf ("wrong number of arguments for %s, got %d want %d", \
+ str, CP->argcount, n)); \
+ ERROR ("", MPEXPR_RESULT_PARSE_ERROR); \
+ } \
+ } while (0)
+
+
+/* There's two basic states here. In both p->token is the next token.
+
+ "another_expr" is when a whole expression should be parsed. This means a
+ literal or variable value possibly followed by an operator, or a function
+ or prefix operator followed by a further whole expression.
+
+ "another_operator" is when an expression has been parsed and its value is
+ on the top of the data stack (SP) and an optional further postfix or
+ infix operator should be parsed.
+
+ In "another_operator" precedences determine whether to push the operator
+ onto the control stack, or instead go to "apply_control" to reduce the
+ operator currently on top of the control stack.
+
+ When an operator has both a prefix and postfix/infix form, a LOOKAHEAD()
+ for "another_expr" will seek the prefix form, a LOOKAHEAD() for
+ "another_operator" will seek the postfix/infix form. The grammar is
+ simple enough that the next state is known before reading the next token.
+
+ Argument count checking guards against functions consuming the wrong
+ number of operands from the data stack. The same checks are applied to
+ operators, but will always pass since a UNARY or BINARY will only ever
+ parse with the correct operands. */
+
+int
+mpexpr_evaluate (struct mpexpr_parse_t *p)
+{
+ void *(*allocate_func) (size_t);
+ void *(*reallocate_func) (void *, size_t, size_t);
+ void (*free_func) (void *, size_t);
+
+ mp_get_memory_functions (&allocate_func, &reallocate_func, &free_func);
+
+ TRACE (printf ("mpexpr_evaluate() base %d \"%.*s\"\n",
+ p->base, (int) p->elen, p->e));
+
+ /* "done" is a special sentinel at the bottom of the control stack,
+ precedence -1 is lower than any normal operator. */
+ {
+ static const struct mpexpr_operator_t operator_done
+ = { "DONE", NULL, MPEXPR_TYPE_DONE, -1 };
+
+ p->control_alloc = 20;
+ p->control_stack = ALLOCATE_FUNC_TYPE (p->control_alloc,
+ struct mpexpr_control_t);
+ p->control_top = 0;
+ CP->op = &operator_done;
+ CP->argcount = 1;
+ }
+
+ p->data_inited = 0;
+ p->data_alloc = 20;
+ p->data_stack = ALLOCATE_FUNC_TYPE (p->data_alloc, union mpX_t);
+ p->data_top = -1;
+
+ p->error_code = MPEXPR_RESULT_OK;
+
+
+ another_expr_lookahead:
+ LOOKAHEAD (MPEXPR_TYPE_PREFIX);
+ TRACE (printf ("another expr\n"));
+
+ /*another_expr:*/
+ switch (p->token) {
+ case TOKEN_VALUE:
+ goto another_operator_lookahead;
+
+ case TOKEN_OPERATOR:
+ TRACE (printf ("operator %s\n", p->token_op->name));
+ if (! (p->token_op->type & MPEXPR_TYPE_PREFIX))
+ ERROR ("expected a prefix operator", MPEXPR_RESULT_PARSE_ERROR);
+
+ CONTROL_PUSH (p->token_op, 1);
+ goto another_expr_lookahead;
+
+ case TOKEN_FUNCTION:
+ CONTROL_PUSH (p->token_op, 1);
+
+ if (p->token_op->type & MPEXPR_TYPE_CONSTANT)
+ goto apply_control_lookahead;
+
+ LOOKAHEAD (MPEXPR_TYPE_PREFIX);
+ if (! (p->token == TOKEN_OPERATOR
+ && p->token_op->type == MPEXPR_TYPE_OPENPAREN))
+ ERROR ("expected open paren for function", MPEXPR_RESULT_PARSE_ERROR);
+
+ TRACE (printf ("open paren for function \"%s\"\n", CP->op->name));
+
+ if ((CP->op->type & MPEXPR_TYPE_MASK_ARGCOUNT) == MPEXPR_TYPE_NARY(0))
+ {
+ LOOKAHEAD (0);
+ if (! (p->token == TOKEN_OPERATOR
+ && p->token_op->type == MPEXPR_TYPE_CLOSEPAREN))
+ ERROR ("expected close paren for 0ary function",
+ MPEXPR_RESULT_PARSE_ERROR);
+ goto apply_control_lookahead;
+ }
+
+ goto another_expr_lookahead;
+ }
+ ERROR ("unrecognised start of expression", MPEXPR_RESULT_PARSE_ERROR);
+
+
+ another_operator_lookahead:
+ LOOKAHEAD (0);
+ another_operator:
+ TRACE (printf ("another operator maybe: %s\n", TOKEN_NAME(p->token)));
+
+ switch (p->token) {
+ case TOKEN_EOF:
+ goto apply_control;
+
+ case TOKEN_OPERATOR:
+ /* The next operator is compared to the one on top of the control stack.
+ If the next is lower precedence, or the same precedence and not
+ right-associative, then reduce using the control stack and look at
+ the next operator again later. */
+
+#define PRECEDENCE_TEST_REDUCE(tprec,cprec,ttype,ctype) \
+ ((tprec) < (cprec) \
+ || ((tprec) == (cprec) && ! ((ttype) & MPEXPR_TYPE_RIGHTASSOC)))
+
+ if (PRECEDENCE_TEST_REDUCE (p->token_op->precedence, CP->op->precedence,
+ p->token_op->type, CP->op->type))
+ {
+ TRACE (printf ("defer operator: %s (prec %d vs %d, type 0x%X)\n",
+ p->token_op->name,
+ p->token_op->precedence, CP->op->precedence,
+ p->token_op->type));
+ goto apply_control;
+ }
+
+ /* An argsep is a binary operator, but is never pushed on the control
+ stack, it just accumulates an extra argument for a function. */
+ if (p->token_op->type == MPEXPR_TYPE_ARGSEP)
+ {
+ if (CP->op->precedence != 0)
+ ERROR ("ARGSEP not in a function call", MPEXPR_RESULT_PARSE_ERROR);
+
+ TRACE (printf ("argsep for function \"%s\"(%d)\n",
+ CP->op->name, CP->argcount));
+
+#define IS_PAIRWISE(type) \
+ (((type) & (MPEXPR_TYPE_MASK_ARGCOUNT | MPEXPR_TYPE_PAIRWISE)) \
+ == (MPEXPR_TYPE_BINARY | MPEXPR_TYPE_PAIRWISE))
+
+ if (IS_PAIRWISE (CP->op->type) && CP->argcount >= 2)
+ {
+ TRACE (printf (" will reduce pairwise now\n"));
+ CP->argcount--;
+ CONTROL_PUSH (CP->op, 2);
+ goto apply_control;
+ }
+
+ CP->argcount++;
+ goto another_expr_lookahead;
+ }
+
+ switch (p->token_op->type & MPEXPR_TYPE_MASK_ARGCOUNT) {
+ case MPEXPR_TYPE_NARY(1):
+ /* Postfix unary operators can always be applied immediately. The
+ easiest way to do this is just push it on the control stack and go
+ to the normal control stack reduction code. */
+
+ TRACE (printf ("postfix unary operator: %s\n", p->token_op->name));
+ if (p->token_op->type & MPEXPR_TYPE_PREFIX)
+ ERROR ("prefix unary operator used postfix",
+ MPEXPR_RESULT_PARSE_ERROR);
+ CONTROL_PUSH (p->token_op, 1);
+ goto apply_control_lookahead;
+
+ case MPEXPR_TYPE_NARY(2):
+ CONTROL_PUSH (p->token_op, 2);
+ goto another_expr_lookahead;
+
+ case MPEXPR_TYPE_NARY(3):
+ CONTROL_PUSH (p->token_op, 1);
+ goto another_expr_lookahead;
+ }
+
+ TRACE (printf ("unrecognised operator \"%s\" type: 0x%X",
+ CP->op->name, CP->op->type));
+ ERROR ("", MPEXPR_RESULT_PARSE_ERROR);
+ break;
+
+ default:
+ TRACE (printf ("expecting an operator, got token %d", p->token));
+ ERROR ("", MPEXPR_RESULT_PARSE_ERROR);
+ }
+
+
+ apply_control_lookahead:
+ LOOKAHEAD (0);
+ apply_control:
+ /* Apply the top element CP of the control stack. Data values are SP,
+ SP-1, etc. Result is left as stack top SP after popping consumed
+ values.
+
+ The use of sp as a duplicate of SP will help compilers that can't
+ otherwise recognise the various uses of SP as common subexpressions. */
+
+ TRACE (printf ("apply control: nested %d, \"%s\" 0x%X, %d args\n",
+ p->control_top, CP->op->name, CP->op->type, CP->argcount));
+
+ TRACE (printf ("apply 0x%X-ary\n",
+ CP->op->type & MPEXPR_TYPE_MASK_ARGCOUNT));
+ switch (CP->op->type & MPEXPR_TYPE_MASK_ARGCOUNT) {
+ case MPEXPR_TYPE_NARY(0):
+ {
+ mpX_ptr sp;
+ DATA_SPACE ();
+ DATA_PUSH ();
+ sp = SP;
+ switch (CP->op->type & MPEXPR_TYPE_MASK_ARGSTYLE) {
+ case 0:
+ (* (mpexpr_fun_0ary_t) CP->op->fun) (sp);
+ break;
+ case MPEXPR_TYPE_RESULT_INT:
+ (*p->mpX_set_si) (sp, (long) (* (mpexpr_fun_i_0ary_t) CP->op->fun) ());
+ break;
+ default:
+ ERROR ("unrecognised 0ary argument calling style",
+ MPEXPR_RESULT_BAD_TABLE);
+ }
+ }
+ break;
+
+ case MPEXPR_TYPE_NARY(1):
+ {
+ mpX_ptr sp = SP;
+ CHECK_ARGCOUNT ("unary", 1);
+ TRACE (MPX_TRACE ("before", sp));
+
+ switch (CP->op->type & MPEXPR_TYPE_MASK_SPECIAL) {
+ case 0:
+ /* not a special */
+ break;
+
+ case MPEXPR_TYPE_DONE & MPEXPR_TYPE_MASK_SPECIAL:
+ TRACE (printf ("special done\n"));
+ goto done;
+
+ case MPEXPR_TYPE_LOGICAL_NOT & MPEXPR_TYPE_MASK_SPECIAL:
+ TRACE (printf ("special logical not\n"));
+ (*p->mpX_set_si)
+ (sp, (long) ((* (mpexpr_fun_i_unary_t) CP->op->fun) (sp) == 0));
+ goto apply_control_done;
+
+ case MPEXPR_TYPE_CLOSEPAREN & MPEXPR_TYPE_MASK_SPECIAL:
+ CONTROL_POP ();
+ if (CP->op->type == MPEXPR_TYPE_OPENPAREN)
+ {
+ TRACE (printf ("close paren matching open paren\n"));
+ CONTROL_POP ();
+ goto another_operator;
+ }
+ if (CP->op->precedence == 0)
+ {
+ TRACE (printf ("close paren for function\n"));
+ goto apply_control;
+ }
+ ERROR ("unexpected close paren", MPEXPR_RESULT_PARSE_ERROR);
+
+ default:
+ TRACE (printf ("unrecognised special unary operator 0x%X",
+ CP->op->type & MPEXPR_TYPE_MASK_SPECIAL));
+ ERROR ("", MPEXPR_RESULT_BAD_TABLE);
+ }
+
+ switch (CP->op->type & MPEXPR_TYPE_MASK_ARGSTYLE) {
+ case 0:
+ (* (mpexpr_fun_unary_t) CP->op->fun) (sp, sp);
+ break;
+ case MPEXPR_TYPE_LAST_UI:
+ CHECK_UI (sp);
+ (* (mpexpr_fun_unary_ui_t) CP->op->fun)
+ (sp, (*p->mpX_get_ui) (sp));
+ break;
+ case MPEXPR_TYPE_RESULT_INT:
+ (*p->mpX_set_si)
+ (sp, (long) (* (mpexpr_fun_i_unary_t) CP->op->fun) (sp));
+ break;
+ case MPEXPR_TYPE_RESULT_INT | MPEXPR_TYPE_LAST_UI:
+ CHECK_UI (sp);
+ (*p->mpX_set_si)
+ (sp,
+ (long) (* (mpexpr_fun_i_unary_ui_t) CP->op->fun)
+ ((*p->mpX_get_ui) (sp)));
+ break;
+ default:
+ ERROR ("unrecognised unary argument calling style",
+ MPEXPR_RESULT_BAD_TABLE);
+ }
+ }
+ break;
+
+ case MPEXPR_TYPE_NARY(2):
+ {
+ mpX_ptr sp;
+
+ /* pairwise functions are allowed to have just one argument */
+ if ((CP->op->type & MPEXPR_TYPE_PAIRWISE)
+ && CP->op->precedence == 0
+ && CP->argcount == 1)
+ goto apply_control_done;
+
+ CHECK_ARGCOUNT ("binary", 2);
+ DATA_POP (1);
+ sp = SP;
+ TRACE (MPX_TRACE ("lhs", sp);
+ MPX_TRACE ("rhs", sp+1));
+
+ if (CP->op->type & MPEXPR_TYPE_MASK_CMP)
+ {
+ int type = CP->op->type;
+ int cmp = (* (mpexpr_fun_i_binary_t) CP->op->fun)
+ (sp, sp+1);
+ (*p->mpX_set_si)
+ (sp,
+ (long)
+ (( (cmp < 0) & ((type & MPEXPR_TYPE_MASK_CMP_LT) != 0))
+ | ((cmp == 0) & ((type & MPEXPR_TYPE_MASK_CMP_EQ) != 0))
+ | ((cmp > 0) & ((type & MPEXPR_TYPE_MASK_CMP_GT) != 0))));
+ goto apply_control_done;
+ }
+
+ switch (CP->op->type & MPEXPR_TYPE_MASK_SPECIAL) {
+ case 0:
+ /* not a special */
+ break;
+
+ case MPEXPR_TYPE_QUESTION & MPEXPR_TYPE_MASK_SPECIAL:
+ ERROR ("'?' without ':'", MPEXPR_RESULT_PARSE_ERROR);
+
+ case MPEXPR_TYPE_COLON & MPEXPR_TYPE_MASK_SPECIAL:
+ TRACE (printf ("special colon\n"));
+ CONTROL_POP ();
+ if (CP->op->type != MPEXPR_TYPE_QUESTION)
+ ERROR ("':' without '?'", MPEXPR_RESULT_PARSE_ERROR);
+
+ CP->argcount--;
+ DATA_POP (1);
+ sp--;
+ TRACE (MPX_TRACE ("query", sp);
+ MPX_TRACE ("true", sp+1);
+ MPX_TRACE ("false", sp+2));
+ (*p->mpX_set)
+ (sp, (* (mpexpr_fun_i_unary_t) CP->op->fun) (sp)
+ ? sp+1 : sp+2);
+ goto apply_control_done;
+
+ case MPEXPR_TYPE_LOGICAL_AND & MPEXPR_TYPE_MASK_SPECIAL:
+ TRACE (printf ("special logical and\n"));
+ (*p->mpX_set_si)
+ (sp,
+ (long)
+ ((* (mpexpr_fun_i_unary_t) CP->op->fun) (sp)
+ && (* (mpexpr_fun_i_unary_t) CP->op->fun) (sp+1)));
+ goto apply_control_done;
+
+ case MPEXPR_TYPE_LOGICAL_OR & MPEXPR_TYPE_MASK_SPECIAL:
+ TRACE (printf ("special logical and\n"));
+ (*p->mpX_set_si)
+ (sp,
+ (long)
+ ((* (mpexpr_fun_i_unary_t) CP->op->fun) (sp)
+ || (* (mpexpr_fun_i_unary_t) CP->op->fun) (sp+1)));
+ goto apply_control_done;
+
+ case MPEXPR_TYPE_MAX & MPEXPR_TYPE_MASK_SPECIAL:
+ TRACE (printf ("special max\n"));
+ if ((* (mpexpr_fun_i_binary_t) CP->op->fun) (sp, sp+1) < 0)
+ (*p->mpX_swap) (sp, sp+1);
+ goto apply_control_done;
+ case MPEXPR_TYPE_MIN & MPEXPR_TYPE_MASK_SPECIAL:
+ TRACE (printf ("special min\n"));
+ if ((* (mpexpr_fun_i_binary_t) CP->op->fun) (sp, sp+1) > 0)
+ (*p->mpX_swap) (sp, sp+1);
+ goto apply_control_done;
+
+ default:
+ ERROR ("unrecognised special binary operator",
+ MPEXPR_RESULT_BAD_TABLE);
+ }
+
+ switch (CP->op->type & MPEXPR_TYPE_MASK_ARGSTYLE) {
+ case 0:
+ (* (mpexpr_fun_binary_t) CP->op->fun) (sp, sp, sp+1);
+ break;
+ case MPEXPR_TYPE_LAST_UI:
+ CHECK_UI (sp+1);
+ (* (mpexpr_fun_binary_ui_t) CP->op->fun)
+ (sp, sp, (*p->mpX_get_ui) (sp+1));
+ break;
+ case MPEXPR_TYPE_RESULT_INT:
+ (*p->mpX_set_si)
+ (sp,
+ (long) (* (mpexpr_fun_i_binary_t) CP->op->fun) (sp, sp+1));
+ break;
+ case MPEXPR_TYPE_LAST_UI | MPEXPR_TYPE_RESULT_INT:
+ CHECK_UI (sp+1);
+ (*p->mpX_set_si)
+ (sp,
+ (long) (* (mpexpr_fun_i_binary_ui_t) CP->op->fun)
+ (sp, (*p->mpX_get_ui) (sp+1)));
+ break;
+ default:
+ ERROR ("unrecognised binary argument calling style",
+ MPEXPR_RESULT_BAD_TABLE);
+ }
+ }
+ break;
+
+ case MPEXPR_TYPE_NARY(3):
+ {
+ mpX_ptr sp;
+
+ CHECK_ARGCOUNT ("ternary", 3);
+ DATA_POP (2);
+ sp = SP;
+ TRACE (MPX_TRACE ("arg1", sp);
+ MPX_TRACE ("arg2", sp+1);
+ MPX_TRACE ("arg3", sp+1));
+
+ switch (CP->op->type & MPEXPR_TYPE_MASK_ARGSTYLE) {
+ case 0:
+ (* (mpexpr_fun_ternary_t) CP->op->fun) (sp, sp, sp+1, sp+2);
+ break;
+ case MPEXPR_TYPE_LAST_UI:
+ CHECK_UI (sp+2);
+ (* (mpexpr_fun_ternary_ui_t) CP->op->fun)
+ (sp, sp, sp+1, (*p->mpX_get_ui) (sp+2));
+ break;
+ case MPEXPR_TYPE_RESULT_INT:
+ (*p->mpX_set_si)
+ (sp,
+ (long) (* (mpexpr_fun_i_ternary_t) CP->op->fun)
+ (sp, sp+1, sp+2));
+ break;
+ case MPEXPR_TYPE_LAST_UI | MPEXPR_TYPE_RESULT_INT:
+ CHECK_UI (sp+2);
+ (*p->mpX_set_si)
+ (sp,
+ (long) (* (mpexpr_fun_i_ternary_ui_t) CP->op->fun)
+ (sp, sp+1, (*p->mpX_get_ui) (sp+2)));
+ break;
+ default:
+ ERROR ("unrecognised binary argument calling style",
+ MPEXPR_RESULT_BAD_TABLE);
+ }
+ }
+ break;
+
+ default:
+ TRACE (printf ("unrecognised operator type: 0x%X\n", CP->op->type));
+ ERROR ("", MPEXPR_RESULT_PARSE_ERROR);
+ }
+
+ apply_control_done:
+ TRACE (MPX_TRACE ("result", SP));
+ CONTROL_POP ();
+ goto another_operator;
+
+ done:
+ if (p->error_code == MPEXPR_RESULT_OK)
+ {
+ if (p->data_top != 0)
+ {
+ TRACE (printf ("data stack want top at 0, got %d\n", p->data_top));
+ p->error_code = MPEXPR_RESULT_PARSE_ERROR;
+ }
+ else
+ (*p->mpX_set_or_swap) (p->res, SP);
+ }
+
+ {
+ int i;
+ for (i = 0; i < p->data_inited; i++)
+ {
+ TRACE (printf ("clear %d\n", i));
+ (*p->mpX_clear) (p->data_stack+i);
+ }
+ }
+
+ FREE_FUNC_TYPE (p->data_stack, p->data_alloc, union mpX_t);
+ FREE_FUNC_TYPE (p->control_stack, p->control_alloc, struct mpexpr_control_t);
+
+ return p->error_code;
+}
diff --git a/vendor/gmp-6.3.0/demos/expr/expr.h b/vendor/gmp-6.3.0/demos/expr/expr.h
new file mode 100644
index 0000000..d3b7c77
--- /dev/null
+++ b/vendor/gmp-6.3.0/demos/expr/expr.h
@@ -0,0 +1,142 @@
+/* Header for expression evaluation.
+
+Copyright 2000-2002, 2004 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+or
+
+ * the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any
+ later version.
+
+or both in parallel, as here.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received copies of the GNU General Public License and the
+GNU Lesser General Public License along with the GNU MP Library. If not,
+see https://www.gnu.org/licenses/. */
+
+
+#ifndef __EXPR_H__
+#define __EXPR_H__
+
+#define MPEXPR_RESULT_OK 0
+#define MPEXPR_RESULT_BAD_VARIABLE 1
+#define MPEXPR_RESULT_BAD_TABLE 2
+#define MPEXPR_RESULT_PARSE_ERROR 3
+#define MPEXPR_RESULT_NOT_UI 4
+
+
+/* basic types */
+#define MPEXPR_TYPE_NARY(n) ((n) * 0x0100)
+#define MPEXPR_TYPE_MASK_ARGCOUNT MPEXPR_TYPE_NARY(0xF)
+#define MPEXPR_TYPE_0ARY MPEXPR_TYPE_NARY(0)
+#define MPEXPR_TYPE_UNARY MPEXPR_TYPE_NARY(1)
+#define MPEXPR_TYPE_BINARY MPEXPR_TYPE_NARY(2)
+#define MPEXPR_TYPE_TERNARY MPEXPR_TYPE_NARY(3)
+
+/* options for all */
+#define MPEXPR_TYPE_LAST_UI 0x0010
+#define MPEXPR_TYPE_RESULT_INT 0x0020
+#define MPEXPR_TYPE_MASK_ARGSTYLE 0x0030
+
+#define MPEXPR_TYPE_UNARY_UI (MPEXPR_TYPE_UNARY | MPEXPR_TYPE_LAST_UI)
+#define MPEXPR_TYPE_I_UNARY (MPEXPR_TYPE_UNARY | MPEXPR_TYPE_RESULT_INT)
+#define MPEXPR_TYPE_I_UNARY_UI (MPEXPR_TYPE_I_UNARY | MPEXPR_TYPE_LAST_UI)
+#define MPEXPR_TYPE_BINARY_UI (MPEXPR_TYPE_BINARY | MPEXPR_TYPE_LAST_UI)
+#define MPEXPR_TYPE_I_BINARY (MPEXPR_TYPE_BINARY | MPEXPR_TYPE_RESULT_INT)
+#define MPEXPR_TYPE_I_BINARY_UI (MPEXPR_TYPE_I_BINARY| MPEXPR_TYPE_LAST_UI)
+#define MPEXPR_TYPE_TERNARY_UI (MPEXPR_TYPE_TERNARY | MPEXPR_TYPE_LAST_UI)
+#define MPEXPR_TYPE_I_TERNARY (MPEXPR_TYPE_TERNARY | MPEXPR_TYPE_RESULT_INT)
+#define MPEXPR_TYPE_I_TERNARY_UI (MPEXPR_TYPE_I_TERNARY|MPEXPR_TYPE_LAST_UI)
+
+/* 0ary with options */
+#define MPEXPR_TYPE_CONSTANT (MPEXPR_TYPE_0ARY | 0x0040)
+
+/* unary options */
+#define MPEXPR_TYPE_PREFIX 0x0040
+
+/* binary options */
+#define MPEXPR_TYPE_RIGHTASSOC 0x0040
+#define MPEXPR_TYPE_PAIRWISE 0x0080
+
+#define MPEXPR_TYPE_MASK_SPECIAL 0x000F
+
+/* unary specials */
+#define MPEXPR_TYPE_NEW_TABLE (MPEXPR_TYPE_UNARY | 0x001)
+#define MPEXPR_TYPE_DONE (MPEXPR_TYPE_UNARY | 0x002)
+#define MPEXPR_TYPE_VARIABLE (MPEXPR_TYPE_UNARY | 0x003)
+#define MPEXPR_TYPE_LOGICAL_NOT (MPEXPR_TYPE_UNARY | 0x004)
+#define MPEXPR_TYPE_CLOSEPAREN (MPEXPR_TYPE_UNARY | 0x005)
+#define MPEXPR_TYPE_OPENPAREN (MPEXPR_TYPE_CLOSEPAREN | MPEXPR_TYPE_PREFIX)
+
+/* binary specials */
+#define MPEXPR_TYPE_LOGICAL_AND (MPEXPR_TYPE_BINARY | 0x001)
+#define MPEXPR_TYPE_LOGICAL_OR (MPEXPR_TYPE_BINARY | 0x002)
+#define MPEXPR_TYPE_ARGSEP (MPEXPR_TYPE_BINARY | 0x003)
+#define MPEXPR_TYPE_QUESTION (MPEXPR_TYPE_BINARY | 0x004)
+#define MPEXPR_TYPE_COLON (MPEXPR_TYPE_BINARY | 0x005)
+#define MPEXPR_TYPE_MAX (MPEXPR_TYPE_BINARY | 0x006)
+#define MPEXPR_TYPE_MIN (MPEXPR_TYPE_BINARY | 0x007)
+#define MPEXPR_TYPE_MASK_CMP 0x008
+#define MPEXPR_TYPE_MASK_CMP_LT 0x001
+#define MPEXPR_TYPE_MASK_CMP_EQ 0x002
+#define MPEXPR_TYPE_MASK_CMP_GT 0x004
+#define MPEXPR_TYPE_CMP_LT (MPEXPR_TYPE_BINARY | MPEXPR_TYPE_MASK_CMP \
+ | MPEXPR_TYPE_MASK_CMP_LT)
+#define MPEXPR_TYPE_CMP_EQ (MPEXPR_TYPE_BINARY | MPEXPR_TYPE_MASK_CMP \
+ | MPEXPR_TYPE_MASK_CMP_EQ)
+#define MPEXPR_TYPE_CMP_GT (MPEXPR_TYPE_BINARY | MPEXPR_TYPE_MASK_CMP \
+ | MPEXPR_TYPE_MASK_CMP_GT)
+#define MPEXPR_TYPE_CMP_LE (MPEXPR_TYPE_CMP_LT | MPEXPR_TYPE_MASK_CMP_EQ)
+#define MPEXPR_TYPE_CMP_NE (MPEXPR_TYPE_CMP_LT | MPEXPR_TYPE_MASK_CMP_GT)
+#define MPEXPR_TYPE_CMP_GE (MPEXPR_TYPE_CMP_GT | MPEXPR_TYPE_MASK_CMP_EQ)
+
+/* parse options */
+#define MPEXPR_TYPE_WHOLEWORD 0x1000
+#define MPEXPR_TYPE_OPERATOR 0x2000
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*mpexpr_fun_t) (void);
+
+struct mpexpr_operator_t {
+ const char *name;
+ mpexpr_fun_t fun;
+ int type;
+ int precedence;
+};
+
+
+int mpf_expr_a (const struct mpexpr_operator_t *, mpf_ptr, int,
+ unsigned long, const char *, size_t, mpf_srcptr [26]);
+int mpf_expr (mpf_ptr, int, const char *, ...);
+
+int mpq_expr_a (const struct mpexpr_operator_t *, mpq_ptr,
+ int, const char *, size_t, mpq_srcptr [26]);
+int mpq_expr (mpq_ptr, int, const char *, ...);
+
+int mpz_expr_a (const struct mpexpr_operator_t *, mpz_ptr, int,
+ const char *, size_t, mpz_srcptr [26]);
+int mpz_expr (mpz_ptr, int, const char *, ...);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif
diff --git a/vendor/gmp-6.3.0/demos/expr/exprf.c b/vendor/gmp-6.3.0/demos/expr/exprf.c
new file mode 100644
index 0000000..1f7e21f
--- /dev/null
+++ b/vendor/gmp-6.3.0/demos/expr/exprf.c
@@ -0,0 +1,123 @@
+/* mpf expression evaluation
+
+Copyright 2000-2002 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+or
+
+ * the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any
+ later version.
+
+or both in parallel, as here.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received copies of the GNU General Public License and the
+GNU Lesser General Public License along with the GNU MP Library. If not,
+see https://www.gnu.org/licenses/. */
+
+#include <stdio.h>
+#include <string.h>
+#include "gmp.h"
+#include "expr-impl.h"
+
+
+/* Change this to "#define TRACE(x) x" to get some traces. */
+#define TRACE(x)
+
+
+static int
+e_mpf_sgn (mpf_srcptr x)
+{
+ return mpf_sgn (x);
+}
+
+
+static const struct mpexpr_operator_t _mpf_expr_standard_table[] = {
+
+ { "**", (mpexpr_fun_t) mpf_pow_ui,
+ MPEXPR_TYPE_BINARY_UI | MPEXPR_TYPE_RIGHTASSOC, 220 },
+
+ { "!", (mpexpr_fun_t) e_mpf_sgn,
+ MPEXPR_TYPE_LOGICAL_NOT | MPEXPR_TYPE_PREFIX, 210 },
+ { "-", (mpexpr_fun_t) mpf_neg,
+ MPEXPR_TYPE_UNARY | MPEXPR_TYPE_PREFIX, 210 },
+
+ { "*", (mpexpr_fun_t) mpf_mul, MPEXPR_TYPE_BINARY, 200 },
+ { "/", (mpexpr_fun_t) mpf_div, MPEXPR_TYPE_BINARY, 200 },
+
+ { "+", (mpexpr_fun_t) mpf_add, MPEXPR_TYPE_BINARY, 190 },
+ { "-", (mpexpr_fun_t) mpf_sub, MPEXPR_TYPE_BINARY, 190 },
+
+ { "<<", (mpexpr_fun_t) mpf_mul_2exp, MPEXPR_TYPE_BINARY_UI, 180 },
+ { ">>", (mpexpr_fun_t) mpf_div_2exp, MPEXPR_TYPE_BINARY_UI, 180 },
+
+ { "<=", (mpexpr_fun_t) mpf_cmp, MPEXPR_TYPE_CMP_LE, 170 },
+ { "<", (mpexpr_fun_t) mpf_cmp, MPEXPR_TYPE_CMP_LT, 170 },
+ { ">=", (mpexpr_fun_t) mpf_cmp, MPEXPR_TYPE_CMP_GE, 170 },
+ { ">", (mpexpr_fun_t) mpf_cmp, MPEXPR_TYPE_CMP_GT, 170 },
+
+ { "==", (mpexpr_fun_t) mpf_cmp, MPEXPR_TYPE_CMP_EQ, 160 },
+ { "!=", (mpexpr_fun_t) mpf_cmp, MPEXPR_TYPE_CMP_NE, 160 },
+
+ { "&&", (mpexpr_fun_t) e_mpf_sgn, MPEXPR_TYPE_LOGICAL_AND, 120 },
+ { "||", (mpexpr_fun_t) e_mpf_sgn, MPEXPR_TYPE_LOGICAL_OR, 110 },
+
+ { ":", NULL, MPEXPR_TYPE_COLON, 101 },
+ { "?", (mpexpr_fun_t) e_mpf_sgn, MPEXPR_TYPE_QUESTION, 100 },
+
+ { ")", NULL, MPEXPR_TYPE_CLOSEPAREN, 4 },
+ { "(", NULL, MPEXPR_TYPE_OPENPAREN, 3 },
+ { ",", NULL, MPEXPR_TYPE_ARGSEP, 2 },
+ { "$", NULL, MPEXPR_TYPE_VARIABLE, 1 },
+
+ { "abs", (mpexpr_fun_t) mpf_abs, MPEXPR_TYPE_UNARY },
+ { "ceil", (mpexpr_fun_t) mpf_ceil, MPEXPR_TYPE_UNARY },
+ { "cmp", (mpexpr_fun_t) mpf_cmp, MPEXPR_TYPE_I_BINARY },
+ { "eq", (mpexpr_fun_t) mpf_eq, MPEXPR_TYPE_I_TERNARY_UI },
+ { "floor", (mpexpr_fun_t) mpf_floor, MPEXPR_TYPE_UNARY },
+ { "integer_p",(mpexpr_fun_t) mpf_integer_p, MPEXPR_TYPE_I_UNARY },
+ { "max", (mpexpr_fun_t) mpf_cmp, MPEXPR_TYPE_MAX | MPEXPR_TYPE_PAIRWISE },
+ { "min", (mpexpr_fun_t) mpf_cmp, MPEXPR_TYPE_MIN | MPEXPR_TYPE_PAIRWISE },
+ { "reldiff", (mpexpr_fun_t) mpf_reldiff, MPEXPR_TYPE_BINARY },
+ { "sgn", (mpexpr_fun_t) e_mpf_sgn, MPEXPR_TYPE_I_UNARY },
+ { "sqrt", (mpexpr_fun_t) mpf_sqrt, MPEXPR_TYPE_UNARY },
+ { "trunc", (mpexpr_fun_t) mpf_trunc, MPEXPR_TYPE_UNARY },
+
+ { NULL }
+};
+
+const struct mpexpr_operator_t * const mpf_expr_standard_table
+= _mpf_expr_standard_table;
+
+
+int
+mpf_expr (mpf_ptr res, int base, const char *e, ...)
+{
+ mpf_srcptr var[MPEXPR_VARIABLES];
+ va_list ap;
+ int ret;
+ va_start (ap, e);
+
+ TRACE (printf ("mpf_expr(): base %d, %s\n", base, e));
+ ret = mpexpr_va_to_var ((void **) var, ap);
+ va_end (ap);
+
+ if (ret != MPEXPR_RESULT_OK)
+ return ret;
+
+ return mpf_expr_a (mpf_expr_standard_table, res, base,
+ mpf_get_prec (res), e, strlen(e), var);
+}
diff --git a/vendor/gmp-6.3.0/demos/expr/exprfa.c b/vendor/gmp-6.3.0/demos/expr/exprfa.c
new file mode 100644
index 0000000..1918cb5
--- /dev/null
+++ b/vendor/gmp-6.3.0/demos/expr/exprfa.c
@@ -0,0 +1,191 @@
+/* mpf expression evaluation
+
+Copyright 2000-2002, 2004 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+or
+
+ * the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any
+ later version.
+
+or both in parallel, as here.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received copies of the GNU General Public License and the
+GNU Lesser General Public License along with the GNU MP Library. If not,
+see https://www.gnu.org/licenses/. */
+
+
+/* Future: Bitwise "&", "|" and "&" could be done, if desired. Not sure
+ those functions would be much value though. */
+
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "gmp.h"
+#include "expr-impl.h"
+
+
+/* Change this to "#define TRACE(x) x" to get some traces. */
+#define TRACE(x)
+
+
+static size_t
+e_mpf_number (mpf_ptr res, const char *e, size_t elen, int base)
+{
+ char *edup;
+ size_t i, ret, extra=0;
+ int mant_base, exp_base;
+ void *(*allocate_func) (size_t);
+ void (*free_func) (void *, size_t);
+
+ TRACE (printf ("mpf_number base=%d \"%.*s\"\n", base, (int) elen, e));
+
+ /* mpf_set_str doesn't currently accept 0x for hex in base==0, so do it
+ here instead. FIXME: Would prefer to let mpf_set_str handle this. */
+ if (base == 0 && elen >= 2 && e[0] == '0' && (e[1] == 'x' || e[1] == 'X'))
+ {
+ base = 16;
+ extra = 2;
+ e += extra;
+ elen -= extra;
+ }
+
+ if (base == 0)
+ mant_base = 10;
+ else if (base < 0)
+ mant_base = -base;
+ else
+ mant_base = base;
+
+ /* exponent in decimal if base is negative */
+ if (base < 0)
+ exp_base = 10;
+ else if (base == 0)
+ exp_base = 10;
+ else
+ exp_base = base;
+
+#define IS_EXPONENT(c) \
+ (c == '@' || (base <= 10 && base >= -10 && (e[i] == 'e' || e[i] == 'E')))
+
+ i = 0;
+ for (;;)
+ {
+ if (i >= elen)
+ goto parsed;
+ if (e[i] == '.')
+ break;
+ if (IS_EXPONENT (e[i]))
+ goto exponent;
+ if (! isasciidigit_in_base (e[i], mant_base))
+ goto parsed;
+ i++;
+ }
+
+ /* fraction */
+ i++;
+ for (;;)
+ {
+ if (i >= elen)
+ goto parsed;
+ if (IS_EXPONENT (e[i]))
+ goto exponent;
+ if (! isasciidigit_in_base (e[i], mant_base))
+ goto parsed;
+ i++;
+ }
+
+ exponent:
+ i++;
+ if (i >= elen)
+ goto parsed;
+ if (e[i] == '-')
+ i++;
+ for (;;)
+ {
+ if (i >= elen)
+ goto parsed;
+ if (! isasciidigit_in_base (e[i], exp_base))
+ break;
+ i++;
+ }
+
+ parsed:
+ TRACE (printf (" parsed i=%u \"%.*s\"\n", i, (int) i, e));
+
+ mp_get_memory_functions (&allocate_func, NULL, &free_func);
+ edup = (*allocate_func) (i+1);
+ memcpy (edup, e, i);
+ edup[i] = '\0';
+
+ if (mpf_set_str (res, edup, base) == 0)
+ ret = i + extra;
+ else
+ ret = 0;
+
+ (*free_func) (edup, i+1);
+ return ret;
+}
+
+static int
+e_mpf_ulong_p (mpf_srcptr f)
+{
+ return mpf_integer_p (f) && mpf_fits_ulong_p (f);
+}
+
+/* Don't want to change the precision of w, can only do an actual swap when
+ w and x have the same precision. */
+static void
+e_mpf_set_or_swap (mpf_ptr w, mpf_ptr x)
+{
+ if (mpf_get_prec (w) == mpf_get_prec (x))
+ mpf_swap (w, x);
+ else
+ mpf_set (w, x);
+}
+
+
+int
+mpf_expr_a (const struct mpexpr_operator_t *table,
+ mpf_ptr res, int base, unsigned long prec,
+ const char *e, size_t elen,
+ mpf_srcptr var[26])
+{
+ struct mpexpr_parse_t p;
+
+ p.table = table;
+ p.res = (mpX_ptr) res;
+ p.base = base;
+ p.prec = prec;
+ p.e = e;
+ p.elen = elen;
+ p.var = (mpX_srcptr *) var;
+
+ p.mpX_clear = (mpexpr_fun_one_t) mpf_clear;
+ p.mpX_ulong_p = (mpexpr_fun_i_unary_t) e_mpf_ulong_p;
+ p.mpX_get_ui = (mpexpr_fun_get_ui_t) mpf_get_ui;
+ p.mpX_init = (mpexpr_fun_unary_ui_t) mpf_init2;
+ p.mpX_number = (mpexpr_fun_number_t) e_mpf_number;
+ p.mpX_set = (mpexpr_fun_unary_t) mpf_set;
+ p.mpX_set_or_swap = (mpexpr_fun_unary_t) e_mpf_set_or_swap;
+ p.mpX_set_si = (mpexpr_fun_set_si_t) mpf_set_si;
+ p.mpX_swap = (mpexpr_fun_swap_t) mpf_swap;
+
+ return mpexpr_evaluate (&p);
+}
diff --git a/vendor/gmp-6.3.0/demos/expr/exprq.c b/vendor/gmp-6.3.0/demos/expr/exprq.c
new file mode 100644
index 0000000..9643200
--- /dev/null
+++ b/vendor/gmp-6.3.0/demos/expr/exprq.c
@@ -0,0 +1,155 @@
+/* mpq expression evaluation
+
+Copyright 2000-2002 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+or
+
+ * the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any
+ later version.
+
+or both in parallel, as here.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received copies of the GNU General Public License and the
+GNU Lesser General Public License along with the GNU MP Library. If not,
+see https://www.gnu.org/licenses/. */
+
+#include <stdio.h>
+#include <string.h>
+#include "gmp.h"
+#include "expr-impl.h"
+
+
+/* Change this to "#define TRACE(x) x" to get some traces. */
+#define TRACE(x)
+
+
+static void
+e_mpq_pow_ui (mpq_ptr r, mpq_srcptr b, unsigned long e)
+{
+ mpz_pow_ui (mpq_numref(r), mpq_numref(b), e);
+ mpz_pow_ui (mpq_denref(r), mpq_denref(b), e);
+}
+
+/* Wrapped because mpq_sgn is a macro. */
+static int
+e_mpq_sgn (mpq_srcptr x)
+{
+ return mpq_sgn (x);
+}
+
+/* Wrapped because mpq_equal only guarantees a non-zero return, whereas we
+ want 1 or 0 for == and !=. */
+static int
+e_mpq_equal (mpq_srcptr x, mpq_srcptr y)
+{
+ return mpq_equal (x, y) != 0;
+}
+static int
+e_mpq_notequal (mpq_srcptr x, mpq_srcptr y)
+{
+ return ! mpq_equal (x, y);
+}
+
+static void
+e_mpq_num (mpq_ptr w, mpq_srcptr x)
+{
+ if (w != x)
+ mpz_set (mpq_numref(w), mpq_numref(x));
+ mpz_set_ui (mpq_denref(w), 1L);
+}
+static void
+e_mpq_den (mpq_ptr w, mpq_srcptr x)
+{
+ if (w == x)
+ mpz_swap (mpq_numref(w), mpq_denref(w));
+ else
+ mpz_set (mpq_numref(w), mpq_denref(x));
+ mpz_set_ui (mpq_denref(w), 1L);
+}
+
+
+static const struct mpexpr_operator_t _mpq_expr_standard_table[] = {
+
+ { "**", (mpexpr_fun_t) e_mpq_pow_ui,
+ MPEXPR_TYPE_BINARY_UI | MPEXPR_TYPE_RIGHTASSOC, 220 },
+
+ { "!", (mpexpr_fun_t) e_mpq_sgn,
+ MPEXPR_TYPE_LOGICAL_NOT | MPEXPR_TYPE_PREFIX, 210 },
+ { "-", (mpexpr_fun_t) mpq_neg,
+ MPEXPR_TYPE_UNARY | MPEXPR_TYPE_PREFIX, 210 },
+
+ { "*", (mpexpr_fun_t) mpq_mul, MPEXPR_TYPE_BINARY, 200 },
+ { "/", (mpexpr_fun_t) mpq_div, MPEXPR_TYPE_BINARY, 200 },
+
+ { "+", (mpexpr_fun_t) mpq_add, MPEXPR_TYPE_BINARY, 190 },
+ { "-", (mpexpr_fun_t) mpq_sub, MPEXPR_TYPE_BINARY, 190 },
+
+ { "<<", (mpexpr_fun_t) mpq_mul_2exp, MPEXPR_TYPE_BINARY_UI, 180 },
+ { ">>", (mpexpr_fun_t) mpq_div_2exp, MPEXPR_TYPE_BINARY_UI, 180 },
+
+ { "<=", (mpexpr_fun_t) mpq_cmp, MPEXPR_TYPE_CMP_LE, 170 },
+ { "<", (mpexpr_fun_t) mpq_cmp, MPEXPR_TYPE_CMP_LT, 170 },
+ { ">=", (mpexpr_fun_t) mpq_cmp, MPEXPR_TYPE_CMP_GE, 170 },
+ { ">", (mpexpr_fun_t) mpq_cmp, MPEXPR_TYPE_CMP_GT, 170 },
+
+ { "==", (mpexpr_fun_t) e_mpq_equal, MPEXPR_TYPE_I_BINARY, 160 },
+ { "!=", (mpexpr_fun_t) e_mpq_notequal, MPEXPR_TYPE_I_BINARY, 160 },
+
+ { "&&", (mpexpr_fun_t) e_mpq_sgn, MPEXPR_TYPE_LOGICAL_AND, 120 },
+ { "||", (mpexpr_fun_t) e_mpq_sgn, MPEXPR_TYPE_LOGICAL_OR, 110 },
+
+ { ":", NULL, MPEXPR_TYPE_COLON, 101 },
+ { "?", (mpexpr_fun_t) e_mpq_sgn, MPEXPR_TYPE_QUESTION, 100 },
+
+ { ")", (mpexpr_fun_t) e_mpq_sgn, MPEXPR_TYPE_CLOSEPAREN, 4 },
+ { "(", (mpexpr_fun_t) e_mpq_sgn, MPEXPR_TYPE_OPENPAREN, 3 },
+ { ",", (mpexpr_fun_t) e_mpq_sgn, MPEXPR_TYPE_ARGSEP, 2 },
+ { "$", NULL, MPEXPR_TYPE_VARIABLE, 1 },
+
+ { "abs", (mpexpr_fun_t) mpq_abs, MPEXPR_TYPE_UNARY },
+ { "cmp", (mpexpr_fun_t) mpq_cmp, MPEXPR_TYPE_I_BINARY },
+ { "den", (mpexpr_fun_t) e_mpq_den, MPEXPR_TYPE_UNARY },
+ { "max", (mpexpr_fun_t) mpq_cmp, MPEXPR_TYPE_MAX | MPEXPR_TYPE_PAIRWISE },
+ { "min", (mpexpr_fun_t) mpq_cmp, MPEXPR_TYPE_MIN | MPEXPR_TYPE_PAIRWISE },
+ { "num", (mpexpr_fun_t) e_mpq_num, MPEXPR_TYPE_UNARY },
+ { "sgn", (mpexpr_fun_t) e_mpq_sgn, MPEXPR_TYPE_I_UNARY },
+
+ { NULL }
+};
+
+const struct mpexpr_operator_t * const mpq_expr_standard_table
+= _mpq_expr_standard_table;
+
+
+int
+mpq_expr (mpq_ptr res, int base, const char *e, ...)
+{
+ mpq_srcptr var[MPEXPR_VARIABLES];
+ va_list ap;
+ int ret;
+ va_start (ap, e);
+
+ TRACE (printf ("mpq_expr(): base %d, %s\n", base, e));
+ ret = mpexpr_va_to_var ((void **) var, ap);
+ va_end (ap);
+
+ if (ret != MPEXPR_RESULT_OK)
+ return ret;
+
+ return mpq_expr_a (mpq_expr_standard_table, res, base, e, strlen(e), var);
+}
diff --git a/vendor/gmp-6.3.0/demos/expr/exprqa.c b/vendor/gmp-6.3.0/demos/expr/exprqa.c
new file mode 100644
index 0000000..f3b6ecb
--- /dev/null
+++ b/vendor/gmp-6.3.0/demos/expr/exprqa.c
@@ -0,0 +1,100 @@
+/* mpq expression evaluation
+
+Copyright 2000, 2001, 2004 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+or
+
+ * the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any
+ later version.
+
+or both in parallel, as here.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received copies of the GNU General Public License and the
+GNU Lesser General Public License along with the GNU MP Library. If not,
+see https://www.gnu.org/licenses/. */
+
+
+#include <stdio.h>
+#include "gmp.h"
+#include "expr-impl.h"
+
+
+static int
+e_mpq_ulong_p (mpq_srcptr q)
+{
+ return mpz_fits_ulong_p (mpq_numref (q))
+ && mpz_cmp_ui (mpq_denref (q), 1L) == 0;
+}
+
+/* get value as a ui, on the assumption it fits */
+static int
+e_mpq_get_ui_fits (mpq_srcptr q)
+{
+ return mpz_get_ui (mpq_numref (q));
+}
+
+static void
+e_mpq_set_si1 (mpq_ptr q, long num)
+{
+ mpq_set_si (q, num, 1L);
+}
+
+/* The same as mpz, but putting the result in the numerator. Negatives and
+ fractions aren't parsed here because '-' and '/' are operators. */
+static size_t
+e_mpq_number (mpq_ptr res, const char *e, size_t elen, int base)
+{
+ mpz_set_ui (mpq_denref (res), 1L);
+ return mpexpr_mpz_number (mpq_numref (res), e, elen, base);
+}
+
+
+/* ignoring prec */
+static void
+e_mpq_init (mpq_ptr q, unsigned long prec)
+{
+ mpq_init (q);
+}
+
+int
+mpq_expr_a (const struct mpexpr_operator_t *table,
+ mpq_ptr res, int base,
+ const char *e, size_t elen,
+ mpq_srcptr var[26])
+{
+ struct mpexpr_parse_t p;
+
+ p.table = table;
+ p.res = (mpX_ptr) res;
+ p.base = base;
+ p.e = e;
+ p.elen = elen;
+ p.var = (mpX_srcptr *) var;
+
+ p.mpX_clear = (mpexpr_fun_one_t) mpq_clear;
+ p.mpX_ulong_p = (mpexpr_fun_i_unary_t) e_mpq_ulong_p;
+ p.mpX_get_ui = (mpexpr_fun_get_ui_t) e_mpq_get_ui_fits;
+ p.mpX_init = (mpexpr_fun_unary_ui_t) e_mpq_init;
+ p.mpX_number = (mpexpr_fun_number_t) e_mpq_number;
+ p.mpX_set = (mpexpr_fun_unary_t) mpq_set;
+ p.mpX_set_or_swap = (mpexpr_fun_unary_t) mpq_swap;
+ p.mpX_set_si = (mpexpr_fun_set_si_t) e_mpq_set_si1;
+ p.mpX_swap = (mpexpr_fun_swap_t) mpq_swap;
+
+ return mpexpr_evaluate (&p);
+}
diff --git a/vendor/gmp-6.3.0/demos/expr/exprv.c b/vendor/gmp-6.3.0/demos/expr/exprv.c
new file mode 100644
index 0000000..c25741b
--- /dev/null
+++ b/vendor/gmp-6.3.0/demos/expr/exprv.c
@@ -0,0 +1,57 @@
+/* mpz expression evaluation, simple part */
+
+/*
+Copyright 2000, 2001 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+or
+
+ * the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any
+ later version.
+
+or both in parallel, as here.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received copies of the GNU General Public License and the
+GNU Lesser General Public License along with the GNU MP Library. If not,
+see https://www.gnu.org/licenses/. */
+
+#include <stdio.h>
+#include "gmp.h"
+#include "expr-impl.h"
+
+
+int
+mpexpr_va_to_var (void *var[], va_list ap)
+{
+ int i = 0;
+ void *v;
+
+ for (;;)
+ {
+ v = va_arg (ap, void *);
+ if (v == NULL)
+ break;
+ if (i >= MPEXPR_VARIABLES)
+ return MPEXPR_RESULT_BAD_VARIABLE;
+ var[i++] = v;
+ }
+
+ while (i < MPEXPR_VARIABLES)
+ var[i++] = NULL;
+
+ return MPEXPR_RESULT_OK;
+}
diff --git a/vendor/gmp-6.3.0/demos/expr/exprz.c b/vendor/gmp-6.3.0/demos/expr/exprz.c
new file mode 100644
index 0000000..bac1a99
--- /dev/null
+++ b/vendor/gmp-6.3.0/demos/expr/exprz.c
@@ -0,0 +1,206 @@
+/* mpz expression evaluation, simple part
+
+Copyright 2000-2002 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+or
+
+ * the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any
+ later version.
+
+or both in parallel, as here.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received copies of the GNU General Public License and the
+GNU Lesser General Public License along with the GNU MP Library. If not,
+see https://www.gnu.org/licenses/. */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include "gmp.h"
+#include "expr-impl.h"
+
+
+/* Change this to "#define TRACE(x) x" to get some traces. */
+#define TRACE(x)
+
+
+/* These are macros, so need function wrappers. */
+static int
+e_mpz_sgn (mpz_srcptr x)
+{
+ return mpz_sgn (x);
+}
+static int
+e_mpz_odd_p (mpz_srcptr x)
+{
+ return mpz_odd_p (x);
+}
+static int
+e_mpz_even_p (mpz_srcptr x)
+{
+ return mpz_even_p (x);
+}
+
+/* These wrapped because MPEXPR_TYPE_I_ functions are expected to return
+ "int" whereas these return "unsigned long". */
+static void
+e_mpz_hamdist (mpz_ptr w, mpz_srcptr x, mpz_srcptr y)
+{
+ mpz_set_ui (w, mpz_hamdist (x, y));
+}
+static void
+e_mpz_popcount (mpz_ptr w, mpz_srcptr x)
+{
+ mpz_set_ui (w, mpz_popcount (x));
+}
+static void
+e_mpz_scan0 (mpz_ptr w, mpz_srcptr x, unsigned long start)
+{
+ mpz_set_ui (w, mpz_scan0 (x, start));
+}
+static void
+e_mpz_scan1 (mpz_ptr w, mpz_srcptr x, unsigned long start)
+{
+ mpz_set_ui (w, mpz_scan1 (x, start));
+}
+
+/* These wrapped because they're in-place whereas MPEXPR_TYPE_BINARY_UI
+ expects a separate source and destination. Actually the parser will
+ normally pass w==x anyway. */
+static void
+e_mpz_setbit (mpz_ptr w, mpz_srcptr x, unsigned long n)
+{
+ if (w != x)
+ mpz_set (w, x);
+ mpz_setbit (w, n);
+}
+static void
+e_mpz_clrbit (mpz_ptr w, mpz_srcptr x, unsigned long n)
+{
+ if (w != x)
+ mpz_set (w, x);
+ mpz_clrbit (w, n);
+}
+
+static const struct mpexpr_operator_t _mpz_expr_standard_table[] = {
+
+ { "**", (mpexpr_fun_t) mpz_pow_ui,
+ MPEXPR_TYPE_BINARY_UI | MPEXPR_TYPE_RIGHTASSOC, 220 },
+
+ { "~", (mpexpr_fun_t) mpz_com,
+ MPEXPR_TYPE_UNARY | MPEXPR_TYPE_PREFIX, 210 },
+ { "!", (mpexpr_fun_t) e_mpz_sgn,
+ MPEXPR_TYPE_LOGICAL_NOT | MPEXPR_TYPE_PREFIX, 210 },
+ { "-", (mpexpr_fun_t) mpz_neg,
+ MPEXPR_TYPE_UNARY | MPEXPR_TYPE_PREFIX, 210 },
+
+ { "*", (mpexpr_fun_t) mpz_mul, MPEXPR_TYPE_BINARY, 200 },
+ { "/", (mpexpr_fun_t) mpz_tdiv_q, MPEXPR_TYPE_BINARY, 200 },
+ { "%", (mpexpr_fun_t) mpz_tdiv_r, MPEXPR_TYPE_BINARY, 200 },
+
+ { "+", (mpexpr_fun_t) mpz_add, MPEXPR_TYPE_BINARY, 190 },
+ { "-", (mpexpr_fun_t) mpz_sub, MPEXPR_TYPE_BINARY, 190 },
+
+ { "<<", (mpexpr_fun_t) mpz_mul_2exp, MPEXPR_TYPE_BINARY_UI, 180 },
+ { ">>", (mpexpr_fun_t) mpz_tdiv_q_2exp, MPEXPR_TYPE_BINARY_UI, 180 },
+
+ { "<=", (mpexpr_fun_t) mpz_cmp, MPEXPR_TYPE_CMP_LE, 170 },
+ { "<", (mpexpr_fun_t) mpz_cmp, MPEXPR_TYPE_CMP_LT, 170 },
+ { ">=", (mpexpr_fun_t) mpz_cmp, MPEXPR_TYPE_CMP_GE, 170 },
+ { ">", (mpexpr_fun_t) mpz_cmp, MPEXPR_TYPE_CMP_GT, 170 },
+
+ { "==", (mpexpr_fun_t) mpz_cmp, MPEXPR_TYPE_CMP_EQ, 160 },
+ { "!=", (mpexpr_fun_t) mpz_cmp, MPEXPR_TYPE_CMP_NE, 160 },
+
+ { "&", (mpexpr_fun_t) mpz_and, MPEXPR_TYPE_BINARY, 150 },
+ { "^", (mpexpr_fun_t) mpz_xor, MPEXPR_TYPE_BINARY, 140 },
+ { "|", (mpexpr_fun_t) mpz_ior, MPEXPR_TYPE_BINARY, 130 },
+ { "&&", (mpexpr_fun_t) e_mpz_sgn, MPEXPR_TYPE_LOGICAL_AND, 120 },
+ { "||", (mpexpr_fun_t) e_mpz_sgn, MPEXPR_TYPE_LOGICAL_OR, 110 },
+
+ { ":", NULL, MPEXPR_TYPE_COLON, 101 },
+ { "?", (mpexpr_fun_t) e_mpz_sgn, MPEXPR_TYPE_QUESTION, 100 },
+
+ { ")", NULL, MPEXPR_TYPE_CLOSEPAREN, 4 },
+ { "(", NULL, MPEXPR_TYPE_OPENPAREN, 3 },
+ { ",", NULL, MPEXPR_TYPE_ARGSEP, 2 },
+ { "$", NULL, MPEXPR_TYPE_VARIABLE, 1 },
+
+ { "abs", (mpexpr_fun_t) mpz_abs, MPEXPR_TYPE_UNARY },
+ { "bin", (mpexpr_fun_t) mpz_bin_ui, MPEXPR_TYPE_BINARY_UI },
+ { "clrbit", (mpexpr_fun_t) e_mpz_clrbit, MPEXPR_TYPE_BINARY_UI },
+ { "cmp", (mpexpr_fun_t) mpz_cmp, MPEXPR_TYPE_I_BINARY },
+ { "cmpabs", (mpexpr_fun_t) mpz_cmpabs, MPEXPR_TYPE_I_BINARY },
+ { "congruent_p",(mpexpr_fun_t)mpz_congruent_p, MPEXPR_TYPE_I_TERNARY },
+ { "divisible_p",(mpexpr_fun_t)mpz_divisible_p, MPEXPR_TYPE_I_BINARY },
+ { "even_p", (mpexpr_fun_t) e_mpz_even_p, MPEXPR_TYPE_I_UNARY },
+ { "fib", (mpexpr_fun_t) mpz_fib_ui, MPEXPR_TYPE_UNARY_UI },
+ { "fac", (mpexpr_fun_t) mpz_fac_ui, MPEXPR_TYPE_UNARY_UI },
+ { "gcd", (mpexpr_fun_t) mpz_gcd, MPEXPR_TYPE_BINARY
+ | MPEXPR_TYPE_PAIRWISE },
+ { "hamdist", (mpexpr_fun_t) e_mpz_hamdist, MPEXPR_TYPE_BINARY },
+ { "invert", (mpexpr_fun_t) mpz_invert, MPEXPR_TYPE_BINARY },
+ { "jacobi", (mpexpr_fun_t) mpz_jacobi, MPEXPR_TYPE_I_BINARY },
+ { "kronecker", (mpexpr_fun_t) mpz_kronecker, MPEXPR_TYPE_I_BINARY },
+ { "lcm", (mpexpr_fun_t) mpz_lcm, MPEXPR_TYPE_BINARY
+ | MPEXPR_TYPE_PAIRWISE },
+ { "lucnum", (mpexpr_fun_t) mpz_lucnum_ui, MPEXPR_TYPE_UNARY_UI },
+ { "max", (mpexpr_fun_t) mpz_cmp, MPEXPR_TYPE_MAX
+ | MPEXPR_TYPE_PAIRWISE },
+ { "min", (mpexpr_fun_t) mpz_cmp, MPEXPR_TYPE_MIN
+ | MPEXPR_TYPE_PAIRWISE },
+ { "nextprime", (mpexpr_fun_t) mpz_nextprime, MPEXPR_TYPE_UNARY },
+ { "odd_p", (mpexpr_fun_t) e_mpz_odd_p, MPEXPR_TYPE_I_UNARY },
+ { "perfect_power_p", (mpexpr_fun_t)mpz_perfect_power_p, MPEXPR_TYPE_I_UNARY},
+ { "perfect_square_p",(mpexpr_fun_t)mpz_perfect_square_p,MPEXPR_TYPE_I_UNARY},
+ { "popcount", (mpexpr_fun_t) e_mpz_popcount, MPEXPR_TYPE_UNARY },
+ { "powm", (mpexpr_fun_t) mpz_powm, MPEXPR_TYPE_TERNARY },
+ { "probab_prime_p", (mpexpr_fun_t)mpz_probab_prime_p, MPEXPR_TYPE_I_UNARY},
+ { "root", (mpexpr_fun_t) mpz_root, MPEXPR_TYPE_BINARY_UI },
+ { "scan0", (mpexpr_fun_t) e_mpz_scan0, MPEXPR_TYPE_BINARY_UI },
+ { "scan1", (mpexpr_fun_t) e_mpz_scan1, MPEXPR_TYPE_BINARY_UI },
+ { "setbit", (mpexpr_fun_t) e_mpz_setbit, MPEXPR_TYPE_BINARY_UI },
+ { "tstbit", (mpexpr_fun_t) mpz_tstbit, MPEXPR_TYPE_I_BINARY_UI },
+ { "sgn", (mpexpr_fun_t) e_mpz_sgn, MPEXPR_TYPE_I_UNARY },
+ { "sqrt", (mpexpr_fun_t) mpz_sqrt, MPEXPR_TYPE_UNARY },
+ { NULL }
+};
+
+/* The table is available globally only through a pointer, so the table size
+ can change without breaking binary compatibility. */
+const struct mpexpr_operator_t * const mpz_expr_standard_table
+= _mpz_expr_standard_table;
+
+
+int
+mpz_expr (mpz_ptr res, int base, const char *e, ...)
+{
+ mpz_srcptr var[MPEXPR_VARIABLES];
+ va_list ap;
+ int ret;
+ va_start (ap, e);
+
+ TRACE (printf ("mpz_expr(): base %d, %s\n", base, e));
+ ret = mpexpr_va_to_var ((void **) var, ap);
+ va_end (ap);
+
+ if (ret != MPEXPR_RESULT_OK)
+ return ret;
+
+ return mpz_expr_a (mpz_expr_standard_table, res, base, e, strlen(e), var);
+}
diff --git a/vendor/gmp-6.3.0/demos/expr/exprza.c b/vendor/gmp-6.3.0/demos/expr/exprza.c
new file mode 100644
index 0000000..eda830d
--- /dev/null
+++ b/vendor/gmp-6.3.0/demos/expr/exprza.c
@@ -0,0 +1,108 @@
+/* mpz expression evaluation
+
+Copyright 2000-2002, 2004 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+or
+
+ * the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any
+ later version.
+
+or both in parallel, as here.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received copies of the GNU General Public License and the
+GNU Lesser General Public License along with the GNU MP Library. If not,
+see https://www.gnu.org/licenses/. */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include "gmp.h"
+#include "expr-impl.h"
+
+
+/* No need to parse '-' since that's handled as an operator.
+ This function also by mpq_expr_a, so it's not static. */
+size_t
+mpexpr_mpz_number (mpz_ptr res, const char *e, size_t elen, int base)
+{
+ char *edup;
+ size_t i, ret;
+ int base_effective = (base == 0 ? 10 : base);
+ void *(*allocate_func) (size_t);
+ void (*free_func) (void *, size_t);
+
+ i = 0;
+ if (e[i] == '0')
+ {
+ i++;
+ if (e[i] == 'x' || e[i] == 'b')
+ i++;
+ }
+
+ for ( ; i < elen; i++)
+ if (! isasciidigit_in_base (e[i], base_effective))
+ break;
+
+ mp_get_memory_functions (&allocate_func, NULL, &free_func);
+ edup = (*allocate_func) (i+1);
+ memcpy (edup, e, i);
+ edup[i] = '\0';
+
+ if (mpz_set_str (res, edup, base) == 0)
+ ret = i;
+ else
+ ret = 0;
+
+ (*free_func) (edup, i+1);
+ return ret;
+}
+
+/* ignoring prec */
+static void
+e_mpz_init (mpz_ptr z, unsigned long prec)
+{
+ mpz_init (z);
+}
+
+int
+mpz_expr_a (const struct mpexpr_operator_t *table,
+ mpz_ptr res, int base,
+ const char *e, size_t elen,
+ mpz_srcptr var[26])
+{
+ struct mpexpr_parse_t p;
+
+ p.table = table;
+ p.res = (mpX_ptr) res;
+ p.base = base;
+ p.e = e;
+ p.elen = elen;
+ p.var = (mpX_srcptr *) var;
+
+ p.mpX_clear = (mpexpr_fun_one_t) mpz_clear;
+ p.mpX_ulong_p = (mpexpr_fun_i_unary_t) mpz_fits_ulong_p;
+ p.mpX_get_ui = (mpexpr_fun_get_ui_t) mpz_get_ui;
+ p.mpX_init = (mpexpr_fun_unary_ui_t) e_mpz_init;
+ p.mpX_number = (mpexpr_fun_number_t) mpexpr_mpz_number;
+ p.mpX_set = (mpexpr_fun_unary_t) mpz_set;
+ p.mpX_set_or_swap = (mpexpr_fun_unary_t) mpz_swap;
+ p.mpX_set_si = (mpexpr_fun_set_si_t) mpz_set_si;
+ p.mpX_swap = (mpexpr_fun_swap_t) mpz_swap;
+
+ return mpexpr_evaluate (&p);
+}
diff --git a/vendor/gmp-6.3.0/demos/expr/run-expr.c b/vendor/gmp-6.3.0/demos/expr/run-expr.c
new file mode 100644
index 0000000..706b910
--- /dev/null
+++ b/vendor/gmp-6.3.0/demos/expr/run-expr.c
@@ -0,0 +1,242 @@
+/* Demo program to run expression evaluation.
+
+Copyright 2000-2002, 2004 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+or
+
+ * the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any
+ later version.
+
+or both in parallel, as here.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received copies of the GNU General Public License and the
+GNU Lesser General Public License along with the GNU MP Library. If not,
+see https://www.gnu.org/licenses/. */
+
+
+/* Usage: ./run-expr [-z] [-q] [-f] [-p prec] [-b base] expression...
+
+ Evaluate each argument as a simple expression. By default this is in mpz
+ integers, but -q selects mpq or -f selects mpf. For mpf the float
+ precision can be set with -p. In all cases the input base can be set
+ with -b, or the default is "0" meaning decimal with "0x" allowed.
+
+ This is a pretty trivial program, it's just an easy way to experiment
+ with the evaluation functions. */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "gmp.h"
+#include "expr.h"
+
+
+void
+run_expr (int type, int base, unsigned long prec, char *str)
+{
+ int outbase = (base == 0 ? 10 : base);
+ int ret;
+
+ switch (type) {
+ case 'z':
+ default:
+ {
+ mpz_t res, var_a, var_b;
+
+ mpz_init (res);
+ mpz_init_set_ui (var_a, 55L);
+ mpz_init_set_ui (var_b, 99L);
+
+ ret = mpz_expr (res, base, str, var_a, var_b, NULL);
+ printf ("\"%s\" base %d: ", str, base);
+ if (ret == MPEXPR_RESULT_OK)
+ {
+ printf ("result ");
+ mpz_out_str (stdout, outbase, res);
+ printf ("\n");
+ }
+ else
+ printf ("invalid (return code %d)\n", ret);
+
+ mpz_clear (res);
+ mpz_clear (var_a);
+ mpz_clear (var_b);
+ }
+ break;
+
+ case 'q':
+ {
+ mpq_t res, var_a, var_b;
+
+ mpq_init (res);
+ mpq_init (var_a);
+ mpq_init (var_b);
+
+ mpq_set_ui (var_a, 55L, 1);
+ mpq_set_ui (var_b, 99L, 1);
+
+ ret = mpq_expr (res, base, str, var_a, var_b, NULL);
+ printf ("\"%s\" base %d: ", str, base);
+ if (ret == MPEXPR_RESULT_OK)
+ {
+ printf ("result ");
+ mpq_out_str (stdout, outbase, res);
+ printf ("\n");
+ }
+ else
+ printf ("invalid (return code %d)\n", ret);
+
+ mpq_clear (res);
+ mpq_clear (var_a);
+ mpq_clear (var_b);
+ }
+ break;
+
+ case 'f':
+ {
+ mpf_t res, var_a, var_b;
+
+ mpf_init2 (res, prec);
+ mpf_init_set_ui (var_a, 55L);
+ mpf_init_set_ui (var_b, 99L);
+
+ ret = mpf_expr (res, base, str, var_a, var_b, NULL);
+ printf ("\"%s\" base %d: ", str, base);
+ if (ret == MPEXPR_RESULT_OK)
+ {
+ printf ("result ");
+ mpf_out_str (stdout, outbase, (size_t) 0, res);
+ printf ("\n");
+ }
+ else
+ printf ("invalid (return code %d)\n", ret);
+
+ mpf_clear (res);
+ mpf_clear (var_a);
+ mpf_clear (var_b);
+ }
+ break;
+ }
+}
+
+int
+main (int argc, char *argv[])
+{
+ int type = 'z';
+ int base = 0;
+ unsigned long prec = 64;
+ int seen_expr = 0;
+ int opt;
+ char *arg;
+
+ for (;;)
+ {
+ argv++;
+ arg = argv[0];
+ if (arg == NULL)
+ break;
+
+ if (arg[0] == '-')
+ {
+ for (;;)
+ {
+ arg++;
+ opt = arg[0];
+
+ switch (opt) {
+ case '\0':
+ goto end_opt;
+
+ case 'f':
+ case 'q':
+ case 'z':
+ type = opt;
+ break;
+
+ case 'b':
+ arg++;
+ if (arg[0] == '\0')
+ {
+ argv++;
+ arg = argv[0];
+ if (arg == NULL)
+ {
+ need_arg:
+ fprintf (stderr, "Need argument for -%c\n", opt);
+ exit (1);
+ }
+ }
+ base = atoi (arg);
+ goto end_opt;
+
+ case 'p':
+ arg++;
+ if (arg[0] == '\0')
+ {
+ argv++;
+ arg = argv[0];
+ if (arg == NULL)
+ goto need_arg;
+ }
+ prec = atoi (arg);
+ goto end_opt;
+
+ case '-':
+ arg++;
+ if (arg[0] != '\0')
+ {
+ /* no "--foo" options */
+ fprintf (stderr, "Unrecognised option --%s\n", arg);
+ exit (1);
+ }
+ /* stop option interpretation at "--" */
+ for (;;)
+ {
+ argv++;
+ arg = argv[0];
+ if (arg == NULL)
+ goto done;
+ run_expr (type, base, prec, arg);
+ seen_expr = 1;
+ }
+
+ default:
+ fprintf (stderr, "Unrecognised option -%c\n", opt);
+ exit (1);
+ }
+ }
+ end_opt:
+ ;
+ }
+ else
+ {
+ run_expr (type, base, prec, arg);
+ seen_expr = 1;
+ }
+ }
+
+ done:
+ if (! seen_expr)
+ {
+ printf ("Usage: %s [-z] [-q] [-f] [-p prec] [-b base] expression...\n", argv[0]);
+ exit (1);
+ }
+
+ return 0;
+}
diff --git a/vendor/gmp-6.3.0/demos/expr/t-expr.c b/vendor/gmp-6.3.0/demos/expr/t-expr.c
new file mode 100644
index 0000000..64fbfab
--- /dev/null
+++ b/vendor/gmp-6.3.0/demos/expr/t-expr.c
@@ -0,0 +1,510 @@
+/* Test expression evaluation (print nothing and exit 0 if successful).
+
+Copyright 2000-2004 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+or
+
+ * the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any
+ later version.
+
+or both in parallel, as here.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received copies of the GNU General Public License and the
+GNU Lesser General Public License along with the GNU MP Library. If not,
+see https://www.gnu.org/licenses/. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "gmp-impl.h"
+#include "tests.h"
+#include "expr-impl.h"
+
+
+int option_trace = 0;
+
+
+struct data_t {
+ int base;
+ const char *expr;
+ const char *want;
+};
+
+#define numberof(x) (sizeof (x) / sizeof ((x)[0]))
+
+
+/* These data_xxx[] arrays are tables to be tested with one or more of the
+ mp?_t types. z=mpz_t, q=mpz_t, f=mpf_t. */
+
+struct data_t data_zqf[] = {
+
+ /* various deliberately wrong expressions */
+ { 0, "", NULL },
+ { 0, "1+", NULL },
+ { 0, "+2", NULL },
+ { 0, "1,2", NULL },
+ { 0, "foo(1,2)", NULL },
+ { 0, "1+foo", NULL },
+ { 10, "0fff", NULL },
+ { 0, "!", NULL },
+ { 0, "10!", NULL },
+ { 0, "-10!", NULL },
+ { 0, "gcd((4,6))", NULL },
+ { 0, "()", NULL },
+ { 0, "fac(2**1000)", NULL },
+ { 0, "$", NULL },
+ { 0, "$-", NULL },
+
+ /* some basics */
+ { 10, "123", "123" },
+ { 10, "-123", "-123" },
+ { 10, "1+2", "3" },
+ { 10, "1+2+3", "6" },
+ { 10, "1+2*3", "7" },
+ { 10, "3*2+1", "7" },
+ { 10, "$a", "55" },
+ { 10, "b", "99" },
+ { 16, "b", "11" },
+ { 10, "4**3 * 2 + 1", "129" },
+ { 10, "1<2", "1" },
+ { 10, "1>2", "0" },
+
+ { 10, "(123)", "123" },
+
+ { 10, "sgn(-123)", "-1" },
+ { 10, "5-7", "-2" },
+
+ { 0, "cmp(0,0)", "0" },
+ { 0, "cmp(1,0)", "1" },
+ { 0, "cmp(0,1)", "-1" },
+ { 0, "cmp(-1,0)", "-1" },
+ { 0, "cmp(0,-1)", "1" },
+
+ { 10, "0 ? 123 : 456", "456" },
+ { 10, "1 ? 4+5 : 6+7", "9" },
+
+ { 10, "(123)", "123" },
+ { 10, "(2+3)", "5" },
+ { 10, "(4+5)*(5+6)", "99" },
+
+ { 0, "1 << 16", "65536" },
+ { 0, "256 >> 4", "16" },
+ { 0, "-256 >> 4", "-16" },
+
+ { 0, "!1", "0" },
+ { 0, "!9", "0" },
+ { 0, "!0", "1" },
+
+ { 0, "2**2**2", "16" },
+ { 0, "-2**2**2", "-16" },
+
+ { 0, "0x100", "256" },
+ { 10, "0x100", NULL },
+ { 10, "0x 100", NULL },
+
+ { 0, " max ( 1, 2, 3, 4, 5, 6, 7, 8)", "8" },
+ { 0, " max ( 1, 9, 2, 3, 4, 5, 6, 7, 8)", "9" },
+ { 0, " min ( 1, 9, 2, 3, 4, 5, 6, 7, 8)", "1" },
+
+ { 10, "abs(123)", "123" },
+ { 10, "abs(-123)", "123" },
+ { 10, "abs(0)", "0" },
+
+ /* filling data stack */
+ { 0, "1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+(1+1))))))))))))))", "16" },
+
+ /* filling control stack */
+ { 0, "----------------------------------------------------1", "1" },
+};
+
+
+const struct data_t data_z[] = {
+ { 0, "divisible_p(333,3)", "1" },
+ { 0, "congruent_p(7,1,3)", "1" },
+
+ { 0, "cmpabs(0,0)", "0" },
+ { 0, "cmpabs(1,0)", "1" },
+ { 0, "cmpabs(0,1)", "-1" },
+ { 0, "cmpabs(-1,0)", "1" },
+ { 0, "cmpabs(0,-1)", "-1" },
+
+ { 0, "odd_p(1)", "1" },
+ { 0, "odd_p(0)", "0" },
+ { 0, "odd_p(-1)", "1" },
+
+ { 0, "even_p(1)", "0" },
+ { 0, "even_p(0)", "1" },
+ { 0, "even_p(-1)", "0" },
+
+ { 0, "fac(0)", "1" },
+ { 0, "fac(1)", "1" },
+ { 0, "fac(2)", "2" },
+ { 0, "fac(3)", "6" },
+ { 0, "fac(10)", "3628800" },
+
+ { 10, "root(81,4)", "3" },
+
+ { 10, "gcd(4,6)", "2" },
+ { 10, "gcd(4,6,9)", "1" },
+
+ { 10, "powm(3,2,9)", "0" },
+ { 10, "powm(3,2,8)", "1" },
+
+ /* filling data stack */
+ { 0, "1 ? 1 : 1 || 1 && 1 | 1 ^ 1 & 1 == 1 >= 1 << 1 - 1 * 1 ** 1", "1" },
+
+ /* filling control stack */
+ { 0, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~1", "1" },
+
+ { 0, "fib(10)", "55" },
+
+ { 0, "setbit(0,5)", "32" },
+ { 0, "clrbit(32,5)", "0" },
+ { 0, "tstbit(32,5)", "1" },
+ { 0, "tstbit(32,4)", "0" },
+ { 0, "scan0(7,0)", "3" },
+ { 0, "scan1(7,0)", "0" },
+};
+
+const struct data_t data_zq[] = {
+ /* expecting failure */
+ { 0, "1.2", NULL },
+};
+
+const struct data_t data_q[] = {
+ { 10, "(1/2 + 1/3 + 1/4 + 1/5 + 1/6)*20", "29" },
+ { 0, "num(5/9)", "5" },
+ { 0, "den(5/9)", "9" },
+};
+
+const struct data_t data_zf[] = {
+ { 10, "sqrt ( 49 )", "7" },
+ { 10, "sqrt ( 49 ) + 1", "8" },
+ { 10, "sqrt((49))", "7" },
+ { 10, "sqrt((((((((49))))))))", "7" },
+};
+
+const struct data_t data_f[] = {
+ { 0, "1@10", "10000000000" },
+ { 0, "1.5@10", "15000000000" },
+ { 0, "1000@-1", "100" },
+ { 0, "10.00@-1", "1" },
+
+ { 0, "1e10", "10000000000" },
+ { 0, "1.5e10", "15000000000" },
+ { 0, "1000e-1", "100" },
+ { 0, "10.00e-1", "1" },
+
+ { 16, "1@9", "68719476736" },
+
+ { 16, "1@10", "18446744073709551616" },
+ { -16, "1@10", "1099511627776" },
+
+ { 0, "ceil(0)", "0" },
+ { 0, "ceil(0.25)", "1" },
+ { 0, "ceil(0.5)", "1" },
+ { 0, "ceil(1.5)", "2" },
+ { 0, "ceil(-0.5)", "0" },
+ { 0, "ceil(-1.5)", "-1" },
+
+ /* only simple cases because mpf_eq currently only works on whole limbs */
+ { 0, "eq(0xFFFFFFFFFFFFFFFF1111111111111111,0xFFFFFFFFFFFFFFFF2222222222222222,64)", "1" },
+ { 0, "eq(0xFFFFFFFFFFFFFFFF1111111111111111,0xFFFFFFFFFFFFFFFF2222222222222222,128)", "0" },
+
+ { 0, "floor(0)", "0" },
+ { 0, "floor(0.25)", "0" },
+ { 0, "floor(0.5)", "0" },
+ { 0, "floor(1.5)", "1" },
+ { 0, "floor(-0.5)", "-1" },
+ { 0, "floor(-1.5)", "-2" },
+
+ { 0, "integer_p(1)", "1" },
+ { 0, "integer_p(0.5)", "0" },
+
+ { 0, "trunc(0)", "0" },
+ { 0, "trunc(0.25)", "0" },
+ { 0, "trunc(0.5)", "0" },
+ { 0, "trunc(1.5)", "1" },
+ { 0, "trunc(-0.5)", "0" },
+ { 0, "trunc(-1.5)", "-1" },
+};
+
+struct datalist_t {
+ const struct data_t *data;
+ int num;
+};
+
+#define DATALIST(data) { data, numberof (data) }
+
+struct datalist_t list_z[] = {
+ DATALIST (data_z),
+ DATALIST (data_zq),
+ DATALIST (data_zf),
+ DATALIST (data_zqf),
+};
+
+struct datalist_t list_q[] = {
+ DATALIST (data_q),
+ DATALIST (data_zq),
+ DATALIST (data_zqf),
+};
+
+struct datalist_t list_f[] = {
+ DATALIST (data_zf),
+ DATALIST (data_zqf),
+ DATALIST (data_f),
+};
+
+
+void
+check_z (void)
+{
+ const struct data_t *data;
+ mpz_t a, b, got, want;
+ int l, i, ret;
+
+ mpz_init (got);
+ mpz_init (want);
+ mpz_init_set_ui (a, 55);
+ mpz_init_set_ui (b, 99);
+
+ for (l = 0; l < numberof (list_z); l++)
+ {
+ data = list_z[l].data;
+
+ for (i = 0; i < list_z[l].num; i++)
+ {
+ if (option_trace)
+ printf ("mpz_expr \"%s\"\n", data[i].expr);
+
+ ret = mpz_expr (got, data[i].base, data[i].expr, a, b, NULL);
+
+ if (data[i].want == NULL)
+ {
+ /* expect to fail */
+ if (ret == MPEXPR_RESULT_OK)
+ {
+ printf ("mpz_expr wrong return value, got %d, expected failure\n", ret);
+ goto error;
+ }
+ }
+ else
+ {
+ if (mpz_set_str (want, data[i].want, 0) != 0)
+ {
+ printf ("Cannot parse wanted value string\n");
+ goto error;
+ }
+ if (ret != MPEXPR_RESULT_OK)
+ {
+ printf ("mpz_expr failed unexpectedly\n");
+ printf (" return value %d\n", ret);
+ goto error;
+ }
+ if (mpz_cmp (got, want) != 0)
+ {
+ printf ("mpz_expr wrong result\n");
+ printf (" got "); mpz_out_str (stdout, 10, got);
+ printf ("\n");
+ printf (" want "); mpz_out_str (stdout, 10, want);
+ printf ("\n");
+ goto error;
+ }
+ }
+ }
+ }
+ mpz_clear (a);
+ mpz_clear (b);
+ mpz_clear (got);
+ mpz_clear (want);
+ return;
+
+ error:
+ printf (" base %d\n", data[i].base);
+ printf (" expr \"%s\"\n", data[i].expr);
+ if (data[i].want != NULL)
+ printf (" want \"%s\"\n", data[i].want);
+ abort ();
+}
+
+void
+check_q (void)
+{
+ const struct data_t *data;
+ mpq_t a, b, got, want;
+ int l, i, ret;
+
+ mpq_init (got);
+ mpq_init (want);
+ mpq_init (a);
+ mpq_init (b);
+
+ mpq_set_ui (a, 55, 1);
+ mpq_set_ui (b, 99, 1);
+
+ for (l = 0; l < numberof (list_q); l++)
+ {
+ data = list_q[l].data;
+
+ for (i = 0; i < list_q[l].num; i++)
+ {
+ if (option_trace)
+ printf ("mpq_expr \"%s\"\n", data[i].expr);
+
+ ret = mpq_expr (got, data[i].base, data[i].expr, a, b, NULL);
+
+ if (data[i].want == NULL)
+ {
+ /* expect to fail */
+ if (ret == MPEXPR_RESULT_OK)
+ {
+ printf ("mpq_expr wrong return value, got %d, expected failure\n", ret);
+ goto error;
+ }
+ }
+ else
+ {
+ if (mpz_set_str (mpq_numref(want), data[i].want, 0) != 0)
+ {
+ printf ("Cannot parse wanted value string\n");
+ goto error;
+ }
+ mpz_set_ui (mpq_denref(want), 1);
+
+ if (ret != MPEXPR_RESULT_OK)
+ {
+ printf ("mpq_expr failed unexpectedly\n");
+ printf (" return value %d\n", ret);
+ goto error;
+ }
+ if (mpq_cmp (got, want) != 0)
+ {
+ printf ("mpq_expr wrong result\n");
+ printf (" got "); mpq_out_str (stdout, 10, got);
+ printf ("\n");
+ printf (" want "); mpq_out_str (stdout, 10, want);
+ printf ("\n");
+ goto error;
+ }
+ }
+ }
+ }
+ mpq_clear (a);
+ mpq_clear (b);
+ mpq_clear (got);
+ mpq_clear (want);
+ return;
+
+ error:
+ printf (" base %d\n", data[i].base);
+ printf (" expr \"%s\"\n", data[i].expr);
+ if (data[i].want != NULL)
+ printf (" want \"%s\"\n", data[i].want);
+ abort ();
+}
+
+void
+check_f (void)
+{
+ const struct data_t *data;
+ mpf_t a, b, got, want;
+ int l, i, ret;
+
+ mpf_set_default_prec (200L);
+
+ mpf_init (got);
+ mpf_init (want);
+ mpf_init_set_ui (a, 55);
+ mpf_init_set_ui (b, 99);
+
+ for (l = 0; l < numberof (list_f); l++)
+ {
+ data = list_f[l].data;
+
+ for (i = 0; i < list_f[l].num; i++)
+ {
+ if (option_trace)
+ printf ("mpf_expr \"%s\"\n", data[i].expr);
+
+ ret = mpf_expr (got, data[i].base, data[i].expr, a, b, NULL);
+
+ if (data[i].want == NULL)
+ {
+ /* expect to fail */
+ if (ret == MPEXPR_RESULT_OK)
+ {
+ printf ("mpf_expr wrong return value, got %d, expected failure\n", ret);
+ goto error;
+ }
+ }
+ else
+ {
+ if (mpf_set_str (want, data[i].want, 0) != 0)
+ {
+ printf ("Cannot parse wanted value string\n");
+ goto error;
+ }
+
+ if (ret != MPEXPR_RESULT_OK)
+ {
+ printf ("mpf_expr failed unexpectedly\n");
+ printf (" return value %d\n", ret);
+ goto error;
+ }
+ if (mpf_cmp (got, want) != 0)
+ {
+ printf ("mpf_expr wrong result\n");
+ printf (" got "); mpf_out_str (stdout, 10, 20, got);
+ printf ("\n");
+ printf (" want "); mpf_out_str (stdout, 10, 20, want);
+ printf ("\n");
+ goto error;
+ }
+ }
+ }
+ }
+ mpf_clear (a);
+ mpf_clear (b);
+ mpf_clear (got);
+ mpf_clear (want);
+ return;
+
+ error:
+ printf (" base %d\n", data[i].base);
+ printf (" expr \"%s\"\n", data[i].expr);
+ if (data[i].want != NULL)
+ printf (" want \"%s\"\n", data[i].want);
+ abort ();
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ tests_start ();
+
+ if (argc >= 2)
+ option_trace = 1;
+
+ check_z ();
+ check_q ();
+ check_f ();
+
+ tests_end ();
+ exit (0);
+}