From a89a14ef5da44684a16b204e7a70460cc8c4922a Mon Sep 17 00:00:00 2001 From: Thomas Voss Date: Fri, 21 Jun 2024 23:36:36 +0200 Subject: Basic constant folding implementation --- vendor/gmp-6.3.0/demos/expr/Makefile.am | 54 +++ vendor/gmp-6.3.0/demos/expr/Makefile.in | 666 +++++++++++++++++++++++++ vendor/gmp-6.3.0/demos/expr/README | 501 +++++++++++++++++++ vendor/gmp-6.3.0/demos/expr/expr-impl.h | 125 +++++ vendor/gmp-6.3.0/demos/expr/expr.c | 834 ++++++++++++++++++++++++++++++++ vendor/gmp-6.3.0/demos/expr/expr.h | 142 ++++++ vendor/gmp-6.3.0/demos/expr/exprf.c | 123 +++++ vendor/gmp-6.3.0/demos/expr/exprfa.c | 191 ++++++++ vendor/gmp-6.3.0/demos/expr/exprq.c | 155 ++++++ vendor/gmp-6.3.0/demos/expr/exprqa.c | 100 ++++ vendor/gmp-6.3.0/demos/expr/exprv.c | 57 +++ vendor/gmp-6.3.0/demos/expr/exprz.c | 206 ++++++++ vendor/gmp-6.3.0/demos/expr/exprza.c | 108 +++++ vendor/gmp-6.3.0/demos/expr/run-expr.c | 242 +++++++++ vendor/gmp-6.3.0/demos/expr/t-expr.c | 510 +++++++++++++++++++ 15 files changed, 4014 insertions(+) create mode 100644 vendor/gmp-6.3.0/demos/expr/Makefile.am create mode 100644 vendor/gmp-6.3.0/demos/expr/Makefile.in create mode 100644 vendor/gmp-6.3.0/demos/expr/README create mode 100644 vendor/gmp-6.3.0/demos/expr/expr-impl.h create mode 100644 vendor/gmp-6.3.0/demos/expr/expr.c create mode 100644 vendor/gmp-6.3.0/demos/expr/expr.h create mode 100644 vendor/gmp-6.3.0/demos/expr/exprf.c create mode 100644 vendor/gmp-6.3.0/demos/expr/exprfa.c create mode 100644 vendor/gmp-6.3.0/demos/expr/exprq.c create mode 100644 vendor/gmp-6.3.0/demos/expr/exprqa.c create mode 100644 vendor/gmp-6.3.0/demos/expr/exprv.c create mode 100644 vendor/gmp-6.3.0/demos/expr/exprz.c create mode 100644 vendor/gmp-6.3.0/demos/expr/exprza.c create mode 100644 vendor/gmp-6.3.0/demos/expr/run-expr.c create mode 100644 vendor/gmp-6.3.0/demos/expr/t-expr.c (limited to 'vendor/gmp-6.3.0/demos/expr') 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 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 + +#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 +#include +#include + +#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 +#include +#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 +#include +#include + +#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 +#include +#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 +#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 +#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 +#include +#include +#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 +#include +#include +#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 +#include + +#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 +#include + +#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); +} -- cgit v1.2.3