merging 1.2 branch into main trunk
authorChristian Bauer <Christian.Bauer@uni-mainz.de>
Wed, 2 Jul 2003 20:46:56 +0000 (20:46 +0000)
committerChristian Bauer <Christian.Bauer@uni-mainz.de>
Wed, 2 Jul 2003 20:46:56 +0000 (20:46 +0000)
144 files changed:
INSTALL
NEWS
check/Makefile.am
check/check_inifcns.cpp
check/check_lsolve.cpp
check/check_matrices.cpp
check/check_numeric.cpp
check/exam_archive.cpp
check/exam_clifford.cpp
check/exam_color.cpp
check/exam_differentiation.cpp
check/exam_indexed.cpp
check/exam_inifcns.cpp
check/exam_lsolve.cpp
check/exam_matrices.cpp
check/exam_misc.cpp
check/exam_normalization.cpp
check/exam_numeric.cpp
check/exam_paranoia.cpp
check/exam_polygcd.cpp
check/exam_powerlaws.cpp
check/exam_pseries.cpp
check/time_antipode.cpp
check/time_dennyfliegner.cpp
check/time_fateman_expand.cpp
check/time_gammaseries.cpp
check/time_lw_A.cpp
check/time_lw_B.cpp
check/time_lw_C.cpp
check/time_lw_D.cpp
check/time_lw_E.cpp
check/time_lw_F.cpp
check/time_lw_G.cpp
check/time_lw_H.cpp
check/time_lw_IJKL.cpp
check/time_lw_M1.cpp
check/time_lw_M2.cpp
check/time_lw_N.cpp
check/time_lw_O.cpp
check/time_lw_P.cpp
check/time_lw_Pprime.cpp
check/time_lw_Q.cpp
check/time_lw_Qprime.cpp
check/time_toeplitz.cpp
check/time_vandermonde.cpp
check/timer.cpp
check/timer.h [new file with mode: 0644]
check/times.h
configure.ac
debian/changelog
debian/control
debian/copyright
debian/docs [new file with mode: 0644]
debian/libginac-dev.postinst
debian/libginac1.1.dirs [moved from debian/dirs with 100% similarity]
debian/libginac1.1.files [new file with mode: 0644]
debian/postinst [deleted file]
debian/rules
debian/shlibs
doc/reference/DoxyfileHTML
doc/reference/DoxyfileTEX
doc/reference/Makefile.am
doc/tutorial/ginac.texi
ginac.m4
ginac/Makefile.am
ginac/add.cpp
ginac/add.h
ginac/archive.cpp
ginac/archive.h
ginac/basic.cpp
ginac/basic.h
ginac/clifford.cpp
ginac/clifford.h
ginac/color.cpp
ginac/color.h
ginac/constant.cpp
ginac/constant.h
ginac/container.h [new file with mode: 0644]
ginac/container.pl [deleted file]
ginac/ex.cpp
ginac/ex.h
ginac/expair.h
ginac/expairseq.cpp
ginac/expairseq.h
ginac/exprseq.cpp [moved from ginac/exprseq_suppl.cpp with 75% similarity]
ginac/exprseq.h [new file with mode: 0644]
ginac/fail.cpp
ginac/fail.h
ginac/fderivative.cpp
ginac/fderivative.h
ginac/flags.h
ginac/function.pl
ginac/idx.cpp
ginac/idx.h
ginac/indexed.cpp
ginac/indexed.h
ginac/inifcns.cpp
ginac/inifcns.h
ginac/inifcns_gamma.cpp
ginac/inifcns_trans.cpp
ginac/inifcns_zeta.cpp
ginac/input_lexer.h
ginac/input_parser.yy
ginac/lst.cpp [moved from ginac/lst_suppl.cpp with 79% similarity]
ginac/lst.h [new file with mode: 0644]
ginac/matrix.cpp
ginac/matrix.h
ginac/mul.cpp
ginac/mul.h
ginac/ncmul.cpp
ginac/ncmul.h
ginac/normal.cpp
ginac/numeric.cpp
ginac/numeric.h
ginac/operators.cpp
ginac/operators.h
ginac/power.cpp
ginac/power.h
ginac/print.cpp
ginac/print.h
ginac/pseries.cpp
ginac/pseries.h
ginac/ptr.h [new file with mode: 0644]
ginac/registrar.cpp
ginac/registrar.h
ginac/relational.cpp
ginac/relational.h
ginac/remember.cpp
ginac/remember.h
ginac/structure.cpp
ginac/structure.h
ginac/structure.pl [deleted file]
ginac/symbol.cpp
ginac/symbol.h
ginac/symmetry.cpp
ginac/symmetry.h
ginac/tensor.cpp
ginac/tensor.h
ginac/utils.cpp
ginac/utils.h
ginac/wildcard.cpp
ginac/wildcard.h
ginsh/ginsh_lexer.ll
ginsh/ginsh_parser.yy

diff --git a/INSTALL b/INSTALL
index 7c6258f..e1881a3 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -6,11 +6,11 @@ one of the following FTP-sites:
   * <ftp://ftp.santafe.edu/pub/gnu/>,
   * <ftp://ftp.ilog.fr/pub/Users/haible/gnu/> or
   * <ftp://ftpthep.physik.uni-mainz.de/pub/gnu/>.
-You will also need a decent ANSI-compliant C++-compiler.  We use
-`post-EGCS' GCC, i.e GCC >= 2.95 for development so if you have a
-different compiler you are on your own.  Note that you may have to use
-the same compiler you compiled CLN with because of differing
-name-mangling schemes.
+You will also need a decent ANSI-compliant C++-compiler.  We recommend
+the C++ compiler from the GNU compiler collection, GCC >= 3.0.  If you
+have a different or older compiler you are on your own.  Note that you
+may have to use the same compiler you compiled CLN with because of
+differing name-mangling schemes.
 
 
 INSTALLATION
@@ -25,9 +25,10 @@ As with any autoconfiguring GNU software, installation is as easy as this:
  # make install
 
 Known to work with:
-  - Linux on x86, Alpha and Sparc using GCC 2-95.x.
+  - Linux on x86, Alpha and Sparc using GCC 3.0.x, 3.1 and 3.2.
 Known not to work with:
-  - GCC 2.7.x or earlier because proper exception support is missing there.
+  - GCC 2.96 or earlier because proper exception and standard library support
+    is missing there.
 
 The "configure" script can be given a number of options to enable and
 disable various features. For a complete list, type:
@@ -67,8 +68,7 @@ Problems with CLN
 You should use at least CLN-1.1, since during the development of
 GiNaC various bugs have been discovered and fixed in earlier versions.
 Please install CLN properly on your system before continuing with
-GiNaC.  When using GCC3 as compiler please use at least CLN-1.1.1
-since some parts of GiNaC won't build with CLN-1.1.
+GiNaC.
 
 Problems with building ginsh
 ----------------------------
@@ -86,12 +86,4 @@ Problems with missing standard header files
 Building GiNaC requires many standard header files.  If you get a
 configure error complaining about such missing files your compiler and
 library are probably not up to date enough and it's no worth
-continuing.  If the only file missing is <sstream>, however, there is
-a solution.  GCC-2.95.2 and earlier don't ship with this file.  A
-working implementation has been available since GCC-2.95.3.  GCC-3.0
-and later have an even better, fully standard-conforming
-implementation, by default.  If you are stuck with GCC-2.95.2 or
-earlier and you cannot upgrade your compiler we recommend obtaining
-the libstdc++-v2 <sstream> header written by Magnus Fromreide.  It was
-posted to the gcc-patches mailing list on November 21 2000:
-<http://gcc.gnu.org/ml/gcc-patches/2000-11/msg01152.html>.
+continuing.
diff --git a/NEWS b/NEWS
index d675dc1..13d6253 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,12 +1,40 @@
 This file records noteworthy changes.
 
-1.0.15 (<date>)
-* Added on-line help and Tab-completion for print(), iprint(), print_latex()
-  and print_csrc() in ginsh.
-* Fixed a bug in the unarchiving of sums and products: terms were not
-  reordered in a canonical way.
-* Fixed a bug in normal()/numer_denom(): denominator was not made unit
-  normal if it was a simple number
+1.2.0 (<insert date>)
+* Added a structure<T> template class for the easy creation of user-defined
+  algebraic classes.
+* Many internal reorganizations and optimizations.
+* Caveats for class implementors:
+   - basic::copy() and basic::destroy() are gone; classes derived from
+     basic can use the defaults for the assignment operator and copy
+     constructor.
+   - basic::subs() now descends into subexpressions (if accessible via
+     nops()/op()/let_op()). If you have a custom implementation of subs()
+     that calls basic::subs() after substituting subexpressions, this needs
+     to be changed to a call to subs_one_level().
+
+1.1.0 (3 April 2003)
+* Removed deprecated macros is_ex_a, is_ex_exactly_a and friends for good.
+* The scalar_products mechanism allows the specification of an index dimension.
+* Removed dirac_gamma6/7().
+* Added ex::to_polynomial().
+* subs() accepts an optional "options" argument. The option
+  subs_option::subs_algebraic enables "smart" substitutions in products and
+  powers.
+* Added stream manipulators "dflt", "latex", "python", "python_repr", "tree",
+  "csrc", "csrc_float", "csrc_double", "csrc_cl_N", "index_dimensions" and
+  "no_index_dimensions" to control the output format. Calling basic::print()
+  directly is now deprecated.
+* Made the hashing more simple and efficient.
+* Caveats for class implementors:
+   - basic::subs(): third argument changed from "bool" to "unsigned"
+   - unarchiving constructor and basic::unarchive(): "const" removed from
+     second argument
+   - basic::let_op() should only be implemented if write access to
+     subexpressions is desired
+   - simplify_ncmul() renamed to eval_ncmul()
+   - simplified_ncmul() renamed to hold_ncmul()
+   - nonsimplified_ncmul() renamed to reeval_ncmul()
 
 1.0.14 (1 March 2003)
 * Improved the C-source output: complex numbers are printed correctly (using
index bf25465..fcc2770 100644 (file)
@@ -20,7 +20,7 @@ times_SOURCES = time_dennyfliegner.cpp time_gammaseries.cpp \
   time_lw_H.cpp time_lw_IJKL.cpp time_lw_M1.cpp time_lw_M2.cpp time_lw_N.cpp \
   time_lw_O.cpp time_lw_P.cpp time_lw_Pprime.cpp time_lw_Q.cpp \
   time_lw_Qprime.cpp time_antipode.cpp time_fateman_expand.cpp \
-  timer.cpp times.cpp times.h
+  timer.cpp timer.h times.cpp times.h
 times_LDADD = ../ginac/libginac.la
 
 INCLUDES = -I$(srcdir)/../ginac -I../ginac
index 3ba8461..81497cb 100644 (file)
@@ -24,7 +24,7 @@
 #include "checks.h"
 
 /* Some tests on the sine trigonometric function. */
-static unsigned inifcns_check_sin(void)
+static unsigned inifcns_check_sin()
 {
        unsigned result = 0;
        bool errorflag = false;
@@ -79,7 +79,7 @@ static unsigned inifcns_check_sin(void)
 }
 
 /* Simple tests on the cosine trigonometric function. */
-static unsigned inifcns_check_cos(void)
+static unsigned inifcns_check_cos()
 {
        unsigned result = 0;
        bool errorflag;
@@ -133,7 +133,7 @@ static unsigned inifcns_check_cos(void)
 }
 
 /* Simple tests on the tangent trigonometric function. */
-static unsigned inifcns_check_tan(void)
+static unsigned inifcns_check_tan()
 {
        unsigned result = 0;
        bool errorflag;
@@ -162,7 +162,7 @@ static unsigned inifcns_check_tan(void)
 }
 
 /* Simple tests on the dilogarithm function. */
-static unsigned inifcns_check_Li2(void)
+static unsigned inifcns_check_Li2()
 {
        // NOTE: this can safely be removed once CLN supports dilogarithms and
        // checks them itself.
@@ -190,7 +190,7 @@ static unsigned inifcns_check_Li2(void)
        return result;
 }
 
-unsigned check_inifcns(void)
+unsigned check_inifcns()
 {
        unsigned result = 0;
 
index ac0574e..4c98fc5 100644 (file)
@@ -1,7 +1,8 @@
 /** @file check_lsolve.cpp
  *
  *  These test routines do some simple checks on solving linear systems of
- *  symbolic equations. */
+ *  symbolic equations.  They are a well-tried resource for cross-checking
+ *  the underlying symbolic manipulations. */
 
 /*
  *  GiNaC Copyright (C) 1999-2003 Johannes Gutenberg University Mainz, Germany
@@ -96,7 +97,7 @@ static unsigned check_inifcns_lsolve(unsigned n)
 {
        unsigned result = 0;
        
-       for (int repetition=0; repetition<100; ++repetition) {
+       for (int repetition=0; repetition<200; ++repetition) {
                // create two size n vectors of symbols, one for the coefficients
                // a[0],..,a[n], one for indeterminates x[0]..x[n]:
                vector<symbol> a;
@@ -155,7 +156,7 @@ static unsigned check_inifcns_lsolve(unsigned n)
        return result;
 }
 
-unsigned check_lsolve(void)
+unsigned check_lsolve()
 {
        unsigned result = 0;
        
@@ -163,23 +164,23 @@ unsigned check_lsolve(void)
        clog << "---------linear solve:" << endl;
        
        // solve some numeric linear systems
-       for (unsigned n=1; n<12; ++n)
+       for (unsigned n=1; n<14; ++n)
                result += check_matrix_solve(n, n, 1, 0);
        cout << '.' << flush;
        // solve some underdetermined numeric systems
-       for (unsigned n=1; n<12; ++n)
+       for (unsigned n=1; n<14; ++n)
                result += check_matrix_solve(n+1, n, 1, 0);
        cout << '.' << flush;
        // solve some overdetermined numeric systems
-       for (unsigned n=1; n<12; ++n)
+       for (unsigned n=1; n<14; ++n)
                result += check_matrix_solve(n, n+1, 1, 0);
        cout << '.' << flush;
        // solve some multiple numeric systems
-       for (unsigned n=1; n<12; ++n)
+       for (unsigned n=1; n<14; ++n)
                result += check_matrix_solve(n, n, n/3+1, 0);
        cout << '.' << flush;
        // solve some symbolic linear systems
-       for (unsigned n=1; n<7; ++n)
+       for (unsigned n=1; n<8; ++n)
                result += check_matrix_solve(n, n, 1, 2);
        cout << '.' << flush;
        
index deb0047..91f4b5d 100644 (file)
@@ -1,6 +1,8 @@
 /** @file check_matrices.cpp
  *
- *  Here we test manipulations on GiNaC's symbolic matrices. */
+ *  Here we test manipulations on GiNaC's symbolic matrices.  They are a
+ *  well-tried resource for cross-checking the underlying symbolic
+ *  manipulations. */
 
 /*
  *  GiNaC Copyright (C) 1999-2003 Johannes Gutenberg University Mainz, Germany
 
 /* determinants of some sparse symbolic matrices with coefficients in
  * an integral domain. */
-static unsigned integdom_matrix_determinants(void)
+static unsigned integdom_matrix_determinants()
 {
        unsigned result = 0;
        symbol a("a");
        
-       for (unsigned size=3; size<20; ++size) {
+       for (unsigned size=3; size<22; ++size) {
                matrix A(size,size);
                // populate one element in each row:
                for (unsigned r=0; r<size-1; ++r)
@@ -51,12 +53,12 @@ static unsigned integdom_matrix_determinants(void)
 
 /* determinants of some symbolic matrices with multivariate rational function
  * coefficients. */
-static unsigned rational_matrix_determinants(void)
+static unsigned rational_matrix_determinants()
 {
        unsigned result = 0;
        symbol a("a"), b("b"), c("c");
        
-       for (unsigned size=3; size<8; ++size) {
+       for (unsigned size=3; size<9; ++size) {
                matrix A(size,size);
                for (unsigned r=0; r<size-1; ++r) {
                        // populate one or two elements in each row:
@@ -85,12 +87,12 @@ static unsigned rational_matrix_determinants(void)
 }
 
 /* Some quite funny determinants with functions and stuff like that inside. */
-static unsigned funny_matrix_determinants(void)
+static unsigned funny_matrix_determinants()
 {
        unsigned result = 0;
        symbol a("a"), b("b"), c("c");
        
-       for (unsigned size=3; size<7; ++size) {
+       for (unsigned size=3; size<8; ++size) {
                matrix A(size,size);
                for (unsigned co=0; co<size-1; ++co) {
                        // populate one or two elements in each row:
@@ -119,12 +121,12 @@ static unsigned funny_matrix_determinants(void)
 }
 
 /* compare results from different determinant algorithms.*/
-static unsigned compare_matrix_determinants(void)
+static unsigned compare_matrix_determinants()
 {
        unsigned result = 0;
        symbol a("a");
        
-       for (unsigned size=2; size<7; ++size) {
+       for (unsigned size=2; size<8; ++size) {
                matrix A(size,size);
                for (unsigned co=0; co<size; ++co) {
                        for (unsigned ro=0; ro<size; ++ro) {
@@ -156,12 +158,12 @@ static unsigned compare_matrix_determinants(void)
        return result;
 }
 
-static unsigned symbolic_matrix_inverse(void)
+static unsigned symbolic_matrix_inverse()
 {
        unsigned result = 0;
        symbol a("a"), b("b"), c("c");
        
-       for (unsigned size=2; size<5; ++size) {
+       for (unsigned size=2; size<6; ++size) {
                matrix A(size,size);
                do {
                        for (unsigned co=0; co<size; ++co) {
@@ -193,7 +195,7 @@ static unsigned symbolic_matrix_inverse(void)
        return result;
 }
 
-unsigned check_matrices(void)
+unsigned check_matrices()
 {
        unsigned result = 0;
        
index 4753302..e67d693 100644 (file)
@@ -25,7 +25,7 @@
 
 /* Simple and maybe somewhat pointless consistency tests of assorted tests and
  * conversions. */
-static unsigned check_numeric1(void)
+static unsigned check_numeric1()
 {
        unsigned result = 0;
        bool errorflag = false;
@@ -53,7 +53,7 @@ static unsigned check_numeric1(void)
        return result;
 }
 
-static unsigned check_numeric2(void)
+static unsigned check_numeric2()
 {
        unsigned result = 0;
        bool errorflag = false;
@@ -105,7 +105,7 @@ static unsigned check_numeric2(void)
        return result;
 }
 
-unsigned check_numeric(void)
+unsigned check_numeric()
 {
        unsigned result = 0;
        
index 6b787c0..0d6f1a6 100644 (file)
@@ -24,7 +24,7 @@
 
 #include <fstream>
 
-unsigned exam_archive(void)
+unsigned exam_archive()
 {
        unsigned result = 0;
        
index 25c815a..aef55cb 100644 (file)
@@ -44,7 +44,7 @@ static unsigned check_equal_simplify(const ex &e1, const ex &e2)
        return 0;
 }
 
-static unsigned clifford_check1(void)
+static unsigned clifford_check1()
 {
        // checks general identities and contractions
 
@@ -80,7 +80,7 @@ static unsigned clifford_check1(void)
        return result;
 }
 
-static unsigned clifford_check2(void)
+static unsigned clifford_check2()
 {
        // checks identities relating to gamma5
 
@@ -99,7 +99,7 @@ static unsigned clifford_check2(void)
        return result;
 }
 
-static unsigned clifford_check3(void)
+static unsigned clifford_check3()
 {
        // checks traces
 
@@ -187,7 +187,7 @@ static unsigned clifford_check3(void)
        return result;
 }
 
-static unsigned clifford_check4(void)
+static unsigned clifford_check4()
 {
        // simplify_indexed()/dirac_trace() cross-checks
 
@@ -221,7 +221,7 @@ static unsigned clifford_check4(void)
        return result;
 }
 
-static unsigned clifford_check5(void)
+static unsigned clifford_check5()
 {
        // canonicalize_clifford() checks
 
@@ -249,7 +249,7 @@ static unsigned clifford_check5(void)
        return result;
 }
 
-unsigned exam_clifford(void)
+unsigned exam_clifford()
 {
        unsigned result = 0;
        
index 558f654..cbc9946 100644 (file)
@@ -44,7 +44,7 @@ static unsigned check_equal_simplify(const ex &e1, const ex &e2)
        return 0;
 }
 
-static unsigned color_check1(void)
+static unsigned color_check1()
 {
        // checks general identities and contractions of the structure constants
 
@@ -78,7 +78,7 @@ static unsigned color_check1(void)
        return result;
 }
 
-static unsigned color_check2(void)
+static unsigned color_check2()
 {
        // checks general identities and contractions of the generators
 
@@ -107,7 +107,7 @@ static unsigned color_check2(void)
        return result;
 }
 
-static unsigned color_check3(void)
+static unsigned color_check3()
 {
        // checks traces
 
@@ -128,7 +128,7 @@ static unsigned color_check3(void)
        return result;
 }
 
-unsigned exam_color(void)
+unsigned exam_color()
 {
        unsigned result = 0;
        
index 7192397..33b13b1 100644 (file)
@@ -45,9 +45,7 @@ static unsigned check_diff(const ex &e, const symbol &x,
                clog << "derivative of " << e << " by " << x << " returned "
                     << ed << " instead of " << d << endl;
                clog << "returned:" << endl;
-               ed.printtree(clog);
-               clog << endl << "instead of" << endl;
-               d.printtree(clog);
+               clog << tree << ed << "instead of\n" << d << dflt;
 
                return 1;
        }
@@ -55,7 +53,7 @@ static unsigned check_diff(const ex &e, const symbol &x,
 }
 
 // Simple (expanded) polynomials
-static unsigned exam_differentiation1(void)
+static unsigned exam_differentiation1()
 {
        unsigned result = 0;
        symbol x("x"), y("y");
@@ -86,7 +84,7 @@ static unsigned exam_differentiation1(void)
 }
 
 // Trigonometric functions
-static unsigned exam_differentiation2(void)
+static unsigned exam_differentiation2()
 {
        unsigned result = 0;
        symbol x("x"), y("y"), a("a"), b("b");
@@ -135,7 +133,7 @@ static unsigned exam_differentiation2(void)
 }
        
 // exp function
-static unsigned exam_differentiation3(void)
+static unsigned exam_differentiation3()
 {
        unsigned result = 0;
        symbol x("x"), y("y"), a("a"), b("b");
@@ -163,7 +161,7 @@ static unsigned exam_differentiation3(void)
 }
 
 // log functions
-static unsigned exam_differentiation4(void)
+static unsigned exam_differentiation4()
 {
        unsigned result = 0;
        symbol x("x"), y("y"), a("a"), b("b");
@@ -193,7 +191,7 @@ static unsigned exam_differentiation4(void)
 }
 
 // Functions with two variables
-static unsigned exam_differentiation5(void)
+static unsigned exam_differentiation5()
 {
        unsigned result = 0;
        symbol x("x"), y("y"), a("a"), b("b");
@@ -214,7 +212,7 @@ static unsigned exam_differentiation5(void)
 }
 
 // Series
-static unsigned exam_differentiation6(void)
+static unsigned exam_differentiation6()
 {
        symbol x("x");
        ex e, d, ed;
@@ -234,7 +232,7 @@ static unsigned exam_differentiation6(void)
 }
 
 // Hashing can help a lot, if differentiation is done cleverly
-static unsigned exam_differentiation7(void)
+static unsigned exam_differentiation7()
 {
        symbol x("x");
        ex P = x + pow(x,3);
@@ -257,7 +255,7 @@ static unsigned exam_differentiation7(void)
        return 0;
 }
 
-unsigned exam_differentiation(void)
+unsigned exam_differentiation()
 {
        unsigned result = 0;
        
index 82a2539..69816a7 100644 (file)
@@ -55,7 +55,7 @@ static unsigned check_equal_simplify(const ex &e1, const ex &e2, const scalar_pr
        return 0;
 }
 
-static unsigned delta_check(void)
+static unsigned delta_check()
 {
        // checks identities of the delta tensor
 
@@ -81,7 +81,7 @@ static unsigned delta_check(void)
        return result;
 }
 
-static unsigned metric_check(void)
+static unsigned metric_check()
 {
        // checks identities of the metric tensor
 
@@ -114,7 +114,7 @@ static unsigned metric_check(void)
        return result;
 }
 
-static unsigned epsilon_check(void)
+static unsigned epsilon_check()
 {
        // checks identities of the epsilon tensor
 
@@ -153,7 +153,7 @@ REGISTER_FUNCTION(symm_fcn, set_symmetry(sy_symm(0, 1)));
 DECLARE_FUNCTION_2P(anti_fcn)
 REGISTER_FUNCTION(anti_fcn, set_symmetry(sy_anti(0, 1)));
 
-static unsigned symmetry_check(void)
+static unsigned symmetry_check()
 {
        // check symmetric/antisymmetric objects
 
@@ -202,7 +202,7 @@ static unsigned symmetry_check(void)
        return result;
 }
 
-static unsigned scalar_product_check(void)
+static unsigned scalar_product_check()
 {
        // check scalar product replacement
 
@@ -225,7 +225,7 @@ static unsigned scalar_product_check(void)
        return result;
 }
 
-static unsigned edyn_check(void)
+static unsigned edyn_check()
 {
        // Relativistic electrodynamics
 
@@ -312,7 +312,7 @@ static unsigned edyn_check(void)
        return result;
 }
 
-static unsigned spinor_check(void)
+static unsigned spinor_check()
 {
        // check identities of the spinor metric
 
@@ -347,7 +347,7 @@ static unsigned spinor_check(void)
        return result;
 }
 
-static unsigned dummy_check(void)
+static unsigned dummy_check()
 {
        // check dummy index renaming/repositioning
 
@@ -380,7 +380,7 @@ static unsigned dummy_check(void)
        return result;
 }
 
-unsigned exam_indexed(void)
+unsigned exam_indexed()
 {
        unsigned result = 0;
        
index 1291030..a3a0965 100644 (file)
@@ -24,7 +24,7 @@
 #include "exams.h"
 
 /* Assorted tests on other transcendental functions. */
-static unsigned inifcns_consist_trans(void)
+static unsigned inifcns_consist_trans()
 {
        unsigned result = 0;
        symbol x("x");
@@ -116,7 +116,7 @@ static unsigned inifcns_consist_trans(void)
 
 /* Simple tests on the tgamma function.  We stuff in arguments where the results
  * exists in closed form and check if it's ok. */
-static unsigned inifcns_consist_gamma(void)
+static unsigned inifcns_consist_gamma()
 {
        unsigned result = 0;
        ex e;
@@ -161,7 +161,7 @@ static unsigned inifcns_consist_gamma(void)
 
 /* Simple tests on the Psi-function (aka polygamma-function).  We stuff in
    arguments where the result exists in closed form and check if it's ok. */
-static unsigned inifcns_consist_psi(void)
+static unsigned inifcns_consist_psi()
 {
        unsigned result = 0;
        symbol x;
@@ -183,7 +183,7 @@ static unsigned inifcns_consist_psi(void)
 /* Simple tests on the Riemann Zeta function.  We stuff in arguments where the
  * result exists in closed form and check if it's ok.  Of course, this checks
  * the Bernoulli numbers as a side effect. */
-static unsigned inifcns_consist_zeta(void)
+static unsigned inifcns_consist_zeta()
 {
        unsigned result = 0;
        ex e;
@@ -208,7 +208,7 @@ static unsigned inifcns_consist_zeta(void)
        return result;
 }
 
-unsigned exam_inifcns(void)
+unsigned exam_inifcns()
 {
        unsigned result = 0;
        
index 1321a71..ff510b3 100644 (file)
@@ -22,7 +22,7 @@
 
 #include "exams.h"
 
-static unsigned exam_lsolve1(void)
+static unsigned exam_lsolve1()
 {
        // A trivial example.
        unsigned result = 0;
@@ -40,7 +40,7 @@ static unsigned exam_lsolve1(void)
        return result;
 }
 
-static unsigned exam_lsolve2a(void)
+static unsigned exam_lsolve2a()
 {
        // An example from the Maple online help.
        unsigned result = 0;
@@ -68,7 +68,7 @@ static unsigned exam_lsolve2a(void)
        return result;
 }
 
-static unsigned exam_lsolve2b(void)
+static unsigned exam_lsolve2b()
 {
        // A boring example from Mathematica's online help.
        unsigned result = 0;
@@ -96,7 +96,7 @@ static unsigned exam_lsolve2b(void)
        return result;
 }
 
-static unsigned exam_lsolve2c(void)
+static unsigned exam_lsolve2c()
 {
        // A more interesting example from the Maple online help.
        unsigned result = 0;
@@ -124,7 +124,7 @@ static unsigned exam_lsolve2c(void)
        return result;
 }
 
-static unsigned exam_lsolve2S(void)
+static unsigned exam_lsolve2S()
 {
        // A degenerate example that went wrong in GiNaC 0.6.2.
        unsigned result = 0;
@@ -152,7 +152,7 @@ static unsigned exam_lsolve2S(void)
        return result;
 }
 
-static unsigned exam_lsolve3S(void)
+static unsigned exam_lsolve3S()
 {
        // A degenerate example that went wrong while trying to improve elimination
        unsigned result = 0;
@@ -183,7 +183,7 @@ static unsigned exam_lsolve3S(void)
        return result;
 }
 
-unsigned exam_lsolve(void)
+unsigned exam_lsolve()
 {
        unsigned result = 0;
        
index 867f52c..9a88c8c 100644 (file)
@@ -23,7 +23,7 @@
 #include <stdexcept>
 #include "exams.h"
 
-static unsigned matrix_determinants(void)
+static unsigned matrix_determinants()
 {
        unsigned result = 0;
        ex det;
@@ -110,7 +110,7 @@ static unsigned matrix_determinants(void)
        return result;
 }
 
-static unsigned matrix_invert1(void)
+static unsigned matrix_invert1()
 {
        unsigned result = 0;
        matrix m(1,1);
@@ -128,7 +128,7 @@ static unsigned matrix_invert1(void)
        return result;
 }
 
-static unsigned matrix_invert2(void)
+static unsigned matrix_invert2()
 {
        unsigned result = 0;
        matrix m(2,2);
@@ -150,7 +150,7 @@ static unsigned matrix_invert2(void)
        return result;
 }
 
-static unsigned matrix_invert3(void)
+static unsigned matrix_invert3()
 {
        unsigned result = 0;
        matrix m(3,3);
@@ -180,7 +180,7 @@ static unsigned matrix_invert3(void)
        return result;
 }
 
-static unsigned matrix_solve2(void)
+static unsigned matrix_solve2()
 {
        // check the solution of the multiple system A*X = B:
        //       [ 1  2 -1 ] [ x0 y0 ]   [ 4 0 ]
@@ -216,7 +216,7 @@ static unsigned matrix_solve2(void)
        return result;
 }
 
-static unsigned matrix_evalm(void)
+static unsigned matrix_evalm()
 {
        unsigned result = 0;
 
@@ -241,7 +241,7 @@ static unsigned matrix_evalm(void)
        return result;
 }
 
-static unsigned matrix_misc(void)
+static unsigned matrix_misc()
 {
        unsigned result = 0;
        matrix m1(2,2);
@@ -292,7 +292,7 @@ static unsigned matrix_misc(void)
        return result;
 }
 
-unsigned exam_matrices(void)
+unsigned exam_matrices()
 {
        unsigned result = 0;
        
index 1da10b7..4127a32 100644 (file)
@@ -24,7 +24,7 @@
 #include "exams.h"
 
 #define VECSIZE 30
-static unsigned exam_expand_subs(void)
+static unsigned exam_expand_subs()
 {
        unsigned result = 0;
        symbol a[VECSIZE];
@@ -51,7 +51,7 @@ static unsigned exam_expand_subs(void)
  *  2)  expand e
  *  3)  substitute a0 by -a1 in e
  *  after which e should return 0 (without expanding). */
-static unsigned exam_expand_subs2(void)
+static unsigned exam_expand_subs2()
 {
        unsigned result = 0;
        symbol a("a"), b("b");
@@ -69,7 +69,7 @@ static unsigned exam_expand_subs2(void)
        return result;
 }
 
-static unsigned exam_expand_power(void)
+static unsigned exam_expand_power()
 {
        unsigned result = 0;
        symbol x("x"), a("a"), b("b");
@@ -86,7 +86,7 @@ static unsigned exam_expand_power(void)
        return result;
 }
 
-static unsigned exam_sqrfree(void)
+static unsigned exam_sqrfree()
 {
        unsigned result = 0;
        symbol x("x"), y("y");
@@ -133,7 +133,7 @@ static unsigned exam_sqrfree(void)
  * When somebody screws up the operators this routine will most probably fail
  * to compile.  Unfortunately we can only test the stuff that is allowed, not
  * what is forbidden (e.g. e1+e2 = 42) since that must not compile.  :-(   */
-static unsigned exam_operator_semantics(void)
+static unsigned exam_operator_semantics()
 {
        unsigned result = 0;
        ex e1, e2;
@@ -200,7 +200,7 @@ static unsigned exam_operator_semantics(void)
 }
 
 /* This checks whether subs() works as intended in some special cases. */
-static unsigned exam_subs(void)
+static unsigned exam_subs()
 {
        unsigned result = 0;
        symbol x("x");
@@ -226,7 +226,45 @@ static unsigned exam_subs(void)
        return result;
 }
 
-unsigned exam_misc(void)
+/* Joris van der Hoeven (he of TeXmacs fame) is a funny guy.  He has his own
+ * ideas what a symbolic system should do.  Let's make sure we won't disappoint
+ * him some day.  Incidentally, this seems to always have worked. */
+static unsigned exam_joris()
+{
+       unsigned result = 0;
+       symbol x("x");
+
+       ex e = expand(pow(x, x-1) * x);
+       if (e != pow(x, x)) {
+               clog << "x^(x-1)*x did not expand to x^x.  Please call Joris!" << endl;
+               ++result;
+       }
+
+       return result;
+}
+
+/* Test Chris Dams' algebraic substitutions. */
+static unsigned exam_subs_algebraic()
+{
+       unsigned result = 0;
+       symbol x("x"), y("y");
+
+       ex e = ex(x*x*x*y*y).subs(x*y==2, subs_options::subs_algebraic);
+       if (e != 4*x) {
+               clog << "(x^3*y^2).subs(x*y==2,subs_options::subs_algebraic) erroneously returned " << e << endl;
+               ++result;
+       }
+
+       e = ex(x*x*x*x*x).subs(x*x==y, subs_options::subs_algebraic);
+       if (e != y*y*x) {
+               clog << "x^5.subs(x^2==y,subs_options::subs_algebraic) erroneously returned " << e << endl;
+               ++result;
+       }
+       
+       return result;
+}
+
+unsigned exam_misc()
 {
        unsigned result = 0;
        
@@ -239,6 +277,8 @@ unsigned exam_misc(void)
        result += exam_sqrfree(); cout << '.' << flush;
        result += exam_operator_semantics(); cout << '.' << flush;
        result += exam_subs(); cout << '.' << flush;
+       result += exam_joris(); cout << '.' << flush;
+       result += exam_subs_algebraic(); cout << '.' << flush;
        
        if (!result) {
                cout << " passed " << endl;
index 02f2a82..0aafa49 100644 (file)
@@ -35,7 +35,7 @@ static unsigned check_normal(const ex &e, const ex &d)
        return 0;
 }
 
-static unsigned exam_normal1(void)
+static unsigned exam_normal1()
 {
        unsigned result = 0;
        ex e, d;
@@ -62,7 +62,7 @@ static unsigned exam_normal1(void)
        return result;
 }
 
-static unsigned exam_normal2(void)
+static unsigned exam_normal2()
 {
        unsigned result = 0;
        ex e, d;
@@ -101,7 +101,7 @@ static unsigned exam_normal2(void)
        return result;
 }
 
-static unsigned exam_normal3(void)
+static unsigned exam_normal3()
 {
        unsigned result = 0;
        ex e, d;
@@ -124,7 +124,7 @@ static unsigned exam_normal3(void)
        return result;
 }
 
-static unsigned exam_normal4(void)
+static unsigned exam_normal4()
 {
        unsigned result = 0;
        ex e, d;
@@ -157,7 +157,7 @@ static unsigned exam_normal4(void)
        return result;
 }
 
-unsigned exam_normalization(void)
+unsigned exam_normalization()
 {
        unsigned result = 0;
        
index 3b943b1..90e435e 100644 (file)
@@ -27,7 +27,7 @@
 
 /* Simple and maybe somewhat pointless consistency tests of assorted tests and
  * conversions. */
-static unsigned exam_numeric1(void)
+static unsigned exam_numeric1()
 {
        unsigned result = 0;
        numeric test_int1(42);
@@ -112,7 +112,7 @@ static unsigned exam_numeric1(void)
  * Implementing a workaround sadly introduced another bug on May 28th 1999
  * that was fixed on May 31st.  The workaround turned out to be stupid and
  * the original bug in CLN was finally killed on September 2nd. */
-static unsigned exam_numeric2(void)
+static unsigned exam_numeric2()
 {
        unsigned result = 0;
        
@@ -151,7 +151,7 @@ static unsigned exam_numeric2(void)
 
 /* Assorted tests to ensure some crucial functions behave exactly as specified
  * in the documentation. */
-static unsigned exam_numeric3(void)
+static unsigned exam_numeric3()
 {
        unsigned result = 0;
        numeric calc_rem, calc_quo;
@@ -269,7 +269,7 @@ static unsigned exam_numeric3(void)
 
 /* Now we perform some less trivial checks about several functions which should
  * return exact numbers if possible. */
-static unsigned exam_numeric4(void)
+static unsigned exam_numeric4()
 {
        unsigned result = 0;
        bool passed;
@@ -300,7 +300,7 @@ static unsigned exam_numeric4(void)
 
 /* This test examines that simplifications of the form 5^(3/2) -> 5*5^(1/2)
  * are carried out properly. */
-static unsigned exam_numeric5(void)
+static unsigned exam_numeric5()
 {
        unsigned result = 0;
        
@@ -319,7 +319,7 @@ static unsigned exam_numeric5(void)
 
 /* This test checks whether the numeric output/parsing routines are
    consistent. */
-static unsigned exam_numeric6(void)
+static unsigned exam_numeric6()
 {
        unsigned result = 0;
 
@@ -373,7 +373,7 @@ static unsigned exam_numeric6(void)
        return result;
 }
 
-unsigned exam_numeric(void)
+unsigned exam_numeric()
 {
        unsigned result = 0;
        
index 4050b5f..c1df502 100644 (file)
@@ -28,7 +28,7 @@
 // The very first pair of historic problems had its roots in power.cpp and was
 // finally resolved on April 27th 1999. (Fixing the first on April 23rd
 // actually introduced the second.)
-static unsigned exam_paranoia1(void)
+static unsigned exam_paranoia1()
 {
        unsigned result = 0;
        symbol x("x"), y("y"), z("z");
@@ -59,7 +59,7 @@ static unsigned exam_paranoia1(void)
 // And here the second oops which showed up until May 17th 1999.  It had to do
 // with lexicographic canonicalization and thus showed up only if the variables
 // had the names as given here:
-static unsigned exam_paranoia2(void)
+static unsigned exam_paranoia2()
 {
        unsigned result = 0;
        symbol x("x"), y("y"), z("z");
@@ -95,7 +95,7 @@ static unsigned exam_paranoia2(void)
 // The third bug was introduced on May 18th 1999, discovered on May 19 and
 // fixed that same day.  It worked when x was substituted by 1 but not with
 // other numbers:
-static unsigned exam_paranoia3(void)
+static unsigned exam_paranoia3()
 {
        unsigned result = 0;
        symbol x("x"), y("y");
@@ -124,7 +124,7 @@ static unsigned exam_paranoia3(void)
 }
 
 // The fourth bug was also discovered on May 19th 1999 and fixed immediately:
-static unsigned exam_paranoia4(void)
+static unsigned exam_paranoia4()
 {
        unsigned result = 0;
        symbol x("x");
@@ -149,7 +149,7 @@ static unsigned exam_paranoia4(void)
 }
 
 // The fifth oops was discovered on May 20th 1999 and fixed a day later:
-static unsigned exam_paranoia5(void)
+static unsigned exam_paranoia5()
 {
        unsigned result = 0;
        symbol x("x"), y("y");
@@ -168,7 +168,7 @@ static unsigned exam_paranoia5(void)
 }
 
 // This one was discovered on Jun 1st 1999 and fixed the same day:
-static unsigned exam_paranoia6(void)
+static unsigned exam_paranoia6()
 {
        unsigned result = 0;
        symbol x("x");
@@ -186,7 +186,7 @@ static unsigned exam_paranoia6(void)
 
 // This one was introduced on June 1st 1999 by some aggressive manual
 // optimization. Discovered and fixed on June 2nd.
-static unsigned exam_paranoia7(void)
+static unsigned exam_paranoia7()
 {
        unsigned result = 0;
        symbol x("x"), y("y");
@@ -206,7 +206,7 @@ static unsigned exam_paranoia7(void)
 // This one was a result of the rewrite of mul::max_coefficient when we
 // introduced the overall_coefficient field in expairseq objects on Oct 1st
 // 1999. Fixed on Oct 4th.
-static unsigned exam_paranoia8(void)
+static unsigned exam_paranoia8()
 {
        unsigned result = 0;
        symbol x("x");
@@ -232,7 +232,7 @@ static unsigned exam_paranoia8(void)
 // Z[X]. multiply_lcm() forgot to multiply the x-linear term with the LCM of
 // the coefficient's denominators (2 in this case).  Introduced on Jan 25th
 // 2000 and fixed on Jan 31th.
-static unsigned exam_paranoia9(void)
+static unsigned exam_paranoia9()
 {
        unsigned result = 0;
        symbol x("x");
@@ -251,7 +251,7 @@ static unsigned exam_paranoia9(void)
 // and on Feb 13th 2000 I found out that things like 2^(3/2) throw an exception
 // "power::eval(): pow(0,0) is undefined" instead of simplifying to 2*2^(1/2).
 // It was fixed that same day.
-static unsigned exam_paranoia10(void)
+static unsigned exam_paranoia10()
 {
        unsigned result = 0;
        
@@ -276,7 +276,7 @@ static unsigned exam_paranoia10(void)
 // add::normal() forgot to multiply the denominator of the overall_coeff of
 // its expanded and normalized children with the denominator of the expanded
 // child (did you get this? Well, never mind...). Fixed on Feb 21th 2000.
-static unsigned exam_paranoia11(void)
+static unsigned exam_paranoia11()
 {
        unsigned result = 0;
        symbol x("x");
@@ -295,7 +295,7 @@ static unsigned exam_paranoia11(void)
 // This one returned 0 because add::normal() incorrectly assumed that if the
 // common denominator is 1, all the denominators would be 1 (they can in fact
 // be +/-1). Fixed on Aug 2nd 2000.
-static unsigned exam_paranoia12(void)
+static unsigned exam_paranoia12()
 {
        unsigned result = 0;
        symbol x("x");
@@ -314,7 +314,7 @@ static unsigned exam_paranoia12(void)
 
 // This one caused a division by 0 because heur_gcd() didn't check its
 // input polynomials against 0. Fixed on Aug 4th 2000.
-static unsigned exam_paranoia13(void)
+static unsigned exam_paranoia13()
 {
        unsigned result = 0;
        symbol a("a"), b("b"), c("c");
@@ -338,7 +338,7 @@ static unsigned exam_paranoia13(void)
 
 // A bug introduced on July 19, 2001. quo() and rem() would sometimes call
 // vector::reserve() with a negative argument. Fixed on Dec 20, 2001.
-static unsigned exam_paranoia14(void)
+static unsigned exam_paranoia14()
 {
        unsigned result = 0;
        symbol x("x");
@@ -354,7 +354,7 @@ static unsigned exam_paranoia14(void)
 
 // Under certain conditions, power::expand_add_2() could produce non-canonical
 // numeric expairs. Fixed on Oct 24, 2002.
-static unsigned exam_paranoia15(void)
+static unsigned exam_paranoia15()
 {
        unsigned result = 0;
 
@@ -370,7 +370,7 @@ static unsigned exam_paranoia15(void)
        return result;
 }
 
-unsigned exam_paranoia(void)
+unsigned exam_paranoia()
 {
        unsigned result = 0;
        
index e350579..4b8bd44 100644 (file)
@@ -29,7 +29,7 @@ static symbol x("x"), z("z");
 static symbol y[MAX_VARIABLES];
 
 // GCD = 1
-static unsigned poly_gcd1(void)
+static unsigned poly_gcd1()
 {
        for (int v=1; v<=MAX_VARIABLES; v++) {
                ex e1 = x;
@@ -51,7 +51,7 @@ static unsigned poly_gcd1(void)
 }
 
 // Linearly dense quartic inputs with quadratic GCDs
-static unsigned poly_gcd2(void)
+static unsigned poly_gcd2()
 {
        for (int v=1; v<=MAX_VARIABLES; v++) {
                ex e1 = x;
@@ -74,7 +74,7 @@ static unsigned poly_gcd2(void)
 }
 
 // Sparse GCD and inputs where degrees are proportional to the number of variables
-static unsigned poly_gcd3(void)
+static unsigned poly_gcd3()
 {
        for (int v=1; v<=MAX_VARIABLES; v++) {
                ex e1 = pow(x, v + 1);
@@ -94,7 +94,7 @@ static unsigned poly_gcd3(void)
 }
 
 // Variation of case 3; major performance degradation with PRS
-static unsigned poly_gcd3p(void)
+static unsigned poly_gcd3p()
 {
        for (int v=1; v<=MAX_VARIABLES; v++) {
                ex e1 = pow(x, v + 1);
@@ -117,7 +117,7 @@ static unsigned poly_gcd3p(void)
 }
 
 // Quadratic non-monic GCD; f and g have other quadratic factors
-static unsigned poly_gcd4(void)
+static unsigned poly_gcd4()
 {
        for (int v=1; v<=MAX_VARIABLES; v++) {
                ex e1 = pow(x, 2) * pow(y[0], 2);
@@ -142,7 +142,7 @@ static unsigned poly_gcd4(void)
 }
 
 // Completely dense non-monic quadratic inputs with dense non-monic linear GCDs
-static unsigned poly_gcd5(void)
+static unsigned poly_gcd5()
 {
        for (int v=1; v<=MAX_VARIABLES; v++) {
                ex e1 = x + 1;
@@ -167,7 +167,7 @@ static unsigned poly_gcd5(void)
 }
 
 // Sparse non-monic quadratic inputs with linear GCDs
-static unsigned poly_gcd5p(void)
+static unsigned poly_gcd5p()
 {
        for (int v=1; v<=MAX_VARIABLES; v++) {
                ex e1 = x;
@@ -187,7 +187,7 @@ static unsigned poly_gcd5p(void)
 }
 
 // Trivariate inputs with increasing degrees
-static unsigned poly_gcd6(void)
+static unsigned poly_gcd6()
 {
        symbol y("y");
 
@@ -205,7 +205,7 @@ static unsigned poly_gcd6(void)
 }
 
 // Trivariate polynomials whose GCD has common factors with its cofactors
-static unsigned poly_gcd7(void)
+static unsigned poly_gcd7()
 {
        symbol y("y");
        ex p = x - y * z + 1;
@@ -226,7 +226,7 @@ static unsigned poly_gcd7(void)
        return 0;
 }
 
-unsigned exam_polygcd(void)
+unsigned exam_polygcd()
 {
        unsigned result = 0;
        
index c6203df..be62bfc 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "exams.h"
 
-static unsigned exam_powerlaws1(void)
+static unsigned exam_powerlaws1()
 {
        // (x^a)^b = x^(a*b)
        
@@ -100,7 +100,7 @@ static unsigned exam_powerlaws1(void)
        return 0;
 }
 
-static unsigned exam_powerlaws2(void)
+static unsigned exam_powerlaws2()
 {
        // (a*x)^b = a^b * x^b
        
@@ -198,7 +198,7 @@ static unsigned exam_powerlaws2(void)
        return 0;
 }
 
-static unsigned exam_powerlaws3(void)
+static unsigned exam_powerlaws3()
 {
        // numeric evaluation
 
@@ -237,7 +237,7 @@ static unsigned exam_powerlaws3(void)
        return 0;
 }
 
-static unsigned exam_powerlaws4(void)
+static unsigned exam_powerlaws4()
 {
        // test for mul::eval()
        
@@ -262,7 +262,7 @@ static unsigned exam_powerlaws4(void)
        return 0;
 }
 
-static unsigned exam_powerlaws5(void)
+static unsigned exam_powerlaws5()
 {
        // cabinet of slightly pathological cases
        
@@ -284,7 +284,7 @@ static unsigned exam_powerlaws5(void)
        return 0;
 }
 
-unsigned exam_powerlaws(void)
+unsigned exam_powerlaws()
 {
        unsigned result = 0;
        
index f757d50..ab1ca0f 100644 (file)
@@ -32,14 +32,14 @@ static unsigned check_series(const ex &e, const ex &point, const ex &d, int orde
                clog << "series expansion of " << e << " at " << point
                     << " erroneously returned " << ep << " (instead of " << d
                     << ")" << endl;
-               (ep-d).printtree(clog);
+               clog << tree << (ep-d) << dflt;
                return 1;
        }
        return 0;
 }
 
 // Series expansion
-static unsigned exam_series1(void)
+static unsigned exam_series1()
 {
        unsigned result = 0;
        ex e, d;
@@ -107,7 +107,7 @@ static unsigned exam_series1(void)
 }
 
 // Series addition
-static unsigned exam_series2(void)
+static unsigned exam_series2()
 {
        unsigned result = 0;
        ex e, d;
@@ -120,7 +120,7 @@ static unsigned exam_series2(void)
 }
 
 // Series multiplication
-static unsigned exam_series3(void)
+static unsigned exam_series3()
 {
        unsigned result = 0;
        ex e, d;
@@ -133,7 +133,7 @@ static unsigned exam_series3(void)
 }
 
 // Series exponentiation
-static unsigned exam_series4(void)
+static unsigned exam_series4()
 {
        unsigned result = 0;
        ex e, d;
@@ -150,7 +150,7 @@ static unsigned exam_series4(void)
 }
 
 // Order term handling
-static unsigned exam_series5(void)
+static unsigned exam_series5()
 {
        unsigned result = 0;
        ex e, d;
@@ -170,7 +170,7 @@ static unsigned exam_series5(void)
 }
 
 // Series expansion of tgamma(-1)
-static unsigned exam_series6(void)
+static unsigned exam_series6()
 {
        ex e = tgamma(2*x);
        ex d = pow(x+1,-1)*numeric(1,4) +
@@ -202,7 +202,7 @@ static unsigned exam_series6(void)
 }
        
 // Series expansion of tan(x==Pi/2)
-static unsigned exam_series7(void)
+static unsigned exam_series7()
 {
        ex e = tan(x*Pi/2);
        ex d = pow(x-1,-1)/Pi*(-2) + pow(x-1,1)*Pi/6 + pow(x-1,3)*pow(Pi,3)/360
@@ -212,7 +212,7 @@ static unsigned exam_series7(void)
 }
 
 // Series expansion of log(sin(x==0))
-static unsigned exam_series8(void)
+static unsigned exam_series8()
 {
        ex e = log(sin(x));
        ex d = log(x) - pow(x,2)/6 - pow(x,4)/180 - pow(x,6)/2835
@@ -221,7 +221,7 @@ static unsigned exam_series8(void)
 }
 
 // Series expansion of Li2(sin(x==0))
-static unsigned exam_series9(void)
+static unsigned exam_series9()
 {
        ex e = Li2(sin(x));
        ex d = x + pow(x,2)/4 - pow(x,3)/18 - pow(x,4)/48
@@ -231,7 +231,7 @@ static unsigned exam_series9(void)
 }
 
 // Series expansion of Li2((x==2)^2), caring about branch-cut
-static unsigned exam_series10(void)
+static unsigned exam_series10()
 {
        ex e = Li2(pow(x,2));
        ex d = Li2(4) + (-log(3) + I*Pi*csgn(I-I*pow(x,2))) * (x-2)
@@ -243,7 +243,7 @@ static unsigned exam_series10(void)
 }
 
 // Series expansion of logarithms around branch points
-static unsigned exam_series11(void)
+static unsigned exam_series11()
 {
        unsigned result = 0;
        ex e, d;
@@ -283,7 +283,7 @@ static unsigned exam_series11(void)
 }
 
 // Series expansion of other functions around branch points
-static unsigned exam_series12(void)
+static unsigned exam_series12()
 {
        unsigned result = 0;
        ex e, d;
@@ -309,7 +309,7 @@ static unsigned exam_series12(void)
 }
 
 
-unsigned exam_pseries(void)
+unsigned exam_pseries()
 {
        unsigned result = 0;
        
index 09870db..e88bd73 100644 (file)
@@ -84,8 +84,8 @@ public:
        vertex(ijpair ij = ijpair(0,0)) : indices(ij) { }
        void increment_indices(const ijpair &ind) { indices.first += ind.first; indices.second += ind.second; }
        virtual ~vertex() { }
-       virtual vertex* copy(void) const = 0;
-       virtual ijpair get_increment(void) const { return indices; }
+       virtual vertex* copy() const = 0;
+       virtual ijpair get_increment() const { return indices; }
        virtual const ex evaluate(const symbol &x, const unsigned grad) const = 0;
        bool operator==(const vertex &v) const { return (indices==v.indices); }
        bool operator<(const vertex &v) const { return (indices<v.indices); }
@@ -100,8 +100,8 @@ protected:
 class Sigma : public vertex {
 public:
        Sigma(ijpair ij = ijpair(0,0)) : vertex(ij) { }
-       vertex* copy(void) const { return new Sigma(*this); }
-       ijpair get_increment(void) const { return ijpair(indices.first+indices.second+1, 0); }
+       vertex* copy() const { return new Sigma(*this); }
+       ijpair get_increment() const { return ijpair(indices.first+indices.second+1, 0); }
        const ex evaluate(const symbol &x, const unsigned grad) const;
 private:
 };
@@ -132,8 +132,8 @@ const ex Sigma::evaluate(const symbol &x, const unsigned grad) const
 class Sigma_flipped : public Sigma {
 public:
        Sigma_flipped(ijpair ij = ijpair(0,0)) : Sigma(ij) { }
-       vertex* copy(void) const { return new Sigma_flipped(*this); }
-       ijpair get_increment(void) const { return ijpair(0, indices.first+indices.second+1); }
+       vertex* copy() const { return new Sigma_flipped(*this); }
+       ijpair get_increment() const { return ijpair(0, indices.first+indices.second+1); }
        const ex evaluate(const symbol &x, const unsigned grad) const { return Sigma::evaluate(x, grad); }
 private:
 };
@@ -145,8 +145,8 @@ private:
 class Gamma : public vertex {
 public:
        Gamma(ijpair ij = ijpair(0,0)) : vertex(ij) { }
-       vertex* copy(void) const { return new Gamma(*this); }
-       ijpair get_increment(void) const { return ijpair(indices.first+indices.second+1, 0); }
+       vertex* copy() const { return new Gamma(*this); }
+       ijpair get_increment() const { return ijpair(indices.first+indices.second+1, 0); }
        const ex evaluate(const symbol &x, const unsigned grad) const;
 private:
 };
@@ -179,7 +179,7 @@ const ex Gamma::evaluate(const symbol &x, const unsigned grad) const
 class Vacuum : public vertex {
 public:
        Vacuum(ijpair ij = ijpair(0,0)) : vertex(ij) { }
-       vertex* copy(void) const { return new Vacuum(*this); }
+       vertex* copy() const { return new Vacuum(*this); }
        ijpair get_increment() const { return ijpair(0, indices.first+indices.second+1); }
        const ex evaluate(const symbol &x, const unsigned grad) const;
 private:
@@ -218,7 +218,7 @@ public:
        ~node() { delete vert; }
        void add_child(const node &, bool = false);
        const ex evaluate(const symbol &x, unsigned grad) const;
-       unsigned total_edges(void) const;
+       unsigned total_edges() const;
        bool operator==(const node &) const;
        bool operator<(const node &) const;
 private:
@@ -274,7 +274,7 @@ const ex node::evaluate(const symbol &x, unsigned grad) const
        return (product * vert->evaluate(x,grad));
 }
 
-unsigned node::total_edges(void) const
+unsigned node::total_edges() const
 {
        unsigned accu = 0;
        for (multiset<child>::const_iterator i=children.begin(); i!=children.end(); ++i) {
@@ -473,7 +473,7 @@ static unsigned test_tree(const node (*tree_generator)(unsigned=0))
        return 0;
 }
 
-unsigned time_antipode(void)
+unsigned time_antipode()
 {
        unsigned result = 0;
        timer jaeger_le_coultre;
index ea3b7be..66531bd 100644 (file)
@@ -53,7 +53,7 @@ static unsigned expand_subs(unsigned size)
        return result;
 }
 
-unsigned time_dennyfliegner(void)
+unsigned time_dennyfliegner()
 {
        unsigned result = 0;
        
index 97f5bcd..274d098 100644 (file)
@@ -25,7 +25,7 @@
 
 #include "times.h"
 
-static unsigned test(void)
+static unsigned test()
 {
        unsigned result = 0;
        const symbol x("x"), y("y"), z("z");
@@ -42,7 +42,7 @@ static unsigned test(void)
        return result;
 }
 
-unsigned time_fateman_expand(void)
+unsigned time_fateman_expand()
 {
        unsigned result = 0;
        unsigned count = 0;
index 96eb85f..afb7839 100644 (file)
@@ -43,7 +43,7 @@ unsigned tgammaseries(unsigned order)
        return result;
 }
 
-unsigned time_gammaseries(void)
+unsigned time_gammaseries()
 {
        unsigned result = 0;
 
index 6badd19..67fcf62 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "times.h"
 
-static unsigned test(void)
+static unsigned test()
 {
        for (int i=1; i<=99; ++i)
                factorial(1000+i)/factorial(900+i);
@@ -36,7 +36,7 @@ static unsigned test(void)
        return 0;
 }
 
-unsigned time_lw_A(void)
+unsigned time_lw_A()
 {
        unsigned result = 0;
        unsigned count = 0;
index cb92efc..a2794dc 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "times.h"
 
-static unsigned test(void)
+static unsigned test()
 {
        numeric s;
        
@@ -37,7 +37,7 @@ static unsigned test(void)
        return 0;
 }
 
-unsigned time_lw_B(void)
+unsigned time_lw_B()
 {
        unsigned result = 0;
        unsigned count = 0;
index 70960ad..2f61a05 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "times.h"
 
-static unsigned test(void)
+static unsigned test()
 {
        numeric x(13*17*31);
        numeric y(13*19*29);
@@ -41,7 +41,7 @@ static unsigned test(void)
        return 0;
 }
 
-unsigned time_lw_C(void)
+unsigned time_lw_C()
 {
        unsigned result = 0;
        unsigned count = 0;
index 631b1cb..2bf3694 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "times.h"
 
-static unsigned test(void)
+static unsigned test()
 {
        ex s;
        symbol y("y");
@@ -41,7 +41,7 @@ static unsigned test(void)
        return 0;
 }
 
-unsigned time_lw_D(void)
+unsigned time_lw_D()
 {
        unsigned result = 0;
        unsigned count = 0;
index 59c590f..4a2abce 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "times.h"
 
-static unsigned test(void)
+static unsigned test()
 {
        ex s;
        symbol y("y");
@@ -41,7 +41,7 @@ static unsigned test(void)
        return 0;
 }
 
-unsigned time_lw_E(void)
+unsigned time_lw_E()
 {
        unsigned result = 0;
        unsigned count = 0;
index 912a0cd..bfd8dcb 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "times.h"
 
-static unsigned test(void)
+static unsigned test()
 {
        symbol x("x");
        symbol y("y");
@@ -38,7 +38,7 @@ static unsigned test(void)
        return 0;
 }
 
-unsigned time_lw_F(void)
+unsigned time_lw_F()
 {
        unsigned result = 0;
        unsigned count = 0;
index 43b0c6e..b65af06 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "times.h"
 
-static unsigned test(void)
+static unsigned test()
 {
        symbol x("x");
        symbol y("y");
@@ -41,7 +41,7 @@ static unsigned test(void)
        return 0;
 }
 
-unsigned time_lw_G(void)
+unsigned time_lw_G()
 {
        unsigned result = 0;
        unsigned count = 0;
index a36e5f2..e988e46 100644 (file)
@@ -56,7 +56,7 @@ static unsigned test(unsigned n)
        return 0;
 }
 
-unsigned time_lw_H(void)
+unsigned time_lw_H()
 {
        unsigned result = 0;
        unsigned count = 0;
index 18a42d8..cc86417 100644 (file)
@@ -79,7 +79,7 @@ static unsigned test(unsigned n)
        return result;
 }
 
-unsigned time_lw_IJKL(void)
+unsigned time_lw_IJKL()
 {
        unsigned result = 0;
        
index cfba9fc..54494c8 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "times.h"
 
-static unsigned test(void)
+static unsigned test()
 {
        // Determinant of a sparse matrix that comes up in graph theory:
        symbol x1("x1"), x2("x2"), x3("x3"), x4("x4"), x5("x5");
@@ -73,7 +73,7 @@ static unsigned test(void)
        return 0;
 }
 
-unsigned time_lw_M1(void)
+unsigned time_lw_M1()
 {
        unsigned result = 0;
        unsigned count = 0;
index 9b35c9f..b835f60 100644 (file)
@@ -25,7 +25,7 @@
 
 static const bool do_test = false;  // set to true in order to run this beast
 
-static unsigned test(void)
+static unsigned test()
 {
        // Determinant of a sparse matrix that comes up in graph theory:
        symbol x1("x1"), x2("x2"), x3("x3"), x4("x4"), x5("x5");
@@ -149,7 +149,7 @@ static unsigned test(void)
        return 0;
 }
 
-unsigned time_lw_M2(void)
+unsigned time_lw_M2()
 {
        unsigned result = 0;
        unsigned count = 0;
index 81d32b0..f55d56b 100644 (file)
@@ -26,7 +26,7 @@
 
 static const bool do_test = false;  // set to true in order to run this beast
 
-static unsigned test(void)
+static unsigned test()
 {
        symbol p11("p11"), p12("p12"), p21("p21"), p22("p22");
        symbol a12("a12"), a21("a21"), a22("a22");
@@ -52,7 +52,7 @@ static unsigned test(void)
        return 0;
 }
 
-unsigned time_lw_N(void)
+unsigned time_lw_N()
 {
        unsigned result = 0;
        unsigned count = 0;
index 1199043..f24016d 100644 (file)
@@ -25,7 +25,7 @@
 
 static const bool do_test = true;  // set to true in order to run this beast
 
-static unsigned test1(void)
+static unsigned test1()
 {
        symbol a1("a1"), a2("a2"), a3("a3"), a4("a4"), a5("a5"), a6("a6");
        symbol b1("b1"), b2("b2"), b3("b3"), b4("b4"), b5("b5"), b6("b6");
@@ -100,7 +100,7 @@ static unsigned test1(void)
        return 0;
 }
 
-unsigned time_lw_O(void)
+unsigned time_lw_O()
 {
        unsigned result = 0;
        unsigned count = 0;
index a523e89..279327b 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "times.h"
 
-static unsigned test(void)
+static unsigned test()
 {
        // This is a pattern that comes up in graph theory:
        const unsigned n = 10;
@@ -51,7 +51,7 @@ static unsigned test(void)
        return 0;
 }
 
-unsigned time_lw_P(void)
+unsigned time_lw_P()
 {
        unsigned result = 0;
        unsigned count = 0;
index 99d7869..69e0780 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "times.h"
 
-static unsigned test(void)
+static unsigned test()
 {
        // create the matrix from test P...
        const unsigned n = 10;
@@ -64,7 +64,7 @@ static unsigned test(void)
        return 0;
 }
 
-unsigned time_lw_Pprime(void)
+unsigned time_lw_Pprime()
 {
        unsigned result = 0;
        unsigned count = 0;
index b48a30c..8c976a1 100644 (file)
@@ -23,9 +23,9 @@
 
 #include "times.h"
 
-static const bool do_test = false;  // set to true in order to run this beast
+static const bool do_test = true;  // set to true in order to run this beast
 
-static unsigned test(void)
+static unsigned test()
 {
        // same matrix as in test P:
        const unsigned n = 10;
@@ -54,7 +54,7 @@ static unsigned test(void)
        return 0;
 }
 
-unsigned time_lw_Q(void)
+unsigned time_lw_Q()
 {
        unsigned result = 0;
        unsigned count = 0;
index 46dac14..b69cb91 100644 (file)
@@ -23,9 +23,9 @@
 
 #include "times.h"
 
-static const bool do_test = false;  // set to true in order to run this beast
+static const bool do_test = true;  // set to true in order to run this beast
 
-static unsigned test(void)
+static unsigned test()
 {
        // same matrix as in test P':
        const unsigned n = 10;
@@ -66,7 +66,7 @@ static unsigned test(void)
        return 0;
 }
 
-unsigned time_lw_Qprime(void)
+unsigned time_lw_Qprime()
 {
        unsigned result = 0;
        unsigned count = 0;
index 573f00f..693b8f7 100644 (file)
@@ -63,7 +63,7 @@ static unsigned toeplitz_det(unsigned size)
        return result;
 }
 
-unsigned time_toeplitz(void)
+unsigned time_toeplitz()
 {
        unsigned result = 0;
 
index 4b4c965..17fa65b 100644 (file)
@@ -61,7 +61,7 @@ static unsigned vandermonde_det(unsigned size)
        return result;
 }
 
-unsigned time_vandermonde(void)
+unsigned time_vandermonde()
 {
        unsigned result = 0;
        
index fe0d160..2a11872 100644 (file)
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include "times.h"
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <unistd.h>
 
-timer::timer(void) : on(false)
+#include "timer.h"
+
+timer::timer() : on(false)
 {
        getrusage(RUSAGE_SELF, &used1);
        getrusage(RUSAGE_SELF, &used2);
 }
 
-void timer::start(void)
+void timer::start()
 {
        on = true;
        getrusage(RUSAGE_SELF, &used1);
        getrusage(RUSAGE_SELF, &used2);
 }
 
-void timer::stop(void)
+void timer::stop()
 {
        on = false;
        getrusage(RUSAGE_SELF, &used2);
 }
 
-void timer::reset(void)
+void timer::reset()
 {
        getrusage(RUSAGE_SELF, &used1);
        getrusage(RUSAGE_SELF, &used2);
 }
 
-double timer::read(void)
+double timer::read()
 {
        double elapsed;
        if (this->running())
@@ -60,7 +64,7 @@ double timer::read(void)
        return 0.01*int(elapsed*100+0.5);
 }
 
-bool timer::running(void)
+bool timer::running()
 {
        return on;
 }
diff --git a/check/timer.h b/check/timer.h
new file mode 100644 (file)
index 0000000..022c29d
--- /dev/null
@@ -0,0 +1,41 @@
+/** @file timer.h
+ *
+ *  A simple stop watch class. */
+
+/*
+ *  GiNaC Copyright (C) 1999-2003 Johannes Gutenberg University Mainz, Germany
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef TIMER_H
+#define TIMER_H
+
+#include <sys/resource.h>
+
+class timer {
+public:
+       timer();
+       void start();
+       void stop();
+       void reset();
+       double read();
+       bool running();
+private:
+       bool on;
+       struct rusage used1, used2;
+};
+
+#endif // ndef TIMER_H
index 5d53b9f..85052de 100644 (file)
@@ -23,7 +23,6 @@
 #ifndef CHECKS_H
 #define CHECKS_H
 
-#include <sys/resource.h>
 #include <cstdlib>
 #include <iostream>
 #include <sstream>
 using namespace std;
 using namespace GiNaC;
 
-class timer {
-public:
-       timer();
-       void start(void);
-       void stop(void);
-       void reset(void);
-       double read(void);
-       bool running(void);
-private:
-       bool on;
-       struct rusage used1, used2;
-};
+#include "timer.h"
 
 // prototypes for all individual timings should be unsigned fcn():
 unsigned time_dennyfliegner();
index dd4eade..af1b549 100644 (file)
@@ -19,10 +19,10 @@ dnl autoconf sees "AC_MAJOR_VERSION" and complains about an undefined macro
 dnl (don't we all *love* M4?)...
 
 GINACLIB_MAJOR_VERSION=1
-GINACLIB_MINOR_VERSION=0
-GINACLIB_MICRO_VERSION=14
-GINACLIB_INTERFACE_AGE=1
-GINACLIB_BINARY_AGE=14
+GINACLIB_MINOR_VERSION=2
+GINACLIB_MICRO_VERSION=0
+GINACLIB_INTERFACE_AGE=0
+GINACLIB_BINARY_AGE=0
 GINACLIB_VERSION=$GINACLIB_MAJOR_VERSION.$GINACLIB_MINOR_VERSION.$GINACLIB_MICRO_VERSION
 
 AC_SUBST(GINACLIB_MAJOR_VERSION)
@@ -115,6 +115,7 @@ AC_CHECK_HEADER(sstream, , GINAC_ERROR([The standard <sstream> header file could
 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.]))
 
 dnl We need to have Bruno Haible's CLN installed.
 dnl (CLN versions >= 1.1.0 must have installed cln.m4 at a visible place,
index 190fcdb..7ad4568 100644 (file)
@@ -1,32 +1,15 @@
-ginac (1.0.14-1) unstable; urgency=low
+ginac (1.1.0-1) unstable; urgency=low
 
-  * New upstream (bugfix only) release.
-
- -- Christian Bauer <cbauer@ginac.de>  Sat,  1 Mar 2003 17:29:13 +0100
+  * New upstream release; binary incompatible, so it's libginac1.1 now.
+  * Adjusted to Standards-Version 3.5.8.
 
-ginac (1.0.13-1) unstable; urgency=low
-
-  * New upstream (bugfix only) release.
-
- -- Christian Bauer <cbauer@ginac.de>  Mon, 27 Jan 2003 17:56:07 +0100
-
-ginac (1.0.12-1) unstable; urgency=low
-
-  * New upstream (bugfix only) release.
-
- -- Christian Bauer <cbauer@ginac.de>  Thu, 31 Oct 2002 16:21:05 +0100
+ -- Richard Kreckel <kreckel@ginac.de>  Thu,  4 Apr 2003 12:11:21 +0200
 
 ginac (1.0.11-1) unstable; urgency=low
 
   * New upstream (bugfix only) release.
 
- -- Richard Kreckel <kreckel@ginac.de>  Wed, 18 Sep 2002 16:45:05 +0200
-
-ginac (1.0.10-1) unstable; urgency=low
-
-  * New upstream (bugfix only) release.
-
- -- Richard Kreckel <kreckel@ginac.de>  Wed, 24 Jul 2002 18:03:00 +0200
+ -- Richard Kreckel <kreckel@ginac.de>  Wed, 18 Sep 2002 16:45:05 +0100
 
 ginac (1.0.8-1) unstable; urgency=low
 
index 97f3b10..08df871 100644 (file)
@@ -2,10 +2,10 @@ Source: ginac
 Section: math
 Priority: optional
 Maintainer: Richard Kreckel <kreckel@ginac.de>
-Standards-Version: 3.1.1
-Build-Depends: debhelper, libcln-dev, libgmp3-dev, libreadline4-dev, flex, bison
+Build-Depends: debhelper (>> 3.0.0), libcln-dev, libgmp3-dev, libreadline4-dev, flex, bison
+Standards-Version: 3.5.8
 
-Package: libginac0
+Package: libginac1.1
 Architecture: any
 Section: libs
 Depends: ${shlibs:Depends}
@@ -16,12 +16,12 @@ Description: The GiNaC framework (runtime library)
  programming language.
  .
  This package provides the runtime library.  See <http://www.ginac.de/> for
- detailed information about the GiNaC framework.
+ detailed information about GiNaC.
 
 Package: libginac-dev
 Architecture: any
-Section: devel
-Depends: libginac0 (= ${Source-Version}), libc6-dev, g++, libcln-dev
+Section: libdevel
+Depends: libginac1.1 (= ${Source-Version}), libc6-dev, g++, libcln-dev
 Recommends: info | info-browser
 Suggests: ginac-tools
 Description: The GiNaC framework (development files)
@@ -30,8 +30,7 @@ Description: The GiNaC framework (development files)
  programming language.
  .
  This package provides header files, a static library plus a tutorial as info
- file.  See <http://www.ginac.de/> for detailed information about the GiNaC
- framework.
+ file.  See <http://www.ginac.de/> for detailed information about GiNaC.
 
 Package: ginac-tools
 Architecture: any
@@ -44,4 +43,4 @@ Description: Some tools for the GiNaC framework
  .
  This package provides some additional tools, like the popular ginsh (GiNaC
  interactive shell) and viewgar (for inspecting GiNaC archive files).  See
- <http://www.ginac.de/> for detailed information about the GiNaC framework.
+ <http://www.ginac.de/> for detailed information about GiNaC.
index 7cb8b5e..b104004 100644 (file)
@@ -1,4 +1,4 @@
-This package was debianized by Richard Kreckel kreckel@ginac.de on
+This package was debianized by Richard Kreckel <kreckel@ginac.de> on
 Thu, 29 Mar 2001 20:30:40 +0100.
 
 It was downloaded from <http://www.ginac.de/>
diff --git a/debian/docs b/debian/docs
new file mode 100644 (file)
index 0000000..eb9b151
--- /dev/null
@@ -0,0 +1,3 @@
+NEWS
+README
+AUTHORS
index 7f19909..c57db5d 100644 (file)
@@ -1,5 +1,8 @@
 #!/bin/sh
 set -e
-install-info --quiet --section Math Math -- /usr/share/info/ginac.info
+
+if [ "$1" = "configure" ]; then
+    install-info --quiet --section Math Math -- /usr/share/info/ginac.info
+fi
 
 #DEBHELPER#
similarity index 100%
rename from debian/dirs
rename to debian/libginac1.1.dirs
diff --git a/debian/libginac1.1.files b/debian/libginac1.1.files
new file mode 100644 (file)
index 0000000..9a5c1be
--- /dev/null
@@ -0,0 +1 @@
+usr/lib/libginac*.so.*
diff --git a/debian/postinst b/debian/postinst
deleted file mode 100644 (file)
index 1ded2f8..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-set -e
-if [ "$1" = "configure" ]; then
-  ldconfig
-fi
-#DEBHELPER#
index b3856a3..a6d80b1 100755 (executable)
@@ -1,53 +1,85 @@
 #!/usr/bin/make -f
 
-package=ginac
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
 
-version=$(shell expr `pwd` : '.*-\([0-9.]*\)')
-version_major=$(shell expr `pwd` : '.*-\([0-9]*\).[0-9.]*')
+# This is the debhelper compatability version to use.
+export DH_COMPAT=4
+# This has to be exported to make some magic below work.
+export DH_OPTIONS
 
-build:
+# These are used for cross-compiling and for saving the configure script
+# from having to guess our platform (since we know it already)
+DEB_HOST_GNU_TYPE   ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
+DEB_BUILD_GNU_TYPE  ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
+
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+       export CXXFLAGS = -O0
+else
+       export CXXFLAGS = -O2 -fomit-frame-pointer -finline-limit=1200
+endif
+ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
+       INSTALL_PROGRAM += -s
+endif
+
+config.status: configure
        dh_testdir
-       ./configure --prefix=/usr
-       $(MAKE) CXXFLAGS="-O2"
-       touch build
+       # Add here commands to configure the package.
+       ./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info
+
+build: build-arch
+
+build-arch: build-arch-stamp
+build-arch-stamp:  config.status
+       # Add here commands to compile the arch part of the package.
+       $(MAKE) prefix=$(CURDIR)/debian/tmp/usr infodir=$(CURDIR)/debian/tmp/usr/share/info mandir=$(CURDIR)/debian/tmp/usr/share/man
 
 clean:
        dh_testdir
-       dh_clean
-       -rm -f build
+       dh_testroot
+       rm -f build-arch-stamp config-stamp
        -$(MAKE) distclean
-       -rm -f `find . -name "*~"`
-       -rm -rf debian/tmp `find debian/* -type d ! -name CVS` debian/files* core
-       -rm -f debian/*substvars
+       dh_clean
 
-binary-indep: build
+install: install-arch
+install-arch:
        dh_testdir
        dh_testroot
+       dh_clean -k -a
+       dh_installdirs -a
+       # Add here commands to install the arch part of the package into 
+       # debian/tmp.
+       $(MAKE) install prefix=$(CURDIR)/debian/tmp/usr
+       mkdir -p $(CURDIR)/debian/tmp/usr/X11R6/include/X11/pixmaps
+       cp $(CURDIR)/debian/ginac.xpm $(CURDIR)/debian/tmp/usr/X11R6/include/X11/pixmaps/
 
-binary-arch: build
+# Must not depend on anything. This is to be called by
+# binary-arch/binary-multi
+# in another 'make' thread.
+binary-common:
        dh_testdir
        dh_testroot
-       dh_installdirs
-       # When is Automake going to honor FHS?
-       $(MAKE) install prefix=`pwd`/debian/tmp/usr infodir=`pwd`/debian/tmp/usr/share/info mandir=`pwd`/debian/tmp/usr/share/man
-       # Automake generated Makefile.in do install-info, which is bad for us:
-       -rm -f `pwd`/debian/tmp/usr/share/info/dir*
-       dh_installdocs ChangeLog NEWS README
-       dh_installchangelogs
+       dh_installdocs
        dh_installmenu
-       mkdir -p `pwd`/debian/tmp/usr/X11R6/include/X11/pixmaps
-       cp `pwd`/debian/ginac.xpm `pwd`/debian/tmp/usr/X11R6/include/X11/pixmaps/
+       dh_installman
+       dh_installinfo
+       dh_installchangelogs ChangeLog
        dh_movefiles
+       dh_link
        dh_strip
        dh_compress
        dh_fixperms
        dh_makeshlibs
-       dh_installdeb
-       dh_shlibdeps
+       dh_shlibdeps --libpackage=libginac1.1 -l debian/libginac1.1/usr/lib
        dh_gencontrol
+       dh_installdeb
        dh_md5sums
        dh_builddeb
 
-binary: binary-indep binary-arch
+# Build architecture dependant packages using the common target.
+binary-arch: build-arch install-arch
+       $(MAKE) -f debian/rules DH_OPTIONS=-a binary-common
 
-.PHONY: binary binary-arch binary-indep clean
+binary: binary-arch
+.PHONY: build clean binary-arch binary install install-arch 
index 6a0cdd0..ce7d3dc 100644 (file)
@@ -1 +1 @@
-libginac-1.0   0       libginac0 (>= 1.0.0)
+libginac-1.1   0       libginac1.1 (>= 1.1.0)
index 868b753..0f5c484 100644 (file)
@@ -1,6 +1,7 @@
-# Doxyfile 1.2.5
+# Doxyfile 1.2.18
 
-# This file describes the settings to be used by doxygen for a project
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
 #
 # All text after a hash (#) is considered a comment and will be ignored
 # The format is:
@@ -14,7 +15,7 @@
 #---------------------------------------------------------------------------
 
 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
-# by quotes) that should identify the project. 
+# by quotes) that should identify the project.
 
 PROJECT_NAME           = GiNaC
 
@@ -29,73 +30,94 @@ PROJECT_NUMBER         =
 # If a relative path is entered, it will be relative to the location 
 # where doxygen was started. If left blank the current directory will be used.
 
-OUTPUT_DIRECTORY       = .
+OUTPUT_DIRECTORY       = 
 
 # The OUTPUT_LANGUAGE tag is used to specify the language in which all 
 # documentation generated by doxygen is written. Doxygen will use this 
 # information to generate all constant output in the proper language. 
 # The default language is English, other supported languages are: 
-# Dutch, French, Italian, Czech, Swedish, German, Finnish, Japanese, 
-# Korean, Hungarian, Norwegian, Spanish, Romanian, Russian, Croatian, 
-# Polish, Portuguese and Slovene.
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, 
+# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en 
+# (Japanese with english messages), Korean, Norwegian, Polish, Portuguese, 
+# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish and Ukrainian.
 
 OUTPUT_LANGUAGE        = English
 
 # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
 # documentation are documented, even if no documentation was available. 
 # Private class members and static file members will be hidden unless 
-# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
 
 EXTRACT_ALL            = YES
 
 # If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
-# will be included in the documentation. 
+# will be included in the documentation.
 
 EXTRACT_PRIVATE        = YES
 
 # If the EXTRACT_STATIC tag is set to YES all static members of a file 
-# will be included in the documentation. 
+# will be included in the documentation.
 
 EXTRACT_STATIC         = YES
 
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
 # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
 # undocumented members of documented classes, files or namespaces. 
 # If set to NO (the default) these members will be included in the 
 # various overviews, but no documentation section is generated. 
-# This option has no effect if EXTRACT_ALL is enabled. 
+# This option has no effect if EXTRACT_ALL is enabled.
 
 HIDE_UNDOC_MEMBERS     = NO
 
 # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
 # undocumented classes that are normally visible in the class hierarchy. 
 # If set to NO (the default) these class will be included in the various 
-# overviews. This option has no effect if EXTRACT_ALL is enabled. 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
 
 HIDE_UNDOC_CLASSES     = NO
 
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
 # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
 # include brief member descriptions after the members that are listed in 
 # the file and class documentation (similar to JavaDoc). 
-# Set to NO to disable this. 
+# Set to NO to disable this.
 
 BRIEF_MEMBER_DESC      = YES
 
 # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
 # the brief description of a member or function before the detailed description. 
 # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
-# brief descriptions will be completely suppressed. 
+# brief descriptions will be completely suppressed.
 
 REPEAT_BRIEF           = YES
 
 # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
 # Doxygen will generate a detailed section even if there is only a brief 
-# description. 
+# description.
 
 ALWAYS_DETAILED_SEC    = NO
 
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited 
+# members of a class in the documentation of that class as if those members were 
+# ordinary class members. Constructors, destructors and assignment operators of 
+# the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
 # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
 # path before files name in the file list and in the header files. If set 
-# to NO the shortest path that makes the file name unique will be used. 
+# to NO the shortest path that makes the file name unique will be used.
 
 FULL_PATH_NAMES        = NO
 
@@ -109,29 +131,13 @@ STRIP_FROM_PATH        =
 # The INTERNAL_DOCS tag determines if documentation 
 # that is typed after a \internal command is included. If the tag is set 
 # to NO (the default) then the documentation will be excluded. 
-# Set it to YES to include the internal documentation. 
+# Set it to YES to include the internal documentation.
 
 INTERNAL_DOCS          = NO
 
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
-# generate a class diagram (in Html and LaTeX) for classes with base or 
-# super classes. Setting the tag to NO turns the diagrams off. 
-
-CLASS_DIAGRAMS         = YES
-
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
-# be generated. Documented entities will be cross-referenced with these sources. 
-
-SOURCE_BROWSER         = YES
-
-# Setting the INLINE_SOURCES tag to YES will include the body 
-# of functions and classes directly in the documentation. 
-
-INLINE_SOURCES         = NO
-
 # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
 # doxygen to hide any special comment blocks from generated source code 
-# fragments. Normal C and C++ comments will always remain visible. 
+# fragments. Normal C and C++ comments will always remain visible.
 
 STRIP_CODE_COMMENTS    = YES
 
@@ -143,21 +149,27 @@ STRIP_CODE_COMMENTS    = YES
 
 CASE_SENSE_NAMES       = YES
 
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful is your file systems 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
 # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
 # will show members with their full class and namespace scopes in the 
-# documentation. If set to YES the scope will be hidden. 
+# documentation. If set to YES the scope will be hidden.
 
 HIDE_SCOPE_NAMES       = NO
 
 # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
 # will generate a verbatim copy of the header file for each class for 
-# which an include is specified. Set to NO to disable this. 
+# which an include is specified. Set to NO to disable this.
 
 VERBATIM_HEADERS       = NO
 
 # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
 # will put list of the files that are included by a file in the documentation 
-# of that file. 
+# of that file.
 
 SHOW_INCLUDE_FILES     = YES
 
@@ -165,25 +177,40 @@ SHOW_INCLUDE_FILES     = YES
 # will interpret the first line (until the first dot) of a JavaDoc-style 
 # comment as the brief description. If set to NO, the JavaDoc 
 # comments  will behave just like the Qt-style comments (thus requiring an 
-# explict @brief command for a brief description. 
+# explict @brief command for a brief description.
 
 JAVADOC_AUTOBRIEF      = YES
 
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member 
+# documentation.
+
+DETAILS_AT_TOP         = NO
+
 # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
 # member inherits the documentation from any documented member that it 
-# reimplements. 
+# reimplements.
 
 INHERIT_DOCS           = YES
 
 # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
-# is inserted in the documentation for inline members. 
+# is inserted in the documentation for inline members.
 
 INLINE_INFO            = YES
 
 # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
 # will sort the (detailed) documentation of file and class members 
 # alphabetically by member name. If set to NO the members will appear in 
-# declaration order. 
+# declaration order.
 
 SORT_MEMBER_DOCS       = NO
 
@@ -195,15 +222,10 @@ SORT_MEMBER_DOCS       = NO
 DISTRIBUTE_GROUP_DOC   = NO
 
 # The TAB_SIZE tag can be used to set the number of spaces in a tab. 
-# Doxygen uses this value to replace tabs by spaces in code fragments. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
 
 TAB_SIZE               = 4
 
-# The ENABLE_SECTIONS tag can be used to enable conditional 
-# documentation sections, marked by \if sectionname ... \endif. 
-
-ENABLED_SECTIONS       = 
-
 # The GENERATE_TODOLIST tag can be used to enable (YES) or 
 # disable (NO) the todo list. This list is created by putting \todo 
 # commands in the documentation.
@@ -216,63 +238,92 @@ GENERATE_TODOLIST      = NO
 
 GENERATE_TESTLIST      = NO
 
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = NO
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= NO
+
 # This tag can be used to specify a number of aliases that acts 
 # as commands in the documentation. An alias has the form "name=value". 
 # For example adding "sideeffect=\par Side Effects:\n" will allow you to 
 # put the command \sideeffect (or @sideeffect) in the documentation, which 
 # will result in a user defined paragraph with heading "Side Effects:". 
-# You can put \n's in the value part of an alias to insert newlines. 
+# You can put \n's in the value part of an alias to insert newlines.
 
 ALIASES                = 
 
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
 # The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
 # the initial value of a variable or define consist of for it to appear in 
 # the documentation. If the initializer consists of more lines than specified 
 # here it will be hidden. Use a value of 0 to hide initializers completely. 
 # The appearance of the initializer of individual variables and defines in the 
 # documentation can be controlled using \showinitializer or \hideinitializer 
-# command in the documentation regardless of this setting. 
+# command in the documentation regardless of this setting.
 
 MAX_INITIALIZER_LINES  = 30
 
 # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources 
 # only. Doxygen will then generate output that is more tailored for C. 
 # For instance some of the names that are used will be different. The list 
-# of all members will be omitted, etc. 
+# of all members will be omitted, etc.
 
 OPTIMIZE_OUTPUT_FOR_C  = NO
 
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources 
+# only. Doxygen will then generate output that is more tailored for Java. 
+# For instance namespaces will be presented as packages, qualified scopes 
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
 #---------------------------------------------------------------------------
 # configuration options related to warning and progress messages
 #---------------------------------------------------------------------------
 
 # The QUIET tag can be used to turn on/off the messages that are generated 
-# by doxygen. Possible values are YES and NO. If left blank NO is used. 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
 
 QUIET                  = NO
 
 # The WARNINGS tag can be used to turn on/off the warning messages that are 
 # generated by doxygen. Possible values are YES and NO. If left blank 
-# NO is used. 
+# NO is used.
 
 WARNINGS               = NO
 
 # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
 # for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
-# automatically be disabled. 
+# automatically be disabled.
 
 WARN_IF_UNDOCUMENTED   = YES
 
 # The WARN_FORMAT tag determines the format of the warning messages that 
 # doxygen can produce. The string should contain the $file, $line, and $text 
 # tags, which will be replaced by the file and line number from which the 
-# warning originated and the warning text. 
+# warning originated and the warning text.
 
 WARN_FORMAT            = "$file:$line: $text"
 
 # The WARN_LOGFILE tag can be used to specify a file to which warning 
 # and error messages should be written. If left blank the output is written 
-# to stderr. 
+# to stderr.
 
 WARN_LOGFILE           = 
 
@@ -283,51 +334,65 @@ WARN_LOGFILE           =
 # The INPUT tag can be used to specify the files and/or directories that contain 
 # documented source files. You may enter file names like "myfile.cpp" or 
 # directories like "/usr/src/myproject". Separate the files or directories 
-# with spaces. 
+# with spaces.
 
 INPUT                  = ../../ginac
 
 # If the value of the INPUT tag contains directories, you can use the 
 # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
 # and *.h) to filter out the source-files in the directories. If left 
-# blank all files are included. 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp 
+# *.h++ *.idl *.odl
 
 FILE_PATTERNS          = *.cpp *.h
 
 # The RECURSIVE tag can be used to turn specify whether or not subdirectories 
 # should be searched for input files as well. Possible values are YES and NO. 
-# If left blank NO is used. 
+# If left blank NO is used.
 
 RECURSIVE              = NO
 
 # The EXCLUDE tag can be used to specify files and/or directories that should 
 # excluded from the INPUT source files. This way you can easily exclude a 
-# subdirectory from a directory tree whose root is specified with the INPUT tag. 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
 
 EXCLUDE                = 
 
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories 
+# that are symbolic links (a Unix filesystem feature) are excluded from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
 # If the value of the INPUT tag contains directories, you can use the 
 # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
-# certain files from those directories. 
+# certain files from those directories.
 
 EXCLUDE_PATTERNS       = 
 
 # The EXAMPLE_PATH tag can be used to specify one or more files or 
 # directories that contain example code fragments that are included (see 
-# the \include command). 
+# the \include command).
 
 EXAMPLE_PATH           = 
 
 # If the value of the EXAMPLE_PATH tag contains directories, you can use the 
 # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
 # and *.h) to filter out the source-files in the directories. If left 
-# blank all files are included. 
+# blank all files are included.
 
 EXAMPLE_PATTERNS       = 
 
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
 # The IMAGE_PATH tag can be used to specify one or more files or 
 # directories that contain image that are included in the documentation (see 
-# the \image command). 
+# the \image command).
 
 IMAGE_PATH             = 
 
@@ -336,36 +401,62 @@ IMAGE_PATH             =
 # by executing (via popen()) the command <filter> <input-file>, where <filter> 
 # is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
 # input file. Doxygen will then use the output that the filter program writes 
-# to standard output. 
+# to standard output.
 
 INPUT_FILTER           = 
 
 # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
 # INPUT_FILTER) will be used to filter the input files when producing source 
-# files to browse
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
 
 FILTER_SOURCE_FILES    = NO
 
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources.
+
+SOURCE_BROWSER         = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default) 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
 #---------------------------------------------------------------------------
 # configuration options related to the alphabetical class index
 #---------------------------------------------------------------------------
 
 # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
 # of all compounds will be generated. Enable this if the project 
-# contains a lot of classes, structs, unions or interfaces. 
+# contains a lot of classes, structs, unions or interfaces.
 
 ALPHABETICAL_INDEX     = YES
 
 # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
 # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
-# in which this list will be split (can be a number in the range [1..20]) 
+# in which this list will be split (can be a number in the range [1..20])
 
 COLS_IN_ALPHA_INDEX    = 5
 
 # In case all classes in a project start with a common prefix, all 
 # classes will be put under the same header in the alphabetical index. 
 # The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
-# should be ignored while generating the index headers. 
+# should be ignored while generating the index headers.
 
 IGNORE_PREFIX          = 
 
@@ -374,16 +465,22 @@ IGNORE_PREFIX          =
 #---------------------------------------------------------------------------
 
 # If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
-# generate HTML output. 
+# generate HTML output.
 
 GENERATE_HTML          = YES
 
 # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
 # If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `html' will be used as the default path. 
+# put in front of it. If left blank `html' will be used as the default path.
 
 HTML_OUTPUT            = .
 
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
 # The HTML_HEADER tag can be used to specify a personal HTML header for 
 # each generated HTML page. If it is left blank doxygen will generate a 
 # standard header.
@@ -399,39 +496,72 @@ HTML_FOOTER            = Doxyfooter
 # The HTML_STYLESHEET tag can be used to specify a user defined cascading 
 # style sheet that is used by each HTML page. It can be used to 
 # fine-tune the look of the HTML output. If the tag is left blank doxygen 
-# will generate a default style sheet 
+# will generate a default style sheet
 
 HTML_STYLESHEET        = 
 
 # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
 # files or namespaces will be aligned in HTML using tables. If set to 
-# NO a bullet list will be used. 
+# NO a bullet list will be used.
 
 HTML_ALIGN_MEMBERS     = YES
 
 # If the GENERATE_HTMLHELP tag is set to YES, additional index files 
 # will be generated that can be used as input for tools like the 
 # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
-# of the generated HTML documentation. 
+# of the generated HTML documentation.
 
 GENERATE_HTMLHELP      = NO
 
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output dir.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non empty doxygen will try to run 
+# the html help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the Html help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
 # The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
 # top of each HTML page. The value NO (the default) enables the index and 
-# the value YES disables it. 
+# the value YES disables it.
 
 DISABLE_INDEX          = NO
 
 # This tag can be used to set the number of enum values (range [1..20]) 
-# that doxygen will group on one line in the generated HTML documentation. 
+# that doxygen will group on one line in the generated HTML documentation.
 
 ENUM_VALUES_PER_LINE   = 4
 
 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
 # generated containing a tree-like index structure (just like the one that 
 # is generated for HTML Help). For this to work a browser that supports 
-# JavaScript and frames is required (for instance Netscape 4.0+ 
-# or Internet explorer 4.0+). 
+# JavaScript and frames is required (for instance Mozilla, Netscape 4.0+, 
+# or Internet explorer 4.0+). Note that for large projects the tree generation 
+# can take a very long time. In such cases it is better to disable this feature. 
+# Windows users are probably better off using the HTML help feature.
 
 GENERATE_TREEVIEW      = NO
 
@@ -446,57 +576,67 @@ TREEVIEW_WIDTH         = 250
 #---------------------------------------------------------------------------
 
 # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
-# generate Latex output. 
+# generate Latex output.
 
 GENERATE_LATEX         = NO
 
 # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
 # If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `latex' will be used as the default path. 
+# put in front of it. If left blank `latex' will be used as the default path.
 
 LATEX_OUTPUT           = latex
 
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
 # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
 # LaTeX documents. This may be useful for small projects and may help to 
-# save some trees in general. 
+# save some trees in general.
 
 COMPACT_LATEX          = NO
 
 # The PAPER_TYPE tag can be used to set the paper type that is used 
 # by the printer. Possible values are: a4, a4wide, letter, legal and 
-# executive. If left blank a4wide will be used. 
+# executive. If left blank a4wide will be used.
 
 PAPER_TYPE             = a4wide
 
 # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
-# packages that should be included in the LaTeX output. 
+# packages that should be included in the LaTeX output.
 
 EXTRA_PACKAGES         = 
 
 # The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
 # the generated latex document. The header should contain everything until 
 # the first chapter. If it is left blank doxygen will generate a 
-# standard header. Notice: only use this tag if you know what you are doing! 
+# standard header. Notice: only use this tag if you know what you are doing!
 
 LATEX_HEADER           = 
 
 # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
 # is prepared for conversion to pdf (using ps2pdf). The pdf file will 
 # contain links (just like the HTML output) instead of page references 
-# This makes the output suitable for online browsing using a pdf viewer. 
+# This makes the output suitable for online browsing using a pdf viewer.
 
 PDF_HYPERLINKS         = NO
 
 # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
 # plain latex in the generated Makefile. Set this option to YES to get a 
-# higher quality PDF documentation. 
+# higher quality PDF documentation.
 
 USE_PDFLATEX           = NO
 
 # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
 # command to the generated LaTeX files. This will instruct LaTeX to keep 
 # running if errors occur, instead of asking the user for help. 
-# This option is also used when generating formulas in HTML. 
+# This option is also used when generating formulas in HTML.
 
 LATEX_BATCHMODE        = NO
 
@@ -512,97 +652,146 @@ GENERATE_RTF           = NO
 
 # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
 # If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `rtf' will be used as the default path. 
+# put in front of it. If left blank `rtf' will be used as the default path.
 
 RTF_OUTPUT             = rtf
 
 # If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
 # RTF documents. This may be useful for small projects and may help to 
-# save some trees in general. 
+# save some trees in general.
 
 COMPACT_RTF            = NO
 
 # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
 # will contain hyperlink fields. The RTF file will 
 # contain links (just like the HTML output) instead of page references. 
-# This makes the output suitable for online browsing using a WORD or other. 
+# This makes the output suitable for online browsing using WORD or other 
 # programs which support those fields. 
-# Note: wordpad (write) and others do not support links. 
+# Note: wordpad (write) and others do not support links.
 
 RTF_HYPERLINKS         = NO
 
 # Load stylesheet definitions from file. Syntax is similar to doxygen's 
 # config file, i.e. a series of assigments. You only have to provide 
-# replacements, missing definitions are set to their default value. 
+# replacements, missing definitions are set to their default value.
 
 RTF_STYLESHEET_FILE    = 
 
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
 #---------------------------------------------------------------------------
 # configuration options related to the man page output
 #---------------------------------------------------------------------------
 
 # If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
-# generate man pages 
+# generate man pages
 
 GENERATE_MAN           = NO
 
 # The MAN_OUTPUT tag is used to specify where the man pages will be put. 
 # If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `man' will be used as the default path. 
+# put in front of it. If left blank `man' will be used as the default path.
 
 MAN_OUTPUT             = man
 
 # The MAN_EXTENSION tag determines the extension that is added to 
-# the generated man pages (default is the subroutine's section .3) 
+# the generated man pages (default is the subroutine's section .3)
 
 MAN_EXTENSION          = .3
 
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_XML           = NO
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
 #---------------------------------------------------------------------------
 # Configuration options related to the preprocessor   
 #---------------------------------------------------------------------------
 
 # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
 # evaluate all C-preprocessor directives found in the sources and include 
-# files. 
+# files.
 
 ENABLE_PREPROCESSING   = YES
 
 # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
 # names in the source code. If set to NO (the default) only conditional 
 # compilation will be performed. Macro expansion can be done in a controlled 
-# way by setting EXPAND_ONLY_PREDEF to YES. 
+# way by setting EXPAND_ONLY_PREDEF to YES.
 
 MACRO_EXPANSION        = YES
 
 # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
 # then the macro expansion is limited to the macros specified with the 
-# PREDEFINED and EXPAND_AS_PREDEFINED tags. 
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
 
 EXPAND_ONLY_PREDEF     = YES
 
 # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
-# in the INCLUDE_PATH (see below) will be search if a #include is found. 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
 
 SEARCH_INCLUDES        = YES
 
 # The INCLUDE_PATH tag can be used to specify one or more directories that 
 # contain include files that are not input files but should be processed by 
-# the preprocessor. 
+# the preprocessor.
 
 INCLUDE_PATH           = 
 
 # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
 # patterns (like *.h and *.hpp) to filter out the header-files in the 
 # directories. If left blank, the patterns specified with FILE_PATTERNS will 
-# be used. 
+# be used.
 
-INCLUDE_FILE_PATTERNS = *.h
+INCLUDE_FILE_PATTERNS  = *.h
 
 # The PREDEFINED tag can be used to specify one or more macro names that 
 # are defined before the preprocessor is started (similar to the -D option of 
 # gcc). The argument of the tag is a list of macros of the form: name 
 # or name=definition (no spaces). If the definition and the = are 
-# omitted =1 is assumed. 
+# omitted =1 is assumed.
 
 PREDEFINED             = "GINAC_DECLARE_REGISTERED_CLASS_NO_CTORS(class, base)=" \
                          "GINAC_DECLARE_REGISTERED_CLASS(class, base)="
@@ -610,31 +799,45 @@ PREDEFINED             = "GINAC_DECLARE_REGISTERED_CLASS_NO_CTORS(class, base)="
 # If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then 
 # this tag can be used to specify a list of macro names that should be expanded. 
 # The macro definition that is found in the sources will be used. 
-# Use the PREDEFINED tag if you want to use a different macro definition. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
 
 EXPAND_AS_DEFINED      = 
 
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse the 
+# parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
 #---------------------------------------------------------------------------
 # Configuration::addtions related to external references   
 #---------------------------------------------------------------------------
 
-# The TAGFILES tag can be used to specify one or more tagfiles. 
+# The TAGFILES tag can be used to specify one or more tagfiles.
 
 TAGFILES               = 
 
 # When a file name is specified after GENERATE_TAGFILE, doxygen will create 
-# a tag file that is based on the input files it reads. 
+# a tag file that is based on the input files it reads.
 
 GENERATE_TAGFILE       = 
 
 # If the ALLEXTERNALS tag is set to YES all external classes will be listed 
 # in the class index. If set to NO only the inherited external classes 
-# will be listed. 
+# will be listed.
 
 ALLEXTERNALS           = NO
 
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
 # The PERL_PATH should be the absolute path and name of the perl script 
-# interpreter (i.e. the result of `which perl'). 
+# interpreter (i.e. the result of `which perl').
 
 PERL_PATH              = /usr/bin/perl
 
@@ -642,10 +845,24 @@ PERL_PATH              = /usr/bin/perl
 # Configuration options related to the dot tool   
 #---------------------------------------------------------------------------
 
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in Html, RTF and LaTeX) for classes with base or 
+# super classes. Setting the tag to NO turns the diagrams off. Note that this 
+# option is superceded by the HAVE_DOT option below. This is only a fallback. It is 
+# recommended to install and use dot, since it yield more powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
 # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
 # available from the path. This tool is part of Graphviz, a graph visualization 
 # toolkit from AT&T and Lucent Bell Labs. The other options in this section 
-# have no effect if this option is set to NO (the default) 
+# have no effect if this option is set to NO (the default)
 
 HAVE_DOT               = NO
 
@@ -659,38 +876,56 @@ CLASS_GRAPH            = YES
 # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
 # will generate a graph for each documented class showing the direct and 
 # indirect implementation dependencies (inheritance, containment, and 
-# class references variables) of the class with other documented classes. 
+# class references variables) of the class with other documented classes.
 
 COLLABORATION_GRAPH    = YES
 
-# If the ENABLE_PREPROCESSING, INCLUDE_GRAPH, and HAVE_DOT tags are set to 
-# YES then doxygen will generate a graph for each documented file showing 
-# the direct and indirect include dependencies of the file with other 
-# documented files. 
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
 
 INCLUDE_GRAPH          = YES
 
-# If the ENABLE_PREPROCESSING, INCLUDED_BY_GRAPH, and HAVE_DOT tags are set to 
-# YES then doxygen will generate a graph for each documented header file showing 
-# the documented files that directly or indirectly include this file 
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
 
 INCLUDED_BY_GRAPH      = YES
 
 # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
-# will graphical hierarchy of all classes instead of a textual one. 
+# will graphical hierarchy of all classes instead of a textual one.
 
 GRAPHICAL_HIERARCHY    = YES
 
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
 # The tag DOT_PATH can be used to specify the path where the dot tool can be 
-# found. If left blank, it is assumed the dot tool can be found on the path. 
+# found. If left blank, it is assumed the dot tool can be found on the path.
 
 DOT_PATH               = 
 
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
 # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
 # (in pixels) of the graphs generated by dot. If a graph becomes larger than 
 # this value, doxygen will try to truncate the graph, so that it fits within 
 # the specified constraint. Beware that most browsers cannot cope with very 
-# large images. 
+# large images.
 
 MAX_DOT_GRAPH_WIDTH    = 1024
 
@@ -698,56 +933,62 @@ MAX_DOT_GRAPH_WIDTH    = 1024
 # (in pixels) of the graphs generated by dot. If a graph becomes larger than 
 # this value, doxygen will try to truncate the graph, so that it fits within 
 # the specified constraint. Beware that most browsers cannot cope with very 
-# large images. 
+# large images.
 
 MAX_DOT_GRAPH_HEIGHT   = 1024
 
 # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
 # generate a legend page explaining the meaning of the various boxes and 
-# arrows in the dot generated graphs. 
+# arrows in the dot generated graphs.
 
 GENERATE_LEGEND        = YES
 
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermedate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
 #---------------------------------------------------------------------------
 # Configuration::addtions related to the search engine   
 #---------------------------------------------------------------------------
 
 # The SEARCHENGINE tag specifies whether or not a search engine should be 
-# used. If set to NO the values of all tags below this one will be ignored. 
+# used. If set to NO the values of all tags below this one will be ignored.
 
 SEARCHENGINE           = NO
 
 # The CGI_NAME tag should be the name of the CGI script that 
 # starts the search engine (doxysearch) with the correct parameters. 
-# A script with this name will be generated by doxygen. 
+# A script with this name will be generated by doxygen.
 
 CGI_NAME               = search.cgi
 
 # The CGI_URL tag should be the absolute URL to the directory where the 
 # cgi binaries are located. See the documentation of your http daemon for 
-# details. 
+# details.
 
 CGI_URL                = 
 
 # The DOC_URL tag should be the absolute URL to the directory where the 
 # documentation is located. If left blank the absolute path to the 
-# documentation, with file:// prepended to it, will be used. 
+# documentation, with file:// prepended to it, will be used.
 
 DOC_URL                = 
 
 # The DOC_ABSPATH tag should be the absolute path to the directory where the 
 # documentation is located. If left blank the directory on the local machine 
-# will be used. 
+# will be used.
 
 DOC_ABSPATH            = 
 
 # The BIN_ABSPATH tag must point to the directory where the doxysearch binary 
-# is installed. 
+# is installed.
 
-BIN_ABSPATH            = /usr/local/bin/
+BIN_ABSPATH            = /usr/bin/
 
 # The EXT_DOC_PATHS tag can be used to specify one or more paths to 
 # documentation generated for other projects. This allows doxysearch to search 
-# the documentation for these projects as well. 
+# the documentation for these projects as well.
 
 EXT_DOC_PATHS          = 
index dd854fd..2c0e879 100644 (file)
@@ -1,6 +1,7 @@
-# Doxyfile 1.2.5
+# Doxyfile 1.2.18
 
-# This file describes the settings to be used by doxygen for a project
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
 #
 # All text after a hash (#) is considered a comment and will be ignored
 # The format is:
@@ -14,7 +15,7 @@
 #---------------------------------------------------------------------------
 
 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
-# by quotes) that should identify the project. 
+# by quotes) that should identify the project.
 
 PROJECT_NAME           = GiNaC
 
@@ -29,73 +30,94 @@ PROJECT_NUMBER         =
 # If a relative path is entered, it will be relative to the location 
 # where doxygen was started. If left blank the current directory will be used.
 
-OUTPUT_DIRECTORY       = .
+OUTPUT_DIRECTORY       = 
 
 # The OUTPUT_LANGUAGE tag is used to specify the language in which all 
 # documentation generated by doxygen is written. Doxygen will use this 
 # information to generate all constant output in the proper language. 
 # The default language is English, other supported languages are: 
-# Dutch, French, Italian, Czech, Swedish, German, Finnish, Japanese, 
-# Korean, Hungarian, Norwegian, Spanish, Romanian, Russian, Croatian, 
-# Polish, Portuguese and Slovene.
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, 
+# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en 
+# (Japanese with english messages), Korean, Norwegian, Polish, Portuguese, 
+# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish and Ukrainian.
 
 OUTPUT_LANGUAGE        = English
 
 # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
 # documentation are documented, even if no documentation was available. 
 # Private class members and static file members will be hidden unless 
-# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
 
 EXTRACT_ALL            = YES
 
 # If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
-# will be included in the documentation. 
+# will be included in the documentation.
 
 EXTRACT_PRIVATE        = YES
 
 # If the EXTRACT_STATIC tag is set to YES all static members of a file 
-# will be included in the documentation. 
+# will be included in the documentation.
 
 EXTRACT_STATIC         = YES
 
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
 # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
 # undocumented members of documented classes, files or namespaces. 
 # If set to NO (the default) these members will be included in the 
 # various overviews, but no documentation section is generated. 
-# This option has no effect if EXTRACT_ALL is enabled. 
+# This option has no effect if EXTRACT_ALL is enabled.
 
 HIDE_UNDOC_MEMBERS     = NO
 
 # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
 # undocumented classes that are normally visible in the class hierarchy. 
 # If set to NO (the default) these class will be included in the various 
-# overviews. This option has no effect if EXTRACT_ALL is enabled. 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
 
 HIDE_UNDOC_CLASSES     = NO
 
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
 # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
 # include brief member descriptions after the members that are listed in 
 # the file and class documentation (similar to JavaDoc). 
-# Set to NO to disable this. 
+# Set to NO to disable this.
 
 BRIEF_MEMBER_DESC      = YES
 
 # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
 # the brief description of a member or function before the detailed description. 
 # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
-# brief descriptions will be completely suppressed. 
+# brief descriptions will be completely suppressed.
 
 REPEAT_BRIEF           = YES
 
 # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
 # Doxygen will generate a detailed section even if there is only a brief 
-# description. 
+# description.
 
 ALWAYS_DETAILED_SEC    = NO
 
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited 
+# members of a class in the documentation of that class as if those members were 
+# ordinary class members. Constructors, destructors and assignment operators of 
+# the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
 # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
 # path before files name in the file list and in the header files. If set 
-# to NO the shortest path that makes the file name unique will be used. 
+# to NO the shortest path that makes the file name unique will be used.
 
 FULL_PATH_NAMES        = NO
 
@@ -109,29 +131,13 @@ STRIP_FROM_PATH        =
 # The INTERNAL_DOCS tag determines if documentation 
 # that is typed after a \internal command is included. If the tag is set 
 # to NO (the default) then the documentation will be excluded. 
-# Set it to YES to include the internal documentation. 
+# Set it to YES to include the internal documentation.
 
 INTERNAL_DOCS          = NO
 
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
-# generate a class diagram (in Html and LaTeX) for classes with base or 
-# super classes. Setting the tag to NO turns the diagrams off. 
-
-CLASS_DIAGRAMS         = YES
-
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
-# be generated. Documented entities will be cross-referenced with these sources. 
-
-SOURCE_BROWSER         = 
-
-# Setting the INLINE_SOURCES tag to YES will include the body 
-# of functions and classes directly in the documentation. 
-
-INLINE_SOURCES         = NO
-
 # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
 # doxygen to hide any special comment blocks from generated source code 
-# fragments. Normal C and C++ comments will always remain visible. 
+# fragments. Normal C and C++ comments will always remain visible.
 
 STRIP_CODE_COMMENTS    = YES
 
@@ -143,21 +149,27 @@ STRIP_CODE_COMMENTS    = YES
 
 CASE_SENSE_NAMES       = YES
 
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful is your file systems 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
 # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
 # will show members with their full class and namespace scopes in the 
-# documentation. If set to YES the scope will be hidden. 
+# documentation. If set to YES the scope will be hidden.
 
 HIDE_SCOPE_NAMES       = NO
 
 # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
 # will generate a verbatim copy of the header file for each class for 
-# which an include is specified. Set to NO to disable this. 
+# which an include is specified. Set to NO to disable this.
 
 VERBATIM_HEADERS       = NO
 
 # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
 # will put list of the files that are included by a file in the documentation 
-# of that file. 
+# of that file.
 
 SHOW_INCLUDE_FILES     = YES
 
@@ -165,25 +177,40 @@ SHOW_INCLUDE_FILES     = YES
 # will interpret the first line (until the first dot) of a JavaDoc-style 
 # comment as the brief description. If set to NO, the JavaDoc 
 # comments  will behave just like the Qt-style comments (thus requiring an 
-# explict @brief command for a brief description. 
+# explict @brief command for a brief description.
 
 JAVADOC_AUTOBRIEF      = YES
 
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member 
+# documentation.
+
+DETAILS_AT_TOP         = NO
+
 # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
 # member inherits the documentation from any documented member that it 
-# reimplements. 
+# reimplements.
 
 INHERIT_DOCS           = YES
 
 # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
-# is inserted in the documentation for inline members. 
+# is inserted in the documentation for inline members.
 
 INLINE_INFO            = YES
 
 # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
 # will sort the (detailed) documentation of file and class members 
 # alphabetically by member name. If set to NO the members will appear in 
-# declaration order. 
+# declaration order.
 
 SORT_MEMBER_DOCS       = NO
 
@@ -195,15 +222,10 @@ SORT_MEMBER_DOCS       = NO
 DISTRIBUTE_GROUP_DOC   = NO
 
 # The TAB_SIZE tag can be used to set the number of spaces in a tab. 
-# Doxygen uses this value to replace tabs by spaces in code fragments. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
 
 TAB_SIZE               = 4
 
-# The ENABLE_SECTIONS tag can be used to enable conditional 
-# documentation sections, marked by \if sectionname ... \endif. 
-
-ENABLED_SECTIONS       = 
-
 # The GENERATE_TODOLIST tag can be used to enable (YES) or 
 # disable (NO) the todo list. This list is created by putting \todo 
 # commands in the documentation.
@@ -216,63 +238,92 @@ GENERATE_TODOLIST      = NO
 
 GENERATE_TESTLIST      = NO
 
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = NO
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= NO
+
 # This tag can be used to specify a number of aliases that acts 
 # as commands in the documentation. An alias has the form "name=value". 
 # For example adding "sideeffect=\par Side Effects:\n" will allow you to 
 # put the command \sideeffect (or @sideeffect) in the documentation, which 
 # will result in a user defined paragraph with heading "Side Effects:". 
-# You can put \n's in the value part of an alias to insert newlines. 
+# You can put \n's in the value part of an alias to insert newlines.
 
 ALIASES                = 
 
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
 # The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
 # the initial value of a variable or define consist of for it to appear in 
 # the documentation. If the initializer consists of more lines than specified 
 # here it will be hidden. Use a value of 0 to hide initializers completely. 
 # The appearance of the initializer of individual variables and defines in the 
 # documentation can be controlled using \showinitializer or \hideinitializer 
-# command in the documentation regardless of this setting. 
+# command in the documentation regardless of this setting.
 
 MAX_INITIALIZER_LINES  = 30
 
 # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources 
 # only. Doxygen will then generate output that is more tailored for C. 
 # For instance some of the names that are used will be different. The list 
-# of all members will be omitted, etc. 
+# of all members will be omitted, etc.
 
 OPTIMIZE_OUTPUT_FOR_C  = NO
 
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources 
+# only. Doxygen will then generate output that is more tailored for Java. 
+# For instance namespaces will be presented as packages, qualified scopes 
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
 #---------------------------------------------------------------------------
 # configuration options related to warning and progress messages
 #---------------------------------------------------------------------------
 
 # The QUIET tag can be used to turn on/off the messages that are generated 
-# by doxygen. Possible values are YES and NO. If left blank NO is used. 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
 
 QUIET                  = NO
 
 # The WARNINGS tag can be used to turn on/off the warning messages that are 
 # generated by doxygen. Possible values are YES and NO. If left blank 
-# NO is used. 
+# NO is used.
 
 WARNINGS               = NO
 
 # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
 # for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
-# automatically be disabled. 
+# automatically be disabled.
 
 WARN_IF_UNDOCUMENTED   = YES
 
 # The WARN_FORMAT tag determines the format of the warning messages that 
 # doxygen can produce. The string should contain the $file, $line, and $text 
 # tags, which will be replaced by the file and line number from which the 
-# warning originated and the warning text. 
+# warning originated and the warning text.
 
 WARN_FORMAT            = "$file:$line: $text"
 
 # The WARN_LOGFILE tag can be used to specify a file to which warning 
 # and error messages should be written. If left blank the output is written 
-# to stderr. 
+# to stderr.
 
 WARN_LOGFILE           = 
 
@@ -283,51 +334,65 @@ WARN_LOGFILE           =
 # The INPUT tag can be used to specify the files and/or directories that contain 
 # documented source files. You may enter file names like "myfile.cpp" or 
 # directories like "/usr/src/myproject". Separate the files or directories 
-# with spaces. 
+# with spaces.
 
 INPUT                  = ../../ginac
 
 # If the value of the INPUT tag contains directories, you can use the 
 # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
 # and *.h) to filter out the source-files in the directories. If left 
-# blank all files are included. 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp 
+# *.h++ *.idl *.odl
 
 FILE_PATTERNS          = *.cpp *.h
 
 # The RECURSIVE tag can be used to turn specify whether or not subdirectories 
 # should be searched for input files as well. Possible values are YES and NO. 
-# If left blank NO is used. 
+# If left blank NO is used.
 
 RECURSIVE              = NO
 
 # The EXCLUDE tag can be used to specify files and/or directories that should 
 # excluded from the INPUT source files. This way you can easily exclude a 
-# subdirectory from a directory tree whose root is specified with the INPUT tag. 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
 
 EXCLUDE                = 
 
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories 
+# that are symbolic links (a Unix filesystem feature) are excluded from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
 # If the value of the INPUT tag contains directories, you can use the 
 # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
-# certain files from those directories. 
+# certain files from those directories.
 
 EXCLUDE_PATTERNS       = 
 
 # The EXAMPLE_PATH tag can be used to specify one or more files or 
 # directories that contain example code fragments that are included (see 
-# the \include command). 
+# the \include command).
 
 EXAMPLE_PATH           = 
 
 # If the value of the EXAMPLE_PATH tag contains directories, you can use the 
 # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
 # and *.h) to filter out the source-files in the directories. If left 
-# blank all files are included. 
+# blank all files are included.
 
 EXAMPLE_PATTERNS       = 
 
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
 # The IMAGE_PATH tag can be used to specify one or more files or 
 # directories that contain image that are included in the documentation (see 
-# the \image command). 
+# the \image command).
 
 IMAGE_PATH             = 
 
@@ -336,36 +401,62 @@ IMAGE_PATH             =
 # by executing (via popen()) the command <filter> <input-file>, where <filter> 
 # is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
 # input file. Doxygen will then use the output that the filter program writes 
-# to standard output. 
+# to standard output.
 
 INPUT_FILTER           = 
 
 # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
 # INPUT_FILTER) will be used to filter the input files when producing source 
-# files to browse
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
 
 FILTER_SOURCE_FILES    = NO
 
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources.
+
+SOURCE_BROWSER         = 
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default) 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
 #---------------------------------------------------------------------------
 # configuration options related to the alphabetical class index
 #---------------------------------------------------------------------------
 
 # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
 # of all compounds will be generated. Enable this if the project 
-# contains a lot of classes, structs, unions or interfaces. 
+# contains a lot of classes, structs, unions or interfaces.
 
 ALPHABETICAL_INDEX     = YES
 
 # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
 # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
-# in which this list will be split (can be a number in the range [1..20]) 
+# in which this list will be split (can be a number in the range [1..20])
 
 COLS_IN_ALPHA_INDEX    = 5
 
 # In case all classes in a project start with a common prefix, all 
 # classes will be put under the same header in the alphabetical index. 
 # The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
-# should be ignored while generating the index headers. 
+# should be ignored while generating the index headers.
 
 IGNORE_PREFIX          = 
 
@@ -374,16 +465,22 @@ IGNORE_PREFIX          =
 #---------------------------------------------------------------------------
 
 # If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
-# generate HTML output. 
+# generate HTML output.
 
 GENERATE_HTML          = NO
 
 # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
 # If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `html' will be used as the default path. 
+# put in front of it. If left blank `html' will be used as the default path.
 
 HTML_OUTPUT            = .
 
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
 # The HTML_HEADER tag can be used to specify a personal HTML header for 
 # each generated HTML page. If it is left blank doxygen will generate a 
 # standard header.
@@ -399,39 +496,72 @@ HTML_FOOTER            = Doxyfooter
 # The HTML_STYLESHEET tag can be used to specify a user defined cascading 
 # style sheet that is used by each HTML page. It can be used to 
 # fine-tune the look of the HTML output. If the tag is left blank doxygen 
-# will generate a default style sheet 
+# will generate a default style sheet
 
 HTML_STYLESHEET        = 
 
 # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
 # files or namespaces will be aligned in HTML using tables. If set to 
-# NO a bullet list will be used. 
+# NO a bullet list will be used.
 
 HTML_ALIGN_MEMBERS     = YES
 
 # If the GENERATE_HTMLHELP tag is set to YES, additional index files 
 # will be generated that can be used as input for tools like the 
 # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
-# of the generated HTML documentation. 
+# of the generated HTML documentation.
 
 GENERATE_HTMLHELP      = NO
 
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output dir.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non empty doxygen will try to run 
+# the html help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the Html help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
 # The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
 # top of each HTML page. The value NO (the default) enables the index and 
-# the value YES disables it. 
+# the value YES disables it.
 
 DISABLE_INDEX          = NO
 
 # This tag can be used to set the number of enum values (range [1..20]) 
-# that doxygen will group on one line in the generated HTML documentation. 
+# that doxygen will group on one line in the generated HTML documentation.
 
 ENUM_VALUES_PER_LINE   = 4
 
 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
 # generated containing a tree-like index structure (just like the one that 
 # is generated for HTML Help). For this to work a browser that supports 
-# JavaScript and frames is required (for instance Netscape 4.0+ 
-# or Internet explorer 4.0+). 
+# JavaScript and frames is required (for instance Mozilla, Netscape 4.0+, 
+# or Internet explorer 4.0+). Note that for large projects the tree generation 
+# can take a very long time. In such cases it is better to disable this feature. 
+# Windows users are probably better off using the HTML help feature.
 
 GENERATE_TREEVIEW      = NO
 
@@ -446,57 +576,67 @@ TREEVIEW_WIDTH         = 250
 #---------------------------------------------------------------------------
 
 # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
-# generate Latex output. 
+# generate Latex output.
 
 GENERATE_LATEX         = YES
 
 # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
 # If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `latex' will be used as the default path. 
+# put in front of it. If left blank `latex' will be used as the default path.
 
 LATEX_OUTPUT           = latex
 
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
 # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
 # LaTeX documents. This may be useful for small projects and may help to 
-# save some trees in general. 
+# save some trees in general.
 
 COMPACT_LATEX          = NO
 
 # The PAPER_TYPE tag can be used to set the paper type that is used 
 # by the printer. Possible values are: a4, a4wide, letter, legal and 
-# executive. If left blank a4wide will be used. 
+# executive. If left blank a4wide will be used.
 
 PAPER_TYPE             = a4wide
 
 # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
-# packages that should be included in the LaTeX output. 
+# packages that should be included in the LaTeX output.
 
 EXTRA_PACKAGES         = 
 
 # The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
 # the generated latex document. The header should contain everything until 
 # the first chapter. If it is left blank doxygen will generate a 
-# standard header. Notice: only use this tag if you know what you are doing! 
+# standard header. Notice: only use this tag if you know what you are doing!
 
 LATEX_HEADER           = 
 
 # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
 # is prepared for conversion to pdf (using ps2pdf). The pdf file will 
 # contain links (just like the HTML output) instead of page references 
-# This makes the output suitable for online browsing using a pdf viewer. 
+# This makes the output suitable for online browsing using a pdf viewer.
 
 PDF_HYPERLINKS         = NO
 
 # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
 # plain latex in the generated Makefile. Set this option to YES to get a 
-# higher quality PDF documentation. 
+# higher quality PDF documentation.
 
 USE_PDFLATEX           = NO
 
 # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
 # command to the generated LaTeX files. This will instruct LaTeX to keep 
 # running if errors occur, instead of asking the user for help. 
-# This option is also used when generating formulas in HTML. 
+# This option is also used when generating formulas in HTML.
 
 LATEX_BATCHMODE        = NO
 
@@ -512,97 +652,146 @@ GENERATE_RTF           = NO
 
 # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
 # If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `rtf' will be used as the default path. 
+# put in front of it. If left blank `rtf' will be used as the default path.
 
 RTF_OUTPUT             = rtf
 
 # If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
 # RTF documents. This may be useful for small projects and may help to 
-# save some trees in general. 
+# save some trees in general.
 
 COMPACT_RTF            = NO
 
 # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
 # will contain hyperlink fields. The RTF file will 
 # contain links (just like the HTML output) instead of page references. 
-# This makes the output suitable for online browsing using a WORD or other. 
+# This makes the output suitable for online browsing using WORD or other 
 # programs which support those fields. 
-# Note: wordpad (write) and others do not support links. 
+# Note: wordpad (write) and others do not support links.
 
 RTF_HYPERLINKS         = NO
 
 # Load stylesheet definitions from file. Syntax is similar to doxygen's 
 # config file, i.e. a series of assigments. You only have to provide 
-# replacements, missing definitions are set to their default value. 
+# replacements, missing definitions are set to their default value.
 
 RTF_STYLESHEET_FILE    = 
 
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
 #---------------------------------------------------------------------------
 # configuration options related to the man page output
 #---------------------------------------------------------------------------
 
 # If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
-# generate man pages 
+# generate man pages
 
 GENERATE_MAN           = NO
 
 # The MAN_OUTPUT tag is used to specify where the man pages will be put. 
 # If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `man' will be used as the default path. 
+# put in front of it. If left blank `man' will be used as the default path.
 
 MAN_OUTPUT             = man
 
 # The MAN_EXTENSION tag determines the extension that is added to 
-# the generated man pages (default is the subroutine's section .3) 
+# the generated man pages (default is the subroutine's section .3)
 
 MAN_EXTENSION          = .3
 
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_XML           = NO
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
 #---------------------------------------------------------------------------
 # Configuration options related to the preprocessor   
 #---------------------------------------------------------------------------
 
 # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
 # evaluate all C-preprocessor directives found in the sources and include 
-# files. 
+# files.
 
 ENABLE_PREPROCESSING   = YES
 
 # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
 # names in the source code. If set to NO (the default) only conditional 
 # compilation will be performed. Macro expansion can be done in a controlled 
-# way by setting EXPAND_ONLY_PREDEF to YES. 
+# way by setting EXPAND_ONLY_PREDEF to YES.
 
 MACRO_EXPANSION        = YES
 
 # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
 # then the macro expansion is limited to the macros specified with the 
-# PREDEFINED and EXPAND_AS_PREDEFINED tags. 
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
 
 EXPAND_ONLY_PREDEF     = YES
 
 # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
-# in the INCLUDE_PATH (see below) will be search if a #include is found. 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
 
 SEARCH_INCLUDES        = YES
 
 # The INCLUDE_PATH tag can be used to specify one or more directories that 
 # contain include files that are not input files but should be processed by 
-# the preprocessor. 
+# the preprocessor.
 
 INCLUDE_PATH           = 
 
 # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
 # patterns (like *.h and *.hpp) to filter out the header-files in the 
 # directories. If left blank, the patterns specified with FILE_PATTERNS will 
-# be used. 
+# be used.
 
-INCLUDE_FILE_PATTERNS = *.h
+INCLUDE_FILE_PATTERNS  = *.h
 
 # The PREDEFINED tag can be used to specify one or more macro names that 
 # are defined before the preprocessor is started (similar to the -D option of 
 # gcc). The argument of the tag is a list of macros of the form: name 
 # or name=definition (no spaces). If the definition and the = are 
-# omitted =1 is assumed. 
+# omitted =1 is assumed.
 
 PREDEFINED             = "GINAC_DECLARE_REGISTERED_CLASS_NO_CTORS(class, base)=" \
                          "GINAC_DECLARE_REGISTERED_CLASS(class, base)="
@@ -610,31 +799,45 @@ PREDEFINED             = "GINAC_DECLARE_REGISTERED_CLASS_NO_CTORS(class, base)="
 # If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then 
 # this tag can be used to specify a list of macro names that should be expanded. 
 # The macro definition that is found in the sources will be used. 
-# Use the PREDEFINED tag if you want to use a different macro definition. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
 
 EXPAND_AS_DEFINED      = 
 
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse the 
+# parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
 #---------------------------------------------------------------------------
 # Configuration::addtions related to external references   
 #---------------------------------------------------------------------------
 
-# The TAGFILES tag can be used to specify one or more tagfiles. 
+# The TAGFILES tag can be used to specify one or more tagfiles.
 
 TAGFILES               = 
 
 # When a file name is specified after GENERATE_TAGFILE, doxygen will create 
-# a tag file that is based on the input files it reads. 
+# a tag file that is based on the input files it reads.
 
 GENERATE_TAGFILE       = 
 
 # If the ALLEXTERNALS tag is set to YES all external classes will be listed 
 # in the class index. If set to NO only the inherited external classes 
-# will be listed. 
+# will be listed.
 
 ALLEXTERNALS           = NO
 
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
 # The PERL_PATH should be the absolute path and name of the perl script 
-# interpreter (i.e. the result of `which perl'). 
+# interpreter (i.e. the result of `which perl').
 
 PERL_PATH              = /usr/bin/perl
 
@@ -642,10 +845,24 @@ PERL_PATH              = /usr/bin/perl
 # Configuration options related to the dot tool   
 #---------------------------------------------------------------------------
 
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in Html, RTF and LaTeX) for classes with base or 
+# super classes. Setting the tag to NO turns the diagrams off. Note that this 
+# option is superceded by the HAVE_DOT option below. This is only a fallback. It is 
+# recommended to install and use dot, since it yield more powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
 # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
 # available from the path. This tool is part of Graphviz, a graph visualization 
 # toolkit from AT&T and Lucent Bell Labs. The other options in this section 
-# have no effect if this option is set to NO (the default) 
+# have no effect if this option is set to NO (the default)
 
 HAVE_DOT               = NO
 
@@ -659,38 +876,56 @@ CLASS_GRAPH            = YES
 # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
 # will generate a graph for each documented class showing the direct and 
 # indirect implementation dependencies (inheritance, containment, and 
-# class references variables) of the class with other documented classes. 
+# class references variables) of the class with other documented classes.
 
 COLLABORATION_GRAPH    = YES
 
-# If the ENABLE_PREPROCESSING, INCLUDE_GRAPH, and HAVE_DOT tags are set to 
-# YES then doxygen will generate a graph for each documented file showing 
-# the direct and indirect include dependencies of the file with other 
-# documented files. 
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
 
 INCLUDE_GRAPH          = NO
 
-# If the ENABLE_PREPROCESSING, INCLUDED_BY_GRAPH, and HAVE_DOT tags are set to 
-# YES then doxygen will generate a graph for each documented header file showing 
-# the documented files that directly or indirectly include this file 
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
 
 INCLUDED_BY_GRAPH      = NO
 
 # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
-# will graphical hierarchy of all classes instead of a textual one. 
+# will graphical hierarchy of all classes instead of a textual one.
 
 GRAPHICAL_HIERARCHY    = YES
 
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
 # The tag DOT_PATH can be used to specify the path where the dot tool can be 
-# found. If left blank, it is assumed the dot tool can be found on the path. 
+# found. If left blank, it is assumed the dot tool can be found on the path.
 
 DOT_PATH               = 
 
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
 # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
 # (in pixels) of the graphs generated by dot. If a graph becomes larger than 
 # this value, doxygen will try to truncate the graph, so that it fits within 
 # the specified constraint. Beware that most browsers cannot cope with very 
-# large images. 
+# large images.
 
 MAX_DOT_GRAPH_WIDTH    = 1024
 
@@ -698,56 +933,62 @@ MAX_DOT_GRAPH_WIDTH    = 1024
 # (in pixels) of the graphs generated by dot. If a graph becomes larger than 
 # this value, doxygen will try to truncate the graph, so that it fits within 
 # the specified constraint. Beware that most browsers cannot cope with very 
-# large images. 
+# large images.
 
 MAX_DOT_GRAPH_HEIGHT   = 1024
 
 # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
 # generate a legend page explaining the meaning of the various boxes and 
-# arrows in the dot generated graphs. 
+# arrows in the dot generated graphs.
 
 GENERATE_LEGEND        = YES
 
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermedate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
 #---------------------------------------------------------------------------
 # Configuration::addtions related to the search engine   
 #---------------------------------------------------------------------------
 
 # The SEARCHENGINE tag specifies whether or not a search engine should be 
-# used. If set to NO the values of all tags below this one will be ignored. 
+# used. If set to NO the values of all tags below this one will be ignored.
 
 SEARCHENGINE           = NO
 
 # The CGI_NAME tag should be the name of the CGI script that 
 # starts the search engine (doxysearch) with the correct parameters. 
-# A script with this name will be generated by doxygen. 
+# A script with this name will be generated by doxygen.
 
 CGI_NAME               = search.cgi
 
 # The CGI_URL tag should be the absolute URL to the directory where the 
 # cgi binaries are located. See the documentation of your http daemon for 
-# details. 
+# details.
 
 CGI_URL                = 
 
 # The DOC_URL tag should be the absolute URL to the directory where the 
 # documentation is located. If left blank the absolute path to the 
-# documentation, with file:// prepended to it, will be used. 
+# documentation, with file:// prepended to it, will be used.
 
 DOC_URL                = 
 
 # The DOC_ABSPATH tag should be the absolute path to the directory where the 
 # documentation is located. If left blank the directory on the local machine 
-# will be used. 
+# will be used.
 
 DOC_ABSPATH            = 
 
 # The BIN_ABSPATH tag must point to the directory where the doxysearch binary 
-# is installed. 
+# is installed.
 
-BIN_ABSPATH            = /usr/local/bin/
+BIN_ABSPATH            = /usr/bin/
 
 # The EXT_DOC_PATHS tag can be used to specify one or more paths to 
 # documentation generated for other projects. This allows doxysearch to search 
-# the documentation for these projects as well. 
+# the documentation for these projects as well.
 
 EXT_DOC_PATHS          = 
index 79eb970..4069480 100644 (file)
@@ -48,7 +48,7 @@ reference.ps: latex latex/reference.ps
 ginacreferencedir = `test -z "@REFERENCE_TARGETS@" || echo @datadir@/doc/GiNaC/reference`
 ginacreference_DATA = @REFERENCE_TARGETS@
 
-CLEANFILES = *.html *.gif doxygen.css *.ps latex/*
+CLEANFILES = *.html *.png doxygen.css *.ps latex/*
 EXTRA_DIST = DoxyfileHTML DoxyfileTEX Doxyfooter
 
 install-data-local:
@@ -61,7 +61,7 @@ install-data-local:
          echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginacreferencedir)/$$p"; \
          $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginacreferencedir)/$$p; \
        done
-       @for p in `echo $(srcdir)/*.gif | sed -e 's,[^ ]*/,,g' -e 's,\*\.gif,,'`; do \
+       @for p in `echo $(srcdir)/*.png | sed -e 's,[^ ]*/,,g' -e 's,\*\.png,,'`; do \
          echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginacreferencedir)/$$p"; \
          $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginacreferencedir)/$$p; \
        done
@@ -69,4 +69,4 @@ install-data-local:
 uninstall-local:
        rm -f $(DESTDIR)$(ginacreferencedir)/doxygen.css
        rm -f $(DESTDIR)$(ginacreferencedir)/*.html
-       rm -f $(DESTDIR)$(ginacreferencedir)/*.gif
+       rm -f $(DESTDIR)$(ginacreferencedir)/*.png
index 5174267..241d254 100644 (file)
@@ -808,7 +808,7 @@ at a singularity.
 The @code{pole_error} class has a member function
 
 @example
-int pole_error::degree(void) const;
+int pole_error::degree() const;
 @end example
 
 that returns the order of the singularity (or 0 when the pole is
@@ -831,7 +831,7 @@ exceptions generated by GiNaC:
 using namespace std;
 using namespace GiNaC;
 
-int main(void)
+int main()
 @{
     try @{
         ...
@@ -1274,6 +1274,7 @@ and safe simplifications are carried out like transforming
 @cindex @code{prepend()}
 @cindex @code{remove_first()}
 @cindex @code{remove_last()}
+@cindex @code{remove_all()}
 
 The GiNaC class @code{lst} serves for holding a @dfn{list} of arbitrary
 expressions. They are not as ubiquitous as in many other computer algebra
@@ -1303,11 +1304,60 @@ individual elements:
     ...
 @end example
 
+As with the standard @code{list<T>} container, accessing random elements of a
+@code{lst} is generally an operation of order @math{O(N)}. Faster read-only
+sequential access to the elements of a list is possible with the
+iterator types provided by the @code{lst} class:
+
+@example
+typedef ... lst::const_iterator;
+typedef ... lst::const_reverse_iterator;
+lst::const_iterator lst::begin() const;
+lst::const_iterator lst::end() const;
+lst::const_reverse_iterator lst::rbegin() const;
+lst::const_reverse_iterator lst::rend() const;
+@end example
+
+For example, to print the elements of a list individually you can use:
+
+@example
+    ...
+    // O(N)
+    for (lst::const_iterator i = l.begin(); i != l.end(); ++i)
+        cout << *i << endl;
+    ...
+@end example
+
+which is one order faster than
+
+@example
+    ...
+    // O(N^2)
+    for (size_t i = 0; i < l.nops(); ++i)
+        cout << l.op(i) << endl;
+    ...
+@end example
+
+These iterators also allow you to use some of the algorithms provided by
+the C++ standard library:
+
+@example
+    ...
+    // print the elements of the list (requires #include <iterator>)
+    copy(l.begin(), l.end(), ostream_iterator<ex>(cout, "\n"));
+
+    // sum up the elements of the list (requires #include <numeric>)
+    ex sum = accumulate(l.begin(), l.end(), ex(0));
+    cout << sum << endl;  // prints '2+2*x+2*y'
+    ...
+@end example
+
 @code{lst} is one of the few GiNaC classes that allow in-place modifications
 (the only other one is @code{matrix}). You can modify single elements:
 
 @example
     ...
+    l[1] = 42;       // l is now @{x, 42, y, x+y@}
     l.let_op(1) = 7; // l is now @{x, 7, y, x+y@}
     ...
 @end example
@@ -1332,6 +1382,14 @@ and @code{remove_last()}:
     ...
 @end example
 
+You can remove all the elements of a list with @code{remove_all()}:
+
+@example
+    ...
+    l.remove_all();     // l is now empty
+    ...
+@end example
+
 You can bring the elements of a list into a canonical order with @code{sort()}:
 
 @example
@@ -1515,9 +1573,8 @@ Here are a couple of examples of constructing matrices:
 @end example
 
 @cindex @code{transpose()}
-@cindex @code{inverse()}
 There are three ways to do arithmetic with matrices. The first (and most
-efficient one) is to use the methods provided by the @code{matrix} class:
+direct one) is to use the methods provided by the @code{matrix} class:
 
 @example
 matrix matrix::add(const matrix & other) const;
@@ -1525,8 +1582,7 @@ matrix matrix::sub(const matrix & other) const;
 matrix matrix::mul(const matrix & other) const;
 matrix matrix::mul_scalar(const ex & other) const;
 matrix matrix::pow(const ex & expn) const;
-matrix matrix::transpose(void) const;
-matrix matrix::inverse(void) const;
+matrix matrix::transpose() const;
 @end example
 
 All of these methods return the result as a new matrix object. Here is an
@@ -1604,16 +1660,36 @@ computing determinants, traces, and characteristic polynomials:
 @cindex @code{trace()}
 @cindex @code{charpoly()}
 @example
-ex matrix::determinant(unsigned algo = determinant_algo::automatic) const;
-ex matrix::trace(void) const;
+ex matrix::determinant(unsigned algo=determinant_algo::automatic) const;
+ex matrix::trace() const;
 ex matrix::charpoly(const symbol & lambda) const;
 @end example
 
-The @samp{algo} argument of @code{determinant()} allows to select between
-different algorithms for calculating the determinant. The possible values
-are defined in the @file{flags.h} header file. By default, GiNaC uses a
-heuristic to automatically select an algorithm that is likely to give the
-result most quickly.
+The @samp{algo} argument of @code{determinant()} allows to select
+between different algorithms for calculating the determinant.  The
+asymptotic speed (as parametrized by the matrix size) can greatly differ
+between those algorithms, depending on the nature of the matrix'
+entries.  The possible values are defined in the @file{flags.h} header
+file.  By default, GiNaC uses a heuristic to automatically select an
+algorithm that is likely (but not guaranteed) to give the result most
+quickly.
+
+@cindex @code{inverse()}
+@cindex @code{solve()}
+Matrices may also be inverted using the @code{ex matrix::inverse()}
+method and linear systems may be solved with:
+
+@example
+matrix matrix::solve(const matrix & vars, const matrix & rhs, unsigned algo=solve_algo::automatic) const;
+@end example
+
+Assuming the matrix object this method is applied on is an @code{m}
+times @code{n} matrix, then @code{vars} must be a @code{n} times
+@code{p} matrix of symbolic indeterminates and @code{rhs} a @code{m}
+times @code{p} matrix.  The returned matrix then has dimension @code{n}
+times @code{p} and in the case of an underdetermined system will still
+contain some of the indeterminates from @code{vars}.  If the system is
+overdetermined, an exception is thrown.
 
 
 @node Indexed objects, Non-commutative objects, Matrices, Basic Concepts
@@ -1678,6 +1754,9 @@ int main()
     symbol A("A");
     cout << indexed(A, i, j) << endl;
      // -> A.i.j
+    cout << index_dimensions << indexed(A, i, j) << endl;
+     // -> A.i[3].j[3]
+    cout << dflt; // reset cout to default output format (dimensions hidden)
     ...
 @end example
 
@@ -1690,6 +1769,10 @@ construct an expression containing one indexed object, @samp{A.i.j}. It has
 the symbol @code{A} as its base expression and the two indices @code{i} and
 @code{j}.
 
+The dimensions of indices are normally not visible in the output, but one
+can request them to be printed with the @code{index_dimensions} manipulator,
+as shown above.
+
 Note the difference between the indices @code{i} and @code{j} which are of
 class @code{idx}, and the index values which are the symbols @code{i_sym}
 and @code{j_sym}. The indices of indexed objects cannot directly be symbols
@@ -1738,8 +1821,8 @@ anything useful with it.
 The methods
 
 @example
-ex idx::get_value(void);
-ex idx::get_dimension(void);
+ex idx::get_value();
+ex idx::get_dimension();
 @end example
 
 return the value and dimension of an @code{idx} object. If you have an index
@@ -1750,10 +1833,10 @@ object, you can get a reference to the @code{idx} object with the function
 There are also the methods
 
 @example
-bool idx::is_numeric(void);
-bool idx::is_symbolic(void);
-bool idx::is_dim_numeric(void);
-bool idx::is_dim_symbolic(void);
+bool idx::is_numeric();
+bool idx::is_symbolic();
+bool idx::is_dim_numeric();
+bool idx::is_dim_symbolic();
 @end example
 
 for checking whether the value and dimension are numeric or symbolic
@@ -1784,8 +1867,8 @@ this can be overridden by supplying a third argument to the @code{varidx}
 constructor. The two methods
 
 @example
-bool varidx::is_covariant(void);
-bool varidx::is_contravariant(void);
+bool varidx::is_covariant();
+bool varidx::is_contravariant();
 @end example
 
 allow you to check the variance of a @code{varidx} object (use @code{ex_to<varidx>()}
@@ -1793,7 +1876,7 @@ to get the object reference from an expression). There's also the very useful
 method
 
 @example
-ex varidx::toggle_variance(void);
+ex varidx::toggle_variance();
 @end example
 
 which makes a new index with the same value and dimension but the opposite
@@ -1827,8 +1910,8 @@ supplying a fourth argument to the @code{spinidx} constructor. The two
 methods
 
 @example
-bool spinidx::is_dotted(void);
-bool spinidx::is_undotted(void);
+bool spinidx::is_dotted();
+bool spinidx::is_undotted();
 @end example
 
 allow you to check whether or not a @code{spinidx} object is dotted (use
@@ -1836,8 +1919,8 @@ allow you to check whether or not a @code{spinidx} object is dotted (use
 Finally, the two methods
 
 @example
-ex spinidx::toggle_dot(void);
-ex spinidx::toggle_variance_dot(void);
+ex spinidx::toggle_dot();
+ex spinidx::toggle_variance_dot();
 @end example
 
 create a new index with the same value and dimension but opposite dottedness
@@ -1997,7 +2080,7 @@ indices into a canonical order which allows for some immediate simplifications:
 @end example
 
 @cindex @code{get_free_indices()}
-@cindex Dummy index
+@cindex dummy index
 @subsection Dummy indices
 
 GiNaC treats certain symbolic index pairs as @dfn{dummy indices} meaning
@@ -2058,7 +2141,7 @@ and calculating traces and convolutions of matrices and predefined tensors)
 there is the method
 
 @example
-ex ex::simplify_indexed(void);
+ex ex::simplify_indexed();
 ex ex::simplify_indexed(const scalar_products & sp);
 @end example
 
@@ -2408,8 +2491,8 @@ Information about the commutativity of an object or expression can be
 obtained with the two member functions
 
 @example
-unsigned ex::return_type(void) const;
-unsigned ex::return_type_tinfo(void) const;
+unsigned ex::return_type() const;
+unsigned ex::return_type_tinfo() const;
 @end example
 
 The @code{return_type()} function returns one of three values (defined in
@@ -2795,12 +2878,14 @@ avoided.
 * Substituting Expressions::
 * Pattern Matching and Advanced Substitutions::
 * Applying a Function on Subexpressions::
+* Visitors and Tree Traversal::
 * Polynomial Arithmetic::           Working with polynomials.
 * Rational Expressions::            Working with rational functions.
 * Symbolic Differentiation::
 * Series Expansion::                Taylor and Laurent expansion.
 * Symmetrization::
 * Built-in Functions::              List of predefined mathematical functions.
+* Solving Linear Systems of Equations::
 * Input/Output::                    Input and output of expressions.
 @end menu
 
@@ -2826,8 +2911,8 @@ GiNaC provides a couple of functions for this:
 bool is_a<T>(const ex & e);
 bool is_exactly_a<T>(const ex & e);
 bool ex::info(unsigned flag);
-unsigned ex::return_type(void) const;
-unsigned ex::return_type_tinfo(void) const;
+unsigned ex::return_type() const;
+unsigned ex::return_type_tinfo() const;
 @end example
 
 When the test made by @code{is_a<T>()} returns true, it is safe to call
@@ -2955,8 +3040,8 @@ for an explanation of these.
 GiNaC provides the two methods
 
 @example
-unsigned ex::nops();
-ex ex::op(unsigned i);
+size_t ex::nops();
+ex ex::op(size_t i);
 @end example
 
 for accessing the subexpressions in the container-like GiNaC classes like
@@ -3286,9 +3371,9 @@ bool ex::find(const ex & pattern, lst & found);
 @end example
 
 works a bit like @code{has()} but it doesn't stop upon finding the first
-match. Instead, it inserts all found matches into the specified list. If
-there are multiple occurrences of the same expression, it is entered only
-once to the list. @code{find()} returns false if no matches were found (in
+match. Instead, it appends all found matches to the specified list. If there
+are multiple occurrences of the same expression, it is entered only once to
+the list. @code{find()} returns false if no matches were found (in
 @command{ginsh}, it returns an empty list):
 
 @example
@@ -3348,11 +3433,63 @@ The last example would be written in C++ in this way:
 @}
 @end example
 
+@subsection Algebraic substitutions
+The @code{subs()} method has an extra, optional, argument. This argument can
+be used to pass one of the @code{subs_options} to it. The only option that is
+currently available is the @code{subs_algebraic} option which affects
+products and powers. If you want to substitute some factors of a product, you
+only need to list these factors in your pattern. Furthermore, if an (integer)
+power of some expression occurs in your pattern and in the expression that you
+want the substitution to occur in, it can be substituted as many times as
+possible, without getting negative powers.
+
+An example clarifies it all (hopefully):
+
+@example
+cout << (a*a*a*a+b*b*b*b+pow(x+y,4)).subs(wild()*wild()==pow(wild(),3),
+                                        subs_options::subs_algebraic) << endl;
+// --> (y+x)^6+b^6+a^6
+
+cout << ((a+b+c)*(a+b+c)).subs(a+b==x,subs_options::subs_algebraic) << endl;
+// --> (c+b+a)^2
+// Powers and products are smart, but addition is just the same.
+
+cout << ((a+b+c)*(a+b+c)).subs(a+b+wild()==x+wild(), subs_options::subs_algebraic)
+                                                                      << endl;
+// --> (x+c)^2
+// As I said: addition is just the same.
+
+cout << (pow(a,5)*pow(b,7)+2*b).subs(b*b*a==x,subs_options::subs_algebraic) << endl;
+// --> x^3*b*a^2+2*b
+
+cout << (pow(a,-5)*pow(b,-7)+2*b).subs(1/(b*b*a)==x,subs_options::subs_algebraic)
+                                                                       << endl;
+// --> 2*b+x^3*b^(-1)*a^(-2)
+
+cout << (4*x*x*x-2*x*x+5*x-1).subs(x==a,subs_options::subs_algebraic) << endl;
+// --> -1-2*a^2+4*a^3+5*a
+
+cout << (4*x*x*x-2*x*x+5*x-1).subs(pow(x,wild())==pow(a,wild()),
+                                subs_options::subs_algebraic) << endl;
+// --> -1+5*x+4*x^3-2*x^2
+// You should not really need this kind of patterns very often now.
+// But perhaps this it's-not-a-bug-it's-a-feature (c/sh)ould still change.
+
+cout << ex(sin(1+sin(x))).subs(sin(wild())==cos(wild()),
+                                subs_options::subs_algebraic) << endl;
+// --> cos(1+cos(x))
+
+cout << expand((a*sin(x+y)*sin(x+y)+a*cos(x+y)*cos(x+y)+b)
+        .subs((pow(cos(wild()),2)==1-pow(sin(wild()),2)),
+                                subs_options::subs_algebraic)) << endl;
+// --> b+a
+@end example
+
 
-@node Applying a Function on Subexpressions, Polynomial Arithmetic, Pattern Matching and Advanced Substitutions, Methods and Functions
+@node Applying a Function on Subexpressions, Visitors and Tree Traversal, Pattern Matching and Advanced Substitutions, Methods and Functions
 @c    node-name, next, previous, up
 @section Applying a Function on Subexpressions
-@cindex Tree traversal
+@cindex tree traversal
 @cindex @code{map()}
 
 Sometimes you may want to perform an operation on specific parts of an
@@ -3369,7 +3506,7 @@ ex calc_trace(ex e)
         return ex_to<matrix>(e).trace();
     else if (is_a<add>(e)) @{
         ex sum = 0;
-        for (unsigned i=0; i<e.nops(); i++)
+        for (size_t i=0; i<e.nops(); i++)
             sum += calc_trace(e.op(i));
         return sum;
     @} else if (is_a<mul>)(e)) @{
@@ -3494,7 +3631,214 @@ argument. You can not use functions like @samp{diff()}, @samp{op()},
 @end example
 
 
-@node Polynomial Arithmetic, Rational Expressions, Applying a Function on Subexpressions, Methods and Functions
+@node Visitors and Tree Traversal, Polynomial Arithmetic, Applying a Function on Subexpressions, Methods and Functions
+@c    node-name, next, previous, up
+@section Visitors and Tree Traversal
+@cindex tree traversal
+@cindex @code{visitor} (class)
+@cindex @code{accept()}
+@cindex @code{visit()}
+@cindex @code{traverse()}
+@cindex @code{traverse_preorder()}
+@cindex @code{traverse_postorder()}
+
+Suppose that you need a function that returns a list of all indices appearing
+in an arbitrary expression. The indices can have any dimension, and for
+indices with variance you always want the covariant version returned.
+
+You can't use @code{get_free_indices()} because you also want to include
+dummy indices in the list, and you can't use @code{find()} as it needs
+specific index dimensions (and it would require two passes: one for indices
+with variance, one for plain ones).
+
+The obvious solution to this problem is a tree traversal with a type switch,
+such as the following:
+
+@example
+void gather_indices_helper(const ex & e, lst & l)
+@{
+    if (is_a<varidx>(e)) @{
+        const varidx & vi = ex_to<varidx>(e);
+        l.append(vi.is_covariant() ? vi : vi.toggle_variance());
+    @} else if (is_a<idx>(e)) @{
+        l.append(e);
+    @} else @{
+        size_t n = e.nops();
+        for (size_t i = 0; i < n; ++i)
+            gather_indices_helper(e.op(i), l);
+    @}
+@}
+
+lst gather_indices(const ex & e)
+@{
+    lst l;
+    gather_indices_helper(e, l);
+    l.sort();
+    l.unique();
+    return l;
+@}
+@end example
+
+This works fine but fans of object-oriented programming will feel
+uncomfortable with the type switch. One reason is that there is a possibility
+for subtle bugs regarding derived classes. If we had, for example, written
+
+@example
+    if (is_a<idx>(e)) @{
+      ...
+    @} else if (is_a<varidx>(e)) @{
+      ...
+@end example
+
+in @code{gather_indices_helper}, the code wouldn't have worked because the
+first line "absorbs" all classes derived from @code{idx}, including
+@code{varidx}, so the special case for @code{varidx} would never have been
+executed.
+
+Also, for a large number of classes, a type switch like the above can get
+unwieldy and inefficient (it's a linear search, after all).
+@code{gather_indices_helper} only checks for two classes, but if you had to
+write a function that required a different implementation for nearly
+every GiNaC class, the result would be very hard to maintain and extend.
+
+The cleanest approach to the problem would be to add a new virtual function
+to GiNaC's class hierarchy. In our example, there would be specializations
+for @code{idx} and @code{varidx} while the default implementation in
+@code{basic} performed the tree traversal. Unfortunately, in C++ it's
+impossible to add virtual member functions to existing classes without
+changing their source and recompiling everything. GiNaC comes with source,
+so you could actually do this, but for a small algorithm like the one
+presented this would be impractical.
+
+One solution to this dilemma is the @dfn{Visitor} design pattern,
+which is implemented in GiNaC (actually, Robert Martin's Acyclic Visitor
+variation, described in detail in
+@uref{http://objectmentor.com/publications/acv.pdf}). Instead of adding
+virtual functions to the class hierarchy to implement operations, GiNaC
+provides a single "bouncing" method @code{accept()} that takes an instance
+of a special @code{visitor} class and redirects execution to the one
+@code{visit()} virtual function of the visitor that matches the type of
+object that @code{accept()} was being invoked on.
+
+Visitors in GiNaC must derive from the global @code{visitor} class as well
+as from the class @code{T::visitor} of each class @code{T} they want to
+visit, and implement the member functions @code{void visit(const T &)} for
+each class.
+
+A call of
+
+@example
+void ex::accept(visitor & v) const;
+@end example
+
+will then dispatch to the correct @code{visit()} member function of the
+specified visitor @code{v} for the type of GiNaC object at the root of the
+expression tree (e.g. a @code{symbol}, an @code{idx} or a @code{mul}).
+
+Here is an example of a visitor:
+
+@example
+class my_visitor
+ : public visitor,          // this is required
+   public add::visitor,     // visit add objects
+   public numeric::visitor, // visit numeric objects
+   public basic::visitor    // visit basic objects
+@{
+    void visit(const add & x)
+    @{ cout << "called with an add object" << endl; @}
+
+    void visit(const numeric & x)
+    @{ cout << "called with a numeric object" << endl; @}
+
+    void visit(const basic & x)
+    @{ cout << "called with a basic object" << endl; @}
+@};
+@end example
+
+which can be used as follows:
+
+@example
+...
+    symbol x("x");
+    ex e1 = 42;
+    ex e2 = 4*x-3;
+    ex e3 = 8*x;
+
+    my_visitor v;
+    e1.accept(v);
+     // prints "called with a numeric object"
+    e2.accept(v);
+     // prints "called with an add object"
+    e3.accept(v);
+     // prints "called with a basic object"
+...
+@end example
+
+The @code{visit(const basic &)} method gets called for all objects that are
+not @code{numeric} or @code{add} and acts as an (optional) default.
+
+From a conceptual point of view, the @code{visit()} methods of the visitor
+behave like a newly added virtual function of the visited hierarchy.
+In addition, visitors can store state in member variables, and they can
+be extended by deriving a new visitor from an existing one, thus building
+hierarchies of visitors.
+
+We can now rewrite our index example from above with a visitor:
+
+@example
+class gather_indices_visitor
+ : public visitor, public idx::visitor, public varidx::visitor
+@{
+    lst l;
+
+    void visit(const idx & i)
+    @{
+        l.append(i);
+    @}
+
+    void visit(const varidx & vi)
+    @{
+        l.append(vi.is_covariant() ? vi : vi.toggle_variance());
+    @}
+
+public:
+    const lst & get_result() // utility function
+    @{
+        l.sort();
+        l.unique();
+        return l;
+    @}
+@};
+@end example
+
+What's missing is the tree traversal. We could implement it in
+@code{visit(const basic &)}, but GiNaC has predefined methods for this:
+
+@example
+void ex::traverse_preorder(visitor & v) const;
+void ex::traverse_postorder(visitor & v) const;
+void ex::traverse(visitor & v) const;
+@end example
+
+@code{traverse_preorder()} visits a node @emph{before} visiting its
+subexpressions, while @code{traverse_postorder()} visits a node @emph{after}
+visiting its subexpressions. @code{traverse()} is a synonym for
+@code{traverse_preorder()}.
+
+Here is a new implementation of @code{gather_indices()} that uses the visitor
+and @code{traverse()}:
+
+@example
+lst gather_indices(const ex & e)
+@{
+    gather_indices_visitor v;
+    e.traverse(v);
+    return v.get_result();
+@}
+@end example
+
+
+@node Polynomial Arithmetic, Rational Expressions, Visitors and Tree Traversal, Methods and Functions
 @c    node-name, next, previous, up
 @section Polynomial arithmetic
 
@@ -3592,34 +3936,9 @@ int ex::degree(const ex & s);
 int ex::ldegree(const ex & s);
 @end example
 
-These functions only work reliably if the input polynomial is collected in
-terms of the object @samp{s}. Otherwise, they are only guaranteed to return
-the upper/lower bounds of the exponents. If you need accurate results, you
-have to call @code{expand()} and/or @code{collect()} on the input polynomial.
-For example
-
-@example
-> a=(x+1)^2-x^2;
-(1+x)^2-x^2;
-> degree(a,x);
-2
-> degree(expand(a),x);
-1
-@end example
-
-@code{degree()} also works on rational functions, returning the asymptotic
-degree:
-
-@example
-> degree((x+1)/(x^3+1),x);
--2
-@end example
-
-If the input is not a polynomial or rational function in the variable @samp{s},
-the behavior of @code{degree()} and @code{ldegree()} is undefined.
-
-To extract a coefficient with a certain power from an expanded
-polynomial you use
+which also work reliably on non-expanded input polynomials (they even work
+on rational functions, returning the asymptotic degree). To extract
+a coefficient with a certain power from an expanded polynomial you use
 
 @example
 ex ex::coeff(const ex & s, int n);
@@ -3890,7 +4209,8 @@ If you need both numerator and denominator, calling @code{numer_denom()} is
 faster than using @code{numer()} and @code{denom()} separately.
 
 
-@subsection Converting to a rational expression
+@subsection Converting to a polynomial or rational expression
+@cindex @code{to_polynomial()}
 @cindex @code{to_rational()}
 
 Some of the methods described so far only work on polynomials or rational
@@ -3898,6 +4218,10 @@ functions. GiNaC provides a way to extend the domain of these functions to
 general expressions by using the temporary replacement algorithm described
 above. You do this by calling
 
+@example
+ex ex::to_polynomial(lst &l);
+@end example
+or
 @example
 ex ex::to_rational(lst &l);
 @end example
@@ -3906,10 +4230,33 @@ on the expression to be converted. The supplied @code{lst} will be filled
 with the generated temporary symbols and their replacement expressions in
 a format that can be used directly for the @code{subs()} method. It can also
 already contain a list of replacements from an earlier application of
-@code{.to_rational()}, so it's possible to use it on multiple expressions
-and get consistent results.
+@code{.to_polynomial()} or @code{.to_rational()}, so it's possible to use
+it on multiple expressions and get consistent results.
+
+The difference betwerrn @code{.to_polynomial()} and @code{.to_rational()}
+is probably best illustrated with an example:
+
+@example
+@{
+    symbol x("x"), y("y");
+    ex a = 2*x/sin(x) - y/(3*sin(x));
+    cout << a << endl;
+
+    lst lp;
+    ex p = a.to_polynomial(lp);
+    cout << " = " << p << "\n   with " << lp << endl;
+     // = symbol3*symbol2*y+2*symbol2*x
+     //   with @{symbol2==sin(x)^(-1),symbol3==-1/3@}
+
+    lst lr;
+    ex r = a.to_rational(lr);
+    cout << " = " << r << "\n   with " << lr << endl;
+     // = -1/3*symbol4^(-1)*y+2*symbol4^(-1)*x
+     //   with @{symbol4==sin(x)@}
+@}
+@end example
 
-For example,
+The following more useful example will print @samp{sin(x)-cos(x)}:
 
 @example
 @{
@@ -3918,13 +4265,11 @@ For example,
     ex b = sin(x) + cos(x);
     ex q;
     lst l;
-    divide(a.to_rational(l), b.to_rational(l), q);
+    divide(a.to_polynomial(l), b.to_polynomial(l), q);
     cout << q.subs(l) << endl;
 @}
 @end example
 
-will print @samp{sin(x)-cos(x)}.
-
 
 @node Symbolic Differentiation, Series Expansion, Rational Expressions, Methods and Functions
 @c    node-name, next, previous, up
@@ -4042,19 +4387,21 @@ value of Archimedes' constant
 $\pi$
 @end tex
 (for which there already exists the built-in constant @code{Pi}) 
-using Machin's amazing formula
+using John Machin's amazing formula
 @tex
 $\pi=16$~atan~$\!\left(1 \over 5 \right)-4$~atan~$\!\left(1 \over 239 \right)$.
 @end tex
 @ifnottex
 @math{Pi==16*atan(1/5)-4*atan(1/239)}.
 @end ifnottex
-We may expand the arcus tangent around @code{0} and insert the fractions
-@code{1/5} and @code{1/239}.  But, as we have seen, a series in GiNaC
-carries an order term with it and the question arises what the system is
-supposed to do when the fractions are plugged into that order term.  The
-solution is to use the function @code{series_to_poly()} to simply strip
-the order term off:
+This equation (and similar ones) were used for over 200 years for
+computing digits of pi (see @cite{Pi Unleashed}).  We may expand the
+arcus tangent around @code{0} and insert the fractions @code{1/5} and
+@code{1/239}.  However, as we have seen, a series in GiNaC carries an
+order term with it and the question arises what the system is supposed
+to do when the fractions are plugged into that order term.  The solution
+is to use the function @code{series_to_poly()} to simply strip the order
+term off:
 
 @example
 #include <ginac/ginac.h>
@@ -4150,7 +4497,7 @@ almost any kind of object (anything that is @code{subs()}able):
 @end example
 
 
-@node Built-in Functions, Input/Output, Symmetrization, Methods and Functions
+@node Built-in Functions, Solving Linear Systems of Equations, Symmetrization, Methods and Functions
 @c    node-name, next, previous, up
 @section Predefined mathematical functions
 
@@ -4264,7 +4611,48 @@ standard incorporate these functions in the complex domain in a manner
 compatible with C99.
 
 
-@node Input/Output, Extending GiNaC, Built-in Functions, Methods and Functions
+@node Solving Linear Systems of Equations, Input/Output, Built-in Functions, Methods and Functions
+@c    node-name, next, previous, up
+@section Solving Linear Systems of Equations
+@cindex @code{lsolve()}
+
+The function @code{lsolve()} provides a convenient wrapper around some
+matrix operations that comes in handy when a system of linear equations
+needs to be solved:
+
+@example
+ex lsolve(const ex &eqns, const ex &symbols, unsigned options=solve_algo::automatic);
+@end example
+
+Here, @code{eqns} is a @code{lst} of equalities (i.e. class
+@code{relational}) while @code{symbols} is a @code{lst} of
+indeterminates.  (@xref{The Class Hierarchy}, for an exposition of class
+@code{lst}).
+
+It returns the @code{lst} of solutions as an expression.  As an example,
+let us solve the two equations @code{a*x+b*y==3} and @code{x-y==b}:
+
+@example
+@{
+    symbol a("a"), b("b"), x("x"), y("y");
+    lst eqns;
+    eqns.append(a*x+b*y==3).append(x-y==b);
+    lst vars;
+    vars.append(x).append(y);
+    cout << lsolve(eqns, vars) << endl;
+    // -> @{x==(3+b^2)/(b+a),y==(3-b*a)/(b+a)@}
+@end example
+
+When the linear equations @code{eqns} are underdetermined, the solution
+will contain one or more tautological entries like @code{x==x},
+depending on the rank of the system.  When they are overdetermined, the
+solution will be an empty @code{lst}.  Note the third optional parameter
+to @code{lsolve()}: it accepts the same parameters as
+@code{matrix::solve()}.  This is because @code{lsolve} is just a wrapper
+around that method.
+
+
+@node Input/Output, Extending GiNaC, Solving Linear Systems of Equations, Methods and Functions
 @c    node-name, next, previous, up
 @section Input and output of expressions
 @cindex I/O
@@ -4273,70 +4661,99 @@ compatible with C99.
 @cindex printing
 @cindex output of expressions
 
-The easiest way to print an expression is to write it to a stream:
+Expressions can simply be written to any stream:
 
 @example
 @{
     symbol x("x");
-    ex e = 4.5+pow(x,2)*3/2;
-    cout << e << endl;    // prints '(4.5)+3/2*x^2'
+    ex e = 4.5*I+pow(x,2)*3/2;
+    cout << e << endl;    // prints '4.5*I+3/2*x^2'
     // ...
 @end example
 
-The output format is identical to the @command{ginsh} input syntax and
+The default output format is identical to the @command{ginsh} input syntax and
 to that used by most computer algebra systems, but not directly pastable
 into a GiNaC C++ program (note that in the above example, @code{pow(x,2)}
 is printed as @samp{x^2}).
 
 It is possible to print expressions in a number of different formats with
-the method
+a set of stream manipulators;
 
 @example
-void ex::print(const print_context & c, unsigned level = 0);
+std::ostream & dflt(std::ostream & os);
+std::ostream & latex(std::ostream & os);
+std::ostream & tree(std::ostream & os);
+std::ostream & csrc(std::ostream & os);
+std::ostream & csrc_float(std::ostream & os);
+std::ostream & csrc_double(std::ostream & os);
+std::ostream & csrc_cl_N(std::ostream & os);
+std::ostream & index_dimensions(std::ostream & os);
+std::ostream & no_index_dimensions(std::ostream & os);
 @end example
 
-@cindex @code{print_context} (class)
-The type of @code{print_context} object passed in determines the format
-of the output. The possible types are defined in @file{ginac/print.h}.
-All constructors of @code{print_context} and derived classes take an
-@code{ostream &} as their first argument.
+The @code{tree}, @code{latex} and @code{csrc} formats are also available in
+@command{ginsh} via the @code{print()}, @code{print_latex()} and
+@code{print_csrc()} functions, respectively.
 
-To print an expression in a way that can be directly used in a C or C++
-program, you pass a @code{print_csrc} object like this:
+@cindex @code{dflt}
+All manipulators affect the stream state permanently. To reset the output
+format to the default, use the @code{dflt} manipulator:
 
 @example
     // ...
-    cout << "float f = ";
-    e.print(print_csrc_float(cout));
-    cout << ";\n";
+    cout << latex;            // all output to cout will be in LaTeX format from now on
+    cout << e << endl;        // prints '4.5 i+\frac@{3@}@{2@} x^@{2@}'
+    cout << sin(x/2) << endl; // prints '\sin(\frac@{1@}@{2@} x)'
+    cout << dflt;             // revert to default output format
+    cout << e << endl;        // prints '4.5*I+3/2*x^2'
+    // ...
+@end example
 
-    cout << "double d = ";
-    e.print(print_csrc_double(cout));
-    cout << ";\n";
+If you don't want to affect the format of the stream you're working with,
+you can output to a temporary @code{ostringstream} like this:
 
-    cout << "cl_N n = ";
-    e.print(print_csrc_cl_N(cout));
-    cout << ";\n";
+@example
+    // ...
+    ostringstream s;
+    s << latex << e;         // format of cout remains unchanged
+    cout << s.str() << endl; // prints '4.5 i+\frac@{3@}@{2@} x^@{2@}'
     // ...
 @end example
 
-The three possible types mostly affect the way in which floating point
-numbers are written.
+@cindex @code{csrc}
+@cindex @code{csrc_float}
+@cindex @code{csrc_double}
+@cindex @code{csrc_cl_N}
+The @code{csrc} (an alias for @code{csrc_double}), @code{csrc_float},
+@code{csrc_double} and @code{csrc_cl_N} manipulators set the output to a
+format that can be directly used in a C or C++ program. The three possible
+formats select the data types used for numbers (@code{csrc_cl_N} uses the
+classes provided by the CLN library):
 
-The above example will produce (note the @code{x^2} being converted to @code{x*x}):
+@example
+    // ...
+    cout << "f = " << csrc_float << e << ";\n";
+    cout << "d = " << csrc_double << e << ";\n";
+    cout << "n = " << csrc_cl_N << e << ";\n";
+    // ...
+@end example
+
+The above example will produce (note the @code{x^2} being converted to
+@code{x*x}):
 
 @example
-float f = (3.0/2.0)*(x*x)+4.500000e+00;
-double d = (3.0/2.0)*(x*x)+4.5000000000000000e+00;
-cl_N n = cln::cl_RA("3/2")*(x*x)+cln::cl_F("4.5_17");
+f = (3.0/2.0)*(x*x)+std::complex<float>(0.0,4.5000000e+00);
+d = (3.0/2.0)*(x*x)+std::complex<double>(0.0,4.5000000000000000e+00);
+n = cln::cl_RA("3/2")*(x*x)+cln::complex(cln::cl_I("0"),cln::cl_F("4.5_17"));
 @end example
 
-The @code{print_context} type @code{print_tree} provides a dump of the
-internal structure of an expression for debugging purposes:
+@cindex @code{tree}
+The @code{tree} manipulator allows dumping the internal structure of an
+expression for debugging purposes:
 
 @example
     // ...
-    e.print(print_tree(cout));
+    cout << tree << e;
 @}
 @end example
 
@@ -4344,41 +4761,63 @@ produces
 
 @example
 add, hash=0x0, flags=0x3, nops=2
-    power, hash=0x9, flags=0x3, nops=2
-        x (symbol), serial=3, hash=0x44a113a6, flags=0xf
-        2 (numeric), hash=0x80000042, flags=0xf
-    3/2 (numeric), hash=0x80000061, flags=0xf
+    power, hash=0x0, flags=0x3, nops=2
+        x (symbol), serial=0, hash=0xc8d5bcdd, flags=0xf
+        2 (numeric), hash=0x6526b0fa, flags=0xf
+    3/2 (numeric), hash=0xf9828fbd, flags=0xf
     -----
     overall_coeff
-    4.5L0 (numeric), hash=0x8000004b, flags=0xf
+    4.5L0i (numeric), hash=0xa40a97e0, flags=0xf
     =====
 @end example
 
-This kind of output is also available in @command{ginsh} as the @code{print()}
-function.
-
-Another useful output format is for LaTeX parsing in mathematical mode.
-It is rather similar to the default @code{print_context} but provides
-some braces needed by LaTeX for delimiting boxes and also converts some
-common objects to conventional LaTeX names. It is possible to give symbols
-a special name for LaTeX output by supplying it as a second argument to
-the @code{symbol} constructor.
+@cindex @code{latex}
+The @code{latex} output format is for LaTeX parsing in mathematical mode.
+It is rather similar to the default format but provides some braces needed
+by LaTeX for delimiting boxes and also converts some common objects to
+conventional LaTeX names. It is possible to give symbols a special name for
+LaTeX output by supplying it as a second argument to the @code{symbol}
+constructor.
 
 For example, the code snippet
 
 @example
-    // ...
-    symbol x("x");
-    ex foo = lgamma(x).series(x==0,3);
-    foo.print(print_latex(std::cout));
+@{
+    symbol x("x", "\\circ");
+    ex e = lgamma(x).series(x==0,3);
+    cout << latex << e << endl;
+@}
+@end example
+
+will print
+
+@example
+    @{(-\ln(\circ))@}+@{(-\gamma_E)@} \circ+@{(\frac@{1@}@{12@} \pi^@{2@})@} \circ^@{2@}+\mathcal@{O@}(\circ^@{3@})
 @end example
 
-will print out:
+@cindex @code{index_dimensions}
+@cindex @code{no_index_dimensions}
+Index dimensions are normally hidden in the output. To make them visible, use
+the @code{index_dimensions} manipulator. The dimensions will be written in
+square brackets behind each index value in the default and LaTeX output
+formats:
 
 @example
-    @{(-\ln(x))@}+@{(-\gamma_E)@} x+@{(1/12 \pi^2)@} x^@{2@}+\mathcal@{O@}(x^3)
+@{
+    symbol x("x"), y("y");
+    varidx mu(symbol("mu"), 4), nu(symbol("nu"), 4);
+    ex e = indexed(x, mu) * indexed(y, nu);
+
+    cout << e << endl;
+     // prints 'x~mu*y~nu'
+    cout << index_dimensions << e << endl;
+     // prints 'x~mu[4]*y~nu[4]'
+    cout << no_index_dimensions << e << endl;
+     // prints 'x~mu*y~nu'
+@}
 @end example
 
+
 @cindex Tree traversal
 If you need any fancy special output format, e.g. for interfacing GiNaC
 with other algebra systems or for producing code for different
@@ -4392,9 +4831,9 @@ static void my_print(const ex & e)
     else
         cout << e.bp->class_name();
     cout << "(";
-    unsigned n = e.nops();
+    size_t n = e.nops();
     if (n)
-        for (unsigned i=0; i<n; i++) @{
+        for (size_t i=0; i<n; i++) @{
             my_print(e.op(i));
             if (i != n-1)
                 cout << ",";
@@ -4404,7 +4843,7 @@ static void my_print(const ex & e)
     cout << ")";
 @}
 
-int main(void)
+int main()
 @{
     my_print(pow(3, x) - 2 * sin(y / Pi)); cout << endl;
     return 0;
@@ -4435,22 +4874,19 @@ and have the @samp{x} and @samp{y} correspond to the symbols @code{x} and
 desired symbols to the @code{>>} stream input operator.
 
 Instead, GiNaC lets you construct an expression from a string, specifying the
-list of symbols and indices to be used:
+list of symbols to be used:
 
 @example
 @{
-    symbol x("x"), y("y"), p("p");
-    idx i(symbol("i"), 3);
-    ex e("2*x+sin(y)+p.i", lst(x, y, p, i));
+    symbol x("x"), y("y");
+    ex e("2*x+sin(y)", lst(x, y));
 @}
 @end example
 
 The input syntax is the same as that used by @command{ginsh} and the stream
-output operator @code{<<}. The symbols and indices in the string are matched
-by name to the symbols and indices in the list and if GiNaC encounters a
-symbol or index not specified in the list it will throw an exception. Only
-indices whose values are single symbols can be used (i.e. numeric indices
-or compound indices as in "A.(2*n+1)" are not allowed).
+output operator @code{<<}. The symbols in the string are matched by name to
+the symbols in the list and if GiNaC encounters a symbol not specified in
+the list it will throw an exception.
 
 With this constructor, it's also easy to implement interactive GiNaC programs:
 
@@ -4582,8 +5018,8 @@ static void my_print2(const archive_node & n)
     archive_node::propinfovector p;
     n.get_properties(p);
 
-    unsigned num = p.size();
-    for (unsigned i=0; i<num; i++) @{
+    size_t num = p.size();
+    for (size_t i=0; i<num; i++) @{
         const string &name = p[i].name;
         if (name == "class")
             continue;
@@ -4634,7 +5070,7 @@ static void my_print2(const archive_node & n)
     cout << ")";
 @}
 
-int main(void)
+int main()
 @{
     ex e = pow(2, x) - y;
     archive ar(e, "e");
@@ -4669,7 +5105,8 @@ authors---they will happily incorporate them into future versions.
 @menu
 * What does not belong into GiNaC::  What to avoid.
 * Symbolic functions::               Implementing symbolic functions.
-* Adding classes::                   Defining new algebraic classes.
+* Structures::                       Defining new algebraic classes (the easy way).
+* Adding classes::                   Defining new algebraic classes (the hard way).
 @end menu
 
 
@@ -4697,7 +5134,7 @@ inefficient.  For this purpose, the underlying foundation classes
 provided by CLN are much better suited.
 
 
-@node Symbolic functions, Adding classes, What does not belong into GiNaC, Extending GiNaC
+@node Symbolic functions, Structures, What does not belong into GiNaC, Extending GiNaC
 @c    node-name, next, previous, up
 @section Symbolic functions
 
@@ -4963,21 +5400,375 @@ specifications. GiNaC will automatically rearrange the arguments of
 symmetric functions into a canonical order.
 
 
-@node Adding classes, A Comparison With Other CAS, Symbolic functions, Extending GiNaC
+@node Structures, Adding classes, Symbolic functions, Extending GiNaC
+@c    node-name, next, previous, up
+@section Structures
+
+If you are doing some very specialized things with GiNaC, or if you just
+need some more organized way to store data in your expressions instead of
+anonymous lists, you may want to implement your own algebraic classes.
+('algebraic class' means any class directly or indirectly derived from
+@code{basic} that can be used in GiNaC expressions).
+
+GiNaC offers two ways of accomplishing this: either by using the
+@code{structure<T>} template class, or by rolling your own class from
+scratch. This section will discuss the @code{structure<T>} template which
+is easier to use but more limited, while the implementation of custom
+GiNaC classes is the topic of the next section. However, you may want to
+read both sections because many common concepts and member functions are
+shared by both concepts, and it will also allow you to decide which approach
+is most suited to your needs.
+
+The @code{structure<T>} template, defined in the GiNaC header file
+@file{structure.h}, wraps a type that you supply (usually a C++ @code{struct}
+or @code{class}) into a GiNaC object that can be used in expressions.
+
+@subsection Example: scalar products
+
+Let's suppose that we need a way to handle some kind of abstract scalar
+product of the form @samp{<x|y>} in expressions. Objects of the scalar
+product class have to store their left and right operands, which can in turn
+be arbitrary expressions. Here is a possible way to represent such a
+product in a C++ @code{struct}:
+
+@example
+#include <iostream>
+using namespace std;
+
+#include <ginac/ginac.h>
+using namespace GiNaC;
+
+struct sprod_s @{
+    ex left, right;
+
+    sprod_s() @{@}
+    sprod_s(ex l, ex r) : left(l), right(r) @{@}
+@};
+@end example
+
+The default constructor is required. Now, to make a GiNaC class out of this
+data structure, we need only one line:
+
+@example
+typedef structure<sprod_s> sprod;
+@end example
+
+That's it. This line constructs an algebraic class @code{sprod} which
+contains objects of type @code{sprod_s}. We can now use @code{sprod} in
+expressions like any other GiNaC class:
+
+@example
+...
+    symbol a("a"), b("b");
+    ex e = sprod(sprod_s(a, b));
+...
+@end example
+
+Note the difference between @code{sprod} which is the algebraic class, and
+@code{sprod_s} which is the unadorned C++ structure containing the @code{left}
+and @code{right} data members. As shown above, an @code{sprod} can be
+constructed from an @code{sprod_s} object.
+
+If you find the nested @code{sprod(sprod_s())} constructor too unwieldy,
+you could define a little wrapper function like this:
+
+@example
+inline ex make_sprod(ex left, ex right)
+@{
+    return sprod(sprod_s(left, right));
+@}
+@end example
+
+The @code{sprod_s} object contained in @code{sprod} can be accessed with
+the GiNaC @code{ex_to<>()} function followed by the @code{->} operator or
+@code{get_struct()}:
+
+@example
+...
+    cout << ex_to<sprod>(e)->left << endl;
+     // -> a
+    cout << ex_to<sprod>(e).get_struct().right << endl;
+     // -> b
+...
+@end example
+
+You only have read access to the members of @code{sprod_s}.
+
+The type definition of @code{sprod} is enough to write your own algorithms
+that deal with scalar products, for example:
+
+@example
+ex swap_sprod(ex p)
+@{
+    if (is_a<sprod>(p)) @{
+        const sprod_s & sp = ex_to<sprod>(p).get_struct();
+        return make_sprod(sp.right, sp.left);
+    @} else
+        return p;
+@}
+
+...
+    f = swap_sprod(e);
+     // f is now <b|a>
+...
+@end example
+
+@subsection Structure output
+
+While the @code{sprod} type is useable it still leaves something to be
+desired, most notably proper output:
+
+@example
+...
+    cout << e << endl;
+     // -> [structure object]
+...
+@end example
+
+By default, any structure types you define will be printed as
+@samp{[structure object]}. To override this, you can specialize the
+template's @code{print()} member function. The member functions of
+GiNaC classes are described in more detail in the next section, but
+it shouldn't be hard to figure out what's going on here:
+
+@example
+void sprod::print(const print_context & c, unsigned level) const
+@{
+    // tree debug output handled by superclass
+    if (is_a<print_tree>(c))
+        inherited::print(c, level);
+
+    // get the contained sprod_s object
+    const sprod_s & sp = get_struct();
+
+    // print_context::s is a reference to an ostream
+    c.s << "<" << sp.left << "|" << sp.right << ">";
+@}
+@end example
+
+Now we can print expressions containing scalar products:
+
+@example
+...
+    cout << e << endl;
+     // -> <a|b>
+    cout << swap_sprod(e) << endl;
+     // -> <b|a>
+...
+@end example
+
+@subsection Comparing structures
+
+The @code{sprod} class defined so far still has one important drawback: all
+scalar products are treated as being equal because GiNaC doesn't know how to
+compare objects of type @code{sprod_s}. This can lead to some confusing
+and undesired behavior:
+
+@example
+...
+    cout << make_sprod(a, b) - make_sprod(a*a, b*b) << endl;
+     // -> 0
+    cout << make_sprod(a, b) + make_sprod(a*a, b*b) << endl;
+     // -> 2*<a|b> or 2*<a^2|b^2> (which one is undefined)
+...
+@end example
+
+To remedy this, we first need to define the operators @code{==} and @code{<}
+for objects of type @code{sprod_s}:
+
+@example
+inline bool operator==(const sprod_s & lhs, const sprod_s & rhs)
+@{
+    return lhs.left.is_equal(rhs.left) && lhs.right.is_equal(rhs.right);
+@}
+
+inline bool operator<(const sprod_s & lhs, const sprod_s & rhs)
+@{
+    return lhs.left.compare(rhs.left) < 0 ? true : lhs.right.compare(rhs.right) < 0;
+@}
+@end example
+
+The ordering established by the @code{<} operator doesn't have to make any
+algebraic sense, but it needs to be well defined. Note that we can't use
+expressions like @code{lhs.left == rhs.left} or @code{lhs.left < rhs.left}
+in the implementation of these operators because they would construct
+GiNaC @code{relational} objects which in the case of @code{<} do not
+establish a well defined ordering (for arbitrary expressions, GiNaC can't
+decide which one is algebraically 'less').
+
+Next, we need to change our definition of the @code{sprod} type to let
+GiNaC know that an ordering relation exists for the embedded objects:
+
+@example
+typedef structure<sprod_s, compare_std_less> sprod;
+@end example
+
+@code{sprod} objects then behave as expected:
+
+@example
+...
+    cout << make_sprod(a, b) - make_sprod(a*a, b*b) << endl;
+     // -> <a|b>-<a^2|b^2>
+    cout << make_sprod(a, b) + make_sprod(a*a, b*b) << endl;
+     // -> <a|b>+<a^2|b^2>
+    cout << make_sprod(a, b) - make_sprod(a, b) << endl;
+     // -> 0
+    cout << make_sprod(a, b) + make_sprod(a, b) << endl;
+     // -> 2*<a|b>
+...
+@end example
+
+The @code{compare_std_less} policy parameter tells GiNaC to use the
+@code{std::less} and @code{std::equal_to} functors to compare objects of
+type @code{sprod_s}. By default, these functors forward their work to the
+standard @code{<} and @code{==} operators, which we have overloaded.
+Alternatively, we could have specialized @code{std::less} and
+@code{std::equal_to} for class @code{sprod_s}.
+
+GiNaC provides two other comparison policies for @code{structure<T>}
+objects: the default @code{compare_all_equal}, and @code{compare_bitwise}
+which does a bit-wise comparison of the contained @code{T} objects.
+This should be used with extreme care because it only works reliably with
+built-in integral types, and it also compares any padding (filler bytes of
+undefined value) that the @code{T} class might have.
+
+@subsection Subexpressions
+
+Our scalar product class has two subexpressions: the left and right
+operands. It might be a good idea to make them accessible via the standard
+@code{nops()} and @code{op()} methods:
+
+@example
+size_t sprod::nops() const
+@{
+    return 2;
+@}
+
+ex sprod::op(size_t i) const
+@{
+    switch (i) @{
+    case 0:
+        return get_struct().left;
+    case 1:
+        return get_struct().right;
+    default:
+        throw std::range_error("sprod::op(): no such operand");
+    @}
+@}
+@end example
+
+Implementing @code{nops()} and @code{op()} for container types such as
+@code{sprod} has two other nice side effects:
+
+@itemize @bullet
+@item
+@code{has()} works as expected
+@item
+GiNaC generates better hash keys for the objects (the default implementation
+of @code{calchash()} takes subexpressions into account)
+@end itemize
+
+@cindex @code{let_op()}
+There is a non-const variant of @code{op()} called @code{let_op()} that
+allows replacing subexpressions:
+
+@example
+ex & sprod::let_op(size_t i)
+@{
+    // every non-const member function must call this
+    ensure_if_modifiable();
+
+    switch (i) @{
+    case 0:
+        return get_struct().left;
+    case 1:
+        return get_struct().right;
+    default:
+        throw std::range_error("sprod::let_op(): no such operand");
+    @}
+@}
+@end example
+
+Once we have provided @code{let_op()} we also get @code{subs()} and
+@code{map()} for free. In fact, every container class that returns a non-null
+@code{nops()} value must either implement @code{let_op()} or provide custom
+implementations of @code{subs()} and @code{map()}.
+
+In turn, the availability of @code{map()} enables the recursive behavior of a
+couple of other default method implementations, in particular @code{evalf()},
+@code{evalm()}, @code{normal()}, @code{diff()} and @code{expand()}. Although
+we probably want to provide our own version of @code{expand()} for scalar
+products that turns expressions like @samp{<a+b|c>} into @samp{<a|c>+<b|c>}.
+This is left as an exercise for the reader.
+
+The @code{structure<T>} template defines many more member functions that
+you can override by specialization to customize the behavior of your
+structures. You are referred to the next section for a description of
+some of these (especially @code{eval()}). There is, however, one topic
+that shall be addressed here, as it demonstrates one peculiarity of the
+@code{structure<T>} template: archiving.
+
+@subsection Archiving structures
+
+If you don't know how the archiving of GiNaC objects is implemented, you
+should first read the next section and then come back here. You're back?
+Good.
+
+To implement archiving for structures it is not enough to provide
+specializations for the @code{archive()} member function and the
+unarchiving constructor (the @code{unarchive()} function has a default
+implementation). You also need to provide a unique name (as a string literal)
+for each structure type you define. This is because in GiNaC archives,
+the class of an object is stored as a string, the class name.
+
+By default, this class name (as returned by the @code{class_name()} member
+function) is @samp{structure} for all structure classes. This works as long
+as you have only defined one structure type, but if you use two or more you
+need to provide a different name for each by specializing the
+@code{get_class_name()} member function. Here is a sample implementation
+for enabling archiving of the scalar product type defined above:
+
+@example
+const char *sprod::get_class_name() @{ return "sprod"; @}
+
+void sprod::archive(archive_node & n) const
+@{
+    inherited::archive(n);
+    n.add_ex("left", get_struct().left);
+    n.add_ex("right", get_struct().right);
+@}
+
+sprod::structure(const archive_node & n, lst & sym_lst) : inherited(n, sym_lst)
+@{
+    n.find_ex("left", get_struct().left, sym_lst);
+    n.find_ex("right", get_struct().right, sym_lst);
+@}
+@end example
+
+Note that the unarchiving constructor is @code{sprod::structure} and not
+@code{sprod::sprod}, and that we don't need to supply an
+@code{sprod::unarchive()} function.
+
+
+@node Adding classes, A Comparison With Other CAS, Structures, Extending GiNaC
 @c    node-name, next, previous, up
 @section Adding classes
 
-If you are doing some very specialized things with GiNaC you may find that
-you have to implement your own algebraic classes to fit your needs. This
-section will explain how to do this by giving the example of a simple
-'string' class. After reading this section you will know how to properly
-declare a GiNaC class and what the minimum required member functions are
-that you have to implement. We only cover the implementation of a 'leaf'
-class here (i.e. one that doesn't contain subexpressions). Creating a
-container class like, for example, a class representing tensor products is
-more involved but this section should give you enough information so you can
-consult the source to GiNaC's predefined classes if you want to implement
-something more complicated.
+The @code{structure<T>} template provides an way to extend GiNaC with custom
+algebraic classes that is easy to use but has its limitations, the most
+severe of which being that you can't add any new member functions to
+structures. To be able to do this, you need to write a new class definition
+from scratch.
+
+This section will explain how to implement new algebraic classes in GiNaC by
+giving the example of a simple 'string' class. After reading this section
+you will know how to properly declare a GiNaC class and what the minimum
+required member functions are that you have to implement. We only cover the
+implementation of a 'leaf' class here (i.e. one that doesn't contain
+subexpressions). Creating a container class like, for example, a class
+representing tensor products is more involved but this section should give
+you enough information so you can consult the source to GiNaC's predefined
+classes if you want to implement something more complicated.
 
 @subsection GiNaC's run-time type information system
 
@@ -5080,14 +5871,13 @@ the first line after the opening brace of the class definition. The
 source (at global scope, of course, not inside a function).
 
 @code{GINAC_DECLARE_REGISTERED_CLASS} contains, among other things the
-declarations of the default and copy constructor, the destructor, the
-assignment operator and a couple of other functions that are required.  It
-also defines a type @code{inherited} which refers to the superclass so you
-don't have to modify your code every time you shuffle around the class
-hierarchy.  @code{GINAC_IMPLEMENT_REGISTERED_CLASS} implements the copy
-constructor, the destructor and the assignment operator.
-
-Now there are nine member functions we have to implement to get a working
+declarations of the default constructor and a couple of other functions that
+are required.  It also defines a type @code{inherited} which refers to the
+superclass so you don't have to modify your code every time you shuffle around
+the class hierarchy.  @code{GINAC_IMPLEMENT_REGISTERED_CLASS} registers the
+class with the GiNaC RTTI.
+
+Now there are seven member functions we have to implement to get a working
 class:
 
 @itemize
@@ -5095,33 +5885,23 @@ class:
 @item
 @code{mystring()}, the default constructor.
 
-@item
-@code{void destroy(bool call_parent)}, which is used in the destructor and the
-assignment operator to free dynamically allocated members. The @code{call_parent}
-specifies whether the @code{destroy()} function of the superclass is to be
-called also.
-
-@item
-@code{void copy(const mystring &other)}, which is used in the copy constructor
-and assignment operator to copy the member variables over from another
-object of the same class.
-
 @item
 @code{void archive(archive_node &n)}, the archiving function. This stores all
 information needed to reconstruct an object of this class inside an
 @code{archive_node}.
 
 @item
-@code{mystring(const archive_node &n, const lst &sym_lst)}, the unarchiving
+@code{mystring(const archive_node &n, lst &sym_lst)}, the unarchiving
 constructor. This constructs an instance of the class from the information
 found in an @code{archive_node}.
 
 @item
-@code{ex unarchive(const archive_node &n, const lst &sym_lst)}, the static
+@code{ex unarchive(const archive_node &n, lst &sym_lst)}, the static
 unarchiving function. It constructs a new instance by calling the unarchiving
 constructor.
 
 @item
+@cindex @code{compare_same_type()}
 @code{int compare_same_type(const basic &other)}, which is used internally
 by GiNaC to establish a canonical sort order for terms. It returns 0, +1 or
 -1, depending on the relative order of this object and the @code{other}
@@ -5143,10 +5923,7 @@ which are the two constructors we declared.
 Let's proceed step-by-step. The default constructor looks like this:
 
 @example
-mystring::mystring() : inherited(TINFO_mystring)
-@{
-    // dynamically allocate resources here if required
-@}
+mystring::mystring() : inherited(TINFO_mystring) @{@}
 @end example
 
 The golden rule is that in all constructors you have to set the
@@ -5154,51 +5931,13 @@ The golden rule is that in all constructors you have to set the
 it will be set by the constructor of the superclass and all hell will break
 loose in the RTTI. For your convenience, the @code{basic} class provides
 a constructor that takes a @code{tinfo_key} value, which we are using here
-(remember that in our case @code{inherited = basic}).  If the superclass
+(remember that in our case @code{inherited == basic}).  If the superclass
 didn't have such a constructor, we would have to set the @code{tinfo_key}
 to the right value manually.
 
 In the default constructor you should set all other member variables to
 reasonable default values (we don't need that here since our @code{str}
-member gets set to an empty string automatically). The constructor(s) are of
-course also the right place to allocate any dynamic resources you require.
-
-Next, the @code{destroy()} function:
-
-@example
-void mystring::destroy(bool call_parent)
-@{
-    // free dynamically allocated resources here if required
-    if (call_parent)
-        inherited::destroy(call_parent);
-@}
-@end example
-
-This function is where we free all dynamically allocated resources.  We
-don't have any so we're not doing anything here, but if we had, for
-example, used a C-style @code{char *} to store our string, this would be
-the place to @code{delete[]} the string storage. If @code{call_parent}
-is true, we have to call the @code{destroy()} function of the superclass
-after we're done (to mimic C++'s automatic invocation of superclass
-destructors where @code{destroy()} is called from outside a destructor).
-
-The @code{copy()} function just copies over the member variables from
-another object:
-
-@example
-void mystring::copy(const mystring &other)
-@{
-    inherited::copy(other);
-    str = other.str;
-@}
-@end example
-
-We can simply overwrite the member variables here. There's no need to worry
-about dynamically allocated storage.  The assignment operator (which is
-automatically defined by @code{GINAC_IMPLEMENT_REGISTERED_CLASS}, as you
-recall) calls @code{destroy()} before it calls @code{copy()}. You have to
-explicitly call the @code{copy()} function of the superclass here so
-all the member variables will get copied.
+member gets set to an empty string automatically).
 
 Next are the three functions for archiving. You have to implement them even
 if you don't plan to use archives, but the minimum required implementation
@@ -5223,7 +5962,7 @@ The unarchiving constructor is basically the inverse of the archiving
 function:
 
 @example
-mystring::mystring(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
+mystring::mystring(const archive_node &n, lst &sym_lst) : inherited(n, sym_lst)
 @{
     n.find_string("string", str);
 @}
@@ -5237,7 +5976,7 @@ by the unarchiving constructor of the @code{basic} class.
 Finally, the unarchiving function:
 
 @example
-ex mystring::unarchive(const archive_node &n, const lst &sym_lst)
+ex mystring::unarchive(const archive_node &n, lst &sym_lst)
 @{
     return (new mystring(n, sym_lst))->setflag(status_flags::dynallocated);
 @}
@@ -5278,15 +6017,8 @@ all relevant member variables.
 Now the only thing missing is our two new constructors:
 
 @example
-mystring::mystring(const string &s) : inherited(TINFO_mystring), str(s)
-@{
-    // dynamically allocate resources here if required
-@}
-
-mystring::mystring(const char *s) : inherited(TINFO_mystring), str(s)
-@{
-    // dynamically allocate resources here if required
-@}
+mystring::mystring(const string &s) : inherited(TINFO_mystring), str(s) @{@}
+mystring::mystring(const char *s) : inherited(TINFO_mystring), str(s) @{@}
 @end example
 
 No surprises here. We set the @code{str} member from the argument and
@@ -5435,11 +6167,35 @@ cout << e << endl;
  // -> 3*"wow"
 @end example
 
-@subsection Other member functions
+@subsection Optional member functions
 
 We have implemented only a small set of member functions to make the class
-work in the GiNaC framework. For a real algebraic class, there are probably
-some more functions that you might want to re-implement:
+work in the GiNaC framework. There are two functions that are not strictly
+required but will make operations with objects of the class more efficient:
+
+@cindex @code{calchash()}
+@cindex @code{is_equal_same_type()}
+@example
+unsigned calchash() const;
+bool is_equal_same_type(const basic &other) const;
+@end example
+
+The @code{calchash()} method returns an @code{unsigned} hash value for the
+object which will allow GiNaC to compare and canonicalize expressions much
+more efficiently. You should consult the implementation of some of the built-in
+GiNaC classes for examples of hash functions. The default implementation of
+@code{calchash()} calculates a hash value out of the @code{tinfo_key} of the
+class and all subexpressions that are accessible via @code{op()}.
+
+@code{is_equal_same_type()} works like @code{compare_same_type()} but only
+tests for equality without establishing an ordering relation, which is often
+faster. The default implementation of @code{is_equal_same_type()} just calls
+@code{compare_same_type()} and tests its result for zero.
+
+@subsection Other member functions
+
+For a real algebraic class, there are probably some more functions that you
+might want to provide:
 
 @example
 bool info(unsigned inf) const;
@@ -5448,33 +6204,21 @@ ex series(const relational & r, int order, unsigned options = 0) const;
 ex derivative(const symbol & s) const;
 @end example
 
-If your class stores sub-expressions you will probably want to override
+If your class stores sub-expressions (see the scalar product example in the
+previous section) you will probably want to override
 
 @cindex @code{let_op()}
 @example
-unsigned nops() cont;
-ex op(int i) const;
-ex & let_op(int i);
+size_t nops() cont;
+ex op(size_t i) const;
+ex & let_op(size_t i);
+ex subs(const lst & ls, const lst & lr, unsigned options = 0) const;
 ex map(map_function & f) const;
-ex subs(const lst & ls, const lst & lr, bool no_pattern = false) const;
 @end example
 
 @code{let_op()} is a variant of @code{op()} that allows write access. The
-default implementation of @code{map()} uses it, so you have to implement
-either @code{let_op()} or @code{map()}.
-
-If your class stores any data that is not accessible via @code{op()}, you
-should also implement
-
-@cindex @code{calchash()}
-@example
-unsigned calchash(void) const;
-@end example
-
-This function returns an @code{unsigned} hash value for the object which
-will allow GiNaC to compare and canonicalize expressions much more
-efficiently. You should consult the implementation of some of the built-in
-GiNaC classes for examples of hash functions.
+default implementations of @code{subs()} and @code{map()} use it, so you have
+to implement either @code{let_op()}, or @code{subs()} and @code{map()}.
 
 You can, of course, also add your own new member functions. Remember
 that the RTTI may be used to get information about what kinds of objects
@@ -5650,12 +6394,19 @@ any other programming language.
 @cindex reference counting
 @cindex copy-on-write
 @cindex garbage collection
-An expression is extremely light-weight since internally it works like a
-handle to the actual representation and really holds nothing more than a
-pointer to some other object.  What this means in practice is that
-whenever you create two @code{ex} and set the second equal to the first
-no copying process is involved. Instead, the copying takes place as soon
-as you try to change the second.  Consider the simple sequence of code:
+In GiNaC, there is an @emph{intrusive reference-counting} mechanism at work
+where the counter belongs to the algebraic objects derived from class
+@code{basic} but is maintained by the smart pointer class @code{ptr}, of
+which @code{ex} contains an instance. If you understood that, you can safely
+skip the rest of this passage.
+
+Expressions are extremely light-weight since internally they work like
+handles to the actual representation.  They really hold nothing more
+than a pointer to some other object.  What this means in practice is
+that whenever you create two @code{ex} and set the second equal to the
+first no copying process is involved. Instead, the copying takes place
+as soon as you try to change the second.  Consider the simple sequence
+of code:
 
 @example
 #include <iostream>
@@ -5982,7 +6733,7 @@ and the @samp{AM_PATH_GINAC} macro. The program used here is @file{simple.cpp}:
 @example
 #include <ginac/ginac.h>
 
-int main(void)
+int main()
 @{
     GiNaC::symbol x("x");
     GiNaC::ex a = GiNaC::sin(x);
@@ -6089,7 +6840,7 @@ and George Labahn, ISBN 0-7923-9259-0, 1992, Kluwer Academic Publishers, Norwell
 
 @item
 @cite{Computer Algebra: Systems and Algorithms for Algebraic Computation},
-James H. Davenport, Yvon Siret, and Evelyne Tournier, ISBN 0-12-204230-1, 1988, 
+James H. Davenport, Yvon Siret and Evelyne Tournier, ISBN 0-12-204230-1, 1988, 
 Academic Press, London
 
 @item
@@ -6100,6 +6851,10 @@ Michael J. Wester (editor), ISBN 0-471-98353-5, 1999, Wiley, Chichester
 @cite{The Art of Computer Programming, Vol 2: Seminumerical Algorithms},
 Donald E. Knuth, ISBN 0-201-89684-2, 1998, Addison Wesley
 
+@item
+@cite{Pi Unleashed}, J@"org Arndt and Christoph Haenel,
+ISBN 3-540-66572-2, 2001, Springer, Heidelberg
+
 @item
 @cite{The Role of gamma5 in Dimensional Regularization}, Dirk Kreimer, hep-ph/9401354
 
index 496cb44..36c3d8b 100644 (file)
--- a/ginac.m4
+++ b/ginac.m4
@@ -91,7 +91,7 @@ dnl match the version of the headers and the version built into the library, too
    prototype for exit() that conflicts with the one in stdlib.h */
 extern "C" int system(const char *);
 
-int main(void)
+int main()
 {
     int major, minor, micro;
     char *tmp_version;
index f0896bd..2b961fc 100644 (file)
@@ -1,36 +1,31 @@
 ## Process this file with automake to produce Makefile.in
 
 lib_LTLIBRARIES = libginac.la
-libginac_la_SOURCES = add.cpp archive.cpp basic.cpp constant.cpp ex.cpp \
-  expair.cpp expairseq.cpp exprseq.cpp fail.cpp function.cpp inifcns.cpp \
-  inifcns_trans.cpp inifcns_zeta.cpp inifcns_gamma.cpp matrix.cpp mul.cpp \
-  normal.cpp numeric.cpp operators.cpp power.cpp registrar.cpp relational.cpp \
-  symbol.cpp pseries.cpp utils.cpp ncmul.cpp structure.cpp exprseq_suppl.cpp \
-  lst.cpp lst_suppl.cpp input_parser.yy input_lexer.ll input_lexer.h \
-  remember.h remember.cpp utils.h idx.cpp indexed.cpp tensor.cpp color.cpp \
-  clifford.cpp wildcard.cpp print.cpp symmetry.cpp fderivative.cpp tostring.h
+libginac_la_SOURCES = add.cpp archive.cpp basic.cpp clifford.cpp color.cpp \
+  constant.cpp ex.cpp expair.cpp expairseq.cpp exprseq.cpp fail.cpp \
+  fderivative.cpp function.cpp idx.cpp indexed.cpp inifcns.cpp \
+  inifcns_trans.cpp inifcns_zeta.cpp inifcns_gamma.cpp lst.cpp matrix.cpp \
+  mul.cpp ncmul.cpp normal.cpp numeric.cpp operators.cpp power.cpp \
+  registrar.cpp relational.cpp remember.cpp pseries.cpp print.cpp structure.cpp \
+  symbol.cpp symmetry.cpp tensor.cpp utils.cpp wildcard.cpp \
+  input_parser.yy input_lexer.ll \
+  input_lexer.h remember.h tostring.h utils.h
 libginac_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
   -release $(LT_RELEASE)
 ginacincludedir = $(includedir)/ginac
-ginacinclude_HEADERS = ginac.h add.h archive.h basic.h constant.h ex.h \
-  expair.h expairseq.h exprseq.h fail.h flags.h function.h inifcns.h \
-  lst.h matrix.h mul.h ncmul.h normal.h numeric.h operators.h power.h \
-  registrar.h relational.h pseries.h structure.h symbol.h tinfos.h assertion.h \
-  version.h idx.h indexed.h tensor.h color.h clifford.h wildcard.h print.h \
-  symmetry.h fderivative.h
+ginacinclude_HEADERS = ginac.h add.h archive.h assertion.h basic.h clifford.h \
+  color.h constant.h container.h ex.h expair.h expairseq.h exprseq.h fail.h \
+  fderivative.h flags.h function.h idx.h indexed.h inifcns.h lst.h matrix.h \
+  mul.h ncmul.h normal.h numeric.h operators.h power.h print.h pseries.h ptr.h \
+  registrar.h relational.h structure.h symbol.h symmetry.h tensor.h tinfos.h \
+  version.h wildcard.h
 LFLAGS = -Pginac_yy -olex.yy.c
 YFLAGS = -p ginac_yy -d
-EXTRA_DIST = container.pl function.pl structure.pl input_parser.h version.h.in
+EXTRA_DIST = function.pl input_parser.h version.h.in
 
 # Files which are generated by perl scripts
 $(srcdir)/function.h $(srcdir)/function.cpp: $(srcdir)/function.pl
        cd $(srcdir) && perl -w function.pl
 
-$(srcdir)/lst.h $(srcdir)/lst.cpp: $(srcdir)/container.pl
-       cd $(srcdir) && perl -w container.pl lst
-
-$(srcdir)/exprseq.h $(srcdir)/exprseq.cpp: $(srcdir)/container.pl
-       cd $(srcdir) && perl -w container.pl exprseq
-
 # Force build of headers before compilation
-$(srcdir)/add.cpp: $(srcdir)/function.h $(srcdir)/lst.h $(srcdir)/exprseq.h
+$(srcdir)/add.cpp: $(srcdir)/function.h
index 9edbf13..511f3b3 100644 (file)
@@ -25,8 +25,9 @@
 
 #include "add.h"
 #include "mul.h"
-#include "matrix.h"
 #include "archive.h"
+#include "operators.h"
+#include "matrix.h"
 #include "utils.h"
 
 namespace GiNaC {
@@ -34,7 +35,7 @@ namespace GiNaC {
 GINAC_IMPLEMENT_REGISTERED_CLASS(add, expairseq)
 
 //////////
-// default ctor, dtor, copy ctor, assignment operator and helpers
+// default constructor
 //////////
 
 add::add()
@@ -42,9 +43,6 @@ add::add()
        tinfo_key = TINFO_add;
 }
 
-DEFAULT_COPY(add)
-DEFAULT_DESTROY(add)
-
 //////////
 // other constructors
 //////////
@@ -163,7 +161,7 @@ void add::print(const print_context & c, unsigned level) const
 
                c.s << class_name() << '(';
                op(0).print(c);
-               for (unsigned i=1; i<nops(); ++i) {
+               for (size_t i=1; i<nops(); ++i) {
                        c.s << ',';
                        op(i).print(c);
                }
@@ -331,7 +329,7 @@ ex add::eval(int level) const
        epvector::const_iterator i = seq.begin(), end = seq.end();
        while (i != end) {
                GINAC_ASSERT(!is_exactly_a<add>(i->rest));
-               if (is_ex_exactly_of_type(i->rest,numeric))
+               if (is_exactly_a<numeric>(i->rest))
                        dbgprint();
                GINAC_ASSERT(!is_exactly_a<numeric>(i->rest));
                ++i;
@@ -357,7 +355,7 @@ ex add::eval(int level) const
        return this->hold();
 }
 
-ex add::evalm(void) const
+ex add::evalm() const
 {
        // Evaluate children first and add up all matrices. Stop if there's one
        // term that is not a matrix.
@@ -372,7 +370,7 @@ ex add::evalm(void) const
        while (it != itend) {
                const ex &m = recombine_pair_to_ex(*it).evalm();
                s->push_back(split_ex_to_pair(m));
-               if (is_ex_of_type(m, matrix)) {
+               if (is_a<matrix>(m)) {
                        if (first_term) {
                                sum = ex_to<matrix>(m);
                                first_term = false;
@@ -390,12 +388,12 @@ ex add::evalm(void) const
                return (new add(s, overall_coeff))->setflag(status_flags::dynallocated);
 }
 
-ex add::simplify_ncmul(const exvector & v) const
+ex add::eval_ncmul(const exvector & v) const
 {
        if (seq.empty())
-               return inherited::simplify_ncmul(v);
+               return inherited::eval_ncmul(v);
        else
-               return seq.begin()->rest.simplify_ncmul(v);
+               return seq.begin()->rest.eval_ncmul(v);
 }    
 
 // protected
@@ -423,12 +421,7 @@ int add::compare_same_type(const basic & other) const
        return inherited::compare_same_type(other);
 }
 
-bool add::is_equal_same_type(const basic & other) const
-{
-       return inherited::is_equal_same_type(other);
-}
-
-unsigned add::return_type(void) const
+unsigned add::return_type() const
 {
        if (seq.empty())
                return return_types::commutative;
@@ -436,7 +429,7 @@ unsigned add::return_type(void) const
                return seq.begin()->rest.return_type();
 }
    
-unsigned add::return_type_tinfo(void) const
+unsigned add::return_type_tinfo() const
 {
        if (seq.empty())
                return tinfo_key;
@@ -456,7 +449,7 @@ ex add::thisexpairseq(epvector * vp, const ex & oc) const
 
 expair add::split_ex_to_pair(const ex & e) const
 {
-       if (is_ex_exactly_of_type(e,mul)) {
+       if (is_exactly_a<mul>(e)) {
                const mul &mulref(ex_to<mul>(e));
                const ex &numfactor = mulref.overall_coeff;
                mul *mulcopyp = new mul(mulref);
@@ -473,7 +466,7 @@ expair add::combine_ex_with_coeff_to_pair(const ex & e,
                                                                                  const ex & c) const
 {
        GINAC_ASSERT(is_exactly_a<numeric>(c));
-       if (is_ex_exactly_of_type(e, mul)) {
+       if (is_exactly_a<mul>(e)) {
                const mul &mulref(ex_to<mul>(e));
                const ex &numfactor = mulref.overall_coeff;
                mul *mulcopyp = new mul(mulref);
@@ -481,14 +474,14 @@ expair add::combine_ex_with_coeff_to_pair(const ex & e,
                mulcopyp->clearflag(status_flags::evaluated);
                mulcopyp->clearflag(status_flags::hash_calculated);
                mulcopyp->setflag(status_flags::dynallocated);
-               if (are_ex_trivially_equal(c, _ex1))
+               if (c.is_equal(_ex1))
                        return expair(*mulcopyp, numfactor);
-               else if (are_ex_trivially_equal(numfactor, _ex1))
+               else if (numfactor.is_equal(_ex1))
                        return expair(*mulcopyp, c);
                else
                        return expair(*mulcopyp, ex_to<numeric>(numfactor).mul_dyn(ex_to<numeric>(c)));
-       } else if (is_ex_exactly_of_type(e, numeric)) {
-               if (are_ex_trivially_equal(c, _ex1))
+       } else if (is_exactly_a<numeric>(e)) {
+               if (c.is_equal(_ex1))
                        return expair(e, _ex1);
                return expair(ex_to<numeric>(e).mul_dyn(ex_to<numeric>(c)), _ex1);
        }
@@ -501,7 +494,7 @@ expair add::combine_pair_with_coeff_to_pair(const expair & p,
        GINAC_ASSERT(is_exactly_a<numeric>(p.coeff));
        GINAC_ASSERT(is_exactly_a<numeric>(c));
 
-       if (is_ex_exactly_of_type(p.rest,numeric)) {
+       if (is_exactly_a<numeric>(p.rest)) {
                GINAC_ASSERT(ex_to<numeric>(p.coeff).is_equal(_num1)); // should be normalized
                return expair(ex_to<numeric>(p.rest).mul_dyn(ex_to<numeric>(c)),_ex1);
        }
index 4f55240..f2a94ed 100644 (file)
@@ -46,25 +46,24 @@ public:
        // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
-       unsigned precedence(void) const {return 40;}
+       unsigned precedence() const {return 40;}
        bool info(unsigned inf) const;
        int degree(const ex & s) const;
        int ldegree(const ex & s) const;
        ex coeff(const ex & s, int n=1) const;
        ex eval(int level=0) const;
-       ex evalm(void) const;
+       ex evalm() const;
        ex series(const relational & r, int order, unsigned options = 0) const;
        ex normal(lst &sym_lst, lst &repl_lst, int level=0) const;
-       numeric integer_content(void) const;
+       numeric integer_content() const;
        ex smod(const numeric &xi) const;
-       numeric max_coefficient(void) const;
-       exvector get_free_indices(void) const;
-       ex simplify_ncmul(const exvector & v) const;
+       numeric max_coefficient() const;
+       exvector get_free_indices() const;
+       ex eval_ncmul(const exvector & v) const;
 protected:
        ex derivative(const symbol & s) const;
-       bool is_equal_same_type(const basic & other) const;
-       unsigned return_type(void) const;
-       unsigned return_type_tinfo(void) const;
+       unsigned return_type() const;
+       unsigned return_type_tinfo() const;
        ex thisexpairseq(const epvector & v, const ex & oc) const;
        ex thisexpairseq(epvector * vp, const ex & oc) const;
        expair split_ex_to_pair(const ex & e) const;
index 28d8afc..3b6e293 100644 (file)
@@ -26,6 +26,7 @@
 #include "archive.h"
 #include "registrar.h"
 #include "ex.h"
+#include "lst.h"
 #include "config.h"
 #include "tostring.h"
 
@@ -49,18 +50,19 @@ void archive::archive_ex(const ex &e, const char *name)
  *  @return ID of archived node */
 archive_node_id archive::add_node(const archive_node &n)
 {
-       // Search for node in nodes vector
-       std::vector<archive_node>::const_iterator i = nodes.begin(), iend = nodes.end();
-       archive_node_id id = 0;
-       while (i != iend) {
-               if (i->has_same_ex_as(n))
-                       return id;
-               i++; id++;
+       // Look if expression is known to be in some node already.
+       if (n.has_ex()) {
+               mapit i = exprtable.find(n.get_ex());
+               if (i != exprtable.end())
+                       return i->second;
+               nodes.push_back(n);
+               exprtable[n.get_ex()] = nodes.size() - 1;
+               return nodes.size() - 1;
        }
 
        // Not found, add archive_node to nodes vector
        nodes.push_back(n);
-       return id;
+       return nodes.size()-1;
 }
 
 
@@ -89,7 +91,8 @@ ex archive::unarchive_ex(const lst &sym_lst, const char *name) const
 
 found:
        // Recursively unarchive all nodes, starting at the root node
-       return nodes[i->root].unarchive(sym_lst);
+       lst sym_lst_copy = sym_lst;
+       return nodes[i->root].unarchive(sym_lst_copy);
 }
 
 ex archive::unarchive_ex(const lst &sym_lst, unsigned index) const
@@ -98,7 +101,8 @@ ex archive::unarchive_ex(const lst &sym_lst, unsigned index) const
                throw (std::range_error("index of archived expression out of range"));
 
        // Recursively unarchive all nodes, starting at the root node
-       return nodes[exprs[index].root].unarchive(sym_lst);
+       lst sym_lst_copy = sym_lst;
+       return nodes[exprs[index].root].unarchive(sym_lst_copy);
 }
 
 ex archive::unarchive_ex(const lst &sym_lst, std::string &name, unsigned index) const
@@ -110,10 +114,11 @@ ex archive::unarchive_ex(const lst &sym_lst, std::string &name, unsigned index)
        name = unatomize(exprs[index].name);
 
        // Recursively unarchive all nodes, starting at the root node
-       return nodes[exprs[index].root].unarchive(sym_lst);
+       lst sym_lst_copy = sym_lst;
+       return nodes[exprs[index].root].unarchive(sym_lst_copy);
 }
 
-unsigned archive::num_expressions(void) const
+unsigned archive::num_expressions() const
 {
        return exprs.size();
 }
@@ -316,18 +321,11 @@ const std::string &archive::unatomize(archive_atom id) const
 }
 
 
-/** Copy constructor of archive_node. */
-archive_node::archive_node(const archive_node &other)
-  : a(other.a), props(other.props), has_expression(other.has_expression), e(other.e)
-{
-}
-
-
 /** Assignment operator of archive_node. */
 const archive_node &archive_node::operator=(const archive_node &other)
 {
        if (this != &other) {
-               a = other.a;
+               // archive &a member doesn't get copied
                props = other.props;
                has_expression = other.has_expression;
                e = other.e;
@@ -432,7 +430,7 @@ bool archive_node::find_string(const std::string &name, std::string &ret, unsign
        return false;
 }
 
-bool archive_node::find_ex(const std::string &name, ex &ret, const lst &sym_lst, unsigned index) const
+bool archive_node::find_ex(const std::string &name, ex &ret, lst &sym_lst, unsigned index) const
 {
        archive_atom name_atom = a.atomize(name);
        std::vector<property>::const_iterator i = props.begin(), iend = props.end();
@@ -493,7 +491,7 @@ void archive_node::get_properties(propinfovector &v) const
 
 
 /** Convert archive node to GiNaC expression. */
-ex archive_node::unarchive(const lst &sym_lst) const
+ex archive_node::unarchive(lst &sym_lst) const
 {
        // Already unarchived? Then return cached unarchived expression.
        if (has_expression)
@@ -512,45 +510,23 @@ ex archive_node::unarchive(const lst &sym_lst) const
 }
 
 
-/** Assignment operator of property_info. */
-const archive_node::property_info &archive_node::property_info::operator=(const property_info &other)
-{
-       if (this != &other) {
-               type = other.type;
-               name = other.name;
-               count = other.count;
-       }
-       return *this;
-}
-
-/** Assignment operator of property. */
-const archive_node::property &archive_node::property::operator=(const property &other)
-{
-       if (this != &other) {
-               type = other.type;
-               name = other.name;
-               value = other.value;
-       }
-       return *this;
-}
-
-
-void archive::clear(void)
+void archive::clear()
 {
        atoms.clear();
        exprs.clear();
        nodes.clear();
+       exprtable.clear();
 }
 
 
 /** Delete cached unarchived expressions in all archive_nodes (mainly for debugging). */
-void archive::forget(void)
+void archive::forget()
 {
        for_each(nodes.begin(), nodes.end(), std::mem_fun_ref(&archive_node::forget));
 }
 
 /** Delete cached unarchived expressions from node (for debugging). */
-void archive_node::forget(void)
+void archive_node::forget()
 {
        has_expression = false;
        e = 0;
@@ -624,7 +600,7 @@ void archive_node::printraw(std::ostream &os) const
 
 /** Create a dummy archive.  The intention is to fill archive_node's default
  *  ctor, which is currently a Cint-requirement. */
-archive* archive_node::dummy_ar_creator(void)
+archive* archive_node::dummy_ar_creator()
 {
        static archive* some_ar = new archive;
        return some_ar;
index b7e9ba9..5423dbf 100644 (file)
 #include <iosfwd>
 #include <string>
 #include <vector>
+#include <map>
 
 namespace GiNaC {
 
-class lst;
 class archive;
 
 
@@ -65,10 +65,6 @@ public:
        struct property_info {
                property_info() {}
                property_info(property_type t, const std::string &n, unsigned c = 1) : type(t), name(n), count(c) {}
-               ~property_info() {}
-
-               property_info(const property_info &other) : type(other.type), name(other.name), count(other.count) {}
-               const property_info &operator=(const property_info &other);
 
                property_type type;     /**< Data type of property. */
                std::string name;   /**< Name of property. */
@@ -79,9 +75,7 @@ public:
        archive_node() : a(*dummy_ar_creator()), has_expression(false) {} // hack for cint which always requires a default constructor
        archive_node(archive &ar) : a(ar), has_expression(false) {}
        archive_node(archive &ar, const ex &expr);
-       ~archive_node() {}
 
-       archive_node(const archive_node &other);
        const archive_node &operator=(const archive_node &other);
 
        /** Add property of type "bool" to node. */
@@ -110,7 +104,7 @@ public:
 
        /** Retrieve property of type "ex" from node.
         *  @return "true" if property was found, "false" otherwise */
-       bool find_ex(const std::string &name, ex &ret, const lst &sym_lst, unsigned index = 0) const;
+       bool find_ex(const std::string &name, ex &ret, lst &sym_lst, unsigned index = 0) const;
 
        /** Retrieve property of type "ex" from node, returning the node of
         *  the sub-expression. */
@@ -119,23 +113,21 @@ public:
        /** Return vector of properties stored in node. */
        void get_properties(propinfovector &v) const;
 
-       ex unarchive(const lst &sym_lst) const;
+       ex unarchive(lst &sym_lst) const;
        bool has_same_ex_as(const archive_node &other) const;
+       bool has_ex() const {return has_expression;}
+       ex get_ex() const {return e;}
 
-       void forget(void);
+       void forget();
        void printraw(std::ostream &os) const;
 
 private:
-       static archive* dummy_ar_creator(void);
+       static archive* dummy_ar_creator();
 
        /** Archived property (data type, name and associated data) */
        struct property {
                property() {}
                property(archive_atom n, property_type t, unsigned v) : type(t), name(n), value(v) {}
-               ~property() {}
-
-               property(const property &other) : type(other.type), name(other.name), value(other.value) {}
-               const property &operator=(const property &other);
 
                property_type type; /**< Data type of property. */
                archive_atom name;  /**< Name of property. */
@@ -199,18 +191,18 @@ public:
        ex unarchive_ex(const lst &sym_lst, std::string &name, unsigned index = 0) const;
 
        /** Return number of archived expressions. */
-       unsigned num_expressions(void) const;
+       unsigned num_expressions() const;
 
        /** Return reference to top node of an expression specified by index. */
        const archive_node &get_top_node(unsigned index = 0) const;
 
        /** Clear all archived expressions. */
-       void clear(void);
+       void clear();
 
        archive_node_id add_node(const archive_node &n);
        archive_node &get_node(archive_node_id id);
 
-       void forget(void);
+       void forget();
        void printraw(std::ostream &os) const;
 
 private:
@@ -236,6 +228,10 @@ public:
 private:
        /** Vector of atomized strings (using a vector allows faster unarchiving). */
        mutable std::vector<std::string> atoms;
+
+       /** Map of stored expressions to nodes for faster archiving */
+       typedef std::map<ex, archive_node_id, ex_is_less>::iterator mapit;
+       mutable std::map<ex, archive_node_id, ex_is_less> exprtable;
 };
 
 
index f625e92..9921d35 100644 (file)
@@ -34,6 +34,7 @@
 #include "lst.h"
 #include "ncmul.h"
 #include "relational.h"
+#include "operators.h"
 #include "wildcard.h"
 #include "print.h"
 #include "archive.h"
 
 namespace GiNaC {
 
-GINAC_IMPLEMENT_REGISTERED_CLASS_NO_CTORS(basic, void)
+GINAC_IMPLEMENT_REGISTERED_CLASS(basic, void)
 
 //////////
-// default ctor, dtor, copy ctor, assignment operator and helpers
+// default constructor, destructor, copy constructor and assignment operator
 //////////
 
 // public
 
-basic::basic(const basic & other) : tinfo_key(TINFO_basic), flags(0), refcount(0)
+/** basic copy constructor: implicitly assumes that the other class is of
+ *  the exact same type (as it's used by duplicate()), so it can copy the
+ *  tinfo_key and the hash value. */
+basic::basic(const basic & other) : tinfo_key(other.tinfo_key), flags(other.flags & ~status_flags::dynallocated), hashvalue(other.hashvalue), refcount(0)
 {
-       copy(other);
+       GINAC_ASSERT(typeid(*this) == typeid(other));
 }
 
+/** basic assignment operator: the other object might be of a derived class. */
 const basic & basic::operator=(const basic & other)
 {
-       if (this != &other) {
-               destroy(true);
-               copy(other);
+       unsigned fl = other.flags & ~status_flags::dynallocated;
+       if (tinfo_key != other.tinfo_key) {
+               // The other object is of a derived class, so clear the flags as they
+               // might no longer apply (especially hash_calculated). Oh, and don't
+               // copy the tinfo_key: it is already set correctly for this object.
+               flags = 0;
+       } else {
+               // The objects are of the exact same class, so copy the hash value.
+               hashvalue = other.hashvalue;
        }
+       flags = fl;
+       refcount = 0;
        return *this;
 }
 
 // protected
 
-// none (all conditionally inlined)
+// none (all inlined)
 
 //////////
-// other ctors
+// other constructors
 //////////
 
-// none (all conditionally inlined)
+// none (all inlined)
 
 //////////
 // archiving
 //////////
 
 /** Construct object from archive_node. */
-basic::basic(const archive_node &n, const lst &sym_lst) : flags(0), refcount(0)
+basic::basic(const archive_node &n, lst &sym_lst) : flags(0), refcount(0)
 {
        // Reconstruct tinfo_key from class name
        std::string class_name;
@@ -109,13 +122,13 @@ void basic::archive(archive_node &n) const
  *               level for placing parentheses and formatting */
 void basic::print(const print_context & c, unsigned level) const
 {
-       if (is_of_type(c, print_tree)) {
+       if (is_a<print_tree>(c)) {
 
                c.s << std::string(level, ' ') << class_name()
                    << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
                    << ", nops=" << nops()
                    << std::endl;
-               for (unsigned i=0; i<nops(); ++i)
+               for (size_t i=0; i<nops(); ++i)
                        op(i).print(c, level + static_cast<const print_tree &>(c).delta_indent);
 
        } else
@@ -127,8 +140,9 @@ void basic::print(const print_context & c, unsigned level) const
  *  debugger because it might not know what cout is.  This method can be
  *  invoked with no argument and it will simply print to stdout.
  *
- *  @see basic::print */
-void basic::dbgprint(void) const
+ *  @see basic::print
+ *  @see basic::dbgprinttree */
+void basic::dbgprint() const
 {
        this->print(std::cerr);
        std::cerr << std::endl;
@@ -136,27 +150,18 @@ void basic::dbgprint(void) const
 
 /** Little wrapper around printtree to be called within a debugger.
  *
- *  @see basic::dbgprint
- *  @see basic::printtree */
-void basic::dbgprinttree(void) const
+ *  @see basic::dbgprint */
+void basic::dbgprinttree() const
 {
        this->print(print_tree(std::cerr));
 }
 
 /** Return relative operator precedence (for parenthizing output). */
-unsigned basic::precedence(void) const
+unsigned basic::precedence() const
 {
        return 70;
 }
 
-/** Create a new copy of this on the heap.  One can think of this as simulating
- *  a virtual copy constructor which is needed for instance by the refcounted
- *  construction of an ex from a basic. */
-basic * basic::duplicate() const
-{
-       return new basic(*this);
-}
-
 /** Information about the object.
  *
  *  @see class info_flags */
@@ -167,7 +172,7 @@ bool basic::info(unsigned inf) const
 }
 
 /** Number of operands/members. */
-unsigned basic::nops() const
+size_t basic::nops() const
 {
        // iterating from 0 to nops() on atomic objects should be an empty loop,
        // and accessing their elements is a range error.  Container objects should
@@ -176,30 +181,44 @@ unsigned basic::nops() const
 }
 
 /** Return operand/member at position i. */
-ex basic::op(int i) const
+ex basic::op(size_t i) const
 {
-       return (const_cast<basic *>(this))->let_op(i);
+       throw(std::range_error(std::string("basic::op(): ") + class_name() + std::string(" has no operands")));
 }
 
 /** Return modifyable operand/member at position i. */
-ex & basic::let_op(int i)
+ex & basic::let_op(size_t i)
 {
-       throw(std::out_of_range("op() out of range"));
+       ensure_if_modifiable();
+       throw(std::range_error(std::string("basic::let_op(): ") + class_name() + std::string(" has no operands")));
 }
 
 ex basic::operator[](const ex & index) const
 {
-       if (is_ex_exactly_of_type(index,numeric))
-               return op(ex_to<numeric>(index).to_int());
+       if (is_exactly_a<numeric>(index))
+               return op(static_cast<size_t>(ex_to<numeric>(index).to_int()));
 
-       throw(std::invalid_argument("non-numeric indices not supported by this type"));
+       throw(std::invalid_argument(std::string("non-numeric indices not supported by ") + class_name()));
 }
 
-ex basic::operator[](int i) const
+ex basic::operator[](size_t i) const
 {
        return op(i);
 }
 
+ex & basic::operator[](const ex & index)
+{
+       if (is_exactly_a<numeric>(index))
+               return let_op(ex_to<numeric>(index).to_int());
+
+       throw(std::invalid_argument(std::string("non-numeric indices not supported by ") + class_name()));
+}
+
+ex & basic::operator[](size_t i)
+{
+       return let_op(i);
+}
+
 /** Test for occurrence of a pattern.  An object 'has' a pattern if it matches
  *  the pattern itself or one of the children 'has' it.  As a consequence
  *  (according to the definition of children) given e=x+y+z, e.has(x) is true
@@ -209,7 +228,7 @@ bool basic::has(const ex & pattern) const
        lst repl_lst;
        if (match(pattern, repl_lst))
                return true;
-       for (unsigned i=0; i<nops(); i++)
+       for (size_t i=0; i<nops(); i++)
                if (op(i).has(pattern))
                        return true;
        
@@ -220,17 +239,16 @@ bool basic::has(const ex & pattern) const
  *  sub-expressions (one level only, not recursively). */
 ex basic::map(map_function & f) const
 {
-       unsigned num = nops();
+       size_t num = nops();
        if (num == 0)
                return *this;
 
        basic *copy = duplicate();
        copy->setflag(status_flags::dynallocated);
        copy->clearflag(status_flags::hash_calculated | status_flags::expanded);
-       ex e(*copy);
-       for (unsigned i=0; i<num; i++)
-               e.let_op(i) = f(e.op(i));
-       return e.eval();
+       for (size_t i=0; i<num; i++)
+               copy->let_op(i) = f(copy->op(i));
+       return *copy;
 }
 
 /** Return degree of highest power in object s. */
@@ -260,7 +278,7 @@ ex basic::coeff(const ex & s, int n) const
 ex basic::collect(const ex & s, bool distributed) const
 {
        ex x;
-       if (is_ex_of_type(s, lst)) {
+       if (is_a<lst>(s)) {
 
                // List of objects specified
                if (s.nops() == 0)
@@ -271,7 +289,7 @@ ex basic::collect(const ex & s, bool distributed) const
                else if (distributed) {
 
                        // Get lower/upper degree of all symbols in list
-                       int num = s.nops();
+                       size_t num = s.nops();
                        struct sym_info {
                                ex sym;
                                int ldeg, deg;
@@ -280,7 +298,7 @@ ex basic::collect(const ex & s, bool distributed) const
                        };
                        sym_info *si = new sym_info[num];
                        ex c = *this;
-                       for (int i=0; i<num; i++) {
+                       for (size_t i=0; i<num; i++) {
                                si[i].sym = s.op(i);
                                si[i].ldeg = si[i].cnt = this->ldegree(si[i].sym);
                                si[i].deg = this->degree(si[i].sym);
@@ -291,14 +309,14 @@ ex basic::collect(const ex & s, bool distributed) const
 
                                // Calculate coeff*x1^c1*...*xn^cn
                                ex y = _ex1;
-                               for (int i=0; i<num; i++) {
+                               for (size_t i=0; i<num; i++) {
                                        int cnt = si[i].cnt;
                                        y *= power(si[i].sym, cnt);
                                }
                                x += y * si[num - 1].coeff;
 
                                // Increment counters
-                               int n = num - 1;
+                               size_t n = num - 1;
                                while (true) {
                                        ++si[n].cnt;
                                        if (si[n].cnt <= si[n].deg) {
@@ -308,7 +326,7 @@ ex basic::collect(const ex & s, bool distributed) const
                                                        c = *this;
                                                else
                                                        c = si[n - 1].coeff;
-                                               for (int i=n; i<num; i++)
+                                               for (size_t i=n; i<num; i++)
                                                        c = si[i].coeff = c.coeff(si[i].sym, si[i].cnt);
                                                break;
                                        }
@@ -325,8 +343,13 @@ done:              delete[] si;
 
                        // Recursive form
                        x = *this;
-                       for (int n=s.nops()-1; n>=0; n--)
+                       size_t n = s.nops() - 1;
+                       while (true) {
                                x = x.collect(s[n]);
+                               if (n == 0)
+                                       break;
+                               n--;
+                       }
                }
 
        } else {
@@ -344,7 +367,7 @@ done:               delete[] si;
 ex basic::eval(int level) const
 {
        // There is nothing to do for basic objects:
-       return this->hold();
+       return hold();
 }
 
 /** Function object to be applied by basic::evalf(). */
@@ -377,7 +400,7 @@ struct evalm_map_function : public map_function {
 } map_evalm;
 
 /** Evaluate sums, products and integer powers of matrices. */
-ex basic::evalm(void) const
+ex basic::evalm() const
 {
        if (nops() == 0)
                return *this;
@@ -459,14 +482,14 @@ bool basic::match(const ex & pattern, lst & repl_lst) const
        Bog is the king of Pattern.
 */
 
-       if (is_ex_exactly_of_type(pattern, wildcard)) {
+       if (is_exactly_a<wildcard>(pattern)) {
 
                // Wildcard matches anything, but check whether we already have found
                // a match for that wildcard first (if so, it the earlier match must
                // be the same expression)
-               for (unsigned i=0; i<repl_lst.nops(); i++) {
-                       if (repl_lst.op(i).op(0).is_equal(pattern))
-                               return is_equal(ex_to<basic>(repl_lst.op(i).op(1)));
+               for (lst::const_iterator it = repl_lst.begin(); it != repl_lst.end(); ++it) {
+                       if (it->op(0).is_equal(pattern))
+                               return is_equal(ex_to<basic>(it->op(1)));
                }
                repl_lst.append(pattern == *this);
                return true;
@@ -491,7 +514,7 @@ bool basic::match(const ex & pattern, lst & repl_lst) const
                        return false;
 
                // Otherwise the subexpressions must match one-to-one
-               for (unsigned i=0; i<nops(); i++)
+               for (size_t i=0; i<nops(); i++)
                        if (!op(i).match(pattern.op(i), repl_lst))
                                return false;
 
@@ -500,28 +523,64 @@ bool basic::match(const ex & pattern, lst & repl_lst) const
        }
 }
 
-/** Substitute a set of objects by arbitrary expressions. The ex returned
- *  will already be evaluated. */
-ex basic::subs(const lst & ls, const lst & lr, bool no_pattern) const
+/** Helper function for subs(). Does not recurse into subexpressions. */
+ex basic::subs_one_level(const lst & ls, const lst & lr, unsigned options) const
 {
        GINAC_ASSERT(ls.nops() == lr.nops());
 
-       if (no_pattern) {
-               for (unsigned i=0; i<ls.nops(); i++) {
-                       if (is_equal(ex_to<basic>(ls.op(i))))
-                               return lr.op(i);
+       lst::const_iterator its, itr;
+
+       if (options & subs_options::subs_no_pattern) {
+               for (its = ls.begin(), itr = lr.begin(); its != ls.end(); ++its, ++itr) {
+                       if (is_equal(ex_to<basic>(*its)))
+                               return *itr;
                }
        } else {
-               for (unsigned i=0; i<ls.nops(); i++) {
+               for (its = ls.begin(), itr = lr.begin(); its != ls.end(); ++its, ++itr) {
                        lst repl_lst;
-                       if (match(ex_to<basic>(ls.op(i)), repl_lst))
-                               return lr.op(i).subs(repl_lst, true); // avoid infinite recursion when re-substituting the wildcards
+                       if (match(ex_to<basic>(*its), repl_lst))
+                               return itr->subs(repl_lst, options | subs_options::subs_no_pattern); // avoid infinite recursion when re-substituting the wildcards
                }
        }
 
        return *this;
 }
 
+/** Substitute a set of objects by arbitrary expressions. The ex returned
+ *  will already be evaluated. */
+ex basic::subs(const lst & ls, const lst & lr, unsigned options) const
+{
+       size_t num = nops();
+       if (num) {
+
+               // Substitute in subexpressions
+               for (size_t i=0; i<num; i++) {
+                       const ex & orig_op = op(i);
+                       const ex & subsed_op = orig_op.subs(ls, lr, options);
+                       if (!are_ex_trivially_equal(orig_op, subsed_op)) {
+
+                               // Something changed, clone the object
+                               basic *copy = duplicate();
+                               copy->setflag(status_flags::dynallocated);
+                               copy->clearflag(status_flags::hash_calculated | status_flags::expanded);
+
+                               // Substitute the changed operand
+                               copy->let_op(i++) = subsed_op;
+
+                               // Substitute the other operands
+                               for (; i<num; i++)
+                                       copy->let_op(i) = op(i).subs(ls, lr, options);
+
+                               // Perform substitutions on the new object as a whole
+                               return copy->subs_one_level(ls, lr, options);
+                       }
+               }
+       }
+
+       // Nothing changed or no subexpressions
+       return subs_one_level(ls, lr, options);
+}
+
 /** Default interface of nth derivative ex::diff(s, n).  It should be called
  *  instead of ::derivative(s) for first derivatives and for nth derivatives it
  *  just recurses down.
@@ -549,14 +608,14 @@ ex basic::diff(const symbol & s, unsigned nth) const
 }
 
 /** Return a vector containing the free indices of an expression. */
-exvector basic::get_free_indices(void) const
+exvector basic::get_free_indices() const
 {
        return exvector(); // return an empty exvector
 }
 
-ex basic::simplify_ncmul(const exvector & v) const
+ex basic::eval_ncmul(const exvector & v) const
 {
-       return simplified_ncmul(v);
+       return hold_ncmul(v);
 }
 
 // protected
@@ -619,12 +678,12 @@ bool basic::match_same_type(const basic & other) const
        return true;
 }
 
-unsigned basic::return_type(void) const
+unsigned basic::return_type() const
 {
        return return_types::commutative;
 }
 
-unsigned basic::return_type_tinfo(void) const
+unsigned basic::return_type_tinfo() const
 {
        return tinfo();
 }
@@ -635,17 +694,14 @@ unsigned basic::return_type_tinfo(void) const
  *  members.  For this reason it is well suited for container classes but
  *  atomic classes should override this implementation because otherwise they
  *  would all end up with the same hashvalue. */
-unsigned basic::calchash(void) const
+unsigned basic::calchash() const
 {
        unsigned v = golden_ratio_hash(tinfo());
-       for (unsigned i=0; i<nops(); i++) {
-               v = rotate_left_31(v);
+       for (size_t i=0; i<nops(); i++) {
+               v = rotate_left(v);
                v ^= (const_cast<basic *>(this))->op(i).gethash();
        }
-       
-       // mask out numeric hashes:
-       v &= 0x7FFFFFFFU;
-       
+
        // store calculated hash value only if object is already evaluated
        if (flags & status_flags::evaluated) {
                setflag(status_flags::hash_calculated);
@@ -686,77 +742,67 @@ ex basic::expand(unsigned options) const
  *  replacement arguments: 1) a relational like object==ex and 2) a list of
  *  relationals lst(object1==ex1,object2==ex2,...), which is converted to
  *  subs(lst(object1,object2,...),lst(ex1,ex2,...)). */
-ex basic::subs(const ex & e, bool no_pattern) const
+ex basic::subs(const ex & e, unsigned options) const
 {
        if (e.info(info_flags::relation_equal)) {
-               return subs(lst(e), no_pattern);
+               return subs(lst(e), options);
        }
        if (!e.info(info_flags::list)) {
                throw(std::invalid_argument("basic::subs(ex): argument must be a list"));
        }
+
+       // Split list into two
        lst ls;
        lst lr;
-       for (unsigned i=0; i<e.nops(); i++) {
-               ex r = e.op(i);
+       GINAC_ASSERT(is_a<lst>(e));
+       for (lst::const_iterator it = ex_to<lst>(e).begin(); it != ex_to<lst>(e).end(); ++it) {
+               ex r = *it;
                if (!r.info(info_flags::relation_equal)) {
                        throw(std::invalid_argument("basic::subs(ex): argument must be a list of equations"));
                }
                ls.append(r.op(0));
                lr.append(r.op(1));
        }
-       return subs(ls, lr, no_pattern);
+       return subs(ls, lr, options);
 }
 
-/** Compare objects to establish canonical ordering.
+/** Compare objects syntactically to establish canonical ordering.
  *  All compare functions return: -1 for *this less than other, 0 equal,
  *  1 greater. */
 int basic::compare(const basic & other) const
 {
-       unsigned hash_this = gethash();
-       unsigned hash_other = other.gethash();
-       
+       const unsigned hash_this = gethash();
+       const unsigned hash_other = other.gethash();