]> www.ginac.de Git - ginac.git/commitdiff
Merge branch 'master' of git://ffmssmsc.jinr.ru:443/varg/ginac
authorJens Vollinga <jensv@nikhef.nl>
Tue, 9 Sep 2008 20:42:50 +0000 (22:42 +0200)
committerJens Vollinga <jensv@nikhef.nl>
Tue, 9 Sep 2008 20:42:50 +0000 (22:42 +0200)
22 files changed:
ChangeLog
INSTALL
acinclude.m4
configure.ac
doc/examples/Makefile.am
doc/tutorial/Makefile.am
doc/tutorial/ginac.texi
ginac/basic.cpp
ginac/function.pl
ginac/inifcns_nstdsums.cpp
ginac/parser/debug.hpp
ginac/parser/lexer.cpp
ginac/parser/lexer.hpp
ginac/parser/parser.cpp
ginac/parser/parser.hpp
ginac/remember.cpp
ginac/symbol.cpp
ginac/symbol.h
ginac/utils.cpp
ginac/utils.h
ginsh/ginsh.1.in
ginsh/ginsh_parser.yy

index 9d497859971421bc323cb41f8771888a68b6ae8c..b57ef5bac11d572659fb653c9b4586f5a616b25c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,7 @@
 This file is not yet operational.  Eventually it should record all changes.
-Till then, you are advised to resort to our CVS server where all changes are
+Till then, you are advised to resort to our git server where all changes are
 logged.  This is how to get anonymous read-only access:
-$ cvs -d :pserver:anoncvs@cvs.ginac.de:/home/cvs/GiNaC login
-enter the password `anoncvs'
-$ cvs -d :pserver:anoncvs@cvs.ginac.de:/home/cvs/GiNaC -z 9 co GiNaC
+$ git clone git://www.ginac.de/ginac.git ginac
+$ cd ginac; git whatchanged
+Alternatively you can browse the repository on-line at
+http://www.ginac.de/ginac.git
diff --git a/INSTALL b/INSTALL
index 1cad2773e5a3ec6ec9aeb4008b1cd94e396b891f..f4c98b7e0b5ef5cb208e96f18d94fac2686ad2a2 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -29,7 +29,7 @@ Known not to work with:
  - GCC 2.96 or earlier because proper exception and standard library support
    is missing there.
 
-If you install from CVS, you also need GNU autoconf (>=2.59), automake (>=1.7),
+If you install from git, you also need GNU autoconf (>=2.59), automake (>=1.7),
 libtool (>= 1.5), bison (>= 2.3), flex (>= 2.5.33), autogen (>= 5.6.0) to be
 installed.
 
@@ -87,15 +87,12 @@ make          |   ~6m   |   ~8m   | shared and static library
 make check    |   ~8m   |  ~12m   | largely due to compilation
 
 
-To install from CVS
+To install from git 
 ===================
 
 First, download the code:
-
- $ cvs -d :pserver:anoncvs@cvs.ginac.de:/home/cvs/GiNaC login
- [enter "anoncvs" as the password]
- $ cvs -d :pserver:anoncvs@cvs.ginac.de:/home/cvs/GiNaC co GiNaC
- $ cd GiNaC
+ $ git clone git://www.ginac.de/ginac.git ginac
+ $ cd ginac
 
 Secondly, make sure all required software is installed. This is *really*
 important step. If some package is missing, the `configure' script might
index dd7299c08ebea595232594d3c224e39918fe1015..78c3bdb7a86a62919ccde358bafc336f0b7af3e5 100644 (file)
@@ -4,44 +4,73 @@ dnl additions' names with AC_ but with GINAC_ in order to steer clear of
 dnl future trouble.
 dnl ===========================================================================
 
-dnl Usage: GINAC_RLVERSION
-dnl The maintainers of libreadline are complete morons: they don't care a shit
-dnl about compatiblilty (which is not so bad by itself) and at the same time 
-dnl they don't export the version to the preprocessor so we could kluge around 
-dnl incomatiblities.  The only reliable way to figure out the version is by 
-dnl checking the extern variable rl_library_version at runtime.  &#@$%*!
-AC_DEFUN([GINAC_LIB_READLINE_VERSION],
-[AC_CACHE_CHECK([for version of libreadline], ginac_cv_rlversion, [
-AC_TRY_RUN([
-#include <stdio.h>
-#include <sys/types.h>
-#include <readline/readline.h>
-
-int main()
-{
-    FILE *fd;
-    fd = fopen("conftest.out", "w");
-    fprintf(fd, "%s\n", rl_library_version);
-    fclose(fd);
-    return 0;
-}], [
-dnl Some non-GNU readline implementations have non-numeric rl_library_version
-ginac_cv_rlversion=`sed -e 's/[[^0-9.]]//g' 'conftest.out'`], [ ginac_cv_rlversion='unknown'], [ ginac_cv_rlversion='4.2'])])
-if test -z "$ginac_cv_rlversion"; then
-       GINAC_WARNING([Unsupported version of libreadline.])
-       ginac_cv_rlversion='unknown'
-fi
-if test "x${ginac_cv_rlversion}" != "xunknown"; then
-       AC_DEFINE(REALLY_HAVE_LIBREADLINE, ,[Define if GNU libreadline is installed])
-  RL_VERSION_MAJOR=`echo ${ginac_cv_rlversion} | sed -e 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
-  AC_DEFINE_UNQUOTED(GINAC_RL_VERSION_MAJOR, $RL_VERSION_MAJOR, [Major version of installed readline library.])
-  RL_VERSION_MINOR=`echo ${ginac_cv_rlversion} | sed -e 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'`
-  AC_DEFINE_UNQUOTED(GINAC_RL_VERSION_MINOR, $RL_VERSION_MINOR, [Minor version of installed readline library.])
-else
-  GINAC_WARNING([I could not run a test of libreadline (needed for building ginsh).])
+dnl Usage: GINAC_STD_CXX_HEADERS
+dnl Check for standard C++ headers, bail out if something is missing.
+AC_DEFUN([GINAC_STD_CXX_HEADERS], [
+AC_CACHE_CHECK([for standard C++ header files], [ginac_cv_std_cxx_headers], [
+       ginac_cv_std_cxx_headers="no"
+       AC_LANG_PUSH([C++])
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+               #include <iosfwd>
+               #include <iostream>
+               #include <vector>
+               #include <list>
+               #include <map>
+               #include <set>
+               #include <string>
+               #include <sstream>
+               #include <typeinfo>
+               #include <stdexcept>
+               #include <algorithm>
+               #include <limits>
+               #include <ctime>
+               ]])], [ginac_cv_std_cxx_headers="yes"])
+       AC_LANG_POP([C++])])
+if test "${ginac_cv_std_cxx_headers}" != "yes"; then
+       AC_MSG_ERROR([Standard ISO C++ 98 headers are missing])
 fi
 ])
 
+dnl Usage: GINAC_LIBREADLINE
+dnl
+dnl Check if GNU readline library and headers are avialable.
+dnl Defines GINSH_LIBS variable, and HAVE_LIBREADLINE,
+dnl HAVE_READLINE_READLINE_H, HAVE_READLINE_HISTORY_H preprocessor macros.
+dnl
+dnl Note: this macro rejects readline versions <= 4.2 and non-GNU
+dnl implementations.
+dnl
+AC_DEFUN([GINAC_READLINE],[
+AC_REQUIRE([GINAC_TERMCAP])
+GINSH_LIBS=""
+AC_CHECK_HEADERS(readline/readline.h readline/history.h)
+if test "x${ac_cv_header_readline_readline_h}" != "xyes" -o "x${ac_cv_header_readline_history_h}" != "xyes"; then
+       GINAC_WARNING([readline headers could not be found.])
+else
+       AC_CACHE_CHECK([for version of libreadline], [ginac_cv_rl_supported], [
+               ginac_cv_rl_supported="no"
+               AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+                       #include <stdio.h>
+                       #include <readline/readline.h>
+                       #if !defined(RL_VERSION_MAJOR) || !defined(RL_VERSION_MINOR)
+                       #error "Ancient/unsupported version of readline"
+                       #endif]])],
+                       [ginac_cv_rl_supported="yes"])])
+       if test "x${ginac_cv_rl_supported}" != "xyes"; then
+               GINAC_WARNING([Unsupported version of readline (<= 4.2 or non-GNU).])
+       else
+               save_LIBS="$LIBS"
+               LIBS="$LIBTERMCAP $LIBS"
+               AC_CHECK_LIB(readline, readline)
+               if test "x${ac_cv_lib_readline_readline}" != "xyes"; then
+                       GINAC_WARNING([libreadline could not be found.])
+               fi
+               GINSH_LIBS="$LIBS"
+               LIBS="$save_LIBS"
+       fi
+fi
+AC_SUBST(GINSH_LIBS)])
+       
 dnl Usage: GINAC_TERMCAP
 dnl libreadline is based on the termcap functions.
 dnl Some systems have tgetent(), tgetnum(), tgetstr(), tgetflag(), tputs(),
@@ -132,3 +161,43 @@ if test "$ac_cv_have_rusage" = yes; then
 fi
 AC_SUBST(CONFIG_RUSAGE)
 ])
+
+dnl Usage: GINAC_EXCOMPILER
+dnl - Checks if dlopen is available
+dnl - Allows user to disable GiNaC::compile_ex (e.g. for security reasons)
+dnl Defines HAVE_LIBDL preprocessor macro, sets DL_LIBS and CONFIG_EXCOMPILER
+dnl variables.
+AC_DEFUN([GINAC_EXCOMPILER], [
+CONFIG_EXCOMPILER=yes
+DL_LIBS=""
+
+AC_ARG_ENABLE([excompiler], 
+       [AS_HELP_STRING([--enable-excompiler], [Enable GiNaC::compile_ex (default: yes)])],
+       [if test "$enableval" = "no"; then
+               CONFIG_EXCOMPILER="no"
+       fi],
+       [CONFIG_EXCOMPILER="yes"])
+
+case $host_os in
+       *mingw32*)
+       CONFIG_EXCOMPILER="notsupported"
+       ;;
+       *)
+       ;;
+esac
+
+if test "$CONFIG_EXCOMPILER" = "yes"; then
+       AC_CHECK_LIB(dl, dlopen, [
+               DL_LIBS="-ldl"
+               AC_DEFINE(HAVE_LIBDL, 1, [set to 1 if you have a working libdl installed.])],
+
+               [AC_MSG_WARN([libdl not found. GiNaC::compile_ex will be disabled.])
+                CONFIG_EXCOMPILER="no"])
+elif test "$CONFIG_EXCOMPILER" = "no"; then
+       AC_MSG_RESULT([INFO: GiNaC::compile_ex disabled at user request.])
+else
+       AC_MSG_RESULT([INFO: GiNaC::compile_ex is not supported on $host_os.])
+fi
+AC_SUBST(DL_LIBS)
+AC_SUBST(CONFIG_EXCOMPILER)])
+
index 22f9c9657ceb382e3ad4d620f5ffed34f0b732f6..c90f09d64010f29c3f6a61b71047a1aed9164bfa 100644 (file)
@@ -21,7 +21,8 @@ m4_define([ginac_binary_age], [0])
 AC_INIT([GiNaC], ginac_version, [<ginac-list@ginac.de>])
 AC_PREREQ(2.59)
 AC_CONFIG_SRCDIR(ginac/basic.cpp)
-AC_CONFIG_HEADERS(config.h)
+AC_CONFIG_AUX_DIR([config])
+AC_CONFIG_HEADERS([config/config.h])
 dnl This defines PACKAGE and VERSION.
 AM_INIT_AUTOMAKE([gnu 1.7 dist-bzip2])
 
@@ -71,62 +72,12 @@ AM_PROG_LIBTOOL
 AM_PROG_LEX
 AC_PROG_YACC
 
-dnl Check for data types which are needed by the hash function 
-dnl (golden_ratio_hash).
-AC_CHECK_SIZEOF(int)
-AC_CHECK_SIZEOF(long)
-AC_CHECK_SIZEOF(long long)
-AC_CHECK_SIZEOF(long double)
-AC_CHECK_SIZEOF(void *)
 
 dnl Switch to C++ language mode for the following libraries and headers.
 AC_LANG([C++])
 
-dnl Check for stuff needed for building the GiNaC interactive shell (ginsh).
-AC_CHECK_HEADERS(unistd.h)
-GINAC_HAVE_RUSAGE
-AC_CHECK_HEADERS(readline/readline.h readline/history.h)
-if test "x${ac_cv_header_readline_readline_h}" != "xyes" -o "x${ac_cv_header_readline_history_h}" != "xyes"; then
-  GINAC_WARNING([I could not find the headers for libreadline (needed for building ginsh).])
-fi
-GINAC_TERMCAP
-save_LIBS=$LIBS
-LIBS="$LIBTERMCAP $LIBS"
-AC_CHECK_LIB(readline, readline)
-if test "x${ac_cv_lib_readline_readline}" = "xyes"; then
-  GINAC_LIB_READLINE_VERSION
-else
-  GINAC_WARNING([I could not find libreadline (needed by ginsh).])
-fi
-GINSH_LIBS=$LIBS
-LIBS=$save_LIBS
-AC_SUBST(GINSH_LIBS)
-
 dnl Make sure all the necessary standard headers are installed on the system.
-AC_CHECK_HEADER(iosfwd, , GINAC_ERROR([The standard <iosfwd> header file could not be found.]))
-AC_CHECK_HEADER(iostream, , GINAC_ERROR([The standard <iostream> header file could not be found.]))
-AC_CHECK_HEADER(vector, , GINAC_ERROR([The standard <vector> header file could not be found.]))
-AC_CHECK_HEADER(list, , GINAC_ERROR([The standard <list> header file could not be found.]))
-AC_CHECK_HEADER(map, , GINAC_ERROR([The standard <map> header file could not be found.]))
-AC_CHECK_HEADER(string, , GINAC_ERROR([The standard <string> header file could not be found.]))
-AC_CHECK_HEADER(sstream, , GINAC_ERROR([The standard <sstream> header file could not be found.]))
-AC_CHECK_HEADER(typeinfo, , GINAC_ERROR([The standard <typeinfo> header file could not be found.]))
-AC_CHECK_HEADER(stdexcept, , GINAC_ERROR([The standard <stdexcept> header file could not be found.]))
-AC_CHECK_HEADER(algorithm, , GINAC_ERROR([The standard <algorithm> header file could not be found.]))
-AC_CHECK_HEADER(limits, , GINAC_ERROR([The standard <limits> header file could not be found.]))
-if test "x$CONFIG_RUSAGE" = "xno"; then
-    AC_CHECK_HEADER(ctime, , GINAC_ERROR([The standard <ctime> header file could not be found.]))
-fi
-
-DL_LIBS=""
-dnl Check for dl library (needed for GiNaC::compile).
-AC_CHECK_LIB(dl, dlopen,
-       [
-               DL_LIBS="-ldl"
-               AC_DEFINE(HAVE_LIBDL, 1, [set to 1 if you have a working libdl installed.])
-       ], 
-       GINAC_WARNING([libdl not found. GiNaC::compile will be disabled.]))
-AC_SUBST(DL_LIBS)
+GINAC_STD_CXX_HEADERS
 
 dnl We need to have Bruno Haible's CLN installed.
 dnl (pkg-config must have installed pkg.m4 at a visible place, which provides
@@ -136,6 +87,18 @@ PKG_CHECK_MODULES(CLN, cln >= 1.1.6)
 LIBS="$LIBS $CLN_LIBS"
 CPPFLAGS="$CPPFLAGS $CLN_CFLAGS"
 
+dnl Check for data types which are needed by the hash function 
+dnl (golden_ratio_hash).
+AC_CHECK_TYPE(long long)
+
+dnl Check for stuff needed for building the GiNaC interactive shell (ginsh).
+AC_CHECK_HEADERS(unistd.h)
+GINAC_HAVE_RUSAGE
+GINAC_READLINE
+
+dnl Check for dl library (needed for GiNaC::compile).
+GINAC_EXCOMPILER
+
 dnl Check for utilities needed by the different kinds of documentation.
 dnl Documentation needs only be built when extending it, so never mind if it
 dnl cannot find those helpers:
index 06bf854e3cd342f530cd4364804076f52deada6f..ef8d4d1421ad57b38b27b84691df47ccf4f3eee0 100644 (file)
@@ -7,8 +7,8 @@ TEXI = ginac-examples.texi
 
 info_TEXINFOS = $(TEXI)
 
-TXT = $(addsuffix .txt, $(basename $(TEXI)))
-HTML = $(addsuffix .html, $(basename $(TEXI)))
+TXT = ginac-examples.txt
+HTML = ginac-examples.html
 
 all: $(EXFILES)
        ${MAKEINFO} --no-split --no-headers $(srcdir)/$(TEXI) > $(TXT)
index d36fb8a7af30d4e5c4ea5b5d6a3f5f214eb4ee7c..d855fda6aec746bccc8faf6fe877098655e3506c 100644 (file)
@@ -8,9 +8,9 @@ if CONFIG_TEX
 if CONFIG_FIG2DEV
 
 # Graphics file conversion
-PNG = $(addsuffix .png, $(basename $(FIG)))
-EPS = $(addsuffix .eps, $(basename $(FIG)))
-PDF = $(addsuffix .pdf, $(basename $(FIG)))
+PNG = classhierarchy.png repnaive.png reppair.png repreal.png
+EPS = classhierarchy.eps repnaive.eps reppair.eps repreal.eps
+PDF = classhierarchy.pdf repnaive.pdf reppair.pdf repreal.pdf
 
 SUFFIXES = .fig .png .eps
 
index eed9fef391386ed71daa9d4c7a6791c359ec8fe3..2f160c7bfb16459bd1d18fd7c46fb9c43273ad27 100644 (file)
@@ -553,7 +553,7 @@ environment variable, like optimization, debugging information and
 warning levels.  If omitted, it defaults to @option{-g
 -O2}.@footnote{The @command{configure} script is itself generated from
 the file @file{configure.ac}.  It is only distributed in packaged
-releases of GiNaC.  If you got the naked sources, e.g. from CVS, you
+releases of GiNaC.  If you got the naked sources, e.g. from git, you
 must generate @command{configure} along with the various
 @file{Makefile.in} by using the @command{autoreconf} utility.  This will
 require a fair amount of support from your local toolchain, though.}
@@ -4420,10 +4420,7 @@ This function returns @code{true} when the expression matches the pattern
 and @code{false} if it doesn't. If used in the second form, the actual
 subexpressions matched by the wildcards get returned in the @code{repls}
 object as a list of relations of the form @samp{wildcard == expression}.
-If @code{match()} returns false, the state of @code{repls} is undefined.
-For reproducible results, the list should be empty when passed to
-@code{match()}, but it is also possible to find similarities in multiple
-expressions by passing in the result of a previous match.
+If @code{match()} returns false,  @code{repls} remains unmodified.
 
 The matching algorithm works as follows:
 
index a3de04aab9cd306eda820e8d7b50dadc492f3164..7a0633de19a18221f241292b21742416cdb29dce 100644 (file)
@@ -585,12 +585,18 @@ bool basic::match(const ex & pattern, lst & repl_lst) const
                if (!match_same_type(ex_to<basic>(pattern)))
                        return false;
 
+               // Even if the expression does not match the pattern, some of
+               // its subexpressions could match it. For example, x^5*y^(-1)
+               // does not match the pattern $0^5, but its subexpression x^5
+               // does. So, save repl_lst in order to not add bogus entries.
+               lst tmp_repl = repl_lst;
                // Otherwise the subexpressions must match one-to-one
                for (size_t i=0; i<nops(); i++)
-                       if (!op(i).match(pattern.op(i), repl_lst))
+                       if (!op(i).match(pattern.op(i), tmp_repl))
                                return false;
 
                // Looks similar enough, match found
+               repl_lst = tmp_repl;
                return true;
        }
 }
index 3e447354d814d87c1a04e71f2f71e99c4e6106e3..7a4d5e78cbc25fb4431f7807f9b424cd9bb6edd0 100644 (file)
@@ -1330,8 +1330,8 @@ ${power_switch_statement}
 
 std::vector<function_options> & function::registered_functions()
 {
-       static std::vector<function_options> * rf = new std::vector<function_options>;
-       return *rf;
+       static std::vector<function_options> rf = std::vector<function_options>();
+       return rf;
 }
 
 bool function::lookup_remember_table(ex & result) const
index bf5ce093165cb7b30d15f410f7f72e5f23582d2d..d85044d04bd1f311b2d26ad5ab8ccf0572d1ebe7 100644 (file)
@@ -3417,13 +3417,6 @@ namespace {
 
 // parameters and data for [Cra] algorithm
 const cln::cl_N lambda = cln::cl_N("319/320");
-int L1;
-int L2;
-std::vector<std::vector<cln::cl_N> > f_kj;
-std::vector<cln::cl_N> crB;
-std::vector<std::vector<cln::cl_N> > crG;
-std::vector<cln::cl_N> crX;
-
 
 void halfcyclic_convolute(const std::vector<cln::cl_N>& a, const std::vector<cln::cl_N>& b, std::vector<cln::cl_N>& c)
 {
@@ -3438,44 +3431,39 @@ void halfcyclic_convolute(const std::vector<cln::cl_N>& a, const std::vector<cln
 
 
 // [Cra] section 4
-void initcX(const std::vector<int>& s)
+static void initcX(std::vector<cln::cl_N>& crX,
+                  const std::vector<int>& s,
+                  const int L2)
 {
-       const int k = s.size();
-
-       crX.clear();
-       crG.clear();
-       crB.clear();
-
-       for (int i=0; i<=L2; i++) {
-               crB.push_back(bernoulli(i).to_cl_N() / cln::factorial(i));
-       }
+       std::vector<cln::cl_N> crB(L2 + 1);
+       for (int i=0; i<=L2; i++)
+               crB[i] = bernoulli(i).to_cl_N() / cln::factorial(i);
 
        int Sm = 0;
        int Smp1 = 0;
-       for (int m=0; m<k-1; m++) {
-               std::vector<cln::cl_N> crGbuf;
-               Sm = Sm + s[m];
+       std::vector<std::vector<cln::cl_N> > crG(s.size() - 1, std::vector<cln::cl_N>(L2 + 1));
+       for (int m=0; m < s.size() - 1; m++) {
+               Sm += s[m];
                Smp1 = Sm + s[m+1];
-               for (int i=0; i<=L2; i++) {
-                       crGbuf.push_back(cln::factorial(i + Sm - m - 2) / cln::factorial(i + Smp1 - m - 2));
-               }
-               crG.push_back(crGbuf);
+               for (int i = 0; i <= L2; i++)
+                       crG[m][i] = cln::factorial(i + Sm - m - 2) / cln::factorial(i + Smp1 - m - 2);
        }
 
        crX = crB;
 
-       for (int m=0; m<k-1; m++) {
-               std::vector<cln::cl_N> Xbuf;
-               for (int i=0; i<=L2; i++) {
-                       Xbuf.push_back(crX[i] * crG[m][i]);
-               }
+       for (std::size_t m = 0; m < s.size() - 1; m++) {
+               std::vector<cln::cl_N> Xbuf(L2 + 1);
+               for (int i = 0; i <= L2; i++)
+                       Xbuf[i] = crX[i] * crG[m][i];
+
                halfcyclic_convolute(Xbuf, crB, crX);
        }
 }
 
 
 // [Cra] section 4
-cln::cl_N crandall_Y_loop(const cln::cl_N& Sqk)
+static cln::cl_N crandall_Y_loop(const cln::cl_N& Sqk,
+                                const std::vector<cln::cl_N>& crX)
 {
        cln::cl_F one = cln::cl_float(1, cln::float_format(Digits));
        cln::cl_N factor = cln::expt(lambda, Sqk);
@@ -3493,11 +3481,9 @@ cln::cl_N crandall_Y_loop(const cln::cl_N& Sqk)
 
 
 // [Cra] section 4
-void calc_f(int maxr)
+static void calc_f(std::vector<std::vector<cln::cl_N> >& f_kj,
+                  const int maxr, const int L1)
 {
-       f_kj.clear();
-       f_kj.resize(L1);
-       
        cln::cl_N t0, t1, t2, t3, t4;
        int i, j, k;
        std::vector<std::vector<cln::cl_N> >::iterator it = f_kj.begin();
@@ -3523,7 +3509,8 @@ void calc_f(int maxr)
 
 
 // [Cra] (3.1)
-cln::cl_N crandall_Z(const std::vector<int>& s)
+static cln::cl_N crandall_Z(const std::vector<int>& s,
+                           const std::vector<std::vector<cln::cl_N> >& f_kj)
 {
        const int j = s.size();
 
@@ -3564,6 +3551,8 @@ cln::cl_N zeta_do_sum_Crandall(const std::vector<int>& s)
        std::vector<int> r = s;
        const int j = r.size();
 
+       std::size_t L1;
+
        // decide on maximal size of f_kj for crandall_Z
        if (Digits < 50) {
                L1 = 150;
@@ -3571,6 +3560,7 @@ cln::cl_N zeta_do_sum_Crandall(const std::vector<int>& s)
                L1 = Digits * 3 + j*2;
        }
 
+       std::size_t L2;
        // decide on maximal size of crX for crandall_Y
        if (Digits < 38) {
                L2 = 63;
@@ -3597,7 +3587,8 @@ cln::cl_N zeta_do_sum_Crandall(const std::vector<int>& s)
                }
        }
 
-       calc_f(maxr);
+       std::vector<std::vector<cln::cl_N> > f_kj(L1);
+       calc_f(f_kj, maxr, L1);
 
        const cln::cl_N r0factorial = cln::factorial(r[0]-1);
 
@@ -3611,12 +3602,13 @@ cln::cl_N zeta_do_sum_Crandall(const std::vector<int>& s)
                Srun -= skp1buf;
                r.pop_back();
 
-               initcX(r);
+               std::vector<cln::cl_N> crX;
+               initcX(crX, r, L2);
                
                for (int q=0; q<skp1buf; q++) {
                        
-                       cln::cl_N pp1 = crandall_Y_loop(Srun+q-k);
-                       cln::cl_N pp2 = crandall_Z(rz);
+                       cln::cl_N pp1 = crandall_Y_loop(Srun+q-k, crX);
+                       cln::cl_N pp2 = crandall_Z(rz, f_kj);
 
                        rz.front()--;
                        
@@ -3630,9 +3622,11 @@ cln::cl_N zeta_do_sum_Crandall(const std::vector<int>& s)
        }
        rz.insert(rz.begin(), r.back());
 
-       initcX(rz);
+       std::vector<cln::cl_N> crX;
+       initcX(crX, rz, L2);
 
-       res = (res + crandall_Y_loop(S-j)) / r0factorial + crandall_Z(rz);
+       res = (res + crandall_Y_loop(S-j, crX)) / r0factorial
+               + crandall_Z(rz, f_kj);
 
        return res;
 }
index a43cc7ade4d86c4d9b05907d08083fcde2a04998..5221580d47a87939694d8f1f4c274bc91c67f176 100644 (file)
@@ -20,6 +20,19 @@ do { \
        throw exception(err.str()); \
 } while (0)
 
+#define Parse_error_(message) \
+do { \
+       std::ostringstream err; \
+       err << "GiNaC: parse error at line " << scanner->line_num << \
+               ", column " << scanner->column << ": "; \
+       err << message << std::endl; \
+       err << '[' << __PRETTY_FUNCTION__ << "(" << __FILE__ << ':' << __LINE__ << ")]" << std::endl; \
+       throw parse_error(err.str(), scanner->line_num, scanner->column); \
+} while (0)
+
+#define Parse_error(message) \
+       Parse_error_(message << ", got: " << scanner->tok2str(token))
+
 #define bug(message) bail_out(std::logic_error, message)
 
 #define dout(condition, message) \
index ed1f894fea381bdc9c553d9a2811ff12b1697bcb..d8c49b8cf4b35da972b19074b506aa0380c3725e 100644 (file)
@@ -126,6 +126,21 @@ void lexer::switch_input(std::istream* in)
        input = in;
        line_num = 0;
        column = 0;
+       c = ' ';
+}
+
+/// Symbolic name of current token (for error reporting)
+std::string lexer::tok2str(const int tok) const
+{
+       switch (tok) {
+               case lexer::token_type::identifier:
+               case lexer::token_type::number:
+                       return std::string("\"") + str + "\"";
+               case lexer::token_type::eof:
+                       return std::string("EOF");
+               default:
+                       return std::string("\"") + char(tok) + "\"";
+       }
 }
 
 } // namespace GiNaC
index b53d08f38d4dddf383d7499b769e21a02f58c241..0a00ed3936dbd2befc02d94e8a4d5778176d958c 100644 (file)
@@ -37,6 +37,9 @@ public:
 
                };
        };
+       
+       /// Symbolic name of the token (for error reporting)
+       std::string tok2str(const int tok) const;
 };
 
 } // namespace GiNaC
index b33261c2c9ed1084ca3296c767d6c9a585a5d384..1e905cf5ff1133e4d2074cf05dd5992a9d813467 100644 (file)
@@ -30,7 +30,7 @@ ex parser::parse_identifier_expr()
                                break;
 
                        if (token != ',')
-                               throw std::invalid_argument("Expected ')' or ',' in argument list");
+                               Parse_error("expected ')' or ',' in argument list");
 
                        get_next_tok();
                }
@@ -40,9 +40,8 @@ ex parser::parse_identifier_expr()
        prototype the_prototype = make_pair(name, args.size());
        prototype_table::const_iterator reader = funcs.find(the_prototype);
        if (reader == funcs.end()) {
-               bail_out(std::invalid_argument,
-                       "no function \"" << name << "\" with " << args.size()
-                       << " arguments");
+               Parse_error_("no function \"" << name << "\" with " <<
+                            args.size() << " arguments");
        }
        ex ret = reader->second(args);
        return ret;
@@ -55,7 +54,7 @@ ex parser::parse_paren_expr()
        ex e = parse_expression();
 
        if (token != ')')
-               throw std::invalid_argument("parser::parse_paren_expr: expected ')'");
+               Parse_error("expected ')'");
        get_next_tok();  // eat ).
        return e;
 }
@@ -74,10 +73,7 @@ ex parser::parse_unary_expr(const int s)
                case '+':
                        return v;
                default:
-                       throw std::invalid_argument(
-                                       std::string(__func__)
-                                       + ": invalid unary operator \""
-                                       + char(s) + "\"");
+                       Parse_error_("invalid unary operator \"" << char(s) << "\"");
        }
 }
 
@@ -98,12 +94,8 @@ ex parser::parse_primary()
                case lexer::token_type::literal:
                         return parse_literal_expr();
                case lexer::token_type::eof:
-                        bail_out(std::invalid_argument, "got EOF while parsing the expression");
                default:
-                        bail_out(std::invalid_argument, "unknown token " <<
-                               token << " (\"" << 
-                               (token ? std::string("") + char(token) : "NULL")
-                               << "\")");
+                        Parse_error("unexpected token");
        }
 }
 
index 81b7847694e43f1b437fbe1cdc8fef2b3503e420..3e10b8fc016bacc9a685918c969a89d36c451841 100644 (file)
@@ -9,6 +9,18 @@ namespace GiNaC
 
 class lexer;
 
+class parse_error : public std::invalid_argument
+{
+public:
+       const std::size_t line;
+       const std::size_t column;
+       parse_error(const std::string& what_,
+                   const std::size_t line_ = 0,
+                   const std::size_t column_ = 0) throw () :
+               std::invalid_argument(what_), line(line_), column(column_)
+       { }
+};
+
 /**
  * Recursive descent parser for GiNaC expressions.
  */
index faa89d383defbcd4eebe5c194bc58182d0a74c50..701a27e7b7c42a56fe229c88093be052853ecc56 100644 (file)
@@ -183,8 +183,8 @@ void remember_table::init_table()
 
 std::vector<remember_table> & remember_table::remember_tables()
 {
-       static std::vector<remember_table> * rt = new std::vector<remember_table>;
-       return *rt;
+       static std::vector<remember_table> rt = std::vector<remember_table>();
+       return rt;
 }
 
 } // namespace GiNaC
index f1b2be6e13885b3cc337c7cde26e9cb689894559..6eedfef3b6142b0fd4e53107ced16ccac916d830 100644 (file)
@@ -45,7 +45,7 @@ GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(symbol, basic,
 // symbol
 
 symbol::symbol()
- : inherited(&symbol::tinfo_static), asexinfop(new assigned_ex_info), serial(next_serial++), name(autoname_prefix() + ToString(serial)), TeX_name(name), domain(domain::complex), ret_type(return_types::commutative), ret_type_tinfo(&symbol::tinfo_static)
+ : inherited(&symbol::tinfo_static), serial(next_serial++), name(autoname_prefix() + ToString(serial)), TeX_name(name), domain(domain::complex), ret_type(return_types::commutative), ret_type_tinfo(&symbol::tinfo_static)
 {
        setflag(status_flags::evaluated | status_flags::expanded);
 }
@@ -73,25 +73,25 @@ possymbol::possymbol()
 // symbol
 
 symbol::symbol(const std::string & initname, unsigned domain)
- : inherited(&symbol::tinfo_static), asexinfop(new assigned_ex_info), serial(next_serial++), name(initname), TeX_name(default_TeX_name()), domain(domain), ret_type(return_types::commutative), ret_type_tinfo(&symbol::tinfo_static)
+ : inherited(&symbol::tinfo_static), serial(next_serial++), name(initname), TeX_name(default_TeX_name()), domain(domain), ret_type(return_types::commutative), ret_type_tinfo(&symbol::tinfo_static)
 {
        setflag(status_flags::evaluated | status_flags::expanded);
 }
 
 symbol::symbol(const std::string & initname, unsigned rt, tinfo_t rtt, unsigned domain)
- : inherited(&symbol::tinfo_static), asexinfop(new assigned_ex_info), serial(next_serial++), name(initname), TeX_name(default_TeX_name()), domain(domain), ret_type(rt), ret_type_tinfo(rtt)
+ : inherited(&symbol::tinfo_static), serial(next_serial++), name(initname), TeX_name(default_TeX_name()), domain(domain), ret_type(rt), ret_type_tinfo(rtt)
 {
        setflag(status_flags::evaluated | status_flags::expanded);
 }
 
 symbol::symbol(const std::string & initname, const std::string & texname, unsigned domain)
- : inherited(&symbol::tinfo_static), asexinfop(new assigned_ex_info), serial(next_serial++), name(initname), TeX_name(texname), domain(domain), ret_type(return_types::commutative), ret_type_tinfo(&symbol::tinfo_static)
+ : inherited(&symbol::tinfo_static), serial(next_serial++), name(initname), TeX_name(texname), domain(domain), ret_type(return_types::commutative), ret_type_tinfo(&symbol::tinfo_static)
 {
        setflag(status_flags::evaluated | status_flags::expanded);
 }
 
 symbol::symbol(const std::string & initname, const std::string & texname, unsigned rt, tinfo_t rtt, unsigned domain)
- : inherited(&symbol::tinfo_static), asexinfop(new assigned_ex_info), serial(next_serial++), name(initname), TeX_name(texname), domain(domain), ret_type(rt), ret_type_tinfo(rtt)
+ : inherited(&symbol::tinfo_static),  serial(next_serial++), name(initname), TeX_name(texname), domain(domain), ret_type(rt), ret_type_tinfo(rtt)
 {
        setflag(status_flags::evaluated | status_flags::expanded);
 }
@@ -130,7 +130,7 @@ possymbol::possymbol(const std::string & initname, const std::string & texname,
 
 /** Construct object from archive_node. */
 symbol::symbol(const archive_node &n, lst &sym_lst)
- : inherited(n, sym_lst), asexinfop(new assigned_ex_info), serial(next_serial++)
+ : inherited(n, sym_lst), serial(next_serial++)
 {
        if (!n.find_string("name", name))
                name = autoname_prefix() + ToString(serial);
@@ -228,22 +228,6 @@ bool symbol::info(unsigned inf) const
        return inherited::info(inf);
 }
 
-ex symbol::eval(int level) const
-{
-       if (level == -max_recursion_level)
-               throw(std::runtime_error("max recursion level reached"));
-       
-       if (asexinfop->is_assigned) {
-               setflag(status_flags::evaluated);
-               if (level==1)
-                       return (asexinfop->assigned_expression);
-               else
-                       return (asexinfop->assigned_expression).eval(level);
-       } else {
-               return this->hold();
-       }
-}
-
 ex symbol::conjugate() const
 {
        if (this->domain == domain::complex) {
@@ -318,32 +302,14 @@ unsigned symbol::calchash() const
 // non-virtual functions in this class
 //////////
 
-// public
-
-void symbol::assign(const ex & value)
-{
-       asexinfop->is_assigned = true;
-       asexinfop->assigned_expression = value;
-       clearflag(status_flags::evaluated | status_flags::expanded);
-}
-
-void symbol::unassign()
-{
-       if (asexinfop->is_assigned) {
-               asexinfop->is_assigned = false;
-               asexinfop->assigned_expression = _ex0;
-       }
-       setflag(status_flags::evaluated | status_flags::expanded);
-}
-
 // private
 
 /** Symbols not constructed with a string get one assigned using this
  *  prefix and a number. */
-std::string & symbol::autoname_prefix()
+std::string& symbol::autoname_prefix()
 {
-       static std::string *s = new std::string("symbol");
-       return *s;
+       static std::string s("symbol");
+       return s;
 }
 
 /** Return default TeX name for symbol. This recognizes some greek letters. */
@@ -376,13 +342,4 @@ std::string symbol::default_TeX_name() const
 
 unsigned symbol::next_serial = 0;
 
-//////////
-// subclass assigned_ex_info
-//////////
-
-/** Default ctor.  Defaults to unassigned. */
-symbol::assigned_ex_info::assigned_ex_info() throw() : is_assigned(false)
-{
-}
-
 } // namespace GiNaC
index e38ed6763bbde01c7750099eaaf31ba9b8c09b2b..c174ad5f5136b10e83d8dc0dc1cf526b07b142d6 100644 (file)
 namespace GiNaC {
 
 /** Basic CAS symbol.  It has a name because it must know how to output itself.
- *  It may be assigned an expression, but this feature is only intended for
- *  programs like 'ginsh' that want to associate symbols with expressions.
- *  If you want to replace symbols by expressions in your code, you should
- *  use ex::subs() or use objects of class ex instead of class symbol in the
- *  first place. */
+ */
 class symbol : public basic
 {
        GINAC_DECLARE_REGISTERED_CLASS(symbol, basic)
@@ -43,16 +39,6 @@ class symbol : public basic
        friend class realsymbol;
        friend class possymbol;
 
-// types
-       
-       /** Symbols as keys to expressions - only for ginsh. */
-       class assigned_ex_info : public refcounted {
-       public:
-               assigned_ex_info() throw();  ///< Default ctor
-               bool is_assigned;            ///< True if there is an expression assigned
-               ex assigned_expression;      ///< The actual expression
-       };
-
 // member functions
        
        // other constructors
@@ -66,7 +52,7 @@ public:
        // functions overriding virtual functions from base classes
 public:
        bool info(unsigned inf) const;
-       ex eval(int level = 0) const;
+       ex eval(int level = 0) const { return *this; } // for performance reasons
        ex evalf(int level = 0) const { return *this; } // overwrites basic::evalf() for performance reasons
        ex series(const relational & s, int order, unsigned options = 0) const;
        ex subs(const exmap & m, unsigned options = 0) const { return subs_one_level(m, options); } // overwrites basic::subs() for performance reasons
@@ -86,8 +72,6 @@ protected:
        
        // non-virtual functions in this class
 public:
-       void assign(const ex & value);
-       void unassign();
        void set_name(const std::string & n) { name = n; }
        std::string get_name() const { return name; }
        unsigned get_domain() const { return domain; }
@@ -103,7 +87,6 @@ private:
 // member variables
 
 protected:
-       ptr<assigned_ex_info> asexinfop; ///< assigned expression, only for private use by ginsh
        unsigned serial;                 ///< unique serial number for comparison
        std::string name;                ///< printname of this symbol
        std::string TeX_name;            ///< LaTeX name of this symbol
@@ -161,10 +144,6 @@ template<> inline bool is_exactly_a<possymbol>(const basic & obj)
        return domain == domain::positive;
 }
 
-// wrapper functions around member functions
-inline void unassign(symbol & symarg)
-{ symarg.unassign(); }
-
 } // namespace GiNaC
 
 #endif // ndef __GINAC_SYMBOL_H__
index b55948b54c56a574f5c464140d0bccc922f1cfac..f44ed9fa821fd6fbcb8bd4c08c029ad8c3899fbf 100644 (file)
@@ -388,9 +388,58 @@ library_init::library_init()
 library_init::~library_init()
 {
        if (--count==0) {
-               // In theory, we would have to clean up here.  But since we were
-               // only initializing memory in the ctor and that memory is reclaimed
-               // anyways by the OS when the program exits, we skip this.
+               // It's really necessary to clean up, since the program
+               // lifetime might not be the same as libginac.{so,dll} one
+               // (e.g. consider // dlopen/dlsym/dlclose sequence).
+               delete _num120_p;
+               delete _num_120_p;
+               delete _num60_p;
+               delete _num_60_p;
+               delete _num48_p;
+               delete _num_48_p;
+               delete _num30_p;
+               delete _num_30_p;
+               delete _num25_p;
+               delete _num_25_p;
+               delete _num24_p;
+               delete _num_24_p;
+               delete _num20_p;
+               delete _num_20_p;
+               delete _num18_p;
+               delete _num_18_p;
+               delete _num15_p;
+               delete _num_15_p;
+               delete _num12_p;
+               delete _num_12_p;
+               delete _num11_p;
+               delete _num_11_p;
+               delete _num10_p;
+               delete _num_10_p;
+               delete _num9_p;
+               delete _num_9_p;
+               delete _num8_p;
+               delete _num_8_p;
+               delete _num7_p;
+               delete _num_7_p;
+               delete _num6_p;
+               delete _num_6_p;
+               delete _num5_p;
+               delete _num_5_p;
+               delete _num4_p;
+               delete _num_4_p;
+               delete _num3_p;
+               delete _num_3_p;
+               delete _num2_p;
+               delete _num_2_p;
+               delete _num1_p;
+               delete _num_1_p;
+               delete _num1_2_p;
+               delete _num_1_2_p;
+               delete _num1_3_p;
+               delete _num_1_3_p;
+               delete _num1_4_p;
+               delete _num_1_4_p;
+               delete _num0_p;
        }
 }
 
index a4af3300e38d8c9d45370a30d908513a6759c6f2..3c293ea8c5e2e3f7b42391e701f780d3e064acdd 100644 (file)
 #ifndef __GINAC_UTILS_H__
 #define __GINAC_UTILS_H__
 
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
 
 #include <string>
 #include <functional>
+#ifdef HAVE_STDINT_H
+#include <stdint.h> // for uintptr_t
+#endif
 
 #include "assertion.h"
 
@@ -65,12 +70,8 @@ inline int compare_pointers(const T * a, const T * b)
        return 0;
 }
 
-#if SIZEOF_VOID_P == SIZEOF_INT
-typedef unsigned int p_int;
-#elif SIZEOF_VOID_P == SIZEOF_LONG
-typedef unsigned long p_int;
-#elif SIZEOF_VOID_P == SIZEOF_LONG_LONG
-typedef unsigned long long p_int;
+#ifdef HAVE_STDINT_H
+typedef uintptr_t p_int;
 #else
 typedef unsigned long p_int;
 #endif
@@ -80,24 +81,26 @@ inline unsigned golden_ratio_hash(p_int n)
 {
        // This function works much better when fast arithmetic with at
        // least 64 significant bits is available.
-#if SIZEOF_LONG >= 8
+       if (sizeof(long) >= 8) {
        // So 'long' has 64 bits.  Excellent!  We prefer it because it might be
        // more efficient than 'long long'.
        unsigned long l = n * 0x4f1bbcddUL;
        return (unsigned)l;
-#elif SIZEOF_LONG_LONG >= 8
+       }
+#ifdef HAVE_LONG_LONG
+       else if (sizeof(long long) >= 8) {
        // This requires 'long long' (or an equivalent 64 bit type)---which is,
        // unfortunately, not ANSI-C++-compliant.
        // (Yet C99 demands it, which is reason for hope.)
        unsigned long long l = n * 0x4f1bbcddULL;
        return (unsigned)l;
-#else
+       }
+#endif
        // Without a type with 64 significant bits do the multiplication manually
        // by splitting n up into the lower and upper two bytes.
        const unsigned n0 = (n & 0x0000ffffU);
        const unsigned n1 = (n & 0xffff0000U) >> 16;
        return (n0 * 0x0000bcddU) + ((n1 * 0x0000bcddU + n0 * 0x00004f1bU) << 16);
-#endif
 }
 
 /* Compute the sign of a permutation of a container, with and without an
index af18f4e7c51485ca88425131ad25e88de26b4ad2..90a60fc13d06acc283dffb16ba4d61721e493327 100644 (file)
@@ -397,8 +397,8 @@ detail here. Please refer to the GiNaC documentation.
 .BI transpose( matrix )
 \- transpose of a matrix
 .br
-.BI unassign( symbol )
-\- unassign an assigned symbol
+.BI unassign( 'symbol' )
+\- unassign an assigned symbol (mind the quotes, please!)
 .br
 .BI unit( expression ", " symbol )
 \- unit part of a polynomial
index b8c6875a2f96da32fb99817c3e82c5c5334222b7..b059172ef5166e3b94a6ad1b3690d3e9c9c1088d 100644 (file)
 
 #define YYERROR_VERBOSE 1
 
-#ifdef REALLY_HAVE_LIBREADLINE
+#ifdef HAVE_LIBREADLINE
 // Original readline settings
 static int orig_completion_append_character;
-#if (GINAC_RL_VERSION_MAJOR < 4) || (GINAC_RL_VERSION_MAJOR == 4 && GINAC_RL_VERSION_MINOR < 2)
-static char *orig_basic_word_break_characters;
-#else
 static const char *orig_basic_word_break_characters;
-#endif
 
-#if (GINAC_RL_VERSION_MAJOR >= 5)
+#if (RL_VERSION_MAJOR >= 5)
 #define GINAC_RL_COMPLETER_CAST(a) const_cast<char *>((a))
 #else
 #define GINAC_RL_COMPLETER_CAST(a) (a)
 #endif
-#endif // REALLY_HAVE_LIBREADLINE
+#endif // HAVE_LIBREADLINE
 
 // Expression stack for %, %% and %%%
 static void push(const ex &e);
 static ex exstack[3];
+// Assigned symbols
+static exmap assigned_symbol_table;
 
 // Start and end time for the time() function
 #ifdef HAVE_RUSAGE
@@ -237,7 +235,13 @@ line       : ';'
        ;
 
 exp    : T_NUMBER              {$$ = $1;}
-       | T_SYMBOL              {$$ = $1.eval();}
+       | T_SYMBOL              {
+               exmap::const_iterator i = assigned_symbol_table.find($1);
+               if (i == assigned_symbol_table.end())
+                       $$ = $1;
+               else
+                       $$ = i->second.eval();
+       }
        | '\'' T_SYMBOL '\''    {$$ = $2;}
        | T_LITERAL             {$$ = $1;}
        | T_DIGITS              {$$ = $1;}
@@ -253,7 +257,7 @@ exp : T_NUMBER              {$$ = $1;}
                }
        }
        | T_DIGITS '=' T_NUMBER {$$ = $3; Digits = ex_to<numeric>($3).to_int();}
-       | T_SYMBOL '=' exp      {$$ = $3; const_cast<symbol&>(ex_to<symbol>($1)).assign($3);}
+       | T_SYMBOL '=' exp      {$$ = $3; assigned_symbol_table[$1] = $3; }
        | exp T_EQUAL exp       {$$ = $1 == $3;}
        | exp T_NOTEQ exp       {$$ = $1 != $3;}
        | exp '<' exp           {$$ = $1 < $3;}
@@ -567,7 +571,9 @@ static ex f_transpose(const exprseq &e)
 static ex f_unassign(const exprseq &e)
 {
        CHECK_ARG(0, symbol, unassign);
-       const_cast<symbol&>(ex_to<symbol>(e[0])).unassign();
+       exmap::iterator i = assigned_symbol_table.find(e[0]);
+       if (i != assigned_symbol_table.end())
+               assigned_symbol_table.erase(i);
        return e[0];
 }
 
@@ -854,7 +860,7 @@ static char *fcn_generator(const char *text, int state)
        return NULL;
 }
 
-#ifdef REALLY_HAVE_LIBREADLINE
+#ifdef HAVE_LIBREADLINE
 static char **fcn_completion(const char *text, int start, int end)
 {
        if (rl_line_buffer[0] == '!') {
@@ -862,24 +868,27 @@ static char **fcn_completion(const char *text, int start, int end)
                rl_completion_append_character = orig_completion_append_character;
                rl_basic_word_break_characters = orig_basic_word_break_characters;
                rl_completer_word_break_characters = GINAC_RL_COMPLETER_CAST(rl_basic_word_break_characters);
-#if (GINAC_RL_VERSION_MAJOR < 4) || (GINAC_RL_VERSION_MAJOR == 4 && GINAC_RL_VERSION_MINOR < 2)
-               return completion_matches(const_cast<char *>(text), (CPFunction *)filename_completion_function);
-#else
                return rl_completion_matches(text, rl_filename_completion_function);
-#endif
        } else {
                // Otherwise, complete function names
                rl_completion_append_character = '(';
                rl_basic_word_break_characters = " \t\n\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~";
                rl_completer_word_break_characters = GINAC_RL_COMPLETER_CAST(rl_basic_word_break_characters);
-#if (GINAC_RL_VERSION_MAJOR < 4) || (GINAC_RL_VERSION_MAJOR == 4 && GINAC_RL_VERSION_MINOR < 2)
-               return completion_matches(const_cast<char *>(text), (CPFunction *)fcn_generator);
-#else
                return rl_completion_matches(text, fcn_generator);
-#endif
        }
 }
-#endif // REALLY_HAVE_LIBREADLINE
+#endif // HAVE_LIBREADLINE
+
+static void ginsh_readline_init(char* name)
+{
+#ifdef HAVE_LIBREADLINE
+       // Init readline completer
+       rl_readline_name = name;
+       rl_attempted_completion_function = fcn_completion;
+       orig_completion_append_character = rl_completion_append_character;
+       orig_basic_word_break_characters = rl_basic_word_break_characters;
+#endif // HAVE_LIBREADLINE
+}
 
 void greeting(void)
 {
@@ -900,6 +909,7 @@ int main(int argc, char **argv)
        // Print banner in interactive mode
        if (isatty(0)) 
                greeting();
+       assigned_symbol_table = exmap();
 
        // Init function table
        insert_fcns(builtin_fcns);
@@ -923,17 +933,7 @@ int main(int argc, char **argv)
        insert_help("print_latex", "print_latex(expression) - prints a LaTeX representation of the given expression");
        insert_help("print_csrc", "print_csrc(expression) - prints a C source code representation of the given expression");
 
-#ifdef REALLY_HAVE_LIBREADLINE
-       // Init readline completer
-       rl_readline_name = argv[0];
-#if (GINAC_RL_VERSION_MAJOR < 4) || (GINAC_RL_VERSION_MAJOR == 4 && GINAC_RL_VERSION_MINOR < 2)
-       rl_attempted_completion_function = (CPPFunction *)fcn_completion;
-#else
-       rl_attempted_completion_function = fcn_completion;
-#endif
-       orig_completion_append_character = rl_completion_append_character;
-       orig_basic_word_break_characters = rl_basic_word_break_characters;
-#endif
+       ginsh_readline_init(argv[0]);
 
        // Init input file list, open first file
        num_files = argc - 1;