From: Christian Bauer Date: Wed, 2 Jul 2003 20:46:56 +0000 (+0000) Subject: merging 1.2 branch into main trunk X-Git-Tag: release_1-0-15~33 X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=commitdiff_plain;h=68fdf425abf14d016d5f95ee7b9d06a19a3c5926 merging 1.2 branch into main trunk --- diff --git a/INSTALL b/INSTALL index 7c6258f3..e1881a35 100644 --- a/INSTALL +++ b/INSTALL @@ -6,11 +6,11 @@ one of the following FTP-sites: * , * or * . -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 , 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 header written by Magnus Fromreide. It was -posted to the gcc-patches mailing list on November 21 2000: -. +continuing. diff --git a/NEWS b/NEWS index d675dc1e..13d62539 100644 --- a/NEWS +++ b/NEWS @@ -1,12 +1,40 @@ This file records noteworthy changes. -1.0.15 () -* 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 () +* Added a structure 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 diff --git a/check/Makefile.am b/check/Makefile.am index bf25465c..fcc2770a 100644 --- a/check/Makefile.am +++ b/check/Makefile.am @@ -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 diff --git a/check/check_inifcns.cpp b/check/check_inifcns.cpp index 3ba84610..81497cb9 100644 --- a/check/check_inifcns.cpp +++ b/check/check_inifcns.cpp @@ -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; diff --git a/check/check_lsolve.cpp b/check/check_lsolve.cpp index ac0574e4..4c98fc51 100644 --- a/check/check_lsolve.cpp +++ b/check/check_lsolve.cpp @@ -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 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; diff --git a/check/check_matrices.cpp b/check/check_matrices.cpp index deb00471..91f4b5da 100644 --- a/check/check_matrices.cpp +++ b/check/check_matrices.cpp @@ -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 @@ -24,12 +26,12 @@ /* 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 -unsigned exam_archive(void) +unsigned exam_archive() { unsigned result = 0; diff --git a/check/exam_clifford.cpp b/check/exam_clifford.cpp index 25c815af..aef55cbc 100644 --- a/check/exam_clifford.cpp +++ b/check/exam_clifford.cpp @@ -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; diff --git a/check/exam_color.cpp b/check/exam_color.cpp index 558f6543..cbc99462 100644 --- a/check/exam_color.cpp +++ b/check/exam_color.cpp @@ -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; diff --git a/check/exam_differentiation.cpp b/check/exam_differentiation.cpp index 71923977..33b13b1f 100644 --- a/check/exam_differentiation.cpp +++ b/check/exam_differentiation.cpp @@ -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; diff --git a/check/exam_indexed.cpp b/check/exam_indexed.cpp index 82a2539f..69816a74 100644 --- a/check/exam_indexed.cpp +++ b/check/exam_indexed.cpp @@ -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; diff --git a/check/exam_inifcns.cpp b/check/exam_inifcns.cpp index 1291030a..a3a09650 100644 --- a/check/exam_inifcns.cpp +++ b/check/exam_inifcns.cpp @@ -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; diff --git a/check/exam_lsolve.cpp b/check/exam_lsolve.cpp index 1321a715..ff510b31 100644 --- a/check/exam_lsolve.cpp +++ b/check/exam_lsolve.cpp @@ -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; diff --git a/check/exam_matrices.cpp b/check/exam_matrices.cpp index 867f52c9..9a88c8c2 100644 --- a/check/exam_matrices.cpp +++ b/check/exam_matrices.cpp @@ -23,7 +23,7 @@ #include #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; diff --git a/check/exam_misc.cpp b/check/exam_misc.cpp index 1da10b78..4127a327 100644 --- a/check/exam_misc.cpp +++ b/check/exam_misc.cpp @@ -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; diff --git a/check/exam_normalization.cpp b/check/exam_normalization.cpp index 02f2a821..0aafa499 100644 --- a/check/exam_normalization.cpp +++ b/check/exam_normalization.cpp @@ -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; diff --git a/check/exam_numeric.cpp b/check/exam_numeric.cpp index 3b943b17..90e435e8 100644 --- a/check/exam_numeric.cpp +++ b/check/exam_numeric.cpp @@ -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; diff --git a/check/exam_paranoia.cpp b/check/exam_paranoia.cpp index 4050b5f5..c1df502c 100644 --- a/check/exam_paranoia.cpp +++ b/check/exam_paranoia.cpp @@ -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; diff --git a/check/exam_polygcd.cpp b/check/exam_polygcd.cpp index e350579b..4b8bd440 100644 --- a/check/exam_polygcd.cpp +++ b/check/exam_polygcd.cpp @@ -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; diff --git a/check/exam_powerlaws.cpp b/check/exam_powerlaws.cpp index c6203df1..be62bfcf 100644 --- a/check/exam_powerlaws.cpp +++ b/check/exam_powerlaws.cpp @@ -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; diff --git a/check/exam_pseries.cpp b/check/exam_pseries.cpp index f757d500..ab1ca0f6 100644 --- a/check/exam_pseries.cpp +++ b/check/exam_pseries.cpp @@ -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; diff --git a/check/time_antipode.cpp b/check/time_antipode.cpp index 09870db8..e88bd735 100644 --- a/check/time_antipode.cpp +++ b/check/time_antipode.cpp @@ -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 (indicesevaluate(x,grad)); } -unsigned node::total_edges(void) const +unsigned node::total_edges() const { unsigned accu = 0; for (multiset::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; diff --git a/check/time_dennyfliegner.cpp b/check/time_dennyfliegner.cpp index ea3b7be5..66531bdc 100644 --- a/check/time_dennyfliegner.cpp +++ b/check/time_dennyfliegner.cpp @@ -53,7 +53,7 @@ static unsigned expand_subs(unsigned size) return result; } -unsigned time_dennyfliegner(void) +unsigned time_dennyfliegner() { unsigned result = 0; diff --git a/check/time_fateman_expand.cpp b/check/time_fateman_expand.cpp index 97f5bcd9..274d098f 100644 --- a/check/time_fateman_expand.cpp +++ b/check/time_fateman_expand.cpp @@ -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; diff --git a/check/time_gammaseries.cpp b/check/time_gammaseries.cpp index 96eb85fa..afb78395 100644 --- a/check/time_gammaseries.cpp +++ b/check/time_gammaseries.cpp @@ -43,7 +43,7 @@ unsigned tgammaseries(unsigned order) return result; } -unsigned time_gammaseries(void) +unsigned time_gammaseries() { unsigned result = 0; diff --git a/check/time_lw_A.cpp b/check/time_lw_A.cpp index 6badd19a..67fcf62c 100644 --- a/check/time_lw_A.cpp +++ b/check/time_lw_A.cpp @@ -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; diff --git a/check/time_lw_B.cpp b/check/time_lw_B.cpp index cb92efcc..a2794dc6 100644 --- a/check/time_lw_B.cpp +++ b/check/time_lw_B.cpp @@ -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; diff --git a/check/time_lw_C.cpp b/check/time_lw_C.cpp index 70960ad9..2f61a05e 100644 --- a/check/time_lw_C.cpp +++ b/check/time_lw_C.cpp @@ -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; diff --git a/check/time_lw_D.cpp b/check/time_lw_D.cpp index 631b1cb7..2bf36949 100644 --- a/check/time_lw_D.cpp +++ b/check/time_lw_D.cpp @@ -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; diff --git a/check/time_lw_E.cpp b/check/time_lw_E.cpp index 59c590fb..4a2abcee 100644 --- a/check/time_lw_E.cpp +++ b/check/time_lw_E.cpp @@ -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; diff --git a/check/time_lw_F.cpp b/check/time_lw_F.cpp index 912a0cd2..bfd8dcb6 100644 --- a/check/time_lw_F.cpp +++ b/check/time_lw_F.cpp @@ -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; diff --git a/check/time_lw_G.cpp b/check/time_lw_G.cpp index 43b0c6e2..b65af066 100644 --- a/check/time_lw_G.cpp +++ b/check/time_lw_G.cpp @@ -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; diff --git a/check/time_lw_H.cpp b/check/time_lw_H.cpp index a36e5f24..e988e46b 100644 --- a/check/time_lw_H.cpp +++ b/check/time_lw_H.cpp @@ -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; diff --git a/check/time_lw_IJKL.cpp b/check/time_lw_IJKL.cpp index 18a42d8b..cc864177 100644 --- a/check/time_lw_IJKL.cpp +++ b/check/time_lw_IJKL.cpp @@ -79,7 +79,7 @@ static unsigned test(unsigned n) return result; } -unsigned time_lw_IJKL(void) +unsigned time_lw_IJKL() { unsigned result = 0; diff --git a/check/time_lw_M1.cpp b/check/time_lw_M1.cpp index cfba9fce..54494c8e 100644 --- a/check/time_lw_M1.cpp +++ b/check/time_lw_M1.cpp @@ -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; diff --git a/check/time_lw_M2.cpp b/check/time_lw_M2.cpp index 9b35c9f2..b835f602 100644 --- a/check/time_lw_M2.cpp +++ b/check/time_lw_M2.cpp @@ -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; diff --git a/check/time_lw_N.cpp b/check/time_lw_N.cpp index 81d32b04..f55d56bb 100644 --- a/check/time_lw_N.cpp +++ b/check/time_lw_N.cpp @@ -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; diff --git a/check/time_lw_O.cpp b/check/time_lw_O.cpp index 1199043e..f24016d5 100644 --- a/check/time_lw_O.cpp +++ b/check/time_lw_O.cpp @@ -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; diff --git a/check/time_lw_P.cpp b/check/time_lw_P.cpp index a523e898..279327be 100644 --- a/check/time_lw_P.cpp +++ b/check/time_lw_P.cpp @@ -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; diff --git a/check/time_lw_Pprime.cpp b/check/time_lw_Pprime.cpp index 99d78692..69e07800 100644 --- a/check/time_lw_Pprime.cpp +++ b/check/time_lw_Pprime.cpp @@ -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; diff --git a/check/time_lw_Q.cpp b/check/time_lw_Q.cpp index b48a30cf..8c976a1f 100644 --- a/check/time_lw_Q.cpp +++ b/check/time_lw_Q.cpp @@ -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; diff --git a/check/time_lw_Qprime.cpp b/check/time_lw_Qprime.cpp index 46dac14a..b69cb91e 100644 --- a/check/time_lw_Qprime.cpp +++ b/check/time_lw_Qprime.cpp @@ -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; diff --git a/check/time_toeplitz.cpp b/check/time_toeplitz.cpp index 573f00f9..693b8f77 100644 --- a/check/time_toeplitz.cpp +++ b/check/time_toeplitz.cpp @@ -63,7 +63,7 @@ static unsigned toeplitz_det(unsigned size) return result; } -unsigned time_toeplitz(void) +unsigned time_toeplitz() { unsigned result = 0; diff --git a/check/time_vandermonde.cpp b/check/time_vandermonde.cpp index 4b4c965a..17fa65ba 100644 --- a/check/time_vandermonde.cpp +++ b/check/time_vandermonde.cpp @@ -61,7 +61,7 @@ static unsigned vandermonde_det(unsigned size) return result; } -unsigned time_vandermonde(void) +unsigned time_vandermonde() { unsigned result = 0; diff --git a/check/timer.cpp b/check/timer.cpp index fe0d1601..2a11872d 100644 --- a/check/timer.cpp +++ b/check/timer.cpp @@ -20,34 +20,38 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "times.h" +#include +#include +#include -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 index 00000000..022c29d7 --- /dev/null +++ b/check/timer.h @@ -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 + +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 diff --git a/check/times.h b/check/times.h index 5d53b9f3..85052de0 100644 --- a/check/times.h +++ b/check/times.h @@ -23,7 +23,6 @@ #ifndef CHECKS_H #define CHECKS_H -#include #include #include #include @@ -33,18 +32,7 @@ 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(); diff --git a/configure.ac b/configure.ac index dd4eadec..af1b5496 100644 --- a/configure.ac +++ b/configure.ac @@ -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 header file could AC_CHECK_HEADER(typeinfo, , GINAC_ERROR([The standard header file could not be found.])) AC_CHECK_HEADER(stdexcept, , GINAC_ERROR([The standard header file could not be found.])) AC_CHECK_HEADER(algorithm, , GINAC_ERROR([The standard header file could not be found.])) +AC_CHECK_HEADER(limits, , GINAC_ERROR([The standard 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, diff --git a/debian/changelog b/debian/changelog index 190fcdb7..7ad4568e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -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 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 Mon, 27 Jan 2003 17:56:07 +0100 - -ginac (1.0.12-1) unstable; urgency=low - - * New upstream (bugfix only) release. - - -- Christian Bauer Thu, 31 Oct 2002 16:21:05 +0100 + -- Richard Kreckel Thu, 4 Apr 2003 12:11:21 +0200 ginac (1.0.11-1) unstable; urgency=low * New upstream (bugfix only) release. - -- Richard Kreckel Wed, 18 Sep 2002 16:45:05 +0200 - -ginac (1.0.10-1) unstable; urgency=low - - * New upstream (bugfix only) release. - - -- Richard Kreckel Wed, 24 Jul 2002 18:03:00 +0200 + -- Richard Kreckel Wed, 18 Sep 2002 16:45:05 +0100 ginac (1.0.8-1) unstable; urgency=low diff --git a/debian/control b/debian/control index 97f3b101..08df8712 100644 --- a/debian/control +++ b/debian/control @@ -2,10 +2,10 @@ Source: ginac Section: math Priority: optional Maintainer: Richard Kreckel -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 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 for detailed information about the GiNaC - framework. + file. See 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 - for detailed information about the GiNaC framework. + for detailed information about GiNaC. diff --git a/debian/copyright b/debian/copyright index 7cb8b5e3..b1040046 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1,4 +1,4 @@ -This package was debianized by Richard Kreckel kreckel@ginac.de on +This package was debianized by Richard Kreckel on Thu, 29 Mar 2001 20:30:40 +0100. It was downloaded from diff --git a/debian/docs b/debian/docs new file mode 100644 index 00000000..eb9b151c --- /dev/null +++ b/debian/docs @@ -0,0 +1,3 @@ +NEWS +README +AUTHORS diff --git a/debian/libginac-dev.postinst b/debian/libginac-dev.postinst index 7f199096..c57db5d9 100644 --- a/debian/libginac-dev.postinst +++ b/debian/libginac-dev.postinst @@ -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# diff --git a/debian/dirs b/debian/libginac1.1.dirs 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 index 00000000..9a5c1be4 --- /dev/null +++ b/debian/libginac1.1.files @@ -0,0 +1 @@ +usr/lib/libginac*.so.* diff --git a/debian/postinst b/debian/postinst deleted file mode 100644 index 1ded2f88..00000000 --- a/debian/postinst +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -set -e -if [ "$1" = "configure" ]; then - ldconfig -fi -#DEBHELPER# diff --git a/debian/rules b/debian/rules index b3856a32..a6d80b19 100755 --- a/debian/rules +++ b/debian/rules @@ -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 diff --git a/debian/shlibs b/debian/shlibs index 6a0cdd01..ce7d3dcb 100644 --- a/debian/shlibs +++ b/debian/shlibs @@ -1 +1 @@ -libginac-1.0 0 libginac0 (>= 1.0.0) +libginac-1.1 0 libginac1.1 (>= 1.1.0) diff --git a/doc/reference/DoxyfileHTML b/doc/reference/DoxyfileHTML index 868b7536..0f5c4843 100644 --- a/doc/reference/DoxyfileHTML +++ b/doc/reference/DoxyfileHTML @@ -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 , where # is the value of the INPUT_FILTER tag, and 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 = diff --git a/doc/reference/DoxyfileTEX b/doc/reference/DoxyfileTEX index dd854fdf..2c0e8791 100644 --- a/doc/reference/DoxyfileTEX +++ b/doc/reference/DoxyfileTEX @@ -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 , where # is the value of the INPUT_FILTER tag, and 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 = diff --git a/doc/reference/Makefile.am b/doc/reference/Makefile.am index 79eb9708..40694807 100644 --- a/doc/reference/Makefile.am +++ b/doc/reference/Makefile.am @@ -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 diff --git a/doc/tutorial/ginac.texi b/doc/tutorial/ginac.texi index 51742673..241d2541 100644 --- a/doc/tutorial/ginac.texi +++ b/doc/tutorial/ginac.texi @@ -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} 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 ) + copy(l.begin(), l.end(), ostream_iterator(cout, "\n")); + + // sum up the elements of the list (requires #include ) + 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()} @@ -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(const ex & e); bool is_exactly_a(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()} 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(e).trace(); else if (is_a(e)) @{ ex sum = 0; - for (unsigned i=0; i)(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(e)) @{ + const varidx & vi = ex_to(e); + l.append(vi.is_covariant() ? vi : vi.toggle_variance()); + @} else if (is_a(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(e)) @{ + ... + @} else if (is_a(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 @@ -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(0.0,4.5000000e+00); +d = (3.0/2.0)*(x*x)+std::complex(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>} 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} template class, or by rolling your own class from +scratch. This section will discuss the @code{structure} 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} 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{} 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 +using namespace std; + +#include +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; +@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(e)->left << endl; + // -> a + cout << ex_to(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(p)) @{ + const sprod_s & sp = ex_to(p).get_struct(); + return make_sprod(sp.right, sp.left); + @} else + return p; +@} + +... + f = swap_sprod(e); + // f is now +... +@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(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; + // -> + cout << swap_sprod(e) << endl; + // -> +... +@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* or 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; +@end example + +@code{sprod} objects then behave as expected: + +@example +... + cout << make_sprod(a, b) - make_sprod(a*a, b*b) << endl; + // -> - + cout << make_sprod(a, b) + make_sprod(a*a, b*b) << endl; + // -> + + cout << make_sprod(a, b) - make_sprod(a, b) << endl; + // -> 0 + cout << make_sprod(a, b) + make_sprod(a, b) << endl; + // -> 2* +... +@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} +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{} into @samp{+}. +This is left as an exercise for the reader. + +The @code{structure} 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} 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} 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 @@ -5982,7 +6733,7 @@ and the @samp{AM_PATH_GINAC} macro. The program used here is @file{simple.cpp}: @example #include -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 diff --git a/ginac.m4 b/ginac.m4 index 496cb446..36c3d8b0 100644 --- 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; diff --git a/ginac/Makefile.am b/ginac/Makefile.am index f0896bd4..2b961fc1 100644 --- a/ginac/Makefile.am +++ b/ginac/Makefile.am @@ -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 diff --git a/ginac/add.cpp b/ginac/add.cpp index 9edbf139..511f3b3d 100644 --- a/ginac/add.cpp +++ b/ginac/add.cpp @@ -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(i->rest)); - if (is_ex_exactly_of_type(i->rest,numeric)) + if (is_exactly_a(i->rest)) dbgprint(); GINAC_ASSERT(!is_exactly_a(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(m)) { if (first_term) { sum = ex_to(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(e)) { const mul &mulref(ex_to(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(c)); - if (is_ex_exactly_of_type(e, mul)) { + if (is_exactly_a(e)) { const mul &mulref(ex_to(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(numfactor).mul_dyn(ex_to(c))); - } else if (is_ex_exactly_of_type(e, numeric)) { - if (are_ex_trivially_equal(c, _ex1)) + } else if (is_exactly_a(e)) { + if (c.is_equal(_ex1)) return expair(e, _ex1); return expair(ex_to(e).mul_dyn(ex_to(c)), _ex1); } @@ -501,7 +494,7 @@ expair add::combine_pair_with_coeff_to_pair(const expair & p, GINAC_ASSERT(is_exactly_a(p.coeff)); GINAC_ASSERT(is_exactly_a(c)); - if (is_ex_exactly_of_type(p.rest,numeric)) { + if (is_exactly_a(p.rest)) { GINAC_ASSERT(ex_to(p.coeff).is_equal(_num1)); // should be normalized return expair(ex_to(p.rest).mul_dyn(ex_to(c)),_ex1); } diff --git a/ginac/add.h b/ginac/add.h index 4f55240a..f2a94ed4 100644 --- a/ginac/add.h +++ b/ginac/add.h @@ -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; diff --git a/ginac/archive.cpp b/ginac/archive.cpp index 28d8afc3..3b6e2931 100644 --- a/ginac/archive.cpp +++ b/ginac/archive.cpp @@ -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::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::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; diff --git a/ginac/archive.h b/ginac/archive.h index b7e9ba98..5423dbfc 100644 --- a/ginac/archive.h +++ b/ginac/archive.h @@ -28,10 +28,10 @@ #include #include #include +#include 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 atoms; + + /** Map of stored expressions to nodes for faster archiving */ + typedef std::map::iterator mapit; + mutable std::map exprtable; }; diff --git a/ginac/basic.cpp b/ginac/basic.cpp index f625e92b..9921d358 100644 --- a/ginac/basic.cpp +++ b/ginac/basic.cpp @@ -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" @@ -41,44 +42,56 @@ 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(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(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(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(index).to_int()); + if (is_exactly_a(index)) + return op(static_cast(ex_to(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(index)) + return let_op(ex_to(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; isetflag(status_flags::dynallocated); copy->clearflag(status_flags::hash_calculated | status_flags::expanded); - ex e(*copy); - for (unsigned i=0; ilet_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(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; ildegree(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=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(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.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(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(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(*its))) + return *itr; } } else { - for (unsigned i=0; i(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(*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; isetflag(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 (; ilet_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(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)); + for (lst::const_iterator it = ex_to(e).begin(); it != ex_to(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(); if (hash_thishash_other) return 1; - - unsigned typeid_this = tinfo(); - unsigned typeid_other = other.tinfo(); - - if (typeid_thisprint(print_tree(std::cout)); -// std::cout << " and "; -// other.print(print_tree(std::cout)); -// std::cout << std::endl; - return -1; - } - if (typeid_this>typeid_other) { + + const unsigned typeid_this = tinfo(); + const unsigned typeid_other = other.tinfo(); + if (typeid_this==typeid_other) { + GINAC_ASSERT(typeid(*this)==typeid(other)); +// int cmpval = compare_same_type(other); +// if (cmpval!=0) { +// std::cout << "hash collision, same type: " +// << *this << " and " << other << std::endl; +// this->print(print_tree(std::cout)); +// std::cout << " and "; +// other.print(print_tree(std::cout)); +// std::cout << std::endl; +// } +// return cmpval; + return compare_same_type(other); + } else { // std::cout << "hash collision, different types: " // << *this << " and " << other << std::endl; // this->print(print_tree(std::cout)); // std::cout << " and "; // other.print(print_tree(std::cout)); // std::cout << std::endl; - return 1; + return (typeid_thisprint(print_tree(std::cout)); -// std::cout << " and "; -// other.print(print_tree(std::cout)); -// std::cout << std::endl; -// } -// return cmpval; - - return compare_same_type(other); } -/** Test for equality. +/** Test for syntactic equality. * This is only a quick test, meaning objects should be in the same domain. * You might have to .expand(), .normal() objects first, depending on the * domain of your computation, to get a more reliable answer. @@ -779,18 +825,18 @@ bool basic::is_equal(const basic & other) const /** Stop further evaluation. * * @see basic::eval */ -const basic & basic::hold(void) const +const basic & basic::hold() const { return setflag(status_flags::evaluated); } /** Ensure the object may be modified without hurting others, throws if this * is not the case. */ -void basic::ensure_if_modifiable(void) const +void basic::ensure_if_modifiable() const { - if (this->refcount>1) + if (refcount > 1) throw(std::runtime_error("cannot modify multiply referenced object")); - clearflag(status_flags::hash_calculated); + clearflag(status_flags::hash_calculated | status_flags::evaluated); } ////////// diff --git a/ginac/basic.h b/ginac/basic.h index d2d3e865..a68c2eee 100644 --- a/ginac/basic.h +++ b/ginac/basic.h @@ -23,6 +23,7 @@ #ifndef __GINAC_BASIC_H__ #define __GINAC_BASIC_H__ +#include // for size_t #include // CINT needs to work properly with #include @@ -35,12 +36,13 @@ namespace GiNaC { class ex; +class ex_is_less; class symbol; -class lst; class numeric; class relational; class archive_node; class print_context; +template class ptr; typedef std::vector exvector; @@ -53,6 +55,15 @@ struct map_function { }; +/** Degenerate base class for visitors. basic and derivative classes + * support Robert C. Martin's Acyclic Visitor pattern (cf. + * http://objectmentor.com/publications/acv.pdf). */ +class visitor { +protected: + virtual ~visitor() {} +}; + + /** This class is the ABC (abstract base class) of GiNaC's class hierarchy. * It is responsible for the reference counting. */ class basic @@ -60,88 +71,133 @@ class basic GINAC_DECLARE_REGISTERED_CLASS_NO_CTORS(basic, void) friend class ex; + friend class ptr; - // default ctor, dtor, copy ctor, assignment operator and helpers -public: + // default constructor, destructor, copy constructor and assignment operator +protected: basic() : tinfo_key(TINFO_basic), flags(0), refcount(0) {} - /** basic dtor, virtual because class ex will delete objects via ptr. */ + +public: + /** basic destructor, virtual because class ex will delete objects of + * derived classes via a basic*. */ virtual ~basic() { - destroy(false); GINAC_ASSERT((!(flags & status_flags::dynallocated))||(refcount==0)); } basic(const basic & other); const basic & operator=(const basic & other); + protected: - /** For use by copy ctor and assignment operator. */ - void copy(const basic & other) - { - flags = other.flags & ~status_flags::dynallocated; - hashvalue = other.hashvalue; - tinfo_key = other.tinfo_key; - } - /** For use by dtor and assignment operator. */ - virtual void destroy(bool call_parent) { } - - // other ctors - /** ctor with specified tinfo_key */ + /** Constructor with specified tinfo_key (used by derived classes instead + * of the default constructor to avoid assigning tinfo_key twice). */ basic(unsigned ti) : tinfo_key(ti), flags(0), refcount(0) {} // new virtual functions which can be overridden by derived classes public: // only const functions please (may break reference counting) - virtual basic * duplicate() const; + + /** Create a clone of this object 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. */ + virtual basic * duplicate() const { return new basic(*this); } + + // evaluation + virtual ex eval(int level = 0) const; + virtual ex evalf(int level = 0) const; + virtual ex evalm() const; +protected: + virtual ex eval_ncmul(const exvector & v) const; +public: + virtual ex eval_indexed(const basic & i) const; + + // printing virtual void print(const print_context & c, unsigned level = 0) const; - virtual void dbgprint(void) const; - virtual void dbgprinttree(void) const; - virtual unsigned precedence(void) const; + virtual void dbgprint() const; + virtual void dbgprinttree() const; + virtual unsigned precedence() const; + + // info virtual bool info(unsigned inf) const; - virtual unsigned nops() const; - virtual ex op(int i) const; - virtual ex & let_op(int i); + + // operand access + virtual size_t nops() const; + virtual ex op(size_t i) const; virtual ex operator[](const ex & index) const; - virtual ex operator[](int i) const; - virtual ex expand(unsigned options = 0) const; + virtual ex operator[](size_t i) const; + virtual ex & let_op(size_t i); + virtual ex & operator[](const ex & index); + virtual ex & operator[](size_t i); + + // pattern matching virtual bool has(const ex & other) const; + virtual bool match(const ex & pattern, lst & repl_lst) const; +protected: + virtual bool match_same_type(const basic & other) const; +public: + + // substitutions + virtual ex subs(const lst & ls, const lst & lr, unsigned options = 0) const; + + // function mapping virtual ex map(map_function & f) const; + + // visitors and tree traversal + virtual void accept(GiNaC::visitor & v) const + { + if (visitor *p = dynamic_cast(&v)) + p->visit(*this); + } + + // degree/coeff virtual int degree(const ex & s) const; virtual int ldegree(const ex & s) const; virtual ex coeff(const ex & s, int n = 1) const; + + // expand/collect + virtual ex expand(unsigned options = 0) const; virtual ex collect(const ex & s, bool distributed = false) const; - virtual ex eval(int level = 0) const; - virtual ex evalf(int level = 0) const; - virtual ex evalm(void) const; + + // differentiation and series expansion +protected: + virtual ex derivative(const symbol & s) const; +public: virtual ex series(const relational & r, int order, unsigned options = 0) const; - virtual bool match(const ex & pattern, lst & repl_lst) const; - virtual ex subs(const lst & ls, const lst & lr, bool no_pattern = false) const; + + // rational functions virtual ex normal(lst &sym_lst, lst &repl_lst, int level = 0) const; virtual ex to_rational(lst &repl_lst) const; - virtual numeric integer_content(void) const; + virtual ex to_polynomial(lst &repl_lst) const; + + // polynomial algorithms + virtual numeric integer_content() const; virtual ex smod(const numeric &xi) const; - virtual numeric max_coefficient(void) const; - virtual exvector get_free_indices(void) const; - virtual ex eval_indexed(const basic & i) const; + virtual numeric max_coefficient() const; + + // indexed objects + virtual exvector get_free_indices() const; virtual ex add_indexed(const ex & self, const ex & other) const; virtual ex scalar_mul_indexed(const ex & self, const numeric & other) const; virtual bool contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const; - virtual unsigned return_type(void) const; - virtual unsigned return_type_tinfo(void) const; + + // noncommutativity + virtual unsigned return_type() const; + virtual unsigned return_type_tinfo() const; + protected: // functions that should be called from class ex only - virtual ex derivative(const symbol & s) const; virtual int compare_same_type(const basic & other) const; virtual bool is_equal_same_type(const basic & other) const; - virtual bool match_same_type(const basic & other) const; - virtual unsigned calchash(void) const; - virtual ex simplify_ncmul(const exvector & v) const; + + virtual unsigned calchash() const; // non-virtual functions in this class public: - ex subs(const ex & e, bool no_pattern = false) const; - ex diff(const symbol & s, unsigned nth=1) const; + ex subs(const ex & e, unsigned options = 0) const; + ex subs_one_level(const lst & ls, const lst & lr, unsigned options) const; + ex diff(const symbol & s, unsigned nth = 1) const; int compare(const basic & other) const; bool is_equal(const basic & other) const; - const basic & hold(void) const; - unsigned gethash(void) const { if (flags & status_flags::hash_calculated) return hashvalue; else return calchash(); } - unsigned tinfo(void) const {return tinfo_key;} + const basic & hold() const; + unsigned gethash() const { if (flags & status_flags::hash_calculated) return hashvalue; else return calchash(); } + unsigned tinfo() const {return tinfo_key;} /** Set some status_flags. */ const basic & setflag(unsigned f) const {flags |= f; return *this;} @@ -150,7 +206,7 @@ public: const basic & clearflag(unsigned f) const {flags &= ~f; return *this;} protected: - void ensure_if_modifiable(void) const; + void ensure_if_modifiable() const; // member variables protected: @@ -158,29 +214,31 @@ protected: mutable unsigned flags; ///< of type status_flags mutable unsigned hashvalue; ///< hash value private: - unsigned refcount; ///< Number of reference counts + size_t refcount; ///< reference counter, managed by ptr }; + // global variables extern int max_recursion_level; + // convenience type checker template functions /** Check if obj is a T, including base classes. */ template inline bool is_a(const basic &obj) { - return dynamic_cast(&obj)!=0; + return dynamic_cast(&obj) != 0; } /** Check if obj is a T, not including base classes. This one is just an * inefficient default. It should in all time-critical cases be overridden - * by template specializations that don't create a temporary. */ + * by template specializations that use the TINFO_* constants directly. */ template inline bool is_exactly_a(const class basic &obj) { - const T foo; return foo.tinfo()==obj.tinfo(); + return obj.tinfo() == T::reg_info.tinfo_key; } /** Check if ex is a handle to a T, including base classes. */ diff --git a/ginac/clifford.cpp b/ginac/clifford.cpp index b6dd31ef..547285d0 100644 --- a/ginac/clifford.cpp +++ b/ginac/clifford.cpp @@ -32,6 +32,7 @@ #include "symmetry.h" #include "lst.h" #include "relational.h" +#include "operators.h" #include "mul.h" #include "print.h" #include "archive.h" @@ -47,7 +48,7 @@ GINAC_IMPLEMENT_REGISTERED_CLASS(diracgammaL, tensor) GINAC_IMPLEMENT_REGISTERED_CLASS(diracgammaR, tensor) ////////// -// default ctor, dtor, copy ctor, assignment operator and helpers +// default constructors ////////// clifford::clifford() : representation_label(0) @@ -55,18 +56,11 @@ clifford::clifford() : representation_label(0) tinfo_key = TINFO_clifford; } -void clifford::copy(const clifford & other) -{ - inherited::copy(other); - representation_label = other.representation_label; -} - -DEFAULT_DESTROY(clifford) -DEFAULT_CTORS(diracone) -DEFAULT_CTORS(diracgamma) -DEFAULT_CTORS(diracgamma5) -DEFAULT_CTORS(diracgammaL) -DEFAULT_CTORS(diracgammaR) +DEFAULT_CTOR(diracone) +DEFAULT_CTOR(diracgamma) +DEFAULT_CTOR(diracgamma5) +DEFAULT_CTOR(diracgammaL) +DEFAULT_CTOR(diracgammaR) ////////// // other constructors @@ -103,7 +97,7 @@ clifford::clifford(unsigned char rl, exvector * vp) : inherited(sy_none(), vp), // archiving ////////// -clifford::clifford(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) +clifford::clifford(const archive_node &n, lst &sym_lst) : inherited(n, sym_lst) { unsigned rl; n.find_unsigned("label", rl); @@ -295,7 +289,7 @@ bool diracgamma::contract_with(exvector::iterator self, exvector::iterator other /** Perform automatic simplification on noncommutative product of clifford * objects. This removes superfluous ONEs, permutes gamma5/L/R's to the front * and removes squares of gamma objects. */ -ex clifford::simplify_ncmul(const exvector & v) const +ex clifford::eval_ncmul(const exvector & v) const { exvector s; s.reserve(v.size()); @@ -453,17 +447,17 @@ ex clifford::simplify_ncmul(const exvector & v) const if (s.empty()) return clifford(diracone(), representation_label) * sign; if (something_changed) - return nonsimplified_ncmul(s) * sign; + return reeval_ncmul(s) * sign; else - return simplified_ncmul(s) * sign; + return hold_ncmul(s) * sign; } -ex clifford::thisexprseq(const exvector & v) const +ex clifford::thiscontainer(const exvector & v) const { return clifford(representation_label, v); } -ex clifford::thisexprseq(exvector * vp) const +ex clifford::thiscontainer(exvector * vp) const { return clifford(representation_label, vp); } @@ -500,16 +494,6 @@ ex dirac_gammaR(unsigned char rl) return clifford(diracgammaR(), rl); } -ex dirac_gamma6(unsigned char rl) -{ - return clifford(diracone(), rl) + clifford(diracgamma5(), rl); -} - -ex dirac_gamma7(unsigned char rl) -{ - return clifford(diracone(), rl) - clifford(diracgamma5(), rl); -} - ex dirac_slash(const ex & e, const ex & dim, unsigned char rl) { // Slashed vectors are actually stored as a clifford object with the @@ -534,13 +518,13 @@ static bool is_clifford_tinfo(unsigned ti) /** Take trace of a string of an even number of Dirac gammas given a vector * of indices. */ -static ex trace_string(exvector::const_iterator ix, unsigned num) +static ex trace_string(exvector::const_iterator ix, size_t num) { // Tr gamma.mu gamma.nu = 4 g.mu.nu if (num == 2) return lorentz_g(ix[0], ix[1]); - // Tr gamma.mu gamma.nu gamma.rho gamma.sig = 4 (g.mu.nu g.rho.sig + g.nu.rho g.mu.sig - g.mu.rho g.nu.sig + // Tr gamma.mu gamma.nu gamma.rho gamma.sig = 4 (g.mu.nu g.rho.sig + g.nu.rho g.mu.sig - g.mu.rho g.nu.sig ) else if (num == 4) return lorentz_g(ix[0], ix[1]) * lorentz_g(ix[2], ix[3]) + lorentz_g(ix[1], ix[2]) * lorentz_g(ix[0], ix[3]) @@ -556,8 +540,8 @@ static ex trace_string(exvector::const_iterator ix, unsigned num) exvector v(num - 2); int sign = 1; ex result; - for (unsigned i=1; i(e)) { // Trace of product: pull out non-clifford factors ex prod = _ex1; - for (unsigned i=0; i(e)) { if (!is_clifford_tinfo(e.return_type_tinfo(), rl)) return _ex0; @@ -610,7 +594,7 @@ ex dirac_trace(const ex & e, unsigned char rl, const ex & trONE) // gamma5 gets moved to the front so this check is enough bool has_gamma5 = is_a(e.op(0).op(0)); - unsigned num = e.nops(); + size_t num = e.nops(); if (has_gamma5) { @@ -634,23 +618,23 @@ ex dirac_trace(const ex & e, unsigned char rl, const ex & trONE) // I/4! * epsilon0123.mu1.mu2.mu3.mu4 * Tr gamma.mu1 gamma.mu2 gamma.mu3 gamma.mu4 S_2k // (the epsilon is always 4-dimensional) exvector ix(num-1), bv(num-1); - for (unsigned i=1; i(rhs) && rhs.return_type() == return_types::noncommutative && is_clifford_tinfo(rhs.return_type_tinfo())) { // Expand product, if necessary ex rhs_expanded = rhs.expand(); if (!is_a(rhs_expanded)) { - srl.let_op(i) = (lhs == canonicalize_clifford(rhs_expanded)); + srl[i] = (lhs == canonicalize_clifford(rhs_expanded)); continue; } else if (!is_a(rhs.op(0))) @@ -722,7 +707,7 @@ ex canonicalize_clifford(const ex & e) exvector v; v.reserve(rhs.nops()); - for (unsigned j=0; jop(0), su3one)) + if (!is_a(it->op(0))) s.push_back(*it); it++; } @@ -170,15 +164,15 @@ ex color::simplify_ncmul(const exvector & v) const if (s.empty()) return color(su3one(), representation_label); else - return simplified_ncmul(s); + return hold_ncmul(s); } -ex color::thisexprseq(const exvector & v) const +ex color::thiscontainer(const exvector & v) const { return color(representation_label, v); } -ex color::thisexprseq(exvector * vp) const +ex color::thiscontainer(exvector * vp) const { return color(representation_label, vp); } @@ -306,7 +300,7 @@ bool su3t::contract_with(exvector::iterator self, exvector::iterator other, exve GINAC_ASSERT(is_a(self->op(0))); unsigned char rl = ex_to(*self).get_representation_label(); - if (is_ex_exactly_of_type(other->op(0), su3t)) { + if (is_exactly_a(other->op(0))) { // Contraction only makes sense if the represenation labels are equal GINAC_ASSERT(is_a(*other)); @@ -321,7 +315,7 @@ bool su3t::contract_with(exvector::iterator self, exvector::iterator other, exve // T.a T.b T.a = -1/6 T.b } else if (other - self == 2 - && is_ex_of_type(self[1], color)) { + && is_a(self[1])) { *self = numeric(-1, 6); *other = _ex1; return true; @@ -330,7 +324,7 @@ bool su3t::contract_with(exvector::iterator self, exvector::iterator other, exve } else { exvector::iterator it = self + 1; while (it != other) { - if (!is_ex_of_type(*it, color)) { + if (!is_a(*it)) { return false; } it++; @@ -360,7 +354,7 @@ bool su3d::contract_with(exvector::iterator self, exvector::iterator other, exve GINAC_ASSERT(self->nops() == 4); GINAC_ASSERT(is_a(self->op(0))); - if (is_ex_exactly_of_type(other->op(0), su3d)) { + if (is_exactly_a(other->op(0))) { // Find the dummy indices of the contraction exvector self_indices = ex_to(*self).get_indices(); @@ -388,11 +382,11 @@ bool su3d::contract_with(exvector::iterator self, exvector::iterator other, exve return true; } - } else if (is_ex_exactly_of_type(other->op(0), su3t)) { + } else if (is_exactly_a(other->op(0))) { // d.abc T.b T.c = 5/6 T.a if (other+1 != v.end() - && is_ex_exactly_of_type(other[1].op(0), su3t) + && is_exactly_a(other[1].op(0)) && ex_to(*self).has_dummy_index_for(other[1].op(1))) { exvector self_indices = ex_to(*self).get_indices(); @@ -419,7 +413,7 @@ bool su3f::contract_with(exvector::iterator self, exvector::iterator other, exve GINAC_ASSERT(self->nops() == 4); GINAC_ASSERT(is_a(self->op(0))); - if (is_ex_exactly_of_type(other->op(0), su3f)) { // f*d is handled by su3d class + if (is_exactly_a(other->op(0))) { // f*d is handled by su3d class // Find the dummy indices of the contraction exvector dummy_indices; @@ -441,11 +435,11 @@ bool su3f::contract_with(exvector::iterator self, exvector::iterator other, exve return true; } - } else if (is_ex_exactly_of_type(other->op(0), su3t)) { + } else if (is_exactly_a(other->op(0))) { // f.abc T.b T.c = 3/2 I T.a if (other+1 != v.end() - && is_ex_exactly_of_type(other[1].op(0), su3t) + && is_exactly_a(other[1].op(0)) && ex_to(*self).has_dummy_index_for(other[1].op(1))) { exvector self_indices = ex_to(*self).get_indices(); @@ -475,7 +469,7 @@ ex color_ONE(unsigned char rl) ex color_T(const ex & a, unsigned char rl) { - if (!is_ex_of_type(a, idx)) + if (!is_a(a)) throw(std::invalid_argument("indices of color_T must be of type idx")); if (!ex_to(a).get_dim().is_equal(8)) throw(std::invalid_argument("index dimension for color_T must be 8")); @@ -485,7 +479,7 @@ ex color_T(const ex & a, unsigned char rl) ex color_f(const ex & a, const ex & b, const ex & c) { - if (!is_ex_of_type(a, idx) || !is_ex_of_type(b, idx) || !is_ex_of_type(c, idx)) + if (!is_a(a) || !is_a(b) || !is_a(c)) throw(std::invalid_argument("indices of color_f must be of type idx")); if (!ex_to(a).get_dim().is_equal(8) || !ex_to(b).get_dim().is_equal(8) || !ex_to(c).get_dim().is_equal(8)) throw(std::invalid_argument("index dimension for color_f must be 8")); @@ -495,7 +489,7 @@ ex color_f(const ex & a, const ex & b, const ex & c) ex color_d(const ex & a, const ex & b, const ex & c) { - if (!is_ex_of_type(a, idx) || !is_ex_of_type(b, idx) || !is_ex_of_type(c, idx)) + if (!is_a(a) || !is_a(b) || !is_a(c)) throw(std::invalid_argument("indices of color_d must be of type idx")); if (!ex_to(a).get_dim().is_equal(8) || !ex_to(b).get_dim().is_equal(8) || !ex_to(c).get_dim().is_equal(8)) throw(std::invalid_argument("index dimension for color_d must be 8")); @@ -517,19 +511,19 @@ static bool is_color_tinfo(unsigned ti, unsigned char rl) ex color_trace(const ex & e, unsigned char rl) { - if (is_ex_of_type(e, color)) { + if (is_a(e)) { if (ex_to(e).get_representation_label() == rl - && is_ex_of_type(e.op(0), su3one)) + && is_a(e.op(0))) return _ex3; else return _ex0; - } else if (is_ex_exactly_of_type(e, mul)) { + } else if (is_exactly_a(e)) { // Trace of product: pull out non-color factors ex prod = _ex1; - for (unsigned i=0; i(e)) { if (!is_color_tinfo(e.return_type_tinfo(), rl)) return _ex0; // Expand product, if necessary ex e_expanded = e.expand(); - if (!is_ex_of_type(e_expanded, ncmul)) + if (!is_a(e_expanded)) return color_trace(e_expanded, rl); - unsigned num = e.nops(); + size_t num = e.nops(); if (num == 2) { @@ -572,7 +566,7 @@ ex color_trace(const ex & e, unsigned char rl) exvector v1; v1.reserve(num - 2); - for (unsigned i=0; ievalf(); + } else { + return number.evalf(); } return *this; } @@ -184,14 +164,12 @@ bool constant::is_equal_same_type(const basic & other) const return serial == o.serial; } -unsigned constant::calchash(void) const +unsigned constant::calchash() const { hashvalue = golden_ratio_hash(tinfo() ^ serial); - // mask out numeric hashes: - hashvalue &= 0x7FFFFFFFU; - + setflag(status_flags::hash_calculated); - + return hashvalue; } diff --git a/ginac/constant.h b/ginac/constant.h index e0242d97..0092ac3b 100644 --- a/ginac/constant.h +++ b/ginac/constant.h @@ -29,7 +29,7 @@ namespace GiNaC { -typedef ex (*evalffunctype)(void); +typedef ex (*evalffunctype)(); /** This class holds constants, symbols with specific numerical value. Each * object of this class must either provide their own function to evaluate it @@ -41,7 +41,7 @@ class constant : public basic // member functions - // other ctors + // other constructors public: constant(const std::string & initname, evalffunctype efun = 0, const std::string & texname = std::string()); constant(const std::string & initname, const numeric & initnumber, const std::string & texname = std::string()); @@ -53,7 +53,7 @@ public: protected: ex derivative(const symbol & s) const; bool is_equal_same_type(const basic & other) const; - unsigned calchash(void) const; + unsigned calchash() const; // new virtual functions which can be overridden by derived classes // none @@ -67,7 +67,7 @@ private: std::string name; ///< printname of this constant std::string TeX_name; ///< LaTeX name evalffunctype ef; - numeric *number; ///< numerical value this constant evalf()s to + ex number; ///< numerical value this constant evalf()s to unsigned serial; ///< unique serial number for comparison static unsigned next_serial; }; diff --git a/ginac/container.h b/ginac/container.h new file mode 100644 index 00000000..135adb96 --- /dev/null +++ b/ginac/container.h @@ -0,0 +1,626 @@ +/** @file container.h + * + * Wrapper template for making GiNaC classes out of STL containers. */ + +/* + * 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 __GINAC_CONTAINER_H__ +#define __GINAC_CONTAINER_H__ + +#include +#include +#include +#include +#include + +#include "ex.h" +#include "print.h" +#include "archive.h" +#include "assertion.h" + +namespace GiNaC { + + +/** Helper template for encapsulating the reserve() mechanics of STL containers. */ +template