From 4e3a4ac2bcb0837611ea31bc8fc05d84a20c33ac Mon Sep 17 00:00:00 2001 From: Richard Kreckel Date: Wed, 28 Feb 2001 15:54:52 +0000 Subject: [PATCH] * ginac/registrar.h: dtor is inlined now. * ginac/basic.h, ginac/ex.h: removed INLINE_FOO_CONSTRUCTORS and hand-inlined stuff instead, since the macros turned out to get in the way while fine-tuning the inlining. * ginac/utils.h: if 'long long' works, use that one for computing the hash value instead of floating point tricks. 2 Reasons: on Intel the assembler is terrible and slow otherwise, 'long long' will appear in C++ anyways when they adapt to the C99 standard. * Several other small performance tweaks. * ginac/constant.cpp: (constant::calchash()) implement, caring for serial. * ginac/function.pl (function::calchash()): implement, caring for serial. * ginac/expairseq.cpp: honor coeff's hash value. * ginac/pseries.cpp: (pseries::power_const()) fix problems with zero pseries. * Added several pounds of in-source documentation in doxygen style. --- ginac/add.cpp | 81 ++-- ginac/add.h | 15 +- ginac/archive.cpp | 4 - ginac/archive.h | 4 - ginac/assertion.h | 6 +- ginac/basic.cpp | 206 +++++---- ginac/basic.h | 107 ++--- ginac/clifford.cpp | 4 - ginac/clifford.h | 4 - ginac/color.cpp | 4 - ginac/color.h | 4 - ginac/coloridx.cpp | 4 - ginac/coloridx.h | 4 - ginac/constant.cpp | 50 ++- ginac/constant.h | 40 +- ginac/container.pl | 24 +- ginac/debugmsg.h | 2 +- ginac/ex.cpp | 162 +------ ginac/ex.h | 375 ++++++++-------- ginac/expair.h | 169 ++----- ginac/expairseq.cpp | 954 +++++++++++++++++++--------------------- ginac/expairseq.h | 79 ++-- ginac/exprseq_suppl.cpp | 10 +- ginac/fail.cpp | 10 +- ginac/fail.h | 14 +- ginac/flags.h | 41 +- ginac/function.pl | 128 ++---- ginac/idx.cpp | 4 - ginac/idx.h | 4 - ginac/indexed.cpp | 4 - ginac/indexed.h | 4 - ginac/inifcns.cpp | 4 - ginac/inifcns.h | 4 - ginac/inifcns_gamma.cpp | 4 - ginac/inifcns_trans.cpp | 4 - ginac/inifcns_zeta.cpp | 4 - ginac/input_lexer.h | 4 - ginac/isospin.cpp | 6 +- ginac/isospin.h | 4 - ginac/lorentzidx.cpp | 4 - ginac/lorentzidx.h | 4 - ginac/lortensor.cpp | 6 +- ginac/lortensor.h | 12 +- ginac/lst_suppl.cpp | 8 +- ginac/matrix.cpp | 18 +- ginac/matrix.h | 20 +- ginac/mul.cpp | 105 +++-- ginac/mul.h | 18 +- ginac/ncmul.cpp | 6 +- ginac/ncmul.h | 4 - ginac/normal.cpp | 32 +- ginac/normal.h | 4 - ginac/numeric.cpp | 288 ++++++------ ginac/numeric.h | 212 +++++---- ginac/operators.cpp | 31 +- ginac/operators.h | 4 - ginac/power.cpp | 143 +++--- ginac/power.h | 25 +- ginac/pseries.cpp | 36 +- ginac/pseries.h | 6 +- ginac/registrar.cpp | 4 - ginac/registrar.h | 25 +- ginac/relational.cpp | 24 +- ginac/relational.h | 6 +- ginac/remember.cpp | 12 +- ginac/remember.h | 4 - ginac/simp_lor.cpp | 6 +- ginac/simp_lor.h | 4 - ginac/structure.cpp | 12 +- ginac/structure.h | 8 +- ginac/structure.pl | 22 +- ginac/symbol.cpp | 117 +++-- ginac/symbol.h | 42 +- ginac/tinfos.h | 4 - ginac/utils.cpp | 27 +- ginac/utils.h | 106 ++--- 76 files changed, 1583 insertions(+), 2381 deletions(-) diff --git a/ginac/add.cpp b/ginac/add.cpp index 2f227fcf..0c22465a 100644 --- a/ginac/add.cpp +++ b/ginac/add.cpp @@ -29,9 +29,7 @@ #include "debugmsg.h" #include "utils.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC GINAC_IMPLEMENT_REGISTERED_CLASS(add, expairseq) @@ -49,6 +47,7 @@ add::add() // protected +/** For use by copy ctor and assignment operator. */ void add::copy(const add & other) { inherited::copy(other); @@ -83,23 +82,6 @@ add::add(const exvector & v) GINAC_ASSERT(is_canonical()); } -/* -add::add(const epvector & v, bool do_not_canonicalize) -{ - debugmsg("add constructor from epvector,bool",LOGLEVEL_CONSTRUCT); - tinfo_key = TINFO_add; - if (do_not_canonicalize) { - seq=v; -#ifdef EXPAIRSEQ_USE_HASHTAB - combine_same_terms(); // to build hashtab -#endif // def EXPAIRSEQ_USE_HASHTAB - } else { - construct_from_epvector(v); - } - GINAC_ASSERT(is_canonical()); -} -*/ - add::add(const epvector & v) { debugmsg("add constructor from epvector",LOGLEVEL_CONSTRUCT); @@ -218,12 +200,12 @@ void add::printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) debugmsg("add print csrc", LOGLEVEL_PRINT); if (precedence <= upper_precedence) os << "("; - + // Print arguments, separated by "+" epvector::const_iterator it = seq.begin(); epvector::const_iterator itend = seq.end(); while (it != itend) { - + // If the coefficient is -1, it is replaced by a single minus sign if (it->coeff.compare(_num1()) == 0) { it->rest.bp->printcsrc(os, type, precedence); @@ -244,14 +226,14 @@ void add::printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) os << "*"; it->rest.bp->printcsrc(os, type, precedence); } - + // Separator is "+", except if the following expression would have a leading minus sign it++; if (it != itend && !(it->coeff.compare(_num0()) < 0 || (it->coeff.compare(_num1()) == 0 && is_ex_exactly_of_type(it->rest, numeric) && it->rest.compare(_num0()) < 0))) os << "+"; } - if (!overall_coeff.is_equal(_ex0())) { + if (!overall_coeff.is_zero()) { if (overall_coeff.info(info_flags::positive)) os << '+'; overall_coeff.bp->printcsrc(os,type,precedence); } @@ -289,13 +271,14 @@ bool add::info(unsigned inf) const int add::degree(const symbol & s) const { int deg = INT_MIN; - if (!overall_coeff.is_equal(_ex0())) { + if (!overall_coeff.is_equal(_ex0())) deg = 0; - } + int cur_deg; for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { - cur_deg=(*cit).rest.degree(s); - if (cur_deg>deg) deg=cur_deg; + cur_deg = (*cit).rest.degree(s); + if (cur_deg>deg) + deg = cur_deg; } return deg; } @@ -303,9 +286,9 @@ int add::degree(const symbol & s) const int add::ldegree(const symbol & s) const { int deg = INT_MAX; - if (!overall_coeff.is_equal(_ex0())) { + if (!overall_coeff.is_equal(_ex0())) deg = 0; - } + int cur_deg; for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { cur_deg = (*cit).rest.ldegree(s); @@ -335,10 +318,10 @@ ex add::eval(int level) const { // simplifications: +(;c) -> c // +(x;1) -> x - + debugmsg("add eval",LOGLEVEL_MEMBER_FUNCTION); - - epvector * evaled_seqp=evalchildren(level); + + epvector * evaled_seqp = evalchildren(level); if (evaled_seqp!=0) { // do more evaluation later return (new add(evaled_seqp,overall_coeff))-> @@ -348,24 +331,23 @@ ex add::eval(int level) const #ifdef DO_GINAC_ASSERT for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { GINAC_ASSERT(!is_ex_exactly_of_type((*cit).rest,add)); - if (is_ex_exactly_of_type((*cit).rest,numeric)) { + if (is_ex_exactly_of_type((*cit).rest,numeric)) dbgprint(); - } GINAC_ASSERT(!is_ex_exactly_of_type((*cit).rest,numeric)); } #endif // def DO_GINAC_ASSERT if (flags & status_flags::evaluated) { GINAC_ASSERT(seq.size()>0); - GINAC_ASSERT((seq.size()>1)||!overall_coeff.is_equal(_ex0())); + GINAC_ASSERT(seq.size()>1 || !overall_coeff.is_zero()); return *this; } - int seq_size=seq.size(); + int seq_size = seq.size(); if (seq_size==0) { // +(;c) -> c return overall_coeff; - } else if ((seq_size==1)&&overall_coeff.is_equal(_ex0())) { + } else if ((seq_size==1) && overall_coeff.is_equal(_ex0())) { // +(x;0) -> x return recombine_pair_to_ex(*(seq.begin())); } @@ -440,14 +422,14 @@ 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)) { - const mul & mulref = ex_to_mul(e); + const mul &mulref = ex_to_mul(e); ex numfactor = mulref.overall_coeff; - // mul * mulcopyp = static_cast(mulref.duplicate()); - mul * mulcopyp = new mul(mulref); + mul *mulcopyp = new mul(mulref); mulcopyp->overall_coeff = _ex1(); mulcopyp->clearflag(status_flags::evaluated); mulcopyp->clearflag(status_flags::hash_calculated); - return expair(mulcopyp->setflag(status_flags::dynallocated),numfactor); + mulcopyp->setflag(status_flags::dynallocated); + return expair(*mulcopyp,numfactor); } return expair(e,_ex1()); } @@ -464,12 +446,12 @@ 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 (are_ex_trivially_equal(c, _ex1())) return expair(*mulcopyp, numfactor); - } else if (are_ex_trivially_equal(numfactor, _ex1())) { + else if (are_ex_trivially_equal(numfactor, _ex1())) return expair(*mulcopyp, c); - } - return expair(*mulcopyp, ex_to_numeric(numfactor).mul_dyn(ex_to_numeric(c))); + else + return expair(*mulcopyp, ex_to_numeric(numfactor).mul_dyn(ex_to_numeric(c))); } else if (is_ex_exactly_of_type(e, numeric)) { if (are_ex_trivially_equal(c, _ex1())) return expair(e, _ex1()); @@ -477,7 +459,7 @@ expair add::combine_ex_with_coeff_to_pair(const ex & e, } return expair(e, c); } - + expair add::combine_pair_with_coeff_to_pair(const expair & p, const ex & c) const { @@ -506,8 +488,11 @@ ex add::expand(unsigned options) const return *this; epvector * vp = expandchildren(options); - if (vp==0) + if (vp==0) { + // the terms have not changed, so it is safe to declare this expanded + setflag(status_flags::expanded); return *this; + } return (new add(vp,overall_coeff))->setflag(status_flags::expanded | status_flags::dynallocated); } @@ -520,6 +505,4 @@ ex add::expand(unsigned options) const unsigned add::precedence = 40; -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/add.h b/ginac/add.h index 0c8e37ca..8a93186b 100644 --- a/ginac/add.h +++ b/ginac/add.h @@ -25,28 +25,25 @@ #include "expairseq.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC /** Sum of expressions. */ class add : public expairseq { GINAC_DECLARE_REGISTERED_CLASS(add, expairseq) - + friend class mul; friend class ncmul; friend class power; - + // other constructors public: add(const ex & lh, const ex & rh); add(const exvector & v); add(const epvector & v); - //add(const epvector & v, bool do_not_canonicalize=0); add(const epvector & v, const ex & oc); add(epvector * vp, const ex & oc); - + // functions overriding virtual functions from bases classes public: void print(std::ostream & os, unsigned upper_precedence=0) const; @@ -73,9 +70,9 @@ protected: ex thisexpairseq(epvector * vp, const ex & oc) const; expair split_ex_to_pair(const ex & e) const; expair combine_ex_with_coeff_to_pair(const ex & e, - const ex & c) const; + const ex & c) const; expair combine_pair_with_coeff_to_pair(const expair & p, - const ex & c) const; + const ex & c) const; ex recombine_pair_to_ex(const expair & p) const; ex expand(unsigned options=0) const; @@ -97,8 +94,6 @@ inline const add &ex_to_add(const ex &e) return static_cast(*e.bp); } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_ADD_H__ diff --git a/ginac/archive.cpp b/ginac/archive.cpp index 61d60c27..849da9b7 100644 --- a/ginac/archive.cpp +++ b/ginac/archive.cpp @@ -29,9 +29,7 @@ #include "config.h" #include "utils.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC /** Archive an expression. @@ -591,6 +589,4 @@ archive* archive_node::dummy_ar_creator(void) } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/archive.h b/ginac/archive.h index d56c0e6c..24c6d5d9 100644 --- a/ginac/archive.h +++ b/ginac/archive.h @@ -29,9 +29,7 @@ #include #include -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC class lst; class archive; @@ -183,8 +181,6 @@ std::ostream &operator<<(std::ostream &os, const archive &ar); std::istream &operator>>(std::istream &is, archive &ar); -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_ARCHIVE_H__ diff --git a/ginac/assertion.h b/ginac/assertion.h index 8e6c29f9..536a18a4 100644 --- a/ginac/assertion.h +++ b/ginac/assertion.h @@ -23,14 +23,14 @@ #ifndef __GINAC_ASSERTION_H__ #define __GINAC_ASSERTION_H__ -extern "C" { -#include -} +#include #if !defined(GINAC_ASSERT) #if defined(DO_GINAC_ASSERT) +/** Assertion macro for checking invariances. */ #define GINAC_ASSERT(X) assert(X) #else +/** Assertion macro for checking invariances. */ #define GINAC_ASSERT(X) ((void)0) #endif #endif diff --git a/ginac/basic.cpp b/ginac/basic.cpp index a33433da..6adc4c49 100644 --- a/ginac/basic.cpp +++ b/ginac/basic.cpp @@ -35,38 +35,21 @@ #include "utils.h" #include "debugmsg.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC GINAC_IMPLEMENT_REGISTERED_CLASS_NO_CTORS(basic, void) ////////// -// default constructor, destructor, copy constructor assignment operator and helpers +// default ctor, dtor, copy ctor assignment operator and helpers ////////// // public -#ifndef INLINE_BASIC_CONSTRUCTORS -basic::basic() : flags(0), refcount(0), tinfo_key(TINFO_BASIC) +basic::basic(const basic & other) : tinfo_key(TINFO_basic), flags(0), refcount(0) { - debugmsg("basic default constructor", LOGLEVEL_CONSTRUCT); - // nothing to do -} - -basic::~basic() -{ - debugmsg("basic destructor", LOGLEVEL_DESTRUCT); - destroy(false); - GINAC_ASSERT((!(flags & status_flags::dynallocated))||(refcount==0)); -} - -basic::basic(const basic & other) : flags(0), refcount(0), tinfo_key(TINFO_BASIC) -{ - debugmsg("basic copy constructor", LOGLEVEL_CONSTRUCT); + debugmsg("basic copy ctor", LOGLEVEL_CONSTRUCT); copy(other); } -#endif const basic & basic::operator=(const basic & other) { @@ -80,19 +63,13 @@ const basic & basic::operator=(const basic & other) // protected -// none (all inlined) +// none (all conditionally inlined) ////////// -// other constructors +// other ctors ////////// -#ifndef INLINE_BASIC_CONSTRUCTORS -basic::basic(unsigned ti) : flags(0), refcount(0), tinfo_key(ti) -{ - debugmsg("basic constructor with tinfo_key", LOGLEVEL_CONSTRUCT); - // nothing to do -} -#endif +// none (all conditionally inlined) ////////// // archiving @@ -101,7 +78,7 @@ basic::basic(unsigned ti) : flags(0), refcount(0), tinfo_key(ti) /** Construct object from archive_node. */ basic::basic(const archive_node &n, const lst &sym_lst) : flags(0), refcount(0) { - debugmsg("basic constructor from archive_node", LOGLEVEL_CONSTRUCT); + debugmsg("basic ctor from archive_node", LOGLEVEL_CONSTRUCT); // Reconstruct tinfo_key from class name std::string class_name; @@ -135,14 +112,15 @@ void basic::archive(archive_node &n) const // public -/** Output to stream formatted to be useful as ginsh input. */ +/** Output to ostream formatted as parsable (as in ginsh) input. + * Generally, superfluous parenthesis should be avoided as far as possible. */ void basic::print(std::ostream & os, unsigned upper_precedence) const { debugmsg("basic print",LOGLEVEL_PRINT); os << "[basic object]"; } -/** Output to stream in ugly raw format, so brave developers can have a look +/** Output to ostream in ugly raw format, so brave developers can have a look * at the underlying structure. */ void basic::printraw(std::ostream & os) const { @@ -150,7 +128,7 @@ void basic::printraw(std::ostream & os) const os << "[basic object]"; } -/** Output to stream formatted in tree- (indented-) form, so developers can +/** Output to ostream formatted in tree- (indented-) form, so developers can * have a look at the underlying structure. */ void basic::printtree(std::ostream & os, unsigned indent) const { @@ -165,7 +143,7 @@ void basic::printtree(std::ostream & os, unsigned indent) const } } -/** Output to stream formatted as C-source. +/** Output to ostream formatted as C-source. * * @param os a stream for output * @param type variable type (one of the csrc_types) @@ -178,13 +156,13 @@ void basic::printcsrc(std::ostream & os, unsigned type, unsigned upper_precedenc /** Little wrapper arount print to be called within a debugger. * This is needed because you cannot call foo.print(cout) from within the - * debugger because it might not know what cout is. This method can be invoked - * with no argument and it will simply print to stdout. + * 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 { - print(std::cerr); + this->print(std::cerr); std::cerr << std::endl; } @@ -194,9 +172,12 @@ void basic::dbgprint(void) const * @see basic::printtree */ void basic::dbgprinttree(void) const { - printtree(std::cerr,0); + this->printtree(std::cerr,0); } +/** 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 { debugmsg("basic duplicate",LOGLEVEL_DUPLICATE); @@ -208,7 +189,8 @@ basic * basic::duplicate() const * @see class info_flags */ bool basic::info(unsigned inf) const { - return false; // all possible properties are false for basic objects + // all possible properties are false for basic objects + return false; } /** Number of operands/members. */ @@ -246,16 +228,19 @@ ex basic::operator[](int i) const } /** Search ocurrences. An object 'has' an expression if it is the expression - * itself or one of the children 'has' it. */ + * 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 but e.has(x+y) + * is false. */ bool basic::has(const ex & other) const { GINAC_ASSERT(other.bp!=0); if (is_equal(*other.bp)) return true; if (nops()>0) { - for (unsigned i=0; ildegree(s); - int deg = this->degree(s); - for (int n=ldeg; n<=deg; n++) { + for (int n=this->ldegree(s); n<=this->degree(s); n++) x += this->coeff(s,n)*power(s,n); - } + return x; } -/* Perform automatic symbolic evaluations on expression. */ +/** Perform automatic non-interruptive symbolic evaluation on expression. */ ex basic::eval(int level) const { // There is nothing to do for basic objects: @@ -304,7 +287,8 @@ ex basic::evalf(int level) const return *this; } -/* Substitute a set of symbols. */ +/** Substitute a set of symbols by arbitrary expressions. The ex returned + * will already be evaluated. */ ex basic::subs(const lst & ls, const lst & lr) const { return *this; @@ -357,8 +341,10 @@ ex basic::derivative(const symbol & s) const throw(std::logic_error("differentiation not supported by this type")); } -/** Returns order relation between two objects of same type. Needs to be - * implemented by each class. */ +/** Returns order relation between two objects of same type. This needs to be + * implemented by each class. It may never return anything else than 0, + * signalling equality, or +1 and -1 signalling inequality and determining + * the canonical ordering. */ int basic::compare_same_type(const basic & other) const { return compare_pointers(this, &other); @@ -366,10 +352,12 @@ int basic::compare_same_type(const basic & other) const /** Returns true if two objects of same type are equal. Normally needs * not be reimplemented as long as it wasn't overwritten by some parent - * class, since it just calls complare_same_type(). */ + * class, since it just calls compare_same_type(). The reason why this + * function exists is that sometimes it is easier to determine equality + * than an order relation and then it can be overridden. */ bool basic::is_equal_same_type(const basic & other) const { - return compare_same_type(other)==0; + return this->compare_same_type(other)==0; } unsigned basic::return_type(void) const @@ -382,20 +370,27 @@ unsigned basic::return_type_tinfo(void) const return tinfo(); } +/** Compute the hash value of an object and if it makes sense to store it in + * the objects status_flags, do so. The method inherited from class basic + * computes a hash value based on the type and hash values of possible + * 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 v=golden_ratio_hash(tinfo()); + unsigned v = golden_ratio_hash(tinfo()); for (unsigned i=0; i(this))->op(i).gethash(); } - - v = v & 0x7FFFFFFFU; + + // 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); - hashvalue=v; + hashvalue = v; } return v; @@ -445,89 +440,86 @@ ex basic::subs(const ex & e) const return subs(ls,lr); } -/** Compare objects to establish canonical order. +/** Compare objects 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(); - + if (hash_thishash_other) return 1; - + unsigned typeid_this = tinfo(); unsigned typeid_other = other.tinfo(); - + if (typeid_thisprintraw(cout); - cout << " and "; - other.printraw(cout); - cout << endl; - */ +// std::cout << "hash collision, different types: " +// << *this << " and " << other << std::endl; +// this->printraw(std::cout); +// std::cout << " and "; +// other.printraw(std::cout); +// std::cout << std::endl; return -1; } if (typeid_this>typeid_other) { - /* - cout << "hash collision, different types: " - << *this << " and " << other << endl; - this->printraw(cout); - cout << " and "; - other.printraw(cout); - cout << endl; - */ +// std::cout << "hash collision, different types: " +// << *this << " and " << other << std::endl; +// this->printraw(std::cout); +// std::cout << " and "; +// other.printraw(std::cout); +// std::cout << std::endl; return 1; } - + GINAC_ASSERT(typeid(*this)==typeid(other)); - - int cmpval=compare_same_type(other); - if ((cmpval!=0)&&(hash_this<0x80000000U)) { - /* - cout << "hash collision, same type: " - << *this << " and " << other << endl; - this->printraw(cout); - cout << " and "; - other.printraw(cout); - cout << endl; - */ + + int cmpval = compare_same_type(other); + if ((cmpval!=0) && (hash_this<0x80000000U)) { +// std::cout << "hash collision, same type: " +// << *this << " and " << other << std::endl; +// this->printraw(std::cout); +// std::cout << " and "; +// other.printraw(std::cout); +// std::cout << std::endl; } return cmpval; } -/** Test for equality. */ +/** Test for 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. + * + * @see is_equal_same_type */ bool basic::is_equal(const basic & other) const { - unsigned hash_this = gethash(); - unsigned hash_other = other.gethash(); - - if (hash_this!=hash_other) return false; - - unsigned typeid_this = tinfo(); - unsigned typeid_other = other.tinfo(); - - if (typeid_this!=typeid_other) return false; - + if (this->gethash()!=other.gethash()) + return false; + if (this->tinfo()!=other.tinfo()) + return false; + GINAC_ASSERT(typeid(*this)==typeid(other)); - - return is_equal_same_type(other); + + return this->is_equal_same_type(other); } // protected /** Stop further evaluation. + * * @see basic::eval */ const basic & basic::hold(void) const { - return setflag(status_flags::evaluated); + return this->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 { - if (refcount>1) + if (this->refcount>1) throw(std::runtime_error("cannot modify multiply referenced object")); } @@ -544,8 +536,6 @@ unsigned basic::delta_indent = 4; // global variables ////////// -int max_recursion_level=1024; +int max_recursion_level = 1024; -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/basic.h b/ginac/basic.h index a75f4c0b..e1325745 100644 --- a/ginac/basic.h +++ b/ginac/basic.h @@ -34,12 +34,10 @@ #include "tinfos.h" #include "assertion.h" #include "registrar.h" +/*#include "debugmsg.h"*/ -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC -class basic; class ex; class symbol; class lst; @@ -50,74 +48,53 @@ class archive_node; // Cint doesn't like vector<..,default_alloc> but malloc_alloc is // unstandardized and not supported by newer GCCs. #if defined(__GNUC__) && ((__GNUC__ == 2) && (__GNUC_MINOR__ < 97)) -typedef std::vector exvector; + typedef std::vector exvector; #else -typedef std::vector exvector; + typedef std::vector exvector; #endif -#define INLINE_BASIC_CONSTRUCTORS - /** This class is the ABC (abstract base class) of GiNaC's class hierarchy. * It is responsible for the reference counting. */ class basic { GINAC_DECLARE_REGISTERED_CLASS_NO_CTORS(basic, void) - + friend class ex; - + // member functions - - // default constructor, destructor, copy constructor assignment operator and helpers + + // default ctor, dtor, copy ctor assignment operator and helpers public: - basic() -#ifdef INLINE_BASIC_CONSTRUCTORS - : tinfo_key(TINFO_basic), flags(0), refcount(0) + basic() : tinfo_key(TINFO_basic), flags(0), refcount(0) { + /* debugmsg("basic default ctor", LOGLEVEL_CONSTRUCT); */ } -#else -; -#endif // def INLINE_BASIC_CONSTRUCTORS - + /** basic dtor, virtual because class ex will delete objects via ptr. */ virtual ~basic() -#ifdef INLINE_BASIC_CONSTRUCTORS { - destroy(0); + /* debugmsg("basic dtor", LOGLEVEL_DESTRUCT); */ + destroy(false); GINAC_ASSERT((!(flags & status_flags::dynallocated))||(refcount==0)); } -#else -; -#endif // def INLINE_BASIC_CONSTRUCTORS - - basic(const basic & other) -#ifdef INLINE_BASIC_CONSTRUCTORS - { - copy(other); - } -#else -; -#endif // def INLINE_BASIC_CONSTRUCTORS - + 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; } - void destroy(bool call_parent) {} - - // other constructors - basic(unsigned ti) -#ifdef INLINE_BASIC_CONSTRUCTORS - : tinfo_key(ti), flags(0), refcount(0) + /** For use by dtor and assignment operator. */ + virtual void destroy(bool call_parent) { } + + // other ctors + /** ctor with specified tinfo_key */ + basic(unsigned ti) : tinfo_key(ti), flags(0), refcount(0) { + /* debugmsg("basic ctor with tinfo_key", LOGLEVEL_CONSTRUCT); */ } -#else -; -#endif // def INLINE_BASIC_CONSTRUCTORS - // functions overriding virtual functions from bases classes // none @@ -159,8 +136,8 @@ protected: // non-const functions should be called from class ex only virtual unsigned return_type(void) const; virtual unsigned return_type_tinfo(void) const; virtual unsigned calchash(void) const; - virtual ex expand(unsigned options=0) const; - + virtual ex expand(unsigned options = 0) const; + // non-virtual functions in this class public: ex subs(const ex & e) const; @@ -168,23 +145,25 @@ public: 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 gethash(void) const { if (flags & status_flags::hash_calculated) return hashvalue; else return calchash(); } unsigned tinfo(void) const {return tinfo_key;} + /** Set some status_flags. */ const basic & setflag(unsigned f) const {flags |= f; return *this;} + /** Clear some status_flags. */ const basic & clearflag(unsigned f) const {flags &= ~f; return *this;} protected: void ensure_if_modifiable(void) const; - + // member variables protected: - unsigned tinfo_key; - mutable unsigned flags; - mutable unsigned hashvalue; - static unsigned precedence; - static unsigned delta_indent; + unsigned tinfo_key; ///< typeinfo + mutable unsigned flags; ///< of type status_flags + mutable unsigned hashvalue; ///< hash value + static unsigned precedence; ///< precedence for printing parens + static unsigned delta_indent; ///< precedence for printtree private: - unsigned refcount; + unsigned refcount; ///< Number of reference counts }; // global variables @@ -193,8 +172,6 @@ extern int max_recursion_level; // convenience macros -#ifndef NO_NAMESPACE_GINAC - /** Check if OBJ is a TYPE, including base classes. */ #define is_of_type(OBJ,TYPE) \ (dynamic_cast(&OBJ)!=0) @@ -211,24 +188,6 @@ extern int max_recursion_level; #define is_ex_exactly_of_type(OBJ,TYPE) \ ((*(OBJ).bp).tinfo()==GiNaC::TINFO_##TYPE) -#else // ndef NO_NAMESPACE_GINAC - -#define is_of_type(OBJ,TYPE) \ - (dynamic_cast(&OBJ)!=0) - -#define is_exactly_of_type(OBJ,TYPE) \ - ((OBJ).tinfo()==TINFO_##TYPE) - -#define is_ex_of_type(OBJ,TYPE) \ - (dynamic_cast((OBJ).bp)!=0) - -#define is_ex_exactly_of_type(OBJ,TYPE) \ - ((*(OBJ).bp).tinfo()==TINFO_##TYPE) - -#endif // ndef NO_NAMESPACE_GINAC - -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_BASIC_H__ diff --git a/ginac/clifford.cpp b/ginac/clifford.cpp index 0dc0518d..a3f26c96 100644 --- a/ginac/clifford.cpp +++ b/ginac/clifford.cpp @@ -30,9 +30,7 @@ #include "utils.h" #include "debugmsg.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC GINAC_IMPLEMENT_REGISTERED_CLASS(clifford, lortensor) @@ -190,6 +188,4 @@ clifford clifford_gamma(const ex & mu) return clifford("gamma", mu); } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/clifford.h b/ginac/clifford.h index aed2b166..86978e98 100644 --- a/ginac/clifford.h +++ b/ginac/clifford.h @@ -26,9 +26,7 @@ #include #include "lortensor.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC /** This class holds an object representing an element of the Clifford @@ -79,8 +77,6 @@ inline const clifford &ex_to_clifford(const ex &e) clifford clifford_gamma(const ex & mu); -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_CLIFFORD_H__ diff --git a/ginac/color.cpp b/ginac/color.cpp index f2360c3d..9e355cb0 100644 --- a/ginac/color.cpp +++ b/ginac/color.cpp @@ -37,9 +37,7 @@ #include "debugmsg.h" #include "utils.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC GINAC_IMPLEMENT_REGISTERED_CLASS(color, indexed) @@ -1033,6 +1031,4 @@ ex brute_force_sum_color_indices(const ex & e) return sum; } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/color.h b/ginac/color.h index 6f126a34..4d4169a7 100644 --- a/ginac/color.h +++ b/ginac/color.h @@ -28,9 +28,7 @@ #include "indexed.h" #include "ex.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC const unsigned MAX_REPRESENTATION_LABELS = 4; const unsigned COLOR_EIGHT = 8; // N*N-1 @@ -163,8 +161,6 @@ ex simplify_color(const ex & e); ex brute_force_sum_color_indices(const ex & e); -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_COLOR_H__ diff --git a/ginac/coloridx.cpp b/ginac/coloridx.cpp index d034ba48..cb8b629e 100644 --- a/ginac/coloridx.cpp +++ b/ginac/coloridx.cpp @@ -27,9 +27,7 @@ #include "utils.h" #include "debugmsg.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC GINAC_IMPLEMENT_REGISTERED_CLASS(coloridx, idx) @@ -212,6 +210,4 @@ int coloridx::compare_same_type(const basic & other) const return inherited::compare_same_type(other); } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/coloridx.h b/ginac/coloridx.h index a727b912..ab78abb3 100644 --- a/ginac/coloridx.h +++ b/ginac/coloridx.h @@ -28,9 +28,7 @@ #include "idx.h" #include "ex.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC /** Class of indices for color algebra objects, to tell them apart from @@ -75,8 +73,6 @@ inline const coloridx &ex_to_coloridx(const ex &e) return static_cast(*e.bp); } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_COLORIDX_H__ diff --git a/ginac/constant.cpp b/ginac/constant.cpp index dcf28374..56f5a851 100644 --- a/ginac/constant.cpp +++ b/ginac/constant.cpp @@ -28,48 +28,47 @@ #include "ex.h" #include "archive.h" #include "debugmsg.h" +#include "utils.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC GINAC_IMPLEMENT_REGISTERED_CLASS(constant, basic) ////////// -// default constructor, destructor, copy constructor assignment operator and helpers +// default ctor, dtor, copy ctor assignment operator and helpers ////////// // public constant::constant() : basic(TINFO_constant), name(""), ef(0), number(0), serial(next_serial++) { - debugmsg("constant default constructor",LOGLEVEL_CONSTRUCT); + debugmsg("constant default ctor",LOGLEVEL_CONSTRUCT); } // protected +/** For use by copy ctor and assignment operator. */ void constant::copy(const constant & other) { - basic::copy(other); - name=other.name; - serial=other.serial; - ef=other.ef; - if (other.number != 0) { + inherited::copy(other); + name = other.name; + serial = other.serial; + ef = other.ef; + if (other.number != 0) number = new numeric(*other.number); - } else { + else number = 0; - } } void constant::destroy(bool call_parent) { delete number; if (call_parent) - basic::destroy(call_parent); + inherited::destroy(call_parent); } ////////// -// other constructors +// other ctors ////////// // public @@ -77,13 +76,15 @@ void constant::destroy(bool call_parent) constant::constant(const std::string & initname, evalffunctype efun) : basic(TINFO_constant), name(initname), ef(efun), number(0), serial(next_serial++) { - debugmsg("constant constructor from string, function",LOGLEVEL_CONSTRUCT); + debugmsg("constant ctor from string, function",LOGLEVEL_CONSTRUCT); + setflag(status_flags::evaluated); } constant::constant(const std::string & initname, const numeric & initnumber) : basic(TINFO_constant), name(initname), ef(0), number(new numeric(initnumber)), serial(next_serial++) { - debugmsg("constant constructor from string, numeric",LOGLEVEL_CONSTRUCT); + debugmsg("constant ctor from string, numeric",LOGLEVEL_CONSTRUCT); + setflag(status_flags::evaluated); } ////////// @@ -93,7 +94,7 @@ constant::constant(const std::string & initname, const numeric & initnumber) /** Construct object from archive_node. */ constant::constant(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) { - debugmsg("constant constructor from archive_node", LOGLEVEL_CONSTRUCT); + debugmsg("constant ctor from archive_node", LOGLEVEL_CONSTRUCT); } /** Unarchive the object. */ @@ -161,7 +162,7 @@ ex constant::evalf(int level) const if (ef!=0) { return ef(); } else if (number != 0) { - return *number; + return number->evalf(); } return *this; } @@ -193,6 +194,17 @@ bool constant::is_equal_same_type(const basic & other) const return serial==o->serial; } +unsigned constant::calchash(void) const +{ + hashvalue = golden_ratio_hash(tinfo() ^ serial); + // mask out numeric hashes: + hashvalue &= 0x7FFFFFFFU; + + setflag(status_flags::hash_calculated); + + return hashvalue; +} + ////////// // new virtual functions which can be overridden by derived classes ////////// @@ -209,7 +221,7 @@ bool constant::is_equal_same_type(const basic & other) const // static member variables ////////// -unsigned constant::next_serial=0; +unsigned constant::next_serial = 0; ////////// // global constants @@ -225,6 +237,4 @@ const constant Euler("Euler", EulerEvalf); /** Catalan's constant. (0.91597...) Diverts straight into CLN for evalf(). */ const constant Catalan("Catalan", CatalanEvalf); -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/constant.h b/ginac/constant.h index f29e5462..b30fc262 100644 --- a/ginac/constant.h +++ b/ginac/constant.h @@ -25,10 +25,9 @@ #include #include "basic.h" +#include "ex.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC typedef ex (*evalffunctype)(void); @@ -39,38 +38,39 @@ typedef ex (*evalffunctype)(void); class constant : public basic { GINAC_DECLARE_REGISTERED_CLASS(constant, basic) - + // member functions - - // other constructors + + // other ctors public: - constant(const std::string & initname, evalffunctype efun=0); + constant(const std::string & initname, evalffunctype efun = 0); constant(const std::string & initname, const numeric & initnumber); - + // functions overriding virtual functions from bases classes public: - void print(std::ostream & os, unsigned upper_precedence=0) const; + void print(std::ostream & os, unsigned upper_precedence = 0) const; void printraw(std::ostream & os) const; void printtree(std::ostream & os, unsigned indent) const; - void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence=0) const; - ex evalf(int level=0) const; + void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence = 0) const; + ex evalf(int level = 0) const; protected: ex derivative(const symbol & s) const; bool is_equal_same_type(const basic & other) const; + unsigned calchash(void) const; // new virtual functions which can be overridden by derived classes // none - + // non-virtual functions in this class // none - + // member variables - + private: - std::string name; + std::string name; ///< printname of this constant evalffunctype ef; - numeric * number; - unsigned serial; //! unique serial number for comparision + numeric *number; ///< numerical value this constant evalf()s to + unsigned serial; ///< unique serial number for comparison static unsigned next_serial; }; @@ -78,8 +78,12 @@ extern const constant Pi; extern const constant Catalan; extern const constant Euler; -#ifndef NO_NAMESPACE_GINAC +// utility functions +inline const constant &ex_to_constant(const ex &e) +{ + return static_cast(*e.bp); +} + } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_CONSTANT_H__ diff --git a/ginac/container.pl b/ginac/container.pl index d2c5bb44..80fb9fac 100755 --- a/ginac/container.pl +++ b/ginac/container.pl @@ -132,7 +132,7 @@ $constructors_implementation=generate( <<'END_OF_CONSTRUCTORS_IMPLEMENTATION','const ex & param${N}',', ',' seq.push_back(param${N});',"\n"); ${CONTAINER}::${CONTAINER}(${SEQ1}) : basic(TINFO_${CONTAINER}) { - debugmsg(\"${CONTAINER} constructor from ${N}*ex\",LOGLEVEL_CONSTRUCT); + debugmsg(\"${CONTAINER} ctor from ${N}*ex\",LOGLEVEL_CONSTRUCT); RESERVE(seq,${N}); ${SEQ2} } @@ -183,9 +183,7 @@ $interface=< but malloc_alloc is @@ -263,9 +261,7 @@ inline ${CONTAINER} &ex_to_nonconst_${CONTAINER}(const ex &e) return static_cast<${CONTAINER} &>(*e.bp); } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_${CONTAINER_UC}_H__ @@ -313,23 +309,21 @@ $implementation=<(s)); } else { @@ -364,7 +358,7 @@ ${CONTAINER}::${CONTAINER}(${STLT} const & s, bool discardable) : basic(TINFO_$ ${CONTAINER}::${CONTAINER}(${STLT} * vp) : basic(TINFO_${CONTAINER}) { - debugmsg("${CONTAINER} constructor from ${STLT} *",LOGLEVEL_CONSTRUCT); + debugmsg("${CONTAINER} ctor from ${STLT} *",LOGLEVEL_CONSTRUCT); GINAC_ASSERT(vp!=0); seq.swap(*vp); delete vp; @@ -379,7 +373,7 @@ ${constructors_implementation} /** Construct object from archive_node. */ ${CONTAINER}::${CONTAINER}(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) { - debugmsg("${CONTAINER} constructor from archive_node", LOGLEVEL_CONSTRUCT); + debugmsg("${CONTAINER} ctor from archive_node", LOGLEVEL_CONSTRUCT); for (unsigned int i=0; true; i++) { ex e; if (n.find_ex("seq", e, sym_lst, i)) @@ -753,7 +747,7 @@ ${STLT} * ${CONTAINER}::subschildren(const lst & ls, const lst & lr) const // protected -unsigned ${CONTAINER}::precedence=10; +unsigned ${CONTAINER}::precedence = 10; ////////// // global constants @@ -762,9 +756,7 @@ unsigned ${CONTAINER}::precedence=10; const ${CONTAINER} some_${CONTAINER}; const std::type_info & typeid_${CONTAINER} = typeid(some_${CONTAINER}); -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC END_OF_IMPLEMENTATION diff --git a/ginac/debugmsg.h b/ginac/debugmsg.h index 91ea0796..08457b5a 100644 --- a/ginac/debugmsg.h +++ b/ginac/debugmsg.h @@ -44,7 +44,7 @@ // #define LOGMASK (LOGLEVEL_PRINT | LOGLEVEL_ASSIGNMENT | LOGLEVEL_OPERATOR | LOGLEVEL_DUPLICATE | LOGLEVEL_OPERATOR | LOGLEVEL_MEMBER_FUNCTION | LOGLEVEL_NONMEMBER_FUNCTION) #ifdef VERBOSE -#define debugmsg(msg, loglevel) if ((loglevel) & ~LOGMASK) std::clog << (msg) << endl; +#define debugmsg(msg, loglevel) if ((loglevel) & ~LOGMASK) std::clog << (msg) << std::endl; #else #define debugmsg(msg, loglevel) #endif // def VERBOSE diff --git a/ginac/ex.cpp b/ginac/ex.cpp index 1fb016c3..6acde9f9 100644 --- a/ginac/ex.cpp +++ b/ginac/ex.cpp @@ -23,7 +23,14 @@ #include #include -#include "ex.h" +#if defined(VERBOSE) +# define GINAC_CONDITIONAL_INLINE +# include "ex.h" +# undef GINAC_CONDITIONAL_INLINE +#else +# include "ex.h" +#endif + #include "add.h" #include "mul.h" #include "ncmul.h" @@ -34,113 +41,13 @@ #include "debugmsg.h" #include "utils.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC ////////// -// default constructor, destructor, copy constructor assignment operator and helpers +// other ctors ////////// -// public - -#ifndef INLINE_EX_CONSTRUCTORS - -ex::ex() : bp(_ex0().bp) -{ - debugmsg("ex default constructor",LOGLEVEL_CONSTRUCT); - GINAC_ASSERT(_ex0().bp!=0); - GINAC_ASSERT(_ex0().bp->flags & status_flags::dynallocated); - GINAC_ASSERT(bp!=0); - ++bp->refcount; -} - -ex::~ex() -{ - debugmsg("ex destructor",LOGLEVEL_DESTRUCT); - GINAC_ASSERT(bp!=0); - GINAC_ASSERT(bp->flags & status_flags::dynallocated); - if (--bp->refcount == 0) { - delete bp; - } -} - -ex::ex(const ex & other) : bp(other.bp) -{ - debugmsg("ex copy constructor",LOGLEVEL_CONSTRUCT); - GINAC_ASSERT(bp!=0); - GINAC_ASSERT((bp->flags) & status_flags::dynallocated); - ++bp->refcount; -} - -const ex & ex::operator=(const ex & other) -{ - debugmsg("ex operator=",LOGLEVEL_ASSIGNMENT); - GINAC_ASSERT(bp!=0); - GINAC_ASSERT(bp->flags & status_flags::dynallocated); - GINAC_ASSERT(other.bp!=0); - GINAC_ASSERT(other.bp->flags & status_flags::dynallocated); - ++other.bp->refcount; - basic * tmpbp = other.bp; - if (--bp->refcount==0) - delete bp; - bp = tmpbp; - return *this; -} - -#endif // ndef INLINE_EX_CONSTRUCTORS - -////////// -// other constructors -////////// - -// public - -#ifndef INLINE_EX_CONSTRUCTORS - -ex::ex(const basic & other) -{ - debugmsg("ex constructor from basic",LOGLEVEL_CONSTRUCT); - construct_from_basic(other); -} - -ex::ex(int i) -{ - debugmsg("ex constructor from int",LOGLEVEL_CONSTRUCT); - construct_from_int(i); -} - -ex::ex(unsigned int i) -{ - debugmsg("ex constructor from unsigned int",LOGLEVEL_CONSTRUCT); - construct_from_uint(i); -} - -ex::ex(long i) -{ - debugmsg("ex constructor from long",LOGLEVEL_CONSTRUCT); - construct_from_long(i); -} - -ex::ex(unsigned long i) -{ - debugmsg("ex constructor from unsigned long",LOGLEVEL_CONSTRUCT); - construct_from_ulong(i); -} - -ex::ex(double const d) -{ - debugmsg("ex constructor from double",LOGLEVEL_CONSTRUCT); - construct_from_double(d); -} - -ex::ex(const std::string &s, const ex &l) -{ - debugmsg("ex constructor from string,lst",LOGLEVEL_CONSTRUCT); - construct_from_string_and_lst(s, l); -} - -#endif // ndef INLINE_EX_CONSTRUCTORS +// none (all inlined) ////////// // functions overriding virtual functions from bases classes @@ -160,7 +67,7 @@ ex::ex(const std::string &s, const ex &l) // public -/** Swap the contents of two expressions. */ +/** Efficiently swap the contents of two expressions. */ void ex::swap(ex & other) { debugmsg("ex swap",LOGLEVEL_MEMBER_FUNCTION); @@ -170,9 +77,9 @@ void ex::swap(ex & other) GINAC_ASSERT(other.bp!=0); GINAC_ASSERT(other.bp->flags & status_flags::dynallocated); - basic * tmpbp=bp; - bp=other.bp; - other.bp=tmpbp; + basic * tmpbp = bp; + bp = other.bp; + other.bp = tmpbp; } /** Output formatted to be useful as ginsh input. */ @@ -183,6 +90,7 @@ void ex::print(std::ostream & os, unsigned upper_precedence) const bp->print(os,upper_precedence); } +/** Unreadable output with detailed type information. */ void ex::printraw(std::ostream & os) const { debugmsg("ex printraw",LOGLEVEL_PRINT); @@ -192,6 +100,7 @@ void ex::printraw(std::ostream & os) const os << ")"; } +/** Very detailed and unreadable output with type information and all this. */ void ex::printtree(std::ostream & os, unsigned indent) const { debugmsg("ex printtree",LOGLEVEL_PRINT); @@ -391,32 +300,6 @@ ex ex::rhs(void) const return (*static_cast(bp)).rhs(); } -#ifndef INLINE_EX_CONSTRUCTORS -int ex::compare(const ex & other) const -{ - GINAC_ASSERT(bp!=0); - GINAC_ASSERT(other.bp!=0); - if (bp==other.bp) { - // special case: both expression point to same basic, trivially equal - return 0; - } - return bp->compare(*other.bp); -} -#endif // ndef INLINE_EX_CONSTRUCTORS - -#ifndef INLINE_EX_CONSTRUCTORS -bool ex::is_equal(const ex & other) const -{ - GINAC_ASSERT(bp!=0); - GINAC_ASSERT(other.bp!=0); - // if both expression point to same basic they are trivially equal - if (bp==other.bp) - return true; - - return bp->is_equal(*other.bp); -} -#endif // ndef INLINE_EX_CONSTRUCTORS - unsigned ex::return_type(void) const { GINAC_ASSERT(bp!=0); @@ -452,6 +335,8 @@ ex ex::exncmul(const ex & rh) const // private +/** Make this ex writable (if more than one ex handle the same basic) by + * unlinking the object and creating an unshared copy of it. */ void ex::makewriteable() { debugmsg("ex makewriteable",LOGLEVEL_MEMBER_FUNCTION); @@ -467,21 +352,22 @@ void ex::makewriteable() GINAC_ASSERT(bp->refcount==1); } +/** Ctor from basic implementation. + * @see ex::ex(const basic &) */ void ex::construct_from_basic(const basic & other) { if ((other.flags & status_flags::evaluated)==0) { - // cf. copy constructor + // cf. copy ctor const ex & tmpex = other.eval(1); // evaluate only one (top) level bp = tmpex.bp; GINAC_ASSERT(bp!=0); GINAC_ASSERT(bp->flags & status_flags::dynallocated); ++bp->refcount; - if ((other.flags & status_flags::dynallocated)&&(other.refcount==0)) { + if ((other.flags & status_flags::dynallocated)&&(other.refcount==0)) delete &const_cast(other); - } } else { if (other.flags & status_flags::dynallocated) { - // it's on the heap, so just copy bp: + // ok, it is already on the heap, so just copy bp: bp = &const_cast(other); } else { // create a duplicate on the heap: @@ -651,6 +537,4 @@ void ex::construct_from_string_and_lst(const std::string &s, const ex &l) // none -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/ex.h b/ginac/ex.h index 30b40eb5..0e2adaf0 100644 --- a/ginac/ex.h +++ b/ginac/ex.h @@ -23,23 +23,18 @@ #ifndef __GINAC_EX_H__ #define __GINAC_EX_H__ -#include #include "basic.h" #include "operators.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC - -class ex; -class symbol; -class lst; // Sorry, this is the only constant to pollute the global scope, the other ones // are defined in utils.h and not visible from outside. -extern const ex & _ex0(void); // single ex(numeric(0)) +class ex; +extern const ex & _ex0(void); ///< single ex(numeric(0)) -#define INLINE_EX_CONSTRUCTORS +class symbol; +class lst; /** Lightweight wrapper for GiNaC's symbolic objects. Basically all it does is * to hold a pointer to the other objects, manage the reference counting and @@ -47,168 +42,28 @@ extern const ex & _ex0(void); // single ex(numeric(0)) class ex { friend class basic; - + // member functions - - // default constructor, destructor, copy constructor assignment operator and helpers + + // default ctor, dtor, copy ctor assignment operator and helpers public: - ex() -#ifdef INLINE_EX_CONSTRUCTORS - : bp(_ex0().bp) - { - GINAC_ASSERT(_ex0().bp!=0); - GINAC_ASSERT(_ex0().bp->flags & status_flags::dynallocated); - GINAC_ASSERT(bp!=0); - ++bp->refcount; -#ifdef OBSCURE_CINT_HACK - update_last_created_or_assigned_bp(); -#endif // def OBSCURE_CINT_HACK - } -#else -; -#endif // def INLINE_EX_CONSTRUCTORS - - ~ex() -#ifdef INLINE_EX_CONSTRUCTORS - { - GINAC_ASSERT(bp!=0); - GINAC_ASSERT(bp->flags & status_flags::dynallocated); - if (--bp->refcount == 0) { - delete bp; - } - } -#else -; -#endif // def INLINE_EX_CONSTRUCTORS - - ex(const ex & other) -#ifdef INLINE_EX_CONSTRUCTORS - : bp(other.bp) - { - GINAC_ASSERT(bp!=0); - GINAC_ASSERT((bp->flags) & status_flags::dynallocated); - ++bp->refcount; -#ifdef OBSCURE_CINT_HACK - update_last_created_or_assigned_bp(); -#endif // def OBSCURE_CINT_HACK - } -#else -; -#endif // def INLINE_EX_CONSTRUCTORS - - const ex & operator=(const ex & other) -#ifdef INLINE_EX_CONSTRUCTORS - { - GINAC_ASSERT(bp!=0); - GINAC_ASSERT(bp->flags & status_flags::dynallocated); - GINAC_ASSERT(other.bp!=0); - GINAC_ASSERT(other.bp->flags & status_flags::dynallocated); - ++other.bp->refcount; - basic * tmpbp=other.bp; - if (--bp->refcount==0) { - delete bp; - } - bp=tmpbp; -#ifdef OBSCURE_CINT_HACK - update_last_created_or_assigned_bp(); -#endif // def OBSCURE_CINT_HACK - return *this; - } -#else -; -#endif // def INLINE_EX_CONSTRUCTORS - - - // other constructors + ex(); + ~ex(); + ex(const ex & other); + const ex & operator=(const ex & other); + // other ctors public: - ex(const basic & other) -#ifdef INLINE_EX_CONSTRUCTORS - { - construct_from_basic(other); -#ifdef OBSCURE_CINT_HACK - update_last_created_or_assigned_bp(); -#endif // def OBSCURE_CINT_HACK - } -#else -; -#endif // def INLINE_EX_CONSTRUCTORS - - ex(int i) -#ifdef INLINE_EX_CONSTRUCTORS - { - construct_from_int(i); -#ifdef OBSCURE_CINT_HACK - update_last_created_or_assigned_bp(); -#endif // def OBSCURE_CINT_HACK - } -#else -; -#endif // def INLINE_EX_CONSTRUCTORS - - ex(unsigned int i) -#ifdef INLINE_EX_CONSTRUCTORS - { - construct_from_uint(i); -#ifdef OBSCURE_CINT_HACK - update_last_created_or_assigned_bp(); -#endif // def OBSCURE_CINT_HACK - } -#else -; -#endif // def INLINE_EX_CONSTRUCTORS - - ex(long i) -#ifdef INLINE_EX_CONSTRUCTORS - { - construct_from_long(i); -#ifdef OBSCURE_CINT_HACK - update_last_created_or_assigned_bp(); -#endif // def OBSCURE_CINT_HACK - } -#else -; -#endif // def INLINE_EX_CONSTRUCTORS - - ex(unsigned long i) -#ifdef INLINE_EX_CONSTRUCTORS - { - construct_from_ulong(i); -#ifdef OBSCURE_CINT_HACK - update_last_created_or_assigned_bp(); -#endif // def OBSCURE_CINT_HACK - } -#else -; -#endif // def INLINE_EX_CONSTRUCTORS - - ex(double const d) -#ifdef INLINE_EX_CONSTRUCTORS - { - construct_from_double(d); -#ifdef OBSCURE_CINT_HACK - update_last_created_or_assigned_bp(); -#endif // def OBSCURE_CINT_HACK - } -#else -; -#endif // def INLINE_EX_CONSTRUCTORS - + ex(const basic & other); + ex(int i); + ex(unsigned int i); + ex(long i); + ex(unsigned long i); + ex(double const d); /** Construct ex from string and a list of symbols. The input grammar is * similar to the GiNaC output format. All symbols to be used in the * expression must be specified in a lst in the second argument. Undefined * symbols and other parser errors will throw an exception. */ - ex(const std::string &s, const ex &l) -#ifdef INLINE_EX_CONSTRUCTORS - { - construct_from_string_and_lst(s, l); -#ifdef OBSCURE_CINT_HACK - update_last_created_or_assigned_bp(); -#endif // def OBSCURE_CINT_HACK - } -#else -; -#endif // def INLINE_EX_CONSTRUCTORS - + ex(const std::string &s, const ex &l); // functions overriding virtual functions from bases classes // none @@ -260,40 +115,14 @@ public: ex & let_op(int i); ex lhs(void) const; ex rhs(void) const; - int compare(const ex & other) const -#ifdef INLINE_EX_CONSTRUCTORS - { - GINAC_ASSERT(bp!=0); - GINAC_ASSERT(other.bp!=0); - if (bp==other.bp) { - // special case: both expression point to same basic, trivially equal - return 0; - } - return bp->compare(*other.bp); - } -#else -; -#endif // def INLINE_EX_CONSTRUCTORS - bool is_equal(const ex & other) const -#ifdef INLINE_EX_CONSTRUCTORS - { - GINAC_ASSERT(bp!=0); - GINAC_ASSERT(other.bp!=0); - if (bp==other.bp) { - // special case: both expression point to same basic, trivially equal - return true; - } - return bp->is_equal(*other.bp); - } -#else -; -#endif // def INLINE_EX_CONSTRUCTORS - bool is_zero(void) const {return compare(_ex0())==0;}; - + int compare(const ex & other) const; + bool is_equal(const ex & other) const; + bool is_zero(void) const { return is_equal(_ex0()); } + unsigned return_type(void) const; unsigned return_type_tinfo(void) const; unsigned gethash(void) const; - + ex exadd(const ex & rh) const; ex exmul(const ex & rh) const; ex exncmul(const ex & rh) const; @@ -326,16 +155,16 @@ protected: delete last_created_or_assigned_bp; } } - last_created_or_assigned_bp=bp; + last_created_or_assigned_bp = bp; ++last_created_or_assigned_bp->refcount; - last_created_or_assigned_exp=(long)(void *)(this); + last_created_or_assigned_exp = (long)(void *)(this); } #endif // def OBSCURE_CINT_HACK // member variables public: - basic *bp; + basic *bp; ///< pointer to basic object managed by this #ifdef OBSCURE_CINT_HACK static basic * last_created_or_assigned_bp; static basic * dummy_bp; @@ -343,6 +172,153 @@ public: #endif // def OBSCURE_CINT_HACK }; + +// performance-critical inlined method implementations + +inline +ex::ex() : bp(_ex0().bp) +{ + /*debugmsg("ex default ctor",LOGLEVEL_CONSTRUCT);*/ + GINAC_ASSERT(_ex0().bp!=0); + GINAC_ASSERT(_ex0().bp->flags & status_flags::dynallocated); + GINAC_ASSERT(bp!=0); + ++bp->refcount; +#ifdef OBSCURE_CINT_HACK + update_last_created_or_assigned_bp(); +#endif // def OBSCURE_CINT_HACK +} + +inline +ex::~ex() +{ + /*debugmsg("ex dtor",LOGLEVEL_DESTRUCT);*/ + GINAC_ASSERT(bp!=0); + GINAC_ASSERT(bp->flags & status_flags::dynallocated); + if (--bp->refcount == 0) + delete bp; +} + +inline +ex::ex(const ex & other) : bp(other.bp) +{ + /*debugmsg("ex copy ctor",LOGLEVEL_CONSTRUCT);*/ + GINAC_ASSERT(bp!=0); + GINAC_ASSERT((bp->flags) & status_flags::dynallocated); + ++bp->refcount; +#ifdef OBSCURE_CINT_HACK + update_last_created_or_assigned_bp(); +#endif // def OBSCURE_CINT_HACK +} + +inline +const ex & ex::operator=(const ex & other) +{ + /*debugmsg("ex operator=",LOGLEVEL_ASSIGNMENT);*/ + GINAC_ASSERT(bp!=0); + GINAC_ASSERT(bp->flags & status_flags::dynallocated); + GINAC_ASSERT(other.bp!=0); + GINAC_ASSERT(other.bp->flags & status_flags::dynallocated); + if (--bp->refcount==0) + delete bp; + ++other.bp->refcount; + bp = other.bp; +#ifdef OBSCURE_CINT_HACK + update_last_created_or_assigned_bp(); +#endif // def OBSCURE_CINT_HACK + return *this; +} + +inline +ex::ex(const basic & other) +{ + /*debugmsg("ex ctor from basic",LOGLEVEL_CONSTRUCT);*/ + construct_from_basic(other); +#ifdef OBSCURE_CINT_HACK + update_last_created_or_assigned_bp(); +#endif // def OBSCURE_CINT_HACK +} + +inline +ex::ex(int i) +{ + /*debugmsg("ex ctor from int",LOGLEVEL_CONSTRUCT);*/ + construct_from_int(i); +#ifdef OBSCURE_CINT_HACK + update_last_created_or_assigned_bp(); +#endif // def OBSCURE_CINT_HACK +} + +inline +ex::ex(unsigned int i) +{ + /*debugmsg("ex ctor from unsigned int",LOGLEVEL_CONSTRUCT);*/ + construct_from_uint(i); +#ifdef OBSCURE_CINT_HACK + update_last_created_or_assigned_bp(); +#endif // def OBSCURE_CINT_HACK +} + +inline +ex::ex(long i) +{ + /*debugmsg("ex ctor from long",LOGLEVEL_CONSTRUCT);*/ + construct_from_long(i); +#ifdef OBSCURE_CINT_HACK + update_last_created_or_assigned_bp(); +#endif // def OBSCURE_CINT_HACK +} + +inline +ex::ex(unsigned long i) +{ + /*debugmsg("ex ctor from unsigned long",LOGLEVEL_CONSTRUCT);*/ + construct_from_ulong(i); +#ifdef OBSCURE_CINT_HACK + update_last_created_or_assigned_bp(); +#endif // def OBSCURE_CINT_HACK +} + +inline +ex::ex(double const d) +{ + /*debugmsg("ex ctor from double",LOGLEVEL_CONSTRUCT);*/ + construct_from_double(d); +#ifdef OBSCURE_CINT_HACK + update_last_created_or_assigned_bp(); +#endif // def OBSCURE_CINT_HACK +} + +inline +ex::ex(const std::string &s, const ex &l) +{ + /*debugmsg("ex ctor from string,lst",LOGLEVEL_CONSTRUCT);*/ + construct_from_string_and_lst(s, l); +#ifdef OBSCURE_CINT_HACK + update_last_created_or_assigned_bp(); +#endif // def OBSCURE_CINT_HACK +} + +inline +int ex::compare(const ex & other) const +{ + GINAC_ASSERT(bp!=0); + GINAC_ASSERT(other.bp!=0); + if (bp==other.bp) // trivial case: both expressions point to same basic + return 0; + return bp->compare(*other.bp); +} + +inline +bool ex::is_equal(const ex & other) const +{ + GINAC_ASSERT(bp!=0); + GINAC_ASSERT(other.bp!=0); + if (bp==other.bp) // trivial case: both expressions point to same basic + return true; + return bp->is_equal(*other.bp); +} + + // utility functions inline bool are_ex_trivially_equal(const ex &e1, const ex &e2) { @@ -416,9 +392,6 @@ inline bool is_zero(const ex & thisex) inline void swap(ex & e1, ex & e2) { e1.swap(e2); } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_EX_H__ - diff --git a/ginac/expair.h b/ginac/expair.h index 30562cdb..2f34b4b8 100644 --- a/ginac/expair.h +++ b/ginac/expair.h @@ -26,153 +26,62 @@ #include "ex.h" #include "numeric.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC /** A pair of expressions. - * This similar to, but slightly extended STL's pair<> but we need to account - * for methods like .compare() */ + * This is similar to STL's pair<>. It is slightly extended since we need to + * account for methods like .compare(). Also, since this is meant for use by + * class expairseq it must satisfy the invariance that the member coeff must + * be of type numeric. */ class expair { public: - expair() {} - ~expair() {} - + expair() : rest(0), coeff(1) { } + ~expair() { } expair(const expair & other) : rest(other.rest), coeff(other.coeff) { GINAC_ASSERT(is_ex_exactly_of_type(coeff,numeric)); } - const expair & operator=(const expair & other) { if (this != &other) { - rest=other.rest; - coeff=other.coeff; + rest = other.rest; + coeff = other.coeff; } return *this; } - + + /** Construct an expair from two ex. */ expair(const ex & r, const ex & c) : rest(r), coeff(c) { GINAC_ASSERT(is_ex_exactly_of_type(coeff,numeric)); } - bool is_numeric_with_coeff_1(void) const - { - GINAC_ASSERT(is_ex_exactly_of_type(coeff,numeric)); - return is_ex_exactly_of_type(rest,numeric) - && (coeff.is_equal(ex(1))); - } - + /** Member-wise check for canonical ordering equality. */ bool is_equal(const expair & other) const { return (rest.is_equal(other.rest) && coeff.is_equal(other.coeff)); } - + + /** Member-wise check for canonical ordering lessness. */ bool is_less(const expair & other) const { - return (rest.compare(other.rest)<0) - || (!(other.rest.compare(rest)<0) && (coeff.compare(other.coeff)<0)); + int restcmp = rest.compare(other.rest); + return ((restcmp<0) || + (!(restcmp>0) && (coeff.compare(other.coeff)<0))); } - + + /** Member-wise check for canonical ordering. */ int compare(const expair & other) const { - int cmpval=rest.compare(other.rest); - if (cmpval!=0) return cmpval; - cmpval=coeff.compare(other.coeff); - return cmpval; - } - - bool is_less_old2(const expair & other) const - { - /* - bool this_numeric_with_coeff_1=is_numeric_with_coeff_1(); - bool other_numeric_with_coeff_1=other.is_numeric_with_coeff_1(); - if (this_numeric_with_coeff_1) { - if (other_numeric_with_coeff_1) { - // both have coeff 1: compare rests - return rest.compare(other.rest)<0; - } - // only this has coeff 1: > - return false; - } else if (other_numeric_with_coeff_1) { - // only other has coeff 1: < - return true; - } - return (rest.compare(other.rest)<0) - || (!(other.rest.compare(rest)<0) && (coeff.compare(other.coeff)<0)); - */ - if (is_ex_exactly_of_type(rest,numeric) && - is_ex_exactly_of_type(other.rest,numeric)) { - if (coeff.is_equal(ex(1))) { - if ((other.coeff).is_equal(ex(1))) { - // both have coeff 1: compare rests - return rest.compare(other.rest)<0; - } - // only this has coeff 1: > - return false; - } else if ((other.coeff).is_equal(ex(1))) { - // only other has coeff 1: < - return true; - } - // neither has coeff 1: usual compare - } - return (rest.compare(other.rest)<0) - || (!(other.rest.compare(rest)<0) && (coeff.compare(other.coeff)<0)); + int restcmp = rest.compare(other.rest); + if (restcmp!=0) + return restcmp; + else + return coeff.compare(other.coeff); } - - int compare_old2(const expair & other) const - { - if (is_ex_exactly_of_type(rest,numeric) && - is_ex_exactly_of_type(other.rest,numeric)) { - if ((coeff).is_equal(ex(1))) { - if ((other.coeff).is_equal(ex(1))) { - // both have coeff 1: compare rests - return rest.compare(other.rest); - } - // only this has coeff 1: > - return 1; - } else if ((other.coeff).is_equal(ex(1))) { - // only other has coeff 1: < - return -1; - } - // neither has coeff 1: usual compare - } - /* - bool this_numeric_with_coeff_1=is_numeric_with_coeff_1(); - bool other_numeric_with_coeff_1=other.is_numeric_with_coeff_1(); - if (this_numeric_with_coeff_1) { - if (other_numeric_with_coeff_1) { - // both have coeff 1: compare rests - return rest.compare(other.rest); - } - // only this has coeff 1: > - return 1; - } else if (other_numeric_with_coeff_1) { - // only other has coeff 1: < - return -1; - // neither has coeff 1: usual compare - } - */ - int cmpval=rest.compare(other.rest); - if (cmpval!=0) return cmpval; - return coeff.compare(other.coeff); - } - - bool is_less_old(const expair & other) const - { - return (rest.compare(other.rest)<0) - || (!(other.rest.compare(rest)<0) && (coeff.compare(other.coeff)<0)); - } - int compare_old(const expair & other) const - { - int cmpval=rest.compare(other.rest); - if (cmpval!=0) return cmpval; - cmpval=coeff.compare(other.coeff); - return cmpval; - } - + + /** Output to ostream in ugly raw format. */ void printraw(std::ostream & os) const { os << "expair("; @@ -181,31 +90,29 @@ public: coeff.printraw(os); os << ")"; } - - ex rest; - ex coeff; -}; - -class expair_is_less -{ -public: - bool operator()(const expair & lh, const expair & rh) const + + /** True if this is of the form (numeric,ex(1)). */ + bool is_canonical_numeric(void) const { - return lh.is_less(rh); + GINAC_ASSERT(is_ex_exactly_of_type(coeff,numeric)); + return (is_ex_exactly_of_type(rest,numeric) && + (coeff.is_equal(1))); } + + ex rest; ///< first member of pair, an arbitrary expression + ex coeff; ///< second member of pair, must be numeric }; -class expair_is_less_old +/** Function object for insertion into third argument of STL's sort() etc. */ +class expair_is_less { public: - bool operator()(const expair & lh, const expair & rh) const + bool operator()(const expair &lh, const expair &rh) const { - return lh.is_less_old(rh); + return lh.is_less(rh); } }; -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_EXPAIR_H__ diff --git a/ginac/expairseq.cpp b/ginac/expairseq.cpp index 246424f7..3e84134b 100644 --- a/ginac/expairseq.cpp +++ b/ginac/expairseq.cpp @@ -30,13 +30,11 @@ #include "debugmsg.h" #include "utils.h" -#ifndef NO_NAMESPACE_GINAC -namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC +#if EXPAIRSEQ_USE_HASHTAB +#include +#endif // EXPAIRSEQ_USE_HASHTAB -#ifdef EXPAIRSEQ_USE_HASHTAB -#error "FIXME: expair_needs_further_processing not yet implemented for hashtabs, sorry. A.F." -#endif // def EXPAIRSEQ_USE_HASHTAB +namespace GiNaC { GINAC_IMPLEMENT_REGISTERED_CLASS_NO_CTORS(expairseq, basic) @@ -47,25 +45,25 @@ GINAC_IMPLEMENT_REGISTERED_CLASS_NO_CTORS(expairseq, basic) class epp_is_less { public: - bool operator()(const epp & lh, const epp & rh) const + bool operator()(const epp &lh, const epp &rh) const { return (*lh).is_less(*rh); } }; ////////// -// default constructor, destructor, copy constructor assignment operator and helpers +// default ctor, dtor, copy ctor assignment operator and helpers ////////// // public -expairseq::expairseq(const expairseq & other) +expairseq::expairseq(const expairseq &other) { - debugmsg("expairseq copy constructor",LOGLEVEL_CONSTRUCT); + debugmsg("expairseq copy ctor",LOGLEVEL_CONSTRUCT); copy(other); } -const expairseq & expairseq::operator=(const expairseq & other) +const expairseq &expairseq::operator=(const expairseq &other) { debugmsg("expairseq operator=",LOGLEVEL_ASSIGNMENT); if (this != &other) { @@ -77,18 +75,19 @@ const expairseq & expairseq::operator=(const expairseq & other) // protected -void expairseq::copy(const expairseq & other) +/** For use by copy ctor and assignment operator. */ +void expairseq::copy(const expairseq &other) { inherited::copy(other); - seq=other.seq; - overall_coeff=other.overall_coeff; -#ifdef EXPAIRSEQ_USE_HASHTAB + seq = other.seq; + overall_coeff = other.overall_coeff; +#if EXPAIRSEQ_USE_HASHTAB // copy hashtab - hashtabsize=other.hashtabsize; + hashtabsize = other.hashtabsize; if (hashtabsize!=0) { - hashmask=other.hashmask; + hashmask = other.hashmask; hashtab.resize(hashtabsize); - epvector::const_iterator osb=other.seq.begin(); + epvector::const_iterator osb = other.seq.begin(); for (unsigned i=0; i0) { os << std::string(indent+delta_indent,' ') << "bin " << i << " with entries "; for (epplist::const_iterator it=hashtab[i].begin(); - it!=hashtab[i].end(); ++it) { + it!=hashtab[i].end(); ++it) { os << *it-seq.begin() << " "; ++this_bin_fill; } @@ -277,18 +265,18 @@ void expairseq::printtree(std::ostream & os, unsigned indent) const cum_fill += this_bin_fill; cum_fill_sq += this_bin_fill*this_bin_fill; } - if (this_bin_fill0) fact *= k; - double prob = pow(lambda,k)/fact*exp(-lambda); + if (k>0) + fact *= k; + double prob = std::pow(lambda,k)/fact * std::exp(-lambda); cum_prob += prob; os << std::string(indent+delta_indent,' ') << "bins with " << k << " entries: " << int(1000.0*count[k]/hashtabsize)/10.0 << "% (expected: " @@ -304,7 +292,7 @@ void expairseq::printtree(std::ostream & os, unsigned indent) const os << std::string(indent+delta_indent,' ') << "average fill: " << (1.0*cum_fill)/hashtabsize << " (should be equal to " << (1.0*seq.size())/hashtabsize << ")" << std::endl; -#endif // def EXPAIRSEQ_USE_HASHTAB +#endif // EXPAIRSEQ_USE_HASHTAB } bool expairseq::info(unsigned inf) const @@ -314,37 +302,34 @@ bool expairseq::info(unsigned inf) const unsigned expairseq::nops() const { - if (overall_coeff.is_equal(default_overall_coeff())) { + if (overall_coeff.is_equal(default_overall_coeff())) return seq.size(); - } - return seq.size()+1; + else + return seq.size()+1; } ex expairseq::op(int i) const { - if (unsigned(i)hold(); - } - + return (new expairseq(vp,overall_coeff))->setflag(status_flags::dynallocated | status_flags::evaluated); } @@ -359,47 +344,45 @@ ex expairseq::normal(lst &sym_lst, lst &repl_lst, int level) const return n.bp->basic::normal(sym_lst,repl_lst,level); } -ex expairseq::subs(const lst & ls, const lst & lr) const +ex expairseq::subs(const lst &ls, const lst &lr) const { - epvector * vp=subschildren(ls,lr); - if (vp==0) { + epvector *vp = subschildren(ls,lr); + if (vp==0) return *this; - } + return thisexpairseq(vp,overall_coeff); } // protected -/** Implementation of ex::diff() for an expairseq. It differentiates all elements of the - * sequence. +/** Implementation of ex::diff() for an expairseq. + * It differentiates all elements of the sequence. * @see ex::diff */ -ex expairseq::derivative(const symbol & s) const +ex expairseq::derivative(const symbol &s) const { return thisexpairseq(diffchildren(s),overall_coeff); } -int expairseq::compare_same_type(const basic & other) const +int expairseq::compare_same_type(const basic &other) const { GINAC_ASSERT(is_of_type(other, expairseq)); - const expairseq & o = static_cast(const_cast(other)); - + const expairseq &o = static_cast(const_cast(other)); + int cmpval; // compare number of elements - if (seq.size() != o.seq.size()) { + if (seq.size() != o.seq.size()) return (seq.size()0) { - const epplist & eppl1=hashtab[i]; - const epplist & eppl2=o.hashtab[i]; - epplist::const_iterator it1=eppl1.begin(); - epplist::const_iterator it2=eppl2.begin(); + const epplist &eppl1 = hashtab[i]; + const epplist &eppl2 = o.hashtab[i]; + epplist::const_iterator it1 = eppl1.begin(); + epplist::const_iterator it2 = eppl2.begin(); while (it1!=eppl1.end()) { - cmpval=(*(*it1)).compare(*(*it2)); - if (cmpval!=0) return cmpval; + cmpval = (*(*it1)).compare(*(*it2)); + if (cmpval!=0) + return cmpval; ++it1; ++it2; } @@ -443,35 +426,37 @@ int expairseq::compare_same_type(const basic & other) const } return 0; // equal -#endif // def EXPAIRSEQ_USE_HASHTAB +#endif // EXPAIRSEQ_USE_HASHTAB } -bool expairseq::is_equal_same_type(const basic & other) const +bool expairseq::is_equal_same_type(const basic &other) const { - const expairseq & o=dynamic_cast(const_cast(other)); - + const expairseq &o = dynamic_cast(const_cast(other)); + // compare number of elements - if (seq.size() != o.seq.size()) return false; - + if (seq.size()!=o.seq.size()) + return false; + // compare overall_coeff - if (!overall_coeff.is_equal(o.overall_coeff)) return false; - -#ifdef EXPAIRSEQ_USE_HASHTAB + if (!overall_coeff.is_equal(o.overall_coeff)) + return false; + +#if EXPAIRSEQ_USE_HASHTAB // compare number of elements in each hashtab entry if (hashtabsize!=o.hashtabsize) { - cout << "this:" << std::endl; - printtree(cout,0); - cout << "other:" << std::endl; - other.printtree(cout,0); + std::cout << "this:" << std::endl; + printtree(std::cout,0); + std::cout << "other:" << std::endl; + other.printtree(std::cout,0); } GINAC_ASSERT(hashtabsize==o.hashtabsize); if (hashtabsize==0) { -#endif // def EXPAIRSEQ_USE_HASHTAB - epvector::const_iterator cit1=seq.begin(); - epvector::const_iterator cit2=o.seq.begin(); - epvector::const_iterator last1=seq.end(); +#endif // EXPAIRSEQ_USE_HASHTAB + epvector::const_iterator cit1 = seq.begin(); + epvector::const_iterator cit2 = o.seq.begin(); + epvector::const_iterator last1 = seq.end(); while (cit1!=last1) { if (!(*cit1).is_equal(*cit2)) return false; @@ -480,21 +465,22 @@ bool expairseq::is_equal_same_type(const basic & other) const } return true; -#ifdef EXPAIRSEQ_USE_HASHTAB +#if EXPAIRSEQ_USE_HASHTAB } - + for (unsigned i=0; i0) { - const epplist & eppl1=hashtab[i]; - const epplist & eppl2=o.hashtab[i]; - epplist::const_iterator it1=eppl1.begin(); - epplist::const_iterator it2=eppl2.begin(); + const epplist &eppl1 = hashtab[i]; + const epplist &eppl2 = o.hashtab[i]; + epplist::const_iterator it1 = eppl1.begin(); + epplist::const_iterator it2 = eppl2.begin(); while (it1!=eppl1.end()) { if (!(*(*it1)).is_equal(*(*it2))) return false; ++it1; @@ -502,9 +488,9 @@ bool expairseq::is_equal_same_type(const basic & other) const } } } - + return true; -#endif // def EXPAIRSEQ_USE_HASHTAB +#endif // EXPAIRSEQ_USE_HASHTAB } unsigned expairseq::return_type(void) const @@ -514,33 +500,39 @@ unsigned expairseq::return_type(void) const unsigned expairseq::calchash(void) const { - unsigned v=golden_ratio_hash(tinfo()); - epvector::const_iterator last=seq.end(); - for (epvector::const_iterator cit=seq.begin(); cit!=last; ++cit) { -#ifndef EXPAIRSEQ_USE_HASHTAB - v=rotate_left_31(v); // rotation would spoil commutativity -#endif // ndef EXPAIRSEQ_USE_HASHTAB - v ^= (*cit).rest.gethash(); + unsigned v = golden_ratio_hash(tinfo()); + for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { +#if !EXPAIRSEQ_USE_HASHTAB + v = rotate_left_31(v); // rotation would spoil commutativity +#endif // EXPAIRSEQ_USE_HASHTAB + v ^= cit->rest.gethash(); +#if !EXPAIRSEQ_USE_HASHTAB + v = rotate_left_31(v); + v ^= cit->coeff.gethash(); +#endif // EXPAIRSEQ_USE_HASHTAB } - + v ^= overall_coeff.gethash(); - v=v & 0x7FFFFFFFU; + v &= 0x7FFFFFFFU; // store calculated hash value only if object is already evaluated - if (flags & status_flags::evaluated) { + if (flags &status_flags::evaluated) { setflag(status_flags::hash_calculated); - hashvalue=v; + hashvalue = v; } - + return v; } ex expairseq::expand(unsigned options) const { - epvector * vp = expandchildren(options); + epvector *vp = expandchildren(options); if (vp==0) { + // the terms have not changed, so it is safe to declare this expanded + setflag(status_flags::expanded); return *this; } + return thisexpairseq(vp,overall_coeff); } @@ -550,17 +542,25 @@ ex expairseq::expand(unsigned options) const // protected -ex expairseq::thisexpairseq(const epvector & v, const ex & oc) const +/** Create an object of this type. + * This method works similar to a constructor. It is useful because expairseq + * has (at least) two possible different semantics but we want to inherit + * methods thus avoiding code duplication. Sometimes a method in expairseq + * has to create a new one of the same semantics, which cannot be done by a + * ctor because the name (add, mul,...) is unknown on the expaiseq level. In + * order for this trick to work a derived class must of course override this + * definition. */ +ex expairseq::thisexpairseq(const epvector &v, const ex &oc) const { return expairseq(v,oc); } -ex expairseq::thisexpairseq(epvector * vp, const ex & oc) const +ex expairseq::thisexpairseq(epvector *vp, const ex &oc) const { return expairseq(vp,oc); } -void expairseq::printpair(std::ostream & os, const expair & p, unsigned upper_precedence) const +void expairseq::printpair(std::ostream &os, const expair &p, unsigned upper_precedence) const { os << "[["; p.rest.bp->print(os,precedence); @@ -569,11 +569,12 @@ void expairseq::printpair(std::ostream & os, const expair & p, unsigned upper_pr os << "]]"; } -void expairseq::printseq(std::ostream & os, char delim, +void expairseq::printseq(std::ostream &os, char delim, unsigned this_precedence, unsigned upper_precedence) const { - if (this_precedence<=upper_precedence) os << "("; + if (this_precedence<=upper_precedence) + os << "("; epvector::const_iterator it,it_last; it_last=seq.end(); --it_last; @@ -582,27 +583,33 @@ void expairseq::printseq(std::ostream & os, char delim, os << delim; } printpair(os,*it,this_precedence); - if (!overall_coeff.is_equal(default_overall_coeff())) { + if (!overall_coeff.is_equal(default_overall_coeff())) os << delim << overall_coeff; - } - if (this_precedence<=upper_precedence) os << ")"; -} -expair expairseq::split_ex_to_pair(const ex & e) const + if (this_precedence<=upper_precedence) + os << ")"; +} + + +/** Form an expair from an ex, using the corresponding semantics. + * @see expairseq::recombine_pair_to_ex() */ +expair expairseq::split_ex_to_pair(const ex &e) const { return expair(e,_ex1()); } -expair expairseq::combine_ex_with_coeff_to_pair(const ex & e, - const ex & c) const + +expair expairseq::combine_ex_with_coeff_to_pair(const ex &e, + const ex &c) const { GINAC_ASSERT(is_ex_exactly_of_type(c,numeric)); - + return expair(e,c); } -expair expairseq::combine_pair_with_coeff_to_pair(const expair & p, - const ex & c) const + +expair expairseq::combine_pair_with_coeff_to_pair(const expair &p, + const ex &c) const { GINAC_ASSERT(is_ex_exactly_of_type(p.coeff,numeric)); GINAC_ASSERT(is_ex_exactly_of_type(c,numeric)); @@ -610,13 +617,19 @@ expair expairseq::combine_pair_with_coeff_to_pair(const expair & p, return expair(p.rest,ex_to_numeric(p.coeff).mul_dyn(ex_to_numeric(c))); } -ex expairseq::recombine_pair_to_ex(const expair & p) const + +/** Form an ex out of an expair, using the corresponding semantics. + * @see expairseq::split_ex_to_pair() */ +ex expairseq::recombine_pair_to_ex(const expair &p) const { return lst(p.rest,p.coeff); } bool expairseq::expair_needs_further_processing(epp it) { +#if EXPAIRSEQ_USE_HASHTAB + //# error "FIXME: expair_needs_further_processing not yet implemented for hashtabs, sorry. A.F." +#endif // EXPAIRSEQ_USE_HASHTAB return false; } @@ -625,14 +638,14 @@ ex expairseq::default_overall_coeff(void) const return _ex0(); } -void expairseq::combine_overall_coeff(const ex & c) +void expairseq::combine_overall_coeff(const ex &c) { GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric)); GINAC_ASSERT(is_ex_exactly_of_type(c,numeric)); overall_coeff = ex_to_numeric(overall_coeff).add_dyn(ex_to_numeric(c)); } -void expairseq::combine_overall_coeff(const ex & c1, const ex & c2) +void expairseq::combine_overall_coeff(const ex &c1, const ex &c2) { GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric)); GINAC_ASSERT(is_ex_exactly_of_type(c1,numeric)); @@ -641,80 +654,80 @@ void expairseq::combine_overall_coeff(const ex & c1, const ex & c2) add_dyn(ex_to_numeric(c1).mul(ex_to_numeric(c2))); } -bool expairseq::can_make_flat(const expair & p) const +bool expairseq::can_make_flat(const expair &p) const { return true; } - + ////////// // non-virtual functions in this class ////////// -void expairseq::construct_from_2_ex_via_exvector(const ex & lh, const ex & rh) +void expairseq::construct_from_2_ex_via_exvector(const ex &lh, const ex &rh) { exvector v; v.reserve(2); v.push_back(lh); v.push_back(rh); construct_from_exvector(v); -#ifdef EXPAIRSEQ_USE_HASHTAB +#if EXPAIRSEQ_USE_HASHTAB GINAC_ASSERT((hashtabsize==0)||(hashtabsize>=minhashtabsize)); GINAC_ASSERT(hashtabsize==calc_hashtabsize(seq.size())); -#endif // def EXPAIRSEQ_USE_HASHTAB +#endif // EXPAIRSEQ_USE_HASHTAB } -void expairseq::construct_from_2_ex(const ex & lh, const ex & rh) +void expairseq::construct_from_2_ex(const ex &lh, const ex &rh) { if (lh.bp->tinfo()==tinfo()) { if (rh.bp->tinfo()==tinfo()) { -#ifdef EXPAIRSEQ_USE_HASHTAB +#if EXPAIRSEQ_USE_HASHTAB unsigned totalsize = ex_to_expairseq(lh).seq.size() + ex_to_expairseq(rh).seq.size(); if (calc_hashtabsize(totalsize)!=0) { construct_from_2_ex_via_exvector(lh,rh); } else { -#endif // def EXPAIRSEQ_USE_HASHTAB +#endif // EXPAIRSEQ_USE_HASHTAB construct_from_2_expairseq(ex_to_expairseq(lh), ex_to_expairseq(rh)); -#ifdef EXPAIRSEQ_USE_HASHTAB +#if EXPAIRSEQ_USE_HASHTAB } -#endif // def EXPAIRSEQ_USE_HASHTAB +#endif // EXPAIRSEQ_USE_HASHTAB return; } else { -#ifdef EXPAIRSEQ_USE_HASHTAB - unsigned totalsize=ex_to_expairseq(lh).seq.size()+1; - if (calc_hashtabsize(totalsize) != 0) { +#if EXPAIRSEQ_USE_HASHTAB + unsigned totalsize = ex_to_expairseq(lh).seq.size()+1; + if (calc_hashtabsize(totalsize)!=0) { construct_from_2_ex_via_exvector(lh, rh); } else { -#endif // def EXPAIRSEQ_USE_HASHTAB +#endif // EXPAIRSEQ_USE_HASHTAB construct_from_expairseq_ex(ex_to_expairseq(lh), rh); -#ifdef EXPAIRSEQ_USE_HASHTAB +#if EXPAIRSEQ_USE_HASHTAB } -#endif // def EXPAIRSEQ_USE_HASHTAB +#endif // EXPAIRSEQ_USE_HASHTAB return; } } else if (rh.bp->tinfo()==tinfo()) { -#ifdef EXPAIRSEQ_USE_HASHTAB +#if EXPAIRSEQ_USE_HASHTAB unsigned totalsize=ex_to_expairseq(rh).seq.size()+1; if (calc_hashtabsize(totalsize)!=0) { construct_from_2_ex_via_exvector(lh,rh); } else { -#endif // def EXPAIRSEQ_USE_HASHTAB +#endif // EXPAIRSEQ_USE_HASHTAB construct_from_expairseq_ex(ex_to_expairseq(rh),lh); -#ifdef EXPAIRSEQ_USE_HASHTAB +#if EXPAIRSEQ_USE_HASHTAB } -#endif // def EXPAIRSEQ_USE_HASHTAB +#endif // EXPAIRSEQ_USE_HASHTAB return; } - -#ifdef EXPAIRSEQ_USE_HASHTAB + +#if EXPAIRSEQ_USE_HASHTAB if (calc_hashtabsize(2)!=0) { construct_from_2_ex_via_exvector(lh,rh); return; } - hashtabsize=0; -#endif // def EXPAIRSEQ_USE_HASHTAB + hashtabsize = 0; +#endif // EXPAIRSEQ_USE_HASHTAB if (is_ex_exactly_of_type(lh,numeric)) { if (is_ex_exactly_of_type(rh,numeric)) { @@ -729,10 +742,10 @@ void expairseq::construct_from_2_ex(const ex & lh, const ex & rh) combine_overall_coeff(rh); seq.push_back(split_ex_to_pair(lh)); } else { - expair p1=split_ex_to_pair(lh); - expair p2=split_ex_to_pair(rh); - - int cmpval=p1.rest.compare(p2.rest); + expair p1 = split_ex_to_pair(lh); + expair p2 = split_ex_to_pair(rh); + + int cmpval = p1.rest.compare(p2.rest); if (cmpval==0) { p1.coeff=ex_to_numeric(p1.coeff).add_dyn(ex_to_numeric(p2.coeff)); if (!ex_to_numeric(p1.coeff).is_zero()) { @@ -754,26 +767,26 @@ void expairseq::construct_from_2_ex(const ex & lh, const ex & rh) } } -void expairseq::construct_from_2_expairseq(const expairseq & s1, - const expairseq & s2) +void expairseq::construct_from_2_expairseq(const expairseq &s1, + const expairseq &s2) { combine_overall_coeff(s1.overall_coeff); combine_overall_coeff(s2.overall_coeff); - epvector::const_iterator first1=s1.seq.begin(); - epvector::const_iterator last1=s1.seq.end(); - epvector::const_iterator first2=s2.seq.begin(); - epvector::const_iterator last2=s2.seq.end(); + epvector::const_iterator first1 = s1.seq.begin(); + epvector::const_iterator last1 = s1.seq.end(); + epvector::const_iterator first2 = s2.seq.begin(); + epvector::const_iterator last2 = s2.seq.end(); seq.reserve(s1.seq.size()+s2.seq.size()); bool needs_further_processing=false; while (first1!=last1 && first2!=last2) { - int cmpval=(*first1).rest.compare((*first2).rest); + int cmpval = (*first1).rest.compare((*first2).rest); if (cmpval==0) { // combine terms - const numeric & newcoeff = ex_to_numeric((*first1).coeff). + const numeric &newcoeff = ex_to_numeric((*first1).coeff). add(ex_to_numeric((*first2).coeff)); if (!newcoeff.is_zero()) { seq.push_back(expair((*first1).rest,newcoeff)); @@ -800,39 +813,39 @@ void expairseq::construct_from_2_expairseq(const expairseq & s1, seq.push_back(*first2); ++first2; } - + if (needs_further_processing) { - epvector v=seq; + epvector v = seq; seq.clear(); construct_from_epvector(v); } } -void expairseq::construct_from_expairseq_ex(const expairseq & s, - const ex & e) +void expairseq::construct_from_expairseq_ex(const expairseq &s, + const ex &e) { combine_overall_coeff(s.overall_coeff); if (is_ex_exactly_of_type(e,numeric)) { combine_overall_coeff(e); - seq=s.seq; + seq = s.seq; return; } - - epvector::const_iterator first=s.seq.begin(); - epvector::const_iterator last=s.seq.end(); - expair p=split_ex_to_pair(e); - + + epvector::const_iterator first = s.seq.begin(); + epvector::const_iterator last = s.seq.end(); + expair p = split_ex_to_pair(e); + seq.reserve(s.seq.size()+1); - bool p_pushed=0; - + bool p_pushed = false; + bool needs_further_processing=false; - + // merge p into s.seq while (first!=last) { int cmpval=(*first).rest.compare(p.rest); if (cmpval==0) { // combine terms - const numeric & newcoeff = ex_to_numeric((*first).coeff). + const numeric &newcoeff = ex_to_numeric((*first).coeff). add(ex_to_numeric(p.coeff)); if (!newcoeff.is_zero()) { seq.push_back(expair((*first).rest,newcoeff)); @@ -841,18 +854,18 @@ void expairseq::construct_from_expairseq_ex(const expairseq & s, } } ++first; - p_pushed=1; + p_pushed = true; break; } else if (cmpval<0) { seq.push_back(*first); ++first; } else { seq.push_back(p); - p_pushed=1; + p_pushed = true; break; } } - + if (p_pushed) { // while loop exited because p was pushed, now push rest of s.seq while (first!=last) { @@ -865,13 +878,13 @@ void expairseq::construct_from_expairseq_ex(const expairseq & s, } if (needs_further_processing) { - epvector v=seq; + epvector v = seq; seq.clear(); construct_from_epvector(v); } } -void expairseq::construct_from_exvector(const exvector & v) +void expairseq::construct_from_exvector(const exvector &v) { // simplifications: +(a,+(b,c),d) -> +(a,b,c,d) (associativity) // +(d,b,c,a) -> +(a,b,c,d) (canonicalization) @@ -879,15 +892,16 @@ void expairseq::construct_from_exvector(const exvector & v) // (same for (+,*) -> (*,^) make_flat(v); -#ifdef EXPAIRSEQ_USE_HASHTAB +#if EXPAIRSEQ_USE_HASHTAB combine_same_terms(); #else canonicalize(); combine_same_terms_sorted_seq(); -#endif // def EXPAIRSEQ_USE_HASHTAB +#endif // EXPAIRSEQ_USE_HASHTAB + return; } -void expairseq::construct_from_epvector(const epvector & v) +void expairseq::construct_from_epvector(const epvector &v) { // simplifications: +(a,+(b,c),d) -> +(a,b,c,d) (associativity) // +(d,b,c,a) -> +(a,b,c,d) (canonicalization) @@ -895,93 +909,93 @@ void expairseq::construct_from_epvector(const epvector & v) // (same for (+,*) -> (*,^) make_flat(v); -#ifdef EXPAIRSEQ_USE_HASHTAB +#if EXPAIRSEQ_USE_HASHTAB combine_same_terms(); #else canonicalize(); combine_same_terms_sorted_seq(); -#endif // def EXPAIRSEQ_USE_HASHTAB +#endif // EXPAIRSEQ_USE_HASHTAB + return; } -void expairseq::make_flat(const exvector & v) +/** Combine this expairseq with argument exvector. + * It cares for associativity as well as for special handling of numerics. */ +void expairseq::make_flat(const exvector &v) { - exvector::const_iterator cit, citend = v.end(); - + exvector::const_iterator cit; + // count number of operands which are of same expairseq derived type // and their cumulative number of operands - int nexpairseqs=0; - int noperands=0; - cit=v.begin(); - while (cit!=citend) { - if (cit->bp->tinfo()==tinfo()) { + int nexpairseqs = 0; + int noperands = 0; + + cit = v.begin(); + while (cit!=v.end()) { + if (cit->bp->tinfo()==this->tinfo()) { ++nexpairseqs; - noperands+=ex_to_expairseq(*cit).seq.size(); + noperands += ex_to_expairseq(*cit).seq.size(); } ++cit; } - + // reserve seq and coeffseq which will hold all operands seq.reserve(v.size()+noperands-nexpairseqs); - + // copy elements and split off numerical part - cit=v.begin(); - while (cit!=citend) { - if (cit->bp->tinfo()==tinfo()) { - const expairseq & subseqref=ex_to_expairseq(*cit); + cit = v.begin(); + while (cit!=v.end()) { + if (cit->bp->tinfo()==this->tinfo()) { + const expairseq &subseqref = ex_to_expairseq(*cit); combine_overall_coeff(subseqref.overall_coeff); - epvector::const_iterator cit_s=subseqref.seq.begin(); + epvector::const_iterator cit_s = subseqref.seq.begin(); while (cit_s!=subseqref.seq.end()) { seq.push_back(*cit_s); ++cit_s; } } else { - if (is_ex_exactly_of_type(*cit,numeric)) { + if (is_ex_exactly_of_type(*cit,numeric)) combine_overall_coeff(*cit); - } else { + else seq.push_back(split_ex_to_pair(*cit)); - } } ++cit; } - - /* - cout << "after make flat" << std::endl; - for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { - (*cit).printraw(cout); - } - cout << std::endl; - */ + + return; } -void expairseq::make_flat(const epvector & v) +/** Combine this expairseq with argument epvector. + * It cares for associativity as well as for special handling of numerics. */ +void expairseq::make_flat(const epvector &v) { - epvector::const_iterator cit, citend = v.end(); - + epvector::const_iterator cit; + // count number of operands which are of same expairseq derived type // and their cumulative number of operands - int nexpairseqs=0; - int noperands=0; - + int nexpairseqs = 0; + int noperands = 0; + cit = v.begin(); - while (cit!=citend) { - if (cit->rest.bp->tinfo()==tinfo()) { + while (cit!=v.end()) { + if (cit->rest.bp->tinfo()==this->tinfo()) { ++nexpairseqs; noperands += ex_to_expairseq((*cit).rest).seq.size(); } ++cit; } - + // reserve seq and coeffseq which will hold all operands seq.reserve(v.size()+noperands-nexpairseqs); - + // copy elements and split off numerical part cit = v.begin(); - while (cit!=citend) { - if ((cit->rest.bp->tinfo()==tinfo())&&can_make_flat(*cit)) { - const expairseq & subseqref=ex_to_expairseq((*cit).rest); + while (cit!=v.end()) { + if (cit->rest.bp->tinfo()==this->tinfo() && + this->can_make_flat(*cit)) { + const expairseq &subseqref = ex_to_expairseq((*cit).rest); combine_overall_coeff(ex_to_numeric(subseqref.overall_coeff), ex_to_numeric((*cit).coeff)); - epvector::const_iterator cit_s=subseqref.seq.begin(); + epvector::const_iterator cit_s = subseqref.seq.begin(); while (cit_s!=subseqref.seq.end()) { seq.push_back(expair((*cit_s).rest, ex_to_numeric((*cit_s).coeff).mul_dyn(ex_to_numeric((*cit).coeff)))); @@ -990,216 +1004,101 @@ void expairseq::make_flat(const epvector & v) ++cit_s; } } else { - if ((*cit).is_numeric_with_coeff_1()) { - combine_overall_coeff((*cit).rest); - //if (is_ex_exactly_of_type((*cit).rest,numeric)) { - // combine_overall_coeff(recombine_pair_to_ex(*cit)); - } else { + if (cit->is_canonical_numeric()) + combine_overall_coeff(cit->rest); + else seq.push_back(*cit); - } } ++cit; } + return; } -epvector * expairseq::bubblesort(epvector::iterator itbegin, epvector::iterator itend) -{ - unsigned n=itend-itbegin; - - epvector * sp=new epvector; - sp->reserve(n); - - epvector::iterator last=itend-1; - for (epvector::iterator it1=itbegin; it1!=last; ++it1) { - for (epvector::iterator it2=it1+1; it2!=itend; ++it2) { - if ((*it2).rest.compare((*it1).rest)<0) { - iter_swap(it1,it2); - } - } - sp->push_back(*it1); - } - sp->push_back(*last); - return sp; -} - -epvector * expairseq::mergesort(epvector::iterator itbegin, epvector::iterator itend) -{ - unsigned n=itend-itbegin; - /* - if (n==1) { - epvector * sp=new epvector; - sp->push_back(*itbegin); - return sp; - } - */ - if (n<16) return bubblesort(itbegin, itend); - unsigned m=n/2; - - epvector * s1p=mergesort(itbegin, itbegin+m); - epvector * s2p=mergesort(itbegin+m, itend); - - epvector * sp=new epvector; - sp->reserve(s1p->size()+s2p->size()); - - epvector::iterator first1=s1p->begin(); - epvector::iterator last1=s1p->end(); - - epvector::iterator first2=s2p->begin(); - epvector::iterator last2=s2p->end(); - - while (first1 != last1 && first2 != last2) { - if ((*first1).rest.compare((*first2).rest)<0) { - sp->push_back(*first1); - ++first1; - } else { - sp->push_back(*first2); - ++first2; - } - } - - if (first1 != last1) { - while (first1 != last1) { - sp->push_back(*first1); - ++first1; - } - } else { - while (first2 != last2) { - sp->push_back(*first2); - ++first2; - } - } - - delete s1p; - delete s2p; - - return sp; -} - +/** Brings this expairseq into a sorted (canonical) form. */ void expairseq::canonicalize(void) { // canonicalize sort(seq.begin(),seq.end(),expair_is_less()); - /* - sort(seq.begin(),seq.end(),expair_is_less_old()); - if (seq.size()>1) { - if (is_ex_exactly_of_type((*(seq.begin())).rest,numeric)) { - sort(seq.begin(),seq.end(),expair_is_less()); - } else { - epvector::iterator last_numeric=seq.end(); - do { - last_numeric--; - } while (is_ex_exactly_of_type((*last_numeric).rest,numeric)); - ++last_numeric; - sort(last_numeric,seq.end(),expair_is_less()); - } - } - */ - - /* - epvector * sorted_seqp=mergesort(seq.begin(),seq.end()); - epvector::iterator last=sorted_seqp->end(); - epvector::iterator it2=seq.begin(); - for (epvector::iterator it1=sorted_seqp->begin(); it1!=last; ++it1, ++it2) { - iter_swap(it1,it2); - } - delete sorted_seqp; - */ - - /* - cout << "after canonicalize" << std::endl; - for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { - (*cit).printraw(cout); - } - cout << std::endl; - cout.flush(); - */ + return; } + +/** Compact a presorted expairseq by combining all matching expairs to one + * each. On an add object, this is responsible for 2*x+3*x+y -> 5*x+y, for + * instance. */ void expairseq::combine_same_terms_sorted_seq(void) { - bool needs_further_processing=false; + bool needs_further_processing = false; - // combine same terms, drop term with coeff 0 if (seq.size()>1) { - epvector::iterator itin1=seq.begin(); - epvector::iterator itin2=itin1+1; - epvector::iterator itout=itin1; - epvector::iterator last=seq.end(); - // must_copy will be set to true the first time some combination is possible - // from then on the sequence has changed and must be compacted - bool must_copy=false; + epvector::iterator itin1 = seq.begin(); + epvector::iterator itin2 = itin1+1; + epvector::iterator itout = itin1; + epvector::iterator last = seq.end(); + // must_copy will be set to true the first time some combination is + // possible from then on the sequence has changed and must be compacted + bool must_copy = false; while (itin2!=last) { if ((*itin1).rest.compare((*itin2).rest)==0) { (*itin1).coeff = ex_to_numeric((*itin1).coeff). add_dyn(ex_to_numeric((*itin2).coeff)); - if (expair_needs_further_processing(itin1)) { + if (expair_needs_further_processing(itin1)) needs_further_processing = true; - } - must_copy=true; + must_copy = true; } else { if (!ex_to_numeric((*itin1).coeff).is_zero()) { - if (must_copy) { - *itout=*itin1; - } + if (must_copy) + *itout = *itin1; ++itout; } - itin1=itin2; + itin1 = itin2; } ++itin2; } if (!ex_to_numeric((*itin1).coeff).is_zero()) { - if (must_copy) { - *itout=*itin1; - } + if (must_copy) + *itout = *itin1; ++itout; } - if (itout!=last) { + if (itout!=last) seq.erase(itout,last); - } } - - /* - cout << "after combine" << std::endl; - for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { - (*cit).printraw(cout); - } - cout << std::endl; - cout.flush(); - */ if (needs_further_processing) { - epvector v=seq; + epvector v = seq; seq.clear(); construct_from_epvector(v); } + return; } -#ifdef EXPAIRSEQ_USE_HASHTAB +#if EXPAIRSEQ_USE_HASHTAB unsigned expairseq::calc_hashtabsize(unsigned sz) const { unsigned size; unsigned nearest_power_of_2 = 1 << log2(sz); - // if (nearest_power_of_2 < maxhashtabsize/hashtabfactor) { - // size=nearest_power_of_2*hashtabfactor; - size=nearest_power_of_2/hashtabfactor; - if (size & touched, - unsigned & number_of_zeroes) +void expairseq::build_hashtab_and_combine(epvector::iterator &first_numeric, + epvector::iterator &last_non_zero, + vector &touched, + unsigned &number_of_zeroes) { epp current=seq.begin(); @@ -1317,13 +1217,14 @@ void expairseq::build_hashtab_and_combine(epvector::iterator & first_numeric, iter_swap(current,first_numeric); } else { // calculate hashindex - unsigned currenthashindex=calc_hashindex((*current).rest); + unsigned currenthashindex = calc_hashindex((*current).rest); // test if there is already a matching expair in the hashtab-list - epplist & eppl=hashtab[currenthashindex]; - epplist::iterator epplit=eppl.begin(); + epplist &eppl=hashtab[currenthashindex]; + epplist::iterator epplit = eppl.begin(); while (epplit!=eppl.end()) { - if ((*current).rest.is_equal((*(*epplit)).rest)) break; + if ((*current).rest.is_equal((*(*epplit)).rest)) + break; ++epplit; } if (epplit==eppl.end()) { @@ -1347,27 +1248,27 @@ void expairseq::build_hashtab_and_combine(epvector::iterator & first_numeric, } } } -} +} -void expairseq::drop_coeff_0_terms(epvector::iterator & first_numeric, - epvector::iterator & last_non_zero, - vector & touched, - unsigned & number_of_zeroes) +void expairseq::drop_coeff_0_terms(epvector::iterator &first_numeric, + epvector::iterator &last_non_zero, + vector &touched, + unsigned &number_of_zeroes) { // move terms with coeff 0 to end and remove them from hashtab // check only those elements which have been touched - epp current=seq.begin(); - unsigned i=0; + epp current = seq.begin(); + unsigned i = 0; while (current!=first_numeric) { if (!touched[i]) { ++current; ++i; - } else if (!ex_to_numeric((*current).coeff).is_equal(_num0())) { + } else if (!ex_to_numeric((*current).coeff).is_zero()) { ++current; ++i; } else { remove_hashtab_entry(current); - + // move element to the end, unless it is already at the end if (current!=last_non_zero) { iter_swap(current,last_non_zero); @@ -1376,12 +1277,11 @@ void expairseq::drop_coeff_0_terms(epvector::iterator & first_numeric, if (numeric_swapped) iter_swap(first_numeric,current); epvector::iterator changed_entry; - if (numeric_swapped) { - changed_entry=first_numeric; - } else { - changed_entry=last_non_zero; - } - + if (numeric_swapped) + changed_entry = first_numeric; + else + changed_entry = last_non_zero; + --last_non_zero; ++number_of_zeroes; @@ -1389,7 +1289,7 @@ void expairseq::drop_coeff_0_terms(epvector::iterator & first_numeric, // change entry in hashtab which referred to first_numeric or last_non_zero to current move_hashtab_entry(changed_entry,current); - touched[current-seq.begin()]=touched[changed_entry-seq.begin()]; + touched[current-seq.begin()] = touched[changed_entry-seq.begin()]; } } else { --first_numeric; @@ -1404,9 +1304,8 @@ void expairseq::drop_coeff_0_terms(epvector::iterator & first_numeric, bool expairseq::has_coeff_0(void) const { for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { - if ((*cit).coeff.is_equal(_ex0())) { + if ((*cit).coeff.is_zero()) return true; - } } return false; } @@ -1415,9 +1314,9 @@ void expairseq::add_numerics_to_hashtab(epvector::iterator first_numeric, epvector::const_iterator last_non_zero) { if (first_numeric==seq.end()) return; // no numerics - - epvector::iterator current=first_numeric; - epvector::const_iterator last=last_non_zero+1; + + epvector::iterator current = first_numeric; + epvector::const_iterator last = last_non_zero+1; while (current!=last) { sorted_insert(hashtab[hashmask],current); ++current; @@ -1430,32 +1329,32 @@ void expairseq::combine_same_terms(void) // calculate size of hashtab hashtabsize = calc_hashtabsize(seq.size()); - + // hashtabsize is a power of 2 hashmask = hashtabsize-1; - + // allocate hashtab hashtab.clear(); hashtab.resize(hashtabsize); - + if (hashtabsize==0) { canonicalize(); combine_same_terms_sorted_seq(); GINAC_ASSERT(!has_coeff_0()); return; } - + // iterate through seq, move numerics to end, // fill hashtab and combine same terms - epvector::iterator first_numeric=seq.end(); - epvector::iterator last_non_zero=seq.end()-1; - + epvector::iterator first_numeric = seq.end(); + epvector::iterator last_non_zero = seq.end()-1; + vector touched; touched.reserve(seq.size()); for (unsigned i=0; i0) return 1; // not canoncalized -#endif // def EXPAIRSEQ_USE_HASHTAB +#endif // EXPAIRSEQ_USE_HASHTAB epvector::const_iterator it = seq.begin(); epvector::const_iterator it_last = it; @@ -1539,18 +1441,24 @@ bool expairseq::is_canonical() const return 1; } + +/** Member-wise expand the expairs in this sequence. + * + * @see expairseq::expand() + * @return pointer to epvector containing expanded pairs or zero pointer, + * if no members were changed. */ epvector * expairseq::expandchildren(unsigned options) const { epvector::const_iterator last = seq.end(); epvector::const_iterator cit = seq.begin(); while (cit!=last) { - const ex & expanded_ex=(*cit).rest.expand(options); + const ex &expanded_ex = (*cit).rest.expand(options); if (!are_ex_trivially_equal((*cit).rest,expanded_ex)) { - + // something changed, copy seq, eval and return it - epvector *s=new epvector; + epvector *s = new epvector; s->reserve(seq.size()); - + // copy parts of seq which are known not to have changed epvector::const_iterator cit2 = seq.begin(); while (cit2!=cit) { @@ -1572,33 +1480,38 @@ epvector * expairseq::expandchildren(unsigned options) const ++cit; } - return 0; // nothing has changed + return 0; // signalling nothing has changed } - + + +/** Member-wise evaluate the expairs in this sequence. + * + * @see expairseq::eval() + * @return pointer to epvector containing evaluated pairs or zero pointer, + * if no members were changed. */ epvector * expairseq::evalchildren(int level) const { // returns a NULL pointer if nothing had to be evaluated // returns a pointer to a newly created epvector otherwise // (which has to be deleted somewhere else) - if (level==1) { + if (level==1) return 0; - } - if (level == -max_recursion_level) { + + if (level == -max_recursion_level) throw(std::runtime_error("max recursion level reached")); - } - + --level; epvector::const_iterator last=seq.end(); epvector::const_iterator cit=seq.begin(); while (cit!=last) { - const ex & evaled_ex=(*cit).rest.eval(level); + const ex &evaled_ex = (*cit).rest.eval(level); if (!are_ex_trivially_equal((*cit).rest,evaled_ex)) { - + // something changed, copy seq, eval and return it epvector *s = new epvector; s->reserve(seq.size()); - + // copy parts of seq which are known not to have changed epvector::const_iterator cit2=seq.begin(); while (cit2!=cit) { @@ -1620,14 +1533,19 @@ epvector * expairseq::evalchildren(int level) const ++cit; } - return 0; // nothing has changed + return 0; // signalling nothing has changed } + +/** Member-wise evaluate numerically all expairs in this sequence. + * + * @see expairseq::evalf() + * @return epvector with all entries evaluated numerically. */ epvector expairseq::evalfchildren(int level) const { if (level==1) return seq; - + if (level==-max_recursion_level) throw(std::runtime_error("max recursion level reached")); @@ -1642,17 +1560,22 @@ epvector expairseq::evalfchildren(int level) const return s; } + +/** Member-wise normalize all expairs in this sequence. + * + * @see expairseq::normal() + * @return epvector with all entries normalized. */ epvector expairseq::normalchildren(int level) const { if (level==1) return seq; - if (level == -max_recursion_level) + if (level==-max_recursion_level) throw(std::runtime_error("max recursion level reached")); - + epvector s; s.reserve(seq.size()); - + --level; for (epvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) { s.push_back(combine_ex_with_coeff_to_pair((*it).rest.normal(level), @@ -1661,11 +1584,16 @@ epvector expairseq::normalchildren(int level) const return s; } -epvector expairseq::diffchildren(const symbol & y) const + +/** Member-wise differentiate all expairs in this sequence. + * + * @see expairseq::diff() + * @return epvector with all entries differentiated. */ +epvector expairseq::diffchildren(const symbol &y) const { epvector s; s.reserve(seq.size()); - + for (epvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) { s.push_back(combine_ex_with_coeff_to_pair((*it).rest.diff(y), (*it).coeff)); @@ -1673,17 +1601,23 @@ epvector expairseq::diffchildren(const symbol & y) const return s; } -epvector * expairseq::subschildren(const lst & ls, const lst & lr) const + +/** Member-wise substitute in this sequence. + * + * @see expairseq::subs() + * @return pointer to epvector containing pairs after application of subs or zero + * pointer, if no members were changed. */ +epvector * expairseq::subschildren(const lst &ls, const lst &lr) const { // returns a NULL pointer if nothing had to be substituted // returns a pointer to a newly created epvector otherwise // (which has to be deleted somewhere else) GINAC_ASSERT(ls.nops()==lr.nops()); - epvector::const_iterator last=seq.end(); - epvector::const_iterator cit=seq.begin(); + epvector::const_iterator last = seq.end(); + epvector::const_iterator cit = seq.begin(); while (cit!=last) { - const ex & subsed_ex=(*cit).rest.subs(ls,lr); + const ex &subsed_ex=(*cit).rest.subs(ls,lr); if (!are_ex_trivially_equal((*cit).rest,subsed_ex)) { // something changed, copy seq, subs and return it @@ -1691,7 +1625,7 @@ epvector * expairseq::subschildren(const lst & ls, const lst & lr) const s->reserve(seq.size()); // copy parts of seq which are known not to have changed - epvector::const_iterator cit2=seq.begin(); + epvector::const_iterator cit2 = seq.begin(); while (cit2!=cit) { s->push_back(*cit2); ++cit2; @@ -1711,7 +1645,7 @@ epvector * expairseq::subschildren(const lst & ls, const lst & lr) const ++cit; } - return 0; // nothing has changed + return 0; // signalling nothing has changed } ////////// @@ -1720,14 +1654,12 @@ epvector * expairseq::subschildren(const lst & ls, const lst & lr) const // protected -unsigned expairseq::precedence=10; +unsigned expairseq::precedence = 10; -#ifdef EXPAIRSEQ_USE_HASHTAB -unsigned expairseq::maxhashtabsize=0x4000000U; -unsigned expairseq::minhashtabsize=0x1000U; -unsigned expairseq::hashtabfactor=1; -#endif // def EXPAIRSEQ_USE_HASHTAB +#if EXPAIRSEQ_USE_HASHTAB +unsigned expairseq::maxhashtabsize = 0x4000000U; +unsigned expairseq::minhashtabsize = 0x1000U; +unsigned expairseq::hashtabfactor = 1; +#endif // EXPAIRSEQ_USE_HASHTAB -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/expairseq.h b/ginac/expairseq.h index bba0902d..665daed8 100644 --- a/ginac/expairseq.h +++ b/ginac/expairseq.h @@ -25,70 +25,65 @@ #include #include - // CINT needs to work properly with and #include #include "expair.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC - -//#define EXPAIRSEQ_USE_HASHTAB - -typedef std::vector epvector; -typedef epvector::iterator epviter; - -inline void iter_swap(epvector::iterator it1, epvector::iterator it2) -{ - (*it1).rest.swap((*it2).rest); - (*it1).coeff.swap((*it2).coeff); -} -typedef epvector::iterator epp; -typedef std::list epplist; -typedef std::vector epplistvector; +/** Using hash tables can potentially enhance the asymptotic behaviour of + * combining n terms into one large sum (or n terms into one large product) + * from O(n*log(n)) to about O(n). There are, however, several drawbacks. + * The constant in front of O(n) is quite large, when copying such an object + * one also has to copy the has table, comparison is quite expensive because + * there is no ordering any more, it doesn't help at all when combining two + * expairseqs because due to the presorted nature the behaviour would be + * O(n) anyways, the code is quite messy, etc, etc. The code is here as + * an example for following generations to tinker with. */ +#define EXPAIRSEQ_USE_HASHTAB 0 + +typedef std::vector epvector; ///< expair-vector +typedef epvector::iterator epviter; ///< expair-vector iterator +typedef epvector::iterator epp; ///< expair-vector pointer +typedef std::list epplist; ///< list of expair-vector pointers +typedef std::vector epplistvector; ///< vector of epplist /** A sequence of class expair. * This is used for time-critical classes like sums and products of terms * since handling a list of coeff and rest is much faster than handling a - * list of products or powers, respectively. (Incidentally, Maple does it - * the same way.) */ + * list of products or powers, respectively. (Not incidentally, Maple does it + * the same way, maybe others too.) The semantics is (at least) twofold: + * one for addition and one for multiplication and several methods have to + * be overridden by derived classes to reflect the change in semantics. + * However, most functionality turns out to be shared between addition and + * multiplication, which is the reason why there is this base class. */ class expairseq : public basic { GINAC_DECLARE_REGISTERED_CLASS_NO_CTORS(expairseq, basic) // member functions - // default constructor, destructor, copy constructor assignment operator and helpers + // default ctor, dtor, copy ctor assignment operator and helpers public: expairseq() : basic(TINFO_expairseq) -#ifdef EXPAIRSEQ_USE_HASHTAB +#if EXPAIRSEQ_USE_HASHTAB , hashtabsize(0) -#endif // def EXPAIRSEQ_USE_HASHTAB - { - } - ~expairseq() - { - destroy(0); - } +#endif // EXPAIRSEQ_USE_HASHTAB + { } + ~expairseq() { destroy(false); } expairseq(const expairseq & other); const expairseq & operator=(const expairseq & other); protected: void copy(const expairseq & other); - void destroy(bool call_parent) - { - if (call_parent) basic::destroy(call_parent); - }; - - // other constructors + void destroy(bool call_parent); + // other ctors public: expairseq(const ex & lh, const ex & rh); expairseq(const exvector & v); expairseq(const epvector & v, const ex & oc); expairseq(epvector * vp, const ex & oc); // vp will be deleted - + // functions overriding virtual functions from bases classes public: basic * duplicate() const; @@ -111,7 +106,7 @@ protected: unsigned return_type(void) const; unsigned calchash(void) const; ex expand(unsigned options=0) const; - + // new virtual functions which can be overridden by derived classes protected: virtual ex thisexpairseq(const epvector & v, const ex & oc) const; @@ -145,11 +140,9 @@ protected: void construct_from_epvector(const epvector & v); void make_flat(const exvector & v); void make_flat(const epvector & v); - epvector * bubblesort(epvector::iterator itbegin, epvector::iterator itend); - epvector * mergesort(epvector::iterator itbegin, epvector::iterator itend); void canonicalize(void); void combine_same_terms_sorted_seq(void); -#ifdef EXPAIRSEQ_USE_HASHTAB +#if EXPAIRSEQ_USE_HASHTAB void combine_same_terms(void); unsigned calc_hashtabsize(unsigned sz) const; unsigned calc_hashindex(const ex & e) const; @@ -169,7 +162,7 @@ protected: bool has_coeff_0(void) const; void add_numerics_to_hashtab(epvector::iterator first_numeric, epvector::const_iterator last_non_zero); -#endif // def EXPAIRSEQ_USE_HASHTAB +#endif // EXPAIRSEQ_USE_HASHTAB bool is_canonical() const; epvector * expandchildren(unsigned options) const; epvector * evalchildren(int level) const; @@ -184,14 +177,14 @@ protected: epvector seq; ex overall_coeff; static unsigned precedence; -#ifdef EXPAIRSEQ_USE_HASHTAB +#if EXPAIRSEQ_USE_HASHTAB epplistvector hashtab; unsigned hashtabsize; unsigned hashmask; static unsigned maxhashtabsize; static unsigned minhashtabsize; static unsigned hashtabfactor; -#endif // def EXPAIRSEQ_USE_HASHTAB +#endif // EXPAIRSEQ_USE_HASHTAB }; // utility functions @@ -200,8 +193,6 @@ inline const expairseq &ex_to_expairseq(const ex &e) return static_cast(*e.bp); } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_EXPAIRSEQ_H__ diff --git a/ginac/exprseq_suppl.cpp b/ginac/exprseq_suppl.cpp index acd65c95..cf7de6e0 100644 --- a/ginac/exprseq_suppl.cpp +++ b/ginac/exprseq_suppl.cpp @@ -1,7 +1,7 @@ /** @file exprseq_suppl.cpp * - * Supplement to exprseq.cpp, contains the parts which were - * not automatically generated. */ + * Supplement to exprseq.cpp, contains the parts which were not automatically + * generated. */ /* * GiNaC Copyright (C) 1999-2001 Johannes Gutenberg University Mainz, Germany @@ -24,9 +24,7 @@ #include "exprseq.h" #include "ex.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC bool exprseq::info(unsigned inf) const { @@ -39,10 +37,8 @@ ex & exprseq::let_op(int i) { GINAC_ASSERT(i>=0); GINAC_ASSERT(i(*e.bp); } -#ifndef NO_NAMESPACE_GINAC - #define is_ex_the_function(OBJ, FUNCNAME) \\ (is_ex_exactly_of_type(OBJ, function) && static_cast(OBJ.bp)->getserial() == function_index_##FUNCNAME) -#else // ndef NO_NAMESPACE_GINAC - -#define is_ex_the_function(OBJ, FUNCNAME) \\ - (is_ex_exactly_of_type(OBJ, function) && static_cast(OBJ.bp)->getserial() == function_index_##FUNCNAME) - -#endif // ndef NO_NAMESPACE_GINAC - // global constants extern const function some_function; extern const std::type_info & typeid_function; -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_FUNCTION_H__ @@ -505,9 +430,7 @@ $implementation=<op(i).gethash(); + } + v &= 0x7FFFFFFFU; + if (flags & status_flags::evaluated) { + setflag(status_flags::hash_calculated); + hashvalue = v; + } + return v; +} + ex function::thisexprseq(const exvector & v) const { return function(serial,v); @@ -1043,9 +981,7 @@ unsigned function::find_function(const std::string &name, unsigned nparams) const function some_function; const std::type_info & typeid_function=typeid(some_function); -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC END_OF_IMPLEMENTATION diff --git a/ginac/idx.cpp b/ginac/idx.cpp index 480da0f2..3c378840 100644 --- a/ginac/idx.cpp +++ b/ginac/idx.cpp @@ -30,9 +30,7 @@ #include "utils.h" #include "debugmsg.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC GINAC_IMPLEMENT_REGISTERED_CLASS(idx, basic) @@ -527,6 +525,4 @@ ex subs_indices(const ex & e, const exvector & idxv_subs, const exvector & idxv_ return res; } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/idx.h b/ginac/idx.h index 3c8ec34e..66e2502a 100644 --- a/ginac/idx.h +++ b/ginac/idx.h @@ -28,9 +28,7 @@ #include "basic.h" #include "ex.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC /** This class holds one index of an indexed object. Indices can be symbolic @@ -105,8 +103,6 @@ unsigned subs_index_in_exvector(exvector & v, const ex & is, const ex & ir); ex subs_indices(const ex & e, const exvector & idxv_contra, const exvector & idxv_co); unsigned count_index(const ex & e, const ex & i); -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_IDX_H__ diff --git a/ginac/indexed.cpp b/ginac/indexed.cpp index be4a7cb7..9456f38c 100644 --- a/ginac/indexed.cpp +++ b/ginac/indexed.cpp @@ -27,9 +27,7 @@ #include "idx.h" #include "debugmsg.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC GINAC_IMPLEMENT_REGISTERED_CLASS(indexed, exprseq) @@ -310,6 +308,4 @@ bool indexed::all_of_type_idx(void) const return true; } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/indexed.h b/ginac/indexed.h index cc604f13..94ba0e68 100644 --- a/ginac/indexed.h +++ b/ginac/indexed.h @@ -26,9 +26,7 @@ #include #include "exprseq.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC /** Base class for objects with indices. */ @@ -84,8 +82,6 @@ inline const indexed &ex_to_indexed(const ex &e) return static_cast(*e.bp); } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_INDEXED_H__ diff --git a/ginac/inifcns.cpp b/ginac/inifcns.cpp index d5c90e1d..fbdceb70 100644 --- a/ginac/inifcns.cpp +++ b/ginac/inifcns.cpp @@ -37,9 +37,7 @@ #include "symbol.h" #include "utils.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC ////////// // absolute value @@ -527,6 +525,4 @@ ex ncpower(const ex &basis, unsigned exponent) unsigned force_include_tgamma = function_index_tgamma; unsigned force_include_zeta1 = function_index_zeta1; -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/inifcns.h b/ginac/inifcns.h index eaf84883..73fff216 100644 --- a/ginac/inifcns.h +++ b/ginac/inifcns.h @@ -26,9 +26,7 @@ #include "function.h" #include "ex.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC /** Absolute value. */ DECLARE_FUNCTION_1P(abs) @@ -142,8 +140,6 @@ inline bool is_order_function(const ex & e) return is_ex_the_function(e, Order); } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_INIFCNS_H__ diff --git a/ginac/inifcns_gamma.cpp b/ginac/inifcns_gamma.cpp index d180065d..57dbeb3d 100644 --- a/ginac/inifcns_gamma.cpp +++ b/ginac/inifcns_gamma.cpp @@ -33,9 +33,7 @@ #include "symbol.h" #include "utils.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC ////////// // Logarithm of Gamma function @@ -546,6 +544,4 @@ const unsigned function_index_psi2 = overloaded(2)); -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/inifcns_trans.cpp b/ginac/inifcns_trans.cpp index cceaad99..dbbb122c 100644 --- a/ginac/inifcns_trans.cpp +++ b/ginac/inifcns_trans.cpp @@ -34,9 +34,7 @@ #include "pseries.h" #include "utils.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC ////////// // exponential function @@ -1055,6 +1053,4 @@ REGISTER_FUNCTION(atanh, eval_func(atanh_eval). series_func(atanh_series)); -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/inifcns_zeta.cpp b/ginac/inifcns_zeta.cpp index a39d8e6a..0f069089 100644 --- a/ginac/inifcns_zeta.cpp +++ b/ginac/inifcns_zeta.cpp @@ -30,9 +30,7 @@ #include "symbol.h" #include "utils.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC ////////// // Riemann's Zeta-function @@ -120,6 +118,4 @@ const unsigned function_index_zeta2 = derivative_func(zeta2_deriv). overloaded(2)); -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/input_lexer.h b/ginac/input_lexer.h index dfb221e5..0b4f8bd6 100644 --- a/ginac/input_lexer.h +++ b/ginac/input_lexer.h @@ -43,9 +43,7 @@ extern char *ginac_yytext; extern char ginac_yytext[]; #endif -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC class ex; @@ -67,8 +65,6 @@ extern ex parsed_ex; /** Get error message from the parser. */ extern std::string get_parser_error(void); -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_INPUT_LEXER_H__ diff --git a/ginac/isospin.cpp b/ginac/isospin.cpp index 1be79d59..2a2a254d 100644 --- a/ginac/isospin.cpp +++ b/ginac/isospin.cpp @@ -31,9 +31,7 @@ #include "utils.h" #include "debugmsg.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC GINAC_IMPLEMENT_REGISTERED_CLASS(isospin, indexed) @@ -214,9 +212,7 @@ std::string & isospin::autoname_prefix(void) // private -unsigned isospin::next_serial=0; +unsigned isospin::next_serial = 0; -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/isospin.h b/ginac/isospin.h index d9d93a84..925ef63b 100644 --- a/ginac/isospin.h +++ b/ginac/isospin.h @@ -26,9 +26,7 @@ #include #include "indexed.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC /** Base class for isospin object */ class isospin : public indexed @@ -74,8 +72,6 @@ inline const isospin &ex_to_isospin(const ex &e) return static_cast(*e.bp); } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_ISOSPIN_H__ diff --git a/ginac/lorentzidx.cpp b/ginac/lorentzidx.cpp index ca88d94a..783316c4 100644 --- a/ginac/lorentzidx.cpp +++ b/ginac/lorentzidx.cpp @@ -29,9 +29,7 @@ #include "utils.h" #include "debugmsg.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC GINAC_IMPLEMENT_REGISTERED_CLASS(lorentzidx, idx) @@ -296,6 +294,4 @@ ex Dim(void) return *d; } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/lorentzidx.h b/ginac/lorentzidx.h index 20be2b50..d4226e1b 100644 --- a/ginac/lorentzidx.h +++ b/ginac/lorentzidx.h @@ -27,9 +27,7 @@ #include #include "idx.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC /** Class of indices for Lorentz tensors, to tell them apart from other @@ -91,8 +89,6 @@ inline const lorentzidx &ex_to_lorentzidx(const ex &e) ex Dim(void); -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_LORENTZIDX_H__ diff --git a/ginac/lortensor.cpp b/ginac/lortensor.cpp index e8f4f873..1dae91a6 100644 --- a/ginac/lortensor.cpp +++ b/ginac/lortensor.cpp @@ -40,9 +40,7 @@ #include "utils.h" #include "config.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC GINAC_IMPLEMENT_REGISTERED_CLASS(lortensor, indexed) @@ -554,7 +552,7 @@ ex simplify_lortensor_mul(const ex & m) ex simplify_lortensor(const ex & e) { // all simplification is done on expanded objects - ex e_expanded=e.expand(); + ex e_expanded = e.expand(); // simplification of sum=sum of simplifications if (is_ex_exactly_of_type(e_expanded,add)) { @@ -574,6 +572,4 @@ ex simplify_lortensor(const ex & e) return e_expanded; } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/lortensor.h b/ginac/lortensor.h index 8da739d8..8fbadd3d 100644 --- a/ginac/lortensor.h +++ b/ginac/lortensor.h @@ -29,9 +29,7 @@ #include "indexed.h" #include "lorentzidx.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC /** This class holds an object carrying Lorentz indices (of class @@ -48,8 +46,8 @@ class lortensor : public indexed friend lortensor lortensor_delta(const ex & mu, const ex & nu); friend lortensor lortensor_epsilon(const ex & mu, const ex & nu, const ex & rho, const ex & sigma); - friend lortensor lortensor_vector(const string & n, const ex & mu); - friend lortensor lortensor_symbolic(const string & name, const exvector & iv); + friend lortensor lortensor_vector(const std::string & n, const ex & mu); + friend lortensor lortensor_symbolic(const std::string & name, const exvector & iv); friend ex simplify_lortensor_mul(const ex & m); friend ex simplify_lortensor(const ex & e); @@ -130,14 +128,12 @@ lortensor lortensor_g(const ex & mu, const ex & nu); lortensor lortensor_delta(const ex & mu, const ex & nu); lortensor lortensor_epsilon(const ex & mu, const ex & nu, const ex & rho, const ex & sigma); -lortensor lortensor_vector(const string & n, const ex & mu); -lortensor lortensor_symbolic(const string & name, const exvector & iv); +lortensor lortensor_vector(const std::string & n, const ex & mu); +lortensor lortensor_symbolic(const std::string & name, const exvector & iv); ex simplify_lortensor_mul(const ex & m); ex simplify_lortensor(const ex & e); -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_LORTENSOR_H__ diff --git a/ginac/lst_suppl.cpp b/ginac/lst_suppl.cpp index ae8df024..36b6d149 100644 --- a/ginac/lst_suppl.cpp +++ b/ginac/lst_suppl.cpp @@ -1,7 +1,7 @@ /** @file lst_suppl.cpp * - * Supplement to lst.cpp, contains the parts which were - * not automatically generated. */ + * Supplement to lst.cpp, contains the parts which were not automatically + * generated. */ /* * GiNaC Copyright (C) 1999-2001 Johannes Gutenberg University Mainz, Germany @@ -23,9 +23,7 @@ #include "lst.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC bool lst::info(unsigned inf) const { @@ -33,6 +31,4 @@ bool lst::info(unsigned inf) const return basic::info(inf); } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/matrix.cpp b/ginac/matrix.cpp index 81d31bdb..0c32a767 100644 --- a/ginac/matrix.cpp +++ b/ginac/matrix.cpp @@ -34,15 +34,12 @@ #include "symbol.h" #include "normal.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC GINAC_IMPLEMENT_REGISTERED_CLASS(matrix, basic) ////////// -// default constructor, destructor, copy constructor, assignment operator -// and helpers: +// default ctor, dtor, copy ctor, assignment operator and helpers: ////////// // public @@ -50,12 +47,13 @@ GINAC_IMPLEMENT_REGISTERED_CLASS(matrix, basic) /** Default ctor. Initializes to 1 x 1-dimensional zero-matrix. */ matrix::matrix() : inherited(TINFO_matrix), row(1), col(1) { - debugmsg("matrix default constructor",LOGLEVEL_CONSTRUCT); + debugmsg("matrix default ctor",LOGLEVEL_CONSTRUCT); m.push_back(_ex0()); } // protected +/** For use by copy ctor and assignment operator. */ void matrix::copy(const matrix & other) { inherited::copy(other); @@ -70,7 +68,7 @@ void matrix::destroy(bool call_parent) } ////////// -// other constructors +// other ctors ////////// // public @@ -82,7 +80,7 @@ void matrix::destroy(bool call_parent) matrix::matrix(unsigned r, unsigned c) : inherited(TINFO_matrix), row(r), col(c) { - debugmsg("matrix constructor from unsigned,unsigned",LOGLEVEL_CONSTRUCT); + debugmsg("matrix ctor from unsigned,unsigned",LOGLEVEL_CONSTRUCT); m.resize(r*c, _ex0()); } @@ -92,7 +90,7 @@ matrix::matrix(unsigned r, unsigned c) matrix::matrix(unsigned r, unsigned c, const exvector & m2) : inherited(TINFO_matrix), row(r), col(c), m(m2) { - debugmsg("matrix constructor from unsigned,unsigned,exvector",LOGLEVEL_CONSTRUCT); + debugmsg("matrix ctor from unsigned,unsigned,exvector",LOGLEVEL_CONSTRUCT); } ////////// @@ -102,7 +100,7 @@ matrix::matrix(unsigned r, unsigned c, const exvector & m2) /** Construct object from archive_node. */ matrix::matrix(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) { - debugmsg("matrix constructor from archive_node", LOGLEVEL_CONSTRUCT); + debugmsg("matrix ctor from archive_node", LOGLEVEL_CONSTRUCT); if (!(n.find_unsigned("row", row)) || !(n.find_unsigned("col", col))) throw (std::runtime_error("unknown matrix dimensions in archive")); m.reserve(row * col); @@ -1192,6 +1190,4 @@ ex lst_to_matrix(const ex &l) return m; } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/matrix.h b/ginac/matrix.h index c04a592e..02203e05 100644 --- a/ginac/matrix.h +++ b/ginac/matrix.h @@ -27,20 +27,18 @@ #include "basic.h" #include "ex.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC /** Symbolic matrices. */ class matrix : public basic { GINAC_DECLARE_REGISTERED_CLASS(matrix, basic) - - // other constructors + + // other ctors public: matrix(unsigned r, unsigned c); matrix(unsigned r, unsigned c, const exvector & m2); - + // functions overriding virtual functions from bases classes public: void print(std::ostream & os, unsigned upper_precedence=0) const; @@ -60,9 +58,9 @@ protected: // non-virtual functions in this class public: - unsigned rows(void) const //! Get number of rows. + unsigned rows(void) const /// Get number of rows. { return row; } - unsigned cols(void) const //! Get number of columns. + unsigned cols(void) const /// Get number of columns. { return col; } matrix add(const matrix & other) const; matrix sub(const matrix & other) const; @@ -85,9 +83,9 @@ protected: // member variables protected: - unsigned row; /**< number of rows */ - unsigned col; /**< number of columns */ - exvector m; /**< representation (cols indexed first) */ + unsigned row; ///< number of rows + unsigned col; ///< number of columns + exvector m; ///< representation (cols indexed first) static unsigned precedence; }; @@ -138,8 +136,6 @@ inline const matrix &ex_to_matrix(const ex &e) extern ex lst_to_matrix(const ex &l); -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_MATRIX_H__ diff --git a/ginac/mul.cpp b/ginac/mul.cpp index 02029c54..70c161c2 100644 --- a/ginac/mul.cpp +++ b/ginac/mul.cpp @@ -30,26 +30,25 @@ #include "debugmsg.h" #include "utils.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC GINAC_IMPLEMENT_REGISTERED_CLASS(mul, expairseq) ////////// -// default constructor, destructor, copy constructor assignment operator and helpers +// default ctor, dctor, copy ctor assignment operator and helpers ////////// // public mul::mul() { - debugmsg("mul default constructor",LOGLEVEL_CONSTRUCT); + debugmsg("mul default ctor",LOGLEVEL_CONSTRUCT); tinfo_key = TINFO_mul; } // protected +/** For use by copy ctor and assignment operator. */ void mul::copy(const mul & other) { inherited::copy(other); @@ -61,14 +60,14 @@ void mul::destroy(bool call_parent) } ////////// -// other constructors +// other ctors ////////// // public mul::mul(const ex & lh, const ex & rh) { - debugmsg("mul constructor from ex,ex",LOGLEVEL_CONSTRUCT); + debugmsg("mul ctor from ex,ex",LOGLEVEL_CONSTRUCT); tinfo_key = TINFO_mul; overall_coeff = _ex1(); construct_from_2_ex(lh,rh); @@ -77,7 +76,7 @@ mul::mul(const ex & lh, const ex & rh) mul::mul(const exvector & v) { - debugmsg("mul constructor from exvector",LOGLEVEL_CONSTRUCT); + debugmsg("mul ctor from exvector",LOGLEVEL_CONSTRUCT); tinfo_key = TINFO_mul; overall_coeff = _ex1(); construct_from_exvector(v); @@ -86,7 +85,7 @@ mul::mul(const exvector & v) mul::mul(const epvector & v) { - debugmsg("mul constructor from epvector",LOGLEVEL_CONSTRUCT); + debugmsg("mul ctor from epvector",LOGLEVEL_CONSTRUCT); tinfo_key = TINFO_mul; overall_coeff = _ex1(); construct_from_epvector(v); @@ -95,7 +94,7 @@ mul::mul(const epvector & v) mul::mul(const epvector & v, const ex & oc) { - debugmsg("mul constructor from epvector,ex",LOGLEVEL_CONSTRUCT); + debugmsg("mul ctor from epvector,ex",LOGLEVEL_CONSTRUCT); tinfo_key = TINFO_mul; overall_coeff = oc; construct_from_epvector(v); @@ -104,7 +103,7 @@ mul::mul(const epvector & v, const ex & oc) mul::mul(epvector * vp, const ex & oc) { - debugmsg("mul constructor from epvector *,ex",LOGLEVEL_CONSTRUCT); + debugmsg("mul ctor from epvector *,ex",LOGLEVEL_CONSTRUCT); tinfo_key = TINFO_mul; GINAC_ASSERT(vp!=0); overall_coeff = oc; @@ -115,7 +114,7 @@ mul::mul(epvector * vp, const ex & oc) mul::mul(const ex & lh, const ex & mh, const ex & rh) { - debugmsg("mul constructor from ex,ex,ex",LOGLEVEL_CONSTRUCT); + debugmsg("mul ctor from ex,ex,ex",LOGLEVEL_CONSTRUCT); tinfo_key = TINFO_mul; exvector factors; factors.reserve(3); @@ -134,7 +133,7 @@ mul::mul(const ex & lh, const ex & mh, const ex & rh) /** Construct object from archive_node. */ mul::mul(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) { - debugmsg("mul constructor from archive_node", LOGLEVEL_CONSTRUCT); + debugmsg("mul ctor from archive_node", LOGLEVEL_CONSTRUCT); } /** Unarchive the object. */ @@ -159,7 +158,7 @@ void mul::print(std::ostream & os, unsigned upper_precedence) const { debugmsg("mul print",LOGLEVEL_PRINT); if (precedence<=upper_precedence) os << "("; - bool first=true; + bool first = true; // first print the overall numeric coefficient: numeric coeff = ex_to_numeric(overall_coeff); if (coeff.csgn()==-1) os << '-'; @@ -276,8 +275,6 @@ bool mul::info(unsigned inf) const return inherited::info(inf); } -typedef std::vector intvector; - int mul::degree(const symbol & s) const { int deg_sum = 0; @@ -342,54 +339,53 @@ ex mul::eval(int level) const // *(+(x,y,...);c) -> *(+(*(x,c),*(y,c),...)) (c numeric()) // *(x;1) -> x // *(;c) -> c - + debugmsg("mul eval",LOGLEVEL_MEMBER_FUNCTION); - - epvector * evaled_seqp=evalchildren(level); + + epvector * evaled_seqp = evalchildren(level); if (evaled_seqp!=0) { // do more evaluation later return (new mul(evaled_seqp,overall_coeff))-> - setflag(status_flags::dynallocated); + setflag(status_flags::dynallocated); } - + #ifdef DO_GINAC_ASSERT for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { - GINAC_ASSERT((!is_ex_exactly_of_type((*cit).rest,mul))|| - (!(ex_to_numeric((*cit).coeff).is_integer()))); - GINAC_ASSERT(!((*cit).is_numeric_with_coeff_1())); - if (is_ex_exactly_of_type(recombine_pair_to_ex(*cit),numeric)) { - printtree(cerr,0); - } + GINAC_ASSERT((!is_ex_exactly_of_type((*cit).rest,mul)) || + (!(ex_to_numeric((*cit).coeff).is_integer()))); + GINAC_ASSERT(!(cit->is_canonical_numeric())); + if (is_ex_exactly_of_type(recombine_pair_to_ex(*cit),numeric)) + printtree(std::cerr,0); GINAC_ASSERT(!is_ex_exactly_of_type(recombine_pair_to_ex(*cit),numeric)); /* for paranoia */ - expair p=split_ex_to_pair(recombine_pair_to_ex(*cit)); + expair p = split_ex_to_pair(recombine_pair_to_ex(*cit)); GINAC_ASSERT(p.rest.is_equal((*cit).rest)); GINAC_ASSERT(p.coeff.is_equal((*cit).coeff)); /* end paranoia */ } #endif // def DO_GINAC_ASSERT - + if (flags & status_flags::evaluated) { GINAC_ASSERT(seq.size()>0); - GINAC_ASSERT((seq.size()>1)||!overall_coeff.is_equal(_ex1())); + GINAC_ASSERT(seq.size()>1 || !overall_coeff.is_equal(_ex1())); return *this; } - - int seq_size=seq.size(); + + int seq_size = seq.size(); if (overall_coeff.is_equal(_ex0())) { // *(...,x;0) -> 0 return _ex0(); } else if (seq_size==0) { // *(;c) -> c return overall_coeff; - } else if ((seq_size==1)&&overall_coeff.is_equal(_ex1())) { + } else if (seq_size==1 && overall_coeff.is_equal(_ex1())) { // *(x;1) -> x return recombine_pair_to_ex(*(seq.begin())); } else if ((seq_size==1) && is_ex_exactly_of_type((*seq.begin()).rest,add) && ex_to_numeric((*seq.begin()).coeff).is_equal(_num1())) { // *(+(x,y,...);c) -> +(*(x,c),*(y,c),...) (c numeric(), no powers of +()) - const add & addref=ex_to_add((*seq.begin()).rest); + const add & addref = ex_to_add((*seq.begin()).rest); epvector distrseq; distrseq.reserve(addref.seq.size()); for (epvector::const_iterator cit=addref.seq.begin(); cit!=addref.seq.end(); ++cit) { @@ -429,9 +425,8 @@ exvector mul::get_indices(void) const for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { exvector subiv=(*cit).rest.get_indices(); iv.reserve(iv.size()+subiv.size()); - for (exvector::const_iterator cit2=subiv.begin(); cit2!=subiv.end(); ++cit2) { + for (exvector::const_iterator cit2=subiv.begin(); cit2!=subiv.end(); ++cit2) iv.push_back(*cit2); - } } return iv; } @@ -476,11 +471,11 @@ unsigned mul::return_type(void) const // mul without factors: should not happen, but commutes return return_types::commutative; } - + bool all_commutative = 1; unsigned rt; epvector::const_iterator cit_noncommutative_element; // point to first found nc element - + for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { rt=(*cit).rest.return_type(); if (rt==return_types::noncommutative_composite) return rt; // one ncc -> mul also ncc @@ -503,15 +498,13 @@ unsigned mul::return_type(void) const unsigned mul::return_type_tinfo(void) const { - if (seq.size()==0) { - // mul without factors: should not happen - return tinfo_key; - } + if (seq.size()==0) + return tinfo_key; // mul without factors: should not happen + // return type_info of first noncommutative element for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { - if ((*cit).rest.return_type()==return_types::noncommutative) { + if ((*cit).rest.return_type()==return_types::noncommutative) return (*cit).rest.return_type_tinfo(); - } } // no noncommutative element found, should not happen return tinfo_key; @@ -530,10 +523,9 @@ ex mul::thisexpairseq(epvector * vp, const ex & oc) const expair mul::split_ex_to_pair(const ex & e) const { if (is_ex_exactly_of_type(e,power)) { - const power & powerref=ex_to_power(e); - if (is_ex_exactly_of_type(powerref.exponent,numeric)) { + const power & powerref = ex_to_power(e); + if (is_ex_exactly_of_type(powerref.exponent,numeric)) return expair(powerref.basis,powerref.exponent); - } } return expair(e,_ex1()); } @@ -577,14 +569,14 @@ bool mul::expair_needs_further_processing(epp it) if (is_ex_exactly_of_type((*it).rest,mul) && ex_to_numeric((*it).coeff).is_integer()) { // combined pair is product with integer power -> expand it - *it=split_ex_to_pair(recombine_pair_to_ex(*it)); + *it = split_ex_to_pair(recombine_pair_to_ex(*it)); return true; } if (is_ex_exactly_of_type((*it).rest,numeric)) { expair ep=split_ex_to_pair(recombine_pair_to_ex(*it)); if (!ep.is_equal(*it)) { // combined pair is a numeric power which can be simplified - *it=ep; + *it = ep; return true; } if (ex_to_numeric((*it).coeff).is_equal(_num1())) { @@ -630,7 +622,6 @@ ex mul::expand(unsigned options) const return *this; exvector sub_expanded_seq; - intvector positions_of_adds; epvector * expanded_seqp = expandchildren(options); @@ -641,7 +632,7 @@ ex mul::expand(unsigned options) const non_adds.reserve(expanded_seq.size()); epvector::const_iterator cit = expanded_seq.begin(); epvector::const_iterator last = expanded_seq.end(); - ex last_expanded=_ex1(); + ex last_expanded = _ex1(); while (cit!=last) { if (is_ex_exactly_of_type((*cit).rest,add) && ((*cit).coeff.is_equal(_ex1()))) { @@ -699,6 +690,14 @@ ex mul::expand(unsigned options) const // non-virtual functions in this class ////////// + +/** Member-wise expand the expairs representing this sequence. This must be + * overridden from expairseq::expandchildren() and done iteratively in order + * to allow for early cancallations and thus safe memory. + * + * @see mul::expand() + * @return pointer to epvector containing expanded representation or zero + * pointer, if sequence is unchanged. */ epvector * mul::expandchildren(unsigned options) const { epvector::const_iterator last = seq.end(); @@ -709,7 +708,7 @@ epvector * mul::expandchildren(unsigned options) const if (!are_ex_trivially_equal(factor,expanded_factor)) { // something changed, copy seq, eval and return it - epvector *s=new epvector; + epvector *s = new epvector; s->reserve(seq.size()); // copy parts of seq which are known not to have changed @@ -733,7 +732,7 @@ epvector * mul::expandchildren(unsigned options) const return 0; // nothing has changed } - + ////////// // static member variables ////////// @@ -742,6 +741,4 @@ epvector * mul::expandchildren(unsigned options) const unsigned mul::precedence = 50; -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/mul.h b/ginac/mul.h index cad3b9b3..dba5daf1 100644 --- a/ginac/mul.h +++ b/ginac/mul.h @@ -25,20 +25,18 @@ #include "expairseq.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC /** Product of expressions. */ class mul : public expairseq { GINAC_DECLARE_REGISTERED_CLASS(mul, expairseq) - + friend class add; friend class ncmul; friend class power; - - // other constructors + + // other ctors public: mul(const ex & lh, const ex & rh); mul(const exvector & v); @@ -46,7 +44,7 @@ public: mul(const epvector & v, const ex & oc); mul(epvector * vp, const ex & oc); mul(const ex & lh, const ex & mh, const ex & rh); - + // functions overriding virtual functions from bases classes public: void print(std::ostream & os, unsigned upper_precedence) const; @@ -87,13 +85,13 @@ protected: // new virtual functions which can be overridden by derived classes // none - + // non-virtual functions in this class protected: epvector * expandchildren(unsigned options) const; - + // member variables - + protected: static unsigned precedence; }; @@ -104,8 +102,6 @@ inline const mul &ex_to_mul(const ex &e) return static_cast(*e.bp); } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_MUL_H__ diff --git a/ginac/ncmul.cpp b/ginac/ncmul.cpp index 86501111..745cf96b 100644 --- a/ginac/ncmul.cpp +++ b/ginac/ncmul.cpp @@ -32,9 +32,7 @@ #include "debugmsg.h" #include "utils.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC GINAC_IMPLEMENT_REGISTERED_CLASS(ncmul, exprseq) @@ -596,7 +594,7 @@ const exvector & ncmul::get_factors(void) const // protected -unsigned ncmul::precedence=50; +unsigned ncmul::precedence = 50; ////////// // friend functions @@ -618,6 +616,4 @@ ex simplified_ncmul(const exvector & v) status_flags::evaluated); } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/ncmul.h b/ginac/ncmul.h index 5373a75b..cc186a0a 100644 --- a/ginac/ncmul.h +++ b/ginac/ncmul.h @@ -25,9 +25,7 @@ #include "exprseq.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC /** Non-commutative product of expressions. */ class ncmul : public exprseq @@ -101,8 +99,6 @@ inline const ncmul &ex_to_ncmul(const ex &e) return static_cast (*e.bp); } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_NCMUL_H__ diff --git a/ginac/normal.cpp b/ginac/normal.cpp index 3eaf4206..c1698ff7 100644 --- a/ginac/normal.cpp +++ b/ginac/normal.cpp @@ -23,7 +23,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include #include #include @@ -45,9 +44,7 @@ #include "symbol.h" #include "utils.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC // If comparing expressions (ex::compare()) is fast, you can set this to 1. // Some routines like quo(), rem() and gcd() will then return a quick answer @@ -621,9 +618,10 @@ typedef std::pair ex2; typedef std::pair exbool; struct ex2_less { - bool operator() (const ex2 p, const ex2 q) const + bool operator() (const ex2 &p, const ex2 &q) const { - return p.first.compare(q.first) < 0 || (!(q.first.compare(p.first) < 0) && p.second.compare(q.second) < 0); + int cmp = p.first.compare(q.first); + return ((cmp<0) || (!(cmp>0) && p.second.compare(q.second)<0)); } }; @@ -1183,6 +1181,8 @@ numeric ex::max_coefficient(void) const return bp->max_coefficient(); } +/** Implementation ex::max_coefficient(). + * @see heur_gcd */ numeric basic::max_coefficient(void) const { return _num1(); @@ -1245,11 +1245,7 @@ ex basic::smod(const numeric &xi) const ex numeric::smod(const numeric &xi) const { -#ifndef NO_NAMESPACE_GINAC return GiNaC::smod(*this, xi); -#else // ndef NO_NAMESPACE_GINAC - return ::smod(*this, xi); -#endif // ndef NO_NAMESPACE_GINAC } ex add::smod(const numeric &xi) const @@ -1260,21 +1256,13 @@ ex add::smod(const numeric &xi) const epvector::const_iterator itend = seq.end(); while (it != itend) { GINAC_ASSERT(!is_ex_exactly_of_type(it->rest,numeric)); -#ifndef NO_NAMESPACE_GINAC numeric coeff = GiNaC::smod(ex_to_numeric(it->coeff), xi); -#else // ndef NO_NAMESPACE_GINAC - numeric coeff = ::smod(ex_to_numeric(it->coeff), xi); -#endif // ndef NO_NAMESPACE_GINAC if (!coeff.is_zero()) newseq.push_back(expair(it->rest, coeff)); it++; } GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric)); -#ifndef NO_NAMESPACE_GINAC numeric coeff = GiNaC::smod(ex_to_numeric(overall_coeff), xi); -#else // ndef NO_NAMESPACE_GINAC - numeric coeff = ::smod(ex_to_numeric(overall_coeff), xi); -#endif // ndef NO_NAMESPACE_GINAC return (new add(newseq,coeff))->setflag(status_flags::dynallocated); } @@ -1290,11 +1278,7 @@ ex mul::smod(const numeric &xi) const #endif // def DO_GINAC_ASSERT mul * mulcopyp=new mul(*this); GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric)); -#ifndef NO_NAMESPACE_GINAC mulcopyp->overall_coeff = GiNaC::smod(ex_to_numeric(overall_coeff),xi); -#else // ndef NO_NAMESPACE_GINAC - mulcopyp->overall_coeff = ::smod(ex_to_numeric(overall_coeff),xi); -#endif // ndef NO_NAMESPACE_GINAC mulcopyp->clearflag(status_flags::evaluated); mulcopyp->clearflag(status_flags::hash_calculated); return mulcopyp->setflag(status_flags::dynallocated); @@ -2064,8 +2048,8 @@ ex power::normal(lst &sym_lst, lst &repl_lst, int level) const } -/** Implementation of ex::normal() for pseries. It normalizes each coefficient and - * replaces the series by a temporary symbol. +/** Implementation of ex::normal() for pseries. It normalizes each coefficient + * and replaces the series by a temporary symbol. * @see ex::normal */ ex pseries::normal(lst &sym_lst, lst &repl_lst, int level) const { @@ -2244,6 +2228,4 @@ ex ex::to_rational(lst &repl_lst) const } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/normal.h b/ginac/normal.h index b8424af6..b461dcf0 100644 --- a/ginac/normal.h +++ b/ginac/normal.h @@ -26,9 +26,7 @@ #ifndef __GINAC_NORMAL_H__ #define __GINAC_NORMAL_H__ -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC class ex; class symbol; @@ -54,8 +52,6 @@ extern ex lcm(const ex &a, const ex &b, bool check_args = true); // Square-free factorization of a polynomial a(x) extern ex sqrfree(const ex &a, const symbol &x); -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_NORMAL_H__ diff --git a/ginac/numeric.cpp b/ginac/numeric.cpp index 358ad45d..b40e71fc 100644 --- a/ginac/numeric.cpp +++ b/ginac/numeric.cpp @@ -63,14 +63,12 @@ #include #include -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC GINAC_IMPLEMENT_REGISTERED_CLASS(numeric, basic) ////////// -// default constructor, destructor, copy constructor assignment +// default ctor, dtor, copy ctor assignment // operator and helpers ////////// @@ -79,36 +77,34 @@ GINAC_IMPLEMENT_REGISTERED_CLASS(numeric, basic) /** default ctor. Numerically it initializes to an integer zero. */ numeric::numeric() : basic(TINFO_numeric) { - debugmsg("numeric default constructor", LOGLEVEL_CONSTRUCT); + debugmsg("numeric default ctor", LOGLEVEL_CONSTRUCT); value = cln::cl_I(0); - calchash(); - setflag(status_flags::evaluated | - status_flags::expanded | - status_flags::hash_calculated); + setflag(status_flags::evaluated | status_flags::expanded); } // protected -void numeric::copy(const numeric & other) +/** For use by copy ctor and assignment operator. */ +void numeric::copy(const numeric &other) { - basic::copy(other); + inherited::copy(other); value = other.value; } void numeric::destroy(bool call_parent) { - if (call_parent) basic::destroy(call_parent); + if (call_parent) inherited::destroy(call_parent); } ////////// -// other constructors +// other ctors ////////// // public numeric::numeric(int i) : basic(TINFO_numeric) { - debugmsg("numeric constructor from int",LOGLEVEL_CONSTRUCT); + debugmsg("numeric ctor from int",LOGLEVEL_CONSTRUCT); // Not the whole int-range is available if we don't cast to long // first. This is due to the behaviour of the cl_I-ctor, which // emphasizes efficiency. However, if the integer is small enough, @@ -118,16 +114,13 @@ numeric::numeric(int i) : basic(TINFO_numeric) value = cln::cl_I(i); else value = cln::cl_I((long) i); - calchash(); - setflag(status_flags::evaluated | - status_flags::expanded | - status_flags::hash_calculated); + setflag(status_flags::evaluated | status_flags::expanded); } numeric::numeric(unsigned int i) : basic(TINFO_numeric) { - debugmsg("numeric constructor from uint",LOGLEVEL_CONSTRUCT); + debugmsg("numeric ctor from uint",LOGLEVEL_CONSTRUCT); // Not the whole uint-range is available if we don't cast to ulong // first. This is due to the behaviour of the cl_I-ctor, which // emphasizes efficiency. However, if the integer is small enough, @@ -137,32 +130,23 @@ numeric::numeric(unsigned int i) : basic(TINFO_numeric) value = cln::cl_I(i); else value = cln::cl_I((unsigned long) i); - calchash(); - setflag(status_flags::evaluated | - status_flags::expanded | - status_flags::hash_calculated); + setflag(status_flags::evaluated | status_flags::expanded); } numeric::numeric(long i) : basic(TINFO_numeric) { - debugmsg("numeric constructor from long",LOGLEVEL_CONSTRUCT); + debugmsg("numeric ctor from long",LOGLEVEL_CONSTRUCT); value = cln::cl_I(i); - calchash(); - setflag(status_flags::evaluated | - status_flags::expanded | - status_flags::hash_calculated); + setflag(status_flags::evaluated | status_flags::expanded); } numeric::numeric(unsigned long i) : basic(TINFO_numeric) { - debugmsg("numeric constructor from ulong",LOGLEVEL_CONSTRUCT); + debugmsg("numeric ctor from ulong",LOGLEVEL_CONSTRUCT); value = cln::cl_I(i); - calchash(); - setflag(status_flags::evaluated | - status_flags::expanded | - status_flags::hash_calculated); + setflag(status_flags::evaluated | status_flags::expanded); } /** Ctor for rational numerics a/b. @@ -170,35 +154,30 @@ numeric::numeric(unsigned long i) : basic(TINFO_numeric) * @exception overflow_error (division by zero) */ numeric::numeric(long numer, long denom) : basic(TINFO_numeric) { - debugmsg("numeric constructor from long/long",LOGLEVEL_CONSTRUCT); + debugmsg("numeric ctor from long/long",LOGLEVEL_CONSTRUCT); if (!denom) throw std::overflow_error("division by zero"); value = cln::cl_I(numer) / cln::cl_I(denom); - calchash(); - setflag(status_flags::evaluated | - status_flags::expanded | - status_flags::hash_calculated); + setflag(status_flags::evaluated | status_flags::expanded); } numeric::numeric(double d) : basic(TINFO_numeric) { - debugmsg("numeric constructor from double",LOGLEVEL_CONSTRUCT); + debugmsg("numeric ctor from double",LOGLEVEL_CONSTRUCT); // We really want to explicitly use the type cl_LF instead of the // more general cl_F, since that would give us a cl_DF only which // will not be promoted to cl_LF if overflow occurs: value = cln::cl_float(d, cln::default_float_format); - calchash(); - setflag(status_flags::evaluated | - status_flags::expanded | - status_flags::hash_calculated); + setflag(status_flags::evaluated | status_flags::expanded); } + /** ctor from C-style string. It also accepts complex numbers in GiNaC * notation like "2+5*I". */ numeric::numeric(const char *s) : basic(TINFO_numeric) { - debugmsg("numeric constructor from string",LOGLEVEL_CONSTRUCT); + debugmsg("numeric ctor from string",LOGLEVEL_CONSTRUCT); cln::cl_N ctorval = 0; // parse complex numbers (functional but not completely safe, unfortunately // std::string does not understand regexpese): @@ -270,22 +249,17 @@ numeric::numeric(const char *s) : basic(TINFO_numeric) } } while(delim != std::string::npos); value = ctorval; - calchash(); - setflag(status_flags::evaluated | - status_flags::expanded | - status_flags::hash_calculated); + setflag(status_flags::evaluated | status_flags::expanded); } + /** Ctor from CLN types. This is for the initiated user or internal use * only. */ -numeric::numeric(const cln::cl_N & z) : basic(TINFO_numeric) +numeric::numeric(const cln::cl_N &z) : basic(TINFO_numeric) { - debugmsg("numeric constructor from cl_N", LOGLEVEL_CONSTRUCT); + debugmsg("numeric ctor from cl_N", LOGLEVEL_CONSTRUCT); value = z; - calchash(); - setflag(status_flags::evaluated | - status_flags::expanded | - status_flags::hash_calculated); + setflag(status_flags::evaluated | status_flags::expanded); } ////////// @@ -295,7 +269,7 @@ numeric::numeric(const cln::cl_N & z) : basic(TINFO_numeric) /** Construct object from archive_node. */ numeric::numeric(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) { - debugmsg("numeric constructor from archive_node", LOGLEVEL_CONSTRUCT); + debugmsg("numeric ctor from archive_node", LOGLEVEL_CONSTRUCT); cln::cl_N ctorval = 0; // Read number as string @@ -327,10 +301,7 @@ numeric::numeric(const archive_node &n, const lst &sym_lst) : inherited(n, sym_l } } value = ctorval; - calchash(); - setflag(status_flags::evaluated | - status_flags::expanded | - status_flags::hash_calculated); + setflag(status_flags::evaluated | status_flags::expanded); } /** Unarchive the object. */ @@ -388,7 +359,7 @@ void numeric::archive(archive_node &n) const * want to visibly distinguish from cl_LF. * * @see numeric::print() */ -static void print_real_number(std::ostream & os, const cln::cl_R & num) +static void print_real_number(std::ostream &os, const cln::cl_R &num) { cln::cl_print_flags ourflags; if (cln::instanceof(num, cln::cl_RA_ring)) { @@ -408,7 +379,7 @@ static void print_real_number(std::ostream & os, const cln::cl_R & num) * with the other routines and produces something compatible to ginsh input. * * @see print_real_number() */ -void numeric::print(std::ostream & os, unsigned upper_precedence) const +void numeric::print(std::ostream &os, unsigned upper_precedence) const { debugmsg("numeric print", LOGLEVEL_PRINT); cln::cl_R r = cln::realpart(cln::the(value)); @@ -473,7 +444,7 @@ void numeric::print(std::ostream & os, unsigned upper_precedence) const } -void numeric::printraw(std::ostream & os) const +void numeric::printraw(std::ostream &os) const { // The method printraw doesn't do much, it simply uses CLN's operator<<() // for output, which is ugly but reliable. e.g: 2+2i @@ -482,7 +453,7 @@ void numeric::printraw(std::ostream & os) const } -void numeric::printtree(std::ostream & os, unsigned indent) const +void numeric::printtree(std::ostream &os, unsigned indent) const { debugmsg("numeric printtree", LOGLEVEL_PRINT); os << std::string(indent,' ') << cln::the(value) @@ -493,7 +464,7 @@ void numeric::printtree(std::ostream & os, unsigned indent) const } -void numeric::printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const +void numeric::printcsrc(std::ostream &os, unsigned type, unsigned upper_precedence) const { debugmsg("numeric print csrc", LOGLEVEL_PRINT); std::ios::fmtflags oldflags = os.flags(); @@ -579,11 +550,11 @@ bool numeric::info(unsigned inf) const * results: (2+I).has(-2) -> true. But this is consistent, since we also * would like to have (-2+I).has(2) -> true and we want to think about the * sign as a multiplicative factor. */ -bool numeric::has(const ex & other) const +bool numeric::has(const ex &other) const { if (!is_exactly_of_type(*other.bp, numeric)) return false; - const numeric & o = static_cast(const_cast(*other.bp)); + const numeric &o = static_cast(const_cast(*other.bp)); if (this->is_equal(o) || this->is_equal(-o)) return true; if (o.imag().is_zero()) // e.g. scan for 3 in -3*I @@ -620,30 +591,21 @@ ex numeric::evalf(int level) const { // level can safely be discarded for numeric objects. return numeric(cln::cl_float(1.0, cln::default_float_format) * - (cln::the(value))); + (cln::the(value))); } // protected -/** Implementation of ex::diff() for a numeric. It always returns 0. - * - * @see ex::diff */ -ex numeric::derivative(const symbol & s) const -{ - return _ex0(); -} - - -int numeric::compare_same_type(const basic & other) const +int numeric::compare_same_type(const basic &other) const { GINAC_ASSERT(is_exactly_of_type(other, numeric)); - const numeric & o = static_cast(const_cast(other)); + const numeric &o = static_cast(const_cast(other)); return this->compare(o); } -bool numeric::is_equal_same_type(const basic & other) const +bool numeric::is_equal_same_type(const basic &other) const { GINAC_ASSERT(is_exactly_of_type(other,numeric)); const numeric *o = static_cast(&other); @@ -657,6 +619,7 @@ unsigned numeric::calchash(void) const // Use CLN's hashcode. Warning: It depends only on the number's value, not // its type or precision (i.e. a true equivalence relation on numbers). As // a consequence, 3 and 3.0 share the same hashvalue. + setflag(status_flags::hash_calculated); return (hashvalue = cln::equal_hashcode(cln::the(value)) | 0x80000000U); } @@ -674,8 +637,8 @@ unsigned numeric::calchash(void) const // public /** Numerical addition method. Adds argument to *this and returns result as - * a new numeric object. */ -const numeric numeric::add(const numeric & other) const + * a numeric object. */ +const numeric numeric::add(const numeric &other) const { // Efficiency shortcut: trap the neutral element by pointer. static const numeric * _num0p = &_num0(); @@ -689,16 +652,16 @@ const numeric numeric::add(const numeric & other) const /** Numerical subtraction method. Subtracts argument from *this and returns - * result as a new numeric object. */ -const numeric numeric::sub(const numeric & other) const + * result as a numeric object. */ +const numeric numeric::sub(const numeric &other) const { return numeric(cln::the(value)-cln::the(other.value)); } /** Numerical multiplication method. Multiplies *this and argument and returns - * result as a new numeric object. */ -const numeric numeric::mul(const numeric & other) const + * result as a numeric object. */ +const numeric numeric::mul(const numeric &other) const { // Efficiency shortcut: trap the neutral element by pointer. static const numeric * _num1p = &_num1(); @@ -712,10 +675,10 @@ const numeric numeric::mul(const numeric & other) const /** Numerical division method. Divides *this by argument and returns result as - * a new numeric object. + * a numeric object. * * @exception overflow_error (division by zero) */ -const numeric numeric::div(const numeric & other) const +const numeric numeric::div(const numeric &other) const { if (cln::zerop(cln::the(other.value))) throw std::overflow_error("numeric::div(): division by zero"); @@ -723,7 +686,9 @@ const numeric numeric::div(const numeric & other) const } -const numeric numeric::power(const numeric & other) const +/** Numerical exponentiation. Raises *this to the power given as argument and + * returns result as a numeric object. */ +const numeric numeric::power(const numeric &other) const { // Efficiency shortcut: trap the neutral exponent by pointer. static const numeric * _num1p = &_num1(); @@ -744,7 +709,7 @@ const numeric numeric::power(const numeric & other) const } -const numeric & numeric::add_dyn(const numeric & other) const +const numeric &numeric::add_dyn(const numeric &other) const { // Efficiency shortcut: trap the neutral element by pointer. static const numeric * _num0p = &_num0(); @@ -758,14 +723,14 @@ const numeric & numeric::add_dyn(const numeric & other) const } -const numeric & numeric::sub_dyn(const numeric & other) const +const numeric &numeric::sub_dyn(const numeric &other) const { return static_cast((new numeric(cln::the(value)-cln::the(other.value)))-> setflag(status_flags::dynallocated)); } -const numeric & numeric::mul_dyn(const numeric & other) const +const numeric &numeric::mul_dyn(const numeric &other) const { // Efficiency shortcut: trap the neutral element by pointer. static const numeric * _num1p = &_num1(); @@ -779,7 +744,7 @@ const numeric & numeric::mul_dyn(const numeric & other) const } -const numeric & numeric::div_dyn(const numeric & other) const +const numeric &numeric::div_dyn(const numeric &other) const { if (cln::zerop(cln::the(other.value))) throw std::overflow_error("division by zero"); @@ -788,7 +753,7 @@ const numeric & numeric::div_dyn(const numeric & other) const } -const numeric & numeric::power_dyn(const numeric & other) const +const numeric &numeric::power_dyn(const numeric &other) const { // Efficiency shortcut: trap the neutral exponent by pointer. static const numeric * _num1p=&_num1(); @@ -810,37 +775,37 @@ const numeric & numeric::power_dyn(const numeric & other) const } -const numeric & numeric::operator=(int i) +const numeric &numeric::operator=(int i) { return operator=(numeric(i)); } -const numeric & numeric::operator=(unsigned int i) +const numeric &numeric::operator=(unsigned int i) { return operator=(numeric(i)); } -const numeric & numeric::operator=(long i) +const numeric &numeric::operator=(long i) { return operator=(numeric(i)); } -const numeric & numeric::operator=(unsigned long i) +const numeric &numeric::operator=(unsigned long i) { return operator=(numeric(i)); } -const numeric & numeric::operator=(double d) +const numeric &numeric::operator=(double d) { return operator=(numeric(d)); } -const numeric & numeric::operator=(const char * s) +const numeric &numeric::operator=(const char * s) { return operator=(numeric(s)); } @@ -859,7 +824,7 @@ const numeric numeric::inverse(void) const * csgn(x)==0 for x==0, csgn(x)==1 for Re(x)>0 or Re(x)=0 and Im(x)>0, * csgn(x)==-1 for Re(x)<0 or Re(x)=0 and Im(x)<0. * - * @see numeric::compare(const numeric & other) */ + * @see numeric::compare(const numeric &other) */ int numeric::csgn(void) const { if (cln::zerop(cln::the(value))) @@ -886,7 +851,7 @@ int numeric::csgn(void) const * * @return csgn(*this-other) * @see numeric::csgn(void) */ -int numeric::compare(const numeric & other) const +int numeric::compare(const numeric &other) const { // Comparing two real numbers? if (cln::instanceof(value, cln::cl_R_ring) && @@ -904,7 +869,7 @@ int numeric::compare(const numeric & other) const } -bool numeric::is_equal(const numeric & other) const +bool numeric::is_equal(const numeric &other) const { return cln::equal(cln::the(value),cln::the(other.value)); } @@ -994,13 +959,13 @@ bool numeric::is_real(void) const } -bool numeric::operator==(const numeric & other) const +bool numeric::operator==(const numeric &other) const { return equal(cln::the(value), cln::the(other.value)); } -bool numeric::operator!=(const numeric & other) const +bool numeric::operator!=(const numeric &other) const { return !equal(cln::the(value), cln::the(other.value)); } @@ -1039,7 +1004,7 @@ bool numeric::is_crational(void) const /** Numerical comparison: less. * * @exception invalid_argument (complex inequality) */ -bool numeric::operator<(const numeric & other) const +bool numeric::operator<(const numeric &other) const { if (this->is_real() && other.is_real()) return (cln::the(value) < cln::the(other.value)); @@ -1050,7 +1015,7 @@ bool numeric::operator<(const numeric & other) const /** Numerical comparison: less or equal. * * @exception invalid_argument (complex inequality) */ -bool numeric::operator<=(const numeric & other) const +bool numeric::operator<=(const numeric &other) const { if (this->is_real() && other.is_real()) return (cln::the(value) <= cln::the(other.value)); @@ -1061,7 +1026,7 @@ bool numeric::operator<=(const numeric & other) const /** Numerical comparison: greater. * * @exception invalid_argument (complex inequality) */ -bool numeric::operator>(const numeric & other) const +bool numeric::operator>(const numeric &other) const { if (this->is_real() && other.is_real()) return (cln::the(value) > cln::the(other.value)); @@ -1072,7 +1037,7 @@ bool numeric::operator>(const numeric & other) const /** Numerical comparison: greater or equal. * * @exception invalid_argument (complex inequality) */ -bool numeric::operator>=(const numeric & other) const +bool numeric::operator>=(const numeric &other) const { if (this->is_real() && other.is_real()) return (cln::the(value) >= cln::the(other.value)); @@ -1220,14 +1185,15 @@ unsigned numeric::precedence = 30; ////////// /** Imaginary unit. This is not a constant but a numeric since we are - * natively handing complex numbers anyways. */ + * natively handing complex numbers anyways, so in each expression containing + * an I it is automatically eval'ed away anyhow. */ const numeric I = numeric(cln::complex(cln::cl_I(0),cln::cl_I(1))); /** Exponential function. * * @return arbitrary precision numerical exp(x). */ -const numeric exp(const numeric & x) +const numeric exp(const numeric &x) { return cln::exp(x.to_cl_N()); } @@ -1238,7 +1204,7 @@ const numeric exp(const numeric & x) * @param z complex number * @return arbitrary precision numerical log(x). * @exception pole_error("log(): logarithmic pole",0) */ -const numeric log(const numeric & z) +const numeric log(const numeric &z) { if (z.is_zero()) throw pole_error("log(): logarithmic pole",0); @@ -1249,7 +1215,7 @@ const numeric log(const numeric & z) /** Numeric sine (trigonometric function). * * @return arbitrary precision numerical sin(x). */ -const numeric sin(const numeric & x) +const numeric sin(const numeric &x) { return cln::sin(x.to_cl_N()); } @@ -1258,7 +1224,7 @@ const numeric sin(const numeric & x) /** Numeric cosine (trigonometric function). * * @return arbitrary precision numerical cos(x). */ -const numeric cos(const numeric & x) +const numeric cos(const numeric &x) { return cln::cos(x.to_cl_N()); } @@ -1267,7 +1233,7 @@ const numeric cos(const numeric & x) /** Numeric tangent (trigonometric function). * * @return arbitrary precision numerical tan(x). */ -const numeric tan(const numeric & x) +const numeric tan(const numeric &x) { return cln::tan(x.to_cl_N()); } @@ -1276,7 +1242,7 @@ const numeric tan(const numeric & x) /** Numeric inverse sine (trigonometric function). * * @return arbitrary precision numerical asin(x). */ -const numeric asin(const numeric & x) +const numeric asin(const numeric &x) { return cln::asin(x.to_cl_N()); } @@ -1285,7 +1251,7 @@ const numeric asin(const numeric & x) /** Numeric inverse cosine (trigonometric function). * * @return arbitrary precision numerical acos(x). */ -const numeric acos(const numeric & x) +const numeric acos(const numeric &x) { return cln::acos(x.to_cl_N()); } @@ -1296,7 +1262,7 @@ const numeric acos(const numeric & x) * @param z complex number * @return atan(z) * @exception pole_error("atan(): logarithmic pole",0) */ -const numeric atan(const numeric & x) +const numeric atan(const numeric &x) { if (!x.is_real() && x.real().is_zero() && @@ -1311,7 +1277,7 @@ const numeric atan(const numeric & x) * @param x real number * @param y real number * @return atan(y/x) */ -const numeric atan(const numeric & y, const numeric & x) +const numeric atan(const numeric &y, const numeric &x) { if (x.is_real() && y.is_real()) return cln::atan(cln::the(x.to_cl_N()), @@ -1324,7 +1290,7 @@ const numeric atan(const numeric & y, const numeric & x) /** Numeric hyperbolic sine (trigonometric function). * * @return arbitrary precision numerical sinh(x). */ -const numeric sinh(const numeric & x) +const numeric sinh(const numeric &x) { return cln::sinh(x.to_cl_N()); } @@ -1333,7 +1299,7 @@ const numeric sinh(const numeric & x) /** Numeric hyperbolic cosine (trigonometric function). * * @return arbitrary precision numerical cosh(x). */ -const numeric cosh(const numeric & x) +const numeric cosh(const numeric &x) { return cln::cosh(x.to_cl_N()); } @@ -1342,7 +1308,7 @@ const numeric cosh(const numeric & x) /** Numeric hyperbolic tangent (trigonometric function). * * @return arbitrary precision numerical tanh(x). */ -const numeric tanh(const numeric & x) +const numeric tanh(const numeric &x) { return cln::tanh(x.to_cl_N()); } @@ -1351,7 +1317,7 @@ const numeric tanh(const numeric & x) /** Numeric inverse hyperbolic sine (trigonometric function). * * @return arbitrary precision numerical asinh(x). */ -const numeric asinh(const numeric & x) +const numeric asinh(const numeric &x) { return cln::asinh(x.to_cl_N()); } @@ -1360,7 +1326,7 @@ const numeric asinh(const numeric & x) /** Numeric inverse hyperbolic cosine (trigonometric function). * * @return arbitrary precision numerical acosh(x). */ -const numeric acosh(const numeric & x) +const numeric acosh(const numeric &x) { return cln::acosh(x.to_cl_N()); } @@ -1369,14 +1335,14 @@ const numeric acosh(const numeric & x) /** Numeric inverse hyperbolic tangent (trigonometric function). * * @return arbitrary precision numerical atanh(x). */ -const numeric atanh(const numeric & x) +const numeric atanh(const numeric &x) { return cln::atanh(x.to_cl_N()); } -/*static cln::cl_N Li2_series(const ::cl_N & x, - const ::float_format_t & prec) +/*static cln::cl_N Li2_series(const ::cl_N &x, + const ::float_format_t &prec) { // Note: argument must be in the unit circle // This is very inefficient unless we have fast floating point Bernoulli @@ -1403,8 +1369,8 @@ const numeric atanh(const numeric & x) /** Numeric evaluation of Dilogarithm within circle of convergence (unit * circle) using a power series. */ -static cln::cl_N Li2_series(const cln::cl_N & x, - const cln::float_format_t & prec) +static cln::cl_N Li2_series(const cln::cl_N &x, + const cln::float_format_t &prec) { // Note: argument must be in the unit circle cln::cl_N aug, acc; @@ -1422,8 +1388,8 @@ static cln::cl_N Li2_series(const cln::cl_N & x, } /** Folds Li2's argument inside a small rectangle to enhance convergence. */ -static cln::cl_N Li2_projection(const cln::cl_N & x, - const cln::float_format_t & prec) +static cln::cl_N Li2_projection(const cln::cl_N &x, + const cln::float_format_t &prec) { const cln::cl_R re = cln::realpart(x); const cln::cl_R im = cln::imagpart(x); @@ -1448,7 +1414,7 @@ static cln::cl_N Li2_projection(const cln::cl_N & x, * continuous with quadrant IV. * * @return arbitrary precision numerical Li2(x). */ -const numeric Li2(const numeric & x) +const numeric Li2(const numeric &x) { if (x.is_zero()) return _num0(); @@ -1478,7 +1444,7 @@ const numeric Li2(const numeric & x) /** Numeric evaluation of Riemann's Zeta function. Currently works only for * integer arguments. */ -const numeric zeta(const numeric & x) +const numeric zeta(const numeric &x) { // A dirty hack to allow for things like zeta(3.0), since CLN currently // only knows about integer arguments and zeta(3).evalf() automatically @@ -1491,7 +1457,7 @@ const numeric zeta(const numeric & x) return cln::zeta(aux); } std::clog << "zeta(" << x - << "): Does anybody know good way to calculate this numerically?" + << "): Does anybody know a good way to calculate this numerically?" << std::endl; return numeric(0); } @@ -1499,17 +1465,17 @@ const numeric zeta(const numeric & x) /** The Gamma function. * This is only a stub! */ -const numeric lgamma(const numeric & x) +const numeric lgamma(const numeric &x) { std::clog << "lgamma(" << x - << "): Does anybody know good way to calculate this numerically?" + << "): Does anybody know a good way to calculate this numerically?" << std::endl; return numeric(0); } -const numeric tgamma(const numeric & x) +const numeric tgamma(const numeric &x) { std::clog << "tgamma(" << x - << "): Does anybody know good way to calculate this numerically?" + << "): Does anybody know a good way to calculate this numerically?" << std::endl; return numeric(0); } @@ -1517,10 +1483,10 @@ const numeric tgamma(const numeric & x) /** The psi function (aka polygamma function). * This is only a stub! */ -const numeric psi(const numeric & x) +const numeric psi(const numeric &x) { std::clog << "psi(" << x - << "): Does anybody know good way to calculate this numerically?" + << "): Does anybody know a good way to calculate this numerically?" << std::endl; return numeric(0); } @@ -1528,10 +1494,10 @@ const numeric psi(const numeric & x) /** The psi functions (aka polygamma functions). * This is only a stub! */ -const numeric psi(const numeric & n, const numeric & x) +const numeric psi(const numeric &n, const numeric &x) { std::clog << "psi(" << n << "," << x - << "): Does anybody know good way to calculate this numerically?" + << "): Does anybody know a good way to calculate this numerically?" << std::endl; return numeric(0); } @@ -1541,7 +1507,7 @@ const numeric psi(const numeric & n, const numeric & x) * * @param n integer argument >= 0 * @exception range_error (argument must be integer >= 0) */ -const numeric factorial(const numeric & n) +const numeric factorial(const numeric &n) { if (!n.is_nonneg_integer()) throw std::range_error("numeric::factorial(): argument must be integer >= 0"); @@ -1555,9 +1521,9 @@ const numeric factorial(const numeric & n) * @param n integer argument >= -1 * @return n!! == n * (n-2) * (n-4) * ... * ({1|2}) with 0!! == (-1)!! == 1 * @exception range_error (argument must be integer >= -1) */ -const numeric doublefactorial(const numeric & n) +const numeric doublefactorial(const numeric &n) { - if (n == numeric(-1)) + if (n.is_equal(_num_1())) return _num1(); if (!n.is_nonneg_integer()) @@ -1571,7 +1537,7 @@ const numeric doublefactorial(const numeric & n) * integer n and k and positive n this is the number of ways of choosing k * objects from n distinct objects. If n is negative, the formula * binomial(n,k) == (-1)^k*binomial(k-n-1,k) is used to compute the result. */ -const numeric binomial(const numeric & n, const numeric & k) +const numeric binomial(const numeric &n, const numeric &k) { if (n.is_integer() && k.is_integer()) { if (n.is_nonneg_integer()) { @@ -1594,7 +1560,7 @@ const numeric binomial(const numeric & n, const numeric & k) * * @return the nth Bernoulli number (a rational number). * @exception range_error (argument must be integer >= 0) */ -const numeric bernoulli(const numeric & nn) +const numeric bernoulli(const numeric &nn) { if (!nn.is_integer() || nn.is_negative()) throw std::range_error("numeric::bernoulli(): argument must be integer >= 0"); @@ -1671,7 +1637,7 @@ const numeric bernoulli(const numeric & nn) * @param n an integer * @return the nth Fibonacci number F(n) (an integer number) * @exception range_error (argument must be an integer) */ -const numeric fibonacci(const numeric & n) +const numeric fibonacci(const numeric &n) { if (!n.is_integer()) throw std::range_error("numeric::fibonacci(): argument must be integer"); @@ -1738,7 +1704,7 @@ const numeric abs(const numeric& x) * * @return a mod b in the range [0,abs(b)-1] with sign of b if both are * integer, 0 otherwise. */ -const numeric mod(const numeric & a, const numeric & b) +const numeric mod(const numeric &a, const numeric &b) { if (a.is_integer() && b.is_integer()) return cln::mod(cln::the(a.to_cl_N()), @@ -1752,7 +1718,7 @@ const numeric mod(const numeric & a, const numeric & b) * Equivalent to Maple's mods. * * @return a mod b in the range [-iquo(abs(m)-1,2), iquo(abs(m),2)]. */ -const numeric smod(const numeric & a, const numeric & b) +const numeric smod(const numeric &a, const numeric &b) { if (a.is_integer() && b.is_integer()) { const cln::cl_I b2 = cln::ceiling1(cln::the(b.to_cl_N()) >> 1) - 1; @@ -1769,7 +1735,7 @@ const numeric smod(const numeric & a, const numeric & b) * sign of a or is zero. * * @return remainder of a/b if both are integer, 0 otherwise. */ -const numeric irem(const numeric & a, const numeric & b) +const numeric irem(const numeric &a, const numeric &b) { if (a.is_integer() && b.is_integer()) return cln::rem(cln::the(a.to_cl_N()), @@ -1786,7 +1752,7 @@ const numeric irem(const numeric & a, const numeric & b) * * @return remainder of a/b and quotient stored in q if both are integer, * 0 otherwise. */ -const numeric irem(const numeric & a, const numeric & b, numeric & q) +const numeric irem(const numeric &a, const numeric &b, numeric &q) { if (a.is_integer() && b.is_integer()) { const cln::cl_I_div_t rem_quo = cln::truncate2(cln::the(a.to_cl_N()), @@ -1804,7 +1770,7 @@ const numeric irem(const numeric & a, const numeric & b, numeric & q) * Equivalent to Maple's iquo as far as sign conventions are concerned. * * @return truncated quotient of a/b if both are integer, 0 otherwise. */ -const numeric iquo(const numeric & a, const numeric & b) +const numeric iquo(const numeric &a, const numeric &b) { if (a.is_integer() && b.is_integer()) return truncate1(cln::the(a.to_cl_N()), @@ -1820,7 +1786,7 @@ const numeric iquo(const numeric & a, const numeric & b) * * @return truncated quotient of a/b and remainder stored in r if both are * integer, 0 otherwise. */ -const numeric iquo(const numeric & a, const numeric & b, numeric & r) +const numeric iquo(const numeric &a, const numeric &b, numeric &r) { if (a.is_integer() && b.is_integer()) { const cln::cl_I_div_t rem_quo = cln::truncate2(cln::the(a.to_cl_N()), @@ -1838,7 +1804,7 @@ const numeric iquo(const numeric & a, const numeric & b, numeric & r) * * @return The GCD of two numbers if both are integer, a numerical 1 * if they are not. */ -const numeric gcd(const numeric & a, const numeric & b) +const numeric gcd(const numeric &a, const numeric &b) { if (a.is_integer() && b.is_integer()) return cln::gcd(cln::the(a.to_cl_N()), @@ -1852,7 +1818,7 @@ const numeric gcd(const numeric & a, const numeric & b) * * @return The LCM of two numbers if both are integer, the product of those * two numbers if they are not. */ -const numeric lcm(const numeric & a, const numeric & b) +const numeric lcm(const numeric &a, const numeric &b) { if (a.is_integer() && b.is_integer()) return cln::lcm(cln::the(a.to_cl_N()), @@ -1870,14 +1836,14 @@ const numeric lcm(const numeric & a, const numeric & b) * @return square root of z. Branch cut along negative real axis, the negative * real axis itself where imag(z)==0 and real(z)<0 belongs to the upper part * where imag(z)>0. */ -const numeric sqrt(const numeric & z) +const numeric sqrt(const numeric &z) { return cln::sqrt(z.to_cl_N()); } /** Integer numeric square root. */ -const numeric isqrt(const numeric & x) +const numeric isqrt(const numeric &x) { if (x.is_integer()) { cln::cl_I root; @@ -1909,13 +1875,15 @@ ex CatalanEvalf(void) } +/** _numeric_digits default ctor, checking for singleton invariance. */ _numeric_digits::_numeric_digits() : digits(17) { // It initializes to 17 digits, because in CLN float_format(17) turns out // to be 61 (<64) while float_format(18)=65. The reason is we want to // have a cl_LF instead of cl_SF, cl_FF or cl_DF. - assert(!too_late); + if (too_late) + throw(std::runtime_error("I told you not to do instantiate me!")); too_late = true; cln::default_float_format = cln::float_format(17); } @@ -1939,14 +1907,14 @@ _numeric_digits::operator long() /** Append global Digits object to ostream. */ -void _numeric_digits::print(std::ostream & os) const +void _numeric_digits::print(std::ostream &os) const { debugmsg("_numeric_digits print", LOGLEVEL_PRINT); os << digits; } -std::ostream& operator<<(std::ostream& os, const _numeric_digits & e) +std::ostream& operator<<(std::ostream &os, const _numeric_digits &e) { e.print(os); return os; @@ -1965,6 +1933,4 @@ bool _numeric_digits::too_late = false; * assignment from C++ unsigned ints and evaluated like any built-in type. */ _numeric_digits Digits; -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/numeric.h b/ginac/numeric.h index b4d61faa..ce50406f 100644 --- a/ginac/numeric.h +++ b/ginac/numeric.h @@ -38,15 +38,13 @@ namespace cln { class cl_N; } #include #endif -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC #define HASHVALUE_NUMERIC 0x80000001U -/** This class is used to instantiate a global object Digits which - * behaves just like Maple's Digits. We need an object rather than a - * dumber basic type since as a side-effect we let it change +/** This class is used to instantiate a global singleton object Digits + * which behaves just like Maple's Digits. We need an object rather + * than a dumber basic type since as a side-effect we let it change * cl_default_float_format when it gets changed. The only other * meaningful thing to do with it is converting it to an unsigned, * for temprary storing its value e.g. The user must not create an @@ -60,11 +58,11 @@ public: _numeric_digits(); _numeric_digits& operator=(long prec); operator long(); - void print(std::ostream & os) const; + void print(std::ostream &os) const; // member variables private: - long digits; - static bool too_late; + long digits; ///< Number of decimal digits + static bool too_late; ///< Already one object present }; /** This class is a wrapper around CLN-numbers within the GiNaC class @@ -72,10 +70,10 @@ private: class numeric : public basic { GINAC_DECLARE_REGISTERED_CLASS(numeric, basic) - + // member functions - - // other constructors + + // other ctors public: explicit numeric(int i); explicit numeric(unsigned int i); @@ -87,49 +85,51 @@ public: // functions overriding virtual functions from bases classes public: - void print(std::ostream & os, unsigned precedence=0) const; - void printraw(std::ostream & os) const; - void printtree(std::ostream & os, unsigned indent) const; - void printcsrc(std::ostream & os, unsigned type, unsigned precedence=0) const; + void print(std::ostream &os, unsigned precedence = 0) const; + void printraw(std::ostream &os) const; + void printtree(std::ostream &os, unsigned indent) const; + void printcsrc(std::ostream &os, unsigned type, unsigned precedence=0) const; bool info(unsigned inf) const; - bool has(const ex & other) const; + bool has(const ex &other) const; ex eval(int level = 0) const; ex evalf(int level = 0) const; - ex normal(lst &sym_lst, lst &repl_lst, int level=0) const; + ex normal(lst &sym_lst, lst &repl_lst, int level = 0) const; ex to_rational(lst &repl_lst) const; numeric integer_content(void) const; ex smod(const numeric &xi) const; numeric max_coefficient(void) const; protected: - ex derivative(const symbol & s) const; - bool is_equal_same_type(const basic & other) const; + /** Implementation of ex::diff for a numeric always returns 0. + * @see ex::diff */ + ex derivative(const symbol &s) const { return _ex0(); } + bool is_equal_same_type(const basic &other) const; unsigned calchash(void) const; - + // new virtual functions which can be overridden by derived classes // (none) - + // non-virtual functions in this class public: - const numeric add(const numeric & other) const; - const numeric sub(const numeric & other) const; - const numeric mul(const numeric & other) const; - const numeric div(const numeric & other) const; - const numeric power(const numeric & other) const; - const numeric & add_dyn(const numeric & other) const; - const numeric & sub_dyn(const numeric & other) const; - const numeric & mul_dyn(const numeric & other) const; - const numeric & div_dyn(const numeric & other) const; - const numeric & power_dyn(const numeric & other) const; + const numeric add(const numeric &other) const; + const numeric sub(const numeric &other) const; + const numeric mul(const numeric &other) const; + const numeric div(const numeric &other) const; + const numeric power(const numeric &other) const; + const numeric & add_dyn(const numeric &other) const; + const numeric & sub_dyn(const numeric &other) const; + const numeric & mul_dyn(const numeric &other) const; + const numeric & div_dyn(const numeric &other) const; + const numeric & power_dyn(const numeric &other) const; const numeric & operator=(int i); const numeric & operator=(unsigned int i); const numeric & operator=(long i); const numeric & operator=(unsigned long i); const numeric & operator=(double d); - const numeric & operator=(const char * s); + const numeric & operator=(const char *s); const numeric inverse(void) const; int csgn(void) const; - int compare(const numeric & other) const; - bool is_equal(const numeric & other) const; + int compare(const numeric &other) const; + bool is_equal(const numeric &other) const; bool is_zero(void) const; bool is_positive(void) const; bool is_negative(void) const; @@ -143,12 +143,12 @@ public: bool is_real(void) const; bool is_cinteger(void) const; bool is_crational(void) const; - bool operator==(const numeric & other) const; - bool operator!=(const numeric & other) const; - bool operator<(const numeric & other) const; - bool operator<=(const numeric & other) const; - bool operator>(const numeric & other) const; - bool operator>=(const numeric & other) const; + bool operator==(const numeric &other) const; + bool operator!=(const numeric &other) const; + bool operator<(const numeric &other) const; + bool operator<=(const numeric &other) const; + bool operator>(const numeric &other) const; + bool operator>=(const numeric &other) const; int to_int(void) const; long to_long(void) const; double to_double(void) const; @@ -159,7 +159,7 @@ public: const numeric denom(void) const; int int_length(void) const; // converting routines for interfacing with CLN: - numeric(const cln::cl_N & z); + numeric(const cln::cl_N &z); // member variables @@ -173,118 +173,115 @@ protected: extern const numeric I; extern _numeric_digits Digits; -//#define is_a_numeric_hash(x) ((x)==HASHVALUE_NUMERIC) -// may have to be changed to ((x)>=0x80000000U) - -// has been changed -//#define is_a_numeric_hash(x) ((x)&0x80000000U) +// deprecated macro, for internal use only +#define is_a_numeric_hash(x) ((x)&0x80000000U) // global functions -const numeric exp(const numeric & x); -const numeric log(const numeric & x); -const numeric sin(const numeric & x); -const numeric cos(const numeric & x); -const numeric tan(const numeric & x); -const numeric asin(const numeric & x); -const numeric acos(const numeric & x); -const numeric atan(const numeric & x); -const numeric atan(const numeric & y, const numeric & x); -const numeric sinh(const numeric & x); -const numeric cosh(const numeric & x); -const numeric tanh(const numeric & x); -const numeric asinh(const numeric & x); -const numeric acosh(const numeric & x); -const numeric atanh(const numeric & x); -const numeric Li2(const numeric & x); -const numeric zeta(const numeric & x); -const numeric lgamma(const numeric & x); -const numeric tgamma(const numeric & x); -const numeric psi(const numeric & x); -const numeric psi(const numeric & n, const numeric & x); -const numeric factorial(const numeric & n); -const numeric doublefactorial(const numeric & n); -const numeric binomial(const numeric & n, const numeric & k); -const numeric bernoulli(const numeric & n); -const numeric fibonacci(const numeric & n); -const numeric abs(const numeric & x); -const numeric isqrt(const numeric & x); -const numeric sqrt(const numeric & x); -const numeric abs(const numeric & x); -const numeric mod(const numeric & a, const numeric & b); -const numeric smod(const numeric & a, const numeric & b); -const numeric irem(const numeric & a, const numeric & b); -const numeric irem(const numeric & a, const numeric & b, numeric & q); -const numeric iquo(const numeric & a, const numeric & b); -const numeric iquo(const numeric & a, const numeric & b, numeric & r); -const numeric gcd(const numeric & a, const numeric & b); -const numeric lcm(const numeric & a, const numeric & b); +const numeric exp(const numeric &x); +const numeric log(const numeric &x); +const numeric sin(const numeric &x); +const numeric cos(const numeric &x); +const numeric tan(const numeric &x); +const numeric asin(const numeric &x); +const numeric acos(const numeric &x); +const numeric atan(const numeric &x); +const numeric atan(const numeric &y, const numeric &x); +const numeric sinh(const numeric &x); +const numeric cosh(const numeric &x); +const numeric tanh(const numeric &x); +const numeric asinh(const numeric &x); +const numeric acosh(const numeric &x); +const numeric atanh(const numeric &x); +const numeric Li2(const numeric &x); +const numeric zeta(const numeric &x); +const numeric lgamma(const numeric &x); +const numeric tgamma(const numeric &x); +const numeric psi(const numeric &x); +const numeric psi(const numeric &n, const numeric &x); +const numeric factorial(const numeric &n); +const numeric doublefactorial(const numeric &n); +const numeric binomial(const numeric &n, const numeric &k); +const numeric bernoulli(const numeric &n); +const numeric fibonacci(const numeric &n); +const numeric abs(const numeric &x); +const numeric isqrt(const numeric &x); +const numeric sqrt(const numeric &x); +const numeric abs(const numeric &x); +const numeric mod(const numeric &a, const numeric &b); +const numeric smod(const numeric &a, const numeric &b); +const numeric irem(const numeric &a, const numeric &b); +const numeric irem(const numeric &a, const numeric &b, numeric &q); +const numeric iquo(const numeric &a, const numeric &b); +const numeric iquo(const numeric &a, const numeric &b, numeric &r); +const numeric gcd(const numeric &a, const numeric &b); +const numeric lcm(const numeric &a, const numeric &b); // wrapper functions around member functions -inline const numeric pow(const numeric & x, const numeric & y) +inline const numeric pow(const numeric &x, const numeric &y) { return x.power(y); } -inline const numeric inverse(const numeric & x) +inline const numeric inverse(const numeric &x) { return x.inverse(); } -inline int csgn(const numeric & x) +inline int csgn(const numeric &x) { return x.csgn(); } -inline bool is_zero(const numeric & x) +inline bool is_zero(const numeric &x) { return x.is_zero(); } -inline bool is_positive(const numeric & x) +inline bool is_positive(const numeric &x) { return x.is_positive(); } -inline bool is_integer(const numeric & x) +inline bool is_integer(const numeric &x) { return x.is_integer(); } -inline bool is_pos_integer(const numeric & x) +inline bool is_pos_integer(const numeric &x) { return x.is_pos_integer(); } -inline bool is_nonneg_integer(const numeric & x) +inline bool is_nonneg_integer(const numeric &x) { return x.is_nonneg_integer(); } -inline bool is_even(const numeric & x) +inline bool is_even(const numeric &x) { return x.is_even(); } -inline bool is_odd(const numeric & x) +inline bool is_odd(const numeric &x) { return x.is_odd(); } -inline bool is_prime(const numeric & x) +inline bool is_prime(const numeric &x) { return x.is_prime(); } -inline bool is_rational(const numeric & x) +inline bool is_rational(const numeric &x) { return x.is_rational(); } -inline bool is_real(const numeric & x) +inline bool is_real(const numeric &x) { return x.is_real(); } -inline bool is_cinteger(const numeric & x) +inline bool is_cinteger(const numeric &x) { return x.is_cinteger(); } -inline bool is_crational(const numeric & x) +inline bool is_crational(const numeric &x) { return x.is_crational(); } -inline int to_int(const numeric & x) +inline int to_int(const numeric &x) { return x.to_int(); } -inline long to_long(const numeric & x) +inline long to_long(const numeric &x) { return x.to_long(); } -inline double to_double(const numeric & x) +inline double to_double(const numeric &x) { return x.to_double(); } -inline const numeric real(const numeric & x) +inline const numeric real(const numeric &x) { return x.real(); } -inline const numeric imag(const numeric & x) +inline const numeric imag(const numeric &x) { return x.imag(); } -inline const numeric numer(const numeric & x) +inline const numeric numer(const numeric &x) { return x.numer(); } -inline const numeric denom(const numeric & x) +inline const numeric denom(const numeric &x) { return x.denom(); } // numeric evaluation functions for class constant objects: @@ -300,10 +297,7 @@ inline const numeric &ex_to_numeric(const ex &e) return static_cast(*e.bp); } - -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #ifdef __MAKECINT__ #pragma link off defined_in cln/number.h; diff --git a/ginac/operators.cpp b/ginac/operators.cpp index 11b2783c..4e5781a6 100644 --- a/ginac/operators.cpp +++ b/ginac/operators.cpp @@ -20,21 +20,14 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include - #include "operators.h" -#include "basic.h" -#include "ex.h" #include "numeric.h" #include "power.h" #include "relational.h" #include "debugmsg.h" #include "utils.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC // binary arithmetic operators ex with ex @@ -101,25 +94,25 @@ numeric operator/(const numeric & lh, const numeric & rh) const ex & operator+=(ex & lh, const ex & rh) { debugmsg("operator+=(ex,ex)",LOGLEVEL_OPERATOR); - return (lh=lh+rh); + return (lh=lh.exadd(rh)); } const ex & operator-=(ex & lh, const ex & rh) { debugmsg("operator-=(ex,ex)",LOGLEVEL_OPERATOR); - return (lh=lh-rh); + return (lh=lh.exadd(rh.exmul(_ex_1()))); } const ex & operator*=(ex & lh, const ex & rh) { debugmsg("operator*=(ex,ex)",LOGLEVEL_OPERATOR); - return (lh=lh*rh); + return (lh=lh.exmul(rh)); } const ex & operator/=(ex & lh, const ex & rh) { debugmsg("operator/=(ex,ex)",LOGLEVEL_OPERATOR); - return (lh=lh/rh); + return (lh=lh.exmul(power(rh,_ex_1()))); } const ex & operator%=(ex & lh, const ex & rh) @@ -178,14 +171,14 @@ numeric operator+(const numeric & lh) numeric operator-(const numeric & lh) { debugmsg("operator-(numeric)",LOGLEVEL_OPERATOR); - return _num_1()*lh; + return _num_1().mul(lh); } /** Numeric prefix increment. Adds 1 and returns incremented number. */ numeric& operator++(numeric & rh) { debugmsg("operator++(numeric)",LOGLEVEL_OPERATOR); - rh = rh+_num1(); + rh = rh.add(_num1()); return rh; } @@ -193,7 +186,7 @@ numeric& operator++(numeric & rh) numeric& operator--(numeric & rh) { debugmsg("operator--(numeric)",LOGLEVEL_OPERATOR); - rh = rh-_num1(); + rh = rh.add(_num_1()); return rh; } @@ -202,8 +195,8 @@ numeric& operator--(numeric & rh) numeric operator++(numeric & lh, int) { debugmsg("operator++(numeric,int)",LOGLEVEL_OPERATOR); - numeric tmp = lh; - lh = lh+_num1(); + numeric tmp(lh); + lh = lh.add(_num1()); return tmp; } @@ -212,8 +205,8 @@ numeric operator++(numeric & lh, int) numeric operator--(numeric & lh, int) { debugmsg("operator--(numeric,int)",LOGLEVEL_OPERATOR); - numeric tmp = lh; - lh = lh-_num1(); + numeric tmp(lh); + lh = lh.add(_num_1()); return tmp; } @@ -268,6 +261,4 @@ std::istream & operator>>(std::istream & is, ex & e) throw (std::logic_error("expression input from streams not implemented")); } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/operators.h b/ginac/operators.h index 18b1b927..8636e212 100644 --- a/ginac/operators.h +++ b/ginac/operators.h @@ -25,9 +25,7 @@ #include -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC class ex; class numeric; @@ -82,8 +80,6 @@ relational operator>=(const ex & lh, const ex & rh); std::ostream & operator<<(std::ostream & os, const ex & e); std::istream & operator>>(std::istream & is, ex & e); -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_OPERATORS_H__ diff --git a/ginac/power.cpp b/ginac/power.cpp index 7324ca97..5ebeae63 100644 --- a/ginac/power.cpp +++ b/ginac/power.cpp @@ -36,23 +36,21 @@ #include "debugmsg.h" #include "utils.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC GINAC_IMPLEMENT_REGISTERED_CLASS(power, basic) typedef std::vector intvector; ////////// -// default constructor, destructor, copy constructor assignment operator and helpers +// default ctor, dtor, copy ctor assignment operator and helpers ////////// // public power::power() : basic(TINFO_power) { - debugmsg("power default constructor",LOGLEVEL_CONSTRUCT); + debugmsg("power default ctor",LOGLEVEL_CONSTRUCT); } // protected @@ -60,8 +58,8 @@ power::power() : basic(TINFO_power) void power::copy(const power & other) { inherited::copy(other); - basis=other.basis; - exponent=other.exponent; + basis = other.basis; + exponent = other.exponent; } void power::destroy(bool call_parent) @@ -70,20 +68,20 @@ void power::destroy(bool call_parent) } ////////// -// other constructors +// other ctors ////////// // public power::power(const ex & lh, const ex & rh) : basic(TINFO_power), basis(lh), exponent(rh) { - debugmsg("power constructor from ex,ex",LOGLEVEL_CONSTRUCT); + debugmsg("power ctor from ex,ex",LOGLEVEL_CONSTRUCT); GINAC_ASSERT(basis.return_type()==return_types::commutative); } power::power(const ex & lh, const numeric & rh) : basic(TINFO_power), basis(lh), exponent(rh) { - debugmsg("power constructor from ex,numeric",LOGLEVEL_CONSTRUCT); + debugmsg("power ctor from ex,numeric",LOGLEVEL_CONSTRUCT); GINAC_ASSERT(basis.return_type()==return_types::commutative); } @@ -94,7 +92,7 @@ power::power(const ex & lh, const numeric & rh) : basic(TINFO_power), basis(lh), /** Construct object from archive_node. */ power::power(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) { - debugmsg("power constructor from archive_node", LOGLEVEL_CONSTRUCT); + debugmsg("power ctor from archive_node", LOGLEVEL_CONSTRUCT); n.find_ex("basis", basis, sym_lst); n.find_ex("exponent", exponent, sym_lst); } @@ -158,7 +156,9 @@ void power::printtree(std::ostream & os, unsigned indent) const static void print_sym_pow(std::ostream & os, unsigned type, const symbol &x, int exp) { - // Optimal output of integer powers of symbols to aid compiler CSE + // Optimal output of integer powers of symbols to aid compiler CSE. + // C.f. ISO/IEC 14882:1998, section 1.9 [intro execution], paragraph 15 + // to learn why such a hack is really necessary. if (exp == 1) { x.printcsrc(os, type, 0); } else if (exp == 2) { @@ -343,11 +343,12 @@ ex power::eval(int level) const } // ^(x,0) -> 1 (0^0 also handled here) - if (eexponent.is_zero()) + if (eexponent.is_zero()) { if (ebasis.is_zero()) throw (std::domain_error("power::eval(): pow(0,0) is undefined")); else return _ex1(); + } // ^(x,1) -> x if (eexponent.is_equal(_ex1())) @@ -372,7 +373,7 @@ ex power::eval(int level) const // except if c1,c2 are rational, but c1^c2 is not) bool basis_is_crational = num_basis->is_crational(); bool exponent_is_crational = num_exponent->is_crational(); - numeric res = (*num_basis).power(*num_exponent); + numeric res = num_basis->power(*num_exponent); if ((!basis_is_crational || !exponent_is_crational) || res.is_crational()) { @@ -396,7 +397,7 @@ ex power::eval(int level) const else { epvector res; res.push_back(expair(ebasis,r.div(m))); - return (new mul(res,ex(num_basis->power(q))))->setflag(status_flags::dynallocated | status_flags::evaluated); + return (new mul(res,ex(num_basis->power_dyn(q))))->setflag(status_flags::dynallocated | status_flags::evaluated); } } } @@ -411,9 +412,8 @@ ex power::eval(int level) const if (is_ex_exactly_of_type(sub_exponent,numeric)) { const numeric & num_sub_exponent = ex_to_numeric(sub_exponent); GINAC_ASSERT(num_sub_exponent!=numeric(1)); - if (num_exponent->is_integer() || abs(num_sub_exponent)<1) { + if (num_exponent->is_integer() || abs(num_sub_exponent)<1) return power(sub_basis,num_sub_exponent.mul(*num_exponent)); - } } } @@ -427,13 +427,13 @@ ex power::eval(int level) const // ^(*(...,x,c1),c2) -> ^(*(...,x;-1),c2)*(-c1)^c2 (c1, c2 numeric(), c1<0) if (exponent_is_numerical && is_ex_exactly_of_type(ebasis,mul)) { GINAC_ASSERT(!num_exponent->is_integer()); // should have been handled above - const mul & mulref=ex_to_mul(ebasis); + const mul & mulref = ex_to_mul(ebasis); if (!mulref.overall_coeff.is_equal(_ex1())) { - const numeric & num_coeff=ex_to_numeric(mulref.overall_coeff); + const numeric & num_coeff = ex_to_numeric(mulref.overall_coeff); if (num_coeff.is_real()) { - if (num_coeff.is_positive()>0) { - mul * mulp=new mul(mulref); - mulp->overall_coeff=_ex1(); + if (num_coeff.is_positive()) { + mul * mulp = new mul(mulref); + mulp->overall_coeff = _ex1(); mulp->clearflag(status_flags::evaluated); mulp->clearflag(status_flags::hash_calculated); return (new mul(power(*mulp,exponent), @@ -441,8 +441,8 @@ ex power::eval(int level) const } else { GINAC_ASSERT(num_coeff.compare(_num0())<0); if (num_coeff.compare(_num_1())!=0) { - mul * mulp=new mul(mulref); - mulp->overall_coeff=_ex_1(); + mul * mulp = new mul(mulref); + mulp->overall_coeff = _ex_1(); mulp->clearflag(status_flags::evaluated); mulp->clearflag(status_flags::hash_calculated); return (new mul(power(*mulp,exponent), @@ -452,7 +452,7 @@ ex power::eval(int level) const } } } - + if (are_ex_trivially_equal(ebasis,basis) && are_ex_trivially_equal(eexponent,exponent)) { return this->hold(); @@ -553,7 +553,7 @@ ex power::expand(unsigned options) const ex expanded_basis = basis.expand(options); ex expanded_exponent = exponent.expand(options); - + // x^(a+b) -> x^a * x^b if (is_ex_exactly_of_type(expanded_exponent, add)) { const add &a = ex_to_add(expanded_exponent); @@ -565,7 +565,7 @@ ex power::expand(unsigned options) const distrseq.push_back(power(expanded_basis, a.recombine_pair_to_ex(*cit))); cit++; } - + // Make sure that e.g. (x+y)^(2+a) expands the (x+y)^2 factor if (ex_to_numeric(a.overall_coeff).is_integer()) { const numeric &num_exponent = ex_to_numeric(a.overall_coeff); @@ -576,12 +576,12 @@ ex power::expand(unsigned options) const distrseq.push_back(power(expanded_basis, a.overall_coeff)); } else distrseq.push_back(power(expanded_basis, a.overall_coeff)); - + // Make sure that e.g. (x+y)^(1+a) -> x*(x+y)^a + y*(x+y)^a ex r = (new mul(distrseq))->setflag(status_flags::dynallocated); return r.expand(); } - + if (!is_ex_exactly_of_type(expanded_exponent, numeric) || !ex_to_numeric(expanded_exponent).is_integer()) { if (are_ex_trivially_equal(basis,expanded_basis) && are_ex_trivially_equal(exponent,expanded_exponent)) { @@ -596,21 +596,18 @@ ex power::expand(unsigned options) const int int_exponent = num_exponent.to_int(); // (x+y)^n, n>0 - if (int_exponent > 0 && is_ex_exactly_of_type(expanded_basis,add)) { + if (int_exponent > 0 && is_ex_exactly_of_type(expanded_basis,add)) return expand_add(ex_to_add(expanded_basis), int_exponent); - } // (x*y)^n -> x^n * y^n - if (is_ex_exactly_of_type(expanded_basis,mul)) { + if (is_ex_exactly_of_type(expanded_basis,mul)) return expand_mul(ex_to_mul(expanded_basis), num_exponent); - } // cannot expand further - if (are_ex_trivially_equal(basis,expanded_basis) && are_ex_trivially_equal(exponent,expanded_exponent)) { + if (are_ex_trivially_equal(basis,expanded_basis) && are_ex_trivially_equal(exponent,expanded_exponent)) return this->hold(); - } else { + else return (new power(expanded_basis,expanded_exponent))->setflag(status_flags::dynallocated | status_flags::expanded); - } } ////////// @@ -656,11 +653,10 @@ ex power::expand_add(const add & a, int n) const !is_ex_exactly_of_type(ex_to_power(b).basis,add) || !is_ex_exactly_of_type(ex_to_power(b).basis,mul) || !is_ex_exactly_of_type(ex_to_power(b).basis,power)); - if (is_ex_exactly_of_type(b,mul)) { + if (is_ex_exactly_of_type(b,mul)) term.push_back(expand_mul(ex_to_mul(b),numeric(k[l]))); - } else { + else term.push_back(power(b,k[l])); - } } const ex & b = a.op(l); @@ -671,18 +667,17 @@ ex power::expand_add(const add & a, int n) const !is_ex_exactly_of_type(ex_to_power(b).basis,add) || !is_ex_exactly_of_type(ex_to_power(b).basis,mul) || !is_ex_exactly_of_type(ex_to_power(b).basis,power)); - if (is_ex_exactly_of_type(b,mul)) { + if (is_ex_exactly_of_type(b,mul)) term.push_back(expand_mul(ex_to_mul(b),numeric(n-k_cum[m-2]))); - } else { + else term.push_back(power(b,n-k_cum[m-2])); - } numeric f = binomial(numeric(n),numeric(k[0])); - for (l=1; lsetflag(status_flags::dynallocated)); // increment k[] - l=m-2; + l = m-2; while ((l>=0)&&((++k[l])>upper_limit[l])) { - k[l]=0; + k[l] = 0; l--; } if (l<0) break; - + // recalc k_cum[] and upper_limit[] - if (l==0) { - k_cum[0]=k[0]; - } else { - k_cum[l]=k_cum[l-1]+k[l]; - } - for (int i=l+1; isetflag(status_flags::dynallocated | status_flags::expanded ); @@ -731,15 +724,15 @@ ex power::expand_add(const add & a, int n) const ex power::expand_add_2(const add & a) const { epvector sum; - unsigned a_nops=a.nops(); + unsigned a_nops = a.nops(); sum.reserve((a_nops*(a_nops+1))/2); - epvector::const_iterator last=a.seq.end(); - + epvector::const_iterator last = a.seq.end(); + // power(+(x,...,z;c),2)=power(+(x,...,z;0),2)+2*c*+(x,...,z;0)+c*c // first part: ignore overall_coeff and expand other terms for (epvector::const_iterator cit0=a.seq.begin(); cit0!=last; ++cit0) { - const ex & r=(*cit0).rest; - const ex & c=(*cit0).coeff; + const ex & r = (*cit0).rest; + const ex & c = (*cit0).coeff; GINAC_ASSERT(!is_ex_exactly_of_type(r,add)); GINAC_ASSERT(!is_ex_exactly_of_type(r,power) || @@ -748,7 +741,7 @@ ex power::expand_add_2(const add & a) const !is_ex_exactly_of_type(ex_to_power(r).basis,add) || !is_ex_exactly_of_type(ex_to_power(r).basis,mul) || !is_ex_exactly_of_type(ex_to_power(r).basis,power)); - + if (are_ex_trivially_equal(c,_ex1())) { if (is_ex_exactly_of_type(r,mul)) { sum.push_back(expair(expand_mul(ex_to_mul(r),_num2()), @@ -768,23 +761,23 @@ ex power::expand_add_2(const add & a) const } for (epvector::const_iterator cit1=cit0+1; cit1!=last; ++cit1) { - const ex & r1=(*cit1).rest; - const ex & c1=(*cit1).coeff; + const ex & r1 = (*cit1).rest; + const ex & c1 = (*cit1).coeff; sum.push_back(a.combine_ex_with_coeff_to_pair((new mul(r,r1))->setflag(status_flags::dynallocated), _num2().mul(ex_to_numeric(c)).mul_dyn(ex_to_numeric(c1)))); } } - + GINAC_ASSERT(sum.size()==(a.seq.size()*(a.seq.size()+1))/2); - + // second part: add terms coming from overall_factor (if != 0) - if (!a.overall_coeff.is_equal(_ex0())) { + if (!a.overall_coeff.is_zero()) { for (epvector::const_iterator cit=a.seq.begin(); cit!=a.seq.end(); ++cit) { sum.push_back(a.combine_pair_with_coeff_to_pair(*cit,ex_to_numeric(a.overall_coeff).mul_dyn(_num2()))); } sum.push_back(expair(ex_to_numeric(a.overall_coeff).power_dyn(_num2()),_ex1())); } - + GINAC_ASSERT(sum.size()==(a_nops*(a_nops+1))/2); return (new add(sum))->setflag(status_flags::dynallocated | status_flags::expanded); @@ -794,7 +787,7 @@ ex power::expand_add_2(const add & a) const * @see power::expand */ ex power::expand_mul(const mul & m, const numeric & n) const { - if (n.is_equal(_num0())) + if (n.is_zero()) return _ex1(); epvector distrseq; @@ -866,6 +859,4 @@ ex sqrt(const ex & a) return power(a,_ex1_2()); } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/power.h b/ginac/power.h index 24e46f88..8a9d65f8 100644 --- a/ginac/power.h +++ b/ginac/power.h @@ -26,9 +26,7 @@ #include "basic.h" #include "ex.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC class numeric; class add; @@ -38,16 +36,16 @@ class add; class power : public basic { GINAC_DECLARE_REGISTERED_CLASS(power, basic) - + friend class mul; - + // member functions - - // other constructors + + // other ctors public: power(const ex & lh, const ex & rh); power(const ex & lh, const numeric & rh); - + // functions overriding virtual functions from bases classes public: void print(std::ostream & os, unsigned upper_precedence = 0) const; @@ -84,9 +82,9 @@ protected: //ex expand_commutative_3(const ex & basis, const numeric & exponent, // unsigned options) const; //ex expand_noncommutative(const ex & basis, const numeric & exponent, unsigned options) const; - + // member variables - + protected: ex basis; ex exponent; @@ -106,14 +104,13 @@ inline const power &ex_to_power(const ex &e) * @param b the basis expression * @param e the exponent expression */ inline ex pow(const ex & b, const ex & e) -{ return power(b,e); } +{ + return power(b, e); +} -/** Square root expression. Returns a power-object with exponent 1/2 as a new - * expression. */ +/** Square root expression. Returns a power-object with exponent 1/2. */ ex sqrt(const ex & a); -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_POWER_H__ diff --git a/ginac/pseries.cpp b/ginac/pseries.cpp index 78986b4d..fbb7583b 100644 --- a/ginac/pseries.cpp +++ b/ginac/pseries.cpp @@ -35,19 +35,17 @@ #include "utils.h" #include "debugmsg.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC GINAC_IMPLEMENT_REGISTERED_CLASS(pseries, basic) /* - * Default constructor, destructor, copy constructor, assignment operator and helpers + * Default ctor, dtor, copy ctor, assignment operator and helpers */ pseries::pseries() : basic(TINFO_pseries) { - debugmsg("pseries default constructor", LOGLEVEL_CONSTRUCT); + debugmsg("pseries default ctor", LOGLEVEL_CONSTRUCT); } void pseries::copy(const pseries &other) @@ -66,7 +64,7 @@ void pseries::destroy(bool call_parent) /* - * Other constructors + * Other ctors */ /** Construct pseries from a vector of coefficients and powers. @@ -80,7 +78,7 @@ void pseries::destroy(bool call_parent) * @return newly constructed pseries */ pseries::pseries(const ex &rel_, const epvector &ops_) : basic(TINFO_pseries), seq(ops_) { - debugmsg("pseries constructor from ex,epvector", LOGLEVEL_CONSTRUCT); + debugmsg("pseries ctor from ex,epvector", LOGLEVEL_CONSTRUCT); GINAC_ASSERT(is_ex_exactly_of_type(rel_, relational)); GINAC_ASSERT(is_ex_exactly_of_type(rel_.lhs(),symbol)); point = rel_.rhs(); @@ -95,7 +93,7 @@ pseries::pseries(const ex &rel_, const epvector &ops_) : basic(TINFO_pseries), s /** Construct object from archive_node. */ pseries::pseries(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) { - debugmsg("pseries constructor from archive_node", LOGLEVEL_CONSTRUCT); + debugmsg("pseries ctor from archive_node", LOGLEVEL_CONSTRUCT); for (unsigned int i=0; true; ++i) { ex rest; ex coeff; @@ -411,8 +409,7 @@ ex pseries::subs(const lst & ls, const lst & lr) const /** Implementation of ex::expand() for a power series. It expands all the - * terms individually and returns the resulting series as a new pseries. - * @see ex::diff */ + * terms individually and returns the resulting series as a new pseries. */ ex pseries::expand(unsigned options) const { epvector newseq; @@ -453,10 +450,6 @@ ex pseries::derivative(const symbol & s) const } -/* - * Construct ordinary polynomial out of series - */ - /** Convert a pseries object to an ordinary polynomial. * * @param no_order flag: discard higher order terms */ @@ -476,6 +469,7 @@ ex pseries::convert_to_poly(bool no_order) const return e; } + /** Returns true if there is no order term, i.e. the series terminates and * false otherwise. */ bool pseries::is_terminating(void) const @@ -485,7 +479,7 @@ bool pseries::is_terminating(void) const /* - * Implementation of series expansion + * Implementations of series expansion */ /** Default implementation of ex::series(). This performs Taylor expansion. @@ -780,6 +774,18 @@ ex pseries::power_const(const numeric &p, int deg) const // a constant, just consider A2(x) = A(x)*x^m, with some integer m and // repeat the above derivation. The leading power of C2(x) = A2(x)^2 is // then of course x^(p*m) but the recurrence formula still holds. + + if (seq.size()==0) { + // as a spacial case, handle the empty (zero) series honoring the + // usual power laws such as implemented in power::eval() + if (p.real().is_zero()) + throw (std::domain_error("pseries::power_const(): pow(0,I) is undefined")); + else if (p.real().is_negative()) + throw (pole_error("pseries::power_const(): division by zero",1)); + else + return *this; + } + const symbol *s = static_cast(var.bp); int ldeg = ldegree(*s); @@ -932,6 +938,4 @@ ex ex::series(const ex & r, int order, unsigned options) const unsigned pseries::precedence = 38; // for clarity just below add::precedence -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/pseries.h b/ginac/pseries.h index 95d85b28..20005473 100644 --- a/ginac/pseries.h +++ b/ginac/pseries.h @@ -26,9 +26,7 @@ #include "basic.h" #include "expairseq.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC /** This class holds a extended truncated power series (positive and negative * integer powers). It consists of expression coefficients (only non-zero @@ -38,7 +36,7 @@ class pseries : public basic { GINAC_DECLARE_REGISTERED_CLASS(pseries, basic) - // other constructors + // other ctors public: pseries(const ex &rel_, const epvector &ops_); @@ -118,8 +116,6 @@ inline bool is_terminating(const pseries & s) return s.is_terminating(); } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_SERIES_H__ diff --git a/ginac/registrar.cpp b/ginac/registrar.cpp index 0d73b51a..9a747eff 100644 --- a/ginac/registrar.cpp +++ b/ginac/registrar.cpp @@ -25,9 +25,7 @@ #include "registrar.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC registered_class_info *first_registered_class = NULL; @@ -56,6 +54,4 @@ unarch_func find_unarch_func(const std::string &class_name) } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/registrar.h b/ginac/registrar.h index 2737325b..125d0998 100644 --- a/ginac/registrar.h +++ b/ginac/registrar.h @@ -25,9 +25,7 @@ #include -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC class registered_class_info; class ex; @@ -61,6 +59,7 @@ struct registered_class_info { }; +/** Primary macro for inclusion in the implementation of each registered class. */ #define GINAC_DECLARE_REGISTERED_CLASS_NO_CTORS(classname, supername) \ public: \ typedef supername inherited; \ @@ -78,7 +77,7 @@ public: \ GINAC_DECLARE_REGISTERED_CLASS_NO_CTORS(classname, supername) \ public: \ classname(); \ - ~classname(); \ + ~classname() { /*debugmsg(#classname " dtor", LOGLEVEL_DESTRUCT);*/ destroy(false); } \ classname(const classname & other); \ const classname & operator=(const classname & other); \ basic * duplicate() const; \ @@ -88,38 +87,32 @@ protected: \ int compare_same_type(const basic & other) const; \ private: +/** Primary macro for inclusion in the implementation of each registered class. */ #define GINAC_IMPLEMENT_REGISTERED_CLASS_NO_CTORS(classname, supername) \ registered_class_info classname::reg_info(#classname, #supername, TINFO_##classname, &classname::unarchive); \ const char *classname::class_name(void) const {return reg_info.name;} /** Macro for inclusion in the implementation of each registered class. * It implements some functions that are the same in all classes derived - * from 'basic' (such as the destructor, the copy constructor and the - * assignment operator). */ + * from 'basic' (such as the assignment operator). */ #define GINAC_IMPLEMENT_REGISTERED_CLASS(classname, supername) \ GINAC_IMPLEMENT_REGISTERED_CLASS_NO_CTORS(classname, supername) \ -classname::~classname() \ -{ \ - debugmsg(#classname " destructor", LOGLEVEL_DESTRUCT); \ - destroy(false); \ -} \ classname::classname(const classname & other) \ { \ - debugmsg(#classname " copy constructor", LOGLEVEL_CONSTRUCT); \ + /*debugmsg(#classname " copy ctor", LOGLEVEL_CONSTRUCT);*/ \ copy(other); \ } \ const classname & classname::operator=(const classname & other) \ { \ - debugmsg(#classname " operator=", LOGLEVEL_ASSIGNMENT); \ + /*debugmsg(#classname " operator=", LOGLEVEL_ASSIGNMENT);*/ \ if (this != &other) { \ destroy(true); \ copy(other); \ } \ return *this; \ } \ -basic * classname::duplicate() const \ -{ \ - debugmsg(#classname " duplicate", LOGLEVEL_DUPLICATE); \ +basic * classname::duplicate() const { \ + /*debugmsg(#classname " duplicate", LOGLEVEL_DUPLICATE);*/ \ return new classname(*this); \ } @@ -131,8 +124,6 @@ extern unsigned int find_tinfo_key(const std::string &class_name); extern unarch_func find_unarch_func(const std::string &class_name); -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_REGISTRAR_H__ diff --git a/ginac/relational.cpp b/ginac/relational.cpp index 8f7b4b65..b22a6387 100644 --- a/ginac/relational.cpp +++ b/ginac/relational.cpp @@ -28,21 +28,19 @@ #include "utils.h" #include "debugmsg.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC GINAC_IMPLEMENT_REGISTERED_CLASS(relational, basic) ////////// -// default constructor, destructor, copy constructor assignment operator and helpers +// default ctor, dtor, copy ctor assignment operator and helpers ////////// // public relational::relational() : basic(TINFO_relational) { - debugmsg("relational default constructor",LOGLEVEL_CONSTRUCT); + debugmsg("relational default ctor",LOGLEVEL_CONSTRUCT); } // protected @@ -61,14 +59,14 @@ void relational::destroy(bool call_parent) } ////////// -// other constructors +// other ctors ////////// // public relational::relational(const ex & lhs, const ex & rhs, operators oper) : basic(TINFO_relational) { - debugmsg("relational constructor ex,ex,operator",LOGLEVEL_CONSTRUCT); + debugmsg("relational ctor ex,ex,operator",LOGLEVEL_CONSTRUCT); lh=lhs; rh=rhs; o=oper; @@ -81,7 +79,7 @@ relational::relational(const ex & lhs, const ex & rhs, operators oper) : basic(T /** Construct object from archive_node. */ relational::relational(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) { - debugmsg("relational constructor from archive_node", LOGLEVEL_CONSTRUCT); + debugmsg("relational ctor from archive_node", LOGLEVEL_CONSTRUCT); unsigned int opi; if (!(n.find_unsigned("op", opi))) throw (std::runtime_error("unknown relational operator in archive")); @@ -252,12 +250,12 @@ ex & relational::let_op(int i) ex relational::eval(int level) const { - if (level==1) { + if (level==1) return this->hold(); - } - if (level == -max_recursion_level) { + + if (level == -max_recursion_level) throw(std::runtime_error("max recursion level reached")); - } + return (new relational(lh.eval(level-1),rh.eval(level-1),o))->setflag(status_flags::dynallocated | status_flags::evaluated); } @@ -366,8 +364,6 @@ relational::operator bool() const // protected -unsigned relational::precedence=20; +unsigned relational::precedence = 20; -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/relational.h b/ginac/relational.h index c988a631..15bda586 100644 --- a/ginac/relational.h +++ b/ginac/relational.h @@ -26,9 +26,7 @@ #include "basic.h" #include "ex.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC /** This class holds a relation consisting of two expressions and a logical * relation between them. */ @@ -47,7 +45,7 @@ public: greater_or_equal }; - // other constructors + // other ctors public: relational(const ex & lhs, const ex & rhs, operators oper=equal); @@ -91,8 +89,6 @@ inline const relational &ex_to_relational(const ex &e) return static_cast(*e.bp); } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_RELATIONAL_H__ diff --git a/ginac/remember.cpp b/ginac/remember.cpp index 4995c8b1..3a922730 100644 --- a/ginac/remember.cpp +++ b/ginac/remember.cpp @@ -27,9 +27,7 @@ #include "utils.h" #include "remember.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC ////////// // class remember_table_entry @@ -53,7 +51,7 @@ bool remember_table_entry::is_equal(function const & f) const return true; } -unsigned long remember_table_entry::access_counter=0; +unsigned long remember_table_entry::access_counter = 0; ////////// // class remember_table_list @@ -68,8 +66,8 @@ remember_table_list::remember_table_list(unsigned as, unsigned strat) void remember_table_list::add_entry(function const & f, ex const & result) { - if ((max_assoc_size!=0)&& - (remember_strategy!=remember_strategies::delete_never)&& + if ((max_assoc_size!=0) && + (remember_strategy!=remember_strategies::delete_never) && (size()>=max_assoc_size)) { // table is full, we must delete an older entry GINAC_ASSERT(size()>0); // there must be at least one entry @@ -147,7 +145,7 @@ remember_table::remember_table(unsigned s, unsigned as, unsigned strat) { // we keep max_assoc_size and remember_strategy if we need to clear // all entries - + // use some power of 2 next to s table_size = 1 << log2(s); init_table(); @@ -186,6 +184,4 @@ std::vector & remember_table::remember_tables(void) return *rt; } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/remember.h b/ginac/remember.h index a068f5a9..f9f12540 100644 --- a/ginac/remember.h +++ b/ginac/remember.h @@ -27,9 +27,7 @@ #include #include -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC class function; class ex; @@ -97,8 +95,6 @@ protected: unsigned remember_strategy; }; -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_REMEMBER_H__ diff --git a/ginac/simp_lor.cpp b/ginac/simp_lor.cpp index ed79d753..0734439e 100644 --- a/ginac/simp_lor.cpp +++ b/ginac/simp_lor.cpp @@ -35,9 +35,7 @@ #include "debugmsg.h" #include "utils.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC GINAC_IMPLEMENT_REGISTERED_CLASS(simp_lor, indexed) @@ -436,7 +434,7 @@ ex simplify_simp_lor_mul(const ex & m, const scalar_products & sp) ex simplify_simp_lor(const ex & e, const scalar_products & sp) { // all simplification is done on expanded objects - ex e_expanded=e.expand(); + ex e_expanded = e.expand(); // simplification of sum=sum of simplifications if (is_ex_exactly_of_type(e_expanded,add)) { @@ -507,6 +505,4 @@ spmapkey scalar_products::make_key(const simp_lor & v1, const simp_lor & v2) return spmapkey(strstrpair(v1.name,v2.name),anon); } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/simp_lor.h b/ginac/simp_lor.h index 4b4e239c..1fcf84fc 100644 --- a/ginac/simp_lor.h +++ b/ginac/simp_lor.h @@ -31,9 +31,7 @@ #include "indexed.h" #include "lorentzidx.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC typedef std::pair strstrpair; typedef std::pair spmapkey; @@ -142,8 +140,6 @@ simp_lor lor_vec(const std::string & n, const ex & mu); ex simplify_simp_lor_mul(const ex & m, const scalar_products & sp); ex simplify_simp_lor(const ex & e, const scalar_products & sp=scalar_products()); -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef _SIMP__GINAC_LOR_H__ diff --git a/ginac/structure.cpp b/ginac/structure.cpp index 39c09bf1..35b53e3c 100644 --- a/ginac/structure.cpp +++ b/ginac/structure.cpp @@ -26,21 +26,19 @@ #include "archive.h" #include "debugmsg.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC GINAC_IMPLEMENT_REGISTERED_CLASS(structure, basic) ////////// -// default constructor, destructor, copy constructor assignment operator and helpers +// default ctor, dtor, copy ctor assignment operator and helpers ////////// // public structure::structure() { - debugmsg("structure default constructor",LOGLEVEL_CONSTRUCT); + debugmsg("structure default ctor",LOGLEVEL_CONSTRUCT); tinfo_key = TINFO_structure; } @@ -57,7 +55,7 @@ void structure::destroy(bool call_parent) } ////////// -// other constructors +// other ctors ////////// // none @@ -69,7 +67,7 @@ void structure::destroy(bool call_parent) /** Construct object from archive_node. */ structure::structure(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) { - debugmsg("structure constructor from archive_node", LOGLEVEL_CONSTRUCT); + debugmsg("structure ctor from archive_node", LOGLEVEL_CONSTRUCT); } /** Unarchive the object. */ @@ -162,6 +160,4 @@ unsigned structure::register_new(const char * nm) return registered_structures().size()-1; } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/structure.h b/ginac/structure.h index 365f5691..12b86d1c 100644 --- a/ginac/structure.h +++ b/ginac/structure.h @@ -25,9 +25,7 @@ #include "basic.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC struct registered_structure_info { const char * name; @@ -42,8 +40,8 @@ struct registered_structure_info { class structure : public basic { GINAC_DECLARE_REGISTERED_CLASS(structure, basic) - - // other constructors + + // other ctors // none // functions overriding virtual functions from bases classes @@ -69,8 +67,6 @@ public: }; -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_STRUCTURE_H__ diff --git a/ginac/structure.pl b/ginac/structure.pl index 06469b15..e46bf4b2 100755 --- a/ginac/structure.pl +++ b/ginac/structure.pl @@ -150,15 +150,13 @@ ${input_structure} #include "structure.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC class ${STRUCTURE} : public structure { // member functions - // default constructor, destructor, copy constructor assignment operator and helpers + // default ctor, dtor, copy ctor assignment operator and helpers public: ${STRUCTURE}(); ~${STRUCTURE}(); @@ -168,7 +166,7 @@ protected: void copy(${STRUCTURE} const & other); void destroy(bool call_parent); - // other constructors + // other ctors public: ${STRUCTURE}(${constructor_arglist}); @@ -217,9 +215,7 @@ extern const unsigned tinfo_${STRUCTURE}; #define ex_to_${STRUCTURE}(X) (static_cast<${STRUCTURE} const &>(*(X).bp)) -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef _${STRUCTURE_UC}_H_ @@ -258,19 +254,17 @@ ${input_structure} #include "${STRUCTURE}.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC ////////// -// default constructor, destructor, copy constructor assignment operator and helpers +// default ctor, destructor, copy ctor assignment operator and helpers ////////// // public ${STRUCTURE}::${STRUCTURE}() { - debugmsg("${STRUCTURE} default constructor",LOGLEVEL_CONSTRUCT); + debugmsg("${STRUCTURE} default ctor",LOGLEVEL_CONSTRUCT); tinfo_key=tinfo_${STRUCTURE}; } @@ -282,7 +276,7 @@ ${STRUCTURE}::~${STRUCTURE}() ${STRUCTURE}::${STRUCTURE}(${STRUCTURE} const & other) { - debugmsg("${STRUCTURE} copy constructor",LOGLEVEL_CONSTRUCT); + debugmsg("${STRUCTURE} copy ctor",LOGLEVEL_CONSTRUCT); copy(other); } @@ -310,7 +304,7 @@ void ${STRUCTURE}::destroy(bool call_parent) } ////////// -// other constructors +// other ctors ////////// // public @@ -318,7 +312,7 @@ void ${STRUCTURE}::destroy(bool call_parent) ${STRUCTURE}::${STRUCTURE}(${constructor_arglist}) : ${constructor_statements} { - debugmsg("${STRUCTURE} constructor from children", LOGLEVEL_CONSTRUCT); + debugmsg("${STRUCTURE} ctor from children", LOGLEVEL_CONSTRUCT); tinfo_key=tinfo_${STRUCTURE}; } @@ -513,9 +507,7 @@ const ${STRUCTURE} some_${STRUCTURE}; const type_info & typeid_${STRUCTURE}=typeid(some_${STRUCTURE}); const unsigned tinfo_${STRUCTURE}=structure::register_new("${STRUCTURE}"); -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC END_OF_IMPLEMENTATION diff --git a/ginac/symbol.cpp b/ginac/symbol.cpp index 2657900a..169ee631 100644 --- a/ginac/symbol.cpp +++ b/ginac/symbol.cpp @@ -30,37 +30,23 @@ #include "debugmsg.h" #include "utils.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC GINAC_IMPLEMENT_REGISTERED_CLASS_NO_CTORS(symbol, basic) ////////// -// default constructor, destructor, copy constructor assignment operator and helpers +// default ctor, dtor, copy ctor assignment operator and helpers ////////// -symbol::symbol() : inherited(TINFO_symbol) +symbol::symbol() : inherited(TINFO_symbol), serial(next_serial++) { - debugmsg("symbol default constructor", LOGLEVEL_CONSTRUCT); - serial = next_serial++; + debugmsg("symbol default ctor", LOGLEVEL_CONSTRUCT); name = autoname_prefix()+ToString(serial); asexinfop = new assigned_ex_info; - setflag(status_flags::evaluated); -} - -symbol::~symbol() -{ - debugmsg("symbol destructor", LOGLEVEL_DESTRUCT); - destroy(0); -} - -symbol::symbol(const symbol & other) -{ - debugmsg("symbol copy constructor", LOGLEVEL_CONSTRUCT); - copy(other); + setflag(status_flags::evaluated | status_flags::expanded); } +/** For use by copy ctor and assignment operator. */ void symbol::copy(const symbol & other) { inherited::copy(other); @@ -72,33 +58,31 @@ void symbol::copy(const symbol & other) void symbol::destroy(bool call_parent) { - if (--asexinfop->refcount == 0) { + if (--asexinfop->refcount == 0) delete asexinfop; - } - if (call_parent) { + if (call_parent) inherited::destroy(call_parent); - } } -// how should the following be interpreted? -// symbol x; -// symbol y; -// x=y; -// probably as: x=ex(y); - ////////// -// other constructors +// other ctors ////////// // public +symbol::symbol(const symbol & other) +{ + debugmsg("symbol copy ctor", LOGLEVEL_CONSTRUCT); + copy(other); +} + symbol::symbol(const std::string & initname) : inherited(TINFO_symbol) { - debugmsg("symbol constructor from string", LOGLEVEL_CONSTRUCT); + debugmsg("symbol ctor from string", LOGLEVEL_CONSTRUCT); name = initname; serial = next_serial++; asexinfop = new assigned_ex_info; - setflag(status_flags::evaluated); + setflag(status_flags::evaluated | status_flags::expanded); } ////////// @@ -108,7 +92,7 @@ symbol::symbol(const std::string & initname) : inherited(TINFO_symbol) /** Construct object from archive_node. */ symbol::symbol(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) { - debugmsg("symbol constructor from archive_node", LOGLEVEL_CONSTRUCT); + debugmsg("symbol ctor from archive_node", LOGLEVEL_CONSTRUCT); serial = next_serial++; if (!(n.find_string("name", name))) name = autoname_prefix() + ToString(serial); @@ -120,7 +104,7 @@ symbol::symbol(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst ex symbol::unarchive(const archive_node &n, const lst &sym_lst) { ex s = (new symbol(n, sym_lst))->setflag(status_flags::dynallocated); - + // If symbol is in sym_lst, return the existing symbol for (unsigned i=0; iis_equal(*other.bp)) + return true; + else + return false; } int symbol::degree(const symbol & s) const @@ -215,26 +200,23 @@ int symbol::ldegree(const symbol & s) const ex symbol::coeff(const symbol & s, int n) const { - if (compare_same_type(s)==0) { + if (compare_same_type(s)==0) return n==1 ? _ex1() : _ex0(); - } else { + else return n==0 ? *this : _ex0(); - } } ex symbol::eval(int level) const { - if (level == -max_recursion_level) { + if (level == -max_recursion_level) throw(std::runtime_error("max recursion level reached")); - } if (asexinfop->is_assigned) { setflag(status_flags::evaluated); - if (level==1) { + if (level==1) return (asexinfop->assigned_expression); - } else { + else return (asexinfop->assigned_expression).eval(level); - } } else { return this->hold(); } @@ -244,15 +226,15 @@ ex symbol::subs(const lst & ls, const lst & lr) const { GINAC_ASSERT(ls.nops()==lr.nops()); #ifdef DO_GINAC_ASSERT - for (unsigned i=0; iis_assigned=1; - asexinfop->assigned_expression=value; - clearflag(status_flags::evaluated); + asexinfop->is_assigned = 1; + asexinfop->assigned_expression = value; + clearflag(status_flags::evaluated | status_flags::expanded); } void symbol::unassign(void) { if (asexinfop->is_assigned) { - asexinfop->is_assigned=0; - asexinfop->assigned_expression=_ex0(); + asexinfop->is_assigned = 0; + asexinfop->assigned_expression = _ex0(); } - setflag(status_flags::evaluated); + setflag(status_flags::evaluated | status_flags::expanded); } // private +/** Symbols not constructed with a string get one assigned using this + * prefix and a number. */ std::string & symbol::autoname_prefix(void) { - static std::string * s=new std::string("symbol"); + static std::string *s = new std::string("symbol"); return *s; } @@ -348,9 +333,7 @@ std::string & symbol::autoname_prefix(void) // private -unsigned symbol::next_serial=0; - -// std::string const symbol::autoname_prefix="symbol"; +unsigned symbol::next_serial = 0; ////////// // subclass assigned_ex_info @@ -361,6 +344,4 @@ symbol::assigned_ex_info::assigned_ex_info(void) : is_assigned(0), refcount(1) { } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/symbol.h b/ginac/symbol.h index c604bf56..425f85b9 100644 --- a/ginac/symbol.h +++ b/ginac/symbol.h @@ -27,9 +27,7 @@ #include "basic.h" #include "ex.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC /** Basic CAS symbol. It has a name because it must know how to output itself. * It may be assigned an expression, but this feature is only intended for @@ -40,33 +38,37 @@ namespace GiNaC { class symbol : public basic { GINAC_DECLARE_REGISTERED_CLASS_NO_CTORS(symbol, basic) - + // types - - /** Symbols as keys to expressions. */ + + /** Symbols as keys to expressions - this is deprecated. */ class assigned_ex_info { public: - assigned_ex_info(); //! Default ctor - bool is_assigned; //! True if there is an expression assigned - ex assigned_expression; //! The actual expression - unsigned refcount; //! Yet another refcounter. PLEASE EXPLAIN! + assigned_ex_info(); ///< Default ctor + bool is_assigned; ///< True if there is an expression assigned + ex assigned_expression; ///< The actual expression + unsigned refcount; ///< Reference counter }; // member functions - - // default constructor, destructor, copy constructor assignment operator and helpers + + // default ctor, dtor, copy ctor assignment operator and helpers public: symbol(); - ~symbol(); + ~symbol() + { + /*debugmsg("symbol dtor", LOGLEVEL_DESTRUCT);*/ + destroy(false); + } symbol(const symbol & other); protected: void copy(const symbol & other); void destroy(bool call_parent); - - // other constructors + + // other ctors public: explicit symbol(const std::string & initname); - + // functions overriding virtual functions from base classes public: basic * duplicate() const; @@ -105,19 +107,21 @@ private: // member variables protected: - assigned_ex_info * asexinfop; - unsigned serial; //!< unique serial number for comparision - std::string name; + assigned_ex_info * asexinfop; ///< ptr to assigned expression, deprecated + unsigned serial; ///< unique serial number for comparison + std::string name; ///< printname of this symbol private: static unsigned next_serial; }; + // utility functions inline const symbol &ex_to_symbol(const ex &e) { return static_cast(*e.bp); } + // wrapper functions around member functions inline void unassign(symbol & symarg) { symarg.unassign(); } @@ -128,8 +132,6 @@ inline int degree(const symbol & a, const symbol & s) inline int ldegree(const symbol & a, const symbol & s) { return a.ldegree(s); } -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_SYMBOL_H__ diff --git a/ginac/tinfos.h b/ginac/tinfos.h index 77014d93..927cf79c 100644 --- a/ginac/tinfos.h +++ b/ginac/tinfos.h @@ -23,9 +23,7 @@ #ifndef __GINAC_TINFOS_H__ #define __GINAC_TINFOS_H__ -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC const unsigned TINFO_basic = 0x00000001U; @@ -70,8 +68,6 @@ const unsigned TINFO_idx = 0x000d0001U; const unsigned TINFO_coloridx = 0x000d1001U; const unsigned TINFO_lorentzidx = 0x000d1002U; -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_TINFOS_H__ diff --git a/ginac/utils.cpp b/ginac/utils.cpp index 374f3bc4..93408d4c 100644 --- a/ginac/utils.cpp +++ b/ginac/utils.cpp @@ -26,9 +26,7 @@ #include "utils.h" #include "version.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC /* Version information buried into the library */ const int version_major = GINACLIB_MAJOR_VERSION; @@ -55,23 +53,12 @@ int pole_error::degree(void) const unsigned log2(unsigned n) { unsigned k; - for (k = 0; n > 1; n >>= 1) ++k; + for (k = 0; n > 1; n >>= 1) + ++k; return k; } #endif -/** Compare two pointers (just to establish some sort of canonical order). - * @return -1, 0, or 1 */ -int compare_pointers(const void * a, const void * b) -{ - if (ab) { - return 1; - } - return 0; -} - /** Append one exvector to another */ void append_exvector_to_exvector(exvector & dest, const exvector & source) { @@ -774,10 +761,10 @@ const ex & _ex120(void) // member functions - // default constructor, destructor, copy constructor assignment operator and helpers + // default ctor, dtor, copy ctor assignment operator and helpers // none - // other constructors + // other ctors // none // functions overriding virtual functions from bases classes @@ -798,14 +785,14 @@ const ex & _ex120(void) ////////// -// default constructor, destructor, copy constructor assignment operator and helpers +// default ctor, dtor, copy ctor assignment operator and helpers ////////// // public // protected ////////// -// other constructors +// other ctors ////////// // public @@ -844,6 +831,4 @@ const ex & _ex120(void) // none -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/utils.h b/ginac/utils.h index e278f36e..5f34d025 100644 --- a/ginac/utils.h +++ b/ginac/utils.h @@ -30,11 +30,9 @@ #include "config.h" #include "assertion.h" -#ifndef NO_NAMESPACE_GINAC namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC -// This should be obsoleted once is widely available. +// This should be obsoleted once is widely deployed. template std::string ToString(const T & t) { @@ -61,96 +59,60 @@ private: unsigned log2(unsigned n); #endif -int compare_pointers(const void * a, const void * b); +/** Compare two pointers (just to establish some sort of canonical order). + * @return -1, 0, or 1 */ +inline int compare_pointers(const void * a, const void * b) +{ + if (ab) + return 1; + return 0; +} /** Rotate lower 31 bits of unsigned value by one bit to the left - * (upper bits get cleared). */ + * (upper bit gets cleared). */ inline unsigned rotate_left_31(unsigned n) { // clear highest bit and shift 1 bit to the left - n=(n & 0x7FFFFFFFU) << 1; - + n = (n & 0x7FFFFFFFU) << 1; + // overflow? clear highest bit and set lowest bit - if (n & 0x80000000U) { - n=(n & 0x7FFFFFFFU) | 0x00000001U; - } + if (n & 0x80000000U) + n = (n & 0x7FFFFFFFU) | 0x00000001U; + GINAC_ASSERT(n<0x80000000U); - + return n; } -/** Golden ratio hash function. */ +/** Golden ratio hash function for the 31 least significant bits. */ inline unsigned golden_ratio_hash(unsigned n) { // This function requires arithmetic with at least 64 significant bits -#if SIZEOF_LONG_DOUBLE > 8 - // If "long double" is bigger than 64 bits, we assume that the mantissa - // has at least 64 bits. This is not guaranteed but it's a good guess. - const static long double golden_ratio = .618033988749894848204586834370; - long double m = golden_ratio * n; - return unsigned((m - int(m)) * 0x80000000); -#elif SIZEOF_LONG >= 8 - // "long" has 64 bits, so we prefer it because it might be more efficient - // than "long long" +#if SIZEOF_LONG >= 8 + // So 'long' has 64 bits. Excellent! We prefer it because it might be + // more efficient than 'long long'. unsigned long l = n * 0x4f1bbcddL; return (l & 0x7fffffffU) ^ (l >> 32); #elif SIZEOF_LONG_LONG >= 8 - // This requires ´long long´ (or an equivalent 64 bit type)---which is, - // unfortunately, not ANSI-compliant: - unsigned long long l = n * 0x4f1bbcddLL; + // This requires 'long long' (or an equivalent 64 bit type)---which is, + // unfortunately, not ANSI-C++-compliant. + // (Yet C99 demands it, which is reason for hope.) + unsigned long long l = n * 0x4f1bbcddL; return (l & 0x7fffffffU) ^ (l >> 32); +#elif SIZEOF_LONG_DOUBLE > 8 + // If 'long double' is bigger than 64 bits, we assume that the mantissa + // has at least 64 bits. This is not guaranteed but it's a good guess. + // Unfortunately, it may lead to horribly slow code. + const static long double golden_ratio = .618033988749894848204586834370; + long double m = golden_ratio * n; + return unsigned((m - int(m)) * 0x80000000); #else #error "No 64 bit data type. You lose." #endif } -// modified from stl_algo.h: always do com(*first1,*first2) instead of comp(*first2,*first1) -template -OutputIterator mymerge(InputIterator1 first1, InputIterator1 last1, - InputIterator2 first2, InputIterator2 last2, - OutputIterator result, Compare comp) { - while (first1 != last1 && first2 != last2) { - if (comp(*first1, *first2)) { - *result = *first1; - ++first1; - } - else { - *result = *first2; - ++first2; - } - ++result; - } - return copy(first2, last2, copy(first1, last1, result)); -} - -// like merge(), but three lists with *last2<*first3 -template -OutputIterator mymerge3(InputIterator1 first1, InputIterator1 last1, - InputIterator2 first2, InputIterator2 last2, - InputIterator3 first3, InputIterator3 last3, - OutputIterator result, Compare comp) { - while (first1 != last1 && first2 != last2) { - if (comp(*first1, *first2)) { - *result = *first1; - ++first1; - } - else { - *result = *first2; - ++first2; - } - ++result; - } - - if (first1==last1) { - // list1 empty, copy rest of list2, then list3 - return copy(first3, last3, copy(first2, last2, result)); - } else { - // list2 empty, merge rest of list1 with list3 - return mymerge(first1,last1,first3,last3,result,comp); - } -} - // Compute the sign of a permutation of a vector of things. template int permutation_sign(std::vector s) @@ -281,8 +243,6 @@ const ex & _ex60(void); const numeric & _num120(void); // 120 const ex & _ex120(void); -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC #endif // ndef __GINAC_UTILS_H__ -- 2.45.0