From 703c6cebb5d3d395437e73e6935f3691aed68e0a Mon Sep 17 00:00:00 2001 From: Christian Bauer Date: Fri, 11 Aug 2000 19:07:15 +0000 Subject: [PATCH] - indentation is now done with tabs - printtree() prints the class names as known to the registrar, not the (mangled) class names from typeid().name() --- ginac/add.cpp | 639 +++++----- ginac/add.h | 114 +- ginac/archive.cpp | 12 +- ginac/archive.h | 4 +- ginac/basic.cpp | 386 +++--- ginac/basic.h | 196 +-- ginac/clifford.cpp | 120 +- ginac/clifford.h | 58 +- ginac/color.cpp | 1470 +++++++++++----------- ginac/color.h | 148 +-- ginac/coloridx.cpp | 150 +-- ginac/coloridx.h | 52 +- ginac/constant.cpp | 148 +-- ginac/constant.h | 66 +- ginac/ex.cpp | 670 +++++----- ginac/ex.h | 394 +++--- ginac/expair.h | 294 ++--- ginac/expairseq.cpp | 2552 +++++++++++++++++++-------------------- ginac/expairseq.h | 234 ++-- ginac/exprseq_suppl.cpp | 10 +- ginac/fail.cpp | 46 +- ginac/fail.h | 42 +- ginac/flags.h | 168 +-- ginac/idx.cpp | 510 ++++---- ginac/idx.h | 82 +- ginac/indexed.cpp | 224 ++-- ginac/indexed.h | 82 +- ginac/inifcns.cpp | 634 +++++----- ginac/inifcns.h | 14 +- ginac/inifcns_gamma.cpp | 730 +++++------ ginac/inifcns_trans.cpp | 1250 +++++++++---------- ginac/inifcns_zeta.cpp | 100 +- ginac/input_lexer.h | 2 +- ginac/isospin.cpp | 150 +-- ginac/isospin.h | 60 +- ginac/lorentzidx.cpp | 256 ++-- ginac/lorentzidx.h | 66 +- ginac/lortensor.cpp | 500 ++++---- ginac/lortensor.h | 136 +-- ginac/lst_suppl.cpp | 4 +- ginac/matrix.cpp | 1664 ++++++++++++------------- ginac/matrix.h | 112 +- ginac/mul.cpp | 1034 ++++++++-------- ginac/mul.h | 126 +- ginac/ncmul.cpp | 786 ++++++------ ginac/ncmul.h | 104 +- ginac/normal.cpp | 2060 +++++++++++++++---------------- ginac/numeric.cpp | 1894 ++++++++++++++--------------- ginac/numeric.h | 256 ++-- ginac/operators.cpp | 146 +-- ginac/power.cpp | 1176 +++++++++--------- ginac/power.h | 100 +- ginac/pseries.cpp | 1128 ++++++++--------- ginac/pseries.h | 96 +- ginac/registrar.h | 42 +- ginac/relational.cpp | 444 +++---- ginac/relational.h | 90 +- ginac/remember.cpp | 186 +-- ginac/remember.h | 90 +- ginac/simp_lor.cpp | 558 ++++----- ginac/simp_lor.h | 146 +-- ginac/structure.cpp | 72 +- ginac/structure.h | 58 +- ginac/symbol.cpp | 258 ++-- ginac/symbol.h | 104 +- ginac/utils.cpp | 538 ++++----- ginac/utils.h | 140 +-- 67 files changed, 13088 insertions(+), 13093 deletions(-) diff --git a/ginac/add.cpp b/ginac/add.cpp index f85617c6..40ccc23f 100644 --- a/ginac/add.cpp +++ b/ginac/add.cpp @@ -43,42 +43,42 @@ GINAC_IMPLEMENT_REGISTERED_CLASS(add, expairseq) add::add() { - debugmsg("add default constructor",LOGLEVEL_CONSTRUCT); - tinfo_key = TINFO_add; + debugmsg("add default constructor",LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_add; } add::~add() { - debugmsg("add destructor",LOGLEVEL_DESTRUCT); - destroy(0); + debugmsg("add destructor",LOGLEVEL_DESTRUCT); + destroy(0); } add::add(const add & other) { - debugmsg("add copy constructor",LOGLEVEL_CONSTRUCT); - copy(other); + debugmsg("add copy constructor",LOGLEVEL_CONSTRUCT); + copy(other); } const add & add::operator=(const add & other) { - debugmsg("add operator=",LOGLEVEL_ASSIGNMENT); - if (this != &other) { - destroy(1); - copy(other); - } - return *this; + debugmsg("add operator=",LOGLEVEL_ASSIGNMENT); + if (this != &other) { + destroy(1); + copy(other); + } + return *this; } // protected void add::copy(const add & other) { - inherited::copy(other); + inherited::copy(other); } void add::destroy(bool call_parent) { - if (call_parent) inherited::destroy(call_parent); + if (call_parent) inherited::destroy(call_parent); } ////////// @@ -89,66 +89,66 @@ void add::destroy(bool call_parent) add::add(const ex & lh, const ex & rh) { - debugmsg("add constructor from ex,ex",LOGLEVEL_CONSTRUCT); - tinfo_key = TINFO_add; - overall_coeff = _ex0(); - construct_from_2_ex(lh,rh); - GINAC_ASSERT(is_canonical()); + debugmsg("add constructor from ex,ex",LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_add; + overall_coeff = _ex0(); + construct_from_2_ex(lh,rh); + GINAC_ASSERT(is_canonical()); } add::add(const exvector & v) { - debugmsg("add constructor from exvector",LOGLEVEL_CONSTRUCT); - tinfo_key = TINFO_add; - overall_coeff = _ex0(); - construct_from_exvector(v); - GINAC_ASSERT(is_canonical()); + debugmsg("add constructor from exvector",LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_add; + overall_coeff = _ex0(); + construct_from_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; + 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 + combine_same_terms(); // to build hashtab #endif // def EXPAIRSEQ_USE_HASHTAB - } else { - construct_from_epvector(v); - } - GINAC_ASSERT(is_canonical()); + } else { + construct_from_epvector(v); + } + GINAC_ASSERT(is_canonical()); } */ add::add(const epvector & v) { - debugmsg("add constructor from epvector",LOGLEVEL_CONSTRUCT); - tinfo_key = TINFO_add; - overall_coeff = _ex0(); - construct_from_epvector(v); - GINAC_ASSERT(is_canonical()); + debugmsg("add constructor from epvector",LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_add; + overall_coeff = _ex0(); + construct_from_epvector(v); + GINAC_ASSERT(is_canonical()); } add::add(const epvector & v, const ex & oc) { - debugmsg("add constructor from epvector,ex",LOGLEVEL_CONSTRUCT); - tinfo_key = TINFO_add; - overall_coeff = oc; - construct_from_epvector(v); - GINAC_ASSERT(is_canonical()); + debugmsg("add constructor from epvector,ex",LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_add; + overall_coeff = oc; + construct_from_epvector(v); + GINAC_ASSERT(is_canonical()); } add::add(epvector * vp, const ex & oc) { - debugmsg("add constructor from epvector *,ex",LOGLEVEL_CONSTRUCT); - tinfo_key = TINFO_add; - GINAC_ASSERT(vp!=0); - overall_coeff = oc; - construct_from_epvector(*vp); - delete vp; - GINAC_ASSERT(is_canonical()); + debugmsg("add constructor from epvector *,ex",LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_add; + GINAC_ASSERT(vp!=0); + overall_coeff = oc; + construct_from_epvector(*vp); + delete vp; + GINAC_ASSERT(is_canonical()); } ////////// @@ -158,19 +158,19 @@ add::add(epvector * vp, const ex & oc) /** Construct object from archive_node. */ add::add(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) { - debugmsg("add constructor from archive_node", LOGLEVEL_CONSTRUCT); + debugmsg("add constructor from archive_node", LOGLEVEL_CONSTRUCT); } /** Unarchive the object. */ ex add::unarchive(const archive_node &n, const lst &sym_lst) { - return (new add(n, sym_lst))->setflag(status_flags::dynallocated); + return (new add(n, sym_lst))->setflag(status_flags::dynallocated); } /** Archive the object. */ void add::archive(archive_node &n) const { - inherited::archive(n); + inherited::archive(n); } ////////// @@ -181,242 +181,242 @@ void add::archive(archive_node &n) const basic * add::duplicate() const { - debugmsg("add duplicate",LOGLEVEL_DUPLICATE); - return new add(*this); + debugmsg("add duplicate",LOGLEVEL_DUPLICATE); + return new add(*this); } void add::print(std::ostream & os, unsigned upper_precedence) const { - debugmsg("add print",LOGLEVEL_PRINT); - if (precedence<=upper_precedence) os << "("; - numeric coeff; - bool first = true; - // first print the overall numeric coefficient, if present: - if (!overall_coeff.is_zero()) { - os << overall_coeff; - first = false; - } - // then proceed with the remaining factors: - for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { - coeff = ex_to_numeric(cit->coeff); - if (!first) { - if (coeff.csgn()==-1) os << '-'; else os << '+'; - } else { - if (coeff.csgn()==-1) os << '-'; - first = false; - } - if (!coeff.is_equal(_num1()) && - !coeff.is_equal(_num_1())) { - if (coeff.is_rational()) { - if (coeff.is_negative()) - os << -coeff; - else - os << coeff; - } else { - if (coeff.csgn()==-1) - (-coeff).print(os, precedence); - else - coeff.print(os, precedence); - } - os << '*'; - } - os << cit->rest; - } - if (precedence<=upper_precedence) os << ")"; + debugmsg("add print",LOGLEVEL_PRINT); + if (precedence<=upper_precedence) os << "("; + numeric coeff; + bool first = true; + // first print the overall numeric coefficient, if present: + if (!overall_coeff.is_zero()) { + os << overall_coeff; + first = false; + } + // then proceed with the remaining factors: + for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { + coeff = ex_to_numeric(cit->coeff); + if (!first) { + if (coeff.csgn()==-1) os << '-'; else os << '+'; + } else { + if (coeff.csgn()==-1) os << '-'; + first = false; + } + if (!coeff.is_equal(_num1()) && + !coeff.is_equal(_num_1())) { + if (coeff.is_rational()) { + if (coeff.is_negative()) + os << -coeff; + else + os << coeff; + } else { + if (coeff.csgn()==-1) + (-coeff).print(os, precedence); + else + coeff.print(os, precedence); + } + os << '*'; + } + os << cit->rest; + } + if (precedence<=upper_precedence) os << ")"; } void add::printraw(std::ostream & os) const { - debugmsg("add printraw",LOGLEVEL_PRINT); + debugmsg("add printraw",LOGLEVEL_PRINT); - os << "+("; - for (epvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) { - os << "("; - (*it).rest.bp->printraw(os); - os << ","; - (*it).coeff.bp->printraw(os); - os << "),"; - } - os << ",hash=" << hashvalue << ",flags=" << flags; - os << ")"; + os << "+("; + for (epvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) { + os << "("; + (*it).rest.bp->printraw(os); + os << ","; + (*it).coeff.bp->printraw(os); + os << "),"; + } + os << ",hash=" << hashvalue << ",flags=" << flags; + os << ")"; } void add::printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const { - 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); - } else if (it->coeff.compare(_num_1()) == 0) { - os << "-"; - it->rest.bp->printcsrc(os, type, precedence); - } else if (ex_to_numeric(it->coeff).numer().compare(_num1()) == 0) { - it->rest.bp->printcsrc(os, type, precedence); - os << "/"; - ex_to_numeric(it->coeff).denom().printcsrc(os, type, precedence); - } else if (ex_to_numeric(it->coeff).numer().compare(_num_1()) == 0) { - os << "-"; - it->rest.bp->printcsrc(os, type, precedence); - os << "/"; - ex_to_numeric(it->coeff).denom().printcsrc(os, type, precedence); - } else { - it->coeff.bp->printcsrc(os, type, 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.info(info_flags::positive)) os << '+'; - overall_coeff.bp->printcsrc(os,type,precedence); - } - - if (precedence <= upper_precedence) - os << ")"; + 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); + } else if (it->coeff.compare(_num_1()) == 0) { + os << "-"; + it->rest.bp->printcsrc(os, type, precedence); + } else if (ex_to_numeric(it->coeff).numer().compare(_num1()) == 0) { + it->rest.bp->printcsrc(os, type, precedence); + os << "/"; + ex_to_numeric(it->coeff).denom().printcsrc(os, type, precedence); + } else if (ex_to_numeric(it->coeff).numer().compare(_num_1()) == 0) { + os << "-"; + it->rest.bp->printcsrc(os, type, precedence); + os << "/"; + ex_to_numeric(it->coeff).denom().printcsrc(os, type, precedence); + } else { + it->coeff.bp->printcsrc(os, type, 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.info(info_flags::positive)) os << '+'; + overall_coeff.bp->printcsrc(os,type,precedence); + } + + if (precedence <= upper_precedence) + os << ")"; } bool add::info(unsigned inf) const { - switch (inf) { - case info_flags::polynomial: - case info_flags::integer_polynomial: - case info_flags::cinteger_polynomial: - case info_flags::rational_polynomial: - case info_flags::crational_polynomial: - case info_flags::rational_function: { - for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) { - if (!(recombine_pair_to_ex(*i).info(inf))) - return false; - } - return overall_coeff.info(inf); - } - case info_flags::algebraic: { - for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) { - if ((recombine_pair_to_ex(*i).info(inf))) - return true; - } - return false; - } - } - return inherited::info(inf); + switch (inf) { + case info_flags::polynomial: + case info_flags::integer_polynomial: + case info_flags::cinteger_polynomial: + case info_flags::rational_polynomial: + case info_flags::crational_polynomial: + case info_flags::rational_function: { + for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) { + if (!(recombine_pair_to_ex(*i).info(inf))) + return false; + } + return overall_coeff.info(inf); + } + case info_flags::algebraic: { + for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) { + if ((recombine_pair_to_ex(*i).info(inf))) + return true; + } + return false; + } + } + return inherited::info(inf); } int add::degree(const symbol & s) const { - int deg = INT_MIN; - 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; - } - return deg; + int deg = INT_MIN; + 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; + } + return deg; } int add::ldegree(const symbol & s) const { - int deg = INT_MAX; - 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); - if (cur_degsetflag(status_flags::dynallocated); - } - return (new add(coeffseq))->setflag(status_flags::dynallocated); + epvector::const_iterator it=seq.begin(); + while (it!=seq.end()) { + coeffseq.push_back(combine_ex_with_coeff_to_pair((*it).rest.coeff(s,n), + (*it).coeff)); + ++it; + } + if (n==0) { + return (new add(coeffseq,overall_coeff))->setflag(status_flags::dynallocated); + } + return (new add(coeffseq))->setflag(status_flags::dynallocated); } ex add::eval(int level) const { - // simplifications: +(;c) -> c - // +(x;1) -> x + // simplifications: +(;c) -> c + // +(x;1) -> x - debugmsg("add eval",LOGLEVEL_MEMBER_FUNCTION); + debugmsg("add eval",LOGLEVEL_MEMBER_FUNCTION); - epvector * evaled_seqp=evalchildren(level); - if (evaled_seqp!=0) { - // do more evaluation later - return (new add(evaled_seqp,overall_coeff))-> - setflag(status_flags::dynallocated); - } - + epvector * evaled_seqp=evalchildren(level); + if (evaled_seqp!=0) { + // do more evaluation later + return (new add(evaled_seqp,overall_coeff))-> + 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,add)); - if (is_ex_exactly_of_type((*cit).rest,numeric)) { - dbgprint(); - } - GINAC_ASSERT(!is_ex_exactly_of_type((*cit).rest,numeric)); - } + 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)) { + 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())); - return *this; - } - - int seq_size=seq.size(); - if (seq_size==0) { - // +(;c) -> c - return overall_coeff; - } else if ((seq_size==1)&&overall_coeff.is_equal(_ex0())) { - // +(x;0) -> x - return recombine_pair_to_ex(*(seq.begin())); - } - return this->hold(); + + if (flags & status_flags::evaluated) { + GINAC_ASSERT(seq.size()>0); + GINAC_ASSERT((seq.size()>1)||!overall_coeff.is_equal(_ex0())); + return *this; + } + + int seq_size=seq.size(); + if (seq_size==0) { + // +(;c) -> c + return overall_coeff; + } else if ((seq_size==1)&&overall_coeff.is_equal(_ex0())) { + // +(x;0) -> x + return recombine_pair_to_ex(*(seq.begin())); + } + return this->hold(); } exvector add::get_indices(void) const { - // FIXME: all terms in the sum should have the same indices (compatible - // tensors) however this is not checked, since there is no function yet - // which compares indices (idxvector can be unsorted) - if (seq.size()==0) { - return exvector(); - } - return (seq.begin())->rest.get_indices(); + // FIXME: all terms in the sum should have the same indices (compatible + // tensors) however this is not checked, since there is no function yet + // which compares indices (idxvector can be unsorted) + if (seq.size()==0) { + return exvector(); + } + return (seq.begin())->rest.get_indices(); } ex add::simplify_ncmul(const exvector & v) const { - if (seq.size()==0) { - return inherited::simplify_ncmul(v); - } - return (*seq.begin()).rest.simplify_ncmul(v); + if (seq.size()==0) { + return inherited::simplify_ncmul(v); + } + return (*seq.begin()).rest.simplify_ncmul(v); } // protected @@ -425,126 +425,123 @@ ex add::simplify_ncmul(const exvector & v) const * @see ex::diff */ ex add::derivative(const symbol & s) const { - // D(a+b+c)=D(a)+D(b)+D(c) - return (new add(diffchildren(s)))->setflag(status_flags::dynallocated); + // D(a+b+c)=D(a)+D(b)+D(c) + return (new add(diffchildren(s)))->setflag(status_flags::dynallocated); } int add::compare_same_type(const basic & other) const { - return inherited::compare_same_type(other); + return inherited::compare_same_type(other); } bool add::is_equal_same_type(const basic & other) const { - return inherited::is_equal_same_type(other); + return inherited::is_equal_same_type(other); } unsigned add::return_type(void) const { - if (seq.size()==0) { - return return_types::commutative; - } - return (*seq.begin()).rest.return_type(); + if (seq.size()==0) { + return return_types::commutative; + } + return (*seq.begin()).rest.return_type(); } unsigned add::return_type_tinfo(void) const { - if (seq.size()==0) { - return tinfo_key; - } - return (*seq.begin()).rest.return_type_tinfo(); + if (seq.size()==0) { + return tinfo_key; + } + return (*seq.begin()).rest.return_type_tinfo(); } ex add::thisexpairseq(const epvector & v, const ex & oc) const { - return (new add(v,oc))->setflag(status_flags::dynallocated); + return (new add(v,oc))->setflag(status_flags::dynallocated); } ex add::thisexpairseq(epvector * vp, const ex & oc) const { - return (new add(vp,oc))->setflag(status_flags::dynallocated); + return (new add(vp,oc))->setflag(status_flags::dynallocated); } 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); - ex numfactor=mulref.overall_coeff; - // mul * mulcopyp=static_cast(mulref.duplicate()); - 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); - } - return expair(e,_ex1()); + if (is_ex_exactly_of_type(e,mul)) { + const mul & mulref=ex_to_mul(e); + ex numfactor=mulref.overall_coeff; + // mul * mulcopyp=static_cast(mulref.duplicate()); + 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); + } + return expair(e,_ex1()); } expair add::combine_ex_with_coeff_to_pair(const ex & e, - const ex & c) const -{ - GINAC_ASSERT(is_ex_exactly_of_type(c,numeric)); - if (is_ex_exactly_of_type(e,mul)) { - const mul & mulref=ex_to_mul(e); - ex numfactor=mulref.overall_coeff; - //mul * mulcopyp=static_cast(mulref.duplicate()); - mul * mulcopyp=new mul(mulref); - mulcopyp->overall_coeff=_ex1(); - mulcopyp->clearflag(status_flags::evaluated); - mulcopyp->clearflag(status_flags::hash_calculated); - if (are_ex_trivially_equal(c,_ex1())) { - return expair(mulcopyp->setflag(status_flags::dynallocated),numfactor); - } else if (are_ex_trivially_equal(numfactor,_ex1())) { - return expair(mulcopyp->setflag(status_flags::dynallocated),c); - } - return expair(mulcopyp->setflag(status_flags::dynallocated), - 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()); - } - return expair(ex_to_numeric(e).mul_dyn(ex_to_numeric(c)),_ex1()); - } - return expair(e,c); -} - + const ex & c) const +{ + GINAC_ASSERT(is_ex_exactly_of_type(c, numeric)); + ex one = _ex1(); + if (is_ex_exactly_of_type(e, mul)) { + const mul &mulref = ex_to_mul(e); + ex numfactor = mulref.overall_coeff; + mul *mulcopyp = new mul(mulref); + mulcopyp->overall_coeff = one; + mulcopyp->clearflag(status_flags::evaluated); + mulcopyp->clearflag(status_flags::hash_calculated); + mulcopyp->setflag(status_flags::dynallocated); + if (are_ex_trivially_equal(c, one)) { + return expair(*mulcopyp, numfactor); + } else if (are_ex_trivially_equal(numfactor, one)) { + return expair(*mulcopyp, c); + } + 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, one)) { + return expair(e, one); + } + return expair(ex_to_numeric(e).mul_dyn(ex_to_numeric(c)), one); + } + return expair(e, c); +} + expair add::combine_pair_with_coeff_to_pair(const expair & p, - const ex & c) const + const ex & c) const { - GINAC_ASSERT(is_ex_exactly_of_type(p.coeff,numeric)); - GINAC_ASSERT(is_ex_exactly_of_type(c,numeric)); + GINAC_ASSERT(is_ex_exactly_of_type(p.coeff,numeric)); + GINAC_ASSERT(is_ex_exactly_of_type(c,numeric)); - if (is_ex_exactly_of_type(p.rest,numeric)) { - GINAC_ASSERT(ex_to_numeric(p.coeff).is_equal(_num1())); // should be normalized - return expair(ex_to_numeric(p.rest).mul_dyn(ex_to_numeric(c)),_ex1()); - } + if (is_ex_exactly_of_type(p.rest,numeric)) { + GINAC_ASSERT(ex_to_numeric(p.coeff).is_equal(_num1())); // should be normalized + return expair(ex_to_numeric(p.rest).mul_dyn(ex_to_numeric(c)),_ex1()); + } - return expair(p.rest,ex_to_numeric(p.coeff).mul_dyn(ex_to_numeric(c))); + return expair(p.rest,ex_to_numeric(p.coeff).mul_dyn(ex_to_numeric(c))); } - + ex add::recombine_pair_to_ex(const expair & p) const { - //if (p.coeff.compare(_ex1())==0) { - //if (are_ex_trivially_equal(p.coeff,_ex1())) { - if (ex_to_numeric(p.coeff).is_equal(_num1())) { - return p.rest; - } else { - return p.rest*p.coeff; - } + if (ex_to_numeric(p.coeff).is_equal(_num1())) + return p.rest; + else + return p.rest*p.coeff; } ex add::expand(unsigned options) const { - if (flags & status_flags::expanded) - return *this; - - epvector * vp = expandchildren(options); - if (vp==0) - return *this; - - return (new add(vp,overall_coeff))-> - setflag(status_flags::expanded | - status_flags::dynallocated); + if (flags & status_flags::expanded) + return *this; + + epvector * vp = expandchildren(options); + if (vp==0) + return *this; + + return (new add(vp,overall_coeff))-> + setflag(status_flags::expanded | + status_flags::dynallocated); } ////////// diff --git a/ginac/add.h b/ginac/add.h index 78464d3e..4e63665d 100644 --- a/ginac/add.h +++ b/ginac/add.h @@ -32,77 +32,77 @@ namespace GiNaC { /** Sum of expressions. */ class add : public expairseq { - GINAC_DECLARE_REGISTERED_CLASS(add, expairseq) + GINAC_DECLARE_REGISTERED_CLASS(add, expairseq) - friend class mul; - friend class ncmul; - friend class power; + friend class mul; + friend class ncmul; + friend class power; // member functions - // default constructor, destructor, copy constructor assignment operator and helpers + // default constructor, destructor, copy constructor assignment operator and helpers public: - add(); - ~add(); - add(const add & other); - const add & operator=(const add & other); + add(); + ~add(); + add(const add & other); + const add & operator=(const add & other); protected: - void copy(const add & other); - void destroy(bool call_parent); + void copy(const add & other); + void destroy(bool call_parent); - // other constructors + // 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 + 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: - basic * duplicate() const; - void print(std::ostream & os, unsigned upper_precedence=0) const; - void printraw(std::ostream & os) const; - void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence=0) const; - bool info(unsigned inf) const; - int degree(const symbol & s) const; - int ldegree(const symbol & s) const; - ex coeff(const symbol & s, int n=1) const; - ex eval(int level=0) const; - ex series(const relational & r, int order, unsigned options = 0) const; - ex normal(lst &sym_lst, lst &repl_lst, int level=0) const; - numeric integer_content(void) const; - ex smod(const numeric &xi) const; - numeric max_coefficient(void) const; - exvector get_indices(void) const; - ex simplify_ncmul(const exvector & v) const; + basic * duplicate() const; + void print(std::ostream & os, unsigned upper_precedence=0) const; + void printraw(std::ostream & os) const; + void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence=0) const; + bool info(unsigned inf) const; + int degree(const symbol & s) const; + int ldegree(const symbol & s) const; + ex coeff(const symbol & s, int n=1) const; + ex eval(int level=0) const; + ex series(const relational & r, int order, unsigned options = 0) const; + ex normal(lst &sym_lst, lst &repl_lst, int level=0) const; + numeric integer_content(void) const; + ex smod(const numeric &xi) const; + numeric max_coefficient(void) const; + exvector get_indices(void) const; + ex simplify_ncmul(const exvector & v) const; protected: - ex derivative(const symbol & s) const; - int compare_same_type(const basic & other) const; - bool is_equal_same_type(const basic & other) const; - unsigned return_type(void) const; - unsigned return_type_tinfo(void) const; - ex thisexpairseq(const epvector & v, const ex & oc) const; - ex thisexpairseq(epvector * vp, const ex & oc) const; - expair split_ex_to_pair(const ex & e) const; - expair combine_ex_with_coeff_to_pair(const ex & e, - const ex & c) const; - expair combine_pair_with_coeff_to_pair(const expair & p, - const ex & c) const; - ex recombine_pair_to_ex(const expair & p) const; - ex expand(unsigned options=0) const; - - // new virtual functions which can be overridden by derived classes - // none - - // non-virtual functions in this class - // none + ex derivative(const symbol & s) const; + int compare_same_type(const basic & other) const; + bool is_equal_same_type(const basic & other) const; + unsigned return_type(void) const; + unsigned return_type_tinfo(void) const; + ex thisexpairseq(const epvector & v, const ex & oc) const; + ex thisexpairseq(epvector * vp, const ex & oc) const; + expair split_ex_to_pair(const ex & e) const; + expair combine_ex_with_coeff_to_pair(const ex & e, + const ex & c) const; + expair combine_pair_with_coeff_to_pair(const expair & p, + const ex & c) const; + ex recombine_pair_to_ex(const expair & p) const; + ex expand(unsigned options=0) const; + + // new virtual functions which can be overridden by derived classes + // none + + // non-virtual functions in this class + // none // member variables protected: - static unsigned precedence; + static unsigned precedence; }; // global constants diff --git a/ginac/archive.cpp b/ginac/archive.cpp index d249f297..f2372313 100644 --- a/ginac/archive.cpp +++ b/ginac/archive.cpp @@ -205,7 +205,7 @@ std::ostream &operator<<(std::ostream &os, const archive_node &n) write_unsigned(os, n.props[i].type | (n.props[i].name << 3)); write_unsigned(os, n.props[i].value); } - return os; + return os; } /** Write archive to binary data stream. */ @@ -237,7 +237,7 @@ std::ostream &operator<<(std::ostream &os, const archive &ar) write_unsigned(os, num_nodes); for (unsigned int i=0; i>(std::istream &is, archive_node &n) n.props[i].name = name_type >> 3; n.props[i].value = read_unsigned(is); } - return is; + return is; } /** Read archive from binary data stream. */ @@ -287,7 +287,7 @@ std::istream &operator>>(std::istream &is, archive &ar) ar.nodes.resize(num_nodes, ar); for (unsigned int i=0; i> ar.nodes[i]; - return is; + return is; } @@ -584,8 +584,8 @@ void archive_node::printraw(std::ostream &os) const * ctor, which is currently a Cint-requirement. */ archive* archive_node::dummy_ar_creator(void) { - static archive* some_ar = new archive; - return some_ar; + static archive* some_ar = new archive; + return some_ar; } diff --git a/ginac/archive.h b/ginac/archive.h index 082a3268..fd4430da 100644 --- a/ginac/archive.h +++ b/ginac/archive.h @@ -29,8 +29,8 @@ #include namespace std { - class ostream; - class istream; + class ostream; + class istream; } #ifndef NO_NAMESPACE_GINAC diff --git a/ginac/basic.cpp b/ginac/basic.cpp index 5e3ff581..0ca273a9 100644 --- a/ginac/basic.cpp +++ b/ginac/basic.cpp @@ -50,32 +50,32 @@ GINAC_IMPLEMENT_REGISTERED_CLASS(basic, void) #ifndef INLINE_BASIC_CONSTRUCTORS basic::basic() : flags(0), refcount(0), tinfo_key(TINFO_BASIC) { - debugmsg("basic default constructor", LOGLEVEL_CONSTRUCT); - // nothing to do + debugmsg("basic default constructor", LOGLEVEL_CONSTRUCT); + // nothing to do } basic::~basic() { - debugmsg("basic destructor", LOGLEVEL_DESTRUCT); - destroy(0); - GINAC_ASSERT((!(flags & status_flags::dynallocated))||(refcount==0)); + debugmsg("basic destructor", LOGLEVEL_DESTRUCT); + destroy(0); + 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); - copy(other); + debugmsg("basic copy constructor", LOGLEVEL_CONSTRUCT); + copy(other); } #endif const basic & basic::operator=(const basic & other) { - debugmsg("basic operator=", LOGLEVEL_ASSIGNMENT); - if (this != &other) { - destroy(1); - copy(other); - } - return *this; + debugmsg("basic operator=", LOGLEVEL_ASSIGNMENT); + if (this != &other) { + destroy(1); + copy(other); + } + return *this; } // protected @@ -89,8 +89,8 @@ const basic & basic::operator=(const basic & other) #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 + debugmsg("basic constructor with tinfo_key", LOGLEVEL_CONSTRUCT); + // nothing to do } #endif @@ -101,26 +101,26 @@ 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 constructor from archive_node", LOGLEVEL_CONSTRUCT); - // Reconstruct tinfo_key from class name - std::string class_name; - if (n.find_string("class", class_name)) - tinfo_key = find_tinfo_key(class_name); - else - throw (std::runtime_error("archive node contains no class name")); + // Reconstruct tinfo_key from class name + std::string class_name; + if (n.find_string("class", class_name)) + tinfo_key = find_tinfo_key(class_name); + else + throw (std::runtime_error("archive node contains no class name")); } /** Unarchive the object. */ ex basic::unarchive(const archive_node &n, const lst &sym_lst) { - return (new basic(n, sym_lst))->setflag(status_flags::dynallocated); + return (new basic(n, sym_lst))->setflag(status_flags::dynallocated); } /** Archive the object. */ void basic::archive(archive_node &n) const { - n.add_string("class", class_name()); + n.add_string("class", class_name()); } ////////// @@ -138,31 +138,31 @@ void basic::archive(archive_node &n) const /** Output to stream formatted to be useful as ginsh input. */ void basic::print(std::ostream & os, unsigned upper_precedence) const { - debugmsg("basic print",LOGLEVEL_PRINT); - os << "[basic object]"; + debugmsg("basic print",LOGLEVEL_PRINT); + os << "[basic object]"; } /** Output to stream in ugly raw format, so brave developers can have a look * at the underlying structure. */ void basic::printraw(std::ostream & os) const { - debugmsg("basic printraw",LOGLEVEL_PRINT); - os << "[basic object]"; + debugmsg("basic printraw",LOGLEVEL_PRINT); + os << "[basic object]"; } /** Output to stream formatted in tree- (indented-) form, so developers can * have a look at the underlying structure. */ void basic::printtree(std::ostream & os, unsigned indent) const { - debugmsg("basic printtree",LOGLEVEL_PRINT); - os << std::string(indent,' ') << "type=" << typeid(*this).name() - << ", hash=" << hashvalue - << " (0x" << std::hex << hashvalue << std::dec << ")" - << ", flags=" << flags - << ", nops=" << nops() << std::endl; - for (unsigned i=0; i(this))->let_op(i); + return (const_cast(this))->let_op(i); } /** Return modifyable operand/member at position i. */ ex & basic::let_op(int i) { - throw(std::out_of_range("op() out of range")); + throw(std::out_of_range("op() out of range")); } ex basic::operator[](const ex & index) const { - if (is_exactly_of_type(*index.bp,numeric)) - return op(static_cast(*index.bp).to_int()); - - throw(std::invalid_argument("non-numeric indices not supported by this type")); + if (is_exactly_of_type(*index.bp,numeric)) + return op(static_cast(*index.bp).to_int()); + + throw(std::invalid_argument("non-numeric indices not supported by this type")); } ex basic::operator[](int i) const { - return op(i); + return op(i); } /** Search ocurrences. An object 'has' an expression if it is the expression * itself or one of the children 'has' it. */ 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; i0) { + for (unsigned i=0; ildegree(s); - int deg = this->degree(s); - for (int n=ldeg; n<=deg; n++) { - x += this->coeff(s,n)*power(s,n); - } - return x; + ex x; + int ldeg = this->ldegree(s); + int deg = this->degree(s); + for (int n=ldeg; n<=deg; n++) { + x += this->coeff(s,n)*power(s,n); + } + return x; } /* Perform automatic symbolic evaluations on expression. */ ex basic::eval(int level) const { - // There is nothing to do for basic objects: - return this->hold(); + // There is nothing to do for basic objects: + return this->hold(); } /** Evaluate object numerically. */ ex basic::evalf(int level) const { - // There is nothing to do for basic objects: - return *this; + // There is nothing to do for basic objects: + return *this; } /* Substitute a set of symbols. */ ex basic::subs(const lst & ls, const lst & lr) const { - return *this; + return *this; } /** Default interface of nth derivative ex::diff(s, n). It should be called @@ -311,31 +311,31 @@ ex basic::subs(const lst & ls, const lst & lr) const * @see ex::diff */ ex basic::diff(const symbol & s, unsigned nth) const { - // trivial: zeroth derivative - if (nth==0) - return ex(*this); - - // evaluate unevaluated *this before differentiating - if (!(flags & status_flags::evaluated)) - return ex(*this).diff(s, nth); - - ex ndiff = this->derivative(s); - while (!ndiff.is_zero() && // stop differentiating zeros - nth>1) { - ndiff = ndiff.diff(s); - --nth; - } - return ndiff; + // trivial: zeroth derivative + if (nth==0) + return ex(*this); + + // evaluate unevaluated *this before differentiating + if (!(flags & status_flags::evaluated)) + return ex(*this).diff(s, nth); + + ex ndiff = this->derivative(s); + while (!ndiff.is_zero() && // stop differentiating zeros + nth>1) { + ndiff = ndiff.diff(s); + --nth; + } + return ndiff; } exvector basic::get_indices(void) const { - return exvector(); // return an empty exvector + return exvector(); // return an empty exvector } ex basic::simplify_ncmul(const exvector & v) const { - return simplified_ncmul(v); + return simplified_ncmul(v); } // protected @@ -346,14 +346,14 @@ ex basic::simplify_ncmul(const exvector & v) const * @see ex::diff */ ex basic::derivative(const symbol & s) const { - throw(std::logic_error("differentiation not supported by this type")); + 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. */ int basic::compare_same_type(const basic & other) const { - return compare_pointers(this, &other); + return compare_pointers(this, &other); } /** Returns true if two objects of same type are equal. Normally needs @@ -361,43 +361,43 @@ int basic::compare_same_type(const basic & other) const * class, since it just calls complare_same_type(). */ bool basic::is_equal_same_type(const basic & other) const { - return compare_same_type(other)==0; + return compare_same_type(other)==0; } unsigned basic::return_type(void) const { - return return_types::commutative; + return return_types::commutative; } unsigned basic::return_type_tinfo(void) const { - return tinfo(); + return tinfo(); } unsigned basic::calchash(void) const { - unsigned v=golden_ratio_hash(tinfo()); - for (unsigned i=0; i(this))->op(i).gethash(); - } + unsigned v=golden_ratio_hash(tinfo()); + for (unsigned i=0; i(this))->op(i).gethash(); + } - v = v & 0x7FFFFFFFU; - - // store calculated hash value only if object is already evaluated - if (flags & status_flags::evaluated) { - setflag(status_flags::hash_calculated); - hashvalue=v; - } + v = v & 0x7FFFFFFFU; + + // store calculated hash value only if object is already evaluated + if (flags & status_flags::evaluated) { + setflag(status_flags::hash_calculated); + hashvalue=v; + } - return v; + return v; } /** Expand expression, i.e. multiply it out and return the result as a new * expression. */ ex basic::expand(unsigned options) const { - return this->setflag(status_flags::expanded); + return this->setflag(status_flags::expanded); } @@ -414,27 +414,27 @@ ex basic::expand(unsigned options) const * In addition, an object of class idx can be used instead of a symbol. */ ex basic::subs(const ex & e) const { - if (e.info(info_flags::relation_equal)) { - return subs(lst(e)); - } - if (!e.info(info_flags::list)) { - throw(std::invalid_argument("basic::subs(ex): argument must be a list")); - } - lst ls; - lst lr; - for (unsigned i=0; ihash_other) return 1; - - unsigned typeid_this = tinfo(); - unsigned typeid_other = other.tinfo(); - - if (typeid_thisprintraw(cout); - cout << " and "; - other.printraw(cout); - cout << 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; - */ - 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; - */ - } - return cmpval; + 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; + */ + 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; + */ + 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; + */ + } + return cmpval; } /** Test for equality. */ bool basic::is_equal(const basic & other) const { - unsigned hash_this = gethash(); - unsigned hash_other = other.gethash(); + unsigned hash_this = gethash(); + unsigned hash_other = other.gethash(); - if (hash_this!=hash_other) return false; + if (hash_this!=hash_other) return false; - unsigned typeid_this = tinfo(); - unsigned typeid_other = other.tinfo(); + unsigned typeid_this = tinfo(); + unsigned typeid_other = other.tinfo(); - if (typeid_this!=typeid_other) return false; + if (typeid_this!=typeid_other) return false; - GINAC_ASSERT(typeid(*this)==typeid(other)); + GINAC_ASSERT(typeid(*this)==typeid(other)); - return is_equal_same_type(other); + return is_equal_same_type(other); } // protected @@ -514,14 +514,14 @@ bool basic::is_equal(const basic & other) const * @see basic::eval */ const basic & basic::hold(void) const { - return setflag(status_flags::evaluated); + return setflag(status_flags::evaluated); } void basic::ensure_if_modifiable(void) const { - if (refcount>1) { - throw(std::runtime_error("cannot modify multiply referenced object")); - } + if (refcount>1) { + throw(std::runtime_error("cannot modify multiply referenced object")); + } } ////////// diff --git a/ginac/basic.h b/ginac/basic.h index 43fc4958..4acdb9ef 100644 --- a/ginac/basic.h +++ b/ginac/basic.h @@ -56,130 +56,130 @@ typedef std::vector exvector; // CINT does not like vector<..., * It is responsible for the reference counting. */ class basic { - GINAC_DECLARE_REGISTERED_CLASS(basic, void) + GINAC_DECLARE_REGISTERED_CLASS(basic, void) - friend class ex; + friend class ex; // member functions - // default constructor, destructor, copy constructor assignment operator and helpers + // default constructor, destructor, copy constructor assignment operator and helpers public: - basic() + basic() #ifdef INLINE_BASIC_CONSTRUCTORS - : tinfo_key(TINFO_basic), flags(0), refcount(0) - { - } + : tinfo_key(TINFO_basic), flags(0), refcount(0) + { + } #else ; #endif // def INLINE_BASIC_CONSTRUCTORS - virtual ~basic() + virtual ~basic() #ifdef INLINE_BASIC_CONSTRUCTORS - { - destroy(0); - GINAC_ASSERT((!(flags & status_flags::dynallocated))||(refcount==0)); - } + { + destroy(0); + GINAC_ASSERT((!(flags & status_flags::dynallocated))||(refcount==0)); + } #else ; #endif // def INLINE_BASIC_CONSTRUCTORS - basic(const basic & other) + basic(const basic & other) #ifdef INLINE_BASIC_CONSTRUCTORS - { - copy(other); - } + { + copy(other); + } #else ; #endif // def INLINE_BASIC_CONSTRUCTORS - virtual const basic & operator=(const basic & other); - + virtual const basic & operator=(const basic & other); + protected: - 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) + 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) - { - } + : tinfo_key(ti), flags(0), refcount(0) + { + } #else ; #endif // def INLINE_BASIC_CONSTRUCTORS - // functions overriding virtual functions from bases classes - // none - - // new virtual functions which can be overridden by derived classes + // functions overriding virtual functions from bases classes + // none + + // new virtual functions which can be overridden by derived classes public: // only const functions please (may break reference counting) - virtual basic * duplicate() const; - virtual void print(std::ostream & os,unsigned upper_precedence = 0) const; - virtual void printraw(std::ostream & os) const; - virtual void printtree(std::ostream & os, unsigned indent) const; - virtual void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence = 0) const; - virtual void dbgprint(void) const; - virtual void dbgprinttree(void) const; - virtual bool info(unsigned inf) const; - virtual unsigned nops() const; - virtual ex op(int i) const; - virtual ex & let_op(int i); - virtual ex operator[](const ex & index) const; - virtual ex operator[](int i) const; - virtual bool has(const ex & other) const; - virtual int degree(const symbol & s) const; - virtual int ldegree(const symbol & s) const; - virtual ex coeff(const symbol & s, int n = 1) const; - virtual ex collect(const symbol & s) const; - virtual ex eval(int level = 0) const; - virtual ex evalf(int level = 0) const; - virtual ex series(const relational & r, int order, unsigned options = 0) const; - virtual ex subs(const lst & ls, const lst & lr) const; - virtual ex normal(lst &sym_lst, lst &repl_lst, int level = 0) const; - virtual ex to_rational(lst &repl_lst) const; - virtual numeric integer_content(void) const; - virtual ex smod(const numeric &xi) const; - virtual numeric max_coefficient(void) const; - virtual exvector get_indices(void) const; - virtual ex simplify_ncmul(const exvector & v) const; + virtual basic * duplicate() const; + virtual void print(std::ostream & os,unsigned upper_precedence = 0) const; + virtual void printraw(std::ostream & os) const; + virtual void printtree(std::ostream & os, unsigned indent) const; + virtual void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence = 0) const; + virtual void dbgprint(void) const; + virtual void dbgprinttree(void) const; + virtual bool info(unsigned inf) const; + virtual unsigned nops() const; + virtual ex op(int i) const; + virtual ex & let_op(int i); + virtual ex operator[](const ex & index) const; + virtual ex operator[](int i) const; + virtual bool has(const ex & other) const; + virtual int degree(const symbol & s) const; + virtual int ldegree(const symbol & s) const; + virtual ex coeff(const symbol & s, int n = 1) const; + virtual ex collect(const symbol & s) const; + virtual ex eval(int level = 0) const; + virtual ex evalf(int level = 0) const; + virtual ex series(const relational & r, int order, unsigned options = 0) const; + virtual ex subs(const lst & ls, const lst & lr) const; + virtual ex normal(lst &sym_lst, lst &repl_lst, int level = 0) const; + virtual ex to_rational(lst &repl_lst) const; + virtual numeric integer_content(void) const; + virtual ex smod(const numeric &xi) const; + virtual numeric max_coefficient(void) const; + virtual exvector get_indices(void) const; + virtual ex simplify_ncmul(const exvector & v) const; protected: // non-const functions should be called from class ex only - virtual ex derivative(const symbol & s) const; - virtual int compare_same_type(const basic & other) const; - virtual bool is_equal_same_type(const basic & other) const; - virtual unsigned return_type(void) const; - virtual unsigned return_type_tinfo(void) const; - virtual unsigned calchash(void) const; - virtual ex expand(unsigned options=0) const; - - // non-virtual functions in this class + virtual ex derivative(const symbol & s) const; + virtual int compare_same_type(const basic & other) const; + virtual bool is_equal_same_type(const basic & other) const; + virtual unsigned return_type(void) const; + virtual unsigned return_type_tinfo(void) const; + virtual unsigned calchash(void) const; + virtual ex expand(unsigned options=0) const; + + // non-virtual functions in this class public: - ex subs(const ex & e) const; - ex diff(const symbol & s, unsigned nth=1) const; - int compare(const basic & other) const; - bool is_equal(const basic & other) const; - const basic & hold(void) const; - unsigned gethash(void) const {if (flags & status_flags::hash_calculated) return hashvalue; else return calchash();} - unsigned tinfo(void) const {return tinfo_key;} - const basic & setflag(unsigned f) const {flags |= f; return *this;} - const basic & clearflag(unsigned f) const {flags &= ~f; return *this;} + ex subs(const ex & e) const; + ex diff(const symbol & s, unsigned nth=1) const; + int compare(const basic & other) const; + bool is_equal(const basic & other) const; + const basic & hold(void) const; + unsigned gethash(void) const {if (flags & status_flags::hash_calculated) return hashvalue; else return calchash();} + unsigned tinfo(void) const {return tinfo_key;} + const basic & setflag(unsigned f) const {flags |= f; return *this;} + const basic & clearflag(unsigned f) const {flags &= ~f; return *this;} protected: - void ensure_if_modifiable(void) const; + 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; + mutable unsigned flags; + mutable unsigned hashvalue; + static unsigned precedence; + static unsigned delta_indent; private: - unsigned refcount; + unsigned refcount; }; // global constants @@ -196,30 +196,30 @@ extern int max_recursion_level; #ifndef NO_NAMESPACE_GINAC #define is_of_type(OBJ,TYPE) \ - (dynamic_cast(const_cast(&OBJ))!=0) + (dynamic_cast(const_cast(&OBJ))!=0) #define is_exactly_of_type(OBJ,TYPE) \ - ((OBJ).tinfo()==GiNaC::TINFO_##TYPE) + ((OBJ).tinfo()==GiNaC::TINFO_##TYPE) #define is_ex_of_type(OBJ,TYPE) \ - (dynamic_cast(const_cast((OBJ).bp))!=0) + (dynamic_cast(const_cast((OBJ).bp))!=0) #define is_ex_exactly_of_type(OBJ,TYPE) \ - ((*(OBJ).bp).tinfo()==GiNaC::TINFO_##TYPE) + ((*(OBJ).bp).tinfo()==GiNaC::TINFO_##TYPE) #else // ndef NO_NAMESPACE_GINAC #define is_of_type(OBJ,TYPE) \ - (dynamic_cast(const_cast(&OBJ))!=0) + (dynamic_cast(const_cast(&OBJ))!=0) #define is_exactly_of_type(OBJ,TYPE) \ - ((OBJ).tinfo()==TINFO_##TYPE) + ((OBJ).tinfo()==TINFO_##TYPE) #define is_ex_of_type(OBJ,TYPE) \ - (dynamic_cast(const_cast((OBJ).bp))!=0) + (dynamic_cast(const_cast((OBJ).bp))!=0) #define is_ex_exactly_of_type(OBJ,TYPE) \ - ((*(OBJ).bp).tinfo()==TINFO_##TYPE) + ((*(OBJ).bp).tinfo()==TINFO_##TYPE) #endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/clifford.cpp b/ginac/clifford.cpp index 2bf3fbb7..742fd002 100644 --- a/ginac/clifford.cpp +++ b/ginac/clifford.cpp @@ -41,48 +41,48 @@ namespace GiNaC { clifford::clifford() { - debugmsg("clifford default constructor",LOGLEVEL_CONSTRUCT); - serial=next_serial++; - name=autoname_prefix()+ToString(serial); - tinfo_key=TINFO_clifford; + debugmsg("clifford default constructor",LOGLEVEL_CONSTRUCT); + serial=next_serial++; + name=autoname_prefix()+ToString(serial); + tinfo_key=TINFO_clifford; } clifford::~clifford() { - debugmsg("clifford destructor",LOGLEVEL_DESTRUCT); - destroy(0); + debugmsg("clifford destructor",LOGLEVEL_DESTRUCT); + destroy(0); } clifford::clifford(const clifford & other) { - debugmsg("clifford copy constructor",LOGLEVEL_CONSTRUCT); - copy (other); + debugmsg("clifford copy constructor",LOGLEVEL_CONSTRUCT); + copy (other); } const clifford & clifford::operator=(const clifford & other) { - debugmsg("clifford operator=",LOGLEVEL_ASSIGNMENT); - if (this != &other) { - destroy(1); - copy(other); - } - return *this; + debugmsg("clifford operator=",LOGLEVEL_ASSIGNMENT); + if (this != &other) { + destroy(1); + copy(other); + } + return *this; } // protected void clifford::copy(const clifford & other) { - indexed::copy(other); - name=other.name; - serial=other.serial; + indexed::copy(other); + name=other.name; + serial=other.serial; } void clifford::destroy(bool call_parent) { - if (call_parent) { - indexed::destroy(call_parent); - } + if (call_parent) { + indexed::destroy(call_parent); + } } ////////// @@ -93,10 +93,10 @@ void clifford::destroy(bool call_parent) clifford::clifford(const std::string & initname) { - debugmsg("clifford constructor from string",LOGLEVEL_CONSTRUCT); - name=initname; - serial=next_serial++; - tinfo_key=TINFO_clifford; + debugmsg("clifford constructor from string",LOGLEVEL_CONSTRUCT); + name=initname; + serial=next_serial++; + tinfo_key=TINFO_clifford; } ////////// @@ -107,73 +107,73 @@ clifford::clifford(const std::string & initname) basic * clifford::duplicate() const { - debugmsg("clifford duplicate",LOGLEVEL_DUPLICATE); - return new clifford(*this); + debugmsg("clifford duplicate",LOGLEVEL_DUPLICATE); + return new clifford(*this); } void clifford::printraw(std::ostream & os) const { - debugmsg("clifford printraw",LOGLEVEL_PRINT); - os << "clifford(" << "name=" << name << ",serial=" << serial - << ",indices="; - printrawindices(os); - os << ",hash=" << hashvalue << ",flags=" << flags << ")"; + debugmsg("clifford printraw",LOGLEVEL_PRINT); + os << "clifford(" << "name=" << name << ",serial=" << serial + << ",indices="; + printrawindices(os); + os << ",hash=" << hashvalue << ",flags=" << flags << ")"; } void clifford::printtree(std::ostream & os, unsigned indent) const { - debugmsg("clifford printtree",LOGLEVEL_PRINT); - os << std::string(indent,' ') << name << " (clifford): " - << "serial=" << serial << "," - << seq.size() << "indices="; - printtreeindices(os, indent); - os << ", hash=" << hashvalue - << " (0x" << std::hex << hashvalue << std::dec << ")" - << ", flags=" << flags << std::endl; + debugmsg("clifford printtree",LOGLEVEL_PRINT); + os << std::string(indent,' ') << name << " (clifford): " + << "serial=" << serial << "," + << seq.size() << "indices="; + printtreeindices(os, indent); + os << ", hash=" << hashvalue + << " (0x" << std::hex << hashvalue << std::dec << ")" + << ", flags=" << flags << std::endl; } void clifford::print(std::ostream & os, unsigned upper_precedence) const { - debugmsg("clifford print",LOGLEVEL_PRINT); - os << name; - printindices(os); + debugmsg("clifford print",LOGLEVEL_PRINT); + os << name; + printindices(os); } void clifford::printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const { - debugmsg("clifford print csrc",LOGLEVEL_PRINT); - print(os,upper_precedence); + debugmsg("clifford print csrc",LOGLEVEL_PRINT); + print(os,upper_precedence); } bool clifford::info(unsigned inf) const { - return indexed::info(inf); + return indexed::info(inf); } // protected int clifford::compare_same_type(const basic & other) const { - GINAC_ASSERT(other.tinfo() == TINFO_clifford); - const clifford *o = static_cast(&other); - if (serial==o->serial) { - return indexed::compare_same_type(other); - } - return serial < o->serial ? -1 : 1; + GINAC_ASSERT(other.tinfo() == TINFO_clifford); + const clifford *o = static_cast(&other); + if (serial==o->serial) { + return indexed::compare_same_type(other); + } + return serial < o->serial ? -1 : 1; } ex clifford::simplify_ncmul(const exvector & v) const { - return simplified_ncmul(v); + return simplified_ncmul(v); } unsigned clifford::calchash(void) const { - hashvalue=golden_ratio_hash(golden_ratio_hash(0x55555556U ^ - golden_ratio_hash(tinfo_key) ^ - serial)); - setflag(status_flags::hash_calculated); - return hashvalue; + hashvalue=golden_ratio_hash(golden_ratio_hash(0x55555556U ^ + golden_ratio_hash(tinfo_key) ^ + serial)); + setflag(status_flags::hash_calculated); + return hashvalue; } ////////// @@ -188,15 +188,15 @@ unsigned clifford::calchash(void) const void clifford::setname(const std::string & n) { - name = n; + name = n; } // private std::string & clifford::autoname_prefix(void) { - static std::string * s = new std::string("clifford"); - return *s; + static std::string * s = new std::string("clifford"); + return *s; } ////////// diff --git a/ginac/clifford.h b/ginac/clifford.h index 18d8f0a7..efb813de 100644 --- a/ginac/clifford.h +++ b/ginac/clifford.h @@ -36,49 +36,49 @@ class clifford : public indexed { // member functions - // default constructor, destructor, copy constructor assignment operator and helpers + // default constructor, destructor, copy constructor assignment operator and helpers public: - clifford(); - ~clifford(); - clifford(const clifford & other); - const clifford & operator=(const clifford & other); + clifford(); + ~clifford(); + clifford(const clifford & other); + const clifford & operator=(const clifford & other); protected: - void copy(const clifford & other); - void destroy(bool call_parent); + void copy(const clifford & other); + void destroy(bool call_parent); - // other constructors + // other constructors public: - explicit clifford(const std::string & initname); + explicit clifford(const std::string & initname); - // functions overriding virtual functions from base classes + // functions overriding virtual functions from base classes public: - basic * duplicate() const; - void printraw(std::ostream & os) const; - void printtree(std::ostream & os, unsigned indent) const; - void print(std::ostream & os, unsigned upper_precedence=0) const; - void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence=0) const; - bool info(unsigned inf) const; + basic * duplicate() const; + void printraw(std::ostream & os) const; + void printtree(std::ostream & os, unsigned indent) const; + void print(std::ostream & os, unsigned upper_precedence=0) const; + void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence=0) const; + bool info(unsigned inf) const; protected: - int compare_same_type(const basic & other) const; - ex simplify_ncmul(const exvector & v) const; - unsigned calchash(void) const; - - // new virtual functions which can be overridden by derived classes - // none - - // non-virtual functions in this class + int compare_same_type(const basic & other) const; + ex simplify_ncmul(const exvector & v) const; + unsigned calchash(void) const; + + // new virtual functions which can be overridden by derived classes + // none + + // non-virtual functions in this class public: - void setname(const std::string & n); + void setname(const std::string & n); private: - std::string & autoname_prefix(void); + std::string & autoname_prefix(void); // member variables protected: - std::string name; - unsigned serial; // unique serial number for comparision + std::string name; + unsigned serial; // unique serial number for comparision private: - static unsigned next_serial; + static unsigned next_serial; }; // global constants diff --git a/ginac/color.cpp b/ginac/color.cpp index b0cbabf5..82096b57 100644 --- a/ginac/color.cpp +++ b/ginac/color.cpp @@ -51,46 +51,46 @@ GINAC_IMPLEMENT_REGISTERED_CLASS(color, indexed) color::color() : type(invalid), representation_label(0) { - debugmsg("color default constructor",LOGLEVEL_CONSTRUCT); - tinfo_key=TINFO_color; + debugmsg("color default constructor",LOGLEVEL_CONSTRUCT); + tinfo_key=TINFO_color; } color::~color() { - debugmsg("color destructor",LOGLEVEL_DESTRUCT); - destroy(0); + debugmsg("color destructor",LOGLEVEL_DESTRUCT); + destroy(0); } color::color(const color & other) { - debugmsg("color copy constructor",LOGLEVEL_CONSTRUCT); - copy (other); + debugmsg("color copy constructor",LOGLEVEL_CONSTRUCT); + copy (other); } const color & color::operator=(const color & other) { - debugmsg("color operator=",LOGLEVEL_ASSIGNMENT); - if (this != &other) { - destroy(1); - copy(other); - } - return *this; + debugmsg("color operator=",LOGLEVEL_ASSIGNMENT); + if (this != &other) { + destroy(1); + copy(other); + } + return *this; } // protected void color::copy(const color & other) { - inherited::copy(other); - type=other.type; - representation_label=other.representation_label; + inherited::copy(other); + type=other.type; + representation_label=other.representation_label; } void color::destroy(bool call_parent) { - if (call_parent) { - inherited::destroy(call_parent); - } + if (call_parent) { + inherited::destroy(call_parent); + } } ////////// @@ -101,55 +101,55 @@ void color::destroy(bool call_parent) color::color(color_types const t, unsigned rl) : type(t), representation_label(rl) { - debugmsg("color constructor from color_types,unsigned",LOGLEVEL_CONSTRUCT); - GINAC_ASSERT(representation_labelsetflag(status_flags::dynallocated); + return (new color(n, sym_lst))->setflag(status_flags::dynallocated); } /** Archive the object. */ void color::archive(archive_node &n) const { - inherited::archive(n); - n.add_unsigned("type", type); - n.add_unsigned("representation", representation_label); + inherited::archive(n); + n.add_unsigned("type", type); + n.add_unsigned("representation", representation_label); } ////////// @@ -190,445 +190,445 @@ void color::archive(archive_node &n) const basic * color::duplicate() const { - debugmsg("color duplicate",LOGLEVEL_DUPLICATE); - return new color(*this); + debugmsg("color duplicate",LOGLEVEL_DUPLICATE); + return new color(*this); } void color::printraw(std::ostream & os) const { - debugmsg("color printraw",LOGLEVEL_PRINT); - os << "color(type=" << (unsigned)type - << ",representation_label=" << representation_label - << ",indices="; - printrawindices(os); - os << ",hash=" << hashvalue << ",flags=" << flags << ")"; + debugmsg("color printraw",LOGLEVEL_PRINT); + os << "color(type=" << (unsigned)type + << ",representation_label=" << representation_label + << ",indices="; + printrawindices(os); + os << ",hash=" << hashvalue << ",flags=" << flags << ")"; } void color::printtree(std::ostream & os, unsigned indent) const { - debugmsg("color printtree",LOGLEVEL_PRINT); - os << std::string(indent,' ') << "color object: " - << "type=" << (unsigned)type - << ",representation_label=" << representation_label << ", "; - os << seq.size() << " indices" << std::endl; - printtreeindices(os,indent); - os << std::string(indent,' ') << "hash=" << hashvalue - << " (0x" << std::hex << hashvalue << std::dec << ")" - << ", flags=" << flags << std::endl; + debugmsg("color printtree",LOGLEVEL_PRINT); + os << std::string(indent,' ') << "color object: " + << "type=" << (unsigned)type + << ",representation_label=" << representation_label << ", "; + os << seq.size() << " indices" << std::endl; + printtreeindices(os,indent); + os << std::string(indent,' ') << "hash=" << hashvalue + << " (0x" << std::hex << hashvalue << std::dec << ")" + << ", flags=" << flags << std::endl; } void color::print(std::ostream & os, unsigned upper_precedence) const { - debugmsg("color print",LOGLEVEL_PRINT); - switch (type) { - case color_T: - os << "T"; - if (representation_label!=0) { - os << "^(" << representation_label << ")"; - } - break; - case color_f: - os << "f"; - break; - case color_d: - os << "d"; - break; - case color_delta8: - os << "delta8"; - break; - case color_ONE: - os << "color_ONE"; - break; - case invalid: - default: - os << "INVALID_COLOR_OBJECT"; - break; - } - printindices(os); + debugmsg("color print",LOGLEVEL_PRINT); + switch (type) { + case color_T: + os << "T"; + if (representation_label!=0) { + os << "^(" << representation_label << ")"; + } + break; + case color_f: + os << "f"; + break; + case color_d: + os << "d"; + break; + case color_delta8: + os << "delta8"; + break; + case color_ONE: + os << "color_ONE"; + break; + case invalid: + default: + os << "INVALID_COLOR_OBJECT"; + break; + } + printindices(os); } void color::printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const { - debugmsg("color print csrc",LOGLEVEL_PRINT); - print(os,upper_precedence); + debugmsg("color print csrc",LOGLEVEL_PRINT); + print(os,upper_precedence); } bool color::info(unsigned inf) const { - return inherited::info(inf); + return inherited::info(inf); } #define CMPINDICES(A,B,C) ((idx1.get_value()==(A))&&(idx2.get_value()==(B))&&(idx3.get_value()==(C))) ex color::eval(int level) const { - // canonicalize indices - - bool antisymmetric=false; - - switch (type) { - case color_f: - antisymmetric=true; // no break here! - case color_d: - case color_delta8: - { - exvector iv=seq; - int sig=canonicalize_indices(iv,antisymmetric); - if (sig!=INT_MAX) { - // something has changed while sorting indices, more evaluations later - if (sig==0) return _ex0(); - return ex(sig)*color(type,iv,representation_label); - } - } - break; - default: - // nothing to canonicalize - break; - } - - switch (type) { - case color_delta8: - { - GINAC_ASSERT(seq.size()==2); - const coloridx & idx1=ex_to_coloridx(seq[0]); - const coloridx & idx2=ex_to_coloridx(seq[1]); - - // check for delta8_{a,a} where a is a symbolic index, replace by 8 - if ((idx1.is_symbolic())&&(idx1.is_equal_same_type(idx2))) { - return ex(COLOR_EIGHT); - } - - // check for delta8_{a,b} where a and b are numeric indices, replace by 0 or 1 - if ((!idx1.is_symbolic())&&(!idx2.is_symbolic())) { - if ((idx1.get_value()!=idx2.get_value())) { - return _ex1(); - } else { - return _ex0(); - } - } + // canonicalize indices + + bool antisymmetric=false; + + switch (type) { + case color_f: + antisymmetric=true; // no break here! + case color_d: + case color_delta8: + { + exvector iv=seq; + int sig=canonicalize_indices(iv,antisymmetric); + if (sig!=INT_MAX) { + // something has changed while sorting indices, more evaluations later + if (sig==0) return _ex0(); + return ex(sig)*color(type,iv,representation_label); + } + } + break; + default: + // nothing to canonicalize + break; + } + + switch (type) { + case color_delta8: + { + GINAC_ASSERT(seq.size()==2); + const coloridx & idx1=ex_to_coloridx(seq[0]); + const coloridx & idx2=ex_to_coloridx(seq[1]); + + // check for delta8_{a,a} where a is a symbolic index, replace by 8 + if ((idx1.is_symbolic())&&(idx1.is_equal_same_type(idx2))) { + return ex(COLOR_EIGHT); + } + + // check for delta8_{a,b} where a and b are numeric indices, replace by 0 or 1 + if ((!idx1.is_symbolic())&&(!idx2.is_symbolic())) { + if ((idx1.get_value()!=idx2.get_value())) { + return _ex1(); + } else { + return _ex0(); + } + } + } + break; + case color_d: + // check for d_{a,a,c} (=0) when a is symbolic + { + GINAC_ASSERT(seq.size()==3); + const coloridx & idx1=ex_to_coloridx(seq[0]); + const coloridx & idx2=ex_to_coloridx(seq[1]); + const coloridx & idx3=ex_to_coloridx(seq[2]); + + if (idx1.is_equal_same_type(idx2) && idx1.is_symbolic()) { + return _ex0(); + } else if (idx2.is_equal_same_type(idx3) && idx2.is_symbolic()) { + return _ex0(); + } + + // check for three numeric indices + if (!(idx1.is_symbolic()||idx2.is_symbolic()||idx3.is_symbolic())) { + GINAC_ASSERT(idx1.get_value()<=idx2.get_value()); + GINAC_ASSERT(idx2.get_value()<=idx3.get_value()); + if (CMPINDICES(1,4,6)||CMPINDICES(1,5,7)||CMPINDICES(2,5,6)|| + CMPINDICES(3,4,4)||CMPINDICES(3,5,5)) { + return _ex1_2(); + } else if (CMPINDICES(2,4,7)||CMPINDICES(3,6,6)||CMPINDICES(3,7,7)) { + return -_ex1_2(); + } else if (CMPINDICES(1,1,8)||CMPINDICES(2,2,8)||CMPINDICES(3,3,8)) { + return 1/sqrt(numeric(3)); + } else if (CMPINDICES(8,8,8)) { + return -1/sqrt(numeric(3)); + } else if (CMPINDICES(4,4,8)||CMPINDICES(5,5,8)||CMPINDICES(6,6,8)||CMPINDICES(7,7,8)) { + return -1/(2*sqrt(numeric(3))); + } + return _ex0(); + } + } + break; + case color_f: + { + GINAC_ASSERT(seq.size()==3); + const coloridx & idx1=ex_to_coloridx(seq[0]); + const coloridx & idx2=ex_to_coloridx(seq[1]); + const coloridx & idx3=ex_to_coloridx(seq[2]); + + // check for three numeric indices + if (!(idx1.is_symbolic()||idx2.is_symbolic()||idx3.is_symbolic())) { + GINAC_ASSERT(idx1.get_value()<=idx2.get_value()); + GINAC_ASSERT(idx2.get_value()<=idx3.get_value()); + if (CMPINDICES(1,2,3)) { + return _ex1(); + } else if (CMPINDICES(1,4,7)||CMPINDICES(2,4,6)|| + CMPINDICES(2,5,7)||CMPINDICES(3,4,5)) { + return _ex1_2(); + } else if (CMPINDICES(1,5,6)||CMPINDICES(3,6,7)) { + return -_ex1_2(); + } else if (CMPINDICES(4,5,8)||CMPINDICES(6,7,8)) { + return sqrt(numeric(3))/2; + } else if (CMPINDICES(8,8,8)) { + return -1/sqrt(numeric(3)); + } else if (CMPINDICES(4,4,8)||CMPINDICES(5,5,8)||CMPINDICES(6,6,8)||CMPINDICES(7,7,8)) { + return -1/(2*sqrt(numeric(3))); + } + return _ex0(); + } + break; + } + default: + // nothing to evaluate + break; } - break; - case color_d: - // check for d_{a,a,c} (=0) when a is symbolic - { - GINAC_ASSERT(seq.size()==3); - const coloridx & idx1=ex_to_coloridx(seq[0]); - const coloridx & idx2=ex_to_coloridx(seq[1]); - const coloridx & idx3=ex_to_coloridx(seq[2]); - - if (idx1.is_equal_same_type(idx2) && idx1.is_symbolic()) { - return _ex0(); - } else if (idx2.is_equal_same_type(idx3) && idx2.is_symbolic()) { - return _ex0(); - } - - // check for three numeric indices - if (!(idx1.is_symbolic()||idx2.is_symbolic()||idx3.is_symbolic())) { - GINAC_ASSERT(idx1.get_value()<=idx2.get_value()); - GINAC_ASSERT(idx2.get_value()<=idx3.get_value()); - if (CMPINDICES(1,4,6)||CMPINDICES(1,5,7)||CMPINDICES(2,5,6)|| - CMPINDICES(3,4,4)||CMPINDICES(3,5,5)) { - return _ex1_2(); - } else if (CMPINDICES(2,4,7)||CMPINDICES(3,6,6)||CMPINDICES(3,7,7)) { - return -_ex1_2(); - } else if (CMPINDICES(1,1,8)||CMPINDICES(2,2,8)||CMPINDICES(3,3,8)) { - return 1/sqrt(numeric(3)); - } else if (CMPINDICES(8,8,8)) { - return -1/sqrt(numeric(3)); - } else if (CMPINDICES(4,4,8)||CMPINDICES(5,5,8)||CMPINDICES(6,6,8)||CMPINDICES(7,7,8)) { - return -1/(2*sqrt(numeric(3))); - } - return _ex0(); - } - } - break; - case color_f: - { - GINAC_ASSERT(seq.size()==3); - const coloridx & idx1=ex_to_coloridx(seq[0]); - const coloridx & idx2=ex_to_coloridx(seq[1]); - const coloridx & idx3=ex_to_coloridx(seq[2]); - - // check for three numeric indices - if (!(idx1.is_symbolic()||idx2.is_symbolic()||idx3.is_symbolic())) { - GINAC_ASSERT(idx1.get_value()<=idx2.get_value()); - GINAC_ASSERT(idx2.get_value()<=idx3.get_value()); - if (CMPINDICES(1,2,3)) { - return _ex1(); - } else if (CMPINDICES(1,4,7)||CMPINDICES(2,4,6)|| - CMPINDICES(2,5,7)||CMPINDICES(3,4,5)) { - return _ex1_2(); - } else if (CMPINDICES(1,5,6)||CMPINDICES(3,6,7)) { - return -_ex1_2(); - } else if (CMPINDICES(4,5,8)||CMPINDICES(6,7,8)) { - return sqrt(numeric(3))/2; - } else if (CMPINDICES(8,8,8)) { - return -1/sqrt(numeric(3)); - } else if (CMPINDICES(4,4,8)||CMPINDICES(5,5,8)||CMPINDICES(6,6,8)||CMPINDICES(7,7,8)) { - return -1/(2*sqrt(numeric(3))); - } - return _ex0(); - } - break; - } - default: - // nothing to evaluate - break; - } - - return this->hold(); -} - + + return this->hold(); +} + // protected int color::compare_same_type(const basic & other) const { - GINAC_ASSERT(other.tinfo() == TINFO_color); - const color *o = static_cast(&other); - if (type==o->type) { - if (representation_label==o->representation_label) { - return inherited::compare_same_type(other); - } - return representation_label < o->representation_label ? -1 : 1; - } - return type < o->type ? -1 : 1; + GINAC_ASSERT(other.tinfo() == TINFO_color); + const color *o = static_cast(&other); + if (type==o->type) { + if (representation_label==o->representation_label) { + return inherited::compare_same_type(other); + } + return representation_label < o->representation_label ? -1 : 1; + } + return type < o->type ? -1 : 1; } bool color::is_equal_same_type(const basic & other) const { - GINAC_ASSERT(other.tinfo() == TINFO_color); - const color *o = static_cast(&other); - if (type!=o->type) return false; - if (representation_label!=o->representation_label) return false; - return inherited::is_equal_same_type(other); + GINAC_ASSERT(other.tinfo() == TINFO_color); + const color *o = static_cast(&other); + if (type!=o->type) return false; + if (representation_label!=o->representation_label) return false; + return inherited::is_equal_same_type(other); } #include ex color::simplify_ncmul(const exvector & v) const { - // simplifications: contract delta8_{a,b} where possible - // sort delta8,f,d,T(rl=0),T(rl=1),...,ONE(rl=0),ONE(rl=1),... - // remove superfluous ONEs - - // contract indices of delta8_{a,b} if they are different and symbolic - - exvector v_contracted=v; - unsigned replacements; - bool something_changed=false; - - exvector::iterator it=v_contracted.begin(); - while (it!=v_contracted.end()) { - // process only delta8 objects - if (is_ex_exactly_of_type(*it,color) && (ex_to_color(*it).type==color_delta8)) { - color & d8=ex_to_nonconst_color(*it); - GINAC_ASSERT(d8.seq.size()==2); - const coloridx & first_idx=ex_to_coloridx(d8.seq[0]); - const coloridx & second_idx=ex_to_coloridx(d8.seq[1]); - // delta8_{a,a} should have been contracted in color::eval() - GINAC_ASSERT((!first_idx.is_equal(second_idx))||(!first_idx.is_symbolic())); - ex saved_delta8=*it; // save to restore it later - - // try to contract first index - replacements=1; - if (first_idx.is_symbolic()) { - replacements = subs_index_in_exvector(v_contracted,first_idx,second_idx); - if (replacements==1) { - // not contracted except in itself, restore delta8 object - *it=saved_delta8; - } else { - // a contracted index should occur exactly twice - GINAC_ASSERT(replacements==2); - *it=_ex1(); - something_changed=true; - } - } - - // try second index only if first was not contracted - if ((replacements==1)&&(second_idx.is_symbolic())) { - // first index not contracted, *it is guaranteed to be the original delta8 object - replacements = subs_index_in_exvector(v_contracted,second_idx,first_idx); - if (replacements==1) { - // not contracted except in itself, restore delta8 object - *it=saved_delta8; - } else { - // a contracted index should occur exactly twice - GINAC_ASSERT(replacements==2); - *it=_ex1(); - something_changed=true; - } - } - } - ++it; - } - - if (something_changed) { - // do more simplifications later - return nonsimplified_ncmul(v_contracted); - } - - // there were no indices to contract - // sort delta8,f,d,T(rl=0),T(rl=1),...,ONE(rl=0),ONE(rl=1),...,unknown - // (if there is at least one unknown object, all Ts will be unknown to not change the order) - - exvector delta8vec; - exvector fvec; - exvector dvec; - exvectorvector Tvecs; - Tvecs.resize(MAX_REPRESENTATION_LABELS); - exvectorvector ONEvecs; - ONEvecs.resize(MAX_REPRESENTATION_LABELS); - exvector unknownvec; - - split_color_string_in_parts(v,delta8vec,fvec,dvec,Tvecs,ONEvecs,unknownvec); - - // d_{a,k,l} f_{b,k,l}=0 (includes case a=b) - if ((dvec.size()>=1)&&(fvec.size()>=1)) { - for (exvector::iterator it1=dvec.begin(); it1!=dvec.end(); ++it1) { - for (exvector::iterator it2=fvec.begin(); it2!=fvec.end(); ++it2) { - GINAC_ASSERT(is_ex_exactly_of_type(*it1,color)); - GINAC_ASSERT(is_ex_exactly_of_type(*it2,color)); - const color & col1=ex_to_color(*it1); - const color & col2=ex_to_color(*it2); - exvector iv_intersect=idx_intersect(col1.seq,col2.seq); - if (iv_intersect.size()>=2) return _ex0(); - } - } - } - - // d_{a,k,l} d_{b,k,l}=5/3 delta8_{a,b} (includes case a=b) - if (dvec.size()>=2) { - for (exvector::iterator it1=dvec.begin(); it1!=dvec.end()-1; ++it1) { - for (exvector::iterator it2=it1+1; it2!=dvec.end(); ++it2) { - GINAC_ASSERT(is_ex_exactly_of_type(*it1,color)); - GINAC_ASSERT(is_ex_exactly_of_type(*it2,color)); - const color & col1=ex_to_color(*it1); - const color & col2=ex_to_color(*it2); - exvector iv_intersect=idx_intersect(col1.seq,col2.seq); - if (iv_intersect.size()>=2) { - if (iv_intersect.size()==3) { - *it1=numeric(40)/numeric(3); - *it2=_ex1(); - } else { - int sig1, sig2; // unimportant, since symmetric - ex idx1=permute_free_index_to_front(col1.seq,iv_intersect,false,&sig1); - ex idx2=permute_free_index_to_front(col2.seq,iv_intersect,false,&sig2); - *it1=numeric(5)/numeric(3)*color(color_delta8,idx1,idx2); - *it2=_ex1(); - } - return nonsimplified_ncmul(recombine_color_string( - delta8vec,fvec,dvec,Tvecs,ONEvecs,unknownvec)); - } - } - } - } - - // f_{a,k,l} f_{b,k,l}=3 delta8_{a,b} (includes case a=b) - if (fvec.size()>=2) { - for (exvector::iterator it1=fvec.begin(); it1!=fvec.end()-1; ++it1) { - for (exvector::iterator it2=it1+1; it2!=fvec.end(); ++it2) { - GINAC_ASSERT(is_ex_exactly_of_type(*it1,color)); - GINAC_ASSERT(is_ex_exactly_of_type(*it2,color)); - const color & col1=ex_to_color(*it1); - const color & col2=ex_to_color(*it2); - exvector iv_intersect=idx_intersect(col1.seq,col2.seq); - if (iv_intersect.size()>=2) { - if (iv_intersect.size()==3) { - *it1=numeric(24); - *it2=_ex1(); - } else { - int sig1, sig2; - ex idx1=permute_free_index_to_front(col1.seq,iv_intersect,true,&sig1); - ex idx2=permute_free_index_to_front(col2.seq,iv_intersect,true,&sig2); - *it1=numeric(sig1*sig2*5)/numeric(3)*color(color_delta8,idx1,idx2); - *it2=_ex1(); - } - return nonsimplified_ncmul(recombine_color_string( - delta8vec,fvec,dvec,Tvecs,ONEvecs,unknownvec)); - } - } - } - } - - // d_{a,b,c} T_b T_c = 5/6 T_a - // f_{a,b,c} T_b T_c = 3/2 I T_a - for (unsigned rl=0; rl=2)&&((dvec.size()>=1)||(fvec.size()>=1))) { - for (exvector::iterator it1=Tvecs[rl].begin(); it1!=Tvecs[rl].end()-1; ++it1) { - exvector iv; - GINAC_ASSERT(is_ex_exactly_of_type(*it1,color)&&ex_to_color(*it1).type==color_T); - GINAC_ASSERT(is_ex_exactly_of_type(*(it1+1),color)&&ex_to_color(*(it1+1)).type==color_T); - iv.push_back(ex_to_color(*it1).seq[0]); - iv.push_back(ex_to_color(*(it1+1)).seq[0]); - - // d_{a,b,c} T_b T_c = 5/6 T_a - for (exvector::iterator it2=dvec.begin(); it2!=dvec.end(); ++it2) { - GINAC_ASSERT(is_ex_exactly_of_type(*it2,color)&&ex_to_color(*it2).type==color_d); - const color & dref=ex_to_color(*it2); - exvector iv_intersect=idx_intersect(dref.seq,iv); - if (iv_intersect.size()==2) { - int sig; // unimportant, since symmetric - ex free_idx=permute_free_index_to_front(dref.seq,iv,false,&sig); - *it1=color(color_T,free_idx,rl); - *(it1+1)=color(color_ONE,rl); - *it2=numeric(5)/numeric(6); - return nonsimplified_ncmul(recombine_color_string( - delta8vec,fvec,dvec,Tvecs,ONEvecs,unknownvec)); - } - } - - // f_{a,b,c} T_b T_c = 3/2 I T_a - for (exvector::iterator it2=fvec.begin(); it2!=fvec.end(); ++it2) { - GINAC_ASSERT(is_ex_exactly_of_type(*it2,color)&&ex_to_color(*it2).type==color_f); - const color & fref=ex_to_color(*it2); - exvector iv_intersect=idx_intersect(fref.seq,iv); - if (iv_intersect.size()==2) { - int sig; - ex free_idx=permute_free_index_to_front(fref.seq,iv,true,&sig); - *it1=color(color_T,free_idx,rl); - *(it1+1)=color(color_ONE,rl); - *it2=numeric(sig*3)/numeric(2)*I; - return nonsimplified_ncmul(recombine_color_string( - delta8vec,fvec,dvec,Tvecs,ONEvecs,unknownvec)); - } - } - } - } - } - - // clear all ONEs when there is at least one corresponding color_T - // in this representation, retain one ONE otherwise - for (unsigned rl=0; rl=1)&&(fvec.size()>=1)) { + for (exvector::iterator it1=dvec.begin(); it1!=dvec.end(); ++it1) { + for (exvector::iterator it2=fvec.begin(); it2!=fvec.end(); ++it2) { + GINAC_ASSERT(is_ex_exactly_of_type(*it1,color)); + GINAC_ASSERT(is_ex_exactly_of_type(*it2,color)); + const color & col1=ex_to_color(*it1); + const color & col2=ex_to_color(*it2); + exvector iv_intersect=idx_intersect(col1.seq,col2.seq); + if (iv_intersect.size()>=2) return _ex0(); + } + } + } + + // d_{a,k,l} d_{b,k,l}=5/3 delta8_{a,b} (includes case a=b) + if (dvec.size()>=2) { + for (exvector::iterator it1=dvec.begin(); it1!=dvec.end()-1; ++it1) { + for (exvector::iterator it2=it1+1; it2!=dvec.end(); ++it2) { + GINAC_ASSERT(is_ex_exactly_of_type(*it1,color)); + GINAC_ASSERT(is_ex_exactly_of_type(*it2,color)); + const color & col1=ex_to_color(*it1); + const color & col2=ex_to_color(*it2); + exvector iv_intersect=idx_intersect(col1.seq,col2.seq); + if (iv_intersect.size()>=2) { + if (iv_intersect.size()==3) { + *it1=numeric(40)/numeric(3); + *it2=_ex1(); + } else { + int sig1, sig2; // unimportant, since symmetric + ex idx1=permute_free_index_to_front(col1.seq,iv_intersect,false,&sig1); + ex idx2=permute_free_index_to_front(col2.seq,iv_intersect,false,&sig2); + *it1=numeric(5)/numeric(3)*color(color_delta8,idx1,idx2); + *it2=_ex1(); + } + return nonsimplified_ncmul(recombine_color_string( + delta8vec,fvec,dvec,Tvecs,ONEvecs,unknownvec)); + } + } + } + } + + // f_{a,k,l} f_{b,k,l}=3 delta8_{a,b} (includes case a=b) + if (fvec.size()>=2) { + for (exvector::iterator it1=fvec.begin(); it1!=fvec.end()-1; ++it1) { + for (exvector::iterator it2=it1+1; it2!=fvec.end(); ++it2) { + GINAC_ASSERT(is_ex_exactly_of_type(*it1,color)); + GINAC_ASSERT(is_ex_exactly_of_type(*it2,color)); + const color & col1=ex_to_color(*it1); + const color & col2=ex_to_color(*it2); + exvector iv_intersect=idx_intersect(col1.seq,col2.seq); + if (iv_intersect.size()>=2) { + if (iv_intersect.size()==3) { + *it1=numeric(24); + *it2=_ex1(); + } else { + int sig1, sig2; + ex idx1=permute_free_index_to_front(col1.seq,iv_intersect,true,&sig1); + ex idx2=permute_free_index_to_front(col2.seq,iv_intersect,true,&sig2); + *it1=numeric(sig1*sig2*5)/numeric(3)*color(color_delta8,idx1,idx2); + *it2=_ex1(); + } + return nonsimplified_ncmul(recombine_color_string( + delta8vec,fvec,dvec,Tvecs,ONEvecs,unknownvec)); + } + } + } + } + + // d_{a,b,c} T_b T_c = 5/6 T_a + // f_{a,b,c} T_b T_c = 3/2 I T_a + for (unsigned rl=0; rl=2)&&((dvec.size()>=1)||(fvec.size()>=1))) { + for (exvector::iterator it1=Tvecs[rl].begin(); it1!=Tvecs[rl].end()-1; ++it1) { + exvector iv; + GINAC_ASSERT(is_ex_exactly_of_type(*it1,color)&&ex_to_color(*it1).type==color_T); + GINAC_ASSERT(is_ex_exactly_of_type(*(it1+1),color)&&ex_to_color(*(it1+1)).type==color_T); + iv.push_back(ex_to_color(*it1).seq[0]); + iv.push_back(ex_to_color(*(it1+1)).seq[0]); + + // d_{a,b,c} T_b T_c = 5/6 T_a + for (exvector::iterator it2=dvec.begin(); it2!=dvec.end(); ++it2) { + GINAC_ASSERT(is_ex_exactly_of_type(*it2,color)&&ex_to_color(*it2).type==color_d); + const color & dref=ex_to_color(*it2); + exvector iv_intersect=idx_intersect(dref.seq,iv); + if (iv_intersect.size()==2) { + int sig; // unimportant, since symmetric + ex free_idx=permute_free_index_to_front(dref.seq,iv,false,&sig); + *it1=color(color_T,free_idx,rl); + *(it1+1)=color(color_ONE,rl); + *it2=numeric(5)/numeric(6); + return nonsimplified_ncmul(recombine_color_string( + delta8vec,fvec,dvec,Tvecs,ONEvecs,unknownvec)); + } + } + + // f_{a,b,c} T_b T_c = 3/2 I T_a + for (exvector::iterator it2=fvec.begin(); it2!=fvec.end(); ++it2) { + GINAC_ASSERT(is_ex_exactly_of_type(*it2,color)&&ex_to_color(*it2).type==color_f); + const color & fref=ex_to_color(*it2); + exvector iv_intersect=idx_intersect(fref.seq,iv); + if (iv_intersect.size()==2) { + int sig; + ex free_idx=permute_free_index_to_front(fref.seq,iv,true,&sig); + *it1=color(color_T,free_idx,rl); + *(it1+1)=color(color_ONE,rl); + *it2=numeric(sig*3)/numeric(2)*I; + return nonsimplified_ncmul(recombine_color_string( + delta8vec,fvec,dvec,Tvecs,ONEvecs,unknownvec)); + } + } + } + } + } + + // clear all ONEs when there is at least one corresponding color_T + // in this representation, retain one ONE otherwise + for (unsigned rl=0; rl=2) { - for (unsigned i=0; i=2) { + for (unsigned i=0; i counter; - counter.resize(iv_double.size()); - int l; - for (l=0; unsigned(l)=0)&&((++counter[l])>(int)COLOR_EIGHT)) { - counter[l]=1; - l--; - } - if (l<2) { std::cout << counter[0] << counter[1] << std::endl; } - if (l<0) break; - } - - return sum; + exvector iv_all=e.get_indices(); + exvector iv_double; + + // find double symbolic indices + if (iv_all.size()<2) return e; + for (exvector::const_iterator cit1=iv_all.begin(); cit1!=iv_all.end()-1; ++cit1) { + GINAC_ASSERT(is_ex_of_type(*cit1,coloridx)); + for (exvector::const_iterator cit2=cit1+1; cit2!=iv_all.end(); ++cit2) { + GINAC_ASSERT(is_ex_of_type(*cit2,coloridx)); + if (ex_to_coloridx(*cit1).is_symbolic() && + ex_to_coloridx(*cit1).is_equal(ex_to_coloridx(*cit2))) { + iv_double.push_back(*cit1); + break; + } + } + } + + std::vector counter; + counter.resize(iv_double.size()); + int l; + for (l=0; unsigned(l)=0)&&((++counter[l])>(int)COLOR_EIGHT)) { + counter[l]=1; + l--; + } + if (l<2) { std::cout << counter[0] << counter[1] << std::endl; } + if (l<0) break; + } + + return sum; } void append_exvector_to_exvector(exvector & dest, const exvector & source) { - for (exvector::const_iterator cit=source.begin(); cit!=source.end(); ++cit) { - dest.push_back(*cit); - } + for (exvector::const_iterator cit=source.begin(); cit!=source.end(); ++cit) { + dest.push_back(*cit); + } } #ifndef NO_NAMESPACE_GINAC diff --git a/ginac/color.h b/ginac/color.h index 4899fda2..67218342 100644 --- a/ginac/color.h +++ b/ginac/color.h @@ -42,92 +42,92 @@ typedef std::vector exvectorvector; // CINT does not like /** Base class for color object */ class color : public indexed { - GINAC_DECLARE_REGISTERED_CLASS(color, indexed) + GINAC_DECLARE_REGISTERED_CLASS(color, indexed) // friends - friend color color_ONE(unsigned rl); - friend color color_T(const ex & a, unsigned rl); - friend color color_f(const ex & a, const ex & b, const ex & c); - friend color color_d(const ex & a, const ex & b, const ex & c); - friend ex color_h(const ex & a, const ex & b, const ex & c); - friend color color_delta8(const ex & a, const ex & b); - friend unsigned subs_index_in_exvector(exvector & v, const ex & is, const ex & ir); - friend void split_color_string_in_parts(const exvector & v, exvector & delta8vec, - exvector & fvec, exvector & dvec, - exvectorvector & Tvecs, - exvectorvector & ONEvecs, - exvector & unknownvec); - friend exvector recombine_color_string(exvector & delta8vec, exvector & fvec, - exvector & dvec, exvectorvector & Tvecs, - exvectorvector & ONEvecs, exvector & unknownvec); - friend ex color_trace_of_one_representation_label(const exvector & v); - friend ex color_trace(const exvector & v, unsigned rl); - friend ex simplify_pure_color_string(const ex & e); - friend ex simplify_color(const ex & e); - - + friend color color_ONE(unsigned rl); + friend color color_T(const ex & a, unsigned rl); + friend color color_f(const ex & a, const ex & b, const ex & c); + friend color color_d(const ex & a, const ex & b, const ex & c); + friend ex color_h(const ex & a, const ex & b, const ex & c); + friend color color_delta8(const ex & a, const ex & b); + friend unsigned subs_index_in_exvector(exvector & v, const ex & is, const ex & ir); + friend void split_color_string_in_parts(const exvector & v, exvector & delta8vec, + exvector & fvec, exvector & dvec, + exvectorvector & Tvecs, + exvectorvector & ONEvecs, + exvector & unknownvec); + friend exvector recombine_color_string(exvector & delta8vec, exvector & fvec, + exvector & dvec, exvectorvector & Tvecs, + exvectorvector & ONEvecs, exvector & unknownvec); + friend ex color_trace_of_one_representation_label(const exvector & v); + friend ex color_trace(const exvector & v, unsigned rl); + friend ex simplify_pure_color_string(const ex & e); + friend ex simplify_color(const ex & e); + + // types public: - typedef enum { invalid, // not properly constructed by one of the friend functions - color_T, - color_f, - color_d, - color_delta8, - color_ONE - } color_types; - + typedef enum { invalid, // not properly constructed by one of the friend functions + color_T, + color_f, + color_d, + color_delta8, + color_ONE + } color_types; + // member functions - // default constructor, destructor, copy constructor assignment operator and helpers + // default constructor, destructor, copy constructor assignment operator and helpers public: - color(); - ~color(); - color(const color & other); - const color & operator=(const color & other); + color(); + ~color(); + color(const color & other); + const color & operator=(const color & other); protected: - void copy(const color & other); - void destroy(bool call_parent); + void copy(const color & other); + void destroy(bool call_parent); - // other constructors + // other constructors protected: - color(color_types const t, unsigned rl=0); - color(color_types const t, const ex & i1, unsigned rl=0); - color(color_types const t, const ex & i1, const ex & i2, unsigned rl=0); - color(color_types const t, const ex & i1, const ex & i2, const ex & i3, - unsigned rl=0); - color(color_types const t, const exvector & iv, unsigned rl=0); - color(color_types const t, exvector * ivp, unsigned rl=0); - - // functions overriding virtual functions from base classes + color(color_types const t, unsigned rl=0); + color(color_types const t, const ex & i1, unsigned rl=0); + color(color_types const t, const ex & i1, const ex & i2, unsigned rl=0); + color(color_types const t, const ex & i1, const ex & i2, const ex & i3, + unsigned rl=0); + color(color_types const t, const exvector & iv, unsigned rl=0); + color(color_types const t, exvector * ivp, unsigned rl=0); + + // functions overriding virtual functions from base classes public: - basic * duplicate() const; - void printraw(std::ostream & os) const; - void printtree(std::ostream & os, unsigned indent) const; - void print(std::ostream & os, unsigned upper_precedence=0) const; - void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence=0) const; - bool info(unsigned inf) const; - ex eval(int level=0) const; + basic * duplicate() const; + void printraw(std::ostream & os) const; + void printtree(std::ostream & os, unsigned indent) const; + void print(std::ostream & os, unsigned upper_precedence=0) const; + void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence=0) const; + bool info(unsigned inf) const; + ex eval(int level=0) const; protected: - int compare_same_type(const basic & other) const; - bool is_equal_same_type(const basic & other) const; - ex simplify_ncmul(const exvector & v) const; - ex thisexprseq(const exvector & v) const; - ex thisexprseq(exvector * vp) const; - - // new virtual functions which can be overridden by derived classes - // none - - // non-virtual functions in this class + int compare_same_type(const basic & other) const; + bool is_equal_same_type(const basic & other) const; + ex simplify_ncmul(const exvector & v) const; + ex thisexprseq(const exvector & v) const; + ex thisexprseq(exvector * vp) const; + + // new virtual functions which can be overridden by derived classes + // none + + // non-virtual functions in this class protected: - bool all_of_type_coloridx(void) const; - + bool all_of_type_coloridx(void) const; + // member variables protected: - color_types type; - unsigned representation_label; // to distiguish independent color matrices coming from separated fermion lines + color_types type; + unsigned representation_label; // to distiguish independent color matrices coming from separated fermion lines }; // global constants @@ -153,13 +153,13 @@ color color_d(const ex & a, const ex & b, const ex & c); ex color_h(const ex & a, const ex & b, const ex & c); color color_delta8(const ex & a, const ex & b); void split_color_string_in_parts(const exvector & v, exvector & delta8vec, - exvector & fvec, exvector & dvec, - exvectorvector & Tvecs, - exvectorvector & ONEvecs, - exvector & unknownvec); + exvector & fvec, exvector & dvec, + exvectorvector & Tvecs, + exvectorvector & ONEvecs, + exvector & unknownvec); exvector recombine_color_string(exvector & delta8vec, exvector & fvec, - exvector & dvec, exvectorvector & Tvecs, - exvectorvector & ONEvecs, exvector & unknownvec); + exvector & dvec, exvectorvector & Tvecs, + exvectorvector & ONEvecs, exvector & unknownvec); ex color_trace_of_one_representation_label(const exvector & v); ex color_trace(const exvector & v, unsigned rl=0); ex simplify_pure_color_string(const ex & e); diff --git a/ginac/coloridx.cpp b/ginac/coloridx.cpp index aec4c671..261365c7 100644 --- a/ginac/coloridx.cpp +++ b/ginac/coloridx.cpp @@ -41,44 +41,44 @@ GINAC_IMPLEMENT_REGISTERED_CLASS(coloridx, idx) coloridx::coloridx() { - debugmsg("coloridx default constructor",LOGLEVEL_CONSTRUCT); - // serial is incremented in idx::idx() - name="color"+ToString(serial); - tinfo_key=TINFO_coloridx; + debugmsg("coloridx default constructor",LOGLEVEL_CONSTRUCT); + // serial is incremented in idx::idx() + name="color"+ToString(serial); + tinfo_key=TINFO_coloridx; } coloridx::~coloridx() { - debugmsg("coloridx destructor",LOGLEVEL_DESTRUCT); - destroy(0); + debugmsg("coloridx destructor",LOGLEVEL_DESTRUCT); + destroy(0); } coloridx::coloridx(const coloridx & other) { - debugmsg("coloridx copy constructor",LOGLEVEL_CONSTRUCT); - copy(other); + debugmsg("coloridx copy constructor",LOGLEVEL_CONSTRUCT); + copy(other); } const coloridx & coloridx::operator=(const coloridx & other) { - debugmsg("coloridx operator=",LOGLEVEL_ASSIGNMENT); - if (this != &other) { - destroy(1); - copy(other); - } - return *this; + debugmsg("coloridx operator=",LOGLEVEL_ASSIGNMENT); + if (this != &other) { + destroy(1); + copy(other); + } + return *this; } // protected void coloridx::copy(const coloridx & other) { - inherited::copy(other); + inherited::copy(other); } void coloridx::destroy(bool call_parent) { - if (call_parent) inherited::destroy(call_parent); + if (call_parent) inherited::destroy(call_parent); } ////////// @@ -89,28 +89,28 @@ void coloridx::destroy(bool call_parent) coloridx::coloridx(bool cov) : idx(cov) { - debugmsg("coloridx constructor from bool",LOGLEVEL_CONSTRUCT); - // serial is incremented in idx::idx(bool) - name="color"+ToString(serial); - tinfo_key=TINFO_coloridx; + debugmsg("coloridx constructor from bool",LOGLEVEL_CONSTRUCT); + // serial is incremented in idx::idx(bool) + name="color"+ToString(serial); + tinfo_key=TINFO_coloridx; } coloridx::coloridx(const std::string & n, bool cov) : idx(n,cov) { - debugmsg("coloridx constructor from string,bool",LOGLEVEL_CONSTRUCT); - tinfo_key=TINFO_coloridx; + debugmsg("coloridx constructor from string,bool",LOGLEVEL_CONSTRUCT); + tinfo_key=TINFO_coloridx; } coloridx::coloridx(const char * n, bool cov) : idx(n,cov) { - debugmsg("coloridx constructor from char*,bool",LOGLEVEL_CONSTRUCT); - tinfo_key=TINFO_coloridx; + debugmsg("coloridx constructor from char*,bool",LOGLEVEL_CONSTRUCT); + tinfo_key=TINFO_coloridx; } coloridx::coloridx(unsigned v, bool cov) : idx(v,cov) { - debugmsg("coloridx constructor from unsigned,bool",LOGLEVEL_CONSTRUCT); - tinfo_key=TINFO_coloridx; + debugmsg("coloridx constructor from unsigned,bool",LOGLEVEL_CONSTRUCT); + tinfo_key=TINFO_coloridx; } ////////// @@ -120,19 +120,19 @@ coloridx::coloridx(unsigned v, bool cov) : idx(v,cov) /** Construct object from archive_node. */ coloridx::coloridx(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) { - debugmsg("coloridx constructor from archive_node", LOGLEVEL_CONSTRUCT); + debugmsg("coloridx constructor from archive_node", LOGLEVEL_CONSTRUCT); } /** Unarchive the object. */ ex coloridx::unarchive(const archive_node &n, const lst &sym_lst) { - return (new coloridx(n, sym_lst))->setflag(status_flags::dynallocated); + return (new coloridx(n, sym_lst))->setflag(status_flags::dynallocated); } /** Archive the object. */ void coloridx::archive(archive_node &n) const { - inherited::archive(n); + inherited::archive(n); } ////////// @@ -143,77 +143,77 @@ void coloridx::archive(archive_node &n) const basic * coloridx::duplicate() const { - debugmsg("coloridx duplicate",LOGLEVEL_DUPLICATE); - return new coloridx(*this); + debugmsg("coloridx duplicate",LOGLEVEL_DUPLICATE); + return new coloridx(*this); } void coloridx::printraw(std::ostream & os) const { - debugmsg("coloridx printraw",LOGLEVEL_PRINT); + debugmsg("coloridx printraw",LOGLEVEL_PRINT); - os << "coloridx("; + os << "coloridx("; - if (symbolic) { - os << "symbolic,name=" << name; - } else { - os << "non symbolic,value=" << value; - } + if (symbolic) { + os << "symbolic,name=" << name; + } else { + os << "non symbolic,value=" << value; + } - if (covariant) { - os << ",covariant"; - } else { - os << ",contravariant"; - } + if (covariant) { + os << ",covariant"; + } else { + os << ",contravariant"; + } - os << ",serial=" << serial; - os << ",hash=" << hashvalue << ",flags=" << flags; - os << ")"; + os << ",serial=" << serial; + os << ",hash=" << hashvalue << ",flags=" << flags; + os << ")"; } void coloridx::printtree(std::ostream & os, unsigned indent) const { - debugmsg("coloridx printtree",LOGLEVEL_PRINT); + debugmsg("coloridx printtree",LOGLEVEL_PRINT); - os << std::string(indent,' ') << "coloridx: "; + os << std::string(indent,' ') << "coloridx: "; - if (symbolic) { - os << "symbolic,name=" << name; - } else { - os << "non symbolic,value=" << value; - } + if (symbolic) { + os << "symbolic,name=" << name; + } else { + os << "non symbolic,value=" << value; + } - if (covariant) { - os << ",covariant"; - } else { - os << ",contravariant"; - } + if (covariant) { + os << ",covariant"; + } else { + os << ",contravariant"; + } - os << ", serial=" << serial - << ", hash=" << hashvalue - << " (0x" << std::hex << hashvalue << std::dec << ")" - << ", flags=" << flags << std::endl; + os << ", serial=" << serial + << ", hash=" << hashvalue + << " (0x" << std::hex << hashvalue << std::dec << ")" + << ", flags=" << flags << std::endl; } void coloridx::print(std::ostream & os, unsigned upper_precedence) const { - debugmsg("coloridx print",LOGLEVEL_PRINT); + debugmsg("coloridx print",LOGLEVEL_PRINT); - if (covariant) { - os << "_"; - } else { - os << "~"; - } - if (symbolic) { - os << name; - } else { - os << value; - } + if (covariant) { + os << "_"; + } else { + os << "~"; + } + if (symbolic) { + os << name; + } else { + os << value; + } } bool coloridx::info(unsigned inf) const { - if (inf==info_flags::coloridx) return true; - return idx::info(inf); + if (inf==info_flags::coloridx) return true; + return idx::info(inf); } ////////// diff --git a/ginac/coloridx.h b/ginac/coloridx.h index 5031e323..37b82143 100644 --- a/ginac/coloridx.h +++ b/ginac/coloridx.h @@ -34,45 +34,45 @@ namespace GiNaC { class coloridx : public idx { - GINAC_DECLARE_REGISTERED_CLASS(coloridx, idx) + GINAC_DECLARE_REGISTERED_CLASS(coloridx, idx) - friend class color; + friend class color; // member functions - // default constructor, destructor, copy constructor assignment operator and helpers + // default constructor, destructor, copy constructor assignment operator and helpers public: - coloridx(); - ~coloridx(); - coloridx (const coloridx & other); - const coloridx & operator=(const coloridx & other); + coloridx(); + ~coloridx(); + coloridx (const coloridx & other); + const coloridx & operator=(const coloridx & other); protected: - void copy(const coloridx & other); - void destroy(bool call_parent); + void copy(const coloridx & other); + void destroy(bool call_parent); - // other constructors + // other constructors public: - explicit coloridx(bool cov); - explicit coloridx(const std::string & n, bool cov=false); - explicit coloridx(const char * n, bool cov=false); - explicit coloridx(unsigned v, bool cov=false); + explicit coloridx(bool cov); + explicit coloridx(const std::string & n, bool cov=false); + explicit coloridx(const char * n, bool cov=false); + explicit coloridx(unsigned v, bool cov=false); - // functions overriding virtual functions from bases classes + // functions overriding virtual functions from bases classes public: - basic * duplicate() const; - void printraw(std::ostream & os) const; - void printtree(std::ostream & os, unsigned indent) const; - void print(std::ostream & os, unsigned upper_precedence=0) const; - bool info(unsigned inf) const; + basic * duplicate() const; + void printraw(std::ostream & os) const; + void printtree(std::ostream & os, unsigned indent) const; + void print(std::ostream & os, unsigned upper_precedence=0) const; + bool info(unsigned inf) const; - // new virtual functions which can be overridden by derived classes - // none + // new virtual functions which can be overridden by derived classes + // none - // non-virtual functions in this class - // none + // non-virtual functions in this class + // none - // member variables - // none + // member variables + // none }; // global constants diff --git a/ginac/constant.cpp b/ginac/constant.cpp index 826f5153..688d2288 100644 --- a/ginac/constant.cpp +++ b/ginac/constant.cpp @@ -42,45 +42,45 @@ GINAC_IMPLEMENT_REGISTERED_CLASS(constant, basic) // public constant::constant() : - basic(TINFO_constant), name(""), ef(0), - number(0), serial(next_serial++) + basic(TINFO_constant), name(""), ef(0), + number(0), serial(next_serial++) { - debugmsg("constant default constructor",LOGLEVEL_CONSTRUCT); + debugmsg("constant default constructor",LOGLEVEL_CONSTRUCT); } constant::~constant() { - debugmsg("constant destructor",LOGLEVEL_DESTRUCT); - destroy(0); + debugmsg("constant destructor",LOGLEVEL_DESTRUCT); + destroy(0); } constant::constant(const constant & other) { - debugmsg("constant copy constructor",LOGLEVEL_CONSTRUCT); - copy(other); + debugmsg("constant copy constructor",LOGLEVEL_CONSTRUCT); + copy(other); } // protected void constant::copy(const constant & other) { - basic::copy(other); - name=other.name; - serial=other.serial; - ef=other.ef; - if (other.number != 0) { - number = new numeric(*other.number); - } else { - number = 0; - } - // fct_assigned=other.fct_assigned; + basic::copy(other); + name=other.name; + serial=other.serial; + ef=other.ef; + if (other.number != 0) { + number = new numeric(*other.number); + } else { + number = 0; + } + // fct_assigned=other.fct_assigned; } void constant::destroy(bool call_parent) { - delete number; - if (call_parent) - basic::destroy(call_parent); + delete number; + if (call_parent) + basic::destroy(call_parent); } ////////// @@ -90,18 +90,18 @@ void constant::destroy(bool call_parent) // public constant::constant(const std::string & initname, evalffunctype efun) : - basic(TINFO_constant), name(initname), ef(efun), - // number(0), fct_assigned(true), serial(next_serial++) - number(0), serial(next_serial++) + basic(TINFO_constant), name(initname), ef(efun), + // number(0), fct_assigned(true), serial(next_serial++) + number(0), serial(next_serial++) { - debugmsg("constant constructor from string, function",LOGLEVEL_CONSTRUCT); + debugmsg("constant constructor from string, function",LOGLEVEL_CONSTRUCT); } constant::constant(const std::string & initname, const numeric & initnumber) : - basic(TINFO_constant), name(initname), ef(0), - number(new numeric(initnumber)), /* fct_assigned(false),*/ serial(next_serial++) + basic(TINFO_constant), name(initname), ef(0), + number(new numeric(initnumber)), /* fct_assigned(false),*/ serial(next_serial++) { - debugmsg("constant constructor from string, numeric",LOGLEVEL_CONSTRUCT); + debugmsg("constant constructor from string, numeric",LOGLEVEL_CONSTRUCT); } ////////// @@ -111,33 +111,33 @@ 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 constructor from archive_node", LOGLEVEL_CONSTRUCT); } /** Unarchive the object. */ ex constant::unarchive(const archive_node &n, const lst &sym_lst) { - // Find constant by name (!! this is bad: 'twould be better if there - // was a list of all global constants that we could search) - std::string s; - if (n.find_string("name", s)) { - if (s == Pi.name) - return Pi; - else if (s == Catalan.name) - return Catalan; - else if (s == Euler.name) - return Euler; - else - throw (std::runtime_error("unknown constant '" + s + "' in archive")); - } else - throw (std::runtime_error("unnamed constant in archive")); + // Find constant by name (!! this is bad: 'twould be better if there + // was a list of all global constants that we could search) + std::string s; + if (n.find_string("name", s)) { + if (s == Pi.name) + return Pi; + else if (s == Catalan.name) + return Catalan; + else if (s == Euler.name) + return Euler; + else + throw (std::runtime_error("unknown constant '" + s + "' in archive")); + } else + throw (std::runtime_error("unnamed constant in archive")); } /** Archive the object. */ void constant::archive(archive_node &n) const { - inherited::archive(n); - n.add_string("name", name); + inherited::archive(n); + n.add_string("name", name); } ////////// @@ -148,46 +148,46 @@ void constant::archive(archive_node &n) const basic * constant::duplicate() const { - debugmsg("constant duplicate",LOGLEVEL_DUPLICATE); - return new constant(*this); + debugmsg("constant duplicate",LOGLEVEL_DUPLICATE); + return new constant(*this); } void constant::print(std::ostream & os, unsigned upper_precedence) const { - debugmsg("constant print",LOGLEVEL_PRINT); - os << name; + debugmsg("constant print",LOGLEVEL_PRINT); + os << name; } void constant::printraw(std::ostream & os) const { - debugmsg("constant printraw",LOGLEVEL_PRINT); - os << "constant(" << name << ")"; + debugmsg("constant printraw",LOGLEVEL_PRINT); + os << "constant(" << name << ")"; } void constant::printtree(std::ostream & os, unsigned indent) const { - debugmsg("constant printtree",LOGLEVEL_PRINT); - os << std::string(indent,' ') << name - << ", type=" << typeid(*this).name() - << ", hash=" << hashvalue - << " (0x" << std::hex << hashvalue << std::dec << ")" - << ", flags=" << flags << std::endl; + debugmsg("constant printtree",LOGLEVEL_PRINT); + os << std::string(indent,' ') << name + << ", type=" << class_name() + << ", hash=" << hashvalue + << " (0x" << std::hex << hashvalue << std::dec << ")" + << ", flags=" << flags << std::endl; } void constant::printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const { - debugmsg("constant print csrc",LOGLEVEL_PRINT); - os << name; + debugmsg("constant print csrc",LOGLEVEL_PRINT); + os << name; } ex constant::evalf(int level) const { - if (ef!=0) { - return ef(); - } else if (number != 0) { - return *number; - } - return *this; + if (ef!=0) { + return ef(); + } else if (number != 0) { + return *number; + } + return *this; } // protected @@ -197,24 +197,24 @@ ex constant::evalf(int level) const * @see ex::diff */ ex constant::derivative(const symbol & s) const { - return _ex0(); + return _ex0(); } int constant::compare_same_type(const basic & other) const { - GINAC_ASSERT(is_exactly_of_type(other, constant)); - // const constant & o=static_cast(const_cast(other)); - // return name.compare(o.name); - const constant *o = static_cast(&other); - if (serial==o->serial) return 0; - return serial < o->serial ? -1 : 1; + GINAC_ASSERT(is_exactly_of_type(other, constant)); + // const constant & o=static_cast(const_cast(other)); + // return name.compare(o.name); + const constant *o = static_cast(&other); + if (serial==o->serial) return 0; + return serial < o->serial ? -1 : 1; } bool constant::is_equal_same_type(const basic & other) const { - GINAC_ASSERT(is_exactly_of_type(other, constant)); - const constant *o = static_cast(&other); - return serial==o->serial; + GINAC_ASSERT(is_exactly_of_type(other, constant)); + const constant *o = static_cast(&other); + return serial==o->serial; } ////////// diff --git a/ginac/constant.h b/ginac/constant.h index d099378f..47f2a9d6 100644 --- a/ginac/constant.h +++ b/ginac/constant.h @@ -31,60 +31,60 @@ namespace GiNaC { #endif // ndef NO_NAMESPACE_GINAC typedef ex (*evalffunctype)(void); - + /** This class holds constants, symbols with specific numerical value. Each * object of this class must either provide their own function to evaluate it * to class numeric or provide the constant as a numeric (if it's an exact * number). */ class constant : public basic { - GINAC_DECLARE_REGISTERED_CLASS(constant, basic) + GINAC_DECLARE_REGISTERED_CLASS(constant, basic) // member functions - // default constructor, destructor, copy constructor assignment operator and helpers + // default constructor, destructor, copy constructor assignment operator and helpers public: - constant(); - ~constant(); - constant(const constant & other); - // const constant & operator=(const constant & other); /* it's pervert! */ + constant(); + ~constant(); + constant(const constant & other); + // const constant & operator=(const constant & other); /* it's pervert! */ protected: - void copy(const constant & other); - void destroy(bool call_parent); + void copy(const constant & other); + void destroy(bool call_parent); - // other constructors + // other constructors public: - constant(const std::string & initname, evalffunctype efun=0); - constant(const std::string & initname, const numeric & initnumber); + constant(const std::string & initname, evalffunctype efun=0); + constant(const std::string & initname, const numeric & initnumber); - // functions overriding virtual functions from bases classes + // functions overriding virtual functions from bases classes public: - basic * duplicate() 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; + basic * duplicate() 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; protected: - ex derivative(const symbol & s) const; - int compare_same_type(const basic & other) const; - bool is_equal_same_type(const basic & other) const; - - // new virtual functions which can be overridden by derived classes - // none + ex derivative(const symbol & s) const; + int compare_same_type(const basic & other) const; + bool is_equal_same_type(const basic & other) const; + + // new virtual functions which can be overridden by derived classes + // none - // non-virtual functions in this class - // none + // non-virtual functions in this class + // none // member variables private: - std::string name; - evalffunctype ef; - numeric * number; - // bool fct_assigned; - unsigned serial; //!< unique serial number for comparision - static unsigned next_serial; + std::string name; + evalffunctype ef; + numeric * number; + // bool fct_assigned; + unsigned serial; //!< unique serial number for comparision + static unsigned next_serial; }; // global constants diff --git a/ginac/ex.cpp b/ginac/ex.cpp index 2857cdc8..559bae47 100644 --- a/ginac/ex.cpp +++ b/ginac/ex.cpp @@ -48,45 +48,45 @@ namespace GiNaC { 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; + 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; - } + 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; + 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; + 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 @@ -101,44 +101,44 @@ const ex & ex::operator=(const ex & other) ex::ex(const basic & other) { - debugmsg("ex constructor from basic",LOGLEVEL_CONSTRUCT); - construct_from_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); + 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); + 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); + 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); + 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); + 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); + debugmsg("ex constructor from string,lst",LOGLEVEL_CONSTRUCT); + construct_from_string_and_lst(s, l); } #endif // ndef INLINE_EX_CONSTRUCTORS @@ -164,41 +164,41 @@ ex::ex(const std::string &s, const ex &l) /** Swap the contents of two expressions. */ void ex::swap(ex & other) { - debugmsg("ex swap",LOGLEVEL_MEMBER_FUNCTION); + debugmsg("ex swap",LOGLEVEL_MEMBER_FUNCTION); - GINAC_ASSERT(bp!=0); - GINAC_ASSERT(bp->flags & status_flags::dynallocated); - GINAC_ASSERT(other.bp!=0); - GINAC_ASSERT(other.bp->flags & status_flags::dynallocated); - - basic * tmpbp=bp; - bp=other.bp; - other.bp=tmpbp; + GINAC_ASSERT(bp!=0); + GINAC_ASSERT(bp->flags & status_flags::dynallocated); + GINAC_ASSERT(other.bp!=0); + GINAC_ASSERT(other.bp->flags & status_flags::dynallocated); + + basic * tmpbp=bp; + bp=other.bp; + other.bp=tmpbp; } /** Output formatted to be useful as ginsh input. */ void ex::print(std::ostream & os, unsigned upper_precedence) const { - debugmsg("ex print",LOGLEVEL_PRINT); - GINAC_ASSERT(bp!=0); - bp->print(os,upper_precedence); + debugmsg("ex print",LOGLEVEL_PRINT); + GINAC_ASSERT(bp!=0); + bp->print(os,upper_precedence); } void ex::printraw(std::ostream & os) const { - debugmsg("ex printraw",LOGLEVEL_PRINT); - GINAC_ASSERT(bp!=0); - os << "ex("; - bp->printraw(os); - os << ")"; + debugmsg("ex printraw",LOGLEVEL_PRINT); + GINAC_ASSERT(bp!=0); + os << "ex("; + bp->printraw(os); + os << ")"; } void ex::printtree(std::ostream & os, unsigned indent) const { - debugmsg("ex printtree",LOGLEVEL_PRINT); - GINAC_ASSERT(bp!=0); - // os << "refcount=" << bp->refcount << " "; - bp->printtree(os,indent); + debugmsg("ex printtree",LOGLEVEL_PRINT); + GINAC_ASSERT(bp!=0); + // os << "refcount=" << bp->refcount << " "; + bp->printtree(os,indent); } /** Print expression as a C++ statement. The output looks like @@ -210,100 +210,100 @@ void ex::printtree(std::ostream & os, unsigned indent) const * @param var_name variable name to be printed */ void ex::printcsrc(std::ostream & os, unsigned type, const char *var_name) const { - debugmsg("ex print csrc", LOGLEVEL_PRINT); - GINAC_ASSERT(bp!=0); - switch (type) { - case csrc_types::ctype_float: - os << "float "; - break; - case csrc_types::ctype_double: - os << "double "; - break; - case csrc_types::ctype_cl_N: - os << "cl_N "; - break; - } - os << var_name << " = "; - bp->printcsrc(os, type, 0); - os << ";\n"; + debugmsg("ex print csrc", LOGLEVEL_PRINT); + GINAC_ASSERT(bp!=0); + switch (type) { + case csrc_types::ctype_float: + os << "float "; + break; + case csrc_types::ctype_double: + os << "double "; + break; + case csrc_types::ctype_cl_N: + os << "cl_N "; + break; + } + os << var_name << " = "; + bp->printcsrc(os, type, 0); + os << ";\n"; } /** Little wrapper arount print to be called within a debugger. */ void ex::dbgprint(void) const { - debugmsg("ex dbgprint",LOGLEVEL_PRINT); - GINAC_ASSERT(bp!=0); - bp->dbgprint(); + debugmsg("ex dbgprint",LOGLEVEL_PRINT); + GINAC_ASSERT(bp!=0); + bp->dbgprint(); } /** Little wrapper arount printtree to be called within a debugger. */ void ex::dbgprinttree(void) const { - debugmsg("ex dbgprinttree",LOGLEVEL_PRINT); - GINAC_ASSERT(bp!=0); - bp->dbgprinttree(); + debugmsg("ex dbgprinttree",LOGLEVEL_PRINT); + GINAC_ASSERT(bp!=0); + bp->dbgprinttree(); } bool ex::info(unsigned inf) const { - return bp->info(inf); + return bp->info(inf); } unsigned ex::nops() const { - GINAC_ASSERT(bp!=0); - return bp->nops(); + GINAC_ASSERT(bp!=0); + return bp->nops(); } ex ex::expand(unsigned options) const { - GINAC_ASSERT(bp!=0); - if (bp->flags & status_flags::expanded) - return *bp; - else - return bp->expand(options); + GINAC_ASSERT(bp!=0); + if (bp->flags & status_flags::expanded) + return *bp; + else + return bp->expand(options); } bool ex::has(const ex & other) const { - GINAC_ASSERT(bp!=0); - return bp->has(other); + GINAC_ASSERT(bp!=0); + return bp->has(other); } int ex::degree(const symbol & s) const { - GINAC_ASSERT(bp!=0); - return bp->degree(s); + GINAC_ASSERT(bp!=0); + return bp->degree(s); } int ex::ldegree(const symbol & s) const { - GINAC_ASSERT(bp!=0); - return bp->ldegree(s); + GINAC_ASSERT(bp!=0); + return bp->ldegree(s); } ex ex::coeff(const symbol & s, int n) const { - GINAC_ASSERT(bp!=0); - return bp->coeff(s,n); + GINAC_ASSERT(bp!=0); + return bp->coeff(s,n); } ex ex::collect(const symbol & s) const { - GINAC_ASSERT(bp!=0); - return bp->collect(s); + GINAC_ASSERT(bp!=0); + return bp->collect(s); } ex ex::eval(int level) const { - GINAC_ASSERT(bp!=0); - return bp->eval(level); + GINAC_ASSERT(bp!=0); + return bp->eval(level); } ex ex::evalf(int level) const { - GINAC_ASSERT(bp!=0); - return bp->evalf(level); + GINAC_ASSERT(bp!=0); + return bp->evalf(level); } /** Compute partial derivative of an expression. @@ -313,342 +313,342 @@ ex ex::evalf(int level) const * @return partial derivative as a new expression */ ex ex::diff(const symbol & s, unsigned nth) const { - GINAC_ASSERT(bp!=0); + GINAC_ASSERT(bp!=0); - if (!nth) - return *this; - else - return bp->diff(s, nth); + if (!nth) + return *this; + else + return bp->diff(s, nth); } ex ex::subs(const lst & ls, const lst & lr) const { - GINAC_ASSERT(bp!=0); - return bp->subs(ls,lr); + GINAC_ASSERT(bp!=0); + return bp->subs(ls,lr); } ex ex::subs(const ex & e) const { - GINAC_ASSERT(bp!=0); - return bp->subs(e); + GINAC_ASSERT(bp!=0); + return bp->subs(e); } exvector ex::get_indices(void) const { - GINAC_ASSERT(bp!=0); - return bp->get_indices(); + GINAC_ASSERT(bp!=0); + return bp->get_indices(); } ex ex::simplify_ncmul(const exvector & v) const { - GINAC_ASSERT(bp!=0); - return bp->simplify_ncmul(v); + GINAC_ASSERT(bp!=0); + return bp->simplify_ncmul(v); } ex ex::operator[](const ex & index) const { - debugmsg("ex operator[ex]",LOGLEVEL_OPERATOR); - GINAC_ASSERT(bp!=0); - return (*bp)[index]; + debugmsg("ex operator[ex]",LOGLEVEL_OPERATOR); + GINAC_ASSERT(bp!=0); + return (*bp)[index]; } ex ex::operator[](int i) const { - debugmsg("ex operator[int]",LOGLEVEL_OPERATOR); - GINAC_ASSERT(bp!=0); - return (*bp)[i]; + debugmsg("ex operator[int]",LOGLEVEL_OPERATOR); + GINAC_ASSERT(bp!=0); + return (*bp)[i]; } /** Return operand/member at position i. */ ex ex::op(int i) const { - debugmsg("ex op()",LOGLEVEL_MEMBER_FUNCTION); - GINAC_ASSERT(bp!=0); - return bp->op(i); + debugmsg("ex op()",LOGLEVEL_MEMBER_FUNCTION); + GINAC_ASSERT(bp!=0); + return bp->op(i); } /** Return modifyable operand/member at position i. */ ex & ex::let_op(int i) { - debugmsg("ex let_op()",LOGLEVEL_MEMBER_FUNCTION); - makewriteable(); - GINAC_ASSERT(bp!=0); - return bp->let_op(i); + debugmsg("ex let_op()",LOGLEVEL_MEMBER_FUNCTION); + makewriteable(); + GINAC_ASSERT(bp!=0); + return bp->let_op(i); } /** Left hand side of relational expression. */ ex ex::lhs(void) const { - debugmsg("ex lhs()",LOGLEVEL_MEMBER_FUNCTION); - GINAC_ASSERT(is_ex_of_type(*this,relational)); - return (*static_cast(bp)).lhs(); + debugmsg("ex lhs()",LOGLEVEL_MEMBER_FUNCTION); + GINAC_ASSERT(is_ex_of_type(*this,relational)); + return (*static_cast(bp)).lhs(); } /** Right hand side of relational expression. */ ex ex::rhs(void) const { - debugmsg("ex rhs()",LOGLEVEL_MEMBER_FUNCTION); - GINAC_ASSERT(is_ex_of_type(*this,relational)); - return (*static_cast(bp)).rhs(); + debugmsg("ex rhs()",LOGLEVEL_MEMBER_FUNCTION); + GINAC_ASSERT(is_ex_of_type(*this,relational)); + 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); + 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); + 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); - return bp->return_type(); + GINAC_ASSERT(bp!=0); + return bp->return_type(); } unsigned ex::return_type_tinfo(void) const { - GINAC_ASSERT(bp!=0); - return bp->return_type_tinfo(); + GINAC_ASSERT(bp!=0); + return bp->return_type_tinfo(); } unsigned ex::gethash(void) const { - GINAC_ASSERT(bp!=0); - return bp->gethash(); + GINAC_ASSERT(bp!=0); + return bp->gethash(); } ex ex::exadd(const ex & rh) const { - return (new add(*this,rh))->setflag(status_flags::dynallocated); + return (new add(*this,rh))->setflag(status_flags::dynallocated); } ex ex::exmul(const ex & rh) const { - return (new mul(*this,rh))->setflag(status_flags::dynallocated); + return (new mul(*this,rh))->setflag(status_flags::dynallocated); } ex ex::exncmul(const ex & rh) const { - return (new ncmul(*this,rh))->setflag(status_flags::dynallocated); + return (new ncmul(*this,rh))->setflag(status_flags::dynallocated); } // private void ex::makewriteable() { - debugmsg("ex makewriteable",LOGLEVEL_MEMBER_FUNCTION); - GINAC_ASSERT(bp!=0); - GINAC_ASSERT(bp->flags & status_flags::dynallocated); - if (bp->refcount > 1) { - basic * bp2 = bp->duplicate(); - ++bp2->refcount; - bp2->setflag(status_flags::dynallocated); - --bp->refcount; - bp = bp2; - } - GINAC_ASSERT(bp->refcount == 1); + debugmsg("ex makewriteable",LOGLEVEL_MEMBER_FUNCTION); + GINAC_ASSERT(bp!=0); + GINAC_ASSERT(bp->flags & status_flags::dynallocated); + if (bp->refcount > 1) { + basic * bp2 = bp->duplicate(); + ++bp2->refcount; + bp2->setflag(status_flags::dynallocated); + --bp->refcount; + bp = bp2; + } + GINAC_ASSERT(bp->refcount == 1); } void ex::construct_from_basic(const basic & other) { - if ((other.flags & status_flags::evaluated)==0) { - // cf. copy constructor - 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)) { - delete &const_cast(other); - } - } else { - if (other.flags & status_flags::dynallocated) { - // it's on the heap, so just copy bp: - bp = &const_cast(other); - } else { - // create a duplicate on the heap: - bp = other.duplicate(); - bp->setflag(status_flags::dynallocated); - } - GINAC_ASSERT(bp!=0); - // bp->clearflag(status_flags::evaluated); - ++bp->refcount; - } - GINAC_ASSERT(bp!=0); - GINAC_ASSERT(bp->flags & status_flags::dynallocated); + if ((other.flags & status_flags::evaluated)==0) { + // cf. copy constructor + 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)) { + delete &const_cast(other); + } + } else { + if (other.flags & status_flags::dynallocated) { + // it's on the heap, so just copy bp: + bp = &const_cast(other); + } else { + // create a duplicate on the heap: + bp = other.duplicate(); + bp->setflag(status_flags::dynallocated); + } + GINAC_ASSERT(bp!=0); + // bp->clearflag(status_flags::evaluated); + ++bp->refcount; + } + GINAC_ASSERT(bp!=0); + GINAC_ASSERT(bp->flags & status_flags::dynallocated); } void ex::construct_from_int(int i) { - switch (i) { // some tiny efficiency-hack - case -2: - bp = _ex_2().bp; - ++bp->refcount; - break; - case -1: - bp = _ex_1().bp; - ++bp->refcount; - break; - case 0: - bp = _ex0().bp; - ++bp->refcount; - break; - case 1: - bp = _ex1().bp; - ++bp->refcount; - break; - case 2: - bp = _ex2().bp; - ++bp->refcount; - break; - default: - bp = new numeric(i); - bp->setflag(status_flags::dynallocated); - ++bp->refcount; - GINAC_ASSERT((bp->flags) & status_flags::dynallocated); - GINAC_ASSERT(bp->refcount=1); - } -} - + switch (i) { // some tiny efficiency-hack + case -2: + bp = _ex_2().bp; + ++bp->refcount; + break; + case -1: + bp = _ex_1().bp; + ++bp->refcount; + break; + case 0: + bp = _ex0().bp; + ++bp->refcount; + break; + case 1: + bp = _ex1().bp; + ++bp->refcount; + break; + case 2: + bp = _ex2().bp; + ++bp->refcount; + break; + default: + bp = new numeric(i); + bp->setflag(status_flags::dynallocated); + ++bp->refcount; + GINAC_ASSERT((bp->flags) & status_flags::dynallocated); + GINAC_ASSERT(bp->refcount=1); + } +} + void ex::construct_from_uint(unsigned int i) { - switch (i) { // some tiny efficiency-hack - case -2: - bp = _ex_2().bp; - ++bp->refcount; - break; - case -1: - bp = _ex_1().bp; - ++bp->refcount; - break; - case 0: - bp = _ex0().bp; - ++bp->refcount; - break; - case 1: - bp = _ex1().bp; - ++bp->refcount; - break; - case 2: - bp = _ex2().bp; - ++bp->refcount; - break; - default: - bp = new numeric(i); - bp->setflag(status_flags::dynallocated); - ++bp->refcount; - GINAC_ASSERT((bp->flags) & status_flags::dynallocated); - GINAC_ASSERT(bp->refcount=1); - } -} - + switch (i) { // some tiny efficiency-hack + case -2: + bp = _ex_2().bp; + ++bp->refcount; + break; + case -1: + bp = _ex_1().bp; + ++bp->refcount; + break; + case 0: + bp = _ex0().bp; + ++bp->refcount; + break; + case 1: + bp = _ex1().bp; + ++bp->refcount; + break; + case 2: + bp = _ex2().bp; + ++bp->refcount; + break; + default: + bp = new numeric(i); + bp->setflag(status_flags::dynallocated); + ++bp->refcount; + GINAC_ASSERT((bp->flags) & status_flags::dynallocated); + GINAC_ASSERT(bp->refcount=1); + } +} + void ex::construct_from_long(long i) { - switch (i) { // some tiny efficiency-hack - case -2: - bp = _ex_2().bp; - ++bp->refcount; - break; - case -1: - bp = _ex_1().bp; - ++bp->refcount; - break; - case 0: - bp = _ex0().bp; - ++bp->refcount; - break; - case 1: - bp = _ex1().bp; - ++bp->refcount; - break; - case 2: - bp = _ex2().bp; - ++bp->refcount; - break; - default: - bp = new numeric(i); - bp->setflag(status_flags::dynallocated); - ++bp->refcount; - GINAC_ASSERT((bp->flags) & status_flags::dynallocated); - GINAC_ASSERT(bp->refcount=1); - } -} - + switch (i) { // some tiny efficiency-hack + case -2: + bp = _ex_2().bp; + ++bp->refcount; + break; + case -1: + bp = _ex_1().bp; + ++bp->refcount; + break; + case 0: + bp = _ex0().bp; + ++bp->refcount; + break; + case 1: + bp = _ex1().bp; + ++bp->refcount; + break; + case 2: + bp = _ex2().bp; + ++bp->refcount; + break; + default: + bp = new numeric(i); + bp->setflag(status_flags::dynallocated); + ++bp->refcount; + GINAC_ASSERT((bp->flags) & status_flags::dynallocated); + GINAC_ASSERT(bp->refcount=1); + } +} + void ex::construct_from_ulong(unsigned long i) { - switch (i) { // some tiny efficiency-hack - case -2: - bp = _ex_2().bp; - ++bp->refcount; - break; - case -1: - bp = _ex_1().bp; - ++bp->refcount; - break; - case 0: - bp = _ex0().bp; - ++bp->refcount; - break; - case 1: - bp = _ex1().bp; - ++bp->refcount; - break; - case 2: - bp = _ex2().bp; - ++bp->refcount; - break; - default: - bp = new numeric(i); - bp->setflag(status_flags::dynallocated); - ++bp->refcount; - GINAC_ASSERT((bp->flags) & status_flags::dynallocated); - GINAC_ASSERT(bp->refcount=1); - } -} - + switch (i) { // some tiny efficiency-hack + case -2: + bp = _ex_2().bp; + ++bp->refcount; + break; + case -1: + bp = _ex_1().bp; + ++bp->refcount; + break; + case 0: + bp = _ex0().bp; + ++bp->refcount; + break; + case 1: + bp = _ex1().bp; + ++bp->refcount; + break; + case 2: + bp = _ex2().bp; + ++bp->refcount; + break; + default: + bp = new numeric(i); + bp->setflag(status_flags::dynallocated); + ++bp->refcount; + GINAC_ASSERT((bp->flags) & status_flags::dynallocated); + GINAC_ASSERT(bp->refcount=1); + } +} + void ex::construct_from_double(double d) { - bp = new numeric(d); - bp->setflag(status_flags::dynallocated); - ++bp->refcount; - GINAC_ASSERT((bp->flags) & status_flags::dynallocated); - GINAC_ASSERT(bp->refcount=1); + bp = new numeric(d); + bp->setflag(status_flags::dynallocated); + ++bp->refcount; + GINAC_ASSERT((bp->flags) & status_flags::dynallocated); + GINAC_ASSERT(bp->refcount=1); } void ex::construct_from_string_and_lst(const std::string &s, const ex &l) { - set_lexer_string(s); - set_lexer_symbols(l); - ginac_yyrestart(NULL); - if (ginac_yyparse()) - throw (std::runtime_error(get_parser_error())); - else { - bp = parsed_ex.bp; - GINAC_ASSERT(bp!=0); - GINAC_ASSERT((bp->flags) & status_flags::dynallocated); - ++bp->refcount; - } -} - + set_lexer_string(s); + set_lexer_symbols(l); + ginac_yyrestart(NULL); + if (ginac_yyparse()) + throw (std::runtime_error(get_parser_error())); + else { + bp = parsed_ex.bp; + GINAC_ASSERT(bp!=0); + GINAC_ASSERT((bp->flags) & status_flags::dynallocated); + ++bp->refcount; + } +} + ////////// // static member variables ////////// diff --git a/ginac/ex.h b/ginac/ex.h index 216a4646..87105a12 100644 --- a/ginac/ex.h +++ b/ginac/ex.h @@ -49,300 +49,300 @@ extern const ex & _ex0(void); // single ex(numeric(0)) * provide methods for manipulation of these objects. */ class ex { - friend class basic; + friend class basic; // member functions - // default constructor, destructor, copy constructor assignment operator and helpers + // default constructor, destructor, copy constructor assignment operator and helpers public: - ex() + 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; + : 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(); + update_last_created_or_assigned_bp(); #endif // def OBSCURE_CINT_HACK - } + } #else ; #endif // def INLINE_EX_CONSTRUCTORS - ~ex() + ~ex() #ifdef INLINE_EX_CONSTRUCTORS - { - GINAC_ASSERT(bp!=0); - GINAC_ASSERT(bp->flags & status_flags::dynallocated); - if (--bp->refcount == 0) { - delete bp; - } - } + { + 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) + + ex(const ex & other) #ifdef INLINE_EX_CONSTRUCTORS - : bp(other.bp) - { - GINAC_ASSERT(bp!=0); - GINAC_ASSERT((bp->flags) & status_flags::dynallocated); - ++bp->refcount; + : 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(); + update_last_created_or_assigned_bp(); #endif // def OBSCURE_CINT_HACK - } + } #else ; #endif // def INLINE_EX_CONSTRUCTORS - - const ex & operator=(const ex & other) + + 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; + { + 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(); + update_last_created_or_assigned_bp(); #endif // def OBSCURE_CINT_HACK - return *this; - } + return *this; + } #else ; #endif // def INLINE_EX_CONSTRUCTORS - // other constructors + // other constructors public: - ex(const basic & other) + ex(const basic & other) #ifdef INLINE_EX_CONSTRUCTORS - { - construct_from_basic(other); + { + construct_from_basic(other); #ifdef OBSCURE_CINT_HACK - update_last_created_or_assigned_bp(); + update_last_created_or_assigned_bp(); #endif // def OBSCURE_CINT_HACK - } + } #else ; #endif // def INLINE_EX_CONSTRUCTORS - - ex(int i) + + ex(int i) #ifdef INLINE_EX_CONSTRUCTORS - { - construct_from_int(i); + { + construct_from_int(i); #ifdef OBSCURE_CINT_HACK - update_last_created_or_assigned_bp(); + update_last_created_or_assigned_bp(); #endif // def OBSCURE_CINT_HACK - } + } #else ; #endif // def INLINE_EX_CONSTRUCTORS - ex(unsigned int i) + ex(unsigned int i) #ifdef INLINE_EX_CONSTRUCTORS - { - construct_from_uint(i); + { + construct_from_uint(i); #ifdef OBSCURE_CINT_HACK - update_last_created_or_assigned_bp(); + update_last_created_or_assigned_bp(); #endif // def OBSCURE_CINT_HACK - } + } #else ; #endif // def INLINE_EX_CONSTRUCTORS - - ex(long i) + + ex(long i) #ifdef INLINE_EX_CONSTRUCTORS - { - construct_from_long(i); + { + construct_from_long(i); #ifdef OBSCURE_CINT_HACK - update_last_created_or_assigned_bp(); + update_last_created_or_assigned_bp(); #endif // def OBSCURE_CINT_HACK - } + } #else ; #endif // def INLINE_EX_CONSTRUCTORS - ex(unsigned long i) + ex(unsigned long i) #ifdef INLINE_EX_CONSTRUCTORS - { - construct_from_ulong(i); + { + construct_from_ulong(i); #ifdef OBSCURE_CINT_HACK - update_last_created_or_assigned_bp(); + update_last_created_or_assigned_bp(); #endif // def OBSCURE_CINT_HACK - } + } #else ; #endif // def INLINE_EX_CONSTRUCTORS - - ex(double const d) + + ex(double const d) #ifdef INLINE_EX_CONSTRUCTORS - { - construct_from_double(d); + { + construct_from_double(d); #ifdef OBSCURE_CINT_HACK - update_last_created_or_assigned_bp(); + update_last_created_or_assigned_bp(); #endif // def OBSCURE_CINT_HACK - } + } #else ; #endif // def INLINE_EX_CONSTRUCTORS - /** 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) + /** 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); + { + construct_from_string_and_lst(s, l); #ifdef OBSCURE_CINT_HACK - update_last_created_or_assigned_bp(); + update_last_created_or_assigned_bp(); #endif // def OBSCURE_CINT_HACK - } + } #else ; #endif // def INLINE_EX_CONSTRUCTORS - - // functions overriding virtual functions from bases classes - // none - - // new virtual functions which can be overridden by derived classes - // none + + // functions overriding virtual functions from bases classes + // none + + // new virtual functions which can be overridden by derived classes + // none - // non-virtual functions in this class + // non-virtual functions in this class public: - void swap(ex & other); - void printraw(std::ostream & os) const; - void printtree(std::ostream & os, unsigned indent=0) const; - void print(std::ostream & os, unsigned upper_precedence=0) const; - void printcsrc(std::ostream & os, unsigned type, const char *var_name) const; - void dbgprint(void) const; - void dbgprinttree(void) const; - bool info(unsigned inf) const; - unsigned nops() const; - ex expand(unsigned options=0) const; - bool has(const ex & other) const; - int degree(const symbol & s) const; - int ldegree(const symbol & s) const; - ex coeff(const symbol & s, int n=1) const; - ex lcoeff(const symbol & s) const { return coeff(s, degree(s)); } - ex tcoeff(const symbol & s) const { return coeff(s, ldegree(s)); } - ex numer(void) const; - ex denom(void) const; - ex unit(const symbol &x) const; - ex content(const symbol &x) const; - numeric integer_content(void) const; - ex primpart(const symbol &x) const; - ex primpart(const symbol &x, const ex &cont) const; - ex normal(int level = 0) const; - ex to_rational(lst &repl_lst) const; - ex smod(const numeric &xi) const; - numeric max_coefficient(void) const; - ex collect(const symbol & s) const; - ex eval(int level = 0) const; - ex evalf(int level = 0) const; - ex diff(const symbol & s, unsigned nth = 1) const; - ex series(const ex & r, int order, unsigned options = 0) const; - ex subs(const lst & ls, const lst & lr) const; - ex subs(const ex & e) const; - exvector get_indices(void) const; - ex simplify_ncmul(const exvector & v) const; - ex operator[](const ex & index) const; - ex operator[](int i) const; - ex op(int i) const; - ex & let_op(int i); - ex lhs(void) const; - ex rhs(void) const; - int compare(const ex & other) const + void swap(ex & other); + void printraw(std::ostream & os) const; + void printtree(std::ostream & os, unsigned indent=0) const; + void print(std::ostream & os, unsigned upper_precedence=0) const; + void printcsrc(std::ostream & os, unsigned type, const char *var_name) const; + void dbgprint(void) const; + void dbgprinttree(void) const; + bool info(unsigned inf) const; + unsigned nops() const; + ex expand(unsigned options=0) const; + bool has(const ex & other) const; + int degree(const symbol & s) const; + int ldegree(const symbol & s) const; + ex coeff(const symbol & s, int n=1) const; + ex lcoeff(const symbol & s) const { return coeff(s, degree(s)); } + ex tcoeff(const symbol & s) const { return coeff(s, ldegree(s)); } + ex numer(void) const; + ex denom(void) const; + ex unit(const symbol &x) const; + ex content(const symbol &x) const; + numeric integer_content(void) const; + ex primpart(const symbol &x) const; + ex primpart(const symbol &x, const ex &cont) const; + ex normal(int level = 0) const; + ex to_rational(lst &repl_lst) const; + ex smod(const numeric &xi) const; + numeric max_coefficient(void) const; + ex collect(const symbol & s) const; + ex eval(int level = 0) const; + ex evalf(int level = 0) const; + ex diff(const symbol & s, unsigned nth = 1) const; + ex series(const ex & r, int order, unsigned options = 0) const; + ex subs(const lst & ls, const lst & lr) const; + ex subs(const ex & e) const; + exvector get_indices(void) const; + ex simplify_ncmul(const exvector & v) const; + ex operator[](const ex & index) const; + ex operator[](int i) const; + ex op(int i) const; + 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); - } + { + 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 + 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); - } + { + 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;}; - - 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; + bool is_zero(void) const {return compare(_ex0())==0;}; + + 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; private: - void construct_from_basic(const basic & other); - void construct_from_int(int i); - void construct_from_uint(unsigned int i); - void construct_from_long(long i); - void construct_from_ulong(unsigned long i); - void construct_from_double(double d); - void construct_from_string_and_lst(const std::string &s, const ex &l); - void makewriteable(); + void construct_from_basic(const basic & other); + void construct_from_int(int i); + void construct_from_uint(unsigned int i); + void construct_from_long(long i); + void construct_from_ulong(unsigned long i); + void construct_from_double(double d); + void construct_from_string_and_lst(const std::string &s, const ex &l); + void makewriteable(); #ifdef OBSCURE_CINT_HACK public: - static bool last_created_or_assigned_bp_can_be_converted_to_ex(void) - { - if (last_created_or_assigned_bp==0) return false; - if ((last_created_or_assigned_bp->flags & - status_flags::dynallocated)==0) return false; - if ((last_created_or_assigned_bp->flags & - status_flags::evaluated)==0) return false; - return true; - } + static bool last_created_or_assigned_bp_can_be_converted_to_ex(void) + { + if (last_created_or_assigned_bp==0) return false; + if ((last_created_or_assigned_bp->flags & + status_flags::dynallocated)==0) return false; + if ((last_created_or_assigned_bp->flags & + status_flags::evaluated)==0) return false; + return true; + } protected: - void update_last_created_or_assigned_bp(void) - { - if (last_created_or_assigned_bp!=0) { - if (--last_created_or_assigned_bp->refcount == 0) { - delete last_created_or_assigned_bp; - } - } - last_created_or_assigned_bp=bp; - ++last_created_or_assigned_bp->refcount; - last_created_or_assigned_exp=(long)(void *)(this); - } + void update_last_created_or_assigned_bp(void) + { + if (last_created_or_assigned_bp!=0) { + if (--last_created_or_assigned_bp->refcount == 0) { + delete last_created_or_assigned_bp; + } + } + last_created_or_assigned_bp=bp; + ++last_created_or_assigned_bp->refcount; + last_created_or_assigned_exp=(long)(void *)(this); + } #endif // def OBSCURE_CINT_HACK // member variables public: - basic *bp; + basic *bp; #ifdef OBSCURE_CINT_HACK - static basic * last_created_or_assigned_bp; - static basic * dummy_bp; - static long last_created_or_assigned_exp; + static basic * last_created_or_assigned_bp; + static basic * dummy_bp; + static long last_created_or_assigned_exp; #endif // def OBSCURE_CINT_HACK }; diff --git a/ginac/expair.h b/ginac/expair.h index 448e635b..2ec2848d 100644 --- a/ginac/expair.h +++ b/ginac/expair.h @@ -36,167 +36,167 @@ namespace GiNaC { class expair { public: - expair() {} - ~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; - } - return *this; - } - 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))); - } + expair() {} + ~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; + } + return *this; + } + 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))); + } - bool is_equal(const expair & other) const - { - return (rest.is_equal(other.rest) && coeff.is_equal(other.coeff)); - } - bool is_less(const expair & other) const - { - return (rest.compare(other.rest)<0) || - (!(other.rest.compare(rest)<0) && (coeff.compare(other.coeff)<0)); - } - 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_equal(const expair & other) const + { + return (rest.is_equal(other.rest) && coeff.is_equal(other.coeff)); + } + bool is_less(const expair & other) const + { + return (rest.compare(other.rest)<0) || + (!(other.rest.compare(rest)<0) && (coeff.compare(other.coeff)<0)); + } + 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 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; - } + 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 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; + } - void printraw(std::ostream & os) const - { - os << "expair("; - rest.printraw(os); - os << ","; - coeff.printraw(os); - os << ")"; - } + void printraw(std::ostream & os) const + { + os << "expair("; + rest.printraw(os); + os << ","; + coeff.printraw(os); + os << ")"; + } - ex rest; - ex coeff; + ex rest; + ex coeff; }; class expair_is_less { public: - bool operator()(const expair & lh, const expair & rh) const - { - return lh.is_less(rh); - } + bool operator()(const expair & lh, const expair & rh) const + { + return lh.is_less(rh); + } }; class expair_is_less_old { public: - bool operator()(const expair & lh, const expair & rh) const - { - return lh.is_less_old(rh); - } + bool operator()(const expair & lh, const expair & rh) const + { + return lh.is_less_old(rh); + } }; #ifndef NO_NAMESPACE_GINAC diff --git a/ginac/expairseq.cpp b/ginac/expairseq.cpp index 4be6cdd6..798d1bb9 100644 --- a/ginac/expairseq.cpp +++ b/ginac/expairseq.cpp @@ -48,10 +48,10 @@ GINAC_IMPLEMENT_REGISTERED_CLASS(expairseq, basic) class epp_is_less { public: - bool operator()(const epp & lh, const epp & rh) const - { - return (*lh).is_less(*rh); - } + bool operator()(const epp & lh, const epp & rh) const + { + return (*lh).is_less(*rh); + } }; ////////// @@ -62,44 +62,44 @@ public: expairseq::expairseq(const expairseq & other) { - debugmsg("expairseq copy constructor",LOGLEVEL_CONSTRUCT); - copy(other); + debugmsg("expairseq copy constructor",LOGLEVEL_CONSTRUCT); + copy(other); } const expairseq & expairseq::operator=(const expairseq & other) { - debugmsg("expairseq operator=",LOGLEVEL_ASSIGNMENT); - if (this != &other) { - destroy(1); - copy(other); - } - return *this; + debugmsg("expairseq operator=",LOGLEVEL_ASSIGNMENT); + if (this != &other) { + destroy(1); + copy(other); + } + return *this; } // protected void expairseq::copy(const expairseq & other) { - inherited::copy(other); - seq=other.seq; - overall_coeff=other.overall_coeff; + inherited::copy(other); + seq=other.seq; + overall_coeff=other.overall_coeff; #ifdef EXPAIRSEQ_USE_HASHTAB - // copy hashtab - hashtabsize=other.hashtabsize; - if (hashtabsize!=0) { - hashmask=other.hashmask; - hashtab.resize(hashtabsize); - epvector::const_iterator osb=other.seq.begin(); - for (unsigned i=0; isetflag(status_flags::dynallocated); + return (new expairseq(n, sym_lst))->setflag(status_flags::dynallocated); } /** Archive the object. */ void expairseq::archive(archive_node &n) const { - inherited::archive(n); - epvector::const_iterator i = seq.begin(), iend = seq.end(); - while (i != iend) { - n.add_ex("rest", i->rest); - n.add_ex("coeff", i->coeff); - i++; - } - n.add_ex("overall_coeff", overall_coeff); + inherited::archive(n); + epvector::const_iterator i = seq.begin(), iend = seq.end(); + while (i != iend) { + n.add_ex("rest", i->rest); + n.add_ex("coeff", i->coeff); + i++; + } + n.add_ex("overall_coeff", overall_coeff); } ////////// @@ -205,170 +205,170 @@ void expairseq::archive(archive_node &n) const basic * expairseq::duplicate() const { - debugmsg("expairseq duplicate",LOGLEVEL_DUPLICATE); - return new expairseq(*this); + debugmsg("expairseq duplicate",LOGLEVEL_DUPLICATE); + return new expairseq(*this); } void expairseq::print(std::ostream & os, unsigned upper_precedence) const { - debugmsg("expairseq print",LOGLEVEL_PRINT); - os << "[["; - printseq(os,',',precedence,upper_precedence); - os << "]]"; + debugmsg("expairseq print",LOGLEVEL_PRINT); + os << "[["; + printseq(os,',',precedence,upper_precedence); + os << "]]"; } void expairseq::printraw(std::ostream & os) const { - debugmsg("expairseq printraw",LOGLEVEL_PRINT); + debugmsg("expairseq printraw",LOGLEVEL_PRINT); - os << "expairseq("; - for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { - os << "("; - (*cit).rest.printraw(os); - os << ","; - (*cit).coeff.printraw(os); - os << "),"; - } - os << ")"; + os << "expairseq("; + for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { + os << "("; + (*cit).rest.printraw(os); + os << ","; + (*cit).coeff.printraw(os); + os << "),"; + } + os << ")"; } void expairseq::printtree(std::ostream & os, unsigned indent) const { - debugmsg("expairseq printtree",LOGLEVEL_PRINT); - - os << std::string(indent,' ') << "type=" << typeid(*this).name() - << ", hash=" << hashvalue - << " (0x" << std::hex << hashvalue << std::dec << ")" - << ", flags=" << flags - << ", nops=" << nops() << std::endl; - 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) { - os << *it-seq.begin() << " "; - this_bin_fill++; - } - os << std::endl; - 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); - cum_prob += prob; - os << std::string(indent+delta_indent,' ') << "bins with " << k << " entries: " - << int(1000.0*count[k]/hashtabsize)/10.0 << "% (expected: " - << int(prob*1000)/10.0 << ")" << std::endl; - } - os << std::string(indent+delta_indent,' ') << "bins with more entries: " - << int(1000.0*count[MAXCOUNT]/hashtabsize)/10.0 << "% (expected: " - << int((1-cum_prob)*1000)/10.0 << ")" << std::endl; - - os << std::string(indent+delta_indent,' ') << "variance: " - << 1.0/hashtabsize*cum_fill_sq-(1.0/hashtabsize*cum_fill)*(1.0/hashtabsize*cum_fill) - << std::endl; - os << std::string(indent+delta_indent,' ') << "average fill: " - << (1.0*cum_fill)/hashtabsize - << " (should be equal to " << (1.0*seq.size())/hashtabsize << ")" << std::endl; + unsigned count[MAXCOUNT+1]; + for (int 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) { + os << *it-seq.begin() << " "; + this_bin_fill++; + } + os << std::endl; + 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); + cum_prob += prob; + os << std::string(indent+delta_indent,' ') << "bins with " << k << " entries: " + << int(1000.0*count[k]/hashtabsize)/10.0 << "% (expected: " + << int(prob*1000)/10.0 << ")" << std::endl; + } + os << std::string(indent+delta_indent,' ') << "bins with more entries: " + << int(1000.0*count[MAXCOUNT]/hashtabsize)/10.0 << "% (expected: " + << int((1-cum_prob)*1000)/10.0 << ")" << std::endl; + + os << std::string(indent+delta_indent,' ') << "variance: " + << 1.0/hashtabsize*cum_fill_sq-(1.0/hashtabsize*cum_fill)*(1.0/hashtabsize*cum_fill) + << std::endl; + 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 } bool expairseq::info(unsigned inf) const { - return inherited::info(inf); + return inherited::info(inf); } unsigned expairseq::nops() const { - if (overall_coeff.is_equal(default_overall_coeff())) { - return seq.size(); - } - return seq.size()+1; + if (overall_coeff.is_equal(default_overall_coeff())) { + return seq.size(); + } + return seq.size()+1; } ex expairseq::op(int i) const { - if (unsigned(i)hold(); - } + epvector * vp=evalchildren(level); + if (vp==0) { + return this->hold(); + } - return (new expairseq(vp,overall_coeff)) - ->setflag(status_flags::dynallocated | - status_flags::evaluated ); + return (new expairseq(vp,overall_coeff)) + ->setflag(status_flags::dynallocated | + status_flags::evaluated ); } ex expairseq::evalf(int level) const { - return thisexpairseq(evalfchildren(level),overall_coeff.evalf(level-1)); + return thisexpairseq(evalfchildren(level),overall_coeff.evalf(level-1)); } ex expairseq::normal(lst &sym_lst, lst &repl_lst, int level) const { - ex n = thisexpairseq(normalchildren(level),overall_coeff); - return n.bp->basic::normal(sym_lst,repl_lst,level); + ex n = thisexpairseq(normalchildren(level),overall_coeff); + return n.bp->basic::normal(sym_lst,repl_lst,level); } ex expairseq::subs(const lst & ls, const lst & lr) const { - epvector * vp=subschildren(ls,lr); - if (vp==0) { - return *this; - } - return thisexpairseq(vp,overall_coeff); + epvector * vp=subschildren(ls,lr); + if (vp==0) { + return *this; + } + return thisexpairseq(vp,overall_coeff); } // protected @@ -378,173 +378,173 @@ ex expairseq::subs(const lst & ls, const lst & lr) const * @see ex::diff */ ex expairseq::derivative(const symbol & s) const { - return thisexpairseq(diffchildren(s),overall_coeff); + return thisexpairseq(diffchildren(s),overall_coeff); } int expairseq::compare_same_type(const basic & other) const { - GINAC_ASSERT(is_of_type(other, expairseq)); - const expairseq & o = static_cast(const_cast(other)); + GINAC_ASSERT(is_of_type(other, expairseq)); + const expairseq & o = static_cast(const_cast(other)); - int cmpval; - - // compare number of elements - 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(); - while (it1!=eppl1.end()) { - cmpval=(*(*it1)).compare(*(*it2)); - if (cmpval!=0) return cmpval; - ++it1; - ++it2; - } - } - } - - return 0; // equal + } + + // compare number of elements in each hashtab entry + 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(); + while (it1!=eppl1.end()) { + cmpval=(*(*it1)).compare(*(*it2)); + if (cmpval!=0) return cmpval; + ++it1; + ++it2; + } + } + } + + return 0; // equal #endif // def EXPAIRSEQ_USE_HASHTAB } 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; + // compare number of elements + if (seq.size() != o.seq.size()) return false; - // compare overall_coeff - if (!overall_coeff.is_equal(o.overall_coeff)) return false; + // compare overall_coeff + if (!overall_coeff.is_equal(o.overall_coeff)) return false; #ifdef 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); - } - - GINAC_ASSERT(hashtabsize==o.hashtabsize); - - if (hashtabsize==0) { + // 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); + } + + 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(); - - while (cit1!=last1) { - if (!(*cit1).is_equal(*cit2)) return false; - ++cit1; - ++cit2; - } - - return true; + 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; + ++cit1; + ++cit2; + } + + return true; #ifdef 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(); - while (it1!=eppl1.end()) { - if (!(*(*it1)).is_equal(*(*it2))) return false; - ++it1; - ++it2; - } - } - } - - return true; + } + + 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(); + while (it1!=eppl1.end()) { + if (!(*(*it1)).is_equal(*(*it2))) return false; + ++it1; + ++it2; + } + } + } + + return true; #endif // def EXPAIRSEQ_USE_HASHTAB } unsigned expairseq::return_type(void) const { - return return_types::noncommutative_composite; + return return_types::noncommutative_composite; } 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) { + 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 + v=rotate_left_31(v); // rotation would spoil commutativity #endif // ndef EXPAIRSEQ_USE_HASHTAB - v ^= (*cit).rest.gethash(); - } + v ^= (*cit).rest.gethash(); + } - v ^= overall_coeff.gethash(); - v=v & 0x7FFFFFFFU; - - // store calculated hash value only if object is already evaluated - if (flags & status_flags::evaluated) { - setflag(status_flags::hash_calculated); - hashvalue=v; - } + v ^= overall_coeff.gethash(); + v=v & 0x7FFFFFFFU; + + // store calculated hash value only if object is already evaluated + if (flags & status_flags::evaluated) { + setflag(status_flags::hash_calculated); + hashvalue=v; + } - return v; + return v; } ex expairseq::expand(unsigned options) const { - epvector * vp = expandchildren(options); - if (vp==0) { - return *this; - } - return thisexpairseq(vp,overall_coeff); + epvector * vp = expandchildren(options); + if (vp==0) { + return *this; + } + return thisexpairseq(vp,overall_coeff); } ////////// @@ -555,1167 +555,1167 @@ ex expairseq::expand(unsigned options) const ex expairseq::thisexpairseq(const epvector & v, const ex & oc) const { - return expairseq(v,oc); + return expairseq(v,oc); } ex expairseq::thisexpairseq(epvector * vp, const ex & oc) const { - return expairseq(vp,oc); + return expairseq(vp,oc); } void expairseq::printpair(std::ostream & os, const expair & p, unsigned upper_precedence) const { - os << "[["; - p.rest.bp->print(os,precedence); - os << ","; - p.coeff.bp->print(os,precedence); - os << "]]"; + os << "[["; + p.rest.bp->print(os,precedence); + os << ","; + p.coeff.bp->print(os,precedence); + os << "]]"; } void expairseq::printseq(std::ostream & os, char delim, - unsigned this_precedence, - unsigned upper_precedence) const -{ - if (this_precedence<=upper_precedence) os << "("; - epvector::const_iterator it,it_last; - it_last=seq.end(); - --it_last; - for (it=seq.begin(); it!=it_last; ++it) { - printpair(os,*it,this_precedence); - os << delim; - } - printpair(os,*it,this_precedence); - if (!overall_coeff.is_equal(default_overall_coeff())) { - os << delim << overall_coeff; - } - if (this_precedence<=upper_precedence) os << ")"; -} - + unsigned this_precedence, + unsigned upper_precedence) const +{ + if (this_precedence<=upper_precedence) os << "("; + epvector::const_iterator it,it_last; + it_last=seq.end(); + --it_last; + for (it=seq.begin(); it!=it_last; ++it) { + printpair(os,*it,this_precedence); + os << delim; + } + printpair(os,*it,this_precedence); + 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 { - return expair(e,_ex1()); + return expair(e,_ex1()); } expair expairseq::combine_ex_with_coeff_to_pair(const ex & e, - const ex & c) const + const ex & c) const { - GINAC_ASSERT(is_ex_exactly_of_type(c,numeric)); + GINAC_ASSERT(is_ex_exactly_of_type(c,numeric)); - return expair(e,c); + return expair(e,c); } expair expairseq::combine_pair_with_coeff_to_pair(const expair & p, - const ex & c) const + const ex & c) const { - GINAC_ASSERT(is_ex_exactly_of_type(p.coeff,numeric)); - GINAC_ASSERT(is_ex_exactly_of_type(c,numeric)); - - return expair(p.rest,ex_to_numeric(p.coeff).mul_dyn(ex_to_numeric(c))); + GINAC_ASSERT(is_ex_exactly_of_type(p.coeff,numeric)); + GINAC_ASSERT(is_ex_exactly_of_type(c,numeric)); + + 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 { - return lst(p.rest,p.coeff); + return lst(p.rest,p.coeff); } bool expairseq::expair_needs_further_processing(epp it) { - return false; + return false; } ex expairseq::default_overall_coeff(void) const { - return _ex0(); + return _ex0(); } 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)); + 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) { - GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric)); - GINAC_ASSERT(is_ex_exactly_of_type(c1,numeric)); - GINAC_ASSERT(is_ex_exactly_of_type(c2,numeric)); - overall_coeff = ex_to_numeric(overall_coeff). - add_dyn(ex_to_numeric(c1).mul(ex_to_numeric(c2))); + GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric)); + GINAC_ASSERT(is_ex_exactly_of_type(c1,numeric)); + GINAC_ASSERT(is_ex_exactly_of_type(c2,numeric)); + overall_coeff = ex_to_numeric(overall_coeff). + add_dyn(ex_to_numeric(c1).mul(ex_to_numeric(c2))); } bool expairseq::can_make_flat(const expair & p) const { - return true; + return true; } - + ////////// // non-virtual functions in this class ////////// 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); + exvector v; + v.reserve(2); + v.push_back(lh); + v.push_back(rh); + construct_from_exvector(v); #ifdef EXPAIRSEQ_USE_HASHTAB - GINAC_ASSERT((hashtabsize==0)||(hashtabsize>=minhashtabsize)); - GINAC_ASSERT(hashtabsize==calc_hashtabsize(seq.size())); + GINAC_ASSERT((hashtabsize==0)||(hashtabsize>=minhashtabsize)); + GINAC_ASSERT(hashtabsize==calc_hashtabsize(seq.size())); #endif // def EXPAIRSEQ_USE_HASHTAB } void expairseq::construct_from_2_ex(const ex & lh, const ex & rh) { - if (lh.bp->tinfo()==tinfo()) { - if (rh.bp->tinfo()==tinfo()) { + if (lh.bp->tinfo()==tinfo()) { + if (rh.bp->tinfo()==tinfo()) { #ifdef 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 { + 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 - construct_from_2_expairseq(ex_to_expairseq(lh), - ex_to_expairseq(rh)); + construct_from_2_expairseq(ex_to_expairseq(lh), + ex_to_expairseq(rh)); #ifdef EXPAIRSEQ_USE_HASHTAB - } + } #endif // def EXPAIRSEQ_USE_HASHTAB - return; - } else { + return; + } else { #ifdef 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 { + 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 - construct_from_expairseq_ex(ex_to_expairseq(lh),rh); + construct_from_expairseq_ex(ex_to_expairseq(lh),rh); #ifdef EXPAIRSEQ_USE_HASHTAB - } + } #endif // def EXPAIRSEQ_USE_HASHTAB - return; - } - } else if (rh.bp->tinfo()==tinfo()) { + return; + } + } else if (rh.bp->tinfo()==tinfo()) { #ifdef 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 { + 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 - construct_from_expairseq_ex(ex_to_expairseq(rh),lh); + construct_from_expairseq_ex(ex_to_expairseq(rh),lh); #ifdef EXPAIRSEQ_USE_HASHTAB - } + } #endif // def EXPAIRSEQ_USE_HASHTAB - return; - } + return; + } #ifdef EXPAIRSEQ_USE_HASHTAB - if (calc_hashtabsize(2)!=0) { - construct_from_2_ex_via_exvector(lh,rh); - return; - } - hashtabsize=0; + if (calc_hashtabsize(2)!=0) { + construct_from_2_ex_via_exvector(lh,rh); + return; + } + hashtabsize=0; #endif // def EXPAIRSEQ_USE_HASHTAB - - if (is_ex_exactly_of_type(lh,numeric)) { - if (is_ex_exactly_of_type(rh,numeric)) { - combine_overall_coeff(lh); - combine_overall_coeff(rh); - } else { - combine_overall_coeff(lh); - seq.push_back(split_ex_to_pair(rh)); - } - } else { - if (is_ex_exactly_of_type(rh,numeric)) { - 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); - 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()) { - // no further processing is necessary, since this - // one element will usually be recombined in eval() - seq.push_back(p1); - } - } else { - seq.reserve(2); - if (cmpval<0) { - seq.push_back(p1); - seq.push_back(p2); - } else { - seq.push_back(p2); - seq.push_back(p1); - } - } - } - } + + if (is_ex_exactly_of_type(lh,numeric)) { + if (is_ex_exactly_of_type(rh,numeric)) { + combine_overall_coeff(lh); + combine_overall_coeff(rh); + } else { + combine_overall_coeff(lh); + seq.push_back(split_ex_to_pair(rh)); + } + } else { + if (is_ex_exactly_of_type(rh,numeric)) { + 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); + 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()) { + // no further processing is necessary, since this + // one element will usually be recombined in eval() + seq.push_back(p1); + } + } else { + seq.reserve(2); + if (cmpval<0) { + seq.push_back(p1); + seq.push_back(p2); + } else { + seq.push_back(p2); + seq.push_back(p1); + } + } + } + } } 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(); - - 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); - if (cmpval==0) { - // combine terms - 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)); - if (expair_needs_further_processing(seq.end()-1)) { - needs_further_processing = true; - } - } - ++first1; - ++first2; - } else if (cmpval<0) { - seq.push_back(*first1); - ++first1; - } else { - seq.push_back(*first2); - ++first2; - } - } - - while (first1!=last1) { - seq.push_back(*first1); - ++first1; - } - while (first2!=last2) { - seq.push_back(*first2); - ++first2; - } - - if (needs_further_processing) { - epvector v=seq; - seq.clear(); - construct_from_epvector(v); - } + 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(); + + 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); + if (cmpval==0) { + // combine terms + 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)); + if (expair_needs_further_processing(seq.end()-1)) { + needs_further_processing = true; + } + } + ++first1; + ++first2; + } else if (cmpval<0) { + seq.push_back(*first1); + ++first1; + } else { + seq.push_back(*first2); + ++first2; + } + } + + while (first1!=last1) { + seq.push_back(*first1); + ++first1; + } + while (first2!=last2) { + seq.push_back(*first2); + ++first2; + } + + if (needs_further_processing) { + epvector v=seq; + seq.clear(); + construct_from_epvector(v); + } } 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; - return; - } - - 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 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). - add(ex_to_numeric(p.coeff)); - if (!newcoeff.is_zero()) { - seq.push_back(expair((*first).rest,newcoeff)); - if (expair_needs_further_processing(seq.end()-1)) { - needs_further_processing = true; - } - } - ++first; - p_pushed=1; - break; - } else if (cmpval<0) { - seq.push_back(*first); - ++first; - } else { - seq.push_back(p); - p_pushed=1; - break; - } - } - - if (p_pushed) { - // while loop exited because p was pushed, now push rest of s.seq - while (first!=last) { - seq.push_back(*first); - ++first; - } - } else { - // while loop exited because s.seq was pushed, now push p - seq.push_back(p); - } - - if (needs_further_processing) { - epvector v=seq; - seq.clear(); - construct_from_epvector(v); - } + const ex & e) +{ + combine_overall_coeff(s.overall_coeff); + if (is_ex_exactly_of_type(e,numeric)) { + combine_overall_coeff(e); + 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); + + seq.reserve(s.seq.size()+1); + bool p_pushed=0; + + 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). + add(ex_to_numeric(p.coeff)); + if (!newcoeff.is_zero()) { + seq.push_back(expair((*first).rest,newcoeff)); + if (expair_needs_further_processing(seq.end()-1)) { + needs_further_processing = true; + } + } + ++first; + p_pushed=1; + break; + } else if (cmpval<0) { + seq.push_back(*first); + ++first; + } else { + seq.push_back(p); + p_pushed=1; + break; + } + } + + if (p_pushed) { + // while loop exited because p was pushed, now push rest of s.seq + while (first!=last) { + seq.push_back(*first); + ++first; + } + } else { + // while loop exited because s.seq was pushed, now push p + seq.push_back(p); + } + + if (needs_further_processing) { + epvector v=seq; + seq.clear(); + construct_from_epvector(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) - // +(...,x,*(x,c1),*(x,c2)) -> +(...,*(x,1+c1+c2)) (c1, c2 numeric()) - // (same for (+,*) -> (*,^) + // simplifications: +(a,+(b,c),d) -> +(a,b,c,d) (associativity) + // +(d,b,c,a) -> +(a,b,c,d) (canonicalization) + // +(...,x,*(x,c1),*(x,c2)) -> +(...,*(x,1+c1+c2)) (c1, c2 numeric()) + // (same for (+,*) -> (*,^) - make_flat(v); + make_flat(v); #ifdef EXPAIRSEQ_USE_HASHTAB - combine_same_terms(); + combine_same_terms(); #else - canonicalize(); - combine_same_terms_sorted_seq(); + canonicalize(); + combine_same_terms_sorted_seq(); #endif // def EXPAIRSEQ_USE_HASHTAB } 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) - // +(...,x,*(x,c1),*(x,c2)) -> +(...,*(x,1+c1+c2)) (c1, c2 numeric()) - // (same for (+,*) -> (*,^) + // simplifications: +(a,+(b,c),d) -> +(a,b,c,d) (associativity) + // +(d,b,c,a) -> +(a,b,c,d) (canonicalization) + // +(...,x,*(x,c1),*(x,c2)) -> +(...,*(x,1+c1+c2)) (c1, c2 numeric()) + // (same for (+,*) -> (*,^) - make_flat(v); + make_flat(v); #ifdef EXPAIRSEQ_USE_HASHTAB - combine_same_terms(); + combine_same_terms(); #else - canonicalize(); - combine_same_terms_sorted_seq(); + canonicalize(); + combine_same_terms_sorted_seq(); #endif // def EXPAIRSEQ_USE_HASHTAB } void expairseq::make_flat(const exvector & v) { - exvector::const_iterator cit, citend = v.end(); - - // 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()) { - nexpairseqs++; - 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); - combine_overall_coeff(subseqref.overall_coeff); - 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)) { - combine_overall_coeff(*cit); - } 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; - */ + exvector::const_iterator cit, citend = v.end(); + + // 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()) { + nexpairseqs++; + 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); + combine_overall_coeff(subseqref.overall_coeff); + 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)) { + combine_overall_coeff(*cit); + } 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; + */ } void expairseq::make_flat(const epvector & v) { - epvector::const_iterator cit, citend = v.end(); - - // 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->rest.bp->tinfo()==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); - combine_overall_coeff(ex_to_numeric(subseqref.overall_coeff), - ex_to_numeric((*cit).coeff)); - 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)))); - //seq.push_back(combine_pair_with_coeff_to_pair(*cit_s, - // (*cit).coeff)); - ++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 { - seq.push_back(*cit); - } - } - ++cit; - } + epvector::const_iterator cit, citend = v.end(); + + // 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->rest.bp->tinfo()==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); + combine_overall_coeff(ex_to_numeric(subseqref.overall_coeff), + ex_to_numeric((*cit).coeff)); + 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)))); + //seq.push_back(combine_pair_with_coeff_to_pair(*cit_s, + // (*cit).coeff)); + ++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 { + seq.push_back(*cit); + } + } + ++cit; + } } epvector * expairseq::bubblesort(epvector::iterator itbegin, epvector::iterator itend) { - unsigned n=itend-itbegin; + unsigned n=itend-itbegin; - epvector * sp=new epvector; - sp->reserve(n); + 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::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; -} - + 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; +} + 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(); - */ + // 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(); + */ } void expairseq::combine_same_terms_sorted_seq(void) { - 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; - 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)) { - needs_further_processing = true; - } - must_copy=true; - } else { - if (!ex_to_numeric((*itin1).coeff).is_zero()) { - if (must_copy) { - *itout=*itin1; - } - ++itout; - } - itin1=itin2; - } - ++itin2; - } - if (!ex_to_numeric((*itin1).coeff).is_zero()) { - if (must_copy) { - *itout=*itin1; - } - ++itout; - } - 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; - seq.clear(); - construct_from_epvector(v); - } + 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; + 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)) { + needs_further_processing = true; + } + must_copy=true; + } else { + if (!ex_to_numeric((*itin1).coeff).is_zero()) { + if (must_copy) { + *itout=*itin1; + } + ++itout; + } + itin1=itin2; + } + ++itin2; + } + if (!ex_to_numeric((*itin1).coeff).is_zero()) { + if (must_copy) { + *itout=*itin1; + } + ++itout; + } + 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; + seq.clear(); + construct_from_epvector(v); + } } #ifdef 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=0); - GINAC_ASSERT((hashindex=0); + GINAC_ASSERT((hashindex & touched, - unsigned & number_of_zeroes) -{ - epp current=seq.begin(); - - while (current!=first_numeric) { - if (is_ex_exactly_of_type((*current).rest,numeric)) { - --first_numeric; - iter_swap(current,first_numeric); - } else { - // calculate hashindex - 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(); - while (epplit!=eppl.end()) { - if ((*current).rest.is_equal((*(*epplit)).rest)) break; - ++epplit; - } - if (epplit==eppl.end()) { - // no matching expair found, append this to end of list - sorted_insert(eppl,current); - ++current; - } else { - // epplit points to a matching expair, combine it with current - (*(*epplit)).coeff=ex_to_numeric((*(*epplit)).coeff). - add_dyn(ex_to_numeric((*current).coeff)); - - // move obsolete current expair to end by swapping with last_non_zero element - // if this was a numeric, it is swapped with the expair before first_numeric - iter_swap(current,last_non_zero); - --first_numeric; - if (first_numeric!=last_non_zero) iter_swap(first_numeric,current); - --last_non_zero; - ++number_of_zeroes; - // test if combined term has coeff 0 and can be removed is done later - touched[(*epplit)-seq.begin()]=true; - } - } - } + epvector::iterator & last_non_zero, + vector & touched, + unsigned & number_of_zeroes) +{ + epp current=seq.begin(); + + while (current!=first_numeric) { + if (is_ex_exactly_of_type((*current).rest,numeric)) { + --first_numeric; + iter_swap(current,first_numeric); + } else { + // calculate hashindex + 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(); + while (epplit!=eppl.end()) { + if ((*current).rest.is_equal((*(*epplit)).rest)) break; + ++epplit; + } + if (epplit==eppl.end()) { + // no matching expair found, append this to end of list + sorted_insert(eppl,current); + ++current; + } else { + // epplit points to a matching expair, combine it with current + (*(*epplit)).coeff=ex_to_numeric((*(*epplit)).coeff). + add_dyn(ex_to_numeric((*current).coeff)); + + // move obsolete current expair to end by swapping with last_non_zero element + // if this was a numeric, it is swapped with the expair before first_numeric + iter_swap(current,last_non_zero); + --first_numeric; + if (first_numeric!=last_non_zero) iter_swap(first_numeric,current); + --last_non_zero; + ++number_of_zeroes; + // test if combined term has coeff 0 and can be removed is done later + touched[(*epplit)-seq.begin()]=true; + } + } + } } 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; - while (current!=first_numeric) { - if (!touched[i]) { - ++current; - ++i; - } else if (!ex_to_numeric((*current).coeff).is_equal(_num0())) { - ++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); - --first_numeric; - bool numeric_swapped=first_numeric!=last_non_zero; - 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; - } - - --last_non_zero; - ++number_of_zeroes; - - if (first_numeric!=current) { - - // 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()]; - } - } else { - --first_numeric; - --last_non_zero; - ++number_of_zeroes; - } - } - } - GINAC_ASSERT(i==current-seq.begin()); + 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; + while (current!=first_numeric) { + if (!touched[i]) { + ++current; + ++i; + } else if (!ex_to_numeric((*current).coeff).is_equal(_num0())) { + ++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); + --first_numeric; + bool numeric_swapped=first_numeric!=last_non_zero; + 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; + } + + --last_non_zero; + ++number_of_zeroes; + + if (first_numeric!=current) { + + // 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()]; + } + } else { + --first_numeric; + --last_non_zero; + ++number_of_zeroes; + } + } + } + GINAC_ASSERT(i==current-seq.begin()); } bool expairseq::has_coeff_0(void) const { - for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { - if ((*cit).coeff.is_equal(_ex0())) { - return true; - } - } - return false; + for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { + if ((*cit).coeff.is_equal(_ex0())) { + return true; + } + } + return false; } void expairseq::add_numerics_to_hashtab(epvector::iterator first_numeric, - epvector::const_iterator last_non_zero) + epvector::const_iterator last_non_zero) { - if (first_numeric==seq.end()) return; // no numerics + if (first_numeric==seq.end()) return; // no numerics - epvector::iterator current=first_numeric; - epvector::const_iterator last=last_non_zero+1; - while (current!=last) { - sorted_insert(hashtab[hashmask],current); - ++current; - } + epvector::iterator current=first_numeric; + epvector::const_iterator last=last_non_zero+1; + while (current!=last) { + sorted_insert(hashtab[hashmask],current); + ++current; + } } void expairseq::combine_same_terms(void) { - // combine same terms, drop term with coeff 0, move numerics to end - - // 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; - - vector touched; - touched.reserve(seq.size()); - for (unsigned i=0; i touched; + touched.reserve(seq.size()); + for (unsigned i=0; i0) return 1; // not canoncalized + if (hashtabsize>0) return 1; // not canoncalized #endif // def EXPAIRSEQ_USE_HASHTAB - - epvector::const_iterator it = seq.begin(); - epvector::const_iterator it_last = it; - for (++it; it!=seq.end(); it_last=it, ++it) { - if (!((*it_last).is_less(*it)||(*it_last).is_equal(*it))) { - if (!is_ex_exactly_of_type((*it_last).rest,numeric)|| - !is_ex_exactly_of_type((*it).rest,numeric)) { - // double test makes it easier to set a breakpoint... - if (!is_ex_exactly_of_type((*it_last).rest,numeric)|| - !is_ex_exactly_of_type((*it).rest,numeric)) { - printpair(cout,*it_last,0); - cout << ">"; - printpair(cout,*it,0); - cout << "\n"; - cout << "pair1:" << std::endl; - (*it_last).rest.printtree(cout); - (*it_last).coeff.printtree(cout); - cout << "pair2:" << std::endl; - (*it).rest.printtree(cout); - (*it).coeff.printtree(cout); - return 0; - } - } - } - } - return 1; + + epvector::const_iterator it = seq.begin(); + epvector::const_iterator it_last = it; + for (++it; it!=seq.end(); it_last=it, ++it) { + if (!((*it_last).is_less(*it)||(*it_last).is_equal(*it))) { + if (!is_ex_exactly_of_type((*it_last).rest,numeric)|| + !is_ex_exactly_of_type((*it).rest,numeric)) { + // double test makes it easier to set a breakpoint... + if (!is_ex_exactly_of_type((*it_last).rest,numeric)|| + !is_ex_exactly_of_type((*it).rest,numeric)) { + printpair(cout,*it_last,0); + cout << ">"; + printpair(cout,*it,0); + cout << "\n"; + cout << "pair1:" << std::endl; + (*it_last).rest.printtree(cout); + (*it_last).coeff.printtree(cout); + cout << "pair2:" << std::endl; + (*it).rest.printtree(cout); + (*it).coeff.printtree(cout); + return 0; + } + } + } + } + return 1; } 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); - if (!are_ex_trivially_equal((*cit).rest,expanded_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) { - s->push_back(*cit2); - ++cit2; - } - // copy first changed element - s->push_back(combine_ex_with_coeff_to_pair(expanded_ex, - (*cit2).coeff)); - ++cit2; - // copy rest - while (cit2!=last) { - s->push_back(combine_ex_with_coeff_to_pair((*cit2).rest.expand(options), - (*cit2).coeff)); - ++cit2; - } - return s; - } - ++cit; - } - - return 0; // nothing has changed + epvector::const_iterator last = seq.end(); + epvector::const_iterator cit = seq.begin(); + while (cit!=last) { + 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; + s->reserve(seq.size()); + + // copy parts of seq which are known not to have changed + epvector::const_iterator cit2 = seq.begin(); + while (cit2!=cit) { + s->push_back(*cit2); + ++cit2; + } + // copy first changed element + s->push_back(combine_ex_with_coeff_to_pair(expanded_ex, + (*cit2).coeff)); + ++cit2; + // copy rest + while (cit2!=last) { + s->push_back(combine_ex_with_coeff_to_pair((*cit2).rest.expand(options), + (*cit2).coeff)); + ++cit2; + } + return s; + } + ++cit; + } + + return 0; // nothing has 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) { - return 0; - } - 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); - 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) { - s->push_back(*cit2); - ++cit2; - } - // copy first changed element - s->push_back(combine_ex_with_coeff_to_pair(evaled_ex, - (*cit2).coeff)); - ++cit2; - // copy rest - while (cit2!=last) { - s->push_back(combine_ex_with_coeff_to_pair((*cit2).rest.eval(level), - (*cit2).coeff)); - ++cit2; - } - return s; - } - ++cit; - } - - return 0; // nothing has changed + // 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) { + return 0; + } + 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); + 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) { + s->push_back(*cit2); + ++cit2; + } + // copy first changed element + s->push_back(combine_ex_with_coeff_to_pair(evaled_ex, + (*cit2).coeff)); + ++cit2; + // copy rest + while (cit2!=last) { + s->push_back(combine_ex_with_coeff_to_pair((*cit2).rest.eval(level), + (*cit2).coeff)); + ++cit2; + } + return s; + } + ++cit; + } + + return 0; // nothing has changed } epvector expairseq::evalfchildren(int level) const { - if (level==1) - return seq; + if (level==1) + return seq; - 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.evalf(level), - (*it).coeff.evalf(level))); - } - return s; + 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.evalf(level), + (*it).coeff.evalf(level))); + } + return s; } epvector expairseq::normalchildren(int level) const { - if (level==1) - return seq; - - if (level == -max_recursion_level) - throw(std::runtime_error("max recursion level reached")); + if (level==1) + return seq; + + if (level == -max_recursion_level) + throw(std::runtime_error("max recursion level reached")); - epvector s; - s.reserve(seq.size()); + 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), - (*it).coeff)); - } - return s; + --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), + (*it).coeff)); + } + return s; } epvector expairseq::diffchildren(const symbol & y) const { - epvector s; - s.reserve(seq.size()); + 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)); - } - return s; + 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)); + } + return s; } 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(); - while (cit!=last) { - 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 - 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) { - s->push_back(*cit2); - ++cit2; - } - // copy first changed element - s->push_back(combine_ex_with_coeff_to_pair(subsed_ex, - (*cit2).coeff)); - ++cit2; - // copy rest - while (cit2!=last) { - s->push_back(combine_ex_with_coeff_to_pair((*cit2).rest.subs(ls,lr), - (*cit2).coeff)); - ++cit2; - } - return s; - } - ++cit; - } - - return 0; // nothing has changed + // 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(); + while (cit!=last) { + 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 + 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) { + s->push_back(*cit2); + ++cit2; + } + // copy first changed element + s->push_back(combine_ex_with_coeff_to_pair(subsed_ex, + (*cit2).coeff)); + ++cit2; + // copy rest + while (cit2!=last) { + s->push_back(combine_ex_with_coeff_to_pair((*cit2).rest.subs(ls,lr), + (*cit2).coeff)); + ++cit2; + } + return s; + } + ++cit; + } + + return 0; // nothing has changed } ////////// diff --git a/ginac/expairseq.h b/ginac/expairseq.h index 7f467dc2..e4263d51 100644 --- a/ginac/expairseq.h +++ b/ginac/expairseq.h @@ -42,8 +42,8 @@ typedef epvector::iterator epviter; inline void iter_swap(epvector::iterator it1, epvector::iterator it2) { - (*it1).rest.swap((*it2).rest); - (*it1).coeff.swap((*it2).coeff); + (*it1).rest.swap((*it2).rest); + (*it1).coeff.swap((*it2).coeff); } typedef epvector::iterator epp; @@ -57,140 +57,140 @@ typedef std::vector epplistvector; * the same way.) */ class expairseq : public basic { - GINAC_DECLARE_REGISTERED_CLASS(expairseq, basic) + GINAC_DECLARE_REGISTERED_CLASS(expairseq, basic) // member functions - // default constructor, destructor, copy constructor assignment operator and helpers + // default constructor, destructor, copy constructor assignment operator and helpers public: - expairseq() : basic(TINFO_expairseq) + expairseq() : basic(TINFO_expairseq) #ifdef EXPAIRSEQ_USE_HASHTAB - , hashtabsize(0) + , hashtabsize(0) #endif // def EXPAIRSEQ_USE_HASHTAB - { - } - ~expairseq() - { - destroy(0); - } - expairseq(const expairseq & other); - const expairseq & operator=(const expairseq & other); + { + } + ~expairseq() + { + destroy(0); + } + 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); - }; + void copy(const expairseq & other); + void destroy(bool call_parent) + { + if (call_parent) basic::destroy(call_parent); + }; - // other constructors + // other constructors 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 + 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 + // functions overriding virtual functions from bases classes public: - basic * duplicate() 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; - bool info(unsigned inf) const; - unsigned nops() const; - ex op(int i) const; - ex & let_op(int i); - 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 to_rational(lst &repl_lst) const; - ex subs(const lst & ls, const lst & lr) const; + basic * duplicate() 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; + bool info(unsigned inf) const; + unsigned nops() const; + ex op(int i) const; + ex & let_op(int i); + 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 to_rational(lst &repl_lst) const; + ex subs(const lst & ls, const lst & lr) const; protected: - ex derivative(const symbol & s) const; - int compare_same_type(const basic & other) const; - bool is_equal_same_type(const basic & other) const; - 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 + ex derivative(const symbol & s) const; + int compare_same_type(const basic & other) const; + bool is_equal_same_type(const basic & other) const; + 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; - virtual ex thisexpairseq(epvector * vp, const ex & oc) const; - virtual void printseq(std::ostream & os, char delim, - unsigned this_precedence, - unsigned upper_precedence) const; - virtual void printpair(std::ostream & os, const expair & p, - unsigned upper_precedence) const; - virtual expair split_ex_to_pair(const ex & e) const; - virtual expair combine_ex_with_coeff_to_pair(const ex & e, - const ex & c) const; - virtual expair combine_pair_with_coeff_to_pair(const expair & p, - const ex & c) const; - virtual ex recombine_pair_to_ex(const expair & p) const; - virtual bool expair_needs_further_processing(epp it); - virtual ex default_overall_coeff(void) const; - virtual void combine_overall_coeff(const ex & c); - virtual void combine_overall_coeff(const ex & c1, const ex & c2); - virtual bool can_make_flat(const expair & p) const; - - // non-virtual functions in this class + virtual ex thisexpairseq(const epvector & v, const ex & oc) const; + virtual ex thisexpairseq(epvector * vp, const ex & oc) const; + virtual void printseq(std::ostream & os, char delim, + unsigned this_precedence, + unsigned upper_precedence) const; + virtual void printpair(std::ostream & os, const expair & p, + unsigned upper_precedence) const; + virtual expair split_ex_to_pair(const ex & e) const; + virtual expair combine_ex_with_coeff_to_pair(const ex & e, + const ex & c) const; + virtual expair combine_pair_with_coeff_to_pair(const expair & p, + const ex & c) const; + virtual ex recombine_pair_to_ex(const expair & p) const; + virtual bool expair_needs_further_processing(epp it); + virtual ex default_overall_coeff(void) const; + virtual void combine_overall_coeff(const ex & c); + virtual void combine_overall_coeff(const ex & c1, const ex & c2); + virtual bool can_make_flat(const expair & p) const; + + // non-virtual functions in this class protected: - void construct_from_2_ex_via_exvector(const ex & lh, const ex & rh); - void construct_from_2_ex(const ex & lh, const ex & rh); - void construct_from_2_expairseq(const expairseq & s1, - const expairseq & s2); - void construct_from_expairseq_ex(const expairseq & s, - const ex & e); - void construct_from_exvector(const exvector & v); - 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); + void construct_from_2_ex_via_exvector(const ex & lh, const ex & rh); + void construct_from_2_ex(const ex & lh, const ex & rh); + void construct_from_2_expairseq(const expairseq & s1, + const expairseq & s2); + void construct_from_expairseq_ex(const expairseq & s, + const ex & e); + void construct_from_exvector(const exvector & v); + 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 - void combine_same_terms(void); - unsigned calc_hashtabsize(unsigned sz) const; - unsigned calc_hashindex(const ex & e) const; - void shrink_hashtab(void); - void remove_hashtab_entry(epvector::const_iterator element); - void move_hashtab_entry(epvector::const_iterator oldpos, - epvector::iterator newpos); - void sorted_insert(epplist & eppl, epp elem); - void build_hashtab_and_combine(epvector::iterator & first_numeric, - epvector::iterator & last_non_zero, - vector & touched, - unsigned & number_of_zeroes); - void drop_coeff_0_terms(epvector::iterator & first_numeric, - epvector::iterator & last_non_zero, - vector & touched, - unsigned & number_of_zeroes); - bool has_coeff_0(void) const; - void add_numerics_to_hashtab(epvector::iterator first_numeric, - epvector::const_iterator last_non_zero); + void combine_same_terms(void); + unsigned calc_hashtabsize(unsigned sz) const; + unsigned calc_hashindex(const ex & e) const; + void shrink_hashtab(void); + void remove_hashtab_entry(epvector::const_iterator element); + void move_hashtab_entry(epvector::const_iterator oldpos, + epvector::iterator newpos); + void sorted_insert(epplist & eppl, epp elem); + void build_hashtab_and_combine(epvector::iterator & first_numeric, + epvector::iterator & last_non_zero, + vector & touched, + unsigned & number_of_zeroes); + void drop_coeff_0_terms(epvector::iterator & first_numeric, + epvector::iterator & last_non_zero, + vector & touched, + unsigned & number_of_zeroes); + 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 - bool is_canonical() const; - epvector * expandchildren(unsigned options) const; - epvector * evalchildren(int level) const; - epvector evalfchildren(int level) const; - epvector normalchildren(int level) const; - epvector diffchildren(const symbol & s) const; - epvector * subschildren(const lst & ls, const lst & lr) const; - + bool is_canonical() const; + epvector * expandchildren(unsigned options) const; + epvector * evalchildren(int level) const; + epvector evalfchildren(int level) const; + epvector normalchildren(int level) const; + epvector diffchildren(const symbol & s) const; + epvector * subschildren(const lst & ls, const lst & lr) const; + // member variables - + protected: - epvector seq; - ex overall_coeff; - static unsigned precedence; + epvector seq; + ex overall_coeff; + static unsigned precedence; #ifdef EXPAIRSEQ_USE_HASHTAB - epplistvector hashtab; - unsigned hashtabsize; - unsigned hashmask; - static unsigned maxhashtabsize; - static unsigned minhashtabsize; - static unsigned hashtabfactor; + epplistvector hashtab; + unsigned hashtabsize; + unsigned hashmask; + static unsigned maxhashtabsize; + static unsigned minhashtabsize; + static unsigned hashtabfactor; #endif // def EXPAIRSEQ_USE_HASHTAB }; diff --git a/ginac/exprseq_suppl.cpp b/ginac/exprseq_suppl.cpp index ae2abd20..2d7e7bf9 100644 --- a/ginac/exprseq_suppl.cpp +++ b/ginac/exprseq_suppl.cpp @@ -30,16 +30,16 @@ namespace GiNaC { bool exprseq::info(unsigned inf) const { - if (inf==info_flags::exprseq) return 1; - return basic::info(inf); + if (inf==info_flags::exprseq) return 1; + return basic::info(inf); } ex & exprseq::let_op(int i) { - GINAC_ASSERT(i>=0); - GINAC_ASSERT(i=0); + GINAC_ASSERT(isetflag(status_flags::dynallocated); + return (new fail(n, sym_lst))->setflag(status_flags::dynallocated); } /** Archive the object. */ void fail::archive(archive_node &n) const { - inherited::archive(n); + inherited::archive(n); } ////////// @@ -113,20 +113,20 @@ void fail::archive(archive_node &n) const basic * fail::duplicate() const { - debugmsg("fail duplicate",LOGLEVEL_DUPLICATE); - return new fail(*this); + debugmsg("fail duplicate",LOGLEVEL_DUPLICATE); + return new fail(*this); } void fail::print(std::ostream & os, unsigned upper_precedence) const { - debugmsg("fail print",LOGLEVEL_PRINT); - os << "FAIL"; + debugmsg("fail print",LOGLEVEL_PRINT); + os << "FAIL"; } void fail::printraw(std::ostream & os) const { - debugmsg("fail printraw",LOGLEVEL_PRINT); - os << "FAIL"; + debugmsg("fail printraw",LOGLEVEL_PRINT); + os << "FAIL"; } // protected @@ -134,7 +134,7 @@ void fail::printraw(std::ostream & os) const int fail::compare_same_type(const basic & other) const { // two fails are always identical - return 0; + return 0; } ////////// diff --git a/ginac/fail.h b/ginac/fail.h index 41c546d8..c7a80a7e 100644 --- a/ginac/fail.h +++ b/ginac/fail.h @@ -32,35 +32,35 @@ namespace GiNaC { class fail : public basic { - GINAC_DECLARE_REGISTERED_CLASS(fail, basic) + GINAC_DECLARE_REGISTERED_CLASS(fail, basic) - // default constructor, destructor, copy constructor assignment operator and helpers + // default constructor, destructor, copy constructor assignment operator and helpers public: - fail(); - ~fail(); - fail(const fail & other); - const fail & operator=(const fail & other); + fail(); + ~fail(); + fail(const fail & other); + const fail & operator=(const fail & other); protected: - void copy(const fail & other); - void destroy(bool call_parent); + void copy(const fail & other); + void destroy(bool call_parent); - // other constructors - // none + // other constructors + // none - // functions overriding virtual functions from bases classes + // functions overriding virtual functions from bases classes public: - basic * duplicate() const; - void print(std::ostream & os, unsigned upper_precedence=0) const; - void printraw(std::ostream & os) const; + basic * duplicate() const; + void print(std::ostream & os, unsigned upper_precedence=0) const; + void printraw(std::ostream & os) const; protected: - int compare_same_type(const basic & other) const; - unsigned return_type(void) const { return return_types::noncommutative_composite; }; - - // new virtual functions which can be overridden by derived classes - // none + int compare_same_type(const basic & other) const; + unsigned return_type(void) const { return return_types::noncommutative_composite; }; + + // new virtual functions which can be overridden by derived classes + // none - // non-virtual functions in this class - // none + // non-virtual functions in this class + // none // member variables // none diff --git a/ginac/flags.h b/ginac/flags.h index 24edd02a..2ff39e67 100644 --- a/ginac/flags.h +++ b/ginac/flags.h @@ -29,110 +29,110 @@ namespace GiNaC { class expand_options { public: - enum { expand_trigonometric = 0x0001 - }; + enum { expand_trigonometric = 0x0001 + }; }; class series_options { public: - enum { suppress_branchcut = 0x0001 - }; + enum { suppress_branchcut = 0x0001 + }; }; class determinant_algo { public: - enum { automatic, - gauss, - divfree, - laplace, - bareiss - }; + enum { automatic, + gauss, + divfree, + laplace, + bareiss + }; }; class solve_algo { public: - enum { automatic, - gauss, - divfree, - bareiss - }; + enum { automatic, + gauss, + divfree, + bareiss + }; }; class status_flags { public: - enum { dynallocated = 0x0001, - evaluated = 0x0002, - expanded = 0x0004, - hash_calculated = 0x0008 - }; + enum { dynallocated = 0x0001, + evaluated = 0x0002, + expanded = 0x0004, + hash_calculated = 0x0008 + }; }; /** Possible attributes an object can have. */ class info_flags { public: - enum { - // answered by class numeric - numeric, - real, - rational, - integer, - crational, - cinteger, - positive, - negative, - nonnegative, - posint, - negint, - nonnegint, - even, - odd, - prime, - - // answered by class relation - relation, - relation_equal, - relation_not_equal, - relation_less, - relation_less_or_equal, - relation_greater, - relation_greater_or_equal, - - // answered by class symbol - symbol, - - // answered by class lst - list, - - // answered by class exprseq - exprseq, - - // answered by classes numeric, symbol, add, mul, power - polynomial, - integer_polynomial, - cinteger_polynomial, - rational_polynomial, - crational_polynomial, - rational_function, - algebraic, - - // answered by class indexed - indexed, // class can carry indices - has_indices, // object has at least one index - - // answered by class idx - idx, - - // answered by class coloridx - coloridx, - - // answered by class lorentzidx - lorentzidx - }; + enum { + // answered by class numeric + numeric, + real, + rational, + integer, + crational, + cinteger, + positive, + negative, + nonnegative, + posint, + negint, + nonnegint, + even, + odd, + prime, + + // answered by class relation + relation, + relation_equal, + relation_not_equal, + relation_less, + relation_less_or_equal, + relation_greater, + relation_greater_or_equal, + + // answered by class symbol + symbol, + + // answered by class lst + list, + + // answered by class exprseq + exprseq, + + // answered by classes numeric, symbol, add, mul, power + polynomial, + integer_polynomial, + cinteger_polynomial, + rational_polynomial, + crational_polynomial, + rational_function, + algebraic, + + // answered by class indexed + indexed, // class can carry indices + has_indices, // object has at least one index + + // answered by class idx + idx, + + // answered by class coloridx + coloridx, + + // answered by class lorentzidx + lorentzidx + }; }; class return_types { public: - enum { commutative, noncommutative, noncommutative_composite}; + enum { commutative, noncommutative, noncommutative_composite}; }; class csrc_types { @@ -146,11 +146,11 @@ public: class remember_strategies { public: - enum { delete_never, // let table grow undefinitely, not recommmended, but currently default - delete_lru, // least recently used - delete_lfu, // least frequently used - delete_cyclic // first (oldest) one in list - }; + enum { delete_never, // let table grow undefinitely, not recommmended, but currently default + delete_lru, // least recently used + delete_lfu, // least frequently used + delete_cyclic // first (oldest) one in list + }; }; #ifndef NO_NAMESPACE_GINAC diff --git a/ginac/idx.cpp b/ginac/idx.cpp index ff493c6e..8a31ec7e 100644 --- a/ginac/idx.cpp +++ b/ginac/idx.cpp @@ -44,48 +44,48 @@ GINAC_IMPLEMENT_REGISTERED_CLASS(idx, basic) idx::idx() : inherited(TINFO_idx), symbolic(true), covariant(false) { - debugmsg("idx default constructor",LOGLEVEL_CONSTRUCT); - serial=next_serial++; - name="index"+ToString(serial); + debugmsg("idx default constructor",LOGLEVEL_CONSTRUCT); + serial=next_serial++; + name="index"+ToString(serial); } idx::~idx() { - debugmsg("idx destructor",LOGLEVEL_DESTRUCT); - destroy(0); + debugmsg("idx destructor",LOGLEVEL_DESTRUCT); + destroy(0); } idx::idx(const idx & other) { - debugmsg("idx copy constructor",LOGLEVEL_CONSTRUCT); - copy(other); + debugmsg("idx copy constructor",LOGLEVEL_CONSTRUCT); + copy(other); } const idx & idx::operator=(const idx & other) { - debugmsg("idx operator=",LOGLEVEL_ASSIGNMENT); - if (this != &other) { - destroy(1); - copy(other); - } - return *this; + debugmsg("idx operator=",LOGLEVEL_ASSIGNMENT); + if (this != &other) { + destroy(1); + copy(other); + } + return *this; } // protected void idx::copy(const idx & other) { - inherited::copy(other); - serial=other.serial; - symbolic=other.symbolic; - name=other.name; - value=other.value; - covariant=other.covariant; + inherited::copy(other); + serial=other.serial; + symbolic=other.symbolic; + name=other.name; + value=other.value; + covariant=other.covariant; } void idx::destroy(bool call_parent) { - if (call_parent) inherited::destroy(call_parent); + if (call_parent) inherited::destroy(call_parent); } ////////// @@ -96,30 +96,30 @@ void idx::destroy(bool call_parent) idx::idx(bool cov) : inherited(TINFO_idx), symbolic(true), covariant(cov) { - debugmsg("idx constructor from bool",LOGLEVEL_CONSTRUCT); - serial = next_serial++; - name = "index"+ToString(serial); + debugmsg("idx constructor from bool",LOGLEVEL_CONSTRUCT); + serial = next_serial++; + name = "index"+ToString(serial); } idx::idx(const std::string & n, bool cov) : inherited(TINFO_idx), - symbolic(true), name(n), covariant(cov) + symbolic(true), name(n), covariant(cov) { - debugmsg("idx constructor from string,bool",LOGLEVEL_CONSTRUCT); - serial = next_serial++; + debugmsg("idx constructor from string,bool",LOGLEVEL_CONSTRUCT); + serial = next_serial++; } idx::idx(const char * n, bool cov) : inherited(TINFO_idx), - symbolic(true), name(n), covariant(cov) + symbolic(true), name(n), covariant(cov) { - debugmsg("idx constructor from char*,bool",LOGLEVEL_CONSTRUCT); - serial = next_serial++; + debugmsg("idx constructor from char*,bool",LOGLEVEL_CONSTRUCT); + serial = next_serial++; } idx::idx(unsigned v, bool cov) : inherited(TINFO_idx), - symbolic(false), value(v), covariant(cov) + symbolic(false), value(v), covariant(cov) { - debugmsg("idx constructor from unsigned,bool",LOGLEVEL_CONSTRUCT); - serial = 0; + debugmsg("idx constructor from unsigned,bool",LOGLEVEL_CONSTRUCT); + serial = 0; } ////////// @@ -129,44 +129,44 @@ idx::idx(unsigned v, bool cov) : inherited(TINFO_idx), /** Construct object from archive_node. */ idx::idx(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) { - debugmsg("idx constructor from archive_node", LOGLEVEL_CONSTRUCT); - n.find_bool("symbolic", symbolic); - n.find_bool("covariant", covariant); - if (symbolic) { - serial = next_serial++; - if (!(n.find_string("name", name))) - name = "index" + ToString(serial); - } else { - serial = 0; - n.find_unsigned("value", value); - } + debugmsg("idx constructor from archive_node", LOGLEVEL_CONSTRUCT); + n.find_bool("symbolic", symbolic); + n.find_bool("covariant", covariant); + if (symbolic) { + serial = next_serial++; + if (!(n.find_string("name", name))) + name = "index" + ToString(serial); + } else { + serial = 0; + n.find_unsigned("value", value); + } } /** Unarchive the object. */ ex idx::unarchive(const archive_node &n, const lst &sym_lst) { - ex s = (new idx(n, sym_lst))->setflag(status_flags::dynallocated); + ex s = (new idx(n, sym_lst))->setflag(status_flags::dynallocated); - if (ex_to_idx(s).symbolic) { - // If idx is in sym_lst, return the existing idx - for (unsigned i=0; i - (const_cast(other)); - - if (covariant!=o.covariant) { - // different co/contravariant - return covariant ? -1 : 1; - } - if ((!symbolic) && (!o.symbolic)) { - // non-symbolic, of equal type: compare values - if (value==o.value) { - return 0; - } - return value + (const_cast(other)); + + if (covariant!=o.covariant) { + // different co/contravariant + return covariant ? -1 : 1; + } + if ((!symbolic) && (!o.symbolic)) { + // non-symbolic, of equal type: compare values + if (value==o.value) { + return 0; + } + return value - (const_cast(other)); + GINAC_ASSERT(is_of_type(other,idx)); + const idx & o=static_cast + (const_cast(other)); - if (covariant!=o.covariant) return false; - if (symbolic!=o.symbolic) return false; - if (symbolic && o.symbolic) return serial==o.serial; - return value==o.value; + if (covariant!=o.covariant) return false; + if (symbolic!=o.symbolic) return false; + if (symbolic && o.symbolic) return serial==o.serial; + return value==o.value; } unsigned idx::calchash(void) const { - hashvalue=golden_ratio_hash(golden_ratio_hash(tinfo_key ^ serial)); - setflag(status_flags::hash_calculated); - return hashvalue; + hashvalue=golden_ratio_hash(golden_ratio_hash(tinfo_key ^ serial)); + setflag(status_flags::hash_calculated); + return hashvalue; } ////////// @@ -325,38 +325,38 @@ unsigned idx::calchash(void) const bool idx::is_co_contra_pair(const basic & other) const { - // like is_equal_same_type(), but tests for different covariant status - GINAC_ASSERT(is_of_type(other,idx)); - const idx & o=static_cast - (const_cast(other)); + // like is_equal_same_type(), but tests for different covariant status + GINAC_ASSERT(is_of_type(other,idx)); + const idx & o=static_cast + (const_cast(other)); - if (covariant==o.covariant) return false; - if (symbolic!=o.symbolic) return false; - if (symbolic && o.symbolic) return serial==o.serial; - return value==o.value; + if (covariant==o.covariant) return false; + if (symbolic!=o.symbolic) return false; + if (symbolic && o.symbolic) return serial==o.serial; + return value==o.value; } bool idx::is_symbolic(void) const { - return symbolic; + return symbolic; } unsigned idx::get_value(void) const { - return value; + return value; } bool idx::is_covariant(void) const { - return covariant; + return covariant; } ex idx::toggle_covariant(void) const { - idx * i_copy=static_cast(duplicate()); - i_copy->covariant = !i_copy->covariant; - i_copy->clearflag(status_flags::hash_calculated); - return i_copy->setflag(status_flags::dynallocated); + idx * i_copy=static_cast(duplicate()); + i_copy->covariant = !i_copy->covariant; + i_copy->clearflag(status_flags::hash_calculated); + return i_copy->setflag(status_flags::dynallocated); } ////////// @@ -386,116 +386,116 @@ const type_info & typeid_idx=typeid(some_idx); int canonicalize_indices(exvector & iv, bool antisymmetric) { - if (iv.size()<2) { - // nothing do to for 0 or 1 indices - return INT_MAX; - } - - bool something_changed=false; - int sig=1; - // simple bubble sort algorithm should be sufficient for the small number of indices needed - exvector::const_iterator last_idx=iv.end(); - exvector::const_iterator next_to_last_idx=iv.end()-1; - for (exvector::iterator it1=iv.begin(); it1!=next_to_last_idx; ++it1) { - for (exvector::iterator it2=it1+1; it2!=last_idx; ++it2) { - int cmpval=(*it1).compare(*it2); - if (cmpval==1) { - iter_swap(it1,it2); - something_changed=true; - if (antisymmetric) sig=-sig; - } else if ((cmpval==0) && antisymmetric) { - something_changed=true; - sig=0; - } - } - } - return something_changed ? sig : INT_MAX; + if (iv.size()<2) { + // nothing do to for 0 or 1 indices + return INT_MAX; + } + + bool something_changed=false; + int sig=1; + // simple bubble sort algorithm should be sufficient for the small number of indices needed + exvector::const_iterator last_idx=iv.end(); + exvector::const_iterator next_to_last_idx=iv.end()-1; + for (exvector::iterator it1=iv.begin(); it1!=next_to_last_idx; ++it1) { + for (exvector::iterator it2=it1+1; it2!=last_idx; ++it2) { + int cmpval=(*it1).compare(*it2); + if (cmpval==1) { + iter_swap(it1,it2); + something_changed=true; + if (antisymmetric) sig=-sig; + } else if ((cmpval==0) && antisymmetric) { + something_changed=true; + sig=0; + } + } + } + return something_changed ? sig : INT_MAX; } exvector idx_intersect(const exvector & iv1, const exvector & iv2) { - // build a vector of symbolic indices contained in iv1 and iv2 simultaneously - // assumes (but does not test) that each index occurs at most twice - exvector iv_intersect; - for (exvector::const_iterator cit1=iv1.begin(); cit1!=iv1.end(); ++cit1) { - GINAC_ASSERT(is_ex_of_type(*cit1,idx)); - if (ex_to_idx(*cit1).is_symbolic()) { - for (exvector::const_iterator cit2=iv2.begin(); cit2!=iv2.end(); ++cit2) { - GINAC_ASSERT(is_ex_of_type(*cit2,idx)); - if ((*cit1).is_equal(*cit2)) { - iv_intersect.push_back(*cit1); - break; - } - } - } - } - return iv_intersect; + // build a vector of symbolic indices contained in iv1 and iv2 simultaneously + // assumes (but does not test) that each index occurs at most twice + exvector iv_intersect; + for (exvector::const_iterator cit1=iv1.begin(); cit1!=iv1.end(); ++cit1) { + GINAC_ASSERT(is_ex_of_type(*cit1,idx)); + if (ex_to_idx(*cit1).is_symbolic()) { + for (exvector::const_iterator cit2=iv2.begin(); cit2!=iv2.end(); ++cit2) { + GINAC_ASSERT(is_ex_of_type(*cit2,idx)); + if ((*cit1).is_equal(*cit2)) { + iv_intersect.push_back(*cit1); + break; + } + } + } + } + return iv_intersect; } #define TEST_PERMUTATION(A,B,C,P) \ - if ((iv3[B].is_equal(iv2[0]))&&(iv3[C].is_equal(iv2[1]))) { \ - if (antisymmetric) *sig=P; \ - return iv3[A]; \ - } + if ((iv3[B].is_equal(iv2[0]))&&(iv3[C].is_equal(iv2[1]))) { \ + if (antisymmetric) *sig=P; \ + return iv3[A]; \ + } ex permute_free_index_to_front(const exvector & iv3, const exvector & iv2, - bool antisymmetric, int * sig) -{ - // match (return value,iv2) to iv3 by permuting indices - // iv3 is always cyclic - - GINAC_ASSERT(iv3.size()==3); - GINAC_ASSERT(iv2.size()==2); - - *sig=1; - - TEST_PERMUTATION(0,1,2, 1); - TEST_PERMUTATION(0,2,1, -1); - TEST_PERMUTATION(1,0,2, -1); - TEST_PERMUTATION(1,2,0, 1); - TEST_PERMUTATION(2,0,1, 1); - TEST_PERMUTATION(2,1,0, -1); - throw(std::logic_error("permute_free_index_to_front(): no valid permutation found")); + bool antisymmetric, int * sig) +{ + // match (return value,iv2) to iv3 by permuting indices + // iv3 is always cyclic + + GINAC_ASSERT(iv3.size()==3); + GINAC_ASSERT(iv2.size()==2); + + *sig=1; + + TEST_PERMUTATION(0,1,2, 1); + TEST_PERMUTATION(0,2,1, -1); + TEST_PERMUTATION(1,0,2, -1); + TEST_PERMUTATION(1,2,0, 1); + TEST_PERMUTATION(2,0,1, 1); + TEST_PERMUTATION(2,1,0, -1); + throw(std::logic_error("permute_free_index_to_front(): no valid permutation found")); } - + unsigned subs_index_in_exvector(exvector & v, const ex & is, const ex & ir) { - exvector::iterator it; - unsigned replacements=0; - unsigned current_replacements; + exvector::iterator it; + unsigned replacements=0; + unsigned current_replacements; - GINAC_ASSERT(is_ex_of_type(is,idx)); - GINAC_ASSERT(is_ex_of_type(ir,idx)); + GINAC_ASSERT(is_ex_of_type(is,idx)); + GINAC_ASSERT(is_ex_of_type(ir,idx)); - for (it=v.begin(); it!=v.end(); ++it) { - current_replacements=count_index(*it,is); - if (current_replacements>0) { - (*it)=(*it).subs(is==ir); - } - replacements += current_replacements; - } - return replacements; + for (it=v.begin(); it!=v.end(); ++it) { + current_replacements=count_index(*it,is); + if (current_replacements>0) { + (*it)=(*it).subs(is==ir); + } + replacements += current_replacements; + } + return replacements; } unsigned count_index(const ex & e, const ex & i) { - exvector idxv=e.get_indices(); - unsigned count=0; - for (exvector::const_iterator cit=idxv.begin(); cit!=idxv.end(); ++cit) { - if ((*cit).is_equal(i)) count++; - } - return count; + exvector idxv=e.get_indices(); + unsigned count=0; + for (exvector::const_iterator cit=idxv.begin(); cit!=idxv.end(); ++cit) { + if ((*cit).is_equal(i)) count++; + } + return count; } ex subs_indices(const ex & e, const exvector & idxv_subs, - const exvector & idxv_repl) -{ - GINAC_ASSERT(idxv_subs.size()==idxv_repl.size()); - ex res=e; - for (unsigned i=0; isetflag(status_flags::dynallocated); + return (new indexed(n, sym_lst))->setflag(status_flags::dynallocated); } /** Archive the object. */ void indexed::archive(archive_node &n) const { - inherited::archive(n); + inherited::archive(n); } ////////// @@ -162,61 +162,61 @@ void indexed::archive(archive_node &n) const basic * indexed::duplicate() const { - debugmsg("indexed duplicate",LOGLEVEL_DUPLICATE); - return new indexed(*this); + debugmsg("indexed duplicate",LOGLEVEL_DUPLICATE); + return new indexed(*this); } void indexed::printraw(std::ostream & os) const { - debugmsg("indexed printraw",LOGLEVEL_PRINT); - os << "indexed(indices="; - printrawindices(os); - os << ",hash=" << hashvalue << ",flags=" << flags << ")"; + debugmsg("indexed printraw",LOGLEVEL_PRINT); + os << "indexed(indices="; + printrawindices(os); + os << ",hash=" << hashvalue << ",flags=" << flags << ")"; } void indexed::printtree(std::ostream & os, unsigned indent) const { - debugmsg("indexed printtree",LOGLEVEL_PRINT); - os << std::string(indent,' ') << "indexed: " << seq.size() << " indices"; - os << ",hash=" << hashvalue << ",flags=" << flags << std::endl; - printtreeindices(os,indent); + debugmsg("indexed printtree",LOGLEVEL_PRINT); + os << std::string(indent,' ') << "indexed: " << seq.size() << " indices"; + os << ",hash=" << hashvalue << ",flags=" << flags << std::endl; + printtreeindices(os,indent); } void indexed::print(std::ostream & os, unsigned upper_precedence) const { - debugmsg("indexed print",LOGLEVEL_PRINT); - os << "UNNAMEDINDEX"; - printindices(os); + debugmsg("indexed print",LOGLEVEL_PRINT); + os << "UNNAMEDINDEX"; + printindices(os); } void indexed::printcsrc(std::ostream & os, unsigned type, - unsigned upper_precedence) const + unsigned upper_precedence) const { - debugmsg("indexed print csrc",LOGLEVEL_PRINT); - print(os,upper_precedence); + debugmsg("indexed print csrc",LOGLEVEL_PRINT); + print(os,upper_precedence); } bool indexed::info(unsigned inf) const { - if (inf==info_flags::indexed) return true; - if (inf==info_flags::has_indices) return seq.size()!=0; - return inherited::info(inf); + if (inf==info_flags::indexed) return true; + if (inf==info_flags::has_indices) return seq.size()!=0; + return inherited::info(inf); } exvector indexed::get_indices(void) const { - return seq; + return seq; - /* - idxvector filtered_indices; - filtered_indices.reserve(indices.size()); - for (idxvector::const_iterator cit=indices.begin(); cit!=indices.end(); ++cit) { - if ((*cit).get_type()==t) { - filtered_indices.push_back(*cit); - } - } - return filtered_indices; - */ + /* + idxvector filtered_indices; + filtered_indices.reserve(indices.size()); + for (idxvector::const_iterator cit=indices.begin(); cit!=indices.end(); ++cit) { + if ((*cit).get_type()==t) { + filtered_indices.push_back(*cit); + } + } + return filtered_indices; + */ } // protected @@ -225,39 +225,39 @@ exvector indexed::get_indices(void) const * @see ex::diff */ ex indexed::derivative(const symbol & s) const { - return _ex0(); + return _ex0(); } int indexed::compare_same_type(const basic & other) const { - GINAC_ASSERT(is_of_type(other,indexed)); - return inherited::compare_same_type(other); + GINAC_ASSERT(is_of_type(other,indexed)); + return inherited::compare_same_type(other); } bool indexed::is_equal_same_type(const basic & other) const { - GINAC_ASSERT(is_of_type(other,indexed)); - return inherited::is_equal_same_type(other); + GINAC_ASSERT(is_of_type(other,indexed)); + return inherited::is_equal_same_type(other); } unsigned indexed::return_type(void) const { - return return_types::noncommutative; + return return_types::noncommutative; } unsigned indexed::return_type_tinfo(void) const { - return tinfo_key; + return tinfo_key; } ex indexed::thisexprseq(const exvector & v) const { - return indexed(v); + return indexed(v); } ex indexed::thisexprseq(exvector * vp) const { - return indexed(vp); + return indexed(vp); } ////////// @@ -274,51 +274,51 @@ ex indexed::thisexprseq(exvector * vp) const void indexed::printrawindices(std::ostream & os) const { - if (seq.size()!=0) { - for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { - (*cit).printraw(os); - os << ","; - } - } + if (seq.size()!=0) { + for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { + (*cit).printraw(os); + os << ","; + } + } } void indexed::printtreeindices(std::ostream & os, unsigned indent) const { - if (seq.size()!=0) { - for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { - os << std::string(indent+delta_indent,' '); - (*cit).printraw(os); - os << std::endl; - } - } + if (seq.size()!=0) { + for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { + os << std::string(indent+delta_indent,' '); + (*cit).printraw(os); + os << std::endl; + } + } } void indexed::printindices(std::ostream & os) const { - if (seq.size()!=0) { - if (seq.size()>1) { - os << "{"; - } - exvector::const_iterator last=seq.end()-1; - exvector::const_iterator cit=seq.begin(); - for (; cit!=last; ++cit) { - (*cit).print(os); - os << ","; - } - (*cit).print(os); - if (seq.size()>1) { - os << "}"; - } - } + if (seq.size()!=0) { + if (seq.size()>1) { + os << "{"; + } + exvector::const_iterator last=seq.end()-1; + exvector::const_iterator cit=seq.begin(); + for (; cit!=last; ++cit) { + (*cit).print(os); + os << ","; + } + (*cit).print(os); + if (seq.size()>1) { + os << "}"; + } + } } bool indexed::all_of_type_idx(void) const { - // used only inside of ASSERTs - for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { - if (!is_ex_of_type(*cit,idx)) return false; - } - return true; + // used only inside of ASSERTs + for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { + if (!is_ex_of_type(*cit,idx)) return false; + } + return true; } ////////// diff --git a/ginac/indexed.h b/ginac/indexed.h index aa0042b4..03dfa77a 100644 --- a/ginac/indexed.h +++ b/ginac/indexed.h @@ -33,59 +33,59 @@ namespace GiNaC { /** Base class for non-commutative indexed objects */ class indexed : public exprseq { - GINAC_DECLARE_REGISTERED_CLASS(indexed, exprseq) + GINAC_DECLARE_REGISTERED_CLASS(indexed, exprseq) // member functions - // default constructor, destructor, copy constructor assignment operator and helpers + // default constructor, destructor, copy constructor assignment operator and helpers public: - indexed(); - ~indexed(); - indexed(const indexed & other); - const indexed & operator=(const indexed & other); + indexed(); + ~indexed(); + indexed(const indexed & other); + const indexed & operator=(const indexed & other); protected: - void copy(const indexed & other); - void destroy(bool call_parent); + void copy(const indexed & other); + void destroy(bool call_parent); - // other constructors + // other constructors public: - indexed(const ex & i1); - indexed(const ex & i1, const ex & i2); - indexed(const ex & i1, const ex & i2, const ex & i3); - indexed(const ex & i1, const ex & i2, const ex & i3, const ex & i4); - indexed(const exvector & iv); - indexed(exvector * iv); - - // functions overriding virtual functions from base classes + indexed(const ex & i1); + indexed(const ex & i1, const ex & i2); + indexed(const ex & i1, const ex & i2, const ex & i3); + indexed(const ex & i1, const ex & i2, const ex & i3, const ex & i4); + indexed(const exvector & iv); + indexed(exvector * iv); + + // functions overriding virtual functions from base classes public: - basic * duplicate() const; - void printraw(std::ostream & os) const; - void printtree(std::ostream & os, unsigned indent) const; - void print(std::ostream & os, unsigned upper_precedence=0) const; - void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const; - bool info(unsigned inf) const; - exvector get_indices(void) const; + basic * duplicate() const; + void printraw(std::ostream & os) const; + void printtree(std::ostream & os, unsigned indent) const; + void print(std::ostream & os, unsigned upper_precedence=0) const; + void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const; + bool info(unsigned inf) const; + exvector get_indices(void) const; protected: - ex derivative(const symbol & s) const; - int compare_same_type(const basic & other) const; - bool is_equal_same_type(const basic & other) const; - unsigned return_type(void) const; - unsigned return_type_tinfo(void) const; - ex thisexprseq(const exvector & v) const; - ex thisexprseq(exvector * vp) const; - - // new virtual functions which can be overridden by derived classes - // none - - // non-virtual functions in this class + ex derivative(const symbol & s) const; + int compare_same_type(const basic & other) const; + bool is_equal_same_type(const basic & other) const; + unsigned return_type(void) const; + unsigned return_type_tinfo(void) const; + ex thisexprseq(const exvector & v) const; + ex thisexprseq(exvector * vp) const; + + // new virtual functions which can be overridden by derived classes + // none + + // non-virtual functions in this class protected: - void printrawindices(std::ostream & os) const; - void printtreeindices(std::ostream & os, unsigned indent) const; - void printindices(std::ostream & os) const; - bool all_of_type_idx(void) const; + void printrawindices(std::ostream & os) const; + void printtreeindices(std::ostream & os, unsigned indent) const; + void printindices(std::ostream & os) const; + bool all_of_type_idx(void) const; // member variables - // none + // none }; // global constants diff --git a/ginac/inifcns.cpp b/ginac/inifcns.cpp index 677d92f6..d5e9275b 100644 --- a/ginac/inifcns.cpp +++ b/ginac/inifcns.cpp @@ -47,23 +47,23 @@ namespace GiNaC { static ex abs_evalf(const ex & arg) { - BEGIN_TYPECHECK - TYPECHECK(arg,numeric) - END_TYPECHECK(abs(arg)) - - return abs(ex_to_numeric(arg)); + BEGIN_TYPECHECK + TYPECHECK(arg,numeric) + END_TYPECHECK(abs(arg)) + + return abs(ex_to_numeric(arg)); } static ex abs_eval(const ex & arg) { - if (is_ex_exactly_of_type(arg, numeric)) - return abs(ex_to_numeric(arg)); - else - return abs(arg).hold(); + if (is_ex_exactly_of_type(arg, numeric)) + return abs(ex_to_numeric(arg)); + else + return abs(arg).hold(); } REGISTER_FUNCTION(abs, eval_func(abs_eval). - evalf_func(abs_evalf)); + evalf_func(abs_evalf)); ////////// @@ -72,59 +72,59 @@ REGISTER_FUNCTION(abs, eval_func(abs_eval). static ex csgn_evalf(const ex & arg) { - BEGIN_TYPECHECK - TYPECHECK(arg,numeric) - END_TYPECHECK(csgn(arg)) - - return csgn(ex_to_numeric(arg)); + BEGIN_TYPECHECK + TYPECHECK(arg,numeric) + END_TYPECHECK(csgn(arg)) + + return csgn(ex_to_numeric(arg)); } static ex csgn_eval(const ex & arg) { - if (is_ex_exactly_of_type(arg, numeric)) - return csgn(ex_to_numeric(arg)); - - else if (is_ex_exactly_of_type(arg, mul)) { - numeric oc = ex_to_numeric(arg.op(arg.nops()-1)); - if (oc.is_real()) { - if (oc > 0) - // csgn(42*x) -> csgn(x) - return csgn(arg/oc).hold(); - else - // csgn(-42*x) -> -csgn(x) - return -csgn(arg/oc).hold(); - } - if (oc.real().is_zero()) { - if (oc.imag() > 0) - // csgn(42*I*x) -> csgn(I*x) - return csgn(I*arg/oc).hold(); - else - // csgn(-42*I*x) -> -csgn(I*x) - return -csgn(I*arg/oc).hold(); - } + if (is_ex_exactly_of_type(arg, numeric)) + return csgn(ex_to_numeric(arg)); + + else if (is_ex_exactly_of_type(arg, mul)) { + numeric oc = ex_to_numeric(arg.op(arg.nops()-1)); + if (oc.is_real()) { + if (oc > 0) + // csgn(42*x) -> csgn(x) + return csgn(arg/oc).hold(); + else + // csgn(-42*x) -> -csgn(x) + return -csgn(arg/oc).hold(); + } + if (oc.real().is_zero()) { + if (oc.imag() > 0) + // csgn(42*I*x) -> csgn(I*x) + return csgn(I*arg/oc).hold(); + else + // csgn(-42*I*x) -> -csgn(I*x) + return -csgn(I*arg/oc).hold(); + } } - return csgn(arg).hold(); + return csgn(arg).hold(); } static ex csgn_series(const ex & arg, - const relational & rel, - int order, - unsigned options) + const relational & rel, + int order, + unsigned options) { - const ex arg_pt = arg.subs(rel); - if (arg_pt.info(info_flags::numeric) && - ex_to_numeric(arg_pt).real().is_zero()) - throw (std::domain_error("csgn_series(): on imaginary axis")); - - epvector seq; - seq.push_back(expair(csgn(arg_pt), _ex0())); - return pseries(rel,seq); + const ex arg_pt = arg.subs(rel); + if (arg_pt.info(info_flags::numeric) && + ex_to_numeric(arg_pt).real().is_zero()) + throw (std::domain_error("csgn_series(): on imaginary axis")); + + epvector seq; + seq.push_back(expair(csgn(arg_pt), _ex0())); + return pseries(rel,seq); } REGISTER_FUNCTION(csgn, eval_func(csgn_eval). - evalf_func(csgn_evalf). - series_func(csgn_series)); + evalf_func(csgn_evalf). + series_func(csgn_series)); ////////// @@ -133,52 +133,52 @@ REGISTER_FUNCTION(csgn, eval_func(csgn_eval). static ex eta_evalf(const ex & x, const ex & y) { - BEGIN_TYPECHECK - TYPECHECK(x,numeric) - TYPECHECK(y,numeric) - END_TYPECHECK(eta(x,y)) - - numeric xim = imag(ex_to_numeric(x)); - numeric yim = imag(ex_to_numeric(y)); - numeric xyim = imag(ex_to_numeric(x*y)); - return evalf(I/4*Pi)*((csgn(-xim)+1)*(csgn(-yim)+1)*(csgn(xyim)+1)-(csgn(xim)+1)*(csgn(yim)+1)*(csgn(-xyim)+1)); + BEGIN_TYPECHECK + TYPECHECK(x,numeric) + TYPECHECK(y,numeric) + END_TYPECHECK(eta(x,y)) + + numeric xim = imag(ex_to_numeric(x)); + numeric yim = imag(ex_to_numeric(y)); + numeric xyim = imag(ex_to_numeric(x*y)); + return evalf(I/4*Pi)*((csgn(-xim)+1)*(csgn(-yim)+1)*(csgn(xyim)+1)-(csgn(xim)+1)*(csgn(yim)+1)*(csgn(-xyim)+1)); } static ex eta_eval(const ex & x, const ex & y) { - if (is_ex_exactly_of_type(x, numeric) && - is_ex_exactly_of_type(y, numeric)) { - // don't call eta_evalf here because it would call Pi.evalf()! - numeric xim = imag(ex_to_numeric(x)); - numeric yim = imag(ex_to_numeric(y)); - numeric xyim = imag(ex_to_numeric(x*y)); - return (I/4)*Pi*((csgn(-xim)+1)*(csgn(-yim)+1)*(csgn(xyim)+1)-(csgn(xim)+1)*(csgn(yim)+1)*(csgn(-xyim)+1)); - } - - return eta(x,y).hold(); + if (is_ex_exactly_of_type(x, numeric) && + is_ex_exactly_of_type(y, numeric)) { + // don't call eta_evalf here because it would call Pi.evalf()! + numeric xim = imag(ex_to_numeric(x)); + numeric yim = imag(ex_to_numeric(y)); + numeric xyim = imag(ex_to_numeric(x*y)); + return (I/4)*Pi*((csgn(-xim)+1)*(csgn(-yim)+1)*(csgn(xyim)+1)-(csgn(xim)+1)*(csgn(yim)+1)*(csgn(-xyim)+1)); + } + + return eta(x,y).hold(); } static ex eta_series(const ex & arg1, - const ex & arg2, - const relational & rel, - int order, - unsigned options) + const ex & arg2, + const relational & rel, + int order, + unsigned options) { - const ex arg1_pt = arg1.subs(rel); - const ex arg2_pt = arg2.subs(rel); - if (ex_to_numeric(arg1_pt).imag().is_zero() || - ex_to_numeric(arg2_pt).imag().is_zero() || - ex_to_numeric(arg1_pt*arg2_pt).imag().is_zero()) { - throw (std::domain_error("eta_series(): on discontinuity")); - } - epvector seq; - seq.push_back(expair(eta(arg1_pt,arg2_pt), _ex0())); - return pseries(rel,seq); + const ex arg1_pt = arg1.subs(rel); + const ex arg2_pt = arg2.subs(rel); + if (ex_to_numeric(arg1_pt).imag().is_zero() || + ex_to_numeric(arg2_pt).imag().is_zero() || + ex_to_numeric(arg1_pt*arg2_pt).imag().is_zero()) { + throw (std::domain_error("eta_series(): on discontinuity")); + } + epvector seq; + seq.push_back(expair(eta(arg1_pt,arg2_pt), _ex0())); + return pseries(rel,seq); } REGISTER_FUNCTION(eta, eval_func(eta_eval). - evalf_func(eta_evalf). - series_func(eta_series)); + evalf_func(eta_evalf). + series_func(eta_series)); ////////// @@ -187,136 +187,136 @@ REGISTER_FUNCTION(eta, eval_func(eta_eval). static ex Li2_evalf(const ex & x) { - BEGIN_TYPECHECK - TYPECHECK(x,numeric) - END_TYPECHECK(Li2(x)) - - return Li2(ex_to_numeric(x)); // -> numeric Li2(numeric) + BEGIN_TYPECHECK + TYPECHECK(x,numeric) + END_TYPECHECK(Li2(x)) + + return Li2(ex_to_numeric(x)); // -> numeric Li2(numeric) } static ex Li2_eval(const ex & x) { - if (x.info(info_flags::numeric)) { - // Li2(0) -> 0 - if (x.is_zero()) - return _ex0(); - // Li2(1) -> Pi^2/6 - if (x.is_equal(_ex1())) - return power(Pi,_ex2())/_ex6(); - // Li2(1/2) -> Pi^2/12 - log(2)^2/2 - if (x.is_equal(_ex1_2())) - return power(Pi,_ex2())/_ex12() + power(log(_ex2()),_ex2())*_ex_1_2(); - // Li2(-1) -> -Pi^2/12 - if (x.is_equal(_ex_1())) - return -power(Pi,_ex2())/_ex12(); - // Li2(I) -> -Pi^2/48+Catalan*I - if (x.is_equal(I)) - return power(Pi,_ex2())/_ex_48() + Catalan*I; - // Li2(-I) -> -Pi^2/48-Catalan*I - if (x.is_equal(-I)) - return power(Pi,_ex2())/_ex_48() - Catalan*I; - // Li2(float) - if (!x.info(info_flags::crational)) - return Li2_evalf(x); - } - - return Li2(x).hold(); + if (x.info(info_flags::numeric)) { + // Li2(0) -> 0 + if (x.is_zero()) + return _ex0(); + // Li2(1) -> Pi^2/6 + if (x.is_equal(_ex1())) + return power(Pi,_ex2())/_ex6(); + // Li2(1/2) -> Pi^2/12 - log(2)^2/2 + if (x.is_equal(_ex1_2())) + return power(Pi,_ex2())/_ex12() + power(log(_ex2()),_ex2())*_ex_1_2(); + // Li2(-1) -> -Pi^2/12 + if (x.is_equal(_ex_1())) + return -power(Pi,_ex2())/_ex12(); + // Li2(I) -> -Pi^2/48+Catalan*I + if (x.is_equal(I)) + return power(Pi,_ex2())/_ex_48() + Catalan*I; + // Li2(-I) -> -Pi^2/48-Catalan*I + if (x.is_equal(-I)) + return power(Pi,_ex2())/_ex_48() - Catalan*I; + // Li2(float) + if (!x.info(info_flags::crational)) + return Li2_evalf(x); + } + + return Li2(x).hold(); } static ex Li2_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(deriv_param==0); - - // d/dx Li2(x) -> -log(1-x)/x - return -log(1-x)/x; + GINAC_ASSERT(deriv_param==0); + + // d/dx Li2(x) -> -log(1-x)/x + return -log(1-x)/x; } static ex Li2_series(const ex &x, const relational &rel, int order, unsigned options) { - const ex x_pt = x.subs(rel); - if (x_pt.info(info_flags::numeric)) { - // First special case: x==0 (derivatives have poles) - if (x_pt.is_zero()) { - // method: - // The problem is that in d/dx Li2(x==0) == -log(1-x)/x we cannot - // simply substitute x==0. The limit, however, exists: it is 1. - // We also know all higher derivatives' limits: - // (d/dx)^n Li2(x) == n!/n^2. - // So the primitive series expansion is - // Li2(x==0) == x + x^2/4 + x^3/9 + ... - // and so on. - // We first construct such a primitive series expansion manually in - // a dummy symbol s and then insert the argument's series expansion - // for s. Reexpanding the resulting series returns the desired - // result. - const symbol s; - ex ser; - // manually construct the primitive expansion - for (int i=1; i=1 (branch cut) - if (!(options & series_options::suppress_branchcut) && - ex_to_numeric(x_pt).is_real() && ex_to_numeric(x_pt)>1) { - // method: - // This is the branch cut: assemble the primitive series manually - // and then add the corresponding complex step function. - const symbol *s = static_cast(rel.lhs().bp); - const ex point = rel.rhs(); - const symbol foo; - epvector seq; - // zeroth order term: - seq.push_back(expair(Li2(x_pt), _ex0())); - // compute the intermediate terms: - ex replarg = series(Li2(x), *s==foo, order); - for (unsigned i=1; i=1 (branch cut) + if (!(options & series_options::suppress_branchcut) && + ex_to_numeric(x_pt).is_real() && ex_to_numeric(x_pt)>1) { + // method: + // This is the branch cut: assemble the primitive series manually + // and then add the corresponding complex step function. + const symbol *s = static_cast(rel.lhs().bp); + const ex point = rel.rhs(); + const symbol foo; + epvector seq; + // zeroth order term: + seq.push_back(expair(Li2(x_pt), _ex0())); + // compute the intermediate terms: + ex replarg = series(Li2(x), *s==foo, order); + for (unsigned i=1; i O(1) or 0 - if (!x.is_zero()) - return Order(_ex1()).hold(); - else - return _ex0(); - } else if (is_ex_exactly_of_type(x, mul)) { - mul *m = static_cast(x.bp); - // O(c*expr) -> O(expr) - if (is_ex_exactly_of_type(m->op(m->nops() - 1), numeric)) - return Order(x / m->op(m->nops() - 1)).hold(); - } - return Order(x).hold(); + if (is_ex_exactly_of_type(x, numeric)) { + // O(c) -> O(1) or 0 + if (!x.is_zero()) + return Order(_ex1()).hold(); + else + return _ex0(); + } else if (is_ex_exactly_of_type(x, mul)) { + mul *m = static_cast(x.bp); + // O(c*expr) -> O(expr) + if (is_ex_exactly_of_type(m->op(m->nops() - 1), numeric)) + return Order(x / m->op(m->nops() - 1)).hold(); + } + return Order(x).hold(); } static ex Order_series(const ex & x, const relational & r, int order, unsigned options) { // Just wrap the function into a pseries object epvector new_seq; - GINAC_ASSERT(is_ex_exactly_of_type(r.lhs(),symbol)); - const symbol *s = static_cast(r.lhs().bp); + GINAC_ASSERT(is_ex_exactly_of_type(r.lhs(),symbol)); + const symbol *s = static_cast(r.lhs().bp); new_seq.push_back(expair(Order(_ex1()), numeric(std::min(x.ldegree(*s), order)))); return pseries(r, new_seq); } @@ -405,7 +405,7 @@ static ex Order_series(const ex & x, const relational & r, int order, unsigned o // Differentiation is handled in function::derivative because of its special requirements REGISTER_FUNCTION(Order, eval_func(Order_eval). - series_func(Order_series)); + series_func(Order_series)); ////////// // Inert partial differentiation operator @@ -414,11 +414,11 @@ REGISTER_FUNCTION(Order, eval_func(Order_eval). static ex Derivative_eval(const ex & f, const ex & l) { if (!is_ex_exactly_of_type(f, function)) { - throw(std::invalid_argument("Derivative(): 1st argument must be a function")); + throw(std::invalid_argument("Derivative(): 1st argument must be a function")); + } + if (!is_ex_exactly_of_type(l, lst)) { + throw(std::invalid_argument("Derivative(): 2nd argument must be a list")); } - if (!is_ex_exactly_of_type(l, lst)) { - throw(std::invalid_argument("Derivative(): 2nd argument must be a list")); - } return Derivative(f, l).hold(); } @@ -430,95 +430,95 @@ REGISTER_FUNCTION(Derivative, eval_func(Derivative_eval)); ex lsolve(const ex &eqns, const ex &symbols) { - // solve a system of linear equations - if (eqns.info(info_flags::relation_equal)) { - if (!symbols.info(info_flags::symbol)) - throw(std::invalid_argument("lsolve(): 2nd argument must be a symbol")); - ex sol=lsolve(lst(eqns),lst(symbols)); - - GINAC_ASSERT(sol.nops()==1); - GINAC_ASSERT(is_ex_exactly_of_type(sol.op(0),relational)); - - return sol.op(0).op(1); // return rhs of first solution - } - - // syntax checks - if (!eqns.info(info_flags::list)) { - throw(std::invalid_argument("lsolve(): 1st argument must be a list")); - } - for (unsigned i=0; i log((n-1)!) for postitive n - if (x.info(info_flags::posint)) - return log(factorial(x.exadd(_ex_1()))); - else - throw (pole_error("lgamma_eval(): logarithmic pole",0)); - } - // lgamma_evalf should be called here once it becomes available - } - - return lgamma(x).hold(); + if (x.info(info_flags::numeric)) { + // trap integer arguments: + if (x.info(info_flags::integer)) { + // lgamma(n) -> log((n-1)!) for postitive n + if (x.info(info_flags::posint)) + return log(factorial(x.exadd(_ex_1()))); + else + throw (pole_error("lgamma_eval(): logarithmic pole",0)); + } + // lgamma_evalf should be called here once it becomes available + } + + return lgamma(x).hold(); } static ex lgamma_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(deriv_param==0); - - // d/dx lgamma(x) -> psi(x) - return psi(x); + GINAC_ASSERT(deriv_param==0); + + // d/dx lgamma(x) -> psi(x) + return psi(x); } static ex lgamma_series(const ex & arg, - const relational & rel, - int order, - unsigned options) + const relational & rel, + int order, + unsigned options) { - // method: - // Taylor series where there is no pole falls back to psi function - // evaluation. - // On a pole at -m we could use the recurrence relation - // lgamma(x) == lgamma(x+1)-log(x) - // from which follows - // series(lgamma(x),x==-m,order) == - // series(lgamma(x+m+1)-log(x)...-log(x+m)),x==-m,order); - const ex arg_pt = arg.subs(rel); - if (!arg_pt.info(info_flags::integer) || arg_pt.info(info_flags::positive)) - throw do_taylor(); // caught by function::series() - // if we got here we have to care for a simple pole of tgamma(-m): - numeric m = -ex_to_numeric(arg_pt); - ex recur; - for (numeric p; p<=m; ++p) - recur += log(arg+p); - cout << recur << endl; - return (lgamma(arg+m+_ex1())-recur).series(rel, order, options); + // method: + // Taylor series where there is no pole falls back to psi function + // evaluation. + // On a pole at -m we could use the recurrence relation + // lgamma(x) == lgamma(x+1)-log(x) + // from which follows + // series(lgamma(x),x==-m,order) == + // series(lgamma(x+m+1)-log(x)...-log(x+m)),x==-m,order); + const ex arg_pt = arg.subs(rel); + if (!arg_pt.info(info_flags::integer) || arg_pt.info(info_flags::positive)) + throw do_taylor(); // caught by function::series() + // if we got here we have to care for a simple pole of tgamma(-m): + numeric m = -ex_to_numeric(arg_pt); + ex recur; + for (numeric p; p<=m; ++p) + recur += log(arg+p); + cout << recur << endl; + return (lgamma(arg+m+_ex1())-recur).series(rel, order, options); } REGISTER_FUNCTION(lgamma, eval_func(lgamma_eval). - evalf_func(lgamma_evalf). - derivative_func(lgamma_deriv). - series_func(lgamma_series)); + evalf_func(lgamma_evalf). + derivative_func(lgamma_deriv). + series_func(lgamma_series)); ////////// @@ -122,11 +122,11 @@ REGISTER_FUNCTION(lgamma, eval_func(lgamma_eval). static ex tgamma_evalf(const ex & x) { - BEGIN_TYPECHECK - TYPECHECK(x,numeric) - END_TYPECHECK(tgamma(x)) - - return tgamma(ex_to_numeric(x)); + BEGIN_TYPECHECK + TYPECHECK(x,numeric) + END_TYPECHECK(tgamma(x)) + + return tgamma(ex_to_numeric(x)); } @@ -137,79 +137,79 @@ static ex tgamma_evalf(const ex & x) * @exception pole_error("tgamma_eval(): simple pole",0) */ static ex tgamma_eval(const ex & x) { - if (x.info(info_flags::numeric)) { - // trap integer arguments: - if (x.info(info_flags::integer)) { - // tgamma(n) -> (n-1)! for postitive n - if (x.info(info_flags::posint)) { - return factorial(ex_to_numeric(x).sub(_num1())); - } else { - throw (pole_error("tgamma_eval(): simple pole",1)); - } - } - // trap half integer arguments: - if ((x*2).info(info_flags::integer)) { - // trap positive x==(n+1/2) - // tgamma(n+1/2) -> Pi^(1/2)*(1*3*..*(2*n-1))/(2^n) - if ((x*_ex2()).info(info_flags::posint)) { - numeric n = ex_to_numeric(x).sub(_num1_2()); - numeric coefficient = doublefactorial(n.mul(_num2()).sub(_num1())); - coefficient = coefficient.div(pow(_num2(),n)); - return coefficient * pow(Pi,_ex1_2()); - } else { - // trap negative x==(-n+1/2) - // tgamma(-n+1/2) -> Pi^(1/2)*(-2)^n/(1*3*..*(2*n-1)) - numeric n = abs(ex_to_numeric(x).sub(_num1_2())); - numeric coefficient = pow(_num_2(), n); - coefficient = coefficient.div(doublefactorial(n.mul(_num2()).sub(_num1())));; - return coefficient*power(Pi,_ex1_2()); - } - } - // tgamma_evalf should be called here once it becomes available - } - - return tgamma(x).hold(); + if (x.info(info_flags::numeric)) { + // trap integer arguments: + if (x.info(info_flags::integer)) { + // tgamma(n) -> (n-1)! for postitive n + if (x.info(info_flags::posint)) { + return factorial(ex_to_numeric(x).sub(_num1())); + } else { + throw (pole_error("tgamma_eval(): simple pole",1)); + } + } + // trap half integer arguments: + if ((x*2).info(info_flags::integer)) { + // trap positive x==(n+1/2) + // tgamma(n+1/2) -> Pi^(1/2)*(1*3*..*(2*n-1))/(2^n) + if ((x*_ex2()).info(info_flags::posint)) { + numeric n = ex_to_numeric(x).sub(_num1_2()); + numeric coefficient = doublefactorial(n.mul(_num2()).sub(_num1())); + coefficient = coefficient.div(pow(_num2(),n)); + return coefficient * pow(Pi,_ex1_2()); + } else { + // trap negative x==(-n+1/2) + // tgamma(-n+1/2) -> Pi^(1/2)*(-2)^n/(1*3*..*(2*n-1)) + numeric n = abs(ex_to_numeric(x).sub(_num1_2())); + numeric coefficient = pow(_num_2(), n); + coefficient = coefficient.div(doublefactorial(n.mul(_num2()).sub(_num1())));; + return coefficient*power(Pi,_ex1_2()); + } + } + // tgamma_evalf should be called here once it becomes available + } + + return tgamma(x).hold(); } static ex tgamma_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(deriv_param==0); - - // d/dx tgamma(x) -> psi(x)*tgamma(x) - return psi(x)*tgamma(x); + GINAC_ASSERT(deriv_param==0); + + // d/dx tgamma(x) -> psi(x)*tgamma(x) + return psi(x)*tgamma(x); } static ex tgamma_series(const ex & arg, - const relational & rel, - int order, - unsigned options) + const relational & rel, + int order, + unsigned options) { - // method: - // Taylor series where there is no pole falls back to psi function - // evaluation. - // On a pole at -m use the recurrence relation - // tgamma(x) == tgamma(x+1) / x - // from which follows - // series(tgamma(x),x==-m,order) == - // series(tgamma(x+m+1)/(x*(x+1)*...*(x+m)),x==-m,order+1); - const ex arg_pt = arg.subs(rel); - if (!arg_pt.info(info_flags::integer) || arg_pt.info(info_flags::positive)) - throw do_taylor(); // caught by function::series() - // if we got here we have to care for a simple pole at -m: - numeric m = -ex_to_numeric(arg_pt); - ex ser_denom = _ex1(); - for (numeric p; p<=m; ++p) - ser_denom *= arg+p; - return (tgamma(arg+m+_ex1())/ser_denom).series(rel, order+1, options); + // method: + // Taylor series where there is no pole falls back to psi function + // evaluation. + // On a pole at -m use the recurrence relation + // tgamma(x) == tgamma(x+1) / x + // from which follows + // series(tgamma(x),x==-m,order) == + // series(tgamma(x+m+1)/(x*(x+1)*...*(x+m)),x==-m,order+1); + const ex arg_pt = arg.subs(rel); + if (!arg_pt.info(info_flags::integer) || arg_pt.info(info_flags::positive)) + throw do_taylor(); // caught by function::series() + // if we got here we have to care for a simple pole at -m: + numeric m = -ex_to_numeric(arg_pt); + ex ser_denom = _ex1(); + for (numeric p; p<=m; ++p) + ser_denom *= arg+p; + return (tgamma(arg+m+_ex1())/ser_denom).series(rel, order+1, options); } REGISTER_FUNCTION(tgamma, eval_func(tgamma_eval). - evalf_func(tgamma_evalf). - derivative_func(tgamma_deriv). - series_func(tgamma_series)); + evalf_func(tgamma_evalf). + derivative_func(tgamma_deriv). + series_func(tgamma_series)); ////////// @@ -218,109 +218,109 @@ REGISTER_FUNCTION(tgamma, eval_func(tgamma_eval). static ex beta_evalf(const ex & x, const ex & y) { - BEGIN_TYPECHECK - TYPECHECK(x,numeric) - TYPECHECK(y,numeric) - END_TYPECHECK(beta(x,y)) - - return tgamma(ex_to_numeric(x))*tgamma(ex_to_numeric(y))/tgamma(ex_to_numeric(x+y)); + BEGIN_TYPECHECK + TYPECHECK(x,numeric) + TYPECHECK(y,numeric) + END_TYPECHECK(beta(x,y)) + + return tgamma(ex_to_numeric(x))*tgamma(ex_to_numeric(y))/tgamma(ex_to_numeric(x+y)); } static ex beta_eval(const ex & x, const ex & y) { - if (x.info(info_flags::numeric) && y.info(info_flags::numeric)) { - // treat all problematic x and y that may not be passed into tgamma, - // because they would throw there although beta(x,y) is well-defined - // using the formula beta(x,y) == (-1)^y * beta(1-x-y, y) - numeric nx(ex_to_numeric(x)); - numeric ny(ex_to_numeric(y)); - if (nx.is_real() && nx.is_integer() && - ny.is_real() && ny.is_integer()) { - if (nx.is_negative()) { - if (nx<=-ny) - return pow(_num_1(), ny)*beta(1-x-y, y); - else - throw (pole_error("beta_eval(): simple pole",1)); - } - if (ny.is_negative()) { - if (ny<=-nx) - return pow(_num_1(), nx)*beta(1-y-x, x); - else - throw (pole_error("beta_eval(): simple pole",1)); - } - return tgamma(x)*tgamma(y)/tgamma(x+y); - } - // no problem in numerator, but denominator has pole: - if ((nx+ny).is_real() && - (nx+ny).is_integer() && - !(nx+ny).is_positive()) - return _ex0(); - // everything is ok: - return tgamma(x)*tgamma(y)/tgamma(x+y); - } - - return beta(x,y).hold(); + if (x.info(info_flags::numeric) && y.info(info_flags::numeric)) { + // treat all problematic x and y that may not be passed into tgamma, + // because they would throw there although beta(x,y) is well-defined + // using the formula beta(x,y) == (-1)^y * beta(1-x-y, y) + numeric nx(ex_to_numeric(x)); + numeric ny(ex_to_numeric(y)); + if (nx.is_real() && nx.is_integer() && + ny.is_real() && ny.is_integer()) { + if (nx.is_negative()) { + if (nx<=-ny) + return pow(_num_1(), ny)*beta(1-x-y, y); + else + throw (pole_error("beta_eval(): simple pole",1)); + } + if (ny.is_negative()) { + if (ny<=-nx) + return pow(_num_1(), nx)*beta(1-y-x, x); + else + throw (pole_error("beta_eval(): simple pole",1)); + } + return tgamma(x)*tgamma(y)/tgamma(x+y); + } + // no problem in numerator, but denominator has pole: + if ((nx+ny).is_real() && + (nx+ny).is_integer() && + !(nx+ny).is_positive()) + return _ex0(); + // everything is ok: + return tgamma(x)*tgamma(y)/tgamma(x+y); + } + + return beta(x,y).hold(); } static ex beta_deriv(const ex & x, const ex & y, unsigned deriv_param) { - GINAC_ASSERT(deriv_param<2); - ex retval; - - // d/dx beta(x,y) -> (psi(x)-psi(x+y)) * beta(x,y) - if (deriv_param==0) - retval = (psi(x)-psi(x+y))*beta(x,y); - // d/dy beta(x,y) -> (psi(y)-psi(x+y)) * beta(x,y) - if (deriv_param==1) - retval = (psi(y)-psi(x+y))*beta(x,y); - return retval; + GINAC_ASSERT(deriv_param<2); + ex retval; + + // d/dx beta(x,y) -> (psi(x)-psi(x+y)) * beta(x,y) + if (deriv_param==0) + retval = (psi(x)-psi(x+y))*beta(x,y); + // d/dy beta(x,y) -> (psi(y)-psi(x+y)) * beta(x,y) + if (deriv_param==1) + retval = (psi(y)-psi(x+y))*beta(x,y); + return retval; } static ex beta_series(const ex & arg1, - const ex & arg2, - const relational & rel, - int order, - unsigned options) + const ex & arg2, + const relational & rel, + int order, + unsigned options) { - // method: - // Taylor series where there is no pole of one of the tgamma functions - // falls back to beta function evaluation. Otherwise, fall back to - // tgamma series directly. - const ex arg1_pt = arg1.subs(rel); - const ex arg2_pt = arg2.subs(rel); - GINAC_ASSERT(is_ex_exactly_of_type(rel.lhs(),symbol)); - const symbol *s = static_cast(rel.lhs().bp); - ex arg1_ser, arg2_ser, arg1arg2_ser; - if ((!arg1_pt.info(info_flags::integer) || arg1_pt.info(info_flags::positive)) && - (!arg2_pt.info(info_flags::integer) || arg2_pt.info(info_flags::positive))) - throw do_taylor(); // caught by function::series() - // trap the case where arg1 is on a pole: - if (arg1.info(info_flags::integer) && !arg1.info(info_flags::positive)) - arg1_ser = tgamma(arg1+*s).series(rel, order, options); - else - arg1_ser = tgamma(arg1).series(rel,order); - // trap the case where arg2 is on a pole: - if (arg2.info(info_flags::integer) && !arg2.info(info_flags::positive)) - arg2_ser = tgamma(arg2+*s).series(rel, order, options); - else - arg2_ser = tgamma(arg2).series(rel,order); - // trap the case where arg1+arg2 is on a pole: - if ((arg1+arg2).info(info_flags::integer) && !(arg1+arg2).info(info_flags::positive)) - arg1arg2_ser = tgamma(arg2+arg1+*s).series(rel, order, options); - else - arg1arg2_ser = tgamma(arg2+arg1).series(rel,order); - // compose the result (expanding all the terms): - return (arg1_ser*arg2_ser/arg1arg2_ser).series(rel, order, options).expand(); + // method: + // Taylor series where there is no pole of one of the tgamma functions + // falls back to beta function evaluation. Otherwise, fall back to + // tgamma series directly. + const ex arg1_pt = arg1.subs(rel); + const ex arg2_pt = arg2.subs(rel); + GINAC_ASSERT(is_ex_exactly_of_type(rel.lhs(),symbol)); + const symbol *s = static_cast(rel.lhs().bp); + ex arg1_ser, arg2_ser, arg1arg2_ser; + if ((!arg1_pt.info(info_flags::integer) || arg1_pt.info(info_flags::positive)) && + (!arg2_pt.info(info_flags::integer) || arg2_pt.info(info_flags::positive))) + throw do_taylor(); // caught by function::series() + // trap the case where arg1 is on a pole: + if (arg1.info(info_flags::integer) && !arg1.info(info_flags::positive)) + arg1_ser = tgamma(arg1+*s).series(rel, order, options); + else + arg1_ser = tgamma(arg1).series(rel,order); + // trap the case where arg2 is on a pole: + if (arg2.info(info_flags::integer) && !arg2.info(info_flags::positive)) + arg2_ser = tgamma(arg2+*s).series(rel, order, options); + else + arg2_ser = tgamma(arg2).series(rel,order); + // trap the case where arg1+arg2 is on a pole: + if ((arg1+arg2).info(info_flags::integer) && !(arg1+arg2).info(info_flags::positive)) + arg1arg2_ser = tgamma(arg2+arg1+*s).series(rel, order, options); + else + arg1arg2_ser = tgamma(arg2+arg1).series(rel,order); + // compose the result (expanding all the terms): + return (arg1_ser*arg2_ser/arg1arg2_ser).series(rel, order, options).expand(); } REGISTER_FUNCTION(beta, eval_func(beta_eval). - evalf_func(beta_evalf). - derivative_func(beta_deriv). - series_func(beta_series)); + evalf_func(beta_evalf). + derivative_func(beta_deriv). + series_func(beta_series)); ////////// @@ -329,94 +329,94 @@ REGISTER_FUNCTION(beta, eval_func(beta_eval). static ex psi1_evalf(const ex & x) { - BEGIN_TYPECHECK - TYPECHECK(x,numeric) - END_TYPECHECK(psi(x)) - - return psi(ex_to_numeric(x)); + BEGIN_TYPECHECK + TYPECHECK(x,numeric) + END_TYPECHECK(psi(x)) + + return psi(ex_to_numeric(x)); } /** Evaluation of digamma-function psi(x). * Somebody ought to provide some good numerical evaluation some day... */ static ex psi1_eval(const ex & x) { - if (x.info(info_flags::numeric)) { - numeric nx = ex_to_numeric(x); - if (nx.is_integer()) { - // integer case - if (nx.is_positive()) { - // psi(n) -> 1 + 1/2 +...+ 1/(n-1) - Euler - numeric rat(0); - for (numeric i(nx+_num_1()); i.is_positive(); --i) - rat += i.inverse(); - return rat-Euler; - } else { - // for non-positive integers there is a pole: - throw (pole_error("psi_eval(): simple pole",1)); - } - } - if ((_num2()*nx).is_integer()) { - // half integer case - if (nx.is_positive()) { - // psi((2m+1)/2) -> 2/(2m+1) + 2/2m +...+ 2/1 - Euler - 2log(2) - numeric rat(0); - for (numeric i((nx+_num_1())*_num2()); i.is_positive(); i-=_num2()) - rat += _num2()*i.inverse(); - return rat-Euler-_ex2()*log(_ex2()); - } else { - // use the recurrence relation - // psi(-m-1/2) == psi(-m-1/2+1) - 1 / (-m-1/2) - // to relate psi(-m-1/2) to psi(1/2): - // psi(-m-1/2) == psi(1/2) + r - // where r == ((-1/2)^(-1) + ... + (-m-1/2)^(-1)) - numeric recur(0); - for (numeric p(nx); p<0; ++p) - recur -= pow(p, _num_1()); - return recur+psi(_ex1_2()); - } - } - // psi1_evalf should be called here once it becomes available - } - - return psi(x).hold(); + if (x.info(info_flags::numeric)) { + numeric nx = ex_to_numeric(x); + if (nx.is_integer()) { + // integer case + if (nx.is_positive()) { + // psi(n) -> 1 + 1/2 +...+ 1/(n-1) - Euler + numeric rat(0); + for (numeric i(nx+_num_1()); i.is_positive(); --i) + rat += i.inverse(); + return rat-Euler; + } else { + // for non-positive integers there is a pole: + throw (pole_error("psi_eval(): simple pole",1)); + } + } + if ((_num2()*nx).is_integer()) { + // half integer case + if (nx.is_positive()) { + // psi((2m+1)/2) -> 2/(2m+1) + 2/2m +...+ 2/1 - Euler - 2log(2) + numeric rat(0); + for (numeric i((nx+_num_1())*_num2()); i.is_positive(); i-=_num2()) + rat += _num2()*i.inverse(); + return rat-Euler-_ex2()*log(_ex2()); + } else { + // use the recurrence relation + // psi(-m-1/2) == psi(-m-1/2+1) - 1 / (-m-1/2) + // to relate psi(-m-1/2) to psi(1/2): + // psi(-m-1/2) == psi(1/2) + r + // where r == ((-1/2)^(-1) + ... + (-m-1/2)^(-1)) + numeric recur(0); + for (numeric p(nx); p<0; ++p) + recur -= pow(p, _num_1()); + return recur+psi(_ex1_2()); + } + } + // psi1_evalf should be called here once it becomes available + } + + return psi(x).hold(); } static ex psi1_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(deriv_param==0); - - // d/dx psi(x) -> psi(1,x) - return psi(_ex1(), x); + GINAC_ASSERT(deriv_param==0); + + // d/dx psi(x) -> psi(1,x) + return psi(_ex1(), x); } static ex psi1_series(const ex & arg, - const relational & rel, - int order, - unsigned options) + const relational & rel, + int order, + unsigned options) { - // method: - // Taylor series where there is no pole falls back to polygamma function - // evaluation. - // On a pole at -m use the recurrence relation - // psi(x) == psi(x+1) - 1/z - // from which follows - // series(psi(x),x==-m,order) == - // series(psi(x+m+1) - 1/x - 1/(x+1) - 1/(x+m)),x==-m,order); - const ex arg_pt = arg.subs(rel); - if (!arg_pt.info(info_flags::integer) || arg_pt.info(info_flags::positive)) - throw do_taylor(); // caught by function::series() - // if we got here we have to care for a simple pole at -m: - numeric m = -ex_to_numeric(arg_pt); - ex recur; - for (numeric p; p<=m; ++p) - recur += power(arg+p,_ex_1()); - return (psi(arg+m+_ex1())-recur).series(rel, order, options); + // method: + // Taylor series where there is no pole falls back to polygamma function + // evaluation. + // On a pole at -m use the recurrence relation + // psi(x) == psi(x+1) - 1/z + // from which follows + // series(psi(x),x==-m,order) == + // series(psi(x+m+1) - 1/x - 1/(x+1) - 1/(x+m)),x==-m,order); + const ex arg_pt = arg.subs(rel); + if (!arg_pt.info(info_flags::integer) || arg_pt.info(info_flags::positive)) + throw do_taylor(); // caught by function::series() + // if we got here we have to care for a simple pole at -m: + numeric m = -ex_to_numeric(arg_pt); + ex recur; + for (numeric p; p<=m; ++p) + recur += power(arg+p,_ex_1()); + return (psi(arg+m+_ex1())-recur).series(rel, order, options); } const unsigned function_index_psi1 = - function::register_new(function_options("psi"). - eval_func(psi1_eval). - evalf_func(psi1_evalf). + function::register_new(function_options("psi"). + eval_func(psi1_eval). + evalf_func(psi1_evalf). derivative_func(psi1_deriv). series_func(psi1_series). overloaded(2)); @@ -427,123 +427,123 @@ const unsigned function_index_psi1 = static ex psi2_evalf(const ex & n, const ex & x) { - BEGIN_TYPECHECK - TYPECHECK(n,numeric) - TYPECHECK(x,numeric) - END_TYPECHECK(psi(n,x)) - - return psi(ex_to_numeric(n), ex_to_numeric(x)); + BEGIN_TYPECHECK + TYPECHECK(n,numeric) + TYPECHECK(x,numeric) + END_TYPECHECK(psi(n,x)) + + return psi(ex_to_numeric(n), ex_to_numeric(x)); } /** Evaluation of polygamma-function psi(n,x). * Somebody ought to provide some good numerical evaluation some day... */ static ex psi2_eval(const ex & n, const ex & x) { - // psi(0,x) -> psi(x) - if (n.is_zero()) - return psi(x); - // psi(-1,x) -> log(tgamma(x)) - if (n.is_equal(_ex_1())) - return log(tgamma(x)); - if (n.info(info_flags::numeric) && n.info(info_flags::posint) && - x.info(info_flags::numeric)) { - numeric nn = ex_to_numeric(n); - numeric nx = ex_to_numeric(x); - if (nx.is_integer()) { - // integer case - if (nx.is_equal(_num1())) - // use psi(n,1) == (-)^(n+1) * n! * zeta(n+1) - return pow(_num_1(),nn+_num1())*factorial(nn)*zeta(ex(nn+_num1())); - if (nx.is_positive()) { - // use the recurrence relation - // psi(n,m) == psi(n,m+1) - (-)^n * n! / m^(n+1) - // to relate psi(n,m) to psi(n,1): - // psi(n,m) == psi(n,1) + r - // where r == (-)^n * n! * (1^(-n-1) + ... + (m-1)^(-n-1)) - numeric recur(0); - for (numeric p(1); p psi(x) + if (n.is_zero()) + return psi(x); + // psi(-1,x) -> log(tgamma(x)) + if (n.is_equal(_ex_1())) + return log(tgamma(x)); + if (n.info(info_flags::numeric) && n.info(info_flags::posint) && + x.info(info_flags::numeric)) { + numeric nn = ex_to_numeric(n); + numeric nx = ex_to_numeric(x); + if (nx.is_integer()) { + // integer case + if (nx.is_equal(_num1())) + // use psi(n,1) == (-)^(n+1) * n! * zeta(n+1) + return pow(_num_1(),nn+_num1())*factorial(nn)*zeta(ex(nn+_num1())); + if (nx.is_positive()) { + // use the recurrence relation + // psi(n,m) == psi(n,m+1) - (-)^n * n! / m^(n+1) + // to relate psi(n,m) to psi(n,1): + // psi(n,m) == psi(n,1) + r + // where r == (-)^n * n! * (1^(-n-1) + ... + (m-1)^(-n-1)) + numeric recur(0); + for (numeric p(1); p psi(n+1,x) - return psi(n+_ex1(), x); + GINAC_ASSERT(deriv_param<2); + + if (deriv_param==0) { + // d/dn psi(n,x) + throw(std::logic_error("cannot diff psi(n,x) with respect to n")); + } + // d/dx psi(n,x) -> psi(n+1,x) + return psi(n+_ex1(), x); } static ex psi2_series(const ex & n, - const ex & arg, - const relational & rel, - int order, - unsigned options) + const ex & arg, + const relational & rel, + int order, + unsigned options) { - // method: - // Taylor series where there is no pole falls back to polygamma function - // evaluation. - // On a pole at -m use the recurrence relation - // psi(n,x) == psi(n,x+1) - (-)^n * n! / x^(n+1) - // from which follows - // series(psi(x),x==-m,order) == - // series(psi(x+m+1) - (-1)^n * n! * ((x)^(-n-1) + (x+1)^(-n-1) + ... - // ... + (x+m)^(-n-1))),x==-m,order); - const ex arg_pt = arg.subs(rel); - if (!arg_pt.info(info_flags::integer) || arg_pt.info(info_flags::positive)) - throw do_taylor(); // caught by function::series() - // if we got here we have to care for a pole of order n+1 at -m: - numeric m = -ex_to_numeric(arg_pt); - ex recur; - for (numeric p; p<=m; ++p) - recur += power(arg+p,-n+_ex_1()); - recur *= factorial(n)*power(_ex_1(),n); - return (psi(n, arg+m+_ex1())-recur).series(rel, order, options); + // method: + // Taylor series where there is no pole falls back to polygamma function + // evaluation. + // On a pole at -m use the recurrence relation + // psi(n,x) == psi(n,x+1) - (-)^n * n! / x^(n+1) + // from which follows + // series(psi(x),x==-m,order) == + // series(psi(x+m+1) - (-1)^n * n! * ((x)^(-n-1) + (x+1)^(-n-1) + ... + // ... + (x+m)^(-n-1))),x==-m,order); + const ex arg_pt = arg.subs(rel); + if (!arg_pt.info(info_flags::integer) || arg_pt.info(info_flags::positive)) + throw do_taylor(); // caught by function::series() + // if we got here we have to care for a pole of order n+1 at -m: + numeric m = -ex_to_numeric(arg_pt); + ex recur; + for (numeric p; p<=m; ++p) + recur += power(arg+p,-n+_ex_1()); + recur *= factorial(n)*power(_ex_1(),n); + return (psi(n, arg+m+_ex1())-recur).series(rel, order, options); } const unsigned function_index_psi2 = - function::register_new(function_options("psi"). - eval_func(psi2_eval). - evalf_func(psi2_evalf). - derivative_func(psi2_deriv). + function::register_new(function_options("psi"). + eval_func(psi2_eval). + evalf_func(psi2_evalf). + derivative_func(psi2_deriv). series_func(psi2_series). overloaded(2)); diff --git a/ginac/inifcns_trans.cpp b/ginac/inifcns_trans.cpp index 8341651c..ac0bc323 100644 --- a/ginac/inifcns_trans.cpp +++ b/ginac/inifcns_trans.cpp @@ -44,54 +44,54 @@ namespace GiNaC { static ex exp_evalf(const ex & x) { - BEGIN_TYPECHECK - TYPECHECK(x,numeric) - END_TYPECHECK(exp(x)) - - return exp(ex_to_numeric(x)); // -> numeric exp(numeric) + BEGIN_TYPECHECK + TYPECHECK(x,numeric) + END_TYPECHECK(exp(x)) + + return exp(ex_to_numeric(x)); // -> numeric exp(numeric) } static ex exp_eval(const ex & x) { - // exp(0) -> 1 - if (x.is_zero()) { - return _ex1(); - } - // exp(n*Pi*I/2) -> {+1|+I|-1|-I} - ex TwoExOverPiI=(_ex2()*x)/(Pi*I); - if (TwoExOverPiI.info(info_flags::integer)) { - numeric z=mod(ex_to_numeric(TwoExOverPiI),_num4()); - if (z.is_equal(_num0())) - return _ex1(); - if (z.is_equal(_num1())) - return ex(I); - if (z.is_equal(_num2())) - return _ex_1(); - if (z.is_equal(_num3())) - return ex(-I); - } - // exp(log(x)) -> x - if (is_ex_the_function(x, log)) - return x.op(0); - - // exp(float) - if (x.info(info_flags::numeric) && !x.info(info_flags::crational)) - return exp_evalf(x); - - return exp(x).hold(); + // exp(0) -> 1 + if (x.is_zero()) { + return _ex1(); + } + // exp(n*Pi*I/2) -> {+1|+I|-1|-I} + ex TwoExOverPiI=(_ex2()*x)/(Pi*I); + if (TwoExOverPiI.info(info_flags::integer)) { + numeric z=mod(ex_to_numeric(TwoExOverPiI),_num4()); + if (z.is_equal(_num0())) + return _ex1(); + if (z.is_equal(_num1())) + return ex(I); + if (z.is_equal(_num2())) + return _ex_1(); + if (z.is_equal(_num3())) + return ex(-I); + } + // exp(log(x)) -> x + if (is_ex_the_function(x, log)) + return x.op(0); + + // exp(float) + if (x.info(info_flags::numeric) && !x.info(info_flags::crational)) + return exp_evalf(x); + + return exp(x).hold(); } static ex exp_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(deriv_param==0); + GINAC_ASSERT(deriv_param==0); - // d/dx exp(x) -> exp(x) - return exp(x); + // d/dx exp(x) -> exp(x) + return exp(x); } REGISTER_FUNCTION(exp, eval_func(exp_eval). - evalf_func(exp_evalf). - derivative_func(exp_deriv)); + evalf_func(exp_evalf). + derivative_func(exp_deriv)); ////////// // natural logarithm @@ -99,112 +99,112 @@ REGISTER_FUNCTION(exp, eval_func(exp_eval). static ex log_evalf(const ex & x) { - BEGIN_TYPECHECK - TYPECHECK(x,numeric) - END_TYPECHECK(log(x)) - - return log(ex_to_numeric(x)); // -> numeric log(numeric) + BEGIN_TYPECHECK + TYPECHECK(x,numeric) + END_TYPECHECK(log(x)) + + return log(ex_to_numeric(x)); // -> numeric log(numeric) } static ex log_eval(const ex & x) { - if (x.info(info_flags::numeric)) { - if (x.is_equal(_ex0())) // log(0) -> infinity - throw(pole_error("log_eval(): log(0)",0)); - if (x.info(info_flags::real) && x.info(info_flags::negative)) - return (log(-x)+I*Pi); - if (x.is_equal(_ex1())) // log(1) -> 0 - return _ex0(); - if (x.is_equal(I)) // log(I) -> Pi*I/2 - return (Pi*I*_num1_2()); - if (x.is_equal(-I)) // log(-I) -> -Pi*I/2 - return (Pi*I*_num_1_2()); - // log(float) - if (!x.info(info_flags::crational)) - return log_evalf(x); - } - // log(exp(t)) -> t (if -Pi < t.imag() <= Pi): - if (is_ex_the_function(x, exp)) { - ex t = x.op(0); - if (t.info(info_flags::numeric)) { - numeric nt = ex_to_numeric(t); - if (nt.is_real()) - return t; - } - } - - return log(x).hold(); + if (x.info(info_flags::numeric)) { + if (x.is_equal(_ex0())) // log(0) -> infinity + throw(pole_error("log_eval(): log(0)",0)); + if (x.info(info_flags::real) && x.info(info_flags::negative)) + return (log(-x)+I*Pi); + if (x.is_equal(_ex1())) // log(1) -> 0 + return _ex0(); + if (x.is_equal(I)) // log(I) -> Pi*I/2 + return (Pi*I*_num1_2()); + if (x.is_equal(-I)) // log(-I) -> -Pi*I/2 + return (Pi*I*_num_1_2()); + // log(float) + if (!x.info(info_flags::crational)) + return log_evalf(x); + } + // log(exp(t)) -> t (if -Pi < t.imag() <= Pi): + if (is_ex_the_function(x, exp)) { + ex t = x.op(0); + if (t.info(info_flags::numeric)) { + numeric nt = ex_to_numeric(t); + if (nt.is_real()) + return t; + } + } + + return log(x).hold(); } static ex log_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(deriv_param==0); - - // d/dx log(x) -> 1/x - return power(x, _ex_1()); + GINAC_ASSERT(deriv_param==0); + + // d/dx log(x) -> 1/x + return power(x, _ex_1()); } static ex log_series(const ex &arg, - const relational &rel, - int order, - unsigned options) -{ - GINAC_ASSERT(is_ex_exactly_of_type(rel.lhs(),symbol)); - ex arg_pt; - bool must_expand_arg = false; - // maybe substitution of rel into arg fails because of a pole - try { - arg_pt = arg.subs(rel); - } catch (pole_error) { - must_expand_arg = true; - } - // or we are at the branch cut anyways - if (arg_pt.is_zero()) - must_expand_arg = true; - - if (must_expand_arg) { - // method: - // This is the branch point: Series expand the argument first, then - // trivially factorize it to isolate that part which has constant - // leading coefficient in this fashion: - // x^n + Order(x^(n+m)) -> x^n * (1 + Order(x^m)). - // Return a plain n*log(x) for the x^n part and series expand the - // other part. Add them together and reexpand again in order to have - // one unnested pseries object. All this also works for negative n. - const pseries argser = ex_to_pseries(arg.series(rel, order, options)); - const symbol *s = static_cast(rel.lhs().bp); - const ex point = rel.rhs(); - const int n = argser.ldegree(*s); - epvector seq; - seq.push_back(expair(n*log(*s-point), _ex0())); - if (!argser.is_terminating() || argser.nops()!=1) { - // in this case n more terms are needed - ex newarg = ex_to_pseries(arg.series(rel, order+n, options)).shift_exponents(-n).convert_to_poly(true); - return pseries(rel, seq).add_series(ex_to_pseries(log(newarg).series(rel, order, options))); - } else // it was a monomial - return pseries(rel, seq); - } - if (!(options & series_options::suppress_branchcut) && - arg_pt.info(info_flags::negative)) { - // method: - // This is the branch cut: assemble the primitive series manually and - // then add the corresponding complex step function. - const symbol *s = static_cast(rel.lhs().bp); - const ex point = rel.rhs(); - const symbol foo; - ex replarg = series(log(arg), *s==foo, order, false).subs(foo==point); - epvector seq; - seq.push_back(expair(-I*csgn(arg*I)*Pi, _ex0())); - seq.push_back(expair(Order(_ex1()), order)); - return series(replarg - I*Pi + pseries(rel, seq), rel, order); - } - throw do_taylor(); // caught by function::series() + const relational &rel, + int order, + unsigned options) +{ + GINAC_ASSERT(is_ex_exactly_of_type(rel.lhs(),symbol)); + ex arg_pt; + bool must_expand_arg = false; + // maybe substitution of rel into arg fails because of a pole + try { + arg_pt = arg.subs(rel); + } catch (pole_error) { + must_expand_arg = true; + } + // or we are at the branch cut anyways + if (arg_pt.is_zero()) + must_expand_arg = true; + + if (must_expand_arg) { + // method: + // This is the branch point: Series expand the argument first, then + // trivially factorize it to isolate that part which has constant + // leading coefficient in this fashion: + // x^n + Order(x^(n+m)) -> x^n * (1 + Order(x^m)). + // Return a plain n*log(x) for the x^n part and series expand the + // other part. Add them together and reexpand again in order to have + // one unnested pseries object. All this also works for negative n. + const pseries argser = ex_to_pseries(arg.series(rel, order, options)); + const symbol *s = static_cast(rel.lhs().bp); + const ex point = rel.rhs(); + const int n = argser.ldegree(*s); + epvector seq; + seq.push_back(expair(n*log(*s-point), _ex0())); + if (!argser.is_terminating() || argser.nops()!=1) { + // in this case n more terms are needed + ex newarg = ex_to_pseries(arg.series(rel, order+n, options)).shift_exponents(-n).convert_to_poly(true); + return pseries(rel, seq).add_series(ex_to_pseries(log(newarg).series(rel, order, options))); + } else // it was a monomial + return pseries(rel, seq); + } + if (!(options & series_options::suppress_branchcut) && + arg_pt.info(info_flags::negative)) { + // method: + // This is the branch cut: assemble the primitive series manually and + // then add the corresponding complex step function. + const symbol *s = static_cast(rel.lhs().bp); + const ex point = rel.rhs(); + const symbol foo; + ex replarg = series(log(arg), *s==foo, order, false).subs(foo==point); + epvector seq; + seq.push_back(expair(-I*csgn(arg*I)*Pi, _ex0())); + seq.push_back(expair(Order(_ex1()), order)); + return series(replarg - I*Pi + pseries(rel, seq), rel, order); + } + throw do_taylor(); // caught by function::series() } REGISTER_FUNCTION(log, eval_func(log_eval). - evalf_func(log_evalf). - derivative_func(log_deriv). - series_func(log_series)); + evalf_func(log_evalf). + derivative_func(log_deriv). + series_func(log_series)); ////////// // sine (trigonometric function) @@ -212,80 +212,80 @@ REGISTER_FUNCTION(log, eval_func(log_eval). static ex sin_evalf(const ex & x) { - BEGIN_TYPECHECK - TYPECHECK(x,numeric) - END_TYPECHECK(sin(x)) - - return sin(ex_to_numeric(x)); // -> numeric sin(numeric) + BEGIN_TYPECHECK + TYPECHECK(x,numeric) + END_TYPECHECK(sin(x)) + + return sin(ex_to_numeric(x)); // -> numeric sin(numeric) } static ex sin_eval(const ex & x) { - // sin(n/d*Pi) -> { all known non-nested radicals } - ex SixtyExOverPi = _ex60()*x/Pi; - ex sign = _ex1(); - if (SixtyExOverPi.info(info_flags::integer)) { - numeric z = mod(ex_to_numeric(SixtyExOverPi),_num120()); - if (z>=_num60()) { - // wrap to interval [0, Pi) - z -= _num60(); - sign = _ex_1(); - } - if (z>_num30()) { - // wrap to interval [0, Pi/2) - z = _num60()-z; - } - if (z.is_equal(_num0())) // sin(0) -> 0 - return _ex0(); - if (z.is_equal(_num5())) // sin(Pi/12) -> sqrt(6)/4*(1-sqrt(3)/3) - return sign*_ex1_4()*power(_ex6(),_ex1_2())*(_ex1()+_ex_1_3()*power(_ex3(),_ex1_2())); - if (z.is_equal(_num6())) // sin(Pi/10) -> sqrt(5)/4-1/4 - return sign*(_ex1_4()*power(_ex5(),_ex1_2())+_ex_1_4()); - if (z.is_equal(_num10())) // sin(Pi/6) -> 1/2 - return sign*_ex1_2(); - if (z.is_equal(_num15())) // sin(Pi/4) -> sqrt(2)/2 - return sign*_ex1_2()*power(_ex2(),_ex1_2()); - if (z.is_equal(_num18())) // sin(3/10*Pi) -> sqrt(5)/4+1/4 - return sign*(_ex1_4()*power(_ex5(),_ex1_2())+_ex1_4()); - if (z.is_equal(_num20())) // sin(Pi/3) -> sqrt(3)/2 - return sign*_ex1_2()*power(_ex3(),_ex1_2()); - if (z.is_equal(_num25())) // sin(5/12*Pi) -> sqrt(6)/4*(1+sqrt(3)/3) - return sign*_ex1_4()*power(_ex6(),_ex1_2())*(_ex1()+_ex1_3()*power(_ex3(),_ex1_2())); - if (z.is_equal(_num30())) // sin(Pi/2) -> 1 - return sign*_ex1(); - } - - if (is_ex_exactly_of_type(x, function)) { - ex t = x.op(0); - // sin(asin(x)) -> x - if (is_ex_the_function(x, asin)) - return t; - // sin(acos(x)) -> sqrt(1-x^2) - if (is_ex_the_function(x, acos)) - return power(_ex1()-power(t,_ex2()),_ex1_2()); - // sin(atan(x)) -> x*(1+x^2)^(-1/2) - if (is_ex_the_function(x, atan)) - return t*power(_ex1()+power(t,_ex2()),_ex_1_2()); - } - - // sin(float) -> float - if (x.info(info_flags::numeric) && !x.info(info_flags::crational)) - return sin_evalf(x); - - return sin(x).hold(); + // sin(n/d*Pi) -> { all known non-nested radicals } + ex SixtyExOverPi = _ex60()*x/Pi; + ex sign = _ex1(); + if (SixtyExOverPi.info(info_flags::integer)) { + numeric z = mod(ex_to_numeric(SixtyExOverPi),_num120()); + if (z>=_num60()) { + // wrap to interval [0, Pi) + z -= _num60(); + sign = _ex_1(); + } + if (z>_num30()) { + // wrap to interval [0, Pi/2) + z = _num60()-z; + } + if (z.is_equal(_num0())) // sin(0) -> 0 + return _ex0(); + if (z.is_equal(_num5())) // sin(Pi/12) -> sqrt(6)/4*(1-sqrt(3)/3) + return sign*_ex1_4()*power(_ex6(),_ex1_2())*(_ex1()+_ex_1_3()*power(_ex3(),_ex1_2())); + if (z.is_equal(_num6())) // sin(Pi/10) -> sqrt(5)/4-1/4 + return sign*(_ex1_4()*power(_ex5(),_ex1_2())+_ex_1_4()); + if (z.is_equal(_num10())) // sin(Pi/6) -> 1/2 + return sign*_ex1_2(); + if (z.is_equal(_num15())) // sin(Pi/4) -> sqrt(2)/2 + return sign*_ex1_2()*power(_ex2(),_ex1_2()); + if (z.is_equal(_num18())) // sin(3/10*Pi) -> sqrt(5)/4+1/4 + return sign*(_ex1_4()*power(_ex5(),_ex1_2())+_ex1_4()); + if (z.is_equal(_num20())) // sin(Pi/3) -> sqrt(3)/2 + return sign*_ex1_2()*power(_ex3(),_ex1_2()); + if (z.is_equal(_num25())) // sin(5/12*Pi) -> sqrt(6)/4*(1+sqrt(3)/3) + return sign*_ex1_4()*power(_ex6(),_ex1_2())*(_ex1()+_ex1_3()*power(_ex3(),_ex1_2())); + if (z.is_equal(_num30())) // sin(Pi/2) -> 1 + return sign*_ex1(); + } + + if (is_ex_exactly_of_type(x, function)) { + ex t = x.op(0); + // sin(asin(x)) -> x + if (is_ex_the_function(x, asin)) + return t; + // sin(acos(x)) -> sqrt(1-x^2) + if (is_ex_the_function(x, acos)) + return power(_ex1()-power(t,_ex2()),_ex1_2()); + // sin(atan(x)) -> x*(1+x^2)^(-1/2) + if (is_ex_the_function(x, atan)) + return t*power(_ex1()+power(t,_ex2()),_ex_1_2()); + } + + // sin(float) -> float + if (x.info(info_flags::numeric) && !x.info(info_flags::crational)) + return sin_evalf(x); + + return sin(x).hold(); } static ex sin_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(deriv_param==0); - - // d/dx sin(x) -> cos(x) - return cos(x); + GINAC_ASSERT(deriv_param==0); + + // d/dx sin(x) -> cos(x) + return cos(x); } REGISTER_FUNCTION(sin, eval_func(sin_eval). - evalf_func(sin_evalf). - derivative_func(sin_deriv)); + evalf_func(sin_evalf). + derivative_func(sin_deriv)); ////////// // cosine (trigonometric function) @@ -293,80 +293,80 @@ REGISTER_FUNCTION(sin, eval_func(sin_eval). static ex cos_evalf(const ex & x) { - BEGIN_TYPECHECK - TYPECHECK(x,numeric) - END_TYPECHECK(cos(x)) - - return cos(ex_to_numeric(x)); // -> numeric cos(numeric) + BEGIN_TYPECHECK + TYPECHECK(x,numeric) + END_TYPECHECK(cos(x)) + + return cos(ex_to_numeric(x)); // -> numeric cos(numeric) } static ex cos_eval(const ex & x) { - // cos(n/d*Pi) -> { all known non-nested radicals } - ex SixtyExOverPi = _ex60()*x/Pi; - ex sign = _ex1(); - if (SixtyExOverPi.info(info_flags::integer)) { - numeric z = mod(ex_to_numeric(SixtyExOverPi),_num120()); - if (z>=_num60()) { - // wrap to interval [0, Pi) - z = _num120()-z; - } - if (z>=_num30()) { - // wrap to interval [0, Pi/2) - z = _num60()-z; - sign = _ex_1(); - } - if (z.is_equal(_num0())) // cos(0) -> 1 - return sign*_ex1(); - if (z.is_equal(_num5())) // cos(Pi/12) -> sqrt(6)/4*(1+sqrt(3)/3) - return sign*_ex1_4()*power(_ex6(),_ex1_2())*(_ex1()+_ex1_3()*power(_ex3(),_ex1_2())); - if (z.is_equal(_num10())) // cos(Pi/6) -> sqrt(3)/2 - return sign*_ex1_2()*power(_ex3(),_ex1_2()); - if (z.is_equal(_num12())) // cos(Pi/5) -> sqrt(5)/4+1/4 - return sign*(_ex1_4()*power(_ex5(),_ex1_2())+_ex1_4()); - if (z.is_equal(_num15())) // cos(Pi/4) -> sqrt(2)/2 - return sign*_ex1_2()*power(_ex2(),_ex1_2()); - if (z.is_equal(_num20())) // cos(Pi/3) -> 1/2 - return sign*_ex1_2(); - if (z.is_equal(_num24())) // cos(2/5*Pi) -> sqrt(5)/4-1/4x - return sign*(_ex1_4()*power(_ex5(),_ex1_2())+_ex_1_4()); - if (z.is_equal(_num25())) // cos(5/12*Pi) -> sqrt(6)/4*(1-sqrt(3)/3) - return sign*_ex1_4()*power(_ex6(),_ex1_2())*(_ex1()+_ex_1_3()*power(_ex3(),_ex1_2())); - if (z.is_equal(_num30())) // cos(Pi/2) -> 0 - return sign*_ex0(); - } - - if (is_ex_exactly_of_type(x, function)) { - ex t = x.op(0); - // cos(acos(x)) -> x - if (is_ex_the_function(x, acos)) - return t; - // cos(asin(x)) -> (1-x^2)^(1/2) - if (is_ex_the_function(x, asin)) - return power(_ex1()-power(t,_ex2()),_ex1_2()); - // cos(atan(x)) -> (1+x^2)^(-1/2) - if (is_ex_the_function(x, atan)) - return power(_ex1()+power(t,_ex2()),_ex_1_2()); - } - - // cos(float) -> float - if (x.info(info_flags::numeric) && !x.info(info_flags::crational)) - return cos_evalf(x); - - return cos(x).hold(); + // cos(n/d*Pi) -> { all known non-nested radicals } + ex SixtyExOverPi = _ex60()*x/Pi; + ex sign = _ex1(); + if (SixtyExOverPi.info(info_flags::integer)) { + numeric z = mod(ex_to_numeric(SixtyExOverPi),_num120()); + if (z>=_num60()) { + // wrap to interval [0, Pi) + z = _num120()-z; + } + if (z>=_num30()) { + // wrap to interval [0, Pi/2) + z = _num60()-z; + sign = _ex_1(); + } + if (z.is_equal(_num0())) // cos(0) -> 1 + return sign*_ex1(); + if (z.is_equal(_num5())) // cos(Pi/12) -> sqrt(6)/4*(1+sqrt(3)/3) + return sign*_ex1_4()*power(_ex6(),_ex1_2())*(_ex1()+_ex1_3()*power(_ex3(),_ex1_2())); + if (z.is_equal(_num10())) // cos(Pi/6) -> sqrt(3)/2 + return sign*_ex1_2()*power(_ex3(),_ex1_2()); + if (z.is_equal(_num12())) // cos(Pi/5) -> sqrt(5)/4+1/4 + return sign*(_ex1_4()*power(_ex5(),_ex1_2())+_ex1_4()); + if (z.is_equal(_num15())) // cos(Pi/4) -> sqrt(2)/2 + return sign*_ex1_2()*power(_ex2(),_ex1_2()); + if (z.is_equal(_num20())) // cos(Pi/3) -> 1/2 + return sign*_ex1_2(); + if (z.is_equal(_num24())) // cos(2/5*Pi) -> sqrt(5)/4-1/4x + return sign*(_ex1_4()*power(_ex5(),_ex1_2())+_ex_1_4()); + if (z.is_equal(_num25())) // cos(5/12*Pi) -> sqrt(6)/4*(1-sqrt(3)/3) + return sign*_ex1_4()*power(_ex6(),_ex1_2())*(_ex1()+_ex_1_3()*power(_ex3(),_ex1_2())); + if (z.is_equal(_num30())) // cos(Pi/2) -> 0 + return sign*_ex0(); + } + + if (is_ex_exactly_of_type(x, function)) { + ex t = x.op(0); + // cos(acos(x)) -> x + if (is_ex_the_function(x, acos)) + return t; + // cos(asin(x)) -> (1-x^2)^(1/2) + if (is_ex_the_function(x, asin)) + return power(_ex1()-power(t,_ex2()),_ex1_2()); + // cos(atan(x)) -> (1+x^2)^(-1/2) + if (is_ex_the_function(x, atan)) + return power(_ex1()+power(t,_ex2()),_ex_1_2()); + } + + // cos(float) -> float + if (x.info(info_flags::numeric) && !x.info(info_flags::crational)) + return cos_evalf(x); + + return cos(x).hold(); } static ex cos_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(deriv_param==0); + GINAC_ASSERT(deriv_param==0); - // d/dx cos(x) -> -sin(x) - return _ex_1()*sin(x); + // d/dx cos(x) -> -sin(x) + return _ex_1()*sin(x); } REGISTER_FUNCTION(cos, eval_func(cos_eval). - evalf_func(cos_evalf). - derivative_func(cos_deriv)); + evalf_func(cos_evalf). + derivative_func(cos_deriv)); ////////// // tangent (trigonometric function) @@ -374,93 +374,93 @@ REGISTER_FUNCTION(cos, eval_func(cos_eval). static ex tan_evalf(const ex & x) { - BEGIN_TYPECHECK - TYPECHECK(x,numeric) - END_TYPECHECK(tan(x)) // -> numeric tan(numeric) - - return tan(ex_to_numeric(x)); + BEGIN_TYPECHECK + TYPECHECK(x,numeric) + END_TYPECHECK(tan(x)) // -> numeric tan(numeric) + + return tan(ex_to_numeric(x)); } static ex tan_eval(const ex & x) { - // tan(n/d*Pi) -> { all known non-nested radicals } - ex SixtyExOverPi = _ex60()*x/Pi; - ex sign = _ex1(); - if (SixtyExOverPi.info(info_flags::integer)) { - numeric z = mod(ex_to_numeric(SixtyExOverPi),_num60()); - if (z>=_num60()) { - // wrap to interval [0, Pi) - z -= _num60(); - } - if (z>=_num30()) { - // wrap to interval [0, Pi/2) - z = _num60()-z; - sign = _ex_1(); - } - if (z.is_equal(_num0())) // tan(0) -> 0 - return _ex0(); - if (z.is_equal(_num5())) // tan(Pi/12) -> 2-sqrt(3) - return sign*(_ex2()-power(_ex3(),_ex1_2())); - if (z.is_equal(_num10())) // tan(Pi/6) -> sqrt(3)/3 - return sign*_ex1_3()*power(_ex3(),_ex1_2()); - if (z.is_equal(_num15())) // tan(Pi/4) -> 1 - return sign*_ex1(); - if (z.is_equal(_num20())) // tan(Pi/3) -> sqrt(3) - return sign*power(_ex3(),_ex1_2()); - if (z.is_equal(_num25())) // tan(5/12*Pi) -> 2+sqrt(3) - return sign*(power(_ex3(),_ex1_2())+_ex2()); - if (z.is_equal(_num30())) // tan(Pi/2) -> infinity - throw (pole_error("tan_eval(): simple pole",1)); - } - - if (is_ex_exactly_of_type(x, function)) { - ex t = x.op(0); - // tan(atan(x)) -> x - if (is_ex_the_function(x, atan)) - return t; - // tan(asin(x)) -> x*(1+x^2)^(-1/2) - if (is_ex_the_function(x, asin)) - return t*power(_ex1()-power(t,_ex2()),_ex_1_2()); - // tan(acos(x)) -> (1-x^2)^(1/2)/x - if (is_ex_the_function(x, acos)) - return power(t,_ex_1())*power(_ex1()-power(t,_ex2()),_ex1_2()); - } - - // tan(float) -> float - if (x.info(info_flags::numeric) && !x.info(info_flags::crational)) { - return tan_evalf(x); - } - - return tan(x).hold(); + // tan(n/d*Pi) -> { all known non-nested radicals } + ex SixtyExOverPi = _ex60()*x/Pi; + ex sign = _ex1(); + if (SixtyExOverPi.info(info_flags::integer)) { + numeric z = mod(ex_to_numeric(SixtyExOverPi),_num60()); + if (z>=_num60()) { + // wrap to interval [0, Pi) + z -= _num60(); + } + if (z>=_num30()) { + // wrap to interval [0, Pi/2) + z = _num60()-z; + sign = _ex_1(); + } + if (z.is_equal(_num0())) // tan(0) -> 0 + return _ex0(); + if (z.is_equal(_num5())) // tan(Pi/12) -> 2-sqrt(3) + return sign*(_ex2()-power(_ex3(),_ex1_2())); + if (z.is_equal(_num10())) // tan(Pi/6) -> sqrt(3)/3 + return sign*_ex1_3()*power(_ex3(),_ex1_2()); + if (z.is_equal(_num15())) // tan(Pi/4) -> 1 + return sign*_ex1(); + if (z.is_equal(_num20())) // tan(Pi/3) -> sqrt(3) + return sign*power(_ex3(),_ex1_2()); + if (z.is_equal(_num25())) // tan(5/12*Pi) -> 2+sqrt(3) + return sign*(power(_ex3(),_ex1_2())+_ex2()); + if (z.is_equal(_num30())) // tan(Pi/2) -> infinity + throw (pole_error("tan_eval(): simple pole",1)); + } + + if (is_ex_exactly_of_type(x, function)) { + ex t = x.op(0); + // tan(atan(x)) -> x + if (is_ex_the_function(x, atan)) + return t; + // tan(asin(x)) -> x*(1+x^2)^(-1/2) + if (is_ex_the_function(x, asin)) + return t*power(_ex1()-power(t,_ex2()),_ex_1_2()); + // tan(acos(x)) -> (1-x^2)^(1/2)/x + if (is_ex_the_function(x, acos)) + return power(t,_ex_1())*power(_ex1()-power(t,_ex2()),_ex1_2()); + } + + // tan(float) -> float + if (x.info(info_flags::numeric) && !x.info(info_flags::crational)) { + return tan_evalf(x); + } + + return tan(x).hold(); } static ex tan_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(deriv_param==0); - - // d/dx tan(x) -> 1+tan(x)^2; - return (_ex1()+power(tan(x),_ex2())); + GINAC_ASSERT(deriv_param==0); + + // d/dx tan(x) -> 1+tan(x)^2; + return (_ex1()+power(tan(x),_ex2())); } static ex tan_series(const ex &x, - const relational &rel, - int order, - unsigned options) + const relational &rel, + int order, + unsigned options) { - // method: - // Taylor series where there is no pole falls back to tan_deriv. - // On a pole simply expand sin(x)/cos(x). - const ex x_pt = x.subs(rel); - if (!(2*x_pt/Pi).info(info_flags::odd)) - throw do_taylor(); // caught by function::series() - // if we got here we have to care for a simple pole - return (sin(x)/cos(x)).series(rel, order+2); + // method: + // Taylor series where there is no pole falls back to tan_deriv. + // On a pole simply expand sin(x)/cos(x). + const ex x_pt = x.subs(rel); + if (!(2*x_pt/Pi).info(info_flags::odd)) + throw do_taylor(); // caught by function::series() + // if we got here we have to care for a simple pole + return (sin(x)/cos(x)).series(rel, order+2); } REGISTER_FUNCTION(tan, eval_func(tan_eval). - evalf_func(tan_evalf). - derivative_func(tan_deriv). - series_func(tan_series)); + evalf_func(tan_evalf). + derivative_func(tan_deriv). + series_func(tan_series)); ////////// // inverse sine (arc sine) @@ -468,50 +468,50 @@ REGISTER_FUNCTION(tan, eval_func(tan_eval). static ex asin_evalf(const ex & x) { - BEGIN_TYPECHECK - TYPECHECK(x,numeric) - END_TYPECHECK(asin(x)) - - return asin(ex_to_numeric(x)); // -> numeric asin(numeric) + BEGIN_TYPECHECK + TYPECHECK(x,numeric) + END_TYPECHECK(asin(x)) + + return asin(ex_to_numeric(x)); // -> numeric asin(numeric) } static ex asin_eval(const ex & x) { - if (x.info(info_flags::numeric)) { - // asin(0) -> 0 - if (x.is_zero()) - return x; - // asin(1/2) -> Pi/6 - if (x.is_equal(_ex1_2())) - return numeric(1,6)*Pi; - // asin(1) -> Pi/2 - if (x.is_equal(_ex1())) - return _num1_2()*Pi; - // asin(-1/2) -> -Pi/6 - if (x.is_equal(_ex_1_2())) - return numeric(-1,6)*Pi; - // asin(-1) -> -Pi/2 - if (x.is_equal(_ex_1())) - return _num_1_2()*Pi; - // asin(float) -> float - if (!x.info(info_flags::crational)) - return asin_evalf(x); - } - - return asin(x).hold(); + if (x.info(info_flags::numeric)) { + // asin(0) -> 0 + if (x.is_zero()) + return x; + // asin(1/2) -> Pi/6 + if (x.is_equal(_ex1_2())) + return numeric(1,6)*Pi; + // asin(1) -> Pi/2 + if (x.is_equal(_ex1())) + return _num1_2()*Pi; + // asin(-1/2) -> -Pi/6 + if (x.is_equal(_ex_1_2())) + return numeric(-1,6)*Pi; + // asin(-1) -> -Pi/2 + if (x.is_equal(_ex_1())) + return _num_1_2()*Pi; + // asin(float) -> float + if (!x.info(info_flags::crational)) + return asin_evalf(x); + } + + return asin(x).hold(); } static ex asin_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(deriv_param==0); - - // d/dx asin(x) -> 1/sqrt(1-x^2) - return power(1-power(x,_ex2()),_ex_1_2()); + GINAC_ASSERT(deriv_param==0); + + // d/dx asin(x) -> 1/sqrt(1-x^2) + return power(1-power(x,_ex2()),_ex_1_2()); } REGISTER_FUNCTION(asin, eval_func(asin_eval). - evalf_func(asin_evalf). - derivative_func(asin_deriv)); + evalf_func(asin_evalf). + derivative_func(asin_deriv)); ////////// // inverse cosine (arc cosine) @@ -519,50 +519,50 @@ REGISTER_FUNCTION(asin, eval_func(asin_eval). static ex acos_evalf(const ex & x) { - BEGIN_TYPECHECK - TYPECHECK(x,numeric) - END_TYPECHECK(acos(x)) - - return acos(ex_to_numeric(x)); // -> numeric acos(numeric) + BEGIN_TYPECHECK + TYPECHECK(x,numeric) + END_TYPECHECK(acos(x)) + + return acos(ex_to_numeric(x)); // -> numeric acos(numeric) } static ex acos_eval(const ex & x) { - if (x.info(info_flags::numeric)) { - // acos(1) -> 0 - if (x.is_equal(_ex1())) - return _ex0(); - // acos(1/2) -> Pi/3 - if (x.is_equal(_ex1_2())) - return _ex1_3()*Pi; - // acos(0) -> Pi/2 - if (x.is_zero()) - return _ex1_2()*Pi; - // acos(-1/2) -> 2/3*Pi - if (x.is_equal(_ex_1_2())) - return numeric(2,3)*Pi; - // acos(-1) -> Pi - if (x.is_equal(_ex_1())) - return Pi; - // acos(float) -> float - if (!x.info(info_flags::crational)) - return acos_evalf(x); - } - - return acos(x).hold(); + if (x.info(info_flags::numeric)) { + // acos(1) -> 0 + if (x.is_equal(_ex1())) + return _ex0(); + // acos(1/2) -> Pi/3 + if (x.is_equal(_ex1_2())) + return _ex1_3()*Pi; + // acos(0) -> Pi/2 + if (x.is_zero()) + return _ex1_2()*Pi; + // acos(-1/2) -> 2/3*Pi + if (x.is_equal(_ex_1_2())) + return numeric(2,3)*Pi; + // acos(-1) -> Pi + if (x.is_equal(_ex_1())) + return Pi; + // acos(float) -> float + if (!x.info(info_flags::crational)) + return acos_evalf(x); + } + + return acos(x).hold(); } static ex acos_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(deriv_param==0); - - // d/dx acos(x) -> -1/sqrt(1-x^2) - return _ex_1()*power(1-power(x,_ex2()),_ex_1_2()); + GINAC_ASSERT(deriv_param==0); + + // d/dx acos(x) -> -1/sqrt(1-x^2) + return _ex_1()*power(1-power(x,_ex2()),_ex_1_2()); } REGISTER_FUNCTION(acos, eval_func(acos_eval). - evalf_func(acos_evalf). - derivative_func(acos_deriv)); + evalf_func(acos_evalf). + derivative_func(acos_deriv)); ////////// // inverse tangent (arc tangent) @@ -570,38 +570,38 @@ REGISTER_FUNCTION(acos, eval_func(acos_eval). static ex atan_evalf(const ex & x) { - BEGIN_TYPECHECK - TYPECHECK(x,numeric) - END_TYPECHECK(atan(x)) - - return atan(ex_to_numeric(x)); // -> numeric atan(numeric) + BEGIN_TYPECHECK + TYPECHECK(x,numeric) + END_TYPECHECK(atan(x)) + + return atan(ex_to_numeric(x)); // -> numeric atan(numeric) } static ex atan_eval(const ex & x) { - if (x.info(info_flags::numeric)) { - // atan(0) -> 0 - if (x.is_equal(_ex0())) - return _ex0(); - // atan(float) -> float - if (!x.info(info_flags::crational)) - return atan_evalf(x); - } - - return atan(x).hold(); + if (x.info(info_flags::numeric)) { + // atan(0) -> 0 + if (x.is_equal(_ex0())) + return _ex0(); + // atan(float) -> float + if (!x.info(info_flags::crational)) + return atan_evalf(x); + } + + return atan(x).hold(); } static ex atan_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(deriv_param==0); + GINAC_ASSERT(deriv_param==0); - // d/dx atan(x) -> 1/(1+x^2) - return power(_ex1()+power(x,_ex2()), _ex_1()); + // d/dx atan(x) -> 1/(1+x^2) + return power(_ex1()+power(x,_ex2()), _ex_1()); } REGISTER_FUNCTION(atan, eval_func(atan_eval). - evalf_func(atan_evalf). - derivative_func(atan_deriv)); + evalf_func(atan_evalf). + derivative_func(atan_deriv)); ////////// // inverse tangent (atan2(y,x)) @@ -609,39 +609,39 @@ REGISTER_FUNCTION(atan, eval_func(atan_eval). static ex atan2_evalf(const ex & y, const ex & x) { - BEGIN_TYPECHECK - TYPECHECK(y,numeric) - TYPECHECK(x,numeric) - END_TYPECHECK(atan2(y,x)) - - return atan(ex_to_numeric(y),ex_to_numeric(x)); // -> numeric atan(numeric) + BEGIN_TYPECHECK + TYPECHECK(y,numeric) + TYPECHECK(x,numeric) + END_TYPECHECK(atan2(y,x)) + + return atan(ex_to_numeric(y),ex_to_numeric(x)); // -> numeric atan(numeric) } static ex atan2_eval(const ex & y, const ex & x) { - if (y.info(info_flags::numeric) && !y.info(info_flags::crational) && - x.info(info_flags::numeric) && !x.info(info_flags::crational)) { - return atan2_evalf(y,x); - } - - return atan2(y,x).hold(); + if (y.info(info_flags::numeric) && !y.info(info_flags::crational) && + x.info(info_flags::numeric) && !x.info(info_flags::crational)) { + return atan2_evalf(y,x); + } + + return atan2(y,x).hold(); } static ex atan2_deriv(const ex & y, const ex & x, unsigned deriv_param) { - GINAC_ASSERT(deriv_param<2); - - if (deriv_param==0) { - // d/dy atan(y,x) - return x*power(power(x,_ex2())+power(y,_ex2()),_ex_1()); - } - // d/dx atan(y,x) - return -y*power(power(x,_ex2())+power(y,_ex2()),_ex_1()); + GINAC_ASSERT(deriv_param<2); + + if (deriv_param==0) { + // d/dy atan(y,x) + return x*power(power(x,_ex2())+power(y,_ex2()),_ex_1()); + } + // d/dx atan(y,x) + return -y*power(power(x,_ex2())+power(y,_ex2()),_ex_1()); } REGISTER_FUNCTION(atan2, eval_func(atan2_eval). - evalf_func(atan2_evalf). - derivative_func(atan2_deriv)); + evalf_func(atan2_evalf). + derivative_func(atan2_deriv)); ////////// // hyperbolic sine (trigonometric function) @@ -649,53 +649,53 @@ REGISTER_FUNCTION(atan2, eval_func(atan2_eval). static ex sinh_evalf(const ex & x) { - BEGIN_TYPECHECK - TYPECHECK(x,numeric) - END_TYPECHECK(sinh(x)) - - return sinh(ex_to_numeric(x)); // -> numeric sinh(numeric) + BEGIN_TYPECHECK + TYPECHECK(x,numeric) + END_TYPECHECK(sinh(x)) + + return sinh(ex_to_numeric(x)); // -> numeric sinh(numeric) } static ex sinh_eval(const ex & x) { - if (x.info(info_flags::numeric)) { - if (x.is_zero()) // sinh(0) -> 0 - return _ex0(); - if (!x.info(info_flags::crational)) // sinh(float) -> float - return sinh_evalf(x); - } - - if ((x/Pi).info(info_flags::numeric) && - ex_to_numeric(x/Pi).real().is_zero()) // sinh(I*x) -> I*sin(x) - return I*sin(x/I); - - if (is_ex_exactly_of_type(x, function)) { - ex t = x.op(0); - // sinh(asinh(x)) -> x - if (is_ex_the_function(x, asinh)) - return t; - // sinh(acosh(x)) -> (x-1)^(1/2) * (x+1)^(1/2) - if (is_ex_the_function(x, acosh)) - return power(t-_ex1(),_ex1_2())*power(t+_ex1(),_ex1_2()); - // sinh(atanh(x)) -> x*(1-x^2)^(-1/2) - if (is_ex_the_function(x, atanh)) - return t*power(_ex1()-power(t,_ex2()),_ex_1_2()); - } - - return sinh(x).hold(); + if (x.info(info_flags::numeric)) { + if (x.is_zero()) // sinh(0) -> 0 + return _ex0(); + if (!x.info(info_flags::crational)) // sinh(float) -> float + return sinh_evalf(x); + } + + if ((x/Pi).info(info_flags::numeric) && + ex_to_numeric(x/Pi).real().is_zero()) // sinh(I*x) -> I*sin(x) + return I*sin(x/I); + + if (is_ex_exactly_of_type(x, function)) { + ex t = x.op(0); + // sinh(asinh(x)) -> x + if (is_ex_the_function(x, asinh)) + return t; + // sinh(acosh(x)) -> (x-1)^(1/2) * (x+1)^(1/2) + if (is_ex_the_function(x, acosh)) + return power(t-_ex1(),_ex1_2())*power(t+_ex1(),_ex1_2()); + // sinh(atanh(x)) -> x*(1-x^2)^(-1/2) + if (is_ex_the_function(x, atanh)) + return t*power(_ex1()-power(t,_ex2()),_ex_1_2()); + } + + return sinh(x).hold(); } static ex sinh_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(deriv_param==0); - - // d/dx sinh(x) -> cosh(x) - return cosh(x); + GINAC_ASSERT(deriv_param==0); + + // d/dx sinh(x) -> cosh(x) + return cosh(x); } REGISTER_FUNCTION(sinh, eval_func(sinh_eval). - evalf_func(sinh_evalf). - derivative_func(sinh_deriv)); + evalf_func(sinh_evalf). + derivative_func(sinh_deriv)); ////////// // hyperbolic cosine (trigonometric function) @@ -703,53 +703,53 @@ REGISTER_FUNCTION(sinh, eval_func(sinh_eval). static ex cosh_evalf(const ex & x) { - BEGIN_TYPECHECK - TYPECHECK(x,numeric) - END_TYPECHECK(cosh(x)) - - return cosh(ex_to_numeric(x)); // -> numeric cosh(numeric) + BEGIN_TYPECHECK + TYPECHECK(x,numeric) + END_TYPECHECK(cosh(x)) + + return cosh(ex_to_numeric(x)); // -> numeric cosh(numeric) } static ex cosh_eval(const ex & x) { - if (x.info(info_flags::numeric)) { - if (x.is_zero()) // cosh(0) -> 1 - return _ex1(); - if (!x.info(info_flags::crational)) // cosh(float) -> float - return cosh_evalf(x); - } - - if ((x/Pi).info(info_flags::numeric) && - ex_to_numeric(x/Pi).real().is_zero()) // cosh(I*x) -> cos(x) - return cos(x/I); - - if (is_ex_exactly_of_type(x, function)) { - ex t = x.op(0); - // cosh(acosh(x)) -> x - if (is_ex_the_function(x, acosh)) - return t; - // cosh(asinh(x)) -> (1+x^2)^(1/2) - if (is_ex_the_function(x, asinh)) - return power(_ex1()+power(t,_ex2()),_ex1_2()); - // cosh(atanh(x)) -> (1-x^2)^(-1/2) - if (is_ex_the_function(x, atanh)) - return power(_ex1()-power(t,_ex2()),_ex_1_2()); - } - - return cosh(x).hold(); + if (x.info(info_flags::numeric)) { + if (x.is_zero()) // cosh(0) -> 1 + return _ex1(); + if (!x.info(info_flags::crational)) // cosh(float) -> float + return cosh_evalf(x); + } + + if ((x/Pi).info(info_flags::numeric) && + ex_to_numeric(x/Pi).real().is_zero()) // cosh(I*x) -> cos(x) + return cos(x/I); + + if (is_ex_exactly_of_type(x, function)) { + ex t = x.op(0); + // cosh(acosh(x)) -> x + if (is_ex_the_function(x, acosh)) + return t; + // cosh(asinh(x)) -> (1+x^2)^(1/2) + if (is_ex_the_function(x, asinh)) + return power(_ex1()+power(t,_ex2()),_ex1_2()); + // cosh(atanh(x)) -> (1-x^2)^(-1/2) + if (is_ex_the_function(x, atanh)) + return power(_ex1()-power(t,_ex2()),_ex_1_2()); + } + + return cosh(x).hold(); } static ex cosh_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(deriv_param==0); - - // d/dx cosh(x) -> sinh(x) - return sinh(x); + GINAC_ASSERT(deriv_param==0); + + // d/dx cosh(x) -> sinh(x) + return sinh(x); } REGISTER_FUNCTION(cosh, eval_func(cosh_eval). - evalf_func(cosh_evalf). - derivative_func(cosh_deriv)); + evalf_func(cosh_evalf). + derivative_func(cosh_deriv)); ////////// @@ -758,69 +758,69 @@ REGISTER_FUNCTION(cosh, eval_func(cosh_eval). static ex tanh_evalf(const ex & x) { - BEGIN_TYPECHECK - TYPECHECK(x,numeric) - END_TYPECHECK(tanh(x)) - - return tanh(ex_to_numeric(x)); // -> numeric tanh(numeric) + BEGIN_TYPECHECK + TYPECHECK(x,numeric) + END_TYPECHECK(tanh(x)) + + return tanh(ex_to_numeric(x)); // -> numeric tanh(numeric) } static ex tanh_eval(const ex & x) { - if (x.info(info_flags::numeric)) { - if (x.is_zero()) // tanh(0) -> 0 - return _ex0(); - if (!x.info(info_flags::crational)) // tanh(float) -> float - return tanh_evalf(x); - } - - if ((x/Pi).info(info_flags::numeric) && - ex_to_numeric(x/Pi).real().is_zero()) // tanh(I*x) -> I*tan(x); - return I*tan(x/I); - - if (is_ex_exactly_of_type(x, function)) { - ex t = x.op(0); - // tanh(atanh(x)) -> x - if (is_ex_the_function(x, atanh)) - return t; - // tanh(asinh(x)) -> x*(1+x^2)^(-1/2) - if (is_ex_the_function(x, asinh)) - return t*power(_ex1()+power(t,_ex2()),_ex_1_2()); - // tanh(acosh(x)) -> (x-1)^(1/2)*(x+1)^(1/2)/x - if (is_ex_the_function(x, acosh)) - return power(t-_ex1(),_ex1_2())*power(t+_ex1(),_ex1_2())*power(t,_ex_1()); - } - - return tanh(x).hold(); + if (x.info(info_flags::numeric)) { + if (x.is_zero()) // tanh(0) -> 0 + return _ex0(); + if (!x.info(info_flags::crational)) // tanh(float) -> float + return tanh_evalf(x); + } + + if ((x/Pi).info(info_flags::numeric) && + ex_to_numeric(x/Pi).real().is_zero()) // tanh(I*x) -> I*tan(x); + return I*tan(x/I); + + if (is_ex_exactly_of_type(x, function)) { + ex t = x.op(0); + // tanh(atanh(x)) -> x + if (is_ex_the_function(x, atanh)) + return t; + // tanh(asinh(x)) -> x*(1+x^2)^(-1/2) + if (is_ex_the_function(x, asinh)) + return t*power(_ex1()+power(t,_ex2()),_ex_1_2()); + // tanh(acosh(x)) -> (x-1)^(1/2)*(x+1)^(1/2)/x + if (is_ex_the_function(x, acosh)) + return power(t-_ex1(),_ex1_2())*power(t+_ex1(),_ex1_2())*power(t,_ex_1()); + } + + return tanh(x).hold(); } static ex tanh_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(deriv_param==0); - - // d/dx tanh(x) -> 1-tanh(x)^2 - return _ex1()-power(tanh(x),_ex2()); + GINAC_ASSERT(deriv_param==0); + + // d/dx tanh(x) -> 1-tanh(x)^2 + return _ex1()-power(tanh(x),_ex2()); } static ex tanh_series(const ex &x, - const relational &rel, - int order, - unsigned options) + const relational &rel, + int order, + unsigned options) { - // method: - // Taylor series where there is no pole falls back to tanh_deriv. - // On a pole simply expand sinh(x)/cosh(x). - const ex x_pt = x.subs(rel); - if (!(2*I*x_pt/Pi).info(info_flags::odd)) - throw do_taylor(); // caught by function::series() - // if we got here we have to care for a simple pole - return (sinh(x)/cosh(x)).series(rel, order+2); + // method: + // Taylor series where there is no pole falls back to tanh_deriv. + // On a pole simply expand sinh(x)/cosh(x). + const ex x_pt = x.subs(rel); + if (!(2*I*x_pt/Pi).info(info_flags::odd)) + throw do_taylor(); // caught by function::series() + // if we got here we have to care for a simple pole + return (sinh(x)/cosh(x)).series(rel, order+2); } REGISTER_FUNCTION(tanh, eval_func(tanh_eval). - evalf_func(tanh_evalf). - derivative_func(tanh_deriv). - series_func(tanh_series)); + evalf_func(tanh_evalf). + derivative_func(tanh_deriv). + series_func(tanh_series)); ////////// // inverse hyperbolic sine (trigonometric function) @@ -828,38 +828,38 @@ REGISTER_FUNCTION(tanh, eval_func(tanh_eval). static ex asinh_evalf(const ex & x) { - BEGIN_TYPECHECK - TYPECHECK(x,numeric) - END_TYPECHECK(asinh(x)) - - return asinh(ex_to_numeric(x)); // -> numeric asinh(numeric) + BEGIN_TYPECHECK + TYPECHECK(x,numeric) + END_TYPECHECK(asinh(x)) + + return asinh(ex_to_numeric(x)); // -> numeric asinh(numeric) } static ex asinh_eval(const ex & x) { - if (x.info(info_flags::numeric)) { - // asinh(0) -> 0 - if (x.is_zero()) - return _ex0(); - // asinh(float) -> float - if (!x.info(info_flags::crational)) - return asinh_evalf(x); - } - - return asinh(x).hold(); + if (x.info(info_flags::numeric)) { + // asinh(0) -> 0 + if (x.is_zero()) + return _ex0(); + // asinh(float) -> float + if (!x.info(info_flags::crational)) + return asinh_evalf(x); + } + + return asinh(x).hold(); } static ex asinh_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(deriv_param==0); - - // d/dx asinh(x) -> 1/sqrt(1+x^2) - return power(_ex1()+power(x,_ex2()),_ex_1_2()); + GINAC_ASSERT(deriv_param==0); + + // d/dx asinh(x) -> 1/sqrt(1+x^2) + return power(_ex1()+power(x,_ex2()),_ex_1_2()); } REGISTER_FUNCTION(asinh, eval_func(asinh_eval). - evalf_func(asinh_evalf). - derivative_func(asinh_deriv)); + evalf_func(asinh_evalf). + derivative_func(asinh_deriv)); ////////// // inverse hyperbolic cosine (trigonometric function) @@ -867,44 +867,44 @@ REGISTER_FUNCTION(asinh, eval_func(asinh_eval). static ex acosh_evalf(const ex & x) { - BEGIN_TYPECHECK - TYPECHECK(x,numeric) - END_TYPECHECK(acosh(x)) - - return acosh(ex_to_numeric(x)); // -> numeric acosh(numeric) + BEGIN_TYPECHECK + TYPECHECK(x,numeric) + END_TYPECHECK(acosh(x)) + + return acosh(ex_to_numeric(x)); // -> numeric acosh(numeric) } static ex acosh_eval(const ex & x) { - if (x.info(info_flags::numeric)) { - // acosh(0) -> Pi*I/2 - if (x.is_zero()) - return Pi*I*numeric(1,2); - // acosh(1) -> 0 - if (x.is_equal(_ex1())) - return _ex0(); - // acosh(-1) -> Pi*I - if (x.is_equal(_ex_1())) - return Pi*I; - // acosh(float) -> float - if (!x.info(info_flags::crational)) - return acosh_evalf(x); - } - - return acosh(x).hold(); + if (x.info(info_flags::numeric)) { + // acosh(0) -> Pi*I/2 + if (x.is_zero()) + return Pi*I*numeric(1,2); + // acosh(1) -> 0 + if (x.is_equal(_ex1())) + return _ex0(); + // acosh(-1) -> Pi*I + if (x.is_equal(_ex_1())) + return Pi*I; + // acosh(float) -> float + if (!x.info(info_flags::crational)) + return acosh_evalf(x); + } + + return acosh(x).hold(); } static ex acosh_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(deriv_param==0); - - // d/dx acosh(x) -> 1/(sqrt(x-1)*sqrt(x+1)) - return power(x+_ex_1(),_ex_1_2())*power(x+_ex1(),_ex_1_2()); + GINAC_ASSERT(deriv_param==0); + + // d/dx acosh(x) -> 1/(sqrt(x-1)*sqrt(x+1)) + return power(x+_ex_1(),_ex_1_2())*power(x+_ex1(),_ex_1_2()); } REGISTER_FUNCTION(acosh, eval_func(acosh_eval). - evalf_func(acosh_evalf). - derivative_func(acosh_deriv)); + evalf_func(acosh_evalf). + derivative_func(acosh_deriv)); ////////// // inverse hyperbolic tangent (trigonometric function) @@ -912,41 +912,41 @@ REGISTER_FUNCTION(acosh, eval_func(acosh_eval). static ex atanh_evalf(const ex & x) { - BEGIN_TYPECHECK - TYPECHECK(x,numeric) - END_TYPECHECK(atanh(x)) - - return atanh(ex_to_numeric(x)); // -> numeric atanh(numeric) + BEGIN_TYPECHECK + TYPECHECK(x,numeric) + END_TYPECHECK(atanh(x)) + + return atanh(ex_to_numeric(x)); // -> numeric atanh(numeric) } static ex atanh_eval(const ex & x) { - if (x.info(info_flags::numeric)) { - // atanh(0) -> 0 - if (x.is_zero()) - return _ex0(); - // atanh({+|-}1) -> throw - if (x.is_equal(_ex1()) || x.is_equal(_ex_1())) - throw (pole_error("atanh_eval(): logarithmic pole",0)); - // atanh(float) -> float - if (!x.info(info_flags::crational)) - return atanh_evalf(x); - } - - return atanh(x).hold(); + if (x.info(info_flags::numeric)) { + // atanh(0) -> 0 + if (x.is_zero()) + return _ex0(); + // atanh({+|-}1) -> throw + if (x.is_equal(_ex1()) || x.is_equal(_ex_1())) + throw (pole_error("atanh_eval(): logarithmic pole",0)); + // atanh(float) -> float + if (!x.info(info_flags::crational)) + return atanh_evalf(x); + } + + return atanh(x).hold(); } static ex atanh_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(deriv_param==0); - - // d/dx atanh(x) -> 1/(1-x^2) - return power(_ex1()-power(x,_ex2()),_ex_1()); + GINAC_ASSERT(deriv_param==0); + + // d/dx atanh(x) -> 1/(1-x^2) + return power(_ex1()-power(x,_ex2()),_ex_1()); } REGISTER_FUNCTION(atanh, eval_func(atanh_eval). - evalf_func(atanh_evalf). - derivative_func(atanh_deriv)); + evalf_func(atanh_evalf). + derivative_func(atanh_deriv)); #ifndef NO_NAMESPACE_GINAC } // namespace GiNaC diff --git a/ginac/inifcns_zeta.cpp b/ginac/inifcns_zeta.cpp index 7a8b089a..a20e534f 100644 --- a/ginac/inifcns_zeta.cpp +++ b/ginac/inifcns_zeta.cpp @@ -41,50 +41,50 @@ namespace GiNaC { static ex zeta1_evalf(const ex & x) { - BEGIN_TYPECHECK - TYPECHECK(x,numeric) - END_TYPECHECK(zeta(x)) - - return zeta(ex_to_numeric(x)); + BEGIN_TYPECHECK + TYPECHECK(x,numeric) + END_TYPECHECK(zeta(x)) + + return zeta(ex_to_numeric(x)); } static ex zeta1_eval(const ex & x) { - if (x.info(info_flags::numeric)) { - numeric y = ex_to_numeric(x); - // trap integer arguments: - if (y.is_integer()) { - if (y.is_zero()) - return -_ex1_2(); - if (x.is_equal(_ex1())) - throw(std::domain_error("zeta(1): infinity")); - if (x.info(info_flags::posint)) { - if (x.info(info_flags::odd)) - return zeta(x).hold(); - else - return abs(bernoulli(y))*pow(Pi,x)*pow(_num2(),y-_num1())/factorial(y); - } else { - if (x.info(info_flags::odd)) - return -bernoulli(_num1()-y)/(_num1()-y); - else - return _num0(); - } - } - } - return zeta(x).hold(); + if (x.info(info_flags::numeric)) { + numeric y = ex_to_numeric(x); + // trap integer arguments: + if (y.is_integer()) { + if (y.is_zero()) + return -_ex1_2(); + if (x.is_equal(_ex1())) + throw(std::domain_error("zeta(1): infinity")); + if (x.info(info_flags::posint)) { + if (x.info(info_flags::odd)) + return zeta(x).hold(); + else + return abs(bernoulli(y))*pow(Pi,x)*pow(_num2(),y-_num1())/factorial(y); + } else { + if (x.info(info_flags::odd)) + return -bernoulli(_num1()-y)/(_num1()-y); + else + return _num0(); + } + } + } + return zeta(x).hold(); } static ex zeta1_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(deriv_param==0); - - return zeta(_ex1(), x); + GINAC_ASSERT(deriv_param==0); + + return zeta(_ex1(), x); } const unsigned function_index_zeta1 = - function::register_new(function_options("zeta"). - eval_func(zeta1_eval). - evalf_func(zeta1_evalf). + function::register_new(function_options("zeta"). + eval_func(zeta1_eval). + evalf_func(zeta1_evalf). derivative_func(zeta1_deriv). overloaded(2)); @@ -94,30 +94,30 @@ const unsigned function_index_zeta1 = static ex zeta2_eval(const ex & n, const ex & x) { - if (n.info(info_flags::numeric)) { - // zeta(0,x) -> zeta(x) - if (n.is_zero()) - return zeta(x); - } - - return zeta(n, x).hold(); + if (n.info(info_flags::numeric)) { + // zeta(0,x) -> zeta(x) + if (n.is_zero()) + return zeta(x); + } + + return zeta(n, x).hold(); } static ex zeta2_deriv(const ex & n, const ex & x, unsigned deriv_param) { - GINAC_ASSERT(deriv_param<2); - - if (deriv_param==0) { - // d/dn zeta(n,x) - throw(std::logic_error("cannot diff zeta(n,x) with respect to n")); - } - // d/dx psi(n,x) - return zeta(n+1,x); + GINAC_ASSERT(deriv_param<2); + + if (deriv_param==0) { + // d/dn zeta(n,x) + throw(std::logic_error("cannot diff zeta(n,x) with respect to n")); + } + // d/dx psi(n,x) + return zeta(n+1,x); } const unsigned function_index_zeta2 = - function::register_new(function_options("zeta"). - eval_func(zeta2_eval). + function::register_new(function_options("zeta"). + eval_func(zeta2_eval). derivative_func(zeta2_deriv). overloaded(2)); diff --git a/ginac/input_lexer.h b/ginac/input_lexer.h index a7c8c06f..4bb38f9e 100644 --- a/ginac/input_lexer.h +++ b/ginac/input_lexer.h @@ -27,7 +27,7 @@ extern "C" { #include } - + #include "config.h" // yacc stack type diff --git a/ginac/isospin.cpp b/ginac/isospin.cpp index 1afa969f..fafdaec0 100644 --- a/ginac/isospin.cpp +++ b/ginac/isospin.cpp @@ -45,48 +45,48 @@ GINAC_IMPLEMENT_REGISTERED_CLASS(isospin, indexed) isospin::isospin() { - debugmsg("isospin default constructor",LOGLEVEL_CONSTRUCT); - serial=next_serial++; - name=autoname_prefix()+ToString(serial); - tinfo_key=TINFO_isospin; + debugmsg("isospin default constructor",LOGLEVEL_CONSTRUCT); + serial=next_serial++; + name=autoname_prefix()+ToString(serial); + tinfo_key=TINFO_isospin; } isospin::~isospin() { - debugmsg("isospin destructor",LOGLEVEL_DESTRUCT); - destroy(0); + debugmsg("isospin destructor",LOGLEVEL_DESTRUCT); + destroy(0); } isospin::isospin(const isospin & other) { - debugmsg("isospin copy constructor",LOGLEVEL_CONSTRUCT); - copy (other); + debugmsg("isospin copy constructor",LOGLEVEL_CONSTRUCT); + copy (other); } const isospin & isospin::operator=(const isospin & other) { - debugmsg("isospin operator=",LOGLEVEL_ASSIGNMENT); - if (this != &other) { - destroy(1); - copy(other); - } - return *this; + debugmsg("isospin operator=",LOGLEVEL_ASSIGNMENT); + if (this != &other) { + destroy(1); + copy(other); + } + return *this; } // protected void isospin::copy(const isospin & other) { - inherited::copy(other); - name=other.name; - serial=other.serial; + inherited::copy(other); + name=other.name; + serial=other.serial; } void isospin::destroy(bool call_parent) { - if (call_parent) { - inherited::destroy(call_parent); - } + if (call_parent) { + inherited::destroy(call_parent); + } } ////////// @@ -97,10 +97,10 @@ void isospin::destroy(bool call_parent) isospin::isospin(const std::string & initname) { - debugmsg("isospin constructor from string",LOGLEVEL_CONSTRUCT); - name=initname; - serial=next_serial++; - tinfo_key=TINFO_isospin; + debugmsg("isospin constructor from string",LOGLEVEL_CONSTRUCT); + name=initname; + serial=next_serial++; + tinfo_key=TINFO_isospin; } ////////// @@ -110,31 +110,31 @@ isospin::isospin(const std::string & initname) /** Construct object from archive_node. */ isospin::isospin(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) { - debugmsg("isospin constructor from archive_node", LOGLEVEL_CONSTRUCT); - serial = next_serial++; - if (!(n.find_string("name", name))) - name = autoname_prefix() + ToString(serial); - tinfo_key = TINFO_isospin; + debugmsg("isospin constructor from archive_node", LOGLEVEL_CONSTRUCT); + serial = next_serial++; + if (!(n.find_string("name", name))) + name = autoname_prefix() + ToString(serial); + tinfo_key = TINFO_isospin; } /** Unarchive the object. */ ex isospin::unarchive(const archive_node &n, const lst &sym_lst) { - ex s = (new isospin(n, sym_lst))->setflag(status_flags::dynallocated); - - // If isospin is in sym_lst, return the existing isospin - for (unsigned i=0; isetflag(status_flags::dynallocated); + + // If isospin is in sym_lst, return the existing isospin + for (unsigned i=0; i(&other); - if (serial==o->serial) { - return inherited::compare_same_type(other); - } - return serial < o->serial ? -1 : 1; + GINAC_ASSERT(other.tinfo() == TINFO_isospin); + const isospin *o = static_cast(&other); + if (serial==o->serial) { + return inherited::compare_same_type(other); + } + return serial < o->serial ? -1 : 1; } ex isospin::simplify_ncmul(const exvector & v) const { - return simplified_ncmul(v); + return simplified_ncmul(v); } unsigned isospin::calchash(void) const { - hashvalue=golden_ratio_hash(golden_ratio_hash(0x55555556U ^ - golden_ratio_hash(tinfo_key) ^ - serial)); - setflag(status_flags::hash_calculated); - return hashvalue; + hashvalue=golden_ratio_hash(golden_ratio_hash(0x55555556U ^ + golden_ratio_hash(tinfo_key) ^ + serial)); + setflag(status_flags::hash_calculated); + return hashvalue; } ////////// @@ -226,15 +226,15 @@ unsigned isospin::calchash(void) const void isospin::setname(const std::string & n) { - name = n; + name = n; } // private std::string & isospin::autoname_prefix(void) { - static std::string * s = new std::string("isospin"); - return *s; + static std::string * s = new std::string("isospin"); + return *s; } ////////// diff --git a/ginac/isospin.h b/ginac/isospin.h index 8103fc1a..da77efa4 100644 --- a/ginac/isospin.h +++ b/ginac/isospin.h @@ -33,53 +33,53 @@ namespace GiNaC { /** Base class for isospin object */ class isospin : public indexed { - GINAC_DECLARE_REGISTERED_CLASS(isospin, indexed) + GINAC_DECLARE_REGISTERED_CLASS(isospin, indexed) // member functions - // default constructor, destructor, copy constructor assignment operator and helpers + // default constructor, destructor, copy constructor assignment operator and helpers public: - isospin(); - ~isospin(); - isospin(const isospin & other); - const isospin & operator=(const isospin & other); + isospin(); + ~isospin(); + isospin(const isospin & other); + const isospin & operator=(const isospin & other); protected: - void copy(const isospin & other); - void destroy(bool call_parent); + void copy(const isospin & other); + void destroy(bool call_parent); - // other constructors + // other constructors public: - explicit isospin(const std::string & initname); + explicit isospin(const std::string & initname); - // functions overriding virtual functions from base classes + // functions overriding virtual functions from base classes public: - basic * duplicate() const; - void printraw(std::ostream & os) const; - void printtree(std::ostream & os, unsigned indent) const; - void print(std::ostream & os, unsigned upper_precedence=0) const; - void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence=0) const; - bool info(unsigned inf) const; + basic * duplicate() const; + void printraw(std::ostream & os) const; + void printtree(std::ostream & os, unsigned indent) const; + void print(std::ostream & os, unsigned upper_precedence=0) const; + void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence=0) const; + bool info(unsigned inf) const; protected: - int compare_same_type(const basic & other) const; - ex simplify_ncmul(const exvector & v) const; - unsigned calchash(void) const; - - // new virtual functions which can be overridden by derived classes - // none - - // non-virtual functions in this class + int compare_same_type(const basic & other) const; + ex simplify_ncmul(const exvector & v) const; + unsigned calchash(void) const; + + // new virtual functions which can be overridden by derived classes + // none + + // non-virtual functions in this class public: - void setname(const std::string & n); + void setname(const std::string & n); private: - std::string & autoname_prefix(void); + std::string & autoname_prefix(void); // member variables protected: - std::string name; - unsigned serial; // unique serial number for comparision + std::string name; + unsigned serial; // unique serial number for comparision private: - static unsigned next_serial; + static unsigned next_serial; }; // global constants diff --git a/ginac/lorentzidx.cpp b/ginac/lorentzidx.cpp index 9a0aa7bd..d03d9b7a 100644 --- a/ginac/lorentzidx.cpp +++ b/ginac/lorentzidx.cpp @@ -42,46 +42,46 @@ GINAC_IMPLEMENT_REGISTERED_CLASS(lorentzidx, idx) lorentzidx::lorentzidx() : orthogonal_only(false), dim_parallel_space(0) { - debugmsg("lorentzidx default constructor",LOGLEVEL_CONSTRUCT); - // serial is incremented in idx::idx() - name="mu"+ToString(serial); - tinfo_key=TINFO_lorentzidx; + debugmsg("lorentzidx default constructor",LOGLEVEL_CONSTRUCT); + // serial is incremented in idx::idx() + name="mu"+ToString(serial); + tinfo_key=TINFO_lorentzidx; } lorentzidx::~lorentzidx() { - debugmsg("lorentzidx destructor",LOGLEVEL_DESTRUCT); - destroy(0); + debugmsg("lorentzidx destructor",LOGLEVEL_DESTRUCT); + destroy(0); } lorentzidx::lorentzidx(const lorentzidx & other) { - debugmsg("lorentzidx copy constructor",LOGLEVEL_CONSTRUCT); - copy(other); + debugmsg("lorentzidx copy constructor",LOGLEVEL_CONSTRUCT); + copy(other); } const lorentzidx & lorentzidx::operator=(const lorentzidx & other) { - debugmsg("lorentzidx operator=",LOGLEVEL_ASSIGNMENT); - if (this != &other) { - destroy(1); - copy(other); - } - return *this; + debugmsg("lorentzidx operator=",LOGLEVEL_ASSIGNMENT); + if (this != &other) { + destroy(1); + copy(other); + } + return *this; } // protected void lorentzidx::copy(const lorentzidx & other) { - inherited::copy(other); - orthogonal_only=other.orthogonal_only; - dim_parallel_space=other.dim_parallel_space; + inherited::copy(other); + orthogonal_only=other.orthogonal_only; + dim_parallel_space=other.dim_parallel_space; } void lorentzidx::destroy(bool call_parent) { - if (call_parent) inherited::destroy(call_parent); + if (call_parent) inherited::destroy(call_parent); } ////////// @@ -91,39 +91,39 @@ void lorentzidx::destroy(bool call_parent) // public lorentzidx::lorentzidx(bool cov, bool oonly, unsigned dimp) : - idx(cov), orthogonal_only(oonly), dim_parallel_space(dimp) + idx(cov), orthogonal_only(oonly), dim_parallel_space(dimp) { - debugmsg("lorentzidx constructor from bool",LOGLEVEL_CONSTRUCT); - // serial is incremented in idx::idx(bool) - if (oonly) { - name="muorth"+ToString(serial); - } else { - name="mu"+ToString(serial); - } - tinfo_key=TINFO_lorentzidx; + debugmsg("lorentzidx constructor from bool",LOGLEVEL_CONSTRUCT); + // serial is incremented in idx::idx(bool) + if (oonly) { + name="muorth"+ToString(serial); + } else { + name="mu"+ToString(serial); + } + tinfo_key=TINFO_lorentzidx; } lorentzidx::lorentzidx(const std::string & n, bool cov, bool oonly, unsigned dimp) - : idx(n,cov), orthogonal_only(oonly), dim_parallel_space(dimp) + : idx(n,cov), orthogonal_only(oonly), dim_parallel_space(dimp) { - debugmsg("lorentzidx constructor from string,bool,bool,unsigned", - LOGLEVEL_CONSTRUCT); - tinfo_key=TINFO_lorentzidx; + debugmsg("lorentzidx constructor from string,bool,bool,unsigned", + LOGLEVEL_CONSTRUCT); + tinfo_key=TINFO_lorentzidx; } lorentzidx::lorentzidx(const char * n, bool cov, bool oonly, unsigned dimp) - : idx(n,cov), orthogonal_only(oonly), dim_parallel_space(dimp) + : idx(n,cov), orthogonal_only(oonly), dim_parallel_space(dimp) { - debugmsg("lorentzidx constructor from char*,bool,bool,unsigned", - LOGLEVEL_CONSTRUCT); - tinfo_key=TINFO_lorentzidx; + debugmsg("lorentzidx constructor from char*,bool,bool,unsigned", + LOGLEVEL_CONSTRUCT); + tinfo_key=TINFO_lorentzidx; } lorentzidx::lorentzidx(unsigned v, bool cov) : idx(v,cov), - orthogonal_only(false), dim_parallel_space(0) + orthogonal_only(false), dim_parallel_space(0) { - debugmsg("lorentzidx constructor from unsigned,bool",LOGLEVEL_CONSTRUCT); - tinfo_key=TINFO_lorentzidx; + debugmsg("lorentzidx constructor from unsigned,bool",LOGLEVEL_CONSTRUCT); + tinfo_key=TINFO_lorentzidx; } ////////// @@ -133,8 +133,8 @@ lorentzidx::lorentzidx(unsigned v, bool cov) : idx(v,cov), /** Construct object from archive_node. */ lorentzidx::lorentzidx(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) { - debugmsg("lorentzidx constructor from archive_node", LOGLEVEL_CONSTRUCT); - n.find_bool("orthogonal_only", orthogonal_only); + debugmsg("lorentzidx constructor from archive_node", LOGLEVEL_CONSTRUCT); + n.find_bool("orthogonal_only", orthogonal_only); if (orthogonal_only) n.find_unsigned("pdim", dim_parallel_space); } @@ -142,22 +142,22 @@ lorentzidx::lorentzidx(const archive_node &n, const lst &sym_lst) : inherited(n, /** Unarchive the object. */ ex lorentzidx::unarchive(const archive_node &n, const lst &sym_lst) { - ex s = (new lorentzidx(n, sym_lst))->setflag(status_flags::dynallocated); - - if (ex_to_lorentzidx(s).symbolic) { - // If lorentzidx is in sym_lst, return the existing lorentzidx - for (unsigned i=0; isetflag(status_flags::dynallocated); + + if (ex_to_lorentzidx(s).symbolic) { + // If lorentzidx is in sym_lst, return the existing lorentzidx + for (unsigned i=0; i hold(); + if (type==lortensor_g) { + // canonicalize indices + exvector iv=seq; + int sig=canonicalize_indices(iv,false); //symmetric + if (sig!=INT_MAX) { + //something has changed while sorting indices, more evaluations later + return ex(sig) *lortensor(type,name,iv); + } + const lorentzidx & idx1=ex_to_lorentzidx(seq[0]); + const lorentzidx & idx2=ex_to_lorentzidx(seq[1]); + if ((!idx1.is_symbolic()) && (!idx2.is_symbolic())) { + //both indices are numeric + if ((idx1.get_value()==idx2.get_value())) { + //both on diagonal + if (idx1.get_value()==0){ + // (0,0) + return _ex1(); + } else { + if (idx1.is_covariant() != idx2.is_covariant()) { + // (_i,~i) or (~i,_i), i = 1...3 + return _ex1(); + } else { + // (_i,_i) or (~i,~i), i= 1...3 + return _ex_1(); + } + } + } else { + // at least one off-diagonal + return _ex0(); + } + } else if (idx1.is_symbolic() && idx1.is_co_contra_pair(idx2)) { + return Dim()-idx1.get_dim_parallel_space(); + } + } + return this -> hold(); } //protected int lortensor::compare_same_type(const basic & other) const { - GINAC_ASSERT(is_of_type(other,lortensor)); - const lortensor *o = static_cast (&other); - if (type==o->type) { - if (type==lortensor_rankn) { - if (serial!=o->serial) { - return serial < o->serial ? -1 : 1; - } - } - return indexed::compare_same_type(other); - } - return type < o->type ? -1 : 1; + GINAC_ASSERT(is_of_type(other,lortensor)); + const lortensor *o = static_cast (&other); + if (type==o->type) { + if (type==lortensor_rankn) { + if (serial!=o->serial) { + return serial < o->serial ? -1 : 1; + } + } + return indexed::compare_same_type(other); + } + return type < o->type ? -1 : 1; } bool lortensor::is_equal_same_type(const basic & other) const { - GINAC_ASSERT(is_of_type(other,lortensor)); - const lortensor *o=static_cast (&other); - if (type!=o->type) return false; - if (type==lortensor_rankn) { - if (serial!=o->serial) return false; - } - return indexed::is_equal_same_type(other); + GINAC_ASSERT(is_of_type(other,lortensor)); + const lortensor *o=static_cast (&other); + if (type!=o->type) return false; + if (type==lortensor_rankn) { + if (serial!=o->serial) return false; + } + return indexed::is_equal_same_type(other); } unsigned lortensor::return_type(void) const { - return return_types::commutative; + return return_types::commutative; } unsigned lortensor::return_type_tinfo(void) const { - return tinfo_key; + return tinfo_key; } ex lortensor::thisexprseq(const exvector & v) const { - return lortensor(type,name,serial,v); + return lortensor(type,name,serial,v); } ex lortensor::thisexprseq(exvector *vp) const { - return lortensor(type,name,serial,vp); + return lortensor(type,name,serial,vp); } - + ////////// // non-virtual functions in this class ////////// @@ -329,25 +329,25 @@ ex lortensor::thisexprseq(exvector *vp) const void lortensor::setname(const std::string & n) { - name = n; + name = n; } bool lortensor::all_of_type_lorentzidx(void) const { - for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++ cit) { - if (!is_ex_of_type(*cit,lorentzidx)) { - return false; - } - } - return true; + for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++ cit) { + if (!is_ex_of_type(*cit,lorentzidx)) { + return false; + } + } + return true; } // private std::string & lortensor::autoname_prefix(void) { - static std::string * s = new std::string("lortensor"); - return *s; + static std::string * s = new std::string("lortensor"); + return *s; } ////////// @@ -364,125 +364,125 @@ unsigned lortensor::next_serial=0; lortensor lortensor_g(const ex & mu, const ex & nu) { - return lortensor(lortensor::lortensor_g,"",mu,nu); + return lortensor(lortensor::lortensor_g,"",mu,nu); } lortensor lortensor_epsilon(const ex & mu, const ex & nu, const ex & rho, const ex & sigma) { - return lortensor(lortensor::lortensor_epsilon,"",mu,nu,rho,sigma); + return lortensor(lortensor::lortensor_epsilon,"",mu,nu,rho,sigma); } lortensor lortensor_rank1(const std::string & n, const ex & mu) { - return lortensor(lortensor::lortensor_rank1,n,mu); + return lortensor(lortensor::lortensor_rank1,n,mu); } lortensor lortensor_rank2(const std::string & n, const ex & mu, const ex & nu) { - return lortensor(lortensor::lortensor_rank2,n,mu,nu); + return lortensor(lortensor::lortensor_rank2,n,mu,nu); } ex simplify_lortensor_mul(const ex & m) { - GINAC_ASSERT(is_ex_exactly_of_type(m,mul)); - exvector v_contracted; - - // collect factors in an exvector, store squares twice - int n=m.nops(); - v_contracted.reserve(2*n); - for (int i=0; i(*e.bp); diff --git a/ginac/lst_suppl.cpp b/ginac/lst_suppl.cpp index 8e9d94ef..30699c47 100644 --- a/ginac/lst_suppl.cpp +++ b/ginac/lst_suppl.cpp @@ -29,8 +29,8 @@ namespace GiNaC { bool lst::info(unsigned inf) const { - if (inf==info_flags::list) return 1; - return basic::info(inf); + if (inf==info_flags::list) return 1; + return basic::info(inf); } #ifndef NO_NAMESPACE_GINAC diff --git a/ginac/matrix.cpp b/ginac/matrix.cpp index 6240ce20..470991b7 100644 --- a/ginac/matrix.cpp +++ b/ginac/matrix.cpp @@ -49,46 +49,46 @@ 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) + : inherited(TINFO_matrix), row(1), col(1) { - debugmsg("matrix default constructor",LOGLEVEL_CONSTRUCT); - m.push_back(_ex0()); + debugmsg("matrix default constructor",LOGLEVEL_CONSTRUCT); + m.push_back(_ex0()); } matrix::~matrix() { - debugmsg("matrix destructor",LOGLEVEL_DESTRUCT); + debugmsg("matrix destructor",LOGLEVEL_DESTRUCT); } matrix::matrix(const matrix & other) { - debugmsg("matrix copy constructor",LOGLEVEL_CONSTRUCT); - copy(other); + debugmsg("matrix copy constructor",LOGLEVEL_CONSTRUCT); + copy(other); } const matrix & matrix::operator=(const matrix & other) { - debugmsg("matrix operator=",LOGLEVEL_ASSIGNMENT); - if (this != &other) { - destroy(1); - copy(other); - } - return *this; + debugmsg("matrix operator=",LOGLEVEL_ASSIGNMENT); + if (this != &other) { + destroy(1); + copy(other); + } + return *this; } // protected void matrix::copy(const matrix & other) { - inherited::copy(other); - row = other.row; - col = other.col; - m = other.m; // STL's vector copying invoked here + inherited::copy(other); + row = other.row; + col = other.col; + m = other.m; // STL's vector copying invoked here } void matrix::destroy(bool call_parent) { - if (call_parent) inherited::destroy(call_parent); + if (call_parent) inherited::destroy(call_parent); } ////////// @@ -102,19 +102,19 @@ void matrix::destroy(bool call_parent) * @param r number of rows * @param c number of cols */ matrix::matrix(unsigned r, unsigned c) - : inherited(TINFO_matrix), row(r), col(c) + : inherited(TINFO_matrix), row(r), col(c) { - debugmsg("matrix constructor from unsigned,unsigned",LOGLEVEL_CONSTRUCT); - m.resize(r*c, _ex0()); + debugmsg("matrix constructor from unsigned,unsigned",LOGLEVEL_CONSTRUCT); + m.resize(r*c, _ex0()); } // protected /** Ctor from representation, for internal use only. */ matrix::matrix(unsigned r, unsigned c, const exvector & m2) - : inherited(TINFO_matrix), row(r), col(c), m(m2) + : inherited(TINFO_matrix), row(r), col(c), m(m2) { - debugmsg("matrix constructor from unsigned,unsigned,exvector",LOGLEVEL_CONSTRUCT); + debugmsg("matrix constructor from unsigned,unsigned,exvector",LOGLEVEL_CONSTRUCT); } ////////// @@ -124,36 +124,36 @@ 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); - if (!(n.find_unsigned("row", row)) || !(n.find_unsigned("col", col))) - throw (std::runtime_error("unknown matrix dimensions in archive")); - m.reserve(row * col); - for (unsigned int i=0; true; i++) { - ex e; - if (n.find_ex("m", e, sym_lst, i)) - m.push_back(e); - else - break; - } + debugmsg("matrix constructor 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); + for (unsigned int i=0; true; i++) { + ex e; + if (n.find_ex("m", e, sym_lst, i)) + m.push_back(e); + else + break; + } } /** Unarchive the object. */ ex matrix::unarchive(const archive_node &n, const lst &sym_lst) { - return (new matrix(n, sym_lst))->setflag(status_flags::dynallocated); + return (new matrix(n, sym_lst))->setflag(status_flags::dynallocated); } /** Archive the object. */ void matrix::archive(archive_node &n) const { - inherited::archive(n); - n.add_unsigned("row", row); - n.add_unsigned("col", col); - exvector::const_iterator i = m.begin(), iend = m.end(); - while (i != iend) { - n.add_ex("m", *i); - ++i; - } + inherited::archive(n); + n.add_unsigned("row", row); + n.add_unsigned("col", col); + exvector::const_iterator i = m.begin(), iend = m.end(); + while (i != iend) { + n.add_ex("m", *i); + ++i; + } } ////////// @@ -164,162 +164,162 @@ void matrix::archive(archive_node &n) const basic * matrix::duplicate() const { - debugmsg("matrix duplicate",LOGLEVEL_DUPLICATE); - return new matrix(*this); + debugmsg("matrix duplicate",LOGLEVEL_DUPLICATE); + return new matrix(*this); } void matrix::print(std::ostream & os, unsigned upper_precedence) const { - debugmsg("matrix print",LOGLEVEL_PRINT); - os << "[[ "; - for (unsigned r=0; r=0); - GINAC_ASSERT(i=0); + GINAC_ASSERT(isetflag(status_flags::dynallocated | - status_flags::evaluated ); + debugmsg("matrix eval",LOGLEVEL_MEMBER_FUNCTION); + + // check if we have to do anything at all + if ((level==1)&&(flags & status_flags::evaluated)) + return *this; + + // emergency break + if (level == -max_recursion_level) + throw (std::runtime_error("matrix::eval(): recursion limit exceeded")); + + // eval() entry by entry + exvector m2(row*col); + --level; + for (unsigned r=0; rsetflag(status_flags::dynallocated | + status_flags::evaluated ); } /** evaluate matrix numerically entry by entry. */ ex matrix::evalf(int level) const { - debugmsg("matrix evalf",LOGLEVEL_MEMBER_FUNCTION); - - // check if we have to do anything at all - if (level==1) - return *this; - - // emergency break - if (level == -max_recursion_level) { - throw (std::runtime_error("matrix::evalf(): recursion limit exceeded")); - } - - // evalf() entry by entry - exvector m2(row*col); - --level; - for (unsigned r=0; r(const_cast(other)); - - // compare number of rows - if (row != o.rows()) - return row < o.rows() ? -1 : 1; - - // compare number of columns - if (col != o.cols()) - return col < o.cols() ? -1 : 1; - - // equal number of rows and columns, compare individual elements - int cmpval; - for (unsigned r=0; r matrices are equal; - return 0; + GINAC_ASSERT(is_exactly_of_type(other, matrix)); + const matrix & o = static_cast(const_cast(other)); + + // compare number of rows + if (row != o.rows()) + return row < o.rows() ? -1 : 1; + + // compare number of columns + if (col != o.cols()) + return col < o.cols() ? -1 : 1; + + // equal number of rows and columns, compare individual elements + int cmpval; + for (unsigned r=0; r matrices are equal; + return 0; } ////////// @@ -333,16 +333,16 @@ int matrix::compare_same_type(const basic & other) const * @exception logic_error (incompatible matrices) */ matrix matrix::add(const matrix & other) const { - if (col != other.col || row != other.row) - throw (std::logic_error("matrix::add(): incompatible matrices")); - - exvector sum(this->m); - exvector::iterator i; - exvector::const_iterator ci; - for (i=sum.begin(), ci=other.m.begin(); i!=sum.end(); ++i, ++ci) - (*i) += (*ci); - - return matrix(row,col,sum); + if (col != other.col || row != other.row) + throw (std::logic_error("matrix::add(): incompatible matrices")); + + exvector sum(this->m); + exvector::iterator i; + exvector::const_iterator ci; + for (i=sum.begin(), ci=other.m.begin(); i!=sum.end(); ++i, ++ci) + (*i) += (*ci); + + return matrix(row,col,sum); } @@ -351,16 +351,16 @@ matrix matrix::add(const matrix & other) const * @exception logic_error (incompatible matrices) */ matrix matrix::sub(const matrix & other) const { - if (col != other.col || row != other.row) - throw (std::logic_error("matrix::sub(): incompatible matrices")); - - exvector dif(this->m); - exvector::iterator i; - exvector::const_iterator ci; - for (i=dif.begin(), ci=other.m.begin(); i!=dif.end(); ++i, ++ci) - (*i) -= (*ci); - - return matrix(row,col,dif); + if (col != other.col || row != other.row) + throw (std::logic_error("matrix::sub(): incompatible matrices")); + + exvector dif(this->m); + exvector::iterator i; + exvector::const_iterator ci; + for (i=dif.begin(), ci=other.m.begin(); i!=dif.end(); ++i, ++ci) + (*i) -= (*ci); + + return matrix(row,col,dif); } @@ -369,20 +369,20 @@ matrix matrix::sub(const matrix & other) const * @exception logic_error (incompatible matrices) */ matrix matrix::mul(const matrix & other) const { - if (this->cols() != other.rows()) - throw (std::logic_error("matrix::mul(): incompatible matrices")); - - exvector prod(this->rows()*other.cols()); - - for (unsigned r1=0; r1rows(); ++r1) { - for (unsigned c=0; ccols(); ++c) { - if (m[r1*col+c].is_zero()) - continue; - for (unsigned r2=0; r2cols() != other.rows()) + throw (std::logic_error("matrix::mul(): incompatible matrices")); + + exvector prod(this->rows()*other.cols()); + + for (unsigned r1=0; r1rows(); ++r1) { + for (unsigned c=0; ccols(); ++c) { + if (m[r1*col+c].is_zero()) + continue; + for (unsigned r2=0; r2=row || co<0 || co>=col) - throw (std::range_error("matrix::operator(): index out of range")); + if (ro<0 || ro>=row || co<0 || co>=col) + throw (std::range_error("matrix::operator(): index out of range")); - return m[ro*col+co]; + return m[ro*col+co]; } @@ -405,12 +405,12 @@ const ex & matrix::operator() (unsigned ro, unsigned co) const * @exception range_error (index out of range) */ matrix & matrix::set(unsigned ro, unsigned co, ex value) { - if (ro<0 || ro>=row || co<0 || co>=col) - throw (std::range_error("matrix::set(): index out of range")); - - ensure_if_modifiable(); - m[ro*col+co] = value; - return *this; + if (ro<0 || ro>=row || co<0 || co>=col) + throw (std::range_error("matrix::set(): index out of range")); + + ensure_if_modifiable(); + m[ro*col+co] = value; + return *this; } @@ -418,13 +418,13 @@ matrix & matrix::set(unsigned ro, unsigned co, ex value) * represents the transposed. */ matrix matrix::transpose(void) const { - exvector trans(this->cols()*this->rows()); - - for (unsigned r=0; rcols(); ++r) - for (unsigned c=0; crows(); ++c) - trans[r*this->rows()+c] = m[c*this->cols()+r]; - - return matrix(this->cols(),this->rows(),trans); + exvector trans(this->cols()*this->rows()); + + for (unsigned r=0; rcols(); ++r) + for (unsigned c=0; crows(); ++c) + trans[r*this->rows()+c] = m[c*this->cols()+r]; + + return matrix(this->cols(),this->rows(),trans); } @@ -444,121 +444,121 @@ matrix matrix::transpose(void) const * @see determinant_algo */ ex matrix::determinant(unsigned algo) const { - if (row!=col) - throw (std::logic_error("matrix::determinant(): matrix not square")); - GINAC_ASSERT(row*col==m.capacity()); - - // Gather some statistical information about this matrix: - bool numeric_flag = true; - bool normal_flag = false; - unsigned sparse_count = 0; // counts non-zero elements - for (exvector::const_iterator r=m.begin(); r!=m.end(); ++r) { - lst srl; // symbol replacement list - ex rtest = (*r).to_rational(srl); - if (!rtest.is_zero()) - ++sparse_count; - if (!rtest.info(info_flags::numeric)) - numeric_flag = false; - if (!rtest.info(info_flags::crational_polynomial) && - rtest.info(info_flags::rational_function)) - normal_flag = true; - } - - // Here is the heuristics in case this routine has to decide: - if (algo == determinant_algo::automatic) { - // Minor expansion is generally a good guess: - algo = determinant_algo::laplace; - // Does anybody know when a matrix is really sparse? - // Maybe <~row/2.236 nonzero elements average in a row? - if (row>3 && 5*sparse_count<=row*col) - algo = determinant_algo::bareiss; - // Purely numeric matrix can be handled by Gauss elimination. - // This overrides any prior decisions. - if (numeric_flag) - algo = determinant_algo::gauss; - } - - // Trap the trivial case here, since some algorithms don't like it - if (this->row==1) { - // for consistency with non-trivial determinants... - if (normal_flag) - return m[0].normal(); - else - return m[0].expand(); - } - - // Compute the determinant - switch(algo) { - case determinant_algo::gauss: { - ex det = 1; - matrix tmp(*this); - int sign = tmp.gauss_elimination(true); - for (unsigned d=0; d uintpair; - std::vector c_zeros; // number of zeros in column - for (unsigned c=0; c pre_sort; - for (std::vector::iterator i=c_zeros.begin(); i!=c_zeros.end(); ++i) - pre_sort.push_back(i->second); - int sign = permutation_sign(pre_sort); - exvector result(row*col); // represents sorted matrix - unsigned c = 0; - for (std::vector::iterator i=pre_sort.begin(); - i!=pre_sort.end(); - ++i,++c) { - for (unsigned r=0; r3 && 5*sparse_count<=row*col) + algo = determinant_algo::bareiss; + // Purely numeric matrix can be handled by Gauss elimination. + // This overrides any prior decisions. + if (numeric_flag) + algo = determinant_algo::gauss; + } + + // Trap the trivial case here, since some algorithms don't like it + if (this->row==1) { + // for consistency with non-trivial determinants... + if (normal_flag) + return m[0].normal(); + else + return m[0].expand(); + } + + // Compute the determinant + switch(algo) { + case determinant_algo::gauss: { + ex det = 1; + matrix tmp(*this); + int sign = tmp.gauss_elimination(true); + for (unsigned d=0; d uintpair; + std::vector c_zeros; // number of zeros in column + for (unsigned c=0; c pre_sort; + for (std::vector::iterator i=c_zeros.begin(); i!=c_zeros.end(); ++i) + pre_sort.push_back(i->second); + int sign = permutation_sign(pre_sort); + exvector result(row*col); // represents sorted matrix + unsigned c = 0; + for (std::vector::iterator i=pre_sort.begin(); + i!=pre_sort.end(); + ++i,++c) { + for (unsigned r=0; rmul(B); - c = B.trace()/ex(i+1); - poly -= c*power(lambda,row-i-1); - } - if (row%2) - return -poly; - else - return poly; - } - - matrix M(*this); - for (unsigned r=0; rmul(B); + c = B.trace()/ex(i+1); + poly -= c*power(lambda,row-i-1); + } + if (row%2) + return -poly; + else + return poly; + } + + matrix M(*this); + for (unsigned r=0; rrows(); - const unsigned n = this->cols(); - const unsigned p = rhs.cols(); - - // syntax checks - if ((rhs.rows() != m) || (vars.rows() != n) || (vars.col != p)) - throw (std::logic_error("matrix::solve(): incompatible matrices")); - for (unsigned ro=0; rom[r*n+c]; - for (unsigned c=0; c=0; --r) { - unsigned fnz = 1; // first non-zero in row - while ((fnz<=n) && (aug.m[r*(n+p)+(fnz-1)].is_zero())) - ++fnz; - if (fnz>n) { - // row consists only of zeros, corresponding rhs must be 0, too - if (!aug.m[r*(n+p)+n+co].is_zero()) { - throw (std::runtime_error("matrix::solve(): inconsistent linear system")); - } - } else { - // assign solutions for vars between fnz+1 and - // last_assigned_sol-1: free parameters - for (unsigned c=fnz; crows(); + const unsigned n = this->cols(); + const unsigned p = rhs.cols(); + + // syntax checks + if ((rhs.rows() != m) || (vars.rows() != n) || (vars.col != p)) + throw (std::logic_error("matrix::solve(): incompatible matrices")); + for (unsigned ro=0; rom[r*n+c]; + for (unsigned c=0; c=0; --r) { + unsigned fnz = 1; // first non-zero in row + while ((fnz<=n) && (aug.m[r*(n+p)+(fnz-1)].is_zero())) + ++fnz; + if (fnz>n) { + // row consists only of zeros, corresponding rhs must be 0, too + if (!aug.m[r*(n+p)+n+co].is_zero()) { + throw (std::runtime_error("matrix::solve(): inconsistent linear system")); + } + } else { + // assign solutions for vars between fnz+1 and + // last_assigned_sol-1: free parameters + for (unsigned c=fnz; ccols(); - if (n==1) - return m[0].expand(); - if (n==2) - return (m[0]*m[3]-m[2]*m[1]).expand(); - if (n==3) - return (m[0]*m[4]*m[8]-m[0]*m[5]*m[7]- - m[1]*m[3]*m[8]+m[2]*m[3]*m[7]+ - m[1]*m[5]*m[6]-m[2]*m[4]*m[6]).expand(); - - // This algorithm can best be understood by looking at a naive - // implementation of Laplace-expansion, like this one: - // ex det; - // matrix minorM(this->rows()-1,this->cols()-1); - // for (unsigned r1=0; r1rows(); ++r1) { - // // shortcut if element(r1,0) vanishes - // if (m[r1*col].is_zero()) - // continue; - // // assemble the minor matrix - // for (unsigned r=0; r Pkey; - Pkey.reserve(n); - // key for minor determinant (a subpartition of Pkey) - std::vector Mkey; - Mkey.reserve(n-1); - // we store our subminors in maps, keys being the rows they arise from - typedef std::map,class ex> Rmap; - typedef std::map,class ex>::value_type Rmap_value; - Rmap A; - Rmap B; - ex det; - // initialize A with last column: - for (unsigned r=0; r=0; --c) { - Pkey.erase(Pkey.begin(),Pkey.end()); // don't change capacity - Mkey.erase(Mkey.begin(),Mkey.end()); - for (unsigned i=0; i0; --fc) { - ++Pkey[fc-1]; - if (Pkey[fc-1]cols(); + if (n==1) + return m[0].expand(); + if (n==2) + return (m[0]*m[3]-m[2]*m[1]).expand(); + if (n==3) + return (m[0]*m[4]*m[8]-m[0]*m[5]*m[7]- + m[1]*m[3]*m[8]+m[2]*m[3]*m[7]+ + m[1]*m[5]*m[6]-m[2]*m[4]*m[6]).expand(); + + // This algorithm can best be understood by looking at a naive + // implementation of Laplace-expansion, like this one: + // ex det; + // matrix minorM(this->rows()-1,this->cols()-1); + // for (unsigned r1=0; r1rows(); ++r1) { + // // shortcut if element(r1,0) vanishes + // if (m[r1*col].is_zero()) + // continue; + // // assemble the minor matrix + // for (unsigned r=0; r Pkey; + Pkey.reserve(n); + // key for minor determinant (a subpartition of Pkey) + std::vector Mkey; + Mkey.reserve(n-1); + // we store our subminors in maps, keys being the rows they arise from + typedef std::map,class ex> Rmap; + typedef std::map,class ex>::value_type Rmap_value; + Rmap A; + Rmap B; + ex det; + // initialize A with last column: + for (unsigned r=0; r=0; --c) { + Pkey.erase(Pkey.begin(),Pkey.end()); // don't change capacity + Mkey.erase(Mkey.begin(),Mkey.end()); + for (unsigned i=0; i0; --fc) { + ++Pkey[fc-1]; + if (Pkey[fc-1]rows(); - const unsigned n = this->cols(); - GINAC_ASSERT(!det || n==m); - int sign = 1; - - unsigned r0 = 0; - for (unsigned r1=0; (r1=0) { - if (indx > 0) - sign = -sign; - for (unsigned r2=r0+1; r2m[r2*n+r1] / this->m[r0*n+r1]; - for (unsigned c=r1+1; cm[r2*n+c] -= piv * this->m[r0*n+c]; - if (!this->m[r2*n+c].info(info_flags::numeric)) - this->m[r2*n+c] = this->m[r2*n+c].normal(); - } - // fill up left hand side with zeros - for (unsigned c=0; c<=r1; ++c) - this->m[r2*n+c] = _ex0(); - } - if (det) { - // save space by deleting no longer needed elements - for (unsigned c=r0+1; cm[r0*n+c] = _ex0(); - } - ++r0; - } - } - - return sign; + ensure_if_modifiable(); + const unsigned m = this->rows(); + const unsigned n = this->cols(); + GINAC_ASSERT(!det || n==m); + int sign = 1; + + unsigned r0 = 0; + for (unsigned r1=0; (r1=0) { + if (indx > 0) + sign = -sign; + for (unsigned r2=r0+1; r2m[r2*n+r1] / this->m[r0*n+r1]; + for (unsigned c=r1+1; cm[r2*n+c] -= piv * this->m[r0*n+c]; + if (!this->m[r2*n+c].info(info_flags::numeric)) + this->m[r2*n+c] = this->m[r2*n+c].normal(); + } + // fill up left hand side with zeros + for (unsigned c=0; c<=r1; ++c) + this->m[r2*n+c] = _ex0(); + } + if (det) { + // save space by deleting no longer needed elements + for (unsigned c=r0+1; cm[r0*n+c] = _ex0(); + } + ++r0; + } + } + + return sign; } @@ -977,40 +977,40 @@ int matrix::gauss_elimination(const bool det) * number of rows was swapped and 0 if the matrix is singular. */ int matrix::division_free_elimination(const bool det) { - ensure_if_modifiable(); - const unsigned m = this->rows(); - const unsigned n = this->cols(); - GINAC_ASSERT(!det || n==m); - int sign = 1; - - unsigned r0 = 0; - for (unsigned r1=0; (r1=0) { - if (indx>0) - sign = -sign; - for (unsigned r2=r0+1; r2m[r2*n+c] = (this->m[r0*n+r1]*this->m[r2*n+c] - this->m[r2*n+r1]*this->m[r0*n+c]).expand(); - // fill up left hand side with zeros - for (unsigned c=0; c<=r1; ++c) - this->m[r2*n+c] = _ex0(); - } - if (det) { - // save space by deleting no longer needed elements - for (unsigned c=r0+1; cm[r0*n+c] = _ex0(); - } - ++r0; - } - } - - return sign; + ensure_if_modifiable(); + const unsigned m = this->rows(); + const unsigned n = this->cols(); + GINAC_ASSERT(!det || n==m); + int sign = 1; + + unsigned r0 = 0; + for (unsigned r1=0; (r1=0) { + if (indx>0) + sign = -sign; + for (unsigned r2=r0+1; r2m[r2*n+c] = (this->m[r0*n+r1]*this->m[r2*n+c] - this->m[r2*n+r1]*this->m[r0*n+c]).expand(); + // fill up left hand side with zeros + for (unsigned c=0; c<=r1; ++c) + this->m[r2*n+c] = _ex0(); + } + if (det) { + // save space by deleting no longer needed elements + for (unsigned c=r0+1; cm[r0*n+c] = _ex0(); + } + ++r0; + } + } + + return sign; } @@ -1026,117 +1026,117 @@ int matrix::division_free_elimination(const bool det) * number of rows was swapped and 0 if the matrix is singular. */ int matrix::fraction_free_elimination(const bool det) { - // Method: - // (single-step fraction free elimination scheme, already known to Jordan) - // - // Usual division-free elimination sets m[0](r,c) = m(r,c) and then sets - // m[k+1](r,c) = m[k](k,k) * m[k](r,c) - m[k](r,k) * m[k](k,c). - // - // Bareiss (fraction-free) elimination in addition divides that element - // by m[k-1](k-1,k-1) for k>1, where it can be shown by means of the - // Sylvester determinant that this really divides m[k+1](r,c). - // - // We also allow rational functions where the original prove still holds. - // However, we must care for numerator and denominator separately and - // "manually" work in the integral domains because of subtle cancellations - // (see below). This blows up the bookkeeping a bit and the formula has - // to be modified to expand like this (N{x} stands for numerator of x, - // D{x} for denominator of x): - // N{m[k+1](r,c)} = N{m[k](k,k)}*N{m[k](r,c)}*D{m[k](r,k)}*D{m[k](k,c)} - // -N{m[k](r,k)}*N{m[k](k,c)}*D{m[k](k,k)}*D{m[k](r,c)} - // D{m[k+1](r,c)} = D{m[k](k,k)}*D{m[k](r,c)}*D{m[k](r,k)}*D{m[k](k,c)} - // where for k>1 we now divide N{m[k+1](r,c)} by - // N{m[k-1](k-1,k-1)} - // and D{m[k+1](r,c)} by - // D{m[k-1](k-1,k-1)}. - - ensure_if_modifiable(); - const unsigned m = this->rows(); - const unsigned n = this->cols(); - GINAC_ASSERT(!det || n==m); - int sign = 1; - if (m==1) - return 1; - ex divisor_n = 1; - ex divisor_d = 1; - ex dividend_n; - ex dividend_d; - - // We populate temporary matrices to subsequently operate on. There is - // one holding numerators and another holding denominators of entries. - // This is a must since the evaluator (or even earlier mul's constructor) - // might cancel some trivial element which causes divide() to fail. The - // elements are normalized first (yes, even though this algorithm doesn't - // need GCDs) since the elements of *this might be unnormalized, which - // makes things more complicated than they need to be. - matrix tmp_n(*this); - matrix tmp_d(m,n); // for denominators, if needed - lst srl; // symbol replacement list - exvector::iterator it = this->m.begin(); - exvector::iterator tmp_n_it = tmp_n.m.begin(); - exvector::iterator tmp_d_it = tmp_d.m.begin(); - for (; it!= this->m.end(); ++it, ++tmp_n_it, ++tmp_d_it) { - (*tmp_n_it) = (*it).normal().to_rational(srl); - (*tmp_d_it) = (*tmp_n_it).denom(); - (*tmp_n_it) = (*tmp_n_it).numer(); - } - - unsigned r0 = 0; - for (unsigned r1=0; (r1=0) { - if (indx>0) { - sign = -sign; - // tmp_n's rows r0 and indx were swapped, do the same in tmp_d: - for (unsigned c=r1; cm.begin(); - tmp_n_it = tmp_n.m.begin(); - tmp_d_it = tmp_d.m.begin(); - for (; it!= this->m.end(); ++it, ++tmp_n_it, ++tmp_d_it) - (*it) = ((*tmp_n_it)/(*tmp_d_it)).subs(srl); - - return sign; + // Method: + // (single-step fraction free elimination scheme, already known to Jordan) + // + // Usual division-free elimination sets m[0](r,c) = m(r,c) and then sets + // m[k+1](r,c) = m[k](k,k) * m[k](r,c) - m[k](r,k) * m[k](k,c). + // + // Bareiss (fraction-free) elimination in addition divides that element + // by m[k-1](k-1,k-1) for k>1, where it can be shown by means of the + // Sylvester determinant that this really divides m[k+1](r,c). + // + // We also allow rational functions where the original prove still holds. + // However, we must care for numerator and denominator separately and + // "manually" work in the integral domains because of subtle cancellations + // (see below). This blows up the bookkeeping a bit and the formula has + // to be modified to expand like this (N{x} stands for numerator of x, + // D{x} for denominator of x): + // N{m[k+1](r,c)} = N{m[k](k,k)}*N{m[k](r,c)}*D{m[k](r,k)}*D{m[k](k,c)} + // -N{m[k](r,k)}*N{m[k](k,c)}*D{m[k](k,k)}*D{m[k](r,c)} + // D{m[k+1](r,c)} = D{m[k](k,k)}*D{m[k](r,c)}*D{m[k](r,k)}*D{m[k](k,c)} + // where for k>1 we now divide N{m[k+1](r,c)} by + // N{m[k-1](k-1,k-1)} + // and D{m[k+1](r,c)} by + // D{m[k-1](k-1,k-1)}. + + ensure_if_modifiable(); + const unsigned m = this->rows(); + const unsigned n = this->cols(); + GINAC_ASSERT(!det || n==m); + int sign = 1; + if (m==1) + return 1; + ex divisor_n = 1; + ex divisor_d = 1; + ex dividend_n; + ex dividend_d; + + // We populate temporary matrices to subsequently operate on. There is + // one holding numerators and another holding denominators of entries. + // This is a must since the evaluator (or even earlier mul's constructor) + // might cancel some trivial element which causes divide() to fail. The + // elements are normalized first (yes, even though this algorithm doesn't + // need GCDs) since the elements of *this might be unnormalized, which + // makes things more complicated than they need to be. + matrix tmp_n(*this); + matrix tmp_d(m,n); // for denominators, if needed + lst srl; // symbol replacement list + exvector::iterator it = this->m.begin(); + exvector::iterator tmp_n_it = tmp_n.m.begin(); + exvector::iterator tmp_d_it = tmp_d.m.begin(); + for (; it!= this->m.end(); ++it, ++tmp_n_it, ++tmp_d_it) { + (*tmp_n_it) = (*it).normal().to_rational(srl); + (*tmp_d_it) = (*tmp_n_it).denom(); + (*tmp_n_it) = (*tmp_n_it).numer(); + } + + unsigned r0 = 0; + for (unsigned r1=0; (r1=0) { + if (indx>0) { + sign = -sign; + // tmp_n's rows r0 and indx were swapped, do the same in tmp_d: + for (unsigned c=r1; cm.begin(); + tmp_n_it = tmp_n.m.begin(); + tmp_d_it = tmp_d.m.begin(); + for (; it!= this->m.end(); ++it, ++tmp_n_it, ++tmp_d_it) + (*it) = ((*tmp_n_it)/(*tmp_d_it)).subs(srl); + + return sign; } @@ -1155,63 +1155,63 @@ int matrix::fraction_free_elimination(const bool det) */ int matrix::pivot(unsigned ro, unsigned co, bool symbolic) { - unsigned k = ro; - if (symbolic) { - // search first non-zero element in column co beginning at row ro - while ((km[k*col+co].expand().is_zero())) - ++k; - } else { - // search largest element in column co beginning at row ro - GINAC_ASSERT(is_ex_of_type(this->m[k*col+co],numeric)); - unsigned kmax = k+1; - numeric mmax = abs(ex_to_numeric(m[kmax*col+co])); - while (kmaxm[kmax*col+co],numeric)); - numeric tmp = ex_to_numeric(this->m[kmax*col+co]); - if (abs(tmp) > mmax) { - mmax = tmp; - k = kmax; - } - ++kmax; - } - if (!mmax.is_zero()) - k = kmax; - } - if (k==row) - // all elements in column co below row ro vanish - return -1; - if (k==ro) - // matrix needs no pivoting - return 0; - // matrix needs pivoting, so swap rows k and ro - ensure_if_modifiable(); - for (unsigned c=0; cm[k*col+co].expand().is_zero())) + ++k; + } else { + // search largest element in column co beginning at row ro + GINAC_ASSERT(is_ex_of_type(this->m[k*col+co],numeric)); + unsigned kmax = k+1; + numeric mmax = abs(ex_to_numeric(m[kmax*col+co])); + while (kmaxm[kmax*col+co],numeric)); + numeric tmp = ex_to_numeric(this->m[kmax*col+co]); + if (abs(tmp) > mmax) { + mmax = tmp; + k = kmax; + } + ++kmax; + } + if (!mmax.is_zero()) + k = kmax; + } + if (k==row) + // all elements in column co below row ro vanish + return -1; + if (k==ro) + // matrix needs no pivoting + return 0; + // matrix needs pivoting, so swap rows k and ro + ensure_if_modifiable(); + for (unsigned c=0; c cols) - cols = l.op(i).nops(); - - // Allocate and fill matrix - matrix &m = *new matrix(rows, cols); - for (i=0; i j) - m.set(i, j, l.op(i).op(j)); - else - m.set(i, j, ex(0)); - return m; + if (!is_ex_of_type(l, lst)) + throw(std::invalid_argument("argument to lst_to_matrix() must be a lst")); + + // Find number of rows and columns + unsigned rows = l.nops(), cols = 0, i, j; + for (i=0; i cols) + cols = l.op(i).nops(); + + // Allocate and fill matrix + matrix &m = *new matrix(rows, cols); + for (i=0; i j) + m.set(i, j, l.op(i).op(j)); + else + m.set(i, j, ex(0)); + return m; } ////////// diff --git a/ginac/matrix.h b/ginac/matrix.h index baaa8a5b..164d1762 100644 --- a/ginac/matrix.h +++ b/ginac/matrix.h @@ -34,78 +34,78 @@ namespace GiNaC { /** Symbolic matrices. */ class matrix : public basic { - GINAC_DECLARE_REGISTERED_CLASS(matrix, basic) + GINAC_DECLARE_REGISTERED_CLASS(matrix, basic) // friends // (none) // member functions - // default constructor, destructor, copy constructor, assignment operator - // and helpers: + // default constructor, destructor, copy constructor, assignment operator + // and helpers: public: - matrix(); - ~matrix(); - matrix(const matrix & other); - const matrix & operator=(const matrix & other); + matrix(); + ~matrix(); + matrix(const matrix & other); + const matrix & operator=(const matrix & other); protected: - void copy(const matrix & other); - void destroy(bool call_parent); + void copy(const matrix & other); + void destroy(bool call_parent); - // other constructors + // other constructors public: - matrix(unsigned r, unsigned c); - matrix(unsigned r, unsigned c, const exvector & m2); + matrix(unsigned r, unsigned c); + matrix(unsigned r, unsigned c, const exvector & m2); - // functions overriding virtual functions from bases classes + // functions overriding virtual functions from bases classes public: - basic * duplicate() const; - void print(std::ostream & os, unsigned upper_precedence=0) const; - void printraw(std::ostream & os) const; - unsigned nops() const; - ex op(int i) const; - ex & let_op(int i); - ex expand(unsigned options=0) const; - bool has(const ex & other) const; - ex eval(int level=0) const; - ex evalf(int level=0) const; - // ex subs(const lst & ls, const lst & lr) const; + basic * duplicate() const; + void print(std::ostream & os, unsigned upper_precedence=0) const; + void printraw(std::ostream & os) const; + unsigned nops() const; + ex op(int i) const; + ex & let_op(int i); + ex expand(unsigned options=0) const; + bool has(const ex & other) const; + ex eval(int level=0) const; + ex evalf(int level=0) const; + // ex subs(const lst & ls, const lst & lr) const; protected: - int compare_same_type(const basic & other) const; - unsigned return_type(void) const { return return_types::noncommutative; }; - // new virtual functions which can be overridden by derived classes - // (none) - - // non-virtual functions in this class + int compare_same_type(const basic & other) const; + unsigned return_type(void) const { return return_types::noncommutative; }; + // new virtual functions which can be overridden by derived classes + // (none) + + // non-virtual functions in this class public: - unsigned rows(void) const //! Get number of rows. - { return row; } - unsigned cols(void) const //! Get number of columns. - { return col; } - matrix add(const matrix & other) const; - matrix sub(const matrix & other) const; - matrix mul(const matrix & other) const; - const ex & operator() (unsigned ro, unsigned co) const; - matrix & set(unsigned ro, unsigned co, ex value); - matrix transpose(void) const; - ex determinant(unsigned algo = determinant_algo::automatic) const; - ex trace(void) const; - ex charpoly(const symbol & lambda) const; - matrix inverse(void) const; - matrix solve(const matrix & vars, const matrix & rhs, - unsigned algo = solve_algo::automatic) const; + unsigned rows(void) const //! Get number of rows. + { return row; } + unsigned cols(void) const //! Get number of columns. + { return col; } + matrix add(const matrix & other) const; + matrix sub(const matrix & other) const; + matrix mul(const matrix & other) const; + const ex & operator() (unsigned ro, unsigned co) const; + matrix & set(unsigned ro, unsigned co, ex value); + matrix transpose(void) const; + ex determinant(unsigned algo = determinant_algo::automatic) const; + ex trace(void) const; + ex charpoly(const symbol & lambda) const; + matrix inverse(void) const; + matrix solve(const matrix & vars, const matrix & rhs, + unsigned algo = solve_algo::automatic) const; protected: - ex determinant_minor(void) const; - int gauss_elimination(const bool det = false); - int division_free_elimination(const bool det = false); - int fraction_free_elimination(const bool det = false); - int pivot(unsigned ro, unsigned co, bool symbolic = true); - + ex determinant_minor(void) const; + int gauss_elimination(const bool det = false); + int division_free_elimination(const bool det = false); + int fraction_free_elimination(const bool det = false); + int pivot(unsigned ro, unsigned co, bool symbolic = true); + // member variables protected: - unsigned row; /**< number of rows */ - unsigned col; /**< number of columns */ - exvector m; /**< representation (cols indexed first) */ - static unsigned precedence; + unsigned row; /**< number of rows */ + unsigned col; /**< number of columns */ + exvector m; /**< representation (cols indexed first) */ + static unsigned precedence; }; diff --git a/ginac/mul.cpp b/ginac/mul.cpp index 1cc7abf6..b9bae445 100644 --- a/ginac/mul.cpp +++ b/ginac/mul.cpp @@ -44,42 +44,42 @@ GINAC_IMPLEMENT_REGISTERED_CLASS(mul, expairseq) mul::mul() { - debugmsg("mul default constructor",LOGLEVEL_CONSTRUCT); - tinfo_key = TINFO_mul; + debugmsg("mul default constructor",LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_mul; } mul::~mul() { - debugmsg("mul destructor",LOGLEVEL_DESTRUCT); - destroy(0); + debugmsg("mul destructor",LOGLEVEL_DESTRUCT); + destroy(false); } mul::mul(const mul & other) { - debugmsg("mul copy constructor",LOGLEVEL_CONSTRUCT); - copy(other); + debugmsg("mul copy constructor",LOGLEVEL_CONSTRUCT); + copy(other); } const mul & mul::operator=(const mul & other) { - debugmsg("mul operator=",LOGLEVEL_ASSIGNMENT); - if (this != &other) { - destroy(1); - copy(other); - } - return *this; + debugmsg("mul operator=",LOGLEVEL_ASSIGNMENT); + if (this != &other) { + destroy(true); + copy(other); + } + return *this; } // protected void mul::copy(const mul & other) { - inherited::copy(other); + inherited::copy(other); } void mul::destroy(bool call_parent) { - if (call_parent) inherited::destroy(call_parent); + if (call_parent) inherited::destroy(call_parent); } ////////// @@ -90,63 +90,63 @@ void mul::destroy(bool call_parent) mul::mul(const ex & lh, const ex & rh) { - debugmsg("mul constructor from ex,ex",LOGLEVEL_CONSTRUCT); - tinfo_key = TINFO_mul; - overall_coeff = _ex1(); - construct_from_2_ex(lh,rh); - GINAC_ASSERT(is_canonical()); + debugmsg("mul constructor from ex,ex",LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_mul; + overall_coeff = _ex1(); + construct_from_2_ex(lh,rh); + GINAC_ASSERT(is_canonical()); } mul::mul(const exvector & v) { - debugmsg("mul constructor from exvector",LOGLEVEL_CONSTRUCT); - tinfo_key = TINFO_mul; - overall_coeff = _ex1(); - construct_from_exvector(v); - GINAC_ASSERT(is_canonical()); + debugmsg("mul constructor from exvector",LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_mul; + overall_coeff = _ex1(); + construct_from_exvector(v); + GINAC_ASSERT(is_canonical()); } mul::mul(const epvector & v) { - debugmsg("mul constructor from epvector",LOGLEVEL_CONSTRUCT); - tinfo_key = TINFO_mul; - overall_coeff = _ex1(); - construct_from_epvector(v); - GINAC_ASSERT(is_canonical()); + debugmsg("mul constructor from epvector",LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_mul; + overall_coeff = _ex1(); + construct_from_epvector(v); + GINAC_ASSERT(is_canonical()); } mul::mul(const epvector & v, const ex & oc) { - debugmsg("mul constructor from epvector,ex",LOGLEVEL_CONSTRUCT); - tinfo_key = TINFO_mul; - overall_coeff = oc; - construct_from_epvector(v); - GINAC_ASSERT(is_canonical()); + debugmsg("mul constructor from epvector,ex",LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_mul; + overall_coeff = oc; + construct_from_epvector(v); + GINAC_ASSERT(is_canonical()); } mul::mul(epvector * vp, const ex & oc) { - debugmsg("mul constructor from epvector *,ex",LOGLEVEL_CONSTRUCT); - tinfo_key = TINFO_mul; - GINAC_ASSERT(vp!=0); - overall_coeff = oc; - construct_from_epvector(*vp); - delete vp; - GINAC_ASSERT(is_canonical()); + debugmsg("mul constructor from epvector *,ex",LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_mul; + GINAC_ASSERT(vp!=0); + overall_coeff = oc; + construct_from_epvector(*vp); + delete vp; + GINAC_ASSERT(is_canonical()); } mul::mul(const ex & lh, const ex & mh, const ex & rh) { - debugmsg("mul constructor from ex,ex,ex",LOGLEVEL_CONSTRUCT); - tinfo_key = TINFO_mul; - exvector factors; - factors.reserve(3); - factors.push_back(lh); - factors.push_back(mh); - factors.push_back(rh); - overall_coeff = _ex1(); - construct_from_exvector(factors); - GINAC_ASSERT(is_canonical()); + debugmsg("mul constructor from ex,ex,ex",LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_mul; + exvector factors; + factors.reserve(3); + factors.push_back(lh); + factors.push_back(mh); + factors.push_back(rh); + overall_coeff = _ex1(); + construct_from_exvector(factors); + GINAC_ASSERT(is_canonical()); } ////////// @@ -156,19 +156,19 @@ 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 constructor from archive_node", LOGLEVEL_CONSTRUCT); } /** Unarchive the object. */ ex mul::unarchive(const archive_node &n, const lst &sym_lst) { - return (new mul(n, sym_lst))->setflag(status_flags::dynallocated); + return (new mul(n, sym_lst))->setflag(status_flags::dynallocated); } /** Archive the object. */ void mul::archive(archive_node &n) const { - inherited::archive(n); + inherited::archive(n); } ////////// @@ -179,294 +179,294 @@ void mul::archive(archive_node &n) const basic * mul::duplicate() const { - debugmsg("mul duplicate",LOGLEVEL_ASSIGNMENT); - return new mul(*this); + debugmsg("mul duplicate",LOGLEVEL_ASSIGNMENT); + return new mul(*this); } void mul::print(std::ostream & os, unsigned upper_precedence) const { - debugmsg("mul print",LOGLEVEL_PRINT); - if (precedence<=upper_precedence) os << "("; - bool first=true; - // first print the overall numeric coefficient: - numeric coeff = ex_to_numeric(overall_coeff); - if (coeff.csgn()==-1) os << '-'; - if (!coeff.is_equal(_num1()) && - !coeff.is_equal(_num_1())) { - if (coeff.is_rational()) { - if (coeff.is_negative()) - os << -coeff; - else - os << coeff; - } else { - if (coeff.csgn()==-1) - (-coeff).print(os, precedence); - else - coeff.print(os, precedence); - } - os << '*'; - } - // then proceed with the remaining factors: - for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { - if (!first) { - os << '*'; - } else { - first=false; - } - recombine_pair_to_ex(*cit).print(os,precedence); - } - if (precedence<=upper_precedence) os << ")"; + debugmsg("mul print",LOGLEVEL_PRINT); + if (precedence<=upper_precedence) os << "("; + bool first=true; + // first print the overall numeric coefficient: + numeric coeff = ex_to_numeric(overall_coeff); + if (coeff.csgn()==-1) os << '-'; + if (!coeff.is_equal(_num1()) && + !coeff.is_equal(_num_1())) { + if (coeff.is_rational()) { + if (coeff.is_negative()) + os << -coeff; + else + os << coeff; + } else { + if (coeff.csgn()==-1) + (-coeff).print(os, precedence); + else + coeff.print(os, precedence); + } + os << '*'; + } + // then proceed with the remaining factors: + for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { + if (!first) { + os << '*'; + } else { + first=false; + } + recombine_pair_to_ex(*cit).print(os,precedence); + } + if (precedence<=upper_precedence) os << ")"; } void mul::printraw(std::ostream & os) const { - debugmsg("mul printraw",LOGLEVEL_PRINT); + debugmsg("mul printraw",LOGLEVEL_PRINT); - os << "*("; - for (epvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) { - os << "("; - (*it).rest.bp->printraw(os); - os << ","; - (*it).coeff.bp->printraw(os); - os << "),"; - } - os << ",hash=" << hashvalue << ",flags=" << flags; - os << ")"; + os << "*("; + for (epvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) { + os << "("; + (*it).rest.bp->printraw(os); + os << ","; + (*it).coeff.bp->printraw(os); + os << "),"; + } + os << ",hash=" << hashvalue << ",flags=" << flags; + os << ")"; } void mul::printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const { - debugmsg("mul print csrc", LOGLEVEL_PRINT); - if (precedence <= upper_precedence) - os << "("; - - if (!overall_coeff.is_equal(_ex1())) { - overall_coeff.bp->printcsrc(os,type,precedence); - os << "*"; - } - - // Print arguments, separated by "*" or "/" - epvector::const_iterator it = seq.begin(); - epvector::const_iterator itend = seq.end(); - while (it != itend) { - - // If the first argument is a negative integer power, it gets printed as "1.0/" - if (it == seq.begin() && ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(_num0()) < 0) { - if (type == csrc_types::ctype_cl_N) - os << "recip("; - else - os << "1.0/"; - } - - // If the exponent is 1 or -1, it is left out - if (it->coeff.compare(_ex1()) == 0 || it->coeff.compare(_num_1()) == 0) - it->rest.bp->printcsrc(os, type, precedence); - else - // outer parens around ex needed for broken gcc-2.95 parser: - (ex(power(it->rest, abs(ex_to_numeric(it->coeff))))).bp->printcsrc(os, type, upper_precedence); - - // Separator is "/" for negative integer powers, "*" otherwise - ++it; - if (it != itend) { - if (ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(_num0()) < 0) - os << "/"; - else - os << "*"; - } - } - if (precedence <= upper_precedence) - os << ")"; + debugmsg("mul print csrc", LOGLEVEL_PRINT); + if (precedence <= upper_precedence) + os << "("; + + if (!overall_coeff.is_equal(_ex1())) { + overall_coeff.bp->printcsrc(os,type,precedence); + os << "*"; + } + + // Print arguments, separated by "*" or "/" + epvector::const_iterator it = seq.begin(); + epvector::const_iterator itend = seq.end(); + while (it != itend) { + + // If the first argument is a negative integer power, it gets printed as "1.0/" + if (it == seq.begin() && ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(_num0()) < 0) { + if (type == csrc_types::ctype_cl_N) + os << "recip("; + else + os << "1.0/"; + } + + // If the exponent is 1 or -1, it is left out + if (it->coeff.compare(_ex1()) == 0 || it->coeff.compare(_num_1()) == 0) + it->rest.bp->printcsrc(os, type, precedence); + else + // outer parens around ex needed for broken gcc-2.95 parser: + (ex(power(it->rest, abs(ex_to_numeric(it->coeff))))).bp->printcsrc(os, type, upper_precedence); + + // Separator is "/" for negative integer powers, "*" otherwise + ++it; + if (it != itend) { + if (ex_to_numeric(it->coeff).is_integer() && it->coeff.compare(_num0()) < 0) + os << "/"; + else + os << "*"; + } + } + if (precedence <= upper_precedence) + os << ")"; } bool mul::info(unsigned inf) const { - switch (inf) { - case info_flags::polynomial: - case info_flags::integer_polynomial: - case info_flags::cinteger_polynomial: - case info_flags::rational_polynomial: - case info_flags::crational_polynomial: - case info_flags::rational_function: { - for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) { - if (!(recombine_pair_to_ex(*i).info(inf))) - return false; - } - return overall_coeff.info(inf); - } - case info_flags::algebraic: { - for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) { - if ((recombine_pair_to_ex(*i).info(inf))) - return true; - } - return false; - } - } - return inherited::info(inf); + switch (inf) { + case info_flags::polynomial: + case info_flags::integer_polynomial: + case info_flags::cinteger_polynomial: + case info_flags::rational_polynomial: + case info_flags::crational_polynomial: + case info_flags::rational_function: { + for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) { + if (!(recombine_pair_to_ex(*i).info(inf))) + return false; + } + return overall_coeff.info(inf); + } + case info_flags::algebraic: { + for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) { + if ((recombine_pair_to_ex(*i).info(inf))) + return true; + } + return false; + } + } + return inherited::info(inf); } typedef std::vector intvector; int mul::degree(const symbol & s) const { - int deg_sum = 0; - for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { - deg_sum+=(*cit).rest.degree(s) * ex_to_numeric((*cit).coeff).to_int(); - } - return deg_sum; + int deg_sum = 0; + for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { + deg_sum+=(*cit).rest.degree(s) * ex_to_numeric((*cit).coeff).to_int(); + } + return deg_sum; } int mul::ldegree(const symbol & s) const { - int deg_sum = 0; - for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { - deg_sum+=(*cit).rest.ldegree(s) * ex_to_numeric((*cit).coeff).to_int(); - } - return deg_sum; + int deg_sum = 0; + for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { + deg_sum+=(*cit).rest.ldegree(s) * ex_to_numeric((*cit).coeff).to_int(); + } + return deg_sum; } ex mul::coeff(const symbol & s, int n) const { - exvector coeffseq; - coeffseq.reserve(seq.size()+1); - - if (n==0) { - // product of individual coeffs - // if a non-zero power of s is found, the resulting product will be 0 - epvector::const_iterator it=seq.begin(); - while (it!=seq.end()) { - coeffseq.push_back(recombine_pair_to_ex(*it).coeff(s,n)); - ++it; - } - coeffseq.push_back(overall_coeff); - return (new mul(coeffseq))->setflag(status_flags::dynallocated); - } - - epvector::const_iterator it=seq.begin(); - bool coeff_found=0; - while (it!=seq.end()) { - ex t=recombine_pair_to_ex(*it); - ex c=t.coeff(s,n); - if (!c.is_zero()) { - coeffseq.push_back(c); - coeff_found=1; - } else { - coeffseq.push_back(t); - } - ++it; - } - if (coeff_found) { - coeffseq.push_back(overall_coeff); - return (new mul(coeffseq))->setflag(status_flags::dynallocated); - } - - return _ex0(); + exvector coeffseq; + coeffseq.reserve(seq.size()+1); + + if (n==0) { + // product of individual coeffs + // if a non-zero power of s is found, the resulting product will be 0 + epvector::const_iterator it=seq.begin(); + while (it!=seq.end()) { + coeffseq.push_back(recombine_pair_to_ex(*it).coeff(s,n)); + ++it; + } + coeffseq.push_back(overall_coeff); + return (new mul(coeffseq))->setflag(status_flags::dynallocated); + } + + epvector::const_iterator it=seq.begin(); + bool coeff_found=0; + while (it!=seq.end()) { + ex t=recombine_pair_to_ex(*it); + ex c=t.coeff(s,n); + if (!c.is_zero()) { + coeffseq.push_back(c); + coeff_found=1; + } else { + coeffseq.push_back(t); + } + ++it; + } + if (coeff_found) { + coeffseq.push_back(overall_coeff); + return (new mul(coeffseq))->setflag(status_flags::dynallocated); + } + + return _ex0(); } ex mul::eval(int level) const { - // simplifications *(...,x;0) -> 0 - // *(+(x,y,...);c) -> *(+(*(x,c),*(y,c),...)) (c numeric()) - // *(x;1) -> x - // *(;c) -> c + // simplifications *(...,x;0) -> 0 + // *(+(x,y,...);c) -> *(+(*(x,c),*(y,c),...)) (c numeric()) + // *(x;1) -> x + // *(;c) -> c - debugmsg("mul eval",LOGLEVEL_MEMBER_FUNCTION); + debugmsg("mul eval",LOGLEVEL_MEMBER_FUNCTION); - epvector * evaled_seqp=evalchildren(level); - if (evaled_seqp!=0) { - // do more evaluation later - return (new mul(evaled_seqp,overall_coeff))-> - setflag(status_flags::dynallocated); - } + epvector * evaled_seqp=evalchildren(level); + if (evaled_seqp!=0) { + // do more evaluation later + return (new mul(evaled_seqp,overall_coeff))-> + 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(recombine_pair_to_ex(*cit),numeric)); - /* for paranoia */ - 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 */ - } + 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(recombine_pair_to_ex(*cit),numeric)); + /* for paranoia */ + 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())); - return *this; - } - - 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())) { - // *(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); - epvector distrseq; - distrseq.reserve(addref.seq.size()); - for (epvector::const_iterator cit=addref.seq.begin(); cit!=addref.seq.end(); ++cit) { - distrseq.push_back(addref.combine_pair_with_coeff_to_pair(*cit, - overall_coeff)); - } - return (new add(distrseq, - ex_to_numeric(addref.overall_coeff). - mul_dyn(ex_to_numeric(overall_coeff)))) - ->setflag(status_flags::dynallocated | - status_flags::evaluated); - } - return this->hold(); + if (flags & status_flags::evaluated) { + GINAC_ASSERT(seq.size()>0); + GINAC_ASSERT((seq.size()>1)||!overall_coeff.is_equal(_ex1())); + return *this; + } + + 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())) { + // *(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); + epvector distrseq; + distrseq.reserve(addref.seq.size()); + for (epvector::const_iterator cit=addref.seq.begin(); cit!=addref.seq.end(); ++cit) { + distrseq.push_back(addref.combine_pair_with_coeff_to_pair(*cit, + overall_coeff)); + } + return (new add(distrseq, + ex_to_numeric(addref.overall_coeff). + mul_dyn(ex_to_numeric(overall_coeff)))) + ->setflag(status_flags::dynallocated | + status_flags::evaluated); + } + return this->hold(); } ex mul::evalf(int level) const { - if (level==1) - return mul(seq,overall_coeff); - - 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.evalf(level), - (*it).coeff)); - } - return mul(s,overall_coeff.evalf(level)); + if (level==1) + return mul(seq,overall_coeff); + + 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.evalf(level), + (*it).coeff)); + } + return mul(s,overall_coeff.evalf(level)); } exvector mul::get_indices(void) const { - // return union of indices of factors - exvector iv; - 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) { - iv.push_back(*cit2); - } - } - return iv; + // return union of indices of factors + exvector iv; + 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) { + iv.push_back(*cit2); + } + } + return iv; } ex mul::simplify_ncmul(const exvector & v) const { - throw(std::logic_error("mul::simplify_ncmul() should never have been called!")); + throw(std::logic_error("mul::simplify_ncmul() should never have been called!")); } // protected @@ -475,261 +475,259 @@ ex mul::simplify_ncmul(const exvector & v) const * @see ex::diff */ ex mul::derivative(const symbol & s) const { - exvector addseq; - addseq.reserve(seq.size()); - - // D(a*b*c) = D(a)*b*c + a*D(b)*c + a*b*D(c) - for (unsigned i=0; i!=seq.size(); ++i) { - epvector mulseq = seq; - mulseq[i] = split_ex_to_pair(power(seq[i].rest,seq[i].coeff - _ex1())* - seq[i].rest.diff(s)); - addseq.push_back((new mul(mulseq,overall_coeff*seq[i].coeff))->setflag(status_flags::dynallocated)); - } - return (new add(addseq))->setflag(status_flags::dynallocated); + exvector addseq; + addseq.reserve(seq.size()); + + // D(a*b*c) = D(a)*b*c + a*D(b)*c + a*b*D(c) + for (unsigned i=0; i!=seq.size(); ++i) { + epvector mulseq = seq; + mulseq[i] = split_ex_to_pair(power(seq[i].rest,seq[i].coeff - _ex1())* + seq[i].rest.diff(s)); + addseq.push_back((new mul(mulseq,overall_coeff*seq[i].coeff))->setflag(status_flags::dynallocated)); + } + return (new add(addseq))->setflag(status_flags::dynallocated); } int mul::compare_same_type(const basic & other) const { - return inherited::compare_same_type(other); + return inherited::compare_same_type(other); } bool mul::is_equal_same_type(const basic & other) const { - return inherited::is_equal_same_type(other); + return inherited::is_equal_same_type(other); } unsigned mul::return_type(void) const { - if (seq.size()==0) { - // 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 - if ((rt==return_types::noncommutative)&&(all_commutative)) { - // first nc element found, remember position - cit_noncommutative_element = cit; - all_commutative = 0; - } - if ((rt==return_types::noncommutative)&&(!all_commutative)) { - // another nc element found, compare type_infos - if ((*cit_noncommutative_element).rest.return_type_tinfo()!=(*cit).rest.return_type_tinfo()) { - // diffent types -> mul is ncc - return return_types::noncommutative_composite; - } - } - } - // all factors checked - return all_commutative ? return_types::commutative : return_types::noncommutative; + if (seq.size()==0) { + // 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 + if ((rt==return_types::noncommutative)&&(all_commutative)) { + // first nc element found, remember position + cit_noncommutative_element = cit; + all_commutative = 0; + } + if ((rt==return_types::noncommutative)&&(!all_commutative)) { + // another nc element found, compare type_infos + if ((*cit_noncommutative_element).rest.return_type_tinfo()!=(*cit).rest.return_type_tinfo()) { + // diffent types -> mul is ncc + return return_types::noncommutative_composite; + } + } + } + // all factors checked + return all_commutative ? return_types::commutative : return_types::noncommutative; } unsigned mul::return_type_tinfo(void) const { - if (seq.size()==0) { - // mul without factors: should not happen - return tinfo_key; - } - // 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) { - return (*cit).rest.return_type_tinfo(); - } - } - // no noncommutative element found, should not happen - return tinfo_key; + if (seq.size()==0) { + // mul without factors: should not happen + return tinfo_key; + } + // 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) { + return (*cit).rest.return_type_tinfo(); + } + } + // no noncommutative element found, should not happen + return tinfo_key; } ex mul::thisexpairseq(const epvector & v, const ex & oc) const { - return (new mul(v,oc))->setflag(status_flags::dynallocated); + return (new mul(v,oc))->setflag(status_flags::dynallocated); } ex mul::thisexpairseq(epvector * vp, const ex & oc) const { - return (new mul(vp,oc))->setflag(status_flags::dynallocated); + return (new mul(vp,oc))->setflag(status_flags::dynallocated); } 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)) { - return expair(powerref.basis,powerref.exponent); - } - } - return expair(e,_ex1()); + if (is_ex_exactly_of_type(e,power)) { + 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()); } - + expair mul::combine_ex_with_coeff_to_pair(const ex & e, - const ex & c) const -{ - // to avoid duplication of power simplification rules, - // we create a temporary power object - // otherwise it would be hard to correctly simplify - // expression like (4^(1/3))^(3/2) - if (are_ex_trivially_equal(c,_ex1())) - return split_ex_to_pair(e); - - return split_ex_to_pair(power(e,c)); -} - + const ex & c) const +{ + // to avoid duplication of power simplification rules, + // we create a temporary power object + // otherwise it would be hard to correctly simplify + // expression like (4^(1/3))^(3/2) + if (are_ex_trivially_equal(c,_ex1())) + return split_ex_to_pair(e); + + return split_ex_to_pair(power(e,c)); +} + expair mul::combine_pair_with_coeff_to_pair(const expair & p, - const ex & c) const -{ - // to avoid duplication of power simplification rules, - // we create a temporary power object - // otherwise it would be hard to correctly simplify - // expression like (4^(1/3))^(3/2) - if (are_ex_trivially_equal(c,_ex1())) - return p; - - return split_ex_to_pair(power(recombine_pair_to_ex(p),c)); -} - + const ex & c) const +{ + // to avoid duplication of power simplification rules, + // we create a temporary power object + // otherwise it would be hard to correctly simplify + // expression like (4^(1/3))^(3/2) + if (are_ex_trivially_equal(c,_ex1())) + return p; + + return split_ex_to_pair(power(recombine_pair_to_ex(p),c)); +} + ex mul::recombine_pair_to_ex(const expair & p) const { - // if (p.coeff.compare(_ex1())==0) { - // if (are_ex_trivially_equal(p.coeff,_ex1())) { - if (ex_to_numeric(p.coeff).is_equal(_num1())) - return p.rest; - else - return power(p.rest,p.coeff); + if (ex_to_numeric(p.coeff).is_equal(_num1())) + return p.rest; + else + return power(p.rest,p.coeff); } 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)); - 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; - return true; - } - if (ex_to_numeric((*it).coeff).is_equal(_num1())) { - // combined pair has coeff 1 and must be moved to the end - return true; - } - } - return false; + 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)); + 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; + return true; + } + if (ex_to_numeric((*it).coeff).is_equal(_num1())) { + // combined pair has coeff 1 and must be moved to the end + return true; + } + } + return false; } ex mul::default_overall_coeff(void) const { - return _ex1(); + return _ex1(); } void mul::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).mul_dyn(ex_to_numeric(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).mul_dyn(ex_to_numeric(c)); } void mul::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)); - GINAC_ASSERT(is_ex_exactly_of_type(c2,numeric)); - overall_coeff = ex_to_numeric(overall_coeff). - mul_dyn(ex_to_numeric(c1).power(ex_to_numeric(c2))); + GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric)); + GINAC_ASSERT(is_ex_exactly_of_type(c1,numeric)); + GINAC_ASSERT(is_ex_exactly_of_type(c2,numeric)); + overall_coeff = ex_to_numeric(overall_coeff). + mul_dyn(ex_to_numeric(c1).power(ex_to_numeric(c2))); } bool mul::can_make_flat(const expair & p) const { - GINAC_ASSERT(is_ex_exactly_of_type(p.coeff,numeric)); - // this assertion will probably fail somewhere - // it would require a more careful make_flat, obeying the power laws - // probably should return true only if p.coeff is integer - return ex_to_numeric(p.coeff).is_equal(_num1()); + GINAC_ASSERT(is_ex_exactly_of_type(p.coeff,numeric)); + // this assertion will probably fail somewhere + // it would require a more careful make_flat, obeying the power laws + // probably should return true only if p.coeff is integer + return ex_to_numeric(p.coeff).is_equal(_num1()); } ex mul::expand(unsigned options) const { - if (flags & status_flags::expanded) - return *this; - - exvector sub_expanded_seq; - intvector positions_of_adds; - intvector number_of_add_operands; - - epvector * expanded_seqp = expandchildren(options); - - const epvector & expanded_seq = expanded_seqp==0 ? seq : *expanded_seqp; - - positions_of_adds.resize(expanded_seq.size()); - number_of_add_operands.resize(expanded_seq.size()); - - int number_of_adds = 0; - int number_of_expanded_terms = 1; - - unsigned current_position = 0; - epvector::const_iterator last = expanded_seq.end(); - for (epvector::const_iterator cit = expanded_seq.begin(); cit!=last; ++cit) { - if (is_ex_exactly_of_type((*cit).rest,add) && - ((*cit).coeff.is_equal(_ex1()))) { - positions_of_adds[number_of_adds] = current_position; - const add & expanded_addref = ex_to_add((*cit).rest); - unsigned addref_nops = expanded_addref.nops(); - number_of_add_operands[number_of_adds] = addref_nops; - number_of_expanded_terms *= addref_nops; - ++number_of_adds; - } - ++current_position; - } - - if (number_of_adds==0) { - if (expanded_seqp==0) - return this->setflag(status_flags::expanded); - else - return ((new mul(expanded_seqp,overall_coeff))-> - setflag(status_flags::dynallocated | - status_flags::expanded)); - } - - exvector distrseq; - distrseq.reserve(number_of_expanded_terms); - - intvector k; - k.resize(number_of_adds, 0); - - while (1) { - epvector term; - term = expanded_seq; - for (int l=0; l - setflag(status_flags::dynallocated | - status_flags::expanded)); - - // increment k[] - int l = number_of_adds-1; - while ((l>=0) && ((++k[l])>=number_of_add_operands[l])) { - k[l] = 0; - --l; - } - if (l<0) break; - } - - if (expanded_seqp!=0) - delete expanded_seqp; - - return (new add(distrseq))->setflag(status_flags::dynallocated | - status_flags::expanded); + if (flags & status_flags::expanded) + return *this; + + exvector sub_expanded_seq; + intvector positions_of_adds; + intvector number_of_add_operands; + + epvector * expanded_seqp = expandchildren(options); + + const epvector & expanded_seq = expanded_seqp==0 ? seq : *expanded_seqp; + + positions_of_adds.resize(expanded_seq.size()); + number_of_add_operands.resize(expanded_seq.size()); + + int number_of_adds = 0; + int number_of_expanded_terms = 1; + + unsigned current_position = 0; + epvector::const_iterator last = expanded_seq.end(); + for (epvector::const_iterator cit = expanded_seq.begin(); cit!=last; ++cit) { + if (is_ex_exactly_of_type((*cit).rest,add) && + ((*cit).coeff.is_equal(_ex1()))) { + positions_of_adds[number_of_adds] = current_position; + const add & expanded_addref = ex_to_add((*cit).rest); + unsigned addref_nops = expanded_addref.nops(); + number_of_add_operands[number_of_adds] = addref_nops; + number_of_expanded_terms *= addref_nops; + ++number_of_adds; + } + ++current_position; + } + + if (number_of_adds==0) { + if (expanded_seqp==0) + return this->setflag(status_flags::expanded); + else + return ((new mul(expanded_seqp,overall_coeff))-> + setflag(status_flags::dynallocated | + status_flags::expanded)); + } + + exvector distrseq; + distrseq.reserve(number_of_expanded_terms); + + intvector k; + k.resize(number_of_adds, 0); + + for (;;) { + epvector term; + term = expanded_seq; + for (int l=0; l + setflag(status_flags::dynallocated | + status_flags::expanded)); + + // increment k[] + int l = number_of_adds-1; + while ((l>=0) && ((++k[l])>=number_of_add_operands[l])) { + k[l] = 0; + --l; + } + if (l < 0) break; + } + + if (expanded_seqp!=0) + delete expanded_seqp; + + return (new add(distrseq))->setflag(status_flags::dynallocated | + status_flags::expanded); } ////////// @@ -744,37 +742,37 @@ ex mul::expand(unsigned options) const epvector * mul::expandchildren(unsigned options) const { - epvector::const_iterator last = seq.end(); - epvector::const_iterator cit = seq.begin(); - while (cit!=last) { - const ex & factor = recombine_pair_to_ex(*cit); - const ex & expanded_factor = factor.expand(options); - if (!are_ex_trivially_equal(factor,expanded_factor)) { - - // 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) { - s->push_back(*cit2); - ++cit2; - } - // copy first changed element - s->push_back(split_ex_to_pair(expanded_factor)); - ++cit2; - // copy rest - while (cit2!=last) { - s->push_back(split_ex_to_pair(recombine_pair_to_ex(*cit2).expand(options))); - ++cit2; - } - return s; - } - ++cit; - } - - return 0; // nothing has changed + epvector::const_iterator last = seq.end(); + epvector::const_iterator cit = seq.begin(); + while (cit!=last) { + const ex & factor = recombine_pair_to_ex(*cit); + const ex & expanded_factor = factor.expand(options); + if (!are_ex_trivially_equal(factor,expanded_factor)) { + + // 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) { + s->push_back(*cit2); + ++cit2; + } + // copy first changed element + s->push_back(split_ex_to_pair(expanded_factor)); + ++cit2; + // copy rest + while (cit2!=last) { + s->push_back(split_ex_to_pair(recombine_pair_to_ex(*cit2).expand(options))); + ++cit2; + } + return s; + } + ++cit; + } + + return 0; // nothing has changed } ////////// diff --git a/ginac/mul.h b/ginac/mul.h index bfb92366..8358b57d 100644 --- a/ginac/mul.h +++ b/ginac/mul.h @@ -32,84 +32,84 @@ namespace GiNaC { /** Product of expressions. */ class mul : public expairseq { - GINAC_DECLARE_REGISTERED_CLASS(mul, expairseq) + GINAC_DECLARE_REGISTERED_CLASS(mul, expairseq) - friend class add; - friend class ncmul; - friend class power; + friend class add; + friend class ncmul; + friend class power; // member functions - // default constructor, destructor, copy constructor assignment operator and helpers + // default constructor, destructor, copy constructor assignment operator and helpers public: - mul(); - ~mul(); - mul(const mul & other); - const mul & operator=(const mul & other); + mul(); + ~mul(); + mul(const mul & other); + const mul & operator=(const mul & other); protected: - void copy(const mul & other); - void destroy(bool call_parent); + void copy(const mul & other); + void destroy(bool call_parent); - // other constructors + // other constructors public: - mul(const ex & lh, const ex & rh); - mul(const exvector & v); - mul(const epvector & v); - 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 + mul(const ex & lh, const ex & rh); + mul(const exvector & v); + mul(const epvector & v); + 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: - basic * duplicate() const; - void print(std::ostream & os, unsigned upper_precedence) const; - void printraw(std::ostream & os) const; - void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const; - bool info(unsigned inf) const; - int degree(const symbol & s) const; - int ldegree(const symbol & s) const; - ex coeff(const symbol & s, int n = 1) const; - ex eval(int level=0) const; - ex evalf(int level=0) const; - ex series(const relational & s, int order, unsigned options = 0) const; - ex normal(lst &sym_lst, lst &repl_lst, int level = 0) const; - numeric integer_content(void) const; - ex smod(const numeric &xi) const; - numeric max_coefficient(void) const; - exvector get_indices(void) const; - ex simplify_ncmul(const exvector & v) const; + basic * duplicate() const; + void print(std::ostream & os, unsigned upper_precedence) const; + void printraw(std::ostream & os) const; + void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const; + bool info(unsigned inf) const; + int degree(const symbol & s) const; + int ldegree(const symbol & s) const; + ex coeff(const symbol & s, int n = 1) const; + ex eval(int level=0) const; + ex evalf(int level=0) const; + ex series(const relational & s, int order, unsigned options = 0) const; + ex normal(lst &sym_lst, lst &repl_lst, int level = 0) const; + numeric integer_content(void) const; + ex smod(const numeric &xi) const; + numeric max_coefficient(void) const; + exvector get_indices(void) const; + ex simplify_ncmul(const exvector & v) const; protected: - ex derivative(const symbol & s) const; - int compare_same_type(const basic & other) const; - bool is_equal_same_type(const basic & other) const; - unsigned return_type(void) const; - unsigned return_type_tinfo(void) const; - ex thisexpairseq(const epvector & v, const ex & oc) const; - ex thisexpairseq(epvector * vp, const ex & oc) const; - expair split_ex_to_pair(const ex & e) const; - expair combine_ex_with_coeff_to_pair(const ex & e, - const ex & c) const; - expair combine_pair_with_coeff_to_pair(const expair & p, - const ex & c) const; - ex recombine_pair_to_ex(const expair & p) const; - bool expair_needs_further_processing(epp it); - ex default_overall_coeff(void) const; - void combine_overall_coeff(const ex & c); - void combine_overall_coeff(const ex & c1, const ex & c2); - bool can_make_flat(const expair & p) const; - ex expand(unsigned options=0) const; - - // new virtual functions which can be overridden by derived classes - // none - - // non-virtual functions in this class + ex derivative(const symbol & s) const; + int compare_same_type(const basic & other) const; + bool is_equal_same_type(const basic & other) const; + unsigned return_type(void) const; + unsigned return_type_tinfo(void) const; + ex thisexpairseq(const epvector & v, const ex & oc) const; + ex thisexpairseq(epvector * vp, const ex & oc) const; + expair split_ex_to_pair(const ex & e) const; + expair combine_ex_with_coeff_to_pair(const ex & e, + const ex & c) const; + expair combine_pair_with_coeff_to_pair(const expair & p, + const ex & c) const; + ex recombine_pair_to_ex(const expair & p) const; + bool expair_needs_further_processing(epp it); + ex default_overall_coeff(void) const; + void combine_overall_coeff(const ex & c); + void combine_overall_coeff(const ex & c1, const ex & c2); + bool can_make_flat(const expair & p) const; + ex expand(unsigned options=0) const; + + // new virtual functions which can be overridden by derived classes + // none + + // non-virtual functions in this class protected: - epvector * expandchildren(unsigned options) const; + epvector * expandchildren(unsigned options) const; // member variables protected: - static unsigned precedence; + static unsigned precedence; }; // global constants diff --git a/ginac/ncmul.cpp b/ginac/ncmul.cpp index 9d13a43d..1aa43633 100644 --- a/ginac/ncmul.cpp +++ b/ginac/ncmul.cpp @@ -46,42 +46,42 @@ GINAC_IMPLEMENT_REGISTERED_CLASS(ncmul, exprseq) ncmul::ncmul() { - debugmsg("ncmul default constructor",LOGLEVEL_CONSTRUCT); - tinfo_key = TINFO_ncmul; + debugmsg("ncmul default constructor",LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_ncmul; } ncmul::~ncmul() { - debugmsg("ncmul destructor",LOGLEVEL_DESTRUCT); - destroy(0); + debugmsg("ncmul destructor",LOGLEVEL_DESTRUCT); + destroy(0); } ncmul::ncmul(const ncmul & other) { - debugmsg("ncmul copy constructor",LOGLEVEL_CONSTRUCT); - copy(other); + debugmsg("ncmul copy constructor",LOGLEVEL_CONSTRUCT); + copy(other); } const ncmul & ncmul::operator=(const ncmul & other) { - debugmsg("ncmul operator=",LOGLEVEL_ASSIGNMENT); - if (this != &other) { - destroy(1); - copy(other); - } - return *this; + debugmsg("ncmul operator=",LOGLEVEL_ASSIGNMENT); + if (this != &other) { + destroy(1); + copy(other); + } + return *this; } // protected void ncmul::copy(const ncmul & other) { - inherited::copy(other); + inherited::copy(other); } void ncmul::destroy(bool call_parent) { - if (call_parent) inherited::destroy(call_parent); + if (call_parent) inherited::destroy(call_parent); } ////////// @@ -91,51 +91,51 @@ void ncmul::destroy(bool call_parent) // public ncmul::ncmul(const ex & lh, const ex & rh) : - inherited(lh,rh) + inherited(lh,rh) { - debugmsg("ncmul constructor from ex,ex",LOGLEVEL_CONSTRUCT); - tinfo_key = TINFO_ncmul; + debugmsg("ncmul constructor from ex,ex",LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_ncmul; } ncmul::ncmul(const ex & f1, const ex & f2, const ex & f3) : - inherited(f1,f2,f3) + inherited(f1,f2,f3) { - debugmsg("ncmul constructor from 3 ex",LOGLEVEL_CONSTRUCT); - tinfo_key = TINFO_ncmul; + debugmsg("ncmul constructor from 3 ex",LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_ncmul; } ncmul::ncmul(const ex & f1, const ex & f2, const ex & f3, - const ex & f4) : inherited(f1,f2,f3,f4) + const ex & f4) : inherited(f1,f2,f3,f4) { - debugmsg("ncmul constructor from 4 ex",LOGLEVEL_CONSTRUCT); - tinfo_key = TINFO_ncmul; + debugmsg("ncmul constructor from 4 ex",LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_ncmul; } ncmul::ncmul(const ex & f1, const ex & f2, const ex & f3, - const ex & f4, const ex & f5) : inherited(f1,f2,f3,f4,f5) + const ex & f4, const ex & f5) : inherited(f1,f2,f3,f4,f5) { - debugmsg("ncmul constructor from 5 ex",LOGLEVEL_CONSTRUCT); - tinfo_key = TINFO_ncmul; + debugmsg("ncmul constructor from 5 ex",LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_ncmul; } ncmul::ncmul(const ex & f1, const ex & f2, const ex & f3, - const ex & f4, const ex & f5, const ex & f6) : - inherited(f1,f2,f3,f4,f5,f6) + const ex & f4, const ex & f5, const ex & f6) : + inherited(f1,f2,f3,f4,f5,f6) { - debugmsg("ncmul constructor from 6 ex",LOGLEVEL_CONSTRUCT); - tinfo_key = TINFO_ncmul; + debugmsg("ncmul constructor from 6 ex",LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_ncmul; } ncmul::ncmul(const exvector & v, bool discardable) : inherited(v,discardable) { - debugmsg("ncmul constructor from exvector,bool",LOGLEVEL_CONSTRUCT); - tinfo_key = TINFO_ncmul; + debugmsg("ncmul constructor from exvector,bool",LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_ncmul; } ncmul::ncmul(exvector * vp) : inherited(vp) { - debugmsg("ncmul constructor from exvector *",LOGLEVEL_CONSTRUCT); - tinfo_key = TINFO_ncmul; + debugmsg("ncmul constructor from exvector *",LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_ncmul; } ////////// @@ -145,22 +145,22 @@ ncmul::ncmul(exvector * vp) : inherited(vp) /** Construct object from archive_node. */ ncmul::ncmul(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) { - debugmsg("ncmul constructor from archive_node", LOGLEVEL_CONSTRUCT); + debugmsg("ncmul constructor from archive_node", LOGLEVEL_CONSTRUCT); } /** Unarchive the object. */ ex ncmul::unarchive(const archive_node &n, const lst &sym_lst) { - return (new ncmul(n, sym_lst))->setflag(status_flags::dynallocated); + return (new ncmul(n, sym_lst))->setflag(status_flags::dynallocated); } /** Archive the object. */ void ncmul::archive(archive_node &n) const { - inherited::archive(n); + inherited::archive(n); } - + ////////// // functions overriding virtual functions from bases classes ////////// @@ -169,192 +169,192 @@ void ncmul::archive(archive_node &n) const basic * ncmul::duplicate() const { - debugmsg("ncmul duplicate",LOGLEVEL_ASSIGNMENT); - return new ncmul(*this); + debugmsg("ncmul duplicate",LOGLEVEL_ASSIGNMENT); + return new ncmul(*this); } void ncmul::print(std::ostream & os, unsigned upper_precedence) const { - debugmsg("ncmul print",LOGLEVEL_PRINT); - printseq(os,'(','%',')',precedence,upper_precedence); + debugmsg("ncmul print",LOGLEVEL_PRINT); + printseq(os,'(','%',')',precedence,upper_precedence); } void ncmul::printraw(std::ostream & os) const { - debugmsg("ncmul printraw",LOGLEVEL_PRINT); + debugmsg("ncmul printraw",LOGLEVEL_PRINT); - os << "%("; - for (exvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) { - (*it).bp->printraw(os); - os << ","; - } - os << ",hash=" << hashvalue << ",flags=" << flags; - os << ")"; + os << "%("; + for (exvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) { + (*it).bp->printraw(os); + os << ","; + } + os << ",hash=" << hashvalue << ",flags=" << flags; + os << ")"; } void ncmul::printcsrc(std::ostream & os, unsigned upper_precedence) const { - debugmsg("ncmul print csrc",LOGLEVEL_PRINT); - exvector::const_iterator it; - exvector::const_iterator itend = seq.end()-1; - os << "ncmul("; - for (it=seq.begin(); it!=itend; ++it) { - (*it).bp->printcsrc(os,precedence); - os << ","; - } - (*it).bp->printcsrc(os,precedence); - os << ")"; + debugmsg("ncmul print csrc",LOGLEVEL_PRINT); + exvector::const_iterator it; + exvector::const_iterator itend = seq.end()-1; + os << "ncmul("; + for (it=seq.begin(); it!=itend; ++it) { + (*it).bp->printcsrc(os,precedence); + os << ","; + } + (*it).bp->printcsrc(os,precedence); + os << ")"; } bool ncmul::info(unsigned inf) const { - throw(std::logic_error("which flags have to be implemented in ncmul::info()?")); + throw(std::logic_error("which flags have to be implemented in ncmul::info()?")); } typedef std::vector intvector; ex ncmul::expand(unsigned options) const { - exvector sub_expanded_seq; - intvector positions_of_adds; - intvector number_of_add_operands; - - exvector expanded_seq=expandchildren(options); - - positions_of_adds.resize(expanded_seq.size()); - number_of_add_operands.resize(expanded_seq.size()); - - int number_of_adds=0; - int number_of_expanded_terms=1; - - unsigned current_position=0; - exvector::const_iterator last=expanded_seq.end(); - for (exvector::const_iterator cit=expanded_seq.begin(); cit!=last; ++cit) { - if (is_ex_exactly_of_type((*cit),add)) { - positions_of_adds[number_of_adds]=current_position; - const add & expanded_addref=ex_to_add(*cit); - number_of_add_operands[number_of_adds]=expanded_addref.seq.size(); - number_of_expanded_terms *= expanded_addref.seq.size(); - number_of_adds++; - } - current_position++; - } - - if (number_of_adds==0) { - return (new ncmul(expanded_seq,1))->setflag(status_flags::dynallocated || - status_flags::expanded); - } - - exvector distrseq; - distrseq.reserve(number_of_expanded_terms); - - intvector k; - k.resize(number_of_adds); - - int l; - for (l=0; lsetflag(status_flags::dynallocated | - status_flags::expanded)); - - // increment k[] - l=number_of_adds-1; - while ((l>=0)&&((++k[l])>=number_of_add_operands[l])) { - k[l]=0; - l--; - } - if (l<0) break; - } - - return (new add(distrseq))->setflag(status_flags::dynallocated | - status_flags::expanded); + exvector sub_expanded_seq; + intvector positions_of_adds; + intvector number_of_add_operands; + + exvector expanded_seq=expandchildren(options); + + positions_of_adds.resize(expanded_seq.size()); + number_of_add_operands.resize(expanded_seq.size()); + + int number_of_adds=0; + int number_of_expanded_terms=1; + + unsigned current_position=0; + exvector::const_iterator last=expanded_seq.end(); + for (exvector::const_iterator cit=expanded_seq.begin(); cit!=last; ++cit) { + if (is_ex_exactly_of_type((*cit),add)) { + positions_of_adds[number_of_adds]=current_position; + const add & expanded_addref=ex_to_add(*cit); + number_of_add_operands[number_of_adds]=expanded_addref.seq.size(); + number_of_expanded_terms *= expanded_addref.seq.size(); + number_of_adds++; + } + current_position++; + } + + if (number_of_adds==0) { + return (new ncmul(expanded_seq,1))->setflag(status_flags::dynallocated || + status_flags::expanded); + } + + exvector distrseq; + distrseq.reserve(number_of_expanded_terms); + + intvector k; + k.resize(number_of_adds); + + int l; + for (l=0; lsetflag(status_flags::dynallocated | + status_flags::expanded)); + + // increment k[] + l=number_of_adds-1; + while ((l>=0)&&((++k[l])>=number_of_add_operands[l])) { + k[l]=0; + l--; + } + if (l<0) break; + } + + return (new add(distrseq))->setflag(status_flags::dynallocated | + status_flags::expanded); } int ncmul::degree(const symbol & s) const { - int deg_sum=0; - for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { - deg_sum+=(*cit).degree(s); - } - return deg_sum; + int deg_sum=0; + for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { + deg_sum+=(*cit).degree(s); + } + return deg_sum; } int ncmul::ldegree(const symbol & s) const { - int deg_sum=0; - for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { - deg_sum+=(*cit).ldegree(s); - } - return deg_sum; + int deg_sum=0; + for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { + deg_sum+=(*cit).ldegree(s); + } + return deg_sum; } ex ncmul::coeff(const symbol & s, int n) const { - exvector coeffseq; - coeffseq.reserve(seq.size()); - - if (n==0) { - // product of individual coeffs - // if a non-zero power of s is found, the resulting product will be 0 - exvector::const_iterator it=seq.begin(); - while (it!=seq.end()) { - coeffseq.push_back((*it).coeff(s,n)); - ++it; - } - return (new ncmul(coeffseq,1))->setflag(status_flags::dynallocated); - } - - exvector::const_iterator it=seq.begin(); - bool coeff_found=0; - while (it!=seq.end()) { - ex c=(*it).coeff(s,n); - if (!c.is_zero()) { - coeffseq.push_back(c); - coeff_found=1; - } else { - coeffseq.push_back(*it); - } - ++it; - } - - if (coeff_found) return (new ncmul(coeffseq,1))->setflag(status_flags::dynallocated); - - return _ex0(); + exvector coeffseq; + coeffseq.reserve(seq.size()); + + if (n==0) { + // product of individual coeffs + // if a non-zero power of s is found, the resulting product will be 0 + exvector::const_iterator it=seq.begin(); + while (it!=seq.end()) { + coeffseq.push_back((*it).coeff(s,n)); + ++it; + } + return (new ncmul(coeffseq,1))->setflag(status_flags::dynallocated); + } + + exvector::const_iterator it=seq.begin(); + bool coeff_found=0; + while (it!=seq.end()) { + ex c=(*it).coeff(s,n); + if (!c.is_zero()) { + coeffseq.push_back(c); + coeff_found=1; + } else { + coeffseq.push_back(*it); + } + ++it; + } + + if (coeff_found) return (new ncmul(coeffseq,1))->setflag(status_flags::dynallocated); + + return _ex0(); } unsigned ncmul::count_factors(const ex & e) const { - if ((is_ex_exactly_of_type(e,mul)&&(e.return_type()!=return_types::commutative))|| - (is_ex_exactly_of_type(e,ncmul))) { - unsigned factors=0; - for (unsigned i=0; i unsignedvector; @@ -362,178 +362,178 @@ typedef std::vector exvectorvector; ex ncmul::eval(int level) const { - // simplifications: ncmul(...,*(x1,x2),...,ncmul(x3,x4),...) -> - // ncmul(...,x1,x2,...,x3,x4,...) (associativity) - // ncmul(x) -> x - // ncmul() -> 1 - // ncmul(...,c1,...,c2,...) -> - // *(c1,c2,ncmul(...)) (pull out commutative elements) - // ncmul(x1,y1,x2,y2) -> *(ncmul(x1,x2),ncmul(y1,y2)) - // (collect elements of same type) - // ncmul(x1,x2,x3,...) -> x::eval_ncmul(x1,x2,x3,...) - // the following rule would be nice, but produces a recursion, - // which must be trapped by introducing a flag that the sub-ncmuls() - // are already evaluated (maybe later...) - // ncmul(x1,x2,...,X,y1,y2,...) -> - // ncmul(ncmul(x1,x2,...),X,ncmul(y1,y2,...) - // (X noncommutative_composite) - - if ((level==1)&&(flags & status_flags::evaluated)) { - return *this; - } - - exvector evaledseq=evalchildren(level); - - // ncmul(...,*(x1,x2),...,ncmul(x3,x4),...) -> - // ncmul(...,x1,x2,...,x3,x4,...) (associativity) - unsigned factors=0; - for (exvector::const_iterator cit=evaledseq.begin(); cit!=evaledseq.end(); ++cit) { - factors += count_factors(*cit); - } - - exvector assocseq; - assocseq.reserve(factors); - for (exvector::const_iterator cit=evaledseq.begin(); cit!=evaledseq.end(); ++cit) { - append_factors(assocseq,*cit); - } - - // ncmul(x) -> x - if (assocseq.size()==1) return *(seq.begin()); - - // ncmul() -> 1 - if (assocseq.size()==0) return _ex1(); - - // determine return types - unsignedvector rettypes; - rettypes.reserve(assocseq.size()); - unsigned i=0; - unsigned count_commutative=0; - unsigned count_noncommutative=0; - unsigned count_noncommutative_composite=0; - for (exvector::const_iterator cit=assocseq.begin(); cit!=assocseq.end(); ++cit) { - switch (rettypes[i]=(*cit).return_type()) { - case return_types::commutative: - count_commutative++; - break; - case return_types::noncommutative: - count_noncommutative++; - break; - case return_types::noncommutative_composite: - count_noncommutative_composite++; - break; - default: - throw(std::logic_error("ncmul::eval(): invalid return type")); - } - ++i; - } - GINAC_ASSERT(count_commutative+count_noncommutative+count_noncommutative_composite==assocseq.size()); - - // ncmul(...,c1,...,c2,...) -> - // *(c1,c2,ncmul(...)) (pull out commutative elements) - if (count_commutative!=0) { - exvector commutativeseq; - commutativeseq.reserve(count_commutative+1); - exvector noncommutativeseq; - noncommutativeseq.reserve(assocseq.size()-count_commutative); - for (i=0; i - setflag(status_flags::dynallocated)); - return (new mul(commutativeseq))->setflag(status_flags::dynallocated); - } - - // ncmul(x1,y1,x2,y2) -> *(ncmul(x1,x2),ncmul(y1,y2)) - // (collect elements of same type) - - if (count_noncommutative_composite==0) { - // there are neither commutative nor noncommutative_composite - // elements in assocseq - GINAC_ASSERT(count_commutative==0); - - exvectorvector evv; - unsignedvector rttinfos; - evv.reserve(assocseq.size()); - rttinfos.reserve(assocseq.size()); - - for (exvector::const_iterator cit=assocseq.begin(); cit!=assocseq.end(); ++cit) { - unsigned ti=(*cit).return_type_tinfo(); - // search type in vector of known types - for (i=0; i=rttinfos.size()) { - // new type - rttinfos.push_back(ti); - evv.push_back(exvector()); - (*(evv.end()-1)).reserve(assocseq.size()); - (*(evv.end()-1)).push_back(*cit); - } - } + // simplifications: ncmul(...,*(x1,x2),...,ncmul(x3,x4),...) -> + // ncmul(...,x1,x2,...,x3,x4,...) (associativity) + // ncmul(x) -> x + // ncmul() -> 1 + // ncmul(...,c1,...,c2,...) -> + // *(c1,c2,ncmul(...)) (pull out commutative elements) + // ncmul(x1,y1,x2,y2) -> *(ncmul(x1,x2),ncmul(y1,y2)) + // (collect elements of same type) + // ncmul(x1,x2,x3,...) -> x::eval_ncmul(x1,x2,x3,...) + // the following rule would be nice, but produces a recursion, + // which must be trapped by introducing a flag that the sub-ncmuls() + // are already evaluated (maybe later...) + // ncmul(x1,x2,...,X,y1,y2,...) -> + // ncmul(ncmul(x1,x2,...),X,ncmul(y1,y2,...) + // (X noncommutative_composite) + + if ((level==1)&&(flags & status_flags::evaluated)) { + return *this; + } + + exvector evaledseq=evalchildren(level); + + // ncmul(...,*(x1,x2),...,ncmul(x3,x4),...) -> + // ncmul(...,x1,x2,...,x3,x4,...) (associativity) + unsigned factors=0; + for (exvector::const_iterator cit=evaledseq.begin(); cit!=evaledseq.end(); ++cit) { + factors += count_factors(*cit); + } + + exvector assocseq; + assocseq.reserve(factors); + for (exvector::const_iterator cit=evaledseq.begin(); cit!=evaledseq.end(); ++cit) { + append_factors(assocseq,*cit); + } + + // ncmul(x) -> x + if (assocseq.size()==1) return *(seq.begin()); + + // ncmul() -> 1 + if (assocseq.size()==0) return _ex1(); + + // determine return types + unsignedvector rettypes; + rettypes.reserve(assocseq.size()); + unsigned i=0; + unsigned count_commutative=0; + unsigned count_noncommutative=0; + unsigned count_noncommutative_composite=0; + for (exvector::const_iterator cit=assocseq.begin(); cit!=assocseq.end(); ++cit) { + switch (rettypes[i]=(*cit).return_type()) { + case return_types::commutative: + count_commutative++; + break; + case return_types::noncommutative: + count_noncommutative++; + break; + case return_types::noncommutative_composite: + count_noncommutative_composite++; + break; + default: + throw(std::logic_error("ncmul::eval(): invalid return type")); + } + ++i; + } + GINAC_ASSERT(count_commutative+count_noncommutative+count_noncommutative_composite==assocseq.size()); + + // ncmul(...,c1,...,c2,...) -> + // *(c1,c2,ncmul(...)) (pull out commutative elements) + if (count_commutative!=0) { + exvector commutativeseq; + commutativeseq.reserve(count_commutative+1); + exvector noncommutativeseq; + noncommutativeseq.reserve(assocseq.size()-count_commutative); + for (i=0; i + setflag(status_flags::dynallocated)); + return (new mul(commutativeseq))->setflag(status_flags::dynallocated); + } + + // ncmul(x1,y1,x2,y2) -> *(ncmul(x1,x2),ncmul(y1,y2)) + // (collect elements of same type) + + if (count_noncommutative_composite==0) { + // there are neither commutative nor noncommutative_composite + // elements in assocseq + GINAC_ASSERT(count_commutative==0); + + exvectorvector evv; + unsignedvector rttinfos; + evv.reserve(assocseq.size()); + rttinfos.reserve(assocseq.size()); + + for (exvector::const_iterator cit=assocseq.begin(); cit!=assocseq.end(); ++cit) { + unsigned ti=(*cit).return_type_tinfo(); + // search type in vector of known types + for (i=0; i=rttinfos.size()) { + // new type + rttinfos.push_back(ti); + evv.push_back(exvector()); + (*(evv.end()-1)).reserve(assocseq.size()); + (*(evv.end()-1)).push_back(*cit); + } + } #ifdef DO_GINAC_ASSERT - GINAC_ASSERT(evv.size()==rttinfos.size()); - GINAC_ASSERT(evv.size()>0); - unsigned s=0; - for (i=0; i0); + unsigned s=0; + for (i=0; i - setflag(status_flags::dynallocated)); - } - - return (new mul(splitseq))->setflag(status_flags::dynallocated); - } - - return (new ncmul(assocseq))->setflag(status_flags::dynallocated | - status_flags::evaluated); + + // if all elements are of same type, simplify the string + if (evv.size()==1) { + return evv[0][0].simplify_ncmul(evv[0]); + } + + exvector splitseq; + splitseq.reserve(evv.size()); + for (i=0; i + setflag(status_flags::dynallocated)); + } + + return (new mul(splitseq))->setflag(status_flags::dynallocated); + } + + return (new ncmul(assocseq))->setflag(status_flags::dynallocated | + status_flags::evaluated); } exvector ncmul::get_indices(void) const { - // return union of indices of factors - exvector iv; - for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { - exvector subiv=(*cit).get_indices(); - iv.reserve(iv.size()+subiv.size()); - for (exvector::const_iterator cit2=subiv.begin(); cit2!=subiv.end(); ++cit2) { - iv.push_back(*cit2); - } - } - return iv; + // return union of indices of factors + exvector iv; + for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { + exvector subiv=(*cit).get_indices(); + iv.reserve(iv.size()+subiv.size()); + for (exvector::const_iterator cit2=subiv.begin(); cit2!=subiv.end(); ++cit2) { + iv.push_back(*cit2); + } + } + return iv; } ex ncmul::subs(const lst & ls, const lst & lr) const { - return ncmul(subschildren(ls, lr)); + return ncmul(subschildren(ls, lr)); } ex ncmul::thisexprseq(const exvector & v) const { - return (new ncmul(v))->setflag(status_flags::dynallocated); + return (new ncmul(v))->setflag(status_flags::dynallocated); } ex ncmul::thisexprseq(exvector * vp) const { - return (new ncmul(vp))->setflag(status_flags::dynallocated); + return (new ncmul(vp))->setflag(status_flags::dynallocated); } // protected @@ -542,60 +542,60 @@ ex ncmul::thisexprseq(exvector * vp) const * @see ex::diff */ ex ncmul::derivative(const symbol & s) const { - return _ex0(); + return _ex0(); } int ncmul::compare_same_type(const basic & other) const { - return inherited::compare_same_type(other); + return inherited::compare_same_type(other); } unsigned ncmul::return_type(void) const { - if (seq.size()==0) { - // ncmul without factors: should not happen, but commutes - return return_types::commutative; - } - - bool all_commutative=1; - unsigned rt; - exvector::const_iterator cit_noncommutative_element; // point to first found nc element - - for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { - rt=(*cit).return_type(); - if (rt==return_types::noncommutative_composite) return rt; // one ncc -> mul also ncc - if ((rt==return_types::noncommutative)&&(all_commutative)) { - // first nc element found, remember position - cit_noncommutative_element=cit; - all_commutative=0; - } - if ((rt==return_types::noncommutative)&&(!all_commutative)) { - // another nc element found, compare type_infos - if ((*cit_noncommutative_element).return_type_tinfo()!=(*cit).return_type_tinfo()) { - // diffent types -> mul is ncc - return return_types::noncommutative_composite; - } - } - } - // all factors checked - GINAC_ASSERT(!all_commutative); // not all factors should commute, because this is a ncmul(); - return all_commutative ? return_types::commutative : return_types::noncommutative; + if (seq.size()==0) { + // ncmul without factors: should not happen, but commutes + return return_types::commutative; + } + + bool all_commutative=1; + unsigned rt; + exvector::const_iterator cit_noncommutative_element; // point to first found nc element + + for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { + rt=(*cit).return_type(); + if (rt==return_types::noncommutative_composite) return rt; // one ncc -> mul also ncc + if ((rt==return_types::noncommutative)&&(all_commutative)) { + // first nc element found, remember position + cit_noncommutative_element=cit; + all_commutative=0; + } + if ((rt==return_types::noncommutative)&&(!all_commutative)) { + // another nc element found, compare type_infos + if ((*cit_noncommutative_element).return_type_tinfo()!=(*cit).return_type_tinfo()) { + // diffent types -> mul is ncc + return return_types::noncommutative_composite; + } + } + } + // all factors checked + GINAC_ASSERT(!all_commutative); // not all factors should commute, because this is a ncmul(); + return all_commutative ? return_types::commutative : return_types::noncommutative; } unsigned ncmul::return_type_tinfo(void) const { - if (seq.size()==0) { - // mul without factors: should not happen - return tinfo_key; - } - // return type_info of first noncommutative element - for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { - if ((*cit).return_type()==return_types::noncommutative) { - return (*cit).return_type_tinfo(); - } - } - // no noncommutative element found, should not happen - return tinfo_key; + if (seq.size()==0) { + // mul without factors: should not happen + return tinfo_key; + } + // return type_info of first noncommutative element + for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { + if ((*cit).return_type()==return_types::noncommutative) { + return (*cit).return_type_tinfo(); + } + } + // no noncommutative element found, should not happen + return tinfo_key; } ////////// @@ -610,18 +610,18 @@ unsigned ncmul::return_type_tinfo(void) const exvector ncmul::expandchildren(unsigned options) const { - exvector s; - s.reserve(seq.size()); + exvector s; + s.reserve(seq.size()); - for (exvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) { - s.push_back((*it).expand(options)); - } - return s; + for (exvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) { + s.push_back((*it).expand(options)); + } + return s; } const exvector & ncmul::get_factors(void) const { - return seq; + return seq; } ////////// @@ -646,18 +646,18 @@ const type_info & typeid_ncmul=typeid(some_ncmul); ex nonsimplified_ncmul(const exvector & v) { - return (new ncmul(v))->setflag(status_flags::dynallocated); + return (new ncmul(v))->setflag(status_flags::dynallocated); } ex simplified_ncmul(const exvector & v) { - if (v.size()==0) { - return _ex1(); - } else if (v.size()==1) { - return v[0]; - } - return (new ncmul(v))->setflag(status_flags::dynallocated | - status_flags::evaluated); + if (v.size()==0) { + return _ex1(); + } else if (v.size()==1) { + return v[0]; + } + return (new ncmul(v))->setflag(status_flags::dynallocated | + status_flags::evaluated); } #ifndef NO_NAMESPACE_GINAC diff --git a/ginac/ncmul.h b/ginac/ncmul.h index 7476e290..acb4edee 100644 --- a/ginac/ncmul.h +++ b/ginac/ncmul.h @@ -32,74 +32,74 @@ namespace GiNaC { /** Non-commutative product of expressions. */ class ncmul : public exprseq { - GINAC_DECLARE_REGISTERED_CLASS(ncmul, exprseq) + GINAC_DECLARE_REGISTERED_CLASS(ncmul, exprseq) - friend class power; - friend ex nonsimplified_ncmul(const exvector & v); - friend ex simplified_ncmul(const exvector & v); + friend class power; + friend ex nonsimplified_ncmul(const exvector & v); + friend ex simplified_ncmul(const exvector & v); // member functions - // default constructor, destructor, copy constructor assignment operator and helpers + // default constructor, destructor, copy constructor assignment operator and helpers public: - ncmul(); - ~ncmul(); - ncmul(const ncmul & other); - const ncmul & operator=(const ncmul & other); + ncmul(); + ~ncmul(); + ncmul(const ncmul & other); + const ncmul & operator=(const ncmul & other); protected: - void copy(const ncmul & other); - void destroy(bool call_parent); + void copy(const ncmul & other); + void destroy(bool call_parent); - // other constructors + // other constructors public: - ncmul(const ex & lh, const ex & rh); - ncmul(const ex & f1, const ex & f2, const ex & f3); - ncmul(const ex & f1, const ex & f2, const ex & f3, - const ex & f4); - ncmul(const ex & f1, const ex & f2, const ex & f3, - const ex & f4, const ex & f5); - ncmul(const ex & f1, const ex & f2, const ex & f3, - const ex & f4, const ex & f5, const ex & f6); - ncmul(const exvector & v, bool discardable=false); - ncmul(exvector * vp); // vp will be deleted - - // functions overriding virtual functions from bases classes + ncmul(const ex & lh, const ex & rh); + ncmul(const ex & f1, const ex & f2, const ex & f3); + ncmul(const ex & f1, const ex & f2, const ex & f3, + const ex & f4); + ncmul(const ex & f1, const ex & f2, const ex & f3, + const ex & f4, const ex & f5); + ncmul(const ex & f1, const ex & f2, const ex & f3, + const ex & f4, const ex & f5, const ex & f6); + ncmul(const exvector & v, bool discardable=false); + ncmul(exvector * vp); // vp will be deleted + + // functions overriding virtual functions from bases classes public: - basic * duplicate() const; - void print(std::ostream & os, unsigned upper_precedence) const; - void printraw(std::ostream & os) const; - void printcsrc(std::ostream & os, unsigned upper_precedence) const; - bool info(unsigned inf) const; - int degree(const symbol & s) const; - int ldegree(const symbol & s) const; - ex expand(unsigned options=0) const; - ex coeff(const symbol & s, int n=1) const; - ex eval(int level=0) const; - ex subs(const lst & ls, const lst & lr) const; - exvector get_indices(void) const; - ex thisexprseq(const exvector & v) const; - ex thisexprseq(exvector * vp) const; + basic * duplicate() const; + void print(std::ostream & os, unsigned upper_precedence) const; + void printraw(std::ostream & os) const; + void printcsrc(std::ostream & os, unsigned upper_precedence) const; + bool info(unsigned inf) const; + int degree(const symbol & s) const; + int ldegree(const symbol & s) const; + ex expand(unsigned options=0) const; + ex coeff(const symbol & s, int n=1) const; + ex eval(int level=0) const; + ex subs(const lst & ls, const lst & lr) const; + exvector get_indices(void) const; + ex thisexprseq(const exvector & v) const; + ex thisexprseq(exvector * vp) const; protected: - ex derivative(const symbol & s) const; - int compare_same_type(const basic & other) const; - unsigned return_type(void) const; - unsigned return_type_tinfo(void) const; - - // new virtual functions which can be overridden by derived classes - // none - - // non-virtual functions in this class + ex derivative(const symbol & s) const; + int compare_same_type(const basic & other) const; + unsigned return_type(void) const; + unsigned return_type_tinfo(void) const; + + // new virtual functions which can be overridden by derived classes + // none + + // non-virtual functions in this class protected: - unsigned count_factors(const ex & e) const; - void append_factors(exvector & v, const ex & e) const; - exvector expandchildren(unsigned options) const; + unsigned count_factors(const ex & e) const; + void append_factors(exvector & v, const ex & e) const; + exvector expandchildren(unsigned options) const; public: - const exvector & get_factors(void) const; + const exvector & get_factors(void) const; // member variables protected: - static unsigned precedence; + static unsigned precedence; }; // global constants diff --git a/ginac/normal.cpp b/ginac/normal.cpp index 514423c9..851b7ba7 100644 --- a/ginac/normal.cpp +++ b/ginac/normal.cpp @@ -96,18 +96,18 @@ static struct _stat_print { * @return "false" if no symbol was found, "true" otherwise */ static bool get_first_symbol(const ex &e, const symbol *&x) { - if (is_ex_exactly_of_type(e, symbol)) { - x = static_cast(e.bp); - return true; - } else if (is_ex_exactly_of_type(e, add) || is_ex_exactly_of_type(e, mul)) { - for (unsigned i=0; i(e.bp); + return true; + } else if (is_ex_exactly_of_type(e, add) || is_ex_exactly_of_type(e, mul)) { + for (unsigned i=0; i sym_desc_vec; // Add symbol the sym_desc_vec (used internally by get_symbol_stats()) static void add_symbol(const symbol *s, sym_desc_vec &v) { - sym_desc_vec::iterator it = v.begin(), itend = v.end(); - while (it != itend) { - if (it->sym->compare(*s) == 0) // If it's already in there, don't add it a second time - return; - it++; - } - sym_desc d; - d.sym = s; - v.push_back(d); + sym_desc_vec::iterator it = v.begin(), itend = v.end(); + while (it != itend) { + if (it->sym->compare(*s) == 0) // If it's already in there, don't add it a second time + return; + it++; + } + sym_desc d; + d.sym = s; + v.push_back(d); } // Collect all symbols of an expression (used internally by get_symbol_stats()) static void collect_symbols(const ex &e, sym_desc_vec &v) { - if (is_ex_exactly_of_type(e, symbol)) { - add_symbol(static_cast(e.bp), v); - } else if (is_ex_exactly_of_type(e, add) || is_ex_exactly_of_type(e, mul)) { - for (unsigned i=0; i(e.bp), v); + } else if (is_ex_exactly_of_type(e, add) || is_ex_exactly_of_type(e, mul)) { + for (unsigned i=0; isym)); - int deg_b = b.degree(*(it->sym)); - it->deg_a = deg_a; - it->deg_b = deg_b; - it->max_deg = max(deg_a, deg_b); - it->ldeg_a = a.ldegree(*(it->sym)); - it->ldeg_b = b.ldegree(*(it->sym)); - it++; - } - sort(v.begin(), v.end()); + collect_symbols(a.eval(), v); // eval() to expand assigned symbols + collect_symbols(b.eval(), v); + sym_desc_vec::iterator it = v.begin(), itend = v.end(); + while (it != itend) { + int deg_a = a.degree(*(it->sym)); + int deg_b = b.degree(*(it->sym)); + it->deg_a = deg_a; + it->deg_b = deg_b; + it->max_deg = max(deg_a, deg_b); + it->ldeg_a = a.ldegree(*(it->sym)); + it->ldeg_b = b.ldegree(*(it->sym)); + it++; + } + sort(v.begin(), v.end()); #if 0 std::clog << "Symbols:\n"; it = v.begin(); itend = v.end(); @@ -222,21 +222,21 @@ static void get_symbol_stats(const ex &a, const ex &b, sym_desc_vec &v) // expression recursively (used internally by lcm_of_coefficients_denominators()) static numeric lcmcoeff(const ex &e, const numeric &l) { - if (e.info(info_flags::rational)) - return lcm(ex_to_numeric(e).denom(), l); - else if (is_ex_exactly_of_type(e, add)) { - numeric c = _num1(); - for (unsigned i=0; iinteger_content(); + GINAC_ASSERT(bp!=0); + return bp->integer_content(); } numeric basic::integer_content(void) const { - return _num1(); + return _num1(); } numeric numeric::integer_content(void) const { - return abs(*this); + return abs(*this); } numeric add::integer_content(void) const { - epvector::const_iterator it = seq.begin(); - epvector::const_iterator itend = seq.end(); - numeric c = _num0(); - while (it != itend) { - GINAC_ASSERT(!is_ex_exactly_of_type(it->rest,numeric)); - GINAC_ASSERT(is_ex_exactly_of_type(it->coeff,numeric)); - c = gcd(ex_to_numeric(it->coeff), c); - it++; - } - GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric)); - c = gcd(ex_to_numeric(overall_coeff),c); - return c; + epvector::const_iterator it = seq.begin(); + epvector::const_iterator itend = seq.end(); + numeric c = _num0(); + while (it != itend) { + GINAC_ASSERT(!is_ex_exactly_of_type(it->rest,numeric)); + GINAC_ASSERT(is_ex_exactly_of_type(it->coeff,numeric)); + c = gcd(ex_to_numeric(it->coeff), c); + it++; + } + GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric)); + c = gcd(ex_to_numeric(overall_coeff),c); + return c; } numeric mul::integer_content(void) const { #ifdef DO_GINAC_ASSERT - epvector::const_iterator it = seq.begin(); - epvector::const_iterator itend = seq.end(); - while (it != itend) { - GINAC_ASSERT(!is_ex_exactly_of_type(recombine_pair_to_ex(*it),numeric)); - ++it; - } + epvector::const_iterator it = seq.begin(); + epvector::const_iterator itend = seq.end(); + while (it != itend) { + GINAC_ASSERT(!is_ex_exactly_of_type(recombine_pair_to_ex(*it),numeric)); + ++it; + } #endif // def DO_GINAC_ASSERT - GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric)); - return abs(ex_to_numeric(overall_coeff)); + GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric)); + return abs(ex_to_numeric(overall_coeff)); } @@ -347,42 +347,42 @@ numeric mul::integer_content(void) const * @return quotient of a and b in Q[x] */ ex quo(const ex &a, const ex &b, const symbol &x, bool check_args) { - if (b.is_zero()) - throw(std::overflow_error("quo: division by zero")); - if (is_ex_exactly_of_type(a, numeric) && is_ex_exactly_of_type(b, numeric)) - return a / b; + if (b.is_zero()) + throw(std::overflow_error("quo: division by zero")); + if (is_ex_exactly_of_type(a, numeric) && is_ex_exactly_of_type(b, numeric)) + return a / b; #if FAST_COMPARE - if (a.is_equal(b)) - return _ex1(); + if (a.is_equal(b)) + return _ex1(); #endif - if (check_args && (!a.info(info_flags::rational_polynomial) || !b.info(info_flags::rational_polynomial))) - throw(std::invalid_argument("quo: arguments must be polynomials over the rationals")); - - // Polynomial long division - ex q = _ex0(); - ex r = a.expand(); - if (r.is_zero()) - return r; - int bdeg = b.degree(x); - int rdeg = r.degree(x); - ex blcoeff = b.expand().coeff(x, bdeg); - bool blcoeff_is_numeric = is_ex_exactly_of_type(blcoeff, numeric); - while (rdeg >= bdeg) { - ex term, rcoeff = r.coeff(x, rdeg); - if (blcoeff_is_numeric) - term = rcoeff / blcoeff; - else { - if (!divide(rcoeff, blcoeff, term, false)) - return *new ex(fail()); - } - term *= power(x, rdeg - bdeg); - q += term; - r -= (term * b).expand(); - if (r.is_zero()) - break; - rdeg = r.degree(x); - } - return q; + if (check_args && (!a.info(info_flags::rational_polynomial) || !b.info(info_flags::rational_polynomial))) + throw(std::invalid_argument("quo: arguments must be polynomials over the rationals")); + + // Polynomial long division + ex q = _ex0(); + ex r = a.expand(); + if (r.is_zero()) + return r; + int bdeg = b.degree(x); + int rdeg = r.degree(x); + ex blcoeff = b.expand().coeff(x, bdeg); + bool blcoeff_is_numeric = is_ex_exactly_of_type(blcoeff, numeric); + while (rdeg >= bdeg) { + ex term, rcoeff = r.coeff(x, rdeg); + if (blcoeff_is_numeric) + term = rcoeff / blcoeff; + else { + if (!divide(rcoeff, blcoeff, term, false)) + return *new ex(fail()); + } + term *= power(x, rdeg - bdeg); + q += term; + r -= (term * b).expand(); + if (r.is_zero()) + break; + rdeg = r.degree(x); + } + return q; } @@ -397,44 +397,44 @@ ex quo(const ex &a, const ex &b, const symbol &x, bool check_args) * @return remainder of a(x) and b(x) in Q[x] */ ex rem(const ex &a, const ex &b, const symbol &x, bool check_args) { - if (b.is_zero()) - throw(std::overflow_error("rem: division by zero")); - if (is_ex_exactly_of_type(a, numeric)) { - if (is_ex_exactly_of_type(b, numeric)) - return _ex0(); - else - return b; - } + if (b.is_zero()) + throw(std::overflow_error("rem: division by zero")); + if (is_ex_exactly_of_type(a, numeric)) { + if (is_ex_exactly_of_type(b, numeric)) + return _ex0(); + else + return b; + } #if FAST_COMPARE - if (a.is_equal(b)) - return _ex0(); + if (a.is_equal(b)) + return _ex0(); #endif - if (check_args && (!a.info(info_flags::rational_polynomial) || !b.info(info_flags::rational_polynomial))) - throw(std::invalid_argument("rem: arguments must be polynomials over the rationals")); - - // Polynomial long division - ex r = a.expand(); - if (r.is_zero()) - return r; - int bdeg = b.degree(x); - int rdeg = r.degree(x); - ex blcoeff = b.expand().coeff(x, bdeg); - bool blcoeff_is_numeric = is_ex_exactly_of_type(blcoeff, numeric); - while (rdeg >= bdeg) { - ex term, rcoeff = r.coeff(x, rdeg); - if (blcoeff_is_numeric) - term = rcoeff / blcoeff; - else { - if (!divide(rcoeff, blcoeff, term, false)) - return *new ex(fail()); - } - term *= power(x, rdeg - bdeg); - r -= (term * b).expand(); - if (r.is_zero()) - break; - rdeg = r.degree(x); - } - return r; + if (check_args && (!a.info(info_flags::rational_polynomial) || !b.info(info_flags::rational_polynomial))) + throw(std::invalid_argument("rem: arguments must be polynomials over the rationals")); + + // Polynomial long division + ex r = a.expand(); + if (r.is_zero()) + return r; + int bdeg = b.degree(x); + int rdeg = r.degree(x); + ex blcoeff = b.expand().coeff(x, bdeg); + bool blcoeff_is_numeric = is_ex_exactly_of_type(blcoeff, numeric); + while (rdeg >= bdeg) { + ex term, rcoeff = r.coeff(x, rdeg); + if (blcoeff_is_numeric) + term = rcoeff / blcoeff; + else { + if (!divide(rcoeff, blcoeff, term, false)) + return *new ex(fail()); + } + term *= power(x, rdeg - bdeg); + r -= (term * b).expand(); + if (r.is_zero()) + break; + rdeg = r.degree(x); + } + return r; } @@ -448,45 +448,45 @@ ex rem(const ex &a, const ex &b, const symbol &x, bool check_args) * @return pseudo-remainder of a(x) and b(x) in Z[x] */ ex prem(const ex &a, const ex &b, const symbol &x, bool check_args) { - if (b.is_zero()) - throw(std::overflow_error("prem: division by zero")); - if (is_ex_exactly_of_type(a, numeric)) { - if (is_ex_exactly_of_type(b, numeric)) - return _ex0(); - else - return b; - } - if (check_args && (!a.info(info_flags::rational_polynomial) || !b.info(info_flags::rational_polynomial))) - throw(std::invalid_argument("prem: arguments must be polynomials over the rationals")); - - // Polynomial long division - ex r = a.expand(); - ex eb = b.expand(); - int rdeg = r.degree(x); - int bdeg = eb.degree(x); - ex blcoeff; - if (bdeg <= rdeg) { - blcoeff = eb.coeff(x, bdeg); - if (bdeg == 0) - eb = _ex0(); - else - eb -= blcoeff * power(x, bdeg); - } else - blcoeff = _ex1(); - - int delta = rdeg - bdeg + 1, i = 0; - while (rdeg >= bdeg && !r.is_zero()) { - ex rlcoeff = r.coeff(x, rdeg); - ex term = (power(x, rdeg - bdeg) * eb * rlcoeff).expand(); - if (rdeg == 0) - r = _ex0(); - else - r -= rlcoeff * power(x, rdeg); - r = (blcoeff * r).expand() - term; - rdeg = r.degree(x); - i++; - } - return power(blcoeff, delta - i) * r; + if (b.is_zero()) + throw(std::overflow_error("prem: division by zero")); + if (is_ex_exactly_of_type(a, numeric)) { + if (is_ex_exactly_of_type(b, numeric)) + return _ex0(); + else + return b; + } + if (check_args && (!a.info(info_flags::rational_polynomial) || !b.info(info_flags::rational_polynomial))) + throw(std::invalid_argument("prem: arguments must be polynomials over the rationals")); + + // Polynomial long division + ex r = a.expand(); + ex eb = b.expand(); + int rdeg = r.degree(x); + int bdeg = eb.degree(x); + ex blcoeff; + if (bdeg <= rdeg) { + blcoeff = eb.coeff(x, bdeg); + if (bdeg == 0) + eb = _ex0(); + else + eb -= blcoeff * power(x, bdeg); + } else + blcoeff = _ex1(); + + int delta = rdeg - bdeg + 1, i = 0; + while (rdeg >= bdeg && !r.is_zero()) { + ex rlcoeff = r.coeff(x, rdeg); + ex term = (power(x, rdeg - bdeg) * eb * rlcoeff).expand(); + if (rdeg == 0) + r = _ex0(); + else + r -= rlcoeff * power(x, rdeg); + r = (blcoeff * r).expand() - term; + rdeg = r.degree(x); + i++; + } + return power(blcoeff, delta - i) * r; } @@ -501,43 +501,43 @@ ex prem(const ex &a, const ex &b, const symbol &x, bool check_args) ex sprem(const ex &a, const ex &b, const symbol &x, bool check_args) { - if (b.is_zero()) - throw(std::overflow_error("prem: division by zero")); - if (is_ex_exactly_of_type(a, numeric)) { - if (is_ex_exactly_of_type(b, numeric)) - return _ex0(); - else - return b; - } - if (check_args && (!a.info(info_flags::rational_polynomial) || !b.info(info_flags::rational_polynomial))) - throw(std::invalid_argument("prem: arguments must be polynomials over the rationals")); - - // Polynomial long division - ex r = a.expand(); - ex eb = b.expand(); - int rdeg = r.degree(x); - int bdeg = eb.degree(x); - ex blcoeff; - if (bdeg <= rdeg) { - blcoeff = eb.coeff(x, bdeg); - if (bdeg == 0) - eb = _ex0(); - else - eb -= blcoeff * power(x, bdeg); - } else - blcoeff = _ex1(); - - while (rdeg >= bdeg && !r.is_zero()) { - ex rlcoeff = r.coeff(x, rdeg); - ex term = (power(x, rdeg - bdeg) * eb * rlcoeff).expand(); - if (rdeg == 0) - r = _ex0(); - else - r -= rlcoeff * power(x, rdeg); - r = (blcoeff * r).expand() - term; - rdeg = r.degree(x); - } - return r; + if (b.is_zero()) + throw(std::overflow_error("prem: division by zero")); + if (is_ex_exactly_of_type(a, numeric)) { + if (is_ex_exactly_of_type(b, numeric)) + return _ex0(); + else + return b; + } + if (check_args && (!a.info(info_flags::rational_polynomial) || !b.info(info_flags::rational_polynomial))) + throw(std::invalid_argument("prem: arguments must be polynomials over the rationals")); + + // Polynomial long division + ex r = a.expand(); + ex eb = b.expand(); + int rdeg = r.degree(x); + int bdeg = eb.degree(x); + ex blcoeff; + if (bdeg <= rdeg) { + blcoeff = eb.coeff(x, bdeg); + if (bdeg == 0) + eb = _ex0(); + else + eb -= blcoeff * power(x, bdeg); + } else + blcoeff = _ex1(); + + while (rdeg >= bdeg && !r.is_zero()) { + ex rlcoeff = r.coeff(x, rdeg); + ex term = (power(x, rdeg - bdeg) * eb * rlcoeff).expand(); + if (rdeg == 0) + r = _ex0(); + else + r -= rlcoeff * power(x, rdeg); + r = (blcoeff * r).expand() - term; + rdeg = r.degree(x); + } + return r; } @@ -552,54 +552,54 @@ ex sprem(const ex &a, const ex &b, const symbol &x, bool check_args) * "false" otherwise */ bool divide(const ex &a, const ex &b, ex &q, bool check_args) { - q = _ex0(); - if (b.is_zero()) - throw(std::overflow_error("divide: division by zero")); - if (a.is_zero()) - return true; - if (is_ex_exactly_of_type(b, numeric)) { - q = a / b; - return true; - } else if (is_ex_exactly_of_type(a, numeric)) - return false; + q = _ex0(); + if (b.is_zero()) + throw(std::overflow_error("divide: division by zero")); + if (a.is_zero()) + return true; + if (is_ex_exactly_of_type(b, numeric)) { + q = a / b; + return true; + } else if (is_ex_exactly_of_type(a, numeric)) + return false; #if FAST_COMPARE - if (a.is_equal(b)) { - q = _ex1(); - return true; - } + if (a.is_equal(b)) { + q = _ex1(); + return true; + } #endif - if (check_args && (!a.info(info_flags::rational_polynomial) || - !b.info(info_flags::rational_polynomial))) - throw(std::invalid_argument("divide: arguments must be polynomials over the rationals")); - - // Find first symbol - const symbol *x; - if (!get_first_symbol(a, x) && !get_first_symbol(b, x)) - throw(std::invalid_argument("invalid expression in divide()")); - - // Polynomial long division (recursive) - ex r = a.expand(); - if (r.is_zero()) - return true; - int bdeg = b.degree(*x); - int rdeg = r.degree(*x); - ex blcoeff = b.expand().coeff(*x, bdeg); - bool blcoeff_is_numeric = is_ex_exactly_of_type(blcoeff, numeric); - while (rdeg >= bdeg) { - ex term, rcoeff = r.coeff(*x, rdeg); - if (blcoeff_is_numeric) - term = rcoeff / blcoeff; - else - if (!divide(rcoeff, blcoeff, term, false)) - return false; - term *= power(*x, rdeg - bdeg); - q += term; - r -= (term * b).expand(); - if (r.is_zero()) - return true; - rdeg = r.degree(*x); - } - return false; + if (check_args && (!a.info(info_flags::rational_polynomial) || + !b.info(info_flags::rational_polynomial))) + throw(std::invalid_argument("divide: arguments must be polynomials over the rationals")); + + // Find first symbol + const symbol *x; + if (!get_first_symbol(a, x) && !get_first_symbol(b, x)) + throw(std::invalid_argument("invalid expression in divide()")); + + // Polynomial long division (recursive) + ex r = a.expand(); + if (r.is_zero()) + return true; + int bdeg = b.degree(*x); + int rdeg = r.degree(*x); + ex blcoeff = b.expand().coeff(*x, bdeg); + bool blcoeff_is_numeric = is_ex_exactly_of_type(blcoeff, numeric); + while (rdeg >= bdeg) { + ex term, rcoeff = r.coeff(*x, rdeg); + if (blcoeff_is_numeric) + term = rcoeff / blcoeff; + else + if (!divide(rcoeff, blcoeff, term, false)) + return false; + term *= power(*x, rdeg - bdeg); + q += term; + r -= (term * b).expand(); + if (r.is_zero()) + return true; + rdeg = r.degree(*x); + } + return false; } @@ -612,10 +612,10 @@ typedef std::pair ex2; typedef std::pair exbool; struct ex2_less { - 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); - } + 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); + } }; typedef std::map ex2_exbool_remember; @@ -640,127 +640,127 @@ typedef std::map ex2_exbool_remember; * @see get_symbol_stats, heur_gcd */ static bool divide_in_z(const ex &a, const ex &b, ex &q, sym_desc_vec::const_iterator var) { - q = _ex0(); - if (b.is_zero()) - throw(std::overflow_error("divide_in_z: division by zero")); - if (b.is_equal(_ex1())) { - q = a; - return true; - } - if (is_ex_exactly_of_type(a, numeric)) { - if (is_ex_exactly_of_type(b, numeric)) { - q = a / b; - return q.info(info_flags::integer); - } else - return false; - } + q = _ex0(); + if (b.is_zero()) + throw(std::overflow_error("divide_in_z: division by zero")); + if (b.is_equal(_ex1())) { + q = a; + return true; + } + if (is_ex_exactly_of_type(a, numeric)) { + if (is_ex_exactly_of_type(b, numeric)) { + q = a / b; + return q.info(info_flags::integer); + } else + return false; + } #if FAST_COMPARE - if (a.is_equal(b)) { - q = _ex1(); - return true; - } + if (a.is_equal(b)) { + q = _ex1(); + return true; + } #endif #if USE_REMEMBER - // Remembering - static ex2_exbool_remember dr_remember; - ex2_exbool_remember::const_iterator remembered = dr_remember.find(ex2(a, b)); - if (remembered != dr_remember.end()) { - q = remembered->second.first; - return remembered->second.second; - } + // Remembering + static ex2_exbool_remember dr_remember; + ex2_exbool_remember::const_iterator remembered = dr_remember.find(ex2(a, b)); + if (remembered != dr_remember.end()) { + q = remembered->second.first; + return remembered->second.second; + } #endif - // Main symbol - const symbol *x = var->sym; + // Main symbol + const symbol *x = var->sym; - // Compare degrees - int adeg = a.degree(*x), bdeg = b.degree(*x); - if (bdeg > adeg) - return false; + // Compare degrees + int adeg = a.degree(*x), bdeg = b.degree(*x); + if (bdeg > adeg) + return false; #if USE_TRIAL_DIVISION - // Trial division with polynomial interpolation - int i, k; - - // Compute values at evaluation points 0..adeg - vector alpha; alpha.reserve(adeg + 1); - exvector u; u.reserve(adeg + 1); - numeric point = _num0(); - ex c; - for (i=0; i<=adeg; i++) { - ex bs = b.subs(*x == point); - while (bs.is_zero()) { - point += _num1(); - bs = b.subs(*x == point); - } - if (!divide_in_z(a.subs(*x == point), bs, c, var+1)) - return false; - alpha.push_back(point); - u.push_back(c); - point += _num1(); - } - - // Compute inverses - vector rcp; rcp.reserve(adeg + 1); - rcp.push_back(_num0()); - for (k=1; k<=adeg; k++) { - numeric product = alpha[k] - alpha[0]; - for (i=1; i=0; i--) - temp = temp * (alpha[k] - alpha[i]) + v[i]; - v.push_back((u[k] - temp) * rcp[k]); - } - - // Convert from Newton form to standard form - c = v[adeg]; - for (k=adeg-1; k>=0; k--) - c = c * (*x - alpha[k]) + v[k]; - - if (c.degree(*x) == (adeg - bdeg)) { - q = c.expand(); - return true; - } else - return false; + // Trial division with polynomial interpolation + int i, k; + + // Compute values at evaluation points 0..adeg + vector alpha; alpha.reserve(adeg + 1); + exvector u; u.reserve(adeg + 1); + numeric point = _num0(); + ex c; + for (i=0; i<=adeg; i++) { + ex bs = b.subs(*x == point); + while (bs.is_zero()) { + point += _num1(); + bs = b.subs(*x == point); + } + if (!divide_in_z(a.subs(*x == point), bs, c, var+1)) + return false; + alpha.push_back(point); + u.push_back(c); + point += _num1(); + } + + // Compute inverses + vector rcp; rcp.reserve(adeg + 1); + rcp.push_back(_num0()); + for (k=1; k<=adeg; k++) { + numeric product = alpha[k] - alpha[0]; + for (i=1; i=0; i--) + temp = temp * (alpha[k] - alpha[i]) + v[i]; + v.push_back((u[k] - temp) * rcp[k]); + } + + // Convert from Newton form to standard form + c = v[adeg]; + for (k=adeg-1; k>=0; k--) + c = c * (*x - alpha[k]) + v[k]; + + if (c.degree(*x) == (adeg - bdeg)) { + q = c.expand(); + return true; + } else + return false; #else - // Polynomial long division (recursive) - ex r = a.expand(); - if (r.is_zero()) - return true; - int rdeg = adeg; - ex eb = b.expand(); - ex blcoeff = eb.coeff(*x, bdeg); - while (rdeg >= bdeg) { - ex term, rcoeff = r.coeff(*x, rdeg); - if (!divide_in_z(rcoeff, blcoeff, term, var+1)) - break; - term = (term * power(*x, rdeg - bdeg)).expand(); - q += term; - r -= (term * eb).expand(); - if (r.is_zero()) { + // Polynomial long division (recursive) + ex r = a.expand(); + if (r.is_zero()) + return true; + int rdeg = adeg; + ex eb = b.expand(); + ex blcoeff = eb.coeff(*x, bdeg); + while (rdeg >= bdeg) { + ex term, rcoeff = r.coeff(*x, rdeg); + if (!divide_in_z(rcoeff, blcoeff, term, var+1)) + break; + term = (term * power(*x, rdeg - bdeg)).expand(); + q += term; + r -= (term * eb).expand(); + if (r.is_zero()) { #if USE_REMEMBER - dr_remember[ex2(a, b)] = exbool(q, true); + dr_remember[ex2(a, b)] = exbool(q, true); #endif - return true; - } - rdeg = r.degree(*x); - } + return true; + } + rdeg = r.degree(*x); + } #if USE_REMEMBER - dr_remember[ex2(a, b)] = exbool(q, false); + dr_remember[ex2(a, b)] = exbool(q, false); #endif - return false; + return false; #endif } @@ -779,16 +779,16 @@ static bool divide_in_z(const ex &a, const ex &b, ex &q, sym_desc_vec::const_ite * @see ex::content, ex::primpart */ ex ex::unit(const symbol &x) const { - ex c = expand().lcoeff(x); - if (is_ex_exactly_of_type(c, numeric)) - return c < _ex0() ? _ex_1() : _ex1(); - else { - const symbol *y; - if (get_first_symbol(c, y)) - return c.unit(*y); - else - throw(std::invalid_argument("invalid expression in unit()")); - } + ex c = expand().lcoeff(x); + if (is_ex_exactly_of_type(c, numeric)) + return c < _ex0() ? _ex_1() : _ex1(); + else { + const symbol *y; + if (get_first_symbol(c, y)) + return c.unit(*y); + else + throw(std::invalid_argument("invalid expression in unit()")); + } } @@ -801,30 +801,30 @@ ex ex::unit(const symbol &x) const * @see ex::unit, ex::primpart */ ex ex::content(const symbol &x) const { - if (is_zero()) - return _ex0(); - if (is_ex_exactly_of_type(*this, numeric)) - return info(info_flags::negative) ? -*this : *this; - ex e = expand(); - if (e.is_zero()) - return _ex0(); - - // First, try the integer content - ex c = e.integer_content(); - ex r = e / c; - ex lcoeff = r.lcoeff(x); - if (lcoeff.info(info_flags::integer)) - return c; - - // GCD of all coefficients - int deg = e.degree(x); - int ldeg = e.ldegree(x); - if (deg == ldeg) - return e.lcoeff(x) / e.unit(x); - c = _ex0(); - for (int i=ldeg; i<=deg; i++) - c = gcd(e.coeff(x, i), c, NULL, NULL, false); - return c; + if (is_zero()) + return _ex0(); + if (is_ex_exactly_of_type(*this, numeric)) + return info(info_flags::negative) ? -*this : *this; + ex e = expand(); + if (e.is_zero()) + return _ex0(); + + // First, try the integer content + ex c = e.integer_content(); + ex r = e / c; + ex lcoeff = r.lcoeff(x); + if (lcoeff.info(info_flags::integer)) + return c; + + // GCD of all coefficients + int deg = e.degree(x); + int ldeg = e.ldegree(x); + if (deg == ldeg) + return e.lcoeff(x) / e.unit(x); + c = _ex0(); + for (int i=ldeg; i<=deg; i++) + c = gcd(e.coeff(x, i), c, NULL, NULL, false); + return c; } @@ -837,19 +837,19 @@ ex ex::content(const symbol &x) const * @see ex::unit, ex::content */ ex ex::primpart(const symbol &x) const { - if (is_zero()) - return _ex0(); - if (is_ex_exactly_of_type(*this, numeric)) - return _ex1(); - - ex c = content(x); - if (c.is_zero()) - return _ex0(); - ex u = unit(x); - if (is_ex_exactly_of_type(c, numeric)) - return *this / (c * u); - else - return quo(*this, c * u, x, false); + if (is_zero()) + return _ex0(); + if (is_ex_exactly_of_type(*this, numeric)) + return _ex1(); + + ex c = content(x); + if (c.is_zero()) + return _ex0(); + ex u = unit(x); + if (is_ex_exactly_of_type(c, numeric)) + return *this / (c * u); + else + return quo(*this, c * u, x, false); } @@ -862,18 +862,18 @@ ex ex::primpart(const symbol &x) const * @return primitive part */ ex ex::primpart(const symbol &x, const ex &c) const { - if (is_zero()) - return _ex0(); - if (c.is_zero()) - return _ex0(); - if (is_ex_exactly_of_type(*this, numeric)) - return _ex1(); - - ex u = unit(x); - if (is_ex_exactly_of_type(c, numeric)) - return *this / (c * u); - else - return quo(*this, c * u, x, false); + if (is_zero()) + return _ex0(); + if (c.is_zero()) + return _ex0(); + if (is_ex_exactly_of_type(*this, numeric)) + return _ex1(); + + ex u = unit(x); + if (is_ex_exactly_of_type(c, numeric)) + return *this / (c * u); + else + return quo(*this, c * u, x, false); } @@ -895,31 +895,31 @@ static ex eu_gcd(const ex &a, const ex &b, const symbol *x) { //std::clog << "eu_gcd(" << a << "," << b << ")\n"; - // Sort c and d so that c has higher degree - ex c, d; - int adeg = a.degree(*x), bdeg = b.degree(*x); - if (adeg >= bdeg) { - c = a; - d = b; - } else { - c = b; - d = a; - } + // Sort c and d so that c has higher degree + ex c, d; + int adeg = a.degree(*x), bdeg = b.degree(*x); + if (adeg >= bdeg) { + c = a; + d = b; + } else { + c = b; + d = a; + } // Normalize in Q[x] c = c / c.lcoeff(*x); d = d / d.lcoeff(*x); // Euclidean algorithm - ex r; - for (;;) { + ex r; + for (;;) { //std::clog << " d = " << d << endl; - r = rem(c, d, *x, false); - if (r.is_zero()) - return d / d.lcoeff(*x); - c = d; + r = rem(c, d, *x, false); + if (r.is_zero()) + return d / d.lcoeff(*x); + c = d; d = r; - } + } } @@ -937,30 +937,30 @@ static ex euprem_gcd(const ex &a, const ex &b, const symbol *x) { //std::clog << "euprem_gcd(" << a << "," << b << ")\n"; - // Sort c and d so that c has higher degree - ex c, d; - int adeg = a.degree(*x), bdeg = b.degree(*x); - if (adeg >= bdeg) { - c = a; - d = b; - } else { - c = b; - d = a; - } + // Sort c and d so that c has higher degree + ex c, d; + int adeg = a.degree(*x), bdeg = b.degree(*x); + if (adeg >= bdeg) { + c = a; + d = b; + } else { + c = b; + d = a; + } // Calculate GCD of contents ex gamma = gcd(c.content(*x), d.content(*x), NULL, NULL, false); // Euclidean algorithm with pseudo-remainders - ex r; - for (;;) { + ex r; + for (;;) { //std::clog << " d = " << d << endl; - r = prem(c, d, *x, false); - if (r.is_zero()) - return d.primpart(*x) * gamma; - c = d; + r = prem(c, d, *x, false); + if (r.is_zero()) + return d.primpart(*x) * gamma; + c = d; d = r; - } + } } @@ -978,39 +978,39 @@ static ex peu_gcd(const ex &a, const ex &b, const symbol *x) { //std::clog << "peu_gcd(" << a << "," << b << ")\n"; - // Sort c and d so that c has higher degree - ex c, d; - int adeg = a.degree(*x), bdeg = b.degree(*x); - int ddeg; - if (adeg >= bdeg) { - c = a; - d = b; - ddeg = bdeg; - } else { - c = b; - d = a; - ddeg = adeg; - } - - // Remove content from c and d, to be attached to GCD later - ex cont_c = c.content(*x); - ex cont_d = d.content(*x); - ex gamma = gcd(cont_c, cont_d, NULL, NULL, false); - if (ddeg == 0) - return gamma; - c = c.primpart(*x, cont_c); - d = d.primpart(*x, cont_d); - - // Euclidean algorithm with content removal + // Sort c and d so that c has higher degree + ex c, d; + int adeg = a.degree(*x), bdeg = b.degree(*x); + int ddeg; + if (adeg >= bdeg) { + c = a; + d = b; + ddeg = bdeg; + } else { + c = b; + d = a; + ddeg = adeg; + } + + // Remove content from c and d, to be attached to GCD later + ex cont_c = c.content(*x); + ex cont_d = d.content(*x); + ex gamma = gcd(cont_c, cont_d, NULL, NULL, false); + if (ddeg == 0) + return gamma; + c = c.primpart(*x, cont_c); + d = d.primpart(*x, cont_d); + + // Euclidean algorithm with content removal ex r; - for (;;) { + for (;;) { //std::clog << " d = " << d << endl; - r = prem(c, d, *x, false); - if (r.is_zero()) - return gamma * d; - c = d; + r = prem(c, d, *x, false); + if (r.is_zero()) + return gamma * d; + c = d; d = r.primpart(*x); - } + } } @@ -1027,57 +1027,57 @@ static ex red_gcd(const ex &a, const ex &b, const symbol *x) { //std::clog << "red_gcd(" << a << "," << b << ")\n"; - // Sort c and d so that c has higher degree - ex c, d; - int adeg = a.degree(*x), bdeg = b.degree(*x); - int cdeg, ddeg; - if (adeg >= bdeg) { - c = a; - d = b; - cdeg = adeg; - ddeg = bdeg; - } else { - c = b; - d = a; - cdeg = bdeg; - ddeg = adeg; - } - - // Remove content from c and d, to be attached to GCD later - ex cont_c = c.content(*x); - ex cont_d = d.content(*x); - ex gamma = gcd(cont_c, cont_d, NULL, NULL, false); - if (ddeg == 0) - return gamma; - c = c.primpart(*x, cont_c); - d = d.primpart(*x, cont_d); - - // First element of divisor sequence - ex r, ri = _ex1(); - int delta = cdeg - ddeg; - - for (;;) { - // Calculate polynomial pseudo-remainder + // Sort c and d so that c has higher degree + ex c, d; + int adeg = a.degree(*x), bdeg = b.degree(*x); + int cdeg, ddeg; + if (adeg >= bdeg) { + c = a; + d = b; + cdeg = adeg; + ddeg = bdeg; + } else { + c = b; + d = a; + cdeg = bdeg; + ddeg = adeg; + } + + // Remove content from c and d, to be attached to GCD later + ex cont_c = c.content(*x); + ex cont_d = d.content(*x); + ex gamma = gcd(cont_c, cont_d, NULL, NULL, false); + if (ddeg == 0) + return gamma; + c = c.primpart(*x, cont_c); + d = d.primpart(*x, cont_d); + + // First element of divisor sequence + ex r, ri = _ex1(); + int delta = cdeg - ddeg; + + for (;;) { + // Calculate polynomial pseudo-remainder //std::clog << " d = " << d << endl; - r = prem(c, d, *x, false); - if (r.is_zero()) - return gamma * d.primpart(*x); - c = d; - cdeg = ddeg; - - if (!divide(r, pow(ri, delta), d, false)) - throw(std::runtime_error("invalid expression in red_gcd(), division failed")); - ddeg = d.degree(*x); - if (ddeg == 0) { - if (is_ex_exactly_of_type(r, numeric)) - return gamma; - else - return gamma * r.primpart(*x); - } - - ri = c.expand().lcoeff(*x); - delta = cdeg - ddeg; - } + r = prem(c, d, *x, false); + if (r.is_zero()) + return gamma * d.primpart(*x); + c = d; + cdeg = ddeg; + + if (!divide(r, pow(ri, delta), d, false)) + throw(std::runtime_error("invalid expression in red_gcd(), division failed")); + ddeg = d.degree(*x); + if (ddeg == 0) { + if (is_ex_exactly_of_type(r, numeric)) + return gamma; + else + return gamma * r.primpart(*x); + } + + ri = c.expand().lcoeff(*x); + delta = cdeg - ddeg; + } } @@ -1097,68 +1097,68 @@ static ex sr_gcd(const ex &a, const ex &b, sym_desc_vec::const_iterator var) sr_gcd_called++; #endif - // The first symbol is our main variable - const symbol &x = *(var->sym); - - // Sort c and d so that c has higher degree - ex c, d; - int adeg = a.degree(x), bdeg = b.degree(x); - int cdeg, ddeg; - if (adeg >= bdeg) { - c = a; - d = b; - cdeg = adeg; - ddeg = bdeg; - } else { - c = b; - d = a; - cdeg = bdeg; - ddeg = adeg; - } - - // Remove content from c and d, to be attached to GCD later - ex cont_c = c.content(x); - ex cont_d = d.content(x); - ex gamma = gcd(cont_c, cont_d, NULL, NULL, false); - if (ddeg == 0) - return gamma; - c = c.primpart(x, cont_c); - d = d.primpart(x, cont_d); + // The first symbol is our main variable + const symbol &x = *(var->sym); + + // Sort c and d so that c has higher degree + ex c, d; + int adeg = a.degree(x), bdeg = b.degree(x); + int cdeg, ddeg; + if (adeg >= bdeg) { + c = a; + d = b; + cdeg = adeg; + ddeg = bdeg; + } else { + c = b; + d = a; + cdeg = bdeg; + ddeg = adeg; + } + + // Remove content from c and d, to be attached to GCD later + ex cont_c = c.content(x); + ex cont_d = d.content(x); + ex gamma = gcd(cont_c, cont_d, NULL, NULL, false); + if (ddeg == 0) + return gamma; + c = c.primpart(x, cont_c); + d = d.primpart(x, cont_d); //std::clog << " content " << gamma << " removed, continuing with sr_gcd(" << c << "," << d << ")\n"; - // First element of subresultant sequence - ex r = _ex0(), ri = _ex1(), psi = _ex1(); - int delta = cdeg - ddeg; + // First element of subresultant sequence + ex r = _ex0(), ri = _ex1(), psi = _ex1(); + int delta = cdeg - ddeg; - for (;;) { - // Calculate polynomial pseudo-remainder + for (;;) { + // Calculate polynomial pseudo-remainder //std::clog << " start of loop, psi = " << psi << ", calculating pseudo-remainder...\n"; //std::clog << " d = " << d << endl; - r = prem(c, d, x, false); - if (r.is_zero()) - return gamma * d.primpart(x); - c = d; - cdeg = ddeg; + r = prem(c, d, x, false); + if (r.is_zero()) + return gamma * d.primpart(x); + c = d; + cdeg = ddeg; //std::clog << " dividing...\n"; - if (!divide_in_z(r, ri * pow(psi, delta), d, var)) - throw(std::runtime_error("invalid expression in sr_gcd(), division failed")); - ddeg = d.degree(x); - if (ddeg == 0) { - if (is_ex_exactly_of_type(r, numeric)) - return gamma; - else - return gamma * r.primpart(x); - } - - // Next element of subresultant sequence + if (!divide_in_z(r, ri * pow(psi, delta), d, var)) + throw(std::runtime_error("invalid expression in sr_gcd(), division failed")); + ddeg = d.degree(x); + if (ddeg == 0) { + if (is_ex_exactly_of_type(r, numeric)) + return gamma; + else + return gamma * r.primpart(x); + } + + // Next element of subresultant sequence //std::clog << " calculating next subresultant...\n"; - ri = c.expand().lcoeff(x); - if (delta == 1) - psi = ri; - else if (delta) - divide_in_z(pow(ri, delta), pow(psi, delta-1), psi, var+1); - delta = cdeg - ddeg; - } + ri = c.expand().lcoeff(x); + if (delta == 1) + psi = ri; + else if (delta) + divide_in_z(pow(ri, delta), pow(psi, delta-1), psi, var+1); + delta = cdeg - ddeg; + } } @@ -1170,49 +1170,49 @@ static ex sr_gcd(const ex &a, const ex &b, sym_desc_vec::const_iterator var) * @see heur_gcd */ numeric ex::max_coefficient(void) const { - GINAC_ASSERT(bp!=0); - return bp->max_coefficient(); + GINAC_ASSERT(bp!=0); + return bp->max_coefficient(); } numeric basic::max_coefficient(void) const { - return _num1(); + return _num1(); } numeric numeric::max_coefficient(void) const { - return abs(*this); + return abs(*this); } numeric add::max_coefficient(void) const { - epvector::const_iterator it = seq.begin(); - epvector::const_iterator itend = seq.end(); - GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric)); - numeric cur_max = abs(ex_to_numeric(overall_coeff)); - while (it != itend) { - numeric a; - GINAC_ASSERT(!is_ex_exactly_of_type(it->rest,numeric)); - a = abs(ex_to_numeric(it->coeff)); - if (a > cur_max) - cur_max = a; - it++; - } - return cur_max; + epvector::const_iterator it = seq.begin(); + epvector::const_iterator itend = seq.end(); + GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric)); + numeric cur_max = abs(ex_to_numeric(overall_coeff)); + while (it != itend) { + numeric a; + GINAC_ASSERT(!is_ex_exactly_of_type(it->rest,numeric)); + a = abs(ex_to_numeric(it->coeff)); + if (a > cur_max) + cur_max = a; + it++; + } + return cur_max; } numeric mul::max_coefficient(void) const { #ifdef DO_GINAC_ASSERT - epvector::const_iterator it = seq.begin(); - epvector::const_iterator itend = seq.end(); - while (it != itend) { - GINAC_ASSERT(!is_ex_exactly_of_type(recombine_pair_to_ex(*it),numeric)); - it++; - } + epvector::const_iterator it = seq.begin(); + epvector::const_iterator itend = seq.end(); + while (it != itend) { + GINAC_ASSERT(!is_ex_exactly_of_type(recombine_pair_to_ex(*it),numeric)); + it++; + } #endif // def DO_GINAC_ASSERT - GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric)); - return abs(ex_to_numeric(overall_coeff)); + GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric)); + return abs(ex_to_numeric(overall_coeff)); } @@ -1225,70 +1225,70 @@ numeric mul::max_coefficient(void) const * @see heur_gcd */ ex ex::smod(const numeric &xi) const { - GINAC_ASSERT(bp!=0); - return bp->smod(xi); + GINAC_ASSERT(bp!=0); + return bp->smod(xi); } ex basic::smod(const numeric &xi) const { - return *this; + return *this; } ex numeric::smod(const numeric &xi) const { #ifndef NO_NAMESPACE_GINAC - return GiNaC::smod(*this, xi); + return GiNaC::smod(*this, xi); #else // ndef NO_NAMESPACE_GINAC - return ::smod(*this, xi); + return ::smod(*this, xi); #endif // ndef NO_NAMESPACE_GINAC } ex add::smod(const numeric &xi) const { - epvector newseq; - newseq.reserve(seq.size()+1); - epvector::const_iterator it = seq.begin(); - epvector::const_iterator itend = seq.end(); - while (it != itend) { - GINAC_ASSERT(!is_ex_exactly_of_type(it->rest,numeric)); + epvector newseq; + newseq.reserve(seq.size()+1); + epvector::const_iterator it = seq.begin(); + 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); + numeric coeff = GiNaC::smod(ex_to_numeric(it->coeff), xi); #else // ndef NO_NAMESPACE_GINAC - numeric coeff = ::smod(ex_to_numeric(it->coeff), xi); + 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)); + 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); + numeric coeff = GiNaC::smod(ex_to_numeric(overall_coeff), xi); #else // ndef NO_NAMESPACE_GINAC - numeric coeff = ::smod(ex_to_numeric(overall_coeff), xi); + numeric coeff = ::smod(ex_to_numeric(overall_coeff), xi); #endif // ndef NO_NAMESPACE_GINAC - return (new add(newseq,coeff))->setflag(status_flags::dynallocated); + return (new add(newseq,coeff))->setflag(status_flags::dynallocated); } ex mul::smod(const numeric &xi) const { #ifdef DO_GINAC_ASSERT - epvector::const_iterator it = seq.begin(); - epvector::const_iterator itend = seq.end(); - while (it != itend) { - GINAC_ASSERT(!is_ex_exactly_of_type(recombine_pair_to_ex(*it),numeric)); - it++; - } + epvector::const_iterator it = seq.begin(); + epvector::const_iterator itend = seq.end(); + while (it != itend) { + GINAC_ASSERT(!is_ex_exactly_of_type(recombine_pair_to_ex(*it),numeric)); + it++; + } #endif // def DO_GINAC_ASSERT - mul * mulcopyp=new mul(*this); - GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric)); + 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); + 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); + 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); + mulcopyp->clearflag(status_flags::evaluated); + mulcopyp->clearflag(status_flags::hash_calculated); + return mulcopyp->setflag(status_flags::dynallocated); } @@ -1336,61 +1336,61 @@ static ex heur_gcd(const ex &a, const ex &b, ex *ca, ex *cb, sym_desc_vec::const return *new ex(fail()); // GCD of two numeric values -> CLN - if (is_ex_exactly_of_type(a, numeric) && is_ex_exactly_of_type(b, numeric)) { - numeric g = gcd(ex_to_numeric(a), ex_to_numeric(b)); - if (ca) - *ca = ex_to_numeric(a) / g; - if (cb) - *cb = ex_to_numeric(b) / g; - return g; - } - - // The first symbol is our main variable - const symbol &x = *(var->sym); - - // Remove integer content - numeric gc = gcd(a.integer_content(), b.integer_content()); - numeric rgc = gc.inverse(); - ex p = a * rgc; - ex q = b * rgc; - int maxdeg = max(p.degree(x), q.degree(x)); - - // Find evaluation point - numeric mp = p.max_coefficient(), mq = q.max_coefficient(); - numeric xi; - if (mp > mq) - xi = mq * _num2() + _num2(); - else - xi = mp * _num2() + _num2(); - - // 6 tries maximum - for (int t=0; t<6; t++) { - if (xi.int_length() * maxdeg > 100000) { + if (is_ex_exactly_of_type(a, numeric) && is_ex_exactly_of_type(b, numeric)) { + numeric g = gcd(ex_to_numeric(a), ex_to_numeric(b)); + if (ca) + *ca = ex_to_numeric(a) / g; + if (cb) + *cb = ex_to_numeric(b) / g; + return g; + } + + // The first symbol is our main variable + const symbol &x = *(var->sym); + + // Remove integer content + numeric gc = gcd(a.integer_content(), b.integer_content()); + numeric rgc = gc.inverse(); + ex p = a * rgc; + ex q = b * rgc; + int maxdeg = max(p.degree(x), q.degree(x)); + + // Find evaluation point + numeric mp = p.max_coefficient(), mq = q.max_coefficient(); + numeric xi; + if (mp > mq) + xi = mq * _num2() + _num2(); + else + xi = mp * _num2() + _num2(); + + // 6 tries maximum + for (int t=0; t<6; t++) { + if (xi.int_length() * maxdeg > 100000) { //std::clog << "giving up heur_gcd, xi.int_length = " << xi.int_length() << ", maxdeg = " << maxdeg << endl; - throw gcdheu_failed(); + throw gcdheu_failed(); } - // Apply evaluation homomorphism and calculate GCD + // Apply evaluation homomorphism and calculate GCD ex cp, cq; - ex gamma = heur_gcd(p.subs(x == xi), q.subs(x == xi), &cp, &cq, var+1).expand(); - if (!is_ex_exactly_of_type(gamma, fail)) { + ex gamma = heur_gcd(p.subs(x == xi), q.subs(x == xi), &cp, &cq, var+1).expand(); + if (!is_ex_exactly_of_type(gamma, fail)) { - // Reconstruct polynomial from GCD of mapped polynomials + // Reconstruct polynomial from GCD of mapped polynomials ex g = interpolate(gamma, xi, x); - // Remove integer content - g /= g.integer_content(); - - // If the calculated polynomial divides both p and q, this is the GCD - ex dummy; - if (divide_in_z(p, g, ca ? *ca : dummy, var) && divide_in_z(q, g, cb ? *cb : dummy, var)) { - g *= gc; - ex lc = g.lcoeff(x); - if (is_ex_exactly_of_type(lc, numeric) && ex_to_numeric(lc).is_negative()) - return -g; - else - return g; - } + // Remove integer content + g /= g.integer_content(); + + // If the calculated polynomial divides both p and q, this is the GCD + ex dummy; + if (divide_in_z(p, g, ca ? *ca : dummy, var) && divide_in_z(q, g, cb ? *cb : dummy, var)) { + g *= gc; + ex lc = g.lcoeff(x); + if (is_ex_exactly_of_type(lc, numeric) && ex_to_numeric(lc).is_negative()) + return -g; + else + return g; + } #if 0 cp = interpolate(cp, xi, x); if (divide_in_z(cp, p, g, var)) { @@ -1398,11 +1398,11 @@ static ex heur_gcd(const ex &a, const ex &b, ex *ca, ex *cb, sym_desc_vec::const g *= gc; if (ca) *ca = cp; - ex lc = g.lcoeff(x); - if (is_ex_exactly_of_type(lc, numeric) && ex_to_numeric(lc).is_negative()) - return -g; - else - return g; + ex lc = g.lcoeff(x); + if (is_ex_exactly_of_type(lc, numeric) && ex_to_numeric(lc).is_negative()) + return -g; + else + return g; } } cq = interpolate(cq, xi, x); @@ -1411,20 +1411,20 @@ static ex heur_gcd(const ex &a, const ex &b, ex *ca, ex *cb, sym_desc_vec::const g *= gc; if (cb) *cb = cq; - ex lc = g.lcoeff(x); - if (is_ex_exactly_of_type(lc, numeric) && ex_to_numeric(lc).is_negative()) - return -g; - else - return g; + ex lc = g.lcoeff(x); + if (is_ex_exactly_of_type(lc, numeric) && ex_to_numeric(lc).is_negative()) + return -g; + else + return g; } } #endif - } + } - // Next evaluation point - xi = iquo(xi * isqrt(isqrt(xi)) * numeric(73794), numeric(27011)); - } - return *new ex(fail()); + // Next evaluation point + xi = iquo(xi * isqrt(isqrt(xi)) * numeric(73794), numeric(27011)); + } + return *new ex(fail()); } @@ -1444,8 +1444,8 @@ ex gcd(const ex &a, const ex &b, ex *ca, ex *cb, bool check_args) #endif // GCD of numerics -> CLN - if (is_ex_exactly_of_type(a, numeric) && is_ex_exactly_of_type(b, numeric)) { - numeric g = gcd(ex_to_numeric(a), ex_to_numeric(b)); + if (is_ex_exactly_of_type(a, numeric) && is_ex_exactly_of_type(b, numeric)) { + numeric g = gcd(ex_to_numeric(a), ex_to_numeric(b)); if (ca || cb) { if (g.is_zero()) { if (ca) @@ -1453,19 +1453,19 @@ ex gcd(const ex &a, const ex &b, ex *ca, ex *cb, bool check_args) if (cb) *cb = _ex0(); } else { - if (ca) - *ca = ex_to_numeric(a) / g; - if (cb) - *cb = ex_to_numeric(b) / g; + if (ca) + *ca = ex_to_numeric(a) / g; + if (cb) + *cb = ex_to_numeric(b) / g; } } - return g; - } + return g; + } // Check arguments - if (check_args && !a.info(info_flags::rational_polynomial) || !b.info(info_flags::rational_polynomial)) { - throw(std::invalid_argument("gcd: arguments must be polynomials over the rationals")); - } + if (check_args && !a.info(info_flags::rational_polynomial) || !b.info(info_flags::rational_polynomial)) { + throw(std::invalid_argument("gcd: arguments must be polynomials over the rationals")); + } // Partially factored cases (to avoid expanding large expressions) if (is_ex_exactly_of_type(a, mul)) { @@ -1551,83 +1551,83 @@ factored_b: } #endif - // Some trivial cases + // Some trivial cases ex aex = a.expand(), bex = b.expand(); - if (aex.is_zero()) { - if (ca) - *ca = _ex0(); - if (cb) - *cb = _ex1(); - return b; - } - if (bex.is_zero()) { - if (ca) - *ca = _ex1(); - if (cb) - *cb = _ex0(); - return a; - } - if (aex.is_equal(_ex1()) || bex.is_equal(_ex1())) { - if (ca) - *ca = a; - if (cb) - *cb = b; - return _ex1(); - } + if (aex.is_zero()) { + if (ca) + *ca = _ex0(); + if (cb) + *cb = _ex1(); + return b; + } + if (bex.is_zero()) { + if (ca) + *ca = _ex1(); + if (cb) + *cb = _ex0(); + return a; + } + if (aex.is_equal(_ex1()) || bex.is_equal(_ex1())) { + if (ca) + *ca = a; + if (cb) + *cb = b; + return _ex1(); + } #if FAST_COMPARE - if (a.is_equal(b)) { - if (ca) - *ca = _ex1(); - if (cb) - *cb = _ex1(); - return a; - } + if (a.is_equal(b)) { + if (ca) + *ca = _ex1(); + if (cb) + *cb = _ex1(); + return a; + } #endif - // Gather symbol statistics - sym_desc_vec sym_stats; - get_symbol_stats(a, b, sym_stats); + // Gather symbol statistics + sym_desc_vec sym_stats; + get_symbol_stats(a, b, sym_stats); - // The symbol with least degree is our main variable - sym_desc_vec::const_iterator var = sym_stats.begin(); - const symbol &x = *(var->sym); + // The symbol with least degree is our main variable + sym_desc_vec::const_iterator var = sym_stats.begin(); + const symbol &x = *(var->sym); - // Cancel trivial common factor - int ldeg_a = var->ldeg_a; - int ldeg_b = var->ldeg_b; - int min_ldeg = min(ldeg_a, ldeg_b); - if (min_ldeg > 0) { - ex common = power(x, min_ldeg); + // Cancel trivial common factor + int ldeg_a = var->ldeg_a; + int ldeg_b = var->ldeg_b; + int min_ldeg = min(ldeg_a, ldeg_b); + if (min_ldeg > 0) { + ex common = power(x, min_ldeg); //std::clog << "trivial common factor " << common << endl; - return gcd((aex / common).expand(), (bex / common).expand(), ca, cb, false) * common; - } + return gcd((aex / common).expand(), (bex / common).expand(), ca, cb, false) * common; + } - // Try to eliminate variables - if (var->deg_a == 0) { + // Try to eliminate variables + if (var->deg_a == 0) { //std::clog << "eliminating variable " << x << " from b" << endl; - ex c = bex.content(x); - ex g = gcd(aex, c, ca, cb, false); - if (cb) - *cb *= bex.unit(x) * bex.primpart(x, c); - return g; - } else if (var->deg_b == 0) { + ex c = bex.content(x); + ex g = gcd(aex, c, ca, cb, false); + if (cb) + *cb *= bex.unit(x) * bex.primpart(x, c); + return g; + } else if (var->deg_b == 0) { //std::clog << "eliminating variable " << x << " from a" << endl; - ex c = aex.content(x); - ex g = gcd(c, bex, ca, cb, false); - if (ca) - *ca *= aex.unit(x) * aex.primpart(x, c); - return g; - } - - ex g; + ex c = aex.content(x); + ex g = gcd(c, bex, ca, cb, false); + if (ca) + *ca *= aex.unit(x) * aex.primpart(x, c); + return g; + } + + ex g; #if 1 - // Try heuristic algorithm first, fall back to PRS if that failed - try { - g = heur_gcd(aex, bex, ca, cb, var); - } catch (gcdheu_failed) { - g = *new ex(fail()); - } - if (is_ex_exactly_of_type(g, fail)) { + // Try heuristic algorithm first, fall back to PRS if that failed + try { + g = heur_gcd(aex, bex, ca, cb, var); + } catch (gcdheu_failed) { + g = *new ex(fail()); + } + if (is_ex_exactly_of_type(g, fail)) { //std::clog << "heuristics failed" << endl; #if STATISTICS heur_gcd_failed++; @@ -1646,13 +1646,13 @@ factored_b: if (cb) *cb = b; } else { - if (ca) - divide(aex, g, *ca, false); - if (cb) - divide(bex, g, *cb, false); + if (ca) + divide(aex, g, *ca, false); + if (cb) + divide(bex, g, *cb, false); } #if 1 - } else { + } else { if (g.is_equal(_ex1())) { // Keep cofactors factored if possible if (ca) @@ -1662,7 +1662,7 @@ factored_b: } } #endif - return g; + return g; } @@ -1675,14 +1675,14 @@ factored_b: * @return the LCM as a new expression */ ex lcm(const ex &a, const ex &b, bool check_args) { - if (is_ex_exactly_of_type(a, numeric) && is_ex_exactly_of_type(b, numeric)) - return lcm(ex_to_numeric(a), ex_to_numeric(b)); - if (check_args && !a.info(info_flags::rational_polynomial) || !b.info(info_flags::rational_polynomial)) - throw(std::invalid_argument("lcm: arguments must be polynomials over the rationals")); - - ex ca, cb; - ex g = gcd(a, b, &ca, &cb, false); - return ca * cb * g; + if (is_ex_exactly_of_type(a, numeric) && is_ex_exactly_of_type(b, numeric)) + return lcm(ex_to_numeric(a), ex_to_numeric(b)); + if (check_args && !a.info(info_flags::rational_polynomial) || !b.info(info_flags::rational_polynomial)) + throw(std::invalid_argument("lcm: arguments must be polynomials over the rationals")); + + ex ca, cb; + ex g = gcd(a, b, &ca, &cb, false); + return ca * cb * g; } @@ -1694,34 +1694,34 @@ ex lcm(const ex &a, const ex &b, bool check_args) // a and b can be multivariate polynomials but they are treated as univariate polynomials in x. static ex univariate_gcd(const ex &a, const ex &b, const symbol &x) { - if (a.is_zero()) - return b; - if (b.is_zero()) - return a; - if (a.is_equal(_ex1()) || b.is_equal(_ex1())) - return _ex1(); - if (is_ex_of_type(a, numeric) && is_ex_of_type(b, numeric)) - return gcd(ex_to_numeric(a), ex_to_numeric(b)); - if (!a.info(info_flags::rational_polynomial) || !b.info(info_flags::rational_polynomial)) - throw(std::invalid_argument("univariate_gcd: arguments must be polynomials over the rationals")); - - // Euclidean algorithm - ex c, d, r; - if (a.degree(x) >= b.degree(x)) { - c = a; - d = b; - } else { - c = b; - d = a; - } - for (;;) { - r = rem(c, d, x, false); - if (r.is_zero()) - break; - c = d; - d = r; - } - return d / d.lcoeff(x); + if (a.is_zero()) + return b; + if (b.is_zero()) + return a; + if (a.is_equal(_ex1()) || b.is_equal(_ex1())) + return _ex1(); + if (is_ex_of_type(a, numeric) && is_ex_of_type(b, numeric)) + return gcd(ex_to_numeric(a), ex_to_numeric(b)); + if (!a.info(info_flags::rational_polynomial) || !b.info(info_flags::rational_polynomial)) + throw(std::invalid_argument("univariate_gcd: arguments must be polynomials over the rationals")); + + // Euclidean algorithm + ex c, d, r; + if (a.degree(x) >= b.degree(x)) { + c = a; + d = b; + } else { + c = b; + d = a; + } + for (;;) { + r = rem(c, d, x, false); + if (r.is_zero()) + break; + c = d; + d = r; + } + return d / d.lcoeff(x); } @@ -1733,27 +1733,27 @@ static ex univariate_gcd(const ex &a, const ex &b, const symbol &x) * @return factored polynomial */ ex sqrfree(const ex &a, const symbol &x) { - int i = 1; - ex res = _ex1(); - ex b = a.diff(x); - ex c = univariate_gcd(a, b, x); - ex w; - if (c.is_equal(_ex1())) { - w = a; - } else { - w = quo(a, c, x); - ex y = quo(b, c, x); - ex z = y - w.diff(x); - while (!z.is_zero()) { - ex g = univariate_gcd(w, z, x); - res *= power(g, i); - w = quo(w, g, x); - y = quo(z, g, x); - z = y - w.diff(x); - i++; - } - } - return res * power(w, i); + int i = 1; + ex res = _ex1(); + ex b = a.diff(x); + ex c = univariate_gcd(a, b, x); + ex w; + if (c.is_equal(_ex1())) { + w = a; + } else { + w = quo(a, c, x); + ex y = quo(b, c, x); + ex z = y - w.diff(x); + while (!z.is_zero()) { + ex g = univariate_gcd(w, z, x); + res *= power(g, i); + w = quo(w, g, x); + y = quo(z, g, x); + z = y - w.diff(x); + i++; + } + } + return res * power(w, i); } @@ -1775,20 +1775,20 @@ ex sqrfree(const ex &a, const symbol &x) * @see ex::normal */ static ex replace_with_symbol(const ex &e, lst &sym_lst, lst &repl_lst) { - // Expression already in repl_lst? Then return the assigned symbol - for (unsigned i=0; isetflag(status_flags::dynallocated); + return (new lst(replace_with_symbol(*this, sym_lst, repl_lst), _ex1()))->setflag(status_flags::dynallocated); } @@ -1825,7 +1825,7 @@ ex basic::normal(lst &sym_lst, lst &repl_lst, int level) const * @see ex::normal */ ex symbol::normal(lst &sym_lst, lst &repl_lst, int level) const { - return (new lst(*this, _ex1()))->setflag(status_flags::dynallocated); + return (new lst(*this, _ex1()))->setflag(status_flags::dynallocated); } @@ -1838,15 +1838,15 @@ ex numeric::normal(lst &sym_lst, lst &repl_lst, int level) const numeric num = numer(); ex numex = num; - if (num.is_real()) { - if (!num.is_integer()) - numex = replace_with_symbol(numex, sym_lst, repl_lst); - } else { // complex - numeric re = num.real(), im = num.imag(); - ex re_ex = re.is_rational() ? re : replace_with_symbol(re, sym_lst, repl_lst); - ex im_ex = im.is_rational() ? im : replace_with_symbol(im, sym_lst, repl_lst); - numex = re_ex + im_ex * replace_with_symbol(I, sym_lst, repl_lst); - } + if (num.is_real()) { + if (!num.is_integer()) + numex = replace_with_symbol(numex, sym_lst, repl_lst); + } else { // complex + numeric re = num.real(), im = num.imag(); + ex re_ex = re.is_rational() ? re : replace_with_symbol(re, sym_lst, repl_lst); + ex im_ex = im.is_rational() ? im : replace_with_symbol(im, sym_lst, repl_lst); + numex = re_ex + im_ex * replace_with_symbol(I, sym_lst, repl_lst); + } // Denominator is always a real integer (see numeric::denom()) return (new lst(numex, denom()))->setflag(status_flags::dynallocated); @@ -1859,29 +1859,29 @@ ex numeric::normal(lst &sym_lst, lst &repl_lst, int level) const * @return cancelled fraction {n, d} as a list */ static ex frac_cancel(const ex &n, const ex &d) { - ex num = n; - ex den = d; - numeric pre_factor = _num1(); + ex num = n; + ex den = d; + numeric pre_factor = _num1(); //std::clog << "frac_cancel num = " << num << ", den = " << den << endl; - // Handle special cases where numerator or denominator is 0 - if (num.is_zero()) + // Handle special cases where numerator or denominator is 0 + if (num.is_zero()) return (new lst(_ex0(), _ex1()))->setflag(status_flags::dynallocated); - if (den.expand().is_zero()) - throw(std::overflow_error("frac_cancel: division by zero in frac_cancel")); + if (den.expand().is_zero()) + throw(std::overflow_error("frac_cancel: division by zero in frac_cancel")); - // Bring numerator and denominator to Z[X] by multiplying with - // LCM of all coefficients' denominators - numeric num_lcm = lcm_of_coefficients_denominators(num); - numeric den_lcm = lcm_of_coefficients_denominators(den); + // Bring numerator and denominator to Z[X] by multiplying with + // LCM of all coefficients' denominators + numeric num_lcm = lcm_of_coefficients_denominators(num); + numeric den_lcm = lcm_of_coefficients_denominators(den); num = multiply_lcm(num, num_lcm); den = multiply_lcm(den, den_lcm); - pre_factor = den_lcm / num_lcm; + pre_factor = den_lcm / num_lcm; - // Cancel GCD from numerator and denominator - ex cnum, cden; - if (gcd(num, den, &cnum, &cden, false) != _ex1()) { + // Cancel GCD from numerator and denominator + ex cnum, cden; + if (gcd(num, den, &cnum, &cden, false) != _ex1()) { num = cnum; den = cden; } @@ -1890,7 +1890,7 @@ static ex frac_cancel(const ex &n, const ex &d) // as defined by get_first_symbol() is made positive) const symbol *x; if (get_first_symbol(den, x)) { - GINAC_ASSERT(is_ex_exactly_of_type(den.unit(*x),numeric)); + GINAC_ASSERT(is_ex_exactly_of_type(den.unit(*x),numeric)); if (ex_to_numeric(den.unit(*x)).is_negative()) { num *= _ex_1(); den *= _ex_1(); @@ -1899,7 +1899,7 @@ static ex frac_cancel(const ex &n, const ex &d) // Return result as list //std::clog << " returns num = " << num << ", den = " << den << ", pre_factor = " << pre_factor << endl; - return (new lst(num * pre_factor.numer(), den * pre_factor.denom()))->setflag(status_flags::dynallocated); + return (new lst(num * pre_factor.numer(), den * pre_factor.denom()))->setflag(status_flags::dynallocated); } @@ -1911,54 +1911,54 @@ ex add::normal(lst &sym_lst, lst &repl_lst, int level) const if (level == 1) return (new lst(*this, _ex1()))->setflag(status_flags::dynallocated); else if (level == -max_recursion_level) - throw(std::runtime_error("max recursion level reached")); + throw(std::runtime_error("max recursion level reached")); - // Normalize and expand children, chop into summands - exvector o; - o.reserve(seq.size()+1); - epvector::const_iterator it = seq.begin(), itend = seq.end(); - while (it != itend) { + // Normalize and expand children, chop into summands + exvector o; + o.reserve(seq.size()+1); + epvector::const_iterator it = seq.begin(), itend = seq.end(); + while (it != itend) { // Normalize and expand child - ex n = recombine_pair_to_ex(*it).bp->normal(sym_lst, repl_lst, level-1).expand(); + ex n = recombine_pair_to_ex(*it).bp->normal(sym_lst, repl_lst, level-1).expand(); // If numerator is a sum, chop into summands - if (is_ex_exactly_of_type(n.op(0), add)) { - epvector::const_iterator bit = ex_to_add(n.op(0)).seq.begin(), bitend = ex_to_add(n.op(0)).seq.end(); - while (bit != bitend) { - o.push_back((new lst(recombine_pair_to_ex(*bit), n.op(1)))->setflag(status_flags::dynallocated)); - bit++; - } + if (is_ex_exactly_of_type(n.op(0), add)) { + epvector::const_iterator bit = ex_to_add(n.op(0)).seq.begin(), bitend = ex_to_add(n.op(0)).seq.end(); + while (bit != bitend) { + o.push_back((new lst(recombine_pair_to_ex(*bit), n.op(1)))->setflag(status_flags::dynallocated)); + bit++; + } // The overall_coeff is already normalized (== rational), we just // split it into numerator and denominator GINAC_ASSERT(ex_to_numeric(ex_to_add(n.op(0)).overall_coeff).is_rational()); numeric overall = ex_to_numeric(ex_to_add(n.op(0)).overall_coeff); - o.push_back((new lst(overall.numer(), overall.denom() * n.op(1)))->setflag(status_flags::dynallocated)); - } else - o.push_back(n); - it++; - } - o.push_back(overall_coeff.bp->normal(sym_lst, repl_lst, level-1)); + o.push_back((new lst(overall.numer(), overall.denom() * n.op(1)))->setflag(status_flags::dynallocated)); + } else + o.push_back(n); + it++; + } + o.push_back(overall_coeff.bp->normal(sym_lst, repl_lst, level-1)); // o is now a vector of {numerator, denominator} lists - // Determine common denominator - ex den = _ex1(); - exvector::const_iterator ait = o.begin(), aitend = o.end(); + // Determine common denominator + ex den = _ex1(); + exvector::const_iterator ait = o.begin(), aitend = o.end(); //std::clog << "add::normal uses the following summands:\n"; - while (ait != aitend) { + while (ait != aitend) { //std::clog << " num = " << ait->op(0) << ", den = " << ait->op(1) << endl; - den = lcm(ait->op(1), den, false); - ait++; - } + den = lcm(ait->op(1), den, false); + ait++; + } //std::clog << " common denominator = " << den << endl; - // Add fractions - if (den.is_equal(_ex1())) { + // Add fractions + if (den.is_equal(_ex1())) { // Common denominator is 1, simply add all fractions - exvector num_seq; + exvector num_seq; for (ait=o.begin(); ait!=aitend; ait++) { num_seq.push_back(ait->op(0) / ait->op(1)); } @@ -1967,20 +1967,20 @@ ex add::normal(lst &sym_lst, lst &repl_lst, int level) const } else { // Perform fractional addition - exvector num_seq; - for (ait=o.begin(); ait!=aitend; ait++) { - ex q; - if (!divide(den, ait->op(1), q, false)) { - // should not happen - throw(std::runtime_error("invalid expression in add::normal, division failed")); - } - num_seq.push_back((ait->op(0) * q).expand()); - } - ex num = (new add(num_seq))->setflag(status_flags::dynallocated); - - // Cancel common factors from num/den - return frac_cancel(num, den); - } + exvector num_seq; + for (ait=o.begin(); ait!=aitend; ait++) { + ex q; + if (!divide(den, ait->op(1), q, false)) { + // should not happen + throw(std::runtime_error("invalid expression in add::normal, division failed")); + } + num_seq.push_back((ait->op(0) * q).expand()); + } + ex num = (new add(num_seq))->setflag(status_flags::dynallocated); + + // Cancel common factors from num/den + return frac_cancel(num, den); + } } @@ -1992,25 +1992,25 @@ ex mul::normal(lst &sym_lst, lst &repl_lst, int level) const if (level == 1) return (new lst(*this, _ex1()))->setflag(status_flags::dynallocated); else if (level == -max_recursion_level) - throw(std::runtime_error("max recursion level reached")); + throw(std::runtime_error("max recursion level reached")); - // Normalize children, separate into numerator and denominator + // Normalize children, separate into numerator and denominator ex num = _ex1(); ex den = _ex1(); ex n; - epvector::const_iterator it = seq.begin(), itend = seq.end(); - while (it != itend) { + epvector::const_iterator it = seq.begin(), itend = seq.end(); + while (it != itend) { n = recombine_pair_to_ex(*it).bp->normal(sym_lst, repl_lst, level-1); num *= n.op(0); den *= n.op(1); - it++; - } + it++; + } n = overall_coeff.bp->normal(sym_lst, repl_lst, level-1); num *= n.op(0); den *= n.op(1); // Perform fraction cancellation - return frac_cancel(num, den); + return frac_cancel(num, den); } @@ -2023,14 +2023,14 @@ ex power::normal(lst &sym_lst, lst &repl_lst, int level) const if (level == 1) return (new lst(*this, _ex1()))->setflag(status_flags::dynallocated); else if (level == -max_recursion_level) - throw(std::runtime_error("max recursion level reached")); + throw(std::runtime_error("max recursion level reached")); // Normalize basis - ex n = basis.bp->normal(sym_lst, repl_lst, level-1); + ex n = basis.bp->normal(sym_lst, repl_lst, level-1); if (exponent.info(info_flags::integer)) { - if (exponent.info(info_flags::positive)) { + if (exponent.info(info_flags::positive)) { // (a/b)^n -> {a^n, b^n} return (new lst(power(n.op(0), exponent), power(n.op(1), exponent)))->setflag(status_flags::dynallocated); @@ -2066,7 +2066,7 @@ ex power::normal(lst &sym_lst, lst &repl_lst, int level) const // (a/b)^x -> {sym((a/b)^x, 1} return (new lst(replace_with_symbol(power(n.op(0) / n.op(1), exponent), sym_lst, repl_lst), _ex1()))->setflag(status_flags::dynallocated); } - } + } } @@ -2075,15 +2075,15 @@ ex power::normal(lst &sym_lst, lst &repl_lst, int level) const * @see ex::normal */ ex pseries::normal(lst &sym_lst, lst &repl_lst, int level) const { - epvector new_seq; - new_seq.reserve(seq.size()); - - epvector::const_iterator it = seq.begin(), itend = seq.end(); - while (it != itend) { - new_seq.push_back(expair(it->rest.normal(), it->coeff)); - it++; - } - ex n = pseries(relational(var,point), new_seq); + epvector new_seq; + new_seq.reserve(seq.size()); + + epvector::const_iterator it = seq.begin(), itend = seq.end(); + while (it != itend) { + new_seq.push_back(expair(it->rest.normal(), it->coeff)); + it++; + } + ex n = pseries(relational(var,point), new_seq); return (new lst(replace_with_symbol(n, sym_lst, repl_lst), _ex1()))->setflag(status_flags::dynallocated); } @@ -2110,17 +2110,17 @@ ex relational::normal(lst &sym_lst, lst &repl_lst, int level) const * @return normalized expression */ ex ex::normal(int level) const { - lst sym_lst, repl_lst; + lst sym_lst, repl_lst; - ex e = bp->normal(sym_lst, repl_lst, level); + ex e = bp->normal(sym_lst, repl_lst, level); GINAC_ASSERT(is_ex_of_type(e, lst)); // Re-insert replaced symbols - if (sym_lst.nops() > 0) - e = e.subs(sym_lst, repl_lst); + if (sym_lst.nops() > 0) + e = e.subs(sym_lst, repl_lst); // Convert {numerator, denominator} form back to fraction - return e.op(0) / e.op(1); + return e.op(0) / e.op(1); } /** Numerator of an expression. If the expression is not of the normal form @@ -2131,14 +2131,14 @@ ex ex::normal(int level) const * @return numerator */ ex ex::numer(void) const { - lst sym_lst, repl_lst; + lst sym_lst, repl_lst; - ex e = bp->normal(sym_lst, repl_lst, 0); + ex e = bp->normal(sym_lst, repl_lst, 0); GINAC_ASSERT(is_ex_of_type(e, lst)); // Re-insert replaced symbols - if (sym_lst.nops() > 0) - return e.op(0).subs(sym_lst, repl_lst); + if (sym_lst.nops() > 0) + return e.op(0).subs(sym_lst, repl_lst); else return e.op(0); } @@ -2151,14 +2151,14 @@ ex ex::numer(void) const * @return denominator */ ex ex::denom(void) const { - lst sym_lst, repl_lst; + lst sym_lst, repl_lst; - ex e = bp->normal(sym_lst, repl_lst, 0); + ex e = bp->normal(sym_lst, repl_lst, 0); GINAC_ASSERT(is_ex_of_type(e, lst)); // Re-insert replaced symbols - if (sym_lst.nops() > 0) - return e.op(1).subs(sym_lst, repl_lst); + if (sym_lst.nops() > 0) + return e.op(1).subs(sym_lst, repl_lst); else return e.op(1); } @@ -2178,7 +2178,7 @@ ex basic::to_rational(lst &repl_lst) const * @see ex::to_rational */ ex symbol::to_rational(lst &repl_lst) const { - return *this; + return *this; } @@ -2188,16 +2188,16 @@ ex symbol::to_rational(lst &repl_lst) const * @see ex::to_rational */ ex numeric::to_rational(lst &repl_lst) const { - if (is_real()) { - if (!is_rational()) - return replace_with_symbol(*this, repl_lst); - } else { // complex - numeric re = real(); - numeric im = imag(); - ex re_ex = re.is_rational() ? re : replace_with_symbol(re, repl_lst); - ex im_ex = im.is_rational() ? im : replace_with_symbol(im, repl_lst); - return re_ex + im_ex * replace_with_symbol(I, repl_lst); - } + if (is_real()) { + if (!is_rational()) + return replace_with_symbol(*this, repl_lst); + } else { // complex + numeric re = real(); + numeric im = imag(); + ex re_ex = re.is_rational() ? re : replace_with_symbol(re, repl_lst); + ex im_ex = im.is_rational() ? im : replace_with_symbol(im, repl_lst); + return re_ex + im_ex * replace_with_symbol(I, repl_lst); + } return *this; } @@ -2218,17 +2218,17 @@ ex power::to_rational(lst &repl_lst) const * @see ex::to_rational */ ex expairseq::to_rational(lst &repl_lst) const { - epvector s; - s.reserve(seq.size()); - for (epvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) { - s.push_back(split_ex_to_pair(recombine_pair_to_ex(*it).to_rational(repl_lst))); - // s.push_back(combine_ex_with_coeff_to_pair((*it).rest.to_rational(repl_lst), - } - ex oc = overall_coeff.to_rational(repl_lst); - if (oc.info(info_flags::numeric)) - return thisexpairseq(s, overall_coeff); - else s.push_back(combine_ex_with_coeff_to_pair(oc,_ex1())); - return thisexpairseq(s, default_overall_coeff()); + epvector s; + s.reserve(seq.size()); + for (epvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) { + s.push_back(split_ex_to_pair(recombine_pair_to_ex(*it).to_rational(repl_lst))); + // s.push_back(combine_ex_with_coeff_to_pair((*it).rest.to_rational(repl_lst), + } + ex oc = overall_coeff.to_rational(repl_lst); + if (oc.info(info_flags::numeric)) + return thisexpairseq(s, overall_coeff); + else s.push_back(combine_ex_with_coeff_to_pair(oc,_ex1())); + return thisexpairseq(s, default_overall_coeff()); } diff --git a/ginac/numeric.cpp b/ginac/numeric.cpp index bcf140d6..24e33e46 100644 --- a/ginac/numeric.cpp +++ b/ginac/numeric.cpp @@ -94,49 +94,49 @@ 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); - value = new ::cl_N; - *value = ::cl_I(0); - calchash(); - setflag(status_flags::evaluated | - status_flags::expanded | - status_flags::hash_calculated); + debugmsg("numeric default constructor", LOGLEVEL_CONSTRUCT); + value = new ::cl_N; + *value = ::cl_I(0); + calchash(); + setflag(status_flags::evaluated | + status_flags::expanded | + status_flags::hash_calculated); } numeric::~numeric() { - debugmsg("numeric destructor" ,LOGLEVEL_DESTRUCT); - destroy(0); + debugmsg("numeric destructor" ,LOGLEVEL_DESTRUCT); + destroy(0); } numeric::numeric(const numeric & other) { - debugmsg("numeric copy constructor", LOGLEVEL_CONSTRUCT); - copy(other); + debugmsg("numeric copy constructor", LOGLEVEL_CONSTRUCT); + copy(other); } const numeric & numeric::operator=(const numeric & other) { - debugmsg("numeric operator=", LOGLEVEL_ASSIGNMENT); - if (this != &other) { - destroy(1); - copy(other); - } - return *this; + debugmsg("numeric operator=", LOGLEVEL_ASSIGNMENT); + if (this != &other) { + destroy(1); + copy(other); + } + return *this; } // protected void numeric::copy(const numeric & other) { - basic::copy(other); - value = new ::cl_N(*other.value); + basic::copy(other); + value = new ::cl_N(*other.value); } void numeric::destroy(bool call_parent) { - delete value; - if (call_parent) basic::destroy(call_parent); + delete value; + if (call_parent) basic::destroy(call_parent); } ////////// @@ -147,51 +147,51 @@ void numeric::destroy(bool call_parent) numeric::numeric(int i) : basic(TINFO_numeric) { - debugmsg("numeric constructor 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: - value = new ::cl_I((long) i); - calchash(); - setflag(status_flags::evaluated | - status_flags::expanded | - status_flags::hash_calculated); + debugmsg("numeric constructor 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: + value = new ::cl_I((long) i); + calchash(); + setflag(status_flags::evaluated | + status_flags::expanded | + status_flags::hash_calculated); } numeric::numeric(unsigned int i) : basic(TINFO_numeric) { - debugmsg("numeric constructor 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: - value = new ::cl_I((unsigned long)i); - calchash(); - setflag(status_flags::evaluated | - status_flags::expanded | - status_flags::hash_calculated); + debugmsg("numeric constructor 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: + value = new ::cl_I((unsigned long)i); + calchash(); + setflag(status_flags::evaluated | + status_flags::expanded | + status_flags::hash_calculated); } numeric::numeric(long i) : basic(TINFO_numeric) { - debugmsg("numeric constructor from long",LOGLEVEL_CONSTRUCT); - value = new ::cl_I(i); - calchash(); - setflag(status_flags::evaluated | - status_flags::expanded | - status_flags::hash_calculated); + debugmsg("numeric constructor from long",LOGLEVEL_CONSTRUCT); + value = new ::cl_I(i); + calchash(); + setflag(status_flags::evaluated | + status_flags::expanded | + status_flags::hash_calculated); } numeric::numeric(unsigned long i) : basic(TINFO_numeric) { - debugmsg("numeric constructor from ulong",LOGLEVEL_CONSTRUCT); - value = new ::cl_I(i); - calchash(); - setflag(status_flags::evaluated | - status_flags::expanded | - status_flags::hash_calculated); + debugmsg("numeric constructor from ulong",LOGLEVEL_CONSTRUCT); + value = new ::cl_I(i); + calchash(); + setflag(status_flags::evaluated | + status_flags::expanded | + status_flags::hash_calculated); } /** Ctor for rational numerics a/b. @@ -199,30 +199,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); - if (!denom) - throw std::overflow_error("division by zero"); - value = new ::cl_I(numer); - *value = *value / ::cl_I(denom); - calchash(); - setflag(status_flags::evaluated | - status_flags::expanded | - status_flags::hash_calculated); + debugmsg("numeric constructor from long/long",LOGLEVEL_CONSTRUCT); + if (!denom) + throw std::overflow_error("division by zero"); + value = new ::cl_I(numer); + *value = *value / ::cl_I(denom); + calchash(); + setflag(status_flags::evaluated | + status_flags::expanded | + status_flags::hash_calculated); } numeric::numeric(double d) : basic(TINFO_numeric) { - debugmsg("numeric constructor 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 = new cl_N; - *value = cl_float(d, cl_default_float_format); - calchash(); - setflag(status_flags::evaluated | - status_flags::expanded | - status_flags::hash_calculated); + debugmsg("numeric constructor 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 = new cl_N; + *value = cl_float(d, cl_default_float_format); + calchash(); + setflag(status_flags::evaluated | + status_flags::expanded | + status_flags::hash_calculated); } @@ -230,71 +230,71 @@ numeric::numeric(double d) : basic(TINFO_numeric) * notation like "2+5*I". */ numeric::numeric(const char *s) : basic(TINFO_numeric) { - debugmsg("numeric constructor from string",LOGLEVEL_CONSTRUCT); - value = new ::cl_N(0); - // parse complex numbers (functional but not completely safe, unfortunately - // std::string does not understand regexpese): - // ss should represent a simple sum like 2+5*I - std::string ss(s); - // make it safe by adding explicit sign - if (ss.at(0) != '+' && ss.at(0) != '-' && ss.at(0) != '#') - ss = '+' + ss; - std::string::size_type delim; - do { - // chop ss into terms from left to right - std::string term; - bool imaginary = false; - delim = ss.find_first_of(std::string("+-"),1); - // Do we have an exponent marker like "31.415E-1"? If so, hop on! - if (delim != std::string::npos && - ss.at(delim-1) == 'E') - delim = ss.find_first_of(std::string("+-"),delim+1); - term = ss.substr(0,delim); - if (delim != std::string::npos) - ss = ss.substr(delim); - // is the term imaginary? - if (term.find("I") != std::string::npos) { - // erase 'I': - term = term.replace(term.find("I"),1,""); - // erase '*': - if (term.find("*") != std::string::npos) - term = term.replace(term.find("*"),1,""); - // correct for trivial +/-I without explicit factor on I: - if (term.size() == 1) - term += "1"; - imaginary = true; - } - const char *cs = term.c_str(); - // CLN's short types are not useful within the GiNaC framework, hence - // we go straight to the construction of a long float. Simply using - // cl_N(s) would require us to use add a CLN exponent mark, otherwise - // we would not be save from over-/underflows. - if (strchr(cs, '.')) - if (imaginary) - *value = *value + ::complex(cl_I(0),::cl_LF(cs)); - else - *value = *value + ::cl_LF(cs); - else - if (imaginary) - *value = *value + ::complex(cl_I(0),::cl_R(cs)); - else - *value = *value + ::cl_R(cs); - } while(delim != std::string::npos); - calchash(); - setflag(status_flags::evaluated| - status_flags::hash_calculated); + debugmsg("numeric constructor from string",LOGLEVEL_CONSTRUCT); + value = new ::cl_N(0); + // parse complex numbers (functional but not completely safe, unfortunately + // std::string does not understand regexpese): + // ss should represent a simple sum like 2+5*I + std::string ss(s); + // make it safe by adding explicit sign + if (ss.at(0) != '+' && ss.at(0) != '-' && ss.at(0) != '#') + ss = '+' + ss; + std::string::size_type delim; + do { + // chop ss into terms from left to right + std::string term; + bool imaginary = false; + delim = ss.find_first_of(std::string("+-"),1); + // Do we have an exponent marker like "31.415E-1"? If so, hop on! + if (delim != std::string::npos && + ss.at(delim-1) == 'E') + delim = ss.find_first_of(std::string("+-"),delim+1); + term = ss.substr(0,delim); + if (delim != std::string::npos) + ss = ss.substr(delim); + // is the term imaginary? + if (term.find("I") != std::string::npos) { + // erase 'I': + term = term.replace(term.find("I"),1,""); + // erase '*': + if (term.find("*") != std::string::npos) + term = term.replace(term.find("*"),1,""); + // correct for trivial +/-I without explicit factor on I: + if (term.size() == 1) + term += "1"; + imaginary = true; + } + const char *cs = term.c_str(); + // CLN's short types are not useful within the GiNaC framework, hence + // we go straight to the construction of a long float. Simply using + // cl_N(s) would require us to use add a CLN exponent mark, otherwise + // we would not be save from over-/underflows. + if (strchr(cs, '.')) + if (imaginary) + *value = *value + ::complex(cl_I(0),::cl_LF(cs)); + else + *value = *value + ::cl_LF(cs); + else + if (imaginary) + *value = *value + ::complex(cl_I(0),::cl_R(cs)); + else + *value = *value + ::cl_R(cs); + } while(delim != std::string::npos); + calchash(); + setflag(status_flags::evaluated| + status_flags::hash_calculated); } /** Ctor from CLN types. This is for the initiated user or internal use * only. */ numeric::numeric(const cl_N & z) : basic(TINFO_numeric) { - debugmsg("numeric constructor from cl_N", LOGLEVEL_CONSTRUCT); - value = new ::cl_N(z); - calchash(); - setflag(status_flags::evaluated | - status_flags::expanded | - status_flags::hash_calculated); + debugmsg("numeric constructor from cl_N", LOGLEVEL_CONSTRUCT); + value = new ::cl_N(z); + calchash(); + setflag(status_flags::evaluated | + status_flags::expanded | + status_flags::hash_calculated); } ////////// @@ -304,84 +304,84 @@ numeric::numeric(const 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); - value = new ::cl_N; + debugmsg("numeric constructor from archive_node", LOGLEVEL_CONSTRUCT); + value = new ::cl_N; - // Read number as string - std::string str; - if (n.find_string("number", str)) { + // Read number as string + std::string str; + if (n.find_string("number", str)) { #ifdef HAVE_SSTREAM - std::istringstream s(str); + std::istringstream s(str); #else - std::istrstream s(str.c_str(), str.size() + 1); + std::istrstream s(str.c_str(), str.size() + 1); #endif - ::cl_idecoded_float re, im; - char c; - s.get(c); - switch (c) { - case 'R': // Integer-decoded real number - s >> re.sign >> re.mantissa >> re.exponent; - *value = re.sign * re.mantissa * ::expt(cl_float(2.0, cl_default_float_format), re.exponent); - break; - case 'C': // Integer-decoded complex number - s >> re.sign >> re.mantissa >> re.exponent; - s >> im.sign >> im.mantissa >> im.exponent; - *value = ::complex(re.sign * re.mantissa * ::expt(cl_float(2.0, cl_default_float_format), re.exponent), - im.sign * im.mantissa * ::expt(cl_float(2.0, cl_default_float_format), im.exponent)); - break; - default: // Ordinary number - s.putback(c); - s >> *value; - break; - } - } - calchash(); - setflag(status_flags::evaluated | - status_flags::expanded | - status_flags::hash_calculated); + ::cl_idecoded_float re, im; + char c; + s.get(c); + switch (c) { + case 'R': // Integer-decoded real number + s >> re.sign >> re.mantissa >> re.exponent; + *value = re.sign * re.mantissa * ::expt(cl_float(2.0, cl_default_float_format), re.exponent); + break; + case 'C': // Integer-decoded complex number + s >> re.sign >> re.mantissa >> re.exponent; + s >> im.sign >> im.mantissa >> im.exponent; + *value = ::complex(re.sign * re.mantissa * ::expt(cl_float(2.0, cl_default_float_format), re.exponent), + im.sign * im.mantissa * ::expt(cl_float(2.0, cl_default_float_format), im.exponent)); + break; + default: // Ordinary number + s.putback(c); + s >> *value; + break; + } + } + calchash(); + setflag(status_flags::evaluated | + status_flags::expanded | + status_flags::hash_calculated); } /** Unarchive the object. */ ex numeric::unarchive(const archive_node &n, const lst &sym_lst) { - return (new numeric(n, sym_lst))->setflag(status_flags::dynallocated); + return (new numeric(n, sym_lst))->setflag(status_flags::dynallocated); } /** Archive the object. */ void numeric::archive(archive_node &n) const { - inherited::archive(n); + inherited::archive(n); - // Write number as string + // Write number as string #ifdef HAVE_SSTREAM - std::ostringstream s; + std::ostringstream s; #else - char buf[1024]; - std::ostrstream s(buf, 1024); + char buf[1024]; + std::ostrstream s(buf, 1024); #endif - if (this->is_crational()) - s << *value; - else { - // Non-rational numbers are written in an integer-decoded format - // to preserve the precision - if (this->is_real()) { - cl_idecoded_float re = integer_decode_float(The(::cl_F)(*value)); - s << "R"; - s << re.sign << " " << re.mantissa << " " << re.exponent; - } else { - cl_idecoded_float re = integer_decode_float(The(::cl_F)(::realpart(*value))); - cl_idecoded_float im = integer_decode_float(The(::cl_F)(::imagpart(*value))); - s << "C"; - s << re.sign << " " << re.mantissa << " " << re.exponent << " "; - s << im.sign << " " << im.mantissa << " " << im.exponent; - } - } + if (this->is_crational()) + s << *value; + else { + // Non-rational numbers are written in an integer-decoded format + // to preserve the precision + if (this->is_real()) { + cl_idecoded_float re = integer_decode_float(The(::cl_F)(*value)); + s << "R"; + s << re.sign << " " << re.mantissa << " " << re.exponent; + } else { + cl_idecoded_float re = integer_decode_float(The(::cl_F)(::realpart(*value))); + cl_idecoded_float im = integer_decode_float(The(::cl_F)(::imagpart(*value))); + s << "C"; + s << re.sign << " " << re.mantissa << " " << re.exponent << " "; + s << im.sign << " " << im.mantissa << " " << im.exponent; + } + } #ifdef HAVE_SSTREAM - n.add_string("number", s.str()); + n.add_string("number", s.str()); #else - s << ends; - std::string str(buf); - n.add_string("number", str); + s << ends; + std::string str(buf); + n.add_string("number", str); #endif } @@ -393,8 +393,8 @@ void numeric::archive(archive_node &n) const basic * numeric::duplicate() const { - debugmsg("numeric duplicate", LOGLEVEL_DUPLICATE); - return new numeric(*this); + debugmsg("numeric duplicate", LOGLEVEL_DUPLICATE); + return new numeric(*this); } @@ -406,18 +406,18 @@ basic * numeric::duplicate() const * @see numeric::print() */ static void print_real_number(std::ostream & os, const cl_R & num) { - cl_print_flags ourflags; - if (::instanceof(num, ::cl_RA_ring)) { - // case 1: integer or rational, nothing special to do: - ::print_real(os, ourflags, num); - } else { - // case 2: float - // make CLN believe this number has default_float_format, so it prints - // 'E' as exponent marker instead of 'L': - ourflags.default_float_format = ::cl_float_format(The(::cl_F)(num)); - ::print_real(os, ourflags, num); - } - return; + cl_print_flags ourflags; + if (::instanceof(num, ::cl_RA_ring)) { + // case 1: integer or rational, nothing special to do: + ::print_real(os, ourflags, num); + } else { + // case 2: float + // make CLN believe this number has default_float_format, so it prints + // 'E' as exponent marker instead of 'L': + ourflags.default_float_format = ::cl_float_format(The(::cl_F)(num)); + ::print_real(os, ourflags, num); + } + return; } /** This method adds to the output so it blends more consistently together @@ -426,165 +426,165 @@ static void print_real_number(std::ostream & os, const cl_R & num) * @see print_real_number() */ void numeric::print(std::ostream & os, unsigned upper_precedence) const { - debugmsg("numeric print", LOGLEVEL_PRINT); - if (this->is_real()) { - // case 1, real: x or -x - if ((precedence<=upper_precedence) && (!this->is_nonneg_integer())) { - os << "("; - print_real_number(os, The(::cl_R)(*value)); - os << ")"; - } else { - print_real_number(os, The(::cl_R)(*value)); - } - } else { - // case 2, imaginary: y*I or -y*I - if (::realpart(*value) == 0) { - if ((precedence<=upper_precedence) && (::imagpart(*value) < 0)) { - if (::imagpart(*value) == -1) { - os << "(-I)"; - } else { - os << "("; - print_real_number(os, The(::cl_R)(::imagpart(*value))); - os << "*I)"; - } - } else { - if (::imagpart(*value) == 1) { - os << "I"; - } else { - if (::imagpart (*value) == -1) { - os << "-I"; - } else { - print_real_number(os, The(::cl_R)(::imagpart(*value))); - os << "*I"; - } - } - } - } else { - // case 3, complex: x+y*I or x-y*I or -x+y*I or -x-y*I - if (precedence <= upper_precedence) - os << "("; - print_real_number(os, The(::cl_R)(::realpart(*value))); - if (::imagpart(*value) < 0) { - if (::imagpart(*value) == -1) { - os << "-I"; - } else { - print_real_number(os, The(::cl_R)(::imagpart(*value))); - os << "*I"; - } - } else { - if (::imagpart(*value) == 1) { - os << "+I"; - } else { - os << "+"; - print_real_number(os, The(::cl_R)(::imagpart(*value))); - os << "*I"; - } - } - if (precedence <= upper_precedence) - os << ")"; - } - } + debugmsg("numeric print", LOGLEVEL_PRINT); + if (this->is_real()) { + // case 1, real: x or -x + if ((precedence<=upper_precedence) && (!this->is_nonneg_integer())) { + os << "("; + print_real_number(os, The(::cl_R)(*value)); + os << ")"; + } else { + print_real_number(os, The(::cl_R)(*value)); + } + } else { + // case 2, imaginary: y*I or -y*I + if (::realpart(*value) == 0) { + if ((precedence<=upper_precedence) && (::imagpart(*value) < 0)) { + if (::imagpart(*value) == -1) { + os << "(-I)"; + } else { + os << "("; + print_real_number(os, The(::cl_R)(::imagpart(*value))); + os << "*I)"; + } + } else { + if (::imagpart(*value) == 1) { + os << "I"; + } else { + if (::imagpart (*value) == -1) { + os << "-I"; + } else { + print_real_number(os, The(::cl_R)(::imagpart(*value))); + os << "*I"; + } + } + } + } else { + // case 3, complex: x+y*I or x-y*I or -x+y*I or -x-y*I + if (precedence <= upper_precedence) + os << "("; + print_real_number(os, The(::cl_R)(::realpart(*value))); + if (::imagpart(*value) < 0) { + if (::imagpart(*value) == -1) { + os << "-I"; + } else { + print_real_number(os, The(::cl_R)(::imagpart(*value))); + os << "*I"; + } + } else { + if (::imagpart(*value) == 1) { + os << "+I"; + } else { + os << "+"; + print_real_number(os, The(::cl_R)(::imagpart(*value))); + os << "*I"; + } + } + if (precedence <= upper_precedence) + os << ")"; + } + } } 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 - debugmsg("numeric printraw", LOGLEVEL_PRINT); - os << "numeric(" << *value << ")"; + // The method printraw doesn't do much, it simply uses CLN's operator<<() + // for output, which is ugly but reliable. e.g: 2+2i + debugmsg("numeric printraw", LOGLEVEL_PRINT); + os << "numeric(" << *value << ")"; } void numeric::printtree(std::ostream & os, unsigned indent) const { - debugmsg("numeric printtree", LOGLEVEL_PRINT); - os << std::string(indent,' ') << *value - << " (numeric): " - << "hash=" << hashvalue - << " (0x" << std::hex << hashvalue << std::dec << ")" - << ", flags=" << flags << std::endl; + debugmsg("numeric printtree", LOGLEVEL_PRINT); + os << std::string(indent,' ') << *value + << " (numeric): " + << "hash=" << hashvalue + << " (0x" << std::hex << hashvalue << std::dec << ")" + << ", flags=" << flags << std::endl; } void numeric::printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const { - debugmsg("numeric print csrc", LOGLEVEL_PRINT); - ios::fmtflags oldflags = os.flags(); - os.setf(ios::scientific); - if (this->is_rational() && !this->is_integer()) { - if (compare(_num0()) > 0) { - os << "("; - if (type == csrc_types::ctype_cl_N) - os << "cl_F(\"" << numer().evalf() << "\")"; - else - os << numer().to_double(); - } else { - os << "-("; - if (type == csrc_types::ctype_cl_N) - os << "cl_F(\"" << -numer().evalf() << "\")"; - else - os << -numer().to_double(); - } - os << "/"; - if (type == csrc_types::ctype_cl_N) - os << "cl_F(\"" << denom().evalf() << "\")"; - else - os << denom().to_double(); - os << ")"; - } else { - if (type == csrc_types::ctype_cl_N) - os << "cl_F(\"" << evalf() << "\")"; - else - os << to_double(); - } - os.flags(oldflags); + debugmsg("numeric print csrc", LOGLEVEL_PRINT); + ios::fmtflags oldflags = os.flags(); + os.setf(ios::scientific); + if (this->is_rational() && !this->is_integer()) { + if (compare(_num0()) > 0) { + os << "("; + if (type == csrc_types::ctype_cl_N) + os << "cl_F(\"" << numer().evalf() << "\")"; + else + os << numer().to_double(); + } else { + os << "-("; + if (type == csrc_types::ctype_cl_N) + os << "cl_F(\"" << -numer().evalf() << "\")"; + else + os << -numer().to_double(); + } + os << "/"; + if (type == csrc_types::ctype_cl_N) + os << "cl_F(\"" << denom().evalf() << "\")"; + else + os << denom().to_double(); + os << ")"; + } else { + if (type == csrc_types::ctype_cl_N) + os << "cl_F(\"" << evalf() << "\")"; + else + os << to_double(); + } + os.flags(oldflags); } bool numeric::info(unsigned inf) const { - switch (inf) { - case info_flags::numeric: - case info_flags::polynomial: - case info_flags::rational_function: - return true; - case info_flags::real: - return is_real(); - case info_flags::rational: - case info_flags::rational_polynomial: - return is_rational(); - case info_flags::crational: - case info_flags::crational_polynomial: - return is_crational(); - case info_flags::integer: - case info_flags::integer_polynomial: - return is_integer(); - case info_flags::cinteger: - case info_flags::cinteger_polynomial: - return is_cinteger(); - case info_flags::positive: - return is_positive(); - case info_flags::negative: - return is_negative(); - case info_flags::nonnegative: - return !is_negative(); - case info_flags::posint: - return is_pos_integer(); - case info_flags::negint: - return is_integer() && is_negative(); - case info_flags::nonnegint: - return is_nonneg_integer(); - case info_flags::even: - return is_even(); - case info_flags::odd: - return is_odd(); - case info_flags::prime: - return is_prime(); - case info_flags::algebraic: - return !is_real(); - } - return false; + switch (inf) { + case info_flags::numeric: + case info_flags::polynomial: + case info_flags::rational_function: + return true; + case info_flags::real: + return is_real(); + case info_flags::rational: + case info_flags::rational_polynomial: + return is_rational(); + case info_flags::crational: + case info_flags::crational_polynomial: + return is_crational(); + case info_flags::integer: + case info_flags::integer_polynomial: + return is_integer(); + case info_flags::cinteger: + case info_flags::cinteger_polynomial: + return is_cinteger(); + case info_flags::positive: + return is_positive(); + case info_flags::negative: + return is_negative(); + case info_flags::nonnegative: + return !is_negative(); + case info_flags::posint: + return is_pos_integer(); + case info_flags::negint: + return is_integer() && is_negative(); + case info_flags::nonnegint: + return is_nonneg_integer(); + case info_flags::even: + return is_even(); + case info_flags::odd: + return is_odd(); + case info_flags::prime: + return is_prime(); + case info_flags::algebraic: + return !is_real(); + } + return false; } /** Disassemble real part and imaginary part to scan for the occurrence of a @@ -595,31 +595,31 @@ bool numeric::info(unsigned inf) const * sign as a multiplicative factor. */ 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)); - if (this->is_equal(o) || this->is_equal(-o)) - return true; - if (o.imag().is_zero()) // e.g. scan for 3 in -3*I - return (this->real().is_equal(o) || this->imag().is_equal(o) || - this->real().is_equal(-o) || this->imag().is_equal(-o)); - else { - if (o.is_equal(I)) // e.g scan for I in 42*I - return !this->is_real(); - if (o.real().is_zero()) // e.g. scan for 2*I in 2*I+1 - return (this->real().has(o*I) || this->imag().has(o*I) || - this->real().has(-o*I) || this->imag().has(-o*I)); - } - return false; + if (!is_exactly_of_type(*other.bp, numeric)) + return false; + 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 + return (this->real().is_equal(o) || this->imag().is_equal(o) || + this->real().is_equal(-o) || this->imag().is_equal(-o)); + else { + if (o.is_equal(I)) // e.g scan for I in 42*I + return !this->is_real(); + if (o.real().is_zero()) // e.g. scan for 2*I in 2*I+1 + return (this->real().has(o*I) || this->imag().has(o*I) || + this->real().has(-o*I) || this->imag().has(-o*I)); + } + return false; } /** Evaluation of numbers doesn't do anything at all. */ ex numeric::eval(int level) const { - // Warning: if this is ever gonna do something, the ex ctors from all kinds - // of numbers should be checking for status_flags::evaluated. - return this->hold(); + // Warning: if this is ever gonna do something, the ex ctors from all kinds + // of numbers should be checking for status_flags::evaluated. + return this->hold(); } @@ -632,8 +632,8 @@ ex numeric::eval(int level) const * @return an ex-handle to a numeric. */ ex numeric::evalf(int level) const { - // level can safely be discarded for numeric objects. - return numeric(::cl_float(1.0, ::cl_default_float_format) * (*value)); // -> CLN + // level can safely be discarded for numeric objects. + return numeric(::cl_float(1.0, ::cl_default_float_format) * (*value)); // -> CLN } // protected @@ -643,38 +643,38 @@ ex numeric::evalf(int level) const * @see ex::diff */ ex numeric::derivative(const symbol & s) const { - return _ex0(); + return _ex0(); } 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)); + GINAC_ASSERT(is_exactly_of_type(other, numeric)); + const numeric & o = static_cast(const_cast(other)); - if (*value == *o.value) { - return 0; - } + if (*value == *o.value) { + return 0; + } - return compare(o); + return compare(o); } bool numeric::is_equal_same_type(const basic & other) const { - GINAC_ASSERT(is_exactly_of_type(other,numeric)); - const numeric *o = static_cast(&other); - - return this->is_equal(*o); + GINAC_ASSERT(is_exactly_of_type(other,numeric)); + const numeric *o = static_cast(&other); + + return this->is_equal(*o); } 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. - return (hashvalue = cl_equal_hashcode(*value) | 0x80000000U); + // 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. + return (hashvalue = cl_equal_hashcode(*value) | 0x80000000U); } @@ -694,27 +694,27 @@ unsigned numeric::calchash(void) const * a new numeric object. */ numeric numeric::add(const numeric & other) const { - return numeric((*value)+(*other.value)); + return numeric((*value)+(*other.value)); } /** Numerical subtraction method. Subtracts argument from *this and returns * result as a new numeric object. */ numeric numeric::sub(const numeric & other) const { - return numeric((*value)-(*other.value)); + return numeric((*value)-(*other.value)); } /** Numerical multiplication method. Multiplies *this and argument and returns * result as a new numeric object. */ numeric numeric::mul(const numeric & other) const { - static const numeric * _num1p=&_num1(); - if (this==_num1p) { - return other; - } else if (&other==_num1p) { - return *this; - } - return numeric((*value)*(*other.value)); + static const numeric * _num1p=&_num1(); + if (this==_num1p) { + return other; + } else if (&other==_num1p) { + return *this; + } + return numeric((*value)*(*other.value)); } /** Numerical division method. Divides *this by argument and returns result as @@ -723,116 +723,116 @@ numeric numeric::mul(const numeric & other) const * @exception overflow_error (division by zero) */ numeric numeric::div(const numeric & other) const { - if (::zerop(*other.value)) - throw std::overflow_error("numeric::div(): division by zero"); - return numeric((*value)/(*other.value)); + if (::zerop(*other.value)) + throw std::overflow_error("numeric::div(): division by zero"); + return numeric((*value)/(*other.value)); } numeric numeric::power(const numeric & other) const { - static const numeric * _num1p = &_num1(); - if (&other==_num1p) - return *this; - if (::zerop(*value)) { - if (::zerop(*other.value)) - throw std::domain_error("numeric::eval(): pow(0,0) is undefined"); - else if (::zerop(::realpart(*other.value))) - throw std::domain_error("numeric::eval(): pow(0,I) is undefined"); - else if (::minusp(::realpart(*other.value))) - throw std::overflow_error("numeric::eval(): division by zero"); - else - return _num0(); - } - return numeric(::expt(*value,*other.value)); + static const numeric * _num1p = &_num1(); + if (&other==_num1p) + return *this; + if (::zerop(*value)) { + if (::zerop(*other.value)) + throw std::domain_error("numeric::eval(): pow(0,0) is undefined"); + else if (::zerop(::realpart(*other.value))) + throw std::domain_error("numeric::eval(): pow(0,I) is undefined"); + else if (::minusp(::realpart(*other.value))) + throw std::overflow_error("numeric::eval(): division by zero"); + else + return _num0(); + } + return numeric(::expt(*value,*other.value)); } /** Inverse of a number. */ numeric numeric::inverse(void) const { - if (::zerop(*value)) - throw std::overflow_error("numeric::inverse(): division by zero"); - return numeric(::recip(*value)); // -> CLN + if (::zerop(*value)) + throw std::overflow_error("numeric::inverse(): division by zero"); + return numeric(::recip(*value)); // -> CLN } const numeric & numeric::add_dyn(const numeric & other) const { - return static_cast((new numeric((*value)+(*other.value)))-> - setflag(status_flags::dynallocated)); + return static_cast((new numeric((*value)+(*other.value)))-> + setflag(status_flags::dynallocated)); } const numeric & numeric::sub_dyn(const numeric & other) const { - return static_cast((new numeric((*value)-(*other.value)))-> - setflag(status_flags::dynallocated)); + return static_cast((new numeric((*value)-(*other.value)))-> + setflag(status_flags::dynallocated)); } const numeric & numeric::mul_dyn(const numeric & other) const { - static const numeric * _num1p=&_num1(); - if (this==_num1p) { - return other; - } else if (&other==_num1p) { - return *this; - } - return static_cast((new numeric((*value)*(*other.value)))-> - setflag(status_flags::dynallocated)); + static const numeric * _num1p=&_num1(); + if (this==_num1p) { + return other; + } else if (&other==_num1p) { + return *this; + } + return static_cast((new numeric((*value)*(*other.value)))-> + setflag(status_flags::dynallocated)); } const numeric & numeric::div_dyn(const numeric & other) const { - if (::zerop(*other.value)) - throw std::overflow_error("division by zero"); - return static_cast((new numeric((*value)/(*other.value)))-> - setflag(status_flags::dynallocated)); + if (::zerop(*other.value)) + throw std::overflow_error("division by zero"); + return static_cast((new numeric((*value)/(*other.value)))-> + setflag(status_flags::dynallocated)); } const numeric & numeric::power_dyn(const numeric & other) const { - static const numeric * _num1p=&_num1(); - if (&other==_num1p) - return *this; - if (::zerop(*value)) { - if (::zerop(*other.value)) - throw std::domain_error("numeric::eval(): pow(0,0) is undefined"); - else if (::zerop(::realpart(*other.value))) - throw std::domain_error("numeric::eval(): pow(0,I) is undefined"); - else if (::minusp(::realpart(*other.value))) - throw std::overflow_error("numeric::eval(): division by zero"); - else - return _num0(); - } - return static_cast((new numeric(::expt(*value,*other.value)))-> - setflag(status_flags::dynallocated)); + static const numeric * _num1p=&_num1(); + if (&other==_num1p) + return *this; + if (::zerop(*value)) { + if (::zerop(*other.value)) + throw std::domain_error("numeric::eval(): pow(0,0) is undefined"); + else if (::zerop(::realpart(*other.value))) + throw std::domain_error("numeric::eval(): pow(0,I) is undefined"); + else if (::minusp(::realpart(*other.value))) + throw std::overflow_error("numeric::eval(): division by zero"); + else + return _num0(); + } + return static_cast((new numeric(::expt(*value,*other.value)))-> + setflag(status_flags::dynallocated)); } const numeric & numeric::operator=(int i) { - return operator=(numeric(i)); + return operator=(numeric(i)); } const numeric & numeric::operator=(unsigned int i) { - return operator=(numeric(i)); + return operator=(numeric(i)); } const numeric & numeric::operator=(long i) { - return operator=(numeric(i)); + return operator=(numeric(i)); } const numeric & numeric::operator=(unsigned long i) { - return operator=(numeric(i)); + return operator=(numeric(i)); } const numeric & numeric::operator=(double d) { - return operator=(numeric(d)); + return operator=(numeric(d)); } const numeric & numeric::operator=(const char * s) { - return operator=(numeric(s)); + return operator=(numeric(s)); } /** Return the complex half-plane (left or right) in which the number lies. @@ -842,19 +842,19 @@ const numeric & numeric::operator=(const char * s) * @see numeric::compare(const numeric & other) */ int numeric::csgn(void) const { - if (this->is_zero()) - return 0; - if (!::zerop(::realpart(*value))) { - if (::plusp(::realpart(*value))) - return 1; - else - return -1; - } else { - if (::plusp(::imagpart(*value))) - return 1; - else - return -1; - } + if (this->is_zero()) + return 0; + if (!::zerop(::realpart(*value))) { + if (::plusp(::realpart(*value))) + return 1; + else + return -1; + } else { + if (::plusp(::imagpart(*value))) + return 1; + else + return -1; + } } /** This method establishes a canonical order on all numbers. For complex @@ -866,75 +866,75 @@ int numeric::csgn(void) const * @see numeric::csgn(void) */ int numeric::compare(const numeric & other) const { - // Comparing two real numbers? - if (this->is_real() && other.is_real()) - // Yes, just compare them - return ::cl_compare(The(::cl_R)(*value), The(::cl_R)(*other.value)); - else { - // No, first compare real parts - cl_signean real_cmp = ::cl_compare(::realpart(*value), ::realpart(*other.value)); - if (real_cmp) - return real_cmp; + // Comparing two real numbers? + if (this->is_real() && other.is_real()) + // Yes, just compare them + return ::cl_compare(The(::cl_R)(*value), The(::cl_R)(*other.value)); + else { + // No, first compare real parts + cl_signean real_cmp = ::cl_compare(::realpart(*value), ::realpart(*other.value)); + if (real_cmp) + return real_cmp; - return ::cl_compare(::imagpart(*value), ::imagpart(*other.value)); - } + return ::cl_compare(::imagpart(*value), ::imagpart(*other.value)); + } } bool numeric::is_equal(const numeric & other) const { - return (*value == *other.value); + return (*value == *other.value); } /** True if object is zero. */ bool numeric::is_zero(void) const { - return ::zerop(*value); // -> CLN + return ::zerop(*value); // -> CLN } /** True if object is not complex and greater than zero. */ bool numeric::is_positive(void) const { - if (this->is_real()) - return ::plusp(The(::cl_R)(*value)); // -> CLN - return false; + if (this->is_real()) + return ::plusp(The(::cl_R)(*value)); // -> CLN + return false; } /** True if object is not complex and less than zero. */ bool numeric::is_negative(void) const { - if (this->is_real()) - return ::minusp(The(::cl_R)(*value)); // -> CLN - return false; + if (this->is_real()) + return ::minusp(The(::cl_R)(*value)); // -> CLN + return false; } /** True if object is a non-complex integer. */ bool numeric::is_integer(void) const { - return ::instanceof(*value, ::cl_I_ring); // -> CLN + return ::instanceof(*value, ::cl_I_ring); // -> CLN } /** True if object is an exact integer greater than zero. */ bool numeric::is_pos_integer(void) const { - return (this->is_integer() && ::plusp(The(::cl_I)(*value))); // -> CLN + return (this->is_integer() && ::plusp(The(::cl_I)(*value))); // -> CLN } /** True if object is an exact integer greater or equal zero. */ bool numeric::is_nonneg_integer(void) const { - return (this->is_integer() && !::minusp(The(::cl_I)(*value))); // -> CLN + return (this->is_integer() && !::minusp(The(::cl_I)(*value))); // -> CLN } /** True if object is an exact even integer. */ bool numeric::is_even(void) const { - return (this->is_integer() && ::evenp(The(::cl_I)(*value))); // -> CLN + return (this->is_integer() && ::evenp(The(::cl_I)(*value))); // -> CLN } /** True if object is an exact odd integer. */ bool numeric::is_odd(void) const { - return (this->is_integer() && ::oddp(The(::cl_I)(*value))); // -> CLN + return (this->is_integer() && ::oddp(The(::cl_I)(*value))); // -> CLN } /** Probabilistic primality test. @@ -942,58 +942,58 @@ bool numeric::is_odd(void) const * @return true if object is exact integer and prime. */ bool numeric::is_prime(void) const { - return (this->is_integer() && ::isprobprime(The(::cl_I)(*value))); // -> CLN + return (this->is_integer() && ::isprobprime(The(::cl_I)(*value))); // -> CLN } /** True if object is an exact rational number, may even be complex * (denominator may be unity). */ bool numeric::is_rational(void) const { - return ::instanceof(*value, ::cl_RA_ring); // -> CLN + return ::instanceof(*value, ::cl_RA_ring); // -> CLN } /** True if object is a real integer, rational or float (but not complex). */ bool numeric::is_real(void) const { - return ::instanceof(*value, ::cl_R_ring); // -> CLN + return ::instanceof(*value, ::cl_R_ring); // -> CLN } bool numeric::operator==(const numeric & other) const { - return (*value == *other.value); // -> CLN + return (*value == *other.value); // -> CLN } bool numeric::operator!=(const numeric & other) const { - return (*value != *other.value); // -> CLN + return (*value != *other.value); // -> CLN } /** True if object is element of the domain of integers extended by I, i.e. is * of the form a+b*I, where a and b are integers. */ bool numeric::is_cinteger(void) const { - if (::instanceof(*value, ::cl_I_ring)) - return true; - else if (!this->is_real()) { // complex case, handle n+m*I - if (::instanceof(::realpart(*value), ::cl_I_ring) && - ::instanceof(::imagpart(*value), ::cl_I_ring)) - return true; - } - return false; + if (::instanceof(*value, ::cl_I_ring)) + return true; + else if (!this->is_real()) { // complex case, handle n+m*I + if (::instanceof(::realpart(*value), ::cl_I_ring) && + ::instanceof(::imagpart(*value), ::cl_I_ring)) + return true; + } + return false; } /** True if object is an exact rational number, may even be complex * (denominator may be unity). */ bool numeric::is_crational(void) const { - if (::instanceof(*value, ::cl_RA_ring)) - return true; - else if (!this->is_real()) { // complex case, handle Q(i): - if (::instanceof(::realpart(*value), ::cl_RA_ring) && - ::instanceof(::imagpart(*value), ::cl_RA_ring)) - return true; - } - return false; + if (::instanceof(*value, ::cl_RA_ring)) + return true; + else if (!this->is_real()) { // complex case, handle Q(i): + if (::instanceof(::realpart(*value), ::cl_RA_ring) && + ::instanceof(::imagpart(*value), ::cl_RA_ring)) + return true; + } + return false; } /** Numerical comparison: less. @@ -1001,10 +1001,10 @@ bool numeric::is_crational(void) const * @exception invalid_argument (complex inequality) */ bool numeric::operator<(const numeric & other) const { - if (this->is_real() && other.is_real()) - return (The(::cl_R)(*value) < The(::cl_R)(*other.value)); // -> CLN - throw std::invalid_argument("numeric::operator<(): complex inequality"); - return false; // make compiler shut up + if (this->is_real() && other.is_real()) + return (The(::cl_R)(*value) < The(::cl_R)(*other.value)); // -> CLN + throw std::invalid_argument("numeric::operator<(): complex inequality"); + return false; // make compiler shut up } /** Numerical comparison: less or equal. @@ -1012,10 +1012,10 @@ bool numeric::operator<(const numeric & other) const * @exception invalid_argument (complex inequality) */ bool numeric::operator<=(const numeric & other) const { - if (this->is_real() && other.is_real()) - return (The(::cl_R)(*value) <= The(::cl_R)(*other.value)); // -> CLN - throw std::invalid_argument("numeric::operator<=(): complex inequality"); - return false; // make compiler shut up + if (this->is_real() && other.is_real()) + return (The(::cl_R)(*value) <= The(::cl_R)(*other.value)); // -> CLN + throw std::invalid_argument("numeric::operator<=(): complex inequality"); + return false; // make compiler shut up } /** Numerical comparison: greater. @@ -1023,10 +1023,10 @@ bool numeric::operator<=(const numeric & other) const * @exception invalid_argument (complex inequality) */ bool numeric::operator>(const numeric & other) const { - if (this->is_real() && other.is_real()) - return (The(::cl_R)(*value) > The(::cl_R)(*other.value)); // -> CLN - throw std::invalid_argument("numeric::operator>(): complex inequality"); - return false; // make compiler shut up + if (this->is_real() && other.is_real()) + return (The(::cl_R)(*value) > The(::cl_R)(*other.value)); // -> CLN + throw std::invalid_argument("numeric::operator>(): complex inequality"); + return false; // make compiler shut up } /** Numerical comparison: greater or equal. @@ -1034,10 +1034,10 @@ bool numeric::operator>(const numeric & other) const * @exception invalid_argument (complex inequality) */ bool numeric::operator>=(const numeric & other) const { - if (this->is_real() && other.is_real()) - return (The(::cl_R)(*value) >= The(::cl_R)(*other.value)); // -> CLN - throw std::invalid_argument("numeric::operator>=(): complex inequality"); - return false; // make compiler shut up + if (this->is_real() && other.is_real()) + return (The(::cl_R)(*value) >= The(::cl_R)(*other.value)); // -> CLN + throw std::invalid_argument("numeric::operator>=(): complex inequality"); + return false; // make compiler shut up } /** Converts numeric types to machine's int. You should check with @@ -1045,8 +1045,8 @@ bool numeric::operator>=(const numeric & other) const * You may also consider checking the range first. */ int numeric::to_int(void) const { - GINAC_ASSERT(this->is_integer()); - return ::cl_I_to_int(The(::cl_I)(*value)); // -> CLN + GINAC_ASSERT(this->is_integer()); + return ::cl_I_to_int(The(::cl_I)(*value)); // -> CLN } /** Converts numeric types to machine's long. You should check with @@ -1054,28 +1054,28 @@ int numeric::to_int(void) const * You may also consider checking the range first. */ long numeric::to_long(void) const { - GINAC_ASSERT(this->is_integer()); - return ::cl_I_to_long(The(::cl_I)(*value)); // -> CLN + GINAC_ASSERT(this->is_integer()); + return ::cl_I_to_long(The(::cl_I)(*value)); // -> CLN } /** Converts numeric types to machine's double. You should check with is_real() * if the number is really not complex before calling this method. */ double numeric::to_double(void) const { - GINAC_ASSERT(this->is_real()); - return ::cl_double_approx(::realpart(*value)); // -> CLN + GINAC_ASSERT(this->is_real()); + return ::cl_double_approx(::realpart(*value)); // -> CLN } /** Real part of a number. */ const numeric numeric::real(void) const { - return numeric(::realpart(*value)); // -> CLN + return numeric(::realpart(*value)); // -> CLN } /** Imaginary part of a number. */ const numeric numeric::imag(void) const { - return numeric(::imagpart(*value)); // -> CLN + return numeric(::imagpart(*value)); // -> CLN } #ifndef SANE_LINKER @@ -1083,8 +1083,8 @@ const numeric numeric::imag(void) const // or denominator of a rational number (cl_RA). Doing some excavations in CLN // one finds how it works internally in src/rational/cl_RA.h: struct cl_heap_ratio : cl_heap { - cl_I numerator; - cl_I denominator; + cl_I numerator; + cl_I denominator; }; inline cl_heap_ratio* TheRatio (const cl_N& obj) @@ -1097,50 +1097,50 @@ inline cl_heap_ratio* TheRatio (const cl_N& obj) * cases. */ const numeric numeric::numer(void) const { - if (this->is_integer()) { - return numeric(*this); - } + if (this->is_integer()) { + return numeric(*this); + } #ifdef SANE_LINKER - else if (::instanceof(*value, ::cl_RA_ring)) { - return numeric(::numerator(The(::cl_RA)(*value))); - } - else if (!this->is_real()) { // complex case, handle Q(i): - cl_R r = ::realpart(*value); - cl_R i = ::imagpart(*value); - if (::instanceof(r, ::cl_I_ring) && ::instanceof(i, ::cl_I_ring)) - return numeric(*this); - if (::instanceof(r, ::cl_I_ring) && ::instanceof(i, ::cl_RA_ring)) - return numeric(::complex(r*::denominator(The(::cl_RA)(i)), ::numerator(The(::cl_RA)(i)))); - if (::instanceof(r, ::cl_RA_ring) && ::instanceof(i, ::cl_I_ring)) - return numeric(::complex(::numerator(The(::cl_RA)(r)), i*::denominator(The(::cl_RA)(r)))); - if (::instanceof(r, ::cl_RA_ring) && ::instanceof(i, ::cl_RA_ring)) { - cl_I s = ::lcm(::denominator(The(::cl_RA)(r)), ::denominator(The(::cl_RA)(i))); - return numeric(::complex(::numerator(The(::cl_RA)(r))*(exquo(s,::denominator(The(::cl_RA)(r)))), - ::numerator(The(::cl_RA)(i))*(exquo(s,::denominator(The(::cl_RA)(i)))))); - } - } + else if (::instanceof(*value, ::cl_RA_ring)) { + return numeric(::numerator(The(::cl_RA)(*value))); + } + else if (!this->is_real()) { // complex case, handle Q(i): + cl_R r = ::realpart(*value); + cl_R i = ::imagpart(*value); + if (::instanceof(r, ::cl_I_ring) && ::instanceof(i, ::cl_I_ring)) + return numeric(*this); + if (::instanceof(r, ::cl_I_ring) && ::instanceof(i, ::cl_RA_ring)) + return numeric(::complex(r*::denominator(The(::cl_RA)(i)), ::numerator(The(::cl_RA)(i)))); + if (::instanceof(r, ::cl_RA_ring) && ::instanceof(i, ::cl_I_ring)) + return numeric(::complex(::numerator(The(::cl_RA)(r)), i*::denominator(The(::cl_RA)(r)))); + if (::instanceof(r, ::cl_RA_ring) && ::instanceof(i, ::cl_RA_ring)) { + cl_I s = ::lcm(::denominator(The(::cl_RA)(r)), ::denominator(The(::cl_RA)(i))); + return numeric(::complex(::numerator(The(::cl_RA)(r))*(exquo(s,::denominator(The(::cl_RA)(r)))), + ::numerator(The(::cl_RA)(i))*(exquo(s,::denominator(The(::cl_RA)(i)))))); + } + } #else - else if (instanceof(*value, ::cl_RA_ring)) { - return numeric(TheRatio(*value)->numerator); - } - else if (!this->is_real()) { // complex case, handle Q(i): - cl_R r = ::realpart(*value); - cl_R i = ::imagpart(*value); - if (instanceof(r, ::cl_I_ring) && instanceof(i, ::cl_I_ring)) - return numeric(*this); - if (instanceof(r, ::cl_I_ring) && instanceof(i, ::cl_RA_ring)) - return numeric(::complex(r*TheRatio(i)->denominator, TheRatio(i)->numerator)); - if (instanceof(r, ::cl_RA_ring) && instanceof(i, ::cl_I_ring)) - return numeric(::complex(TheRatio(r)->numerator, i*TheRatio(r)->denominator)); - if (instanceof(r, ::cl_RA_ring) && instanceof(i, ::cl_RA_ring)) { - cl_I s = ::lcm(TheRatio(r)->denominator, TheRatio(i)->denominator); - return numeric(::complex(TheRatio(r)->numerator*(exquo(s,TheRatio(r)->denominator)), - TheRatio(i)->numerator*(exquo(s,TheRatio(i)->denominator)))); - } - } + else if (instanceof(*value, ::cl_RA_ring)) { + return numeric(TheRatio(*value)->numerator); + } + else if (!this->is_real()) { // complex case, handle Q(i): + cl_R r = ::realpart(*value); + cl_R i = ::imagpart(*value); + if (instanceof(r, ::cl_I_ring) && instanceof(i, ::cl_I_ring)) + return numeric(*this); + if (instanceof(r, ::cl_I_ring) && instanceof(i, ::cl_RA_ring)) + return numeric(::complex(r*TheRatio(i)->denominator, TheRatio(i)->numerator)); + if (instanceof(r, ::cl_RA_ring) && instanceof(i, ::cl_I_ring)) + return numeric(::complex(TheRatio(r)->numerator, i*TheRatio(r)->denominator)); + if (instanceof(r, ::cl_RA_ring) && instanceof(i, ::cl_RA_ring)) { + cl_I s = ::lcm(TheRatio(r)->denominator, TheRatio(i)->denominator); + return numeric(::complex(TheRatio(r)->numerator*(exquo(s,TheRatio(r)->denominator)), + TheRatio(i)->numerator*(exquo(s,TheRatio(i)->denominator)))); + } + } #endif // def SANE_LINKER - // at least one float encountered - return numeric(*this); + // at least one float encountered + return numeric(*this); } /** Denominator. Computes the denominator of rational numbers, common integer @@ -1148,44 +1148,44 @@ const numeric numeric::numer(void) const * (i.e denom(4/3+5/6*I) == 6), one in all other cases. */ const numeric numeric::denom(void) const { - if (this->is_integer()) { - return _num1(); - } + if (this->is_integer()) { + return _num1(); + } #ifdef SANE_LINKER - if (instanceof(*value, ::cl_RA_ring)) { - return numeric(::denominator(The(::cl_RA)(*value))); - } - if (!this->is_real()) { // complex case, handle Q(i): - cl_R r = ::realpart(*value); - cl_R i = ::imagpart(*value); - if (::instanceof(r, ::cl_I_ring) && ::instanceof(i, ::cl_I_ring)) - return _num1(); - if (::instanceof(r, ::cl_I_ring) && ::instanceof(i, ::cl_RA_ring)) - return numeric(::denominator(The(::cl_RA)(i))); - if (::instanceof(r, ::cl_RA_ring) && ::instanceof(i, ::cl_I_ring)) - return numeric(::denominator(The(::cl_RA)(r))); - if (::instanceof(r, ::cl_RA_ring) && ::instanceof(i, ::cl_RA_ring)) - return numeric(::lcm(::denominator(The(::cl_RA)(r)), ::denominator(The(::cl_RA)(i)))); - } + if (instanceof(*value, ::cl_RA_ring)) { + return numeric(::denominator(The(::cl_RA)(*value))); + } + if (!this->is_real()) { // complex case, handle Q(i): + cl_R r = ::realpart(*value); + cl_R i = ::imagpart(*value); + if (::instanceof(r, ::cl_I_ring) && ::instanceof(i, ::cl_I_ring)) + return _num1(); + if (::instanceof(r, ::cl_I_ring) && ::instanceof(i, ::cl_RA_ring)) + return numeric(::denominator(The(::cl_RA)(i))); + if (::instanceof(r, ::cl_RA_ring) && ::instanceof(i, ::cl_I_ring)) + return numeric(::denominator(The(::cl_RA)(r))); + if (::instanceof(r, ::cl_RA_ring) && ::instanceof(i, ::cl_RA_ring)) + return numeric(::lcm(::denominator(The(::cl_RA)(r)), ::denominator(The(::cl_RA)(i)))); + } #else - if (instanceof(*value, ::cl_RA_ring)) { - return numeric(TheRatio(*value)->denominator); - } - if (!this->is_real()) { // complex case, handle Q(i): - cl_R r = ::realpart(*value); - cl_R i = ::imagpart(*value); - if (instanceof(r, ::cl_I_ring) && instanceof(i, ::cl_I_ring)) - return _num1(); - if (instanceof(r, ::cl_I_ring) && instanceof(i, ::cl_RA_ring)) - return numeric(TheRatio(i)->denominator); - if (instanceof(r, ::cl_RA_ring) && instanceof(i, ::cl_I_ring)) - return numeric(TheRatio(r)->denominator); - if (instanceof(r, ::cl_RA_ring) && instanceof(i, ::cl_RA_ring)) - return numeric(::lcm(TheRatio(r)->denominator, TheRatio(i)->denominator)); - } + if (instanceof(*value, ::cl_RA_ring)) { + return numeric(TheRatio(*value)->denominator); + } + if (!this->is_real()) { // complex case, handle Q(i): + cl_R r = ::realpart(*value); + cl_R i = ::imagpart(*value); + if (instanceof(r, ::cl_I_ring) && instanceof(i, ::cl_I_ring)) + return _num1(); + if (instanceof(r, ::cl_I_ring) && instanceof(i, ::cl_RA_ring)) + return numeric(TheRatio(i)->denominator); + if (instanceof(r, ::cl_RA_ring) && instanceof(i, ::cl_I_ring)) + return numeric(TheRatio(r)->denominator); + if (instanceof(r, ::cl_RA_ring) && instanceof(i, ::cl_RA_ring)) + return numeric(::lcm(TheRatio(r)->denominator, TheRatio(i)->denominator)); + } #endif // def SANE_LINKER - // at least one float encountered - return _num1(); + // at least one float encountered + return _num1(); } /** Size in binary notation. For integers, this is the smallest n >= 0 such @@ -1196,10 +1196,10 @@ const numeric numeric::denom(void) const * in two's complement if it is an integer, 0 otherwise. */ int numeric::int_length(void) const { - if (this->is_integer()) - return ::integer_length(The(::cl_I)(*value)); // -> CLN - else - return 0; + if (this->is_integer()) + return ::integer_length(The(::cl_I)(*value)); // -> CLN + else + return 0; } @@ -1227,7 +1227,7 @@ const numeric I = numeric(::complex(cl_I(0),cl_I(1))); * @return arbitrary precision numerical exp(x). */ const numeric exp(const numeric & x) { - return ::exp(*x.value); // -> CLN + return ::exp(*x.value); // -> CLN } @@ -1238,9 +1238,9 @@ const numeric exp(const numeric & x) * @exception pole_error("log(): logarithmic pole",0) */ const numeric log(const numeric & z) { - if (z.is_zero()) - throw pole_error("log(): logarithmic pole",0); - return ::log(*z.value); // -> CLN + if (z.is_zero()) + throw pole_error("log(): logarithmic pole",0); + return ::log(*z.value); // -> CLN } @@ -1249,7 +1249,7 @@ const numeric log(const numeric & z) * @return arbitrary precision numerical sin(x). */ const numeric sin(const numeric & x) { - return ::sin(*x.value); // -> CLN + return ::sin(*x.value); // -> CLN } @@ -1258,7 +1258,7 @@ const numeric sin(const numeric & x) * @return arbitrary precision numerical cos(x). */ const numeric cos(const numeric & x) { - return ::cos(*x.value); // -> CLN + return ::cos(*x.value); // -> CLN } @@ -1267,16 +1267,16 @@ const numeric cos(const numeric & x) * @return arbitrary precision numerical tan(x). */ const numeric tan(const numeric & x) { - return ::tan(*x.value); // -> CLN + return ::tan(*x.value); // -> CLN } - + /** Numeric inverse sine (trigonometric function). * * @return arbitrary precision numerical asin(x). */ const numeric asin(const numeric & x) { - return ::asin(*x.value); // -> CLN + return ::asin(*x.value); // -> CLN } @@ -1285,9 +1285,9 @@ const numeric asin(const numeric & x) * @return arbitrary precision numerical acos(x). */ const numeric acos(const numeric & x) { - return ::acos(*x.value); // -> CLN + return ::acos(*x.value); // -> CLN } - + /** Arcustangent. * @@ -1296,11 +1296,11 @@ const numeric acos(const numeric & x) * @exception pole_error("atan(): logarithmic pole",0) */ const numeric atan(const numeric & x) { - if (!x.is_real() && - x.real().is_zero() && - abs(x.imag()).is_equal(_num1())) - throw pole_error("atan(): logarithmic pole",0); - return ::atan(*x.value); // -> CLN + if (!x.is_real() && + x.real().is_zero() && + abs(x.imag()).is_equal(_num1())) + throw pole_error("atan(): logarithmic pole",0); + return ::atan(*x.value); // -> CLN } @@ -1311,10 +1311,10 @@ const numeric atan(const numeric & x) * @return atan(y/x) */ const numeric atan(const numeric & y, const numeric & x) { - if (x.is_real() && y.is_real()) - return ::atan(::realpart(*x.value), ::realpart(*y.value)); // -> CLN - else - throw std::invalid_argument("atan(): complex argument"); + if (x.is_real() && y.is_real()) + return ::atan(::realpart(*x.value), ::realpart(*y.value)); // -> CLN + else + throw std::invalid_argument("atan(): complex argument"); } @@ -1323,7 +1323,7 @@ const numeric atan(const numeric & y, const numeric & x) * @return arbitrary precision numerical sinh(x). */ const numeric sinh(const numeric & x) { - return ::sinh(*x.value); // -> CLN + return ::sinh(*x.value); // -> CLN } @@ -1332,7 +1332,7 @@ const numeric sinh(const numeric & x) * @return arbitrary precision numerical cosh(x). */ const numeric cosh(const numeric & x) { - return ::cosh(*x.value); // -> CLN + return ::cosh(*x.value); // -> CLN } @@ -1341,16 +1341,16 @@ const numeric cosh(const numeric & x) * @return arbitrary precision numerical tanh(x). */ const numeric tanh(const numeric & x) { - return ::tanh(*x.value); // -> CLN + return ::tanh(*x.value); // -> CLN } - + /** Numeric inverse hyperbolic sine (trigonometric function). * * @return arbitrary precision numerical asinh(x). */ const numeric asinh(const numeric & x) { - return ::asinh(*x.value); // -> CLN + return ::asinh(*x.value); // -> CLN } @@ -1359,7 +1359,7 @@ const numeric asinh(const numeric & x) * @return arbitrary precision numerical acosh(x). */ const numeric acosh(const numeric & x) { - return ::acosh(*x.value); // -> CLN + return ::acosh(*x.value); // -> CLN } @@ -1368,76 +1368,76 @@ const numeric acosh(const numeric & x) * @return arbitrary precision numerical atanh(x). */ const numeric atanh(const numeric & x) { - return ::atanh(*x.value); // -> CLN + return ::atanh(*x.value); // -> CLN } /*static ::cl_N Li2_series(const ::cl_N & x, - const ::cl_float_format_t & prec) -{ - // Note: argument must be in the unit circle - // This is very inefficient unless we have fast floating point Bernoulli - // numbers implemented! - ::cl_N c1 = -::log(1-x); - ::cl_N c2 = c1; - // hard-wire the first two Bernoulli numbers - ::cl_N acc = c1 - ::square(c1)/4; - ::cl_N aug; - ::cl_F pisq = ::square(::cl_pi(prec)); // pi^2 - ::cl_F piac = ::cl_float(1, prec); // accumulator: pi^(2*i) - unsigned i = 1; - c1 = ::square(c1); - do { - c2 = c1 * c2; - piac = piac * pisq; - aug = c2 * (*(bernoulli(numeric(2*i)).clnptr())) / ::factorial(2*i+1); - // aug = c2 * ::cl_I(i%2 ? 1 : -1) / ::cl_I(2*i+1) * ::cl_zeta(2*i, prec) / piac / (::cl_I(1)<<(2*i-1)); - acc = acc + aug; - ++i; - } while (acc != acc+aug); - return acc; + const ::cl_float_format_t & prec) +{ + // Note: argument must be in the unit circle + // This is very inefficient unless we have fast floating point Bernoulli + // numbers implemented! + ::cl_N c1 = -::log(1-x); + ::cl_N c2 = c1; + // hard-wire the first two Bernoulli numbers + ::cl_N acc = c1 - ::square(c1)/4; + ::cl_N aug; + ::cl_F pisq = ::square(::cl_pi(prec)); // pi^2 + ::cl_F piac = ::cl_float(1, prec); // accumulator: pi^(2*i) + unsigned i = 1; + c1 = ::square(c1); + do { + c2 = c1 * c2; + piac = piac * pisq; + aug = c2 * (*(bernoulli(numeric(2*i)).clnptr())) / ::factorial(2*i+1); + // aug = c2 * ::cl_I(i%2 ? 1 : -1) / ::cl_I(2*i+1) * ::cl_zeta(2*i, prec) / piac / (::cl_I(1)<<(2*i-1)); + acc = acc + aug; + ++i; + } while (acc != acc+aug); + return acc; }*/ /** Numeric evaluation of Dilogarithm within circle of convergence (unit * circle) using a power series. */ static ::cl_N Li2_series(const ::cl_N & x, - const ::cl_float_format_t & prec) -{ - // Note: argument must be in the unit circle - ::cl_N aug, acc; - ::cl_N num = ::complex(::cl_float(1, prec), 0); - ::cl_I den = 0; - unsigned i = 1; - do { - num = num * x; - den = den + i; // 1, 4, 9, 16, ... - i += 2; - aug = num / den; - acc = acc + aug; - } while (acc != acc+aug); - return acc; + const ::cl_float_format_t & prec) +{ + // Note: argument must be in the unit circle + ::cl_N aug, acc; + ::cl_N num = ::complex(::cl_float(1, prec), 0); + ::cl_I den = 0; + unsigned i = 1; + do { + num = num * x; + den = den + i; // 1, 4, 9, 16, ... + i += 2; + aug = num / den; + acc = acc + aug; + } while (acc != acc+aug); + return acc; } /** Folds Li2's argument inside a small rectangle to enhance convergence. */ static ::cl_N Li2_projection(const ::cl_N & x, - const ::cl_float_format_t & prec) -{ - const ::cl_R re = ::realpart(x); - const ::cl_R im = ::imagpart(x); - if (re > ::cl_F(".5")) - // zeta(2) - Li2(1-x) - log(x)*log(1-x) - return(::cl_zeta(2) - - Li2_series(1-x, prec) - - ::log(x)*::log(1-x)); - if ((re <= 0 && ::abs(im) > ::cl_F(".75")) || (re < ::cl_F("-.5"))) - // -log(1-x)^2 / 2 - Li2(x/(x-1)) - return(-::square(::log(1-x))/2 - - Li2_series(x/(x-1), prec)); - if (re > 0 && ::abs(im) > ::cl_LF(".75")) - // Li2(x^2)/2 - Li2(-x) - return(Li2_projection(::square(x), prec)/2 - - Li2_projection(-x, prec)); - return Li2_series(x, prec); + const ::cl_float_format_t & prec) +{ + const ::cl_R re = ::realpart(x); + const ::cl_R im = ::imagpart(x); + if (re > ::cl_F(".5")) + // zeta(2) - Li2(1-x) - log(x)*log(1-x) + return(::cl_zeta(2) + - Li2_series(1-x, prec) + - ::log(x)*::log(1-x)); + if ((re <= 0 && ::abs(im) > ::cl_F(".75")) || (re < ::cl_F("-.5"))) + // -log(1-x)^2 / 2 - Li2(x/(x-1)) + return(-::square(::log(1-x))/2 + - Li2_series(x/(x-1), prec)); + if (re > 0 && ::abs(im) > ::cl_LF(".75")) + // Li2(x^2)/2 - Li2(-x) + return(Li2_projection(::square(x), prec)/2 + - Li2_projection(-x, prec)); + return Li2_series(x, prec); } /** Numeric evaluation of Dilogarithm. The domain is the entire complex plane, @@ -1447,28 +1447,28 @@ static ::cl_N Li2_projection(const ::cl_N & x, * @return arbitrary precision numerical Li2(x). */ const numeric Li2(const numeric & x) { - if (::zerop(*x.value)) - return x; - - // what is the desired float format? - // first guess: default format - ::cl_float_format_t prec = ::cl_default_float_format; - // second guess: the argument's format - if (!::instanceof(::realpart(*x.value),cl_RA_ring)) - prec = ::cl_float_format(The(::cl_F)(::realpart(*x.value))); - else if (!::instanceof(::imagpart(*x.value),cl_RA_ring)) - prec = ::cl_float_format(The(::cl_F)(::imagpart(*x.value))); - - if (*x.value==1) // may cause trouble with log(1-x) - return ::cl_zeta(2, prec); - - if (::abs(*x.value) > 1) - // -log(-x)^2 / 2 - zeta(2) - Li2(1/x) - return(-::square(::log(-*x.value))/2 - - ::cl_zeta(2, prec) - - Li2_projection(::recip(*x.value), prec)); - else - return Li2_projection(*x.value, prec); + if (::zerop(*x.value)) + return x; + + // what is the desired float format? + // first guess: default format + ::cl_float_format_t prec = ::cl_default_float_format; + // second guess: the argument's format + if (!::instanceof(::realpart(*x.value),cl_RA_ring)) + prec = ::cl_float_format(The(::cl_F)(::realpart(*x.value))); + else if (!::instanceof(::imagpart(*x.value),cl_RA_ring)) + prec = ::cl_float_format(The(::cl_F)(::imagpart(*x.value))); + + if (*x.value==1) // may cause trouble with log(1-x) + return ::cl_zeta(2, prec); + + if (::abs(*x.value) > 1) + // -log(-x)^2 / 2 - zeta(2) - Li2(1/x) + return(-::square(::log(-*x.value))/2 + - ::cl_zeta(2, prec) + - Li2_projection(::recip(*x.value), prec)); + else + return Li2_projection(*x.value, prec); } @@ -1476,20 +1476,20 @@ const numeric Li2(const numeric & x) * integer arguments. */ 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 - // cascades down to zeta(3.0).evalf(). The trick is to rely on 3.0-3 - // being an exact zero for CLN, which can be tested and then we can just - // pass the number casted to an int: - if (x.is_real()) { - int aux = (int)(::cl_double_approx(::realpart(*x.value))); - if (::zerop(*x.value-aux)) - return ::cl_zeta(aux); // -> CLN - } - std::clog << "zeta(" << x - << "): Does anybody know good way to calculate this numerically?" - << std::endl; - return numeric(0); + // A dirty hack to allow for things like zeta(3.0), since CLN currently + // only knows about integer arguments and zeta(3).evalf() automatically + // cascades down to zeta(3.0).evalf(). The trick is to rely on 3.0-3 + // being an exact zero for CLN, which can be tested and then we can just + // pass the number casted to an int: + if (x.is_real()) { + int aux = (int)(::cl_double_approx(::realpart(*x.value))); + if (::zerop(*x.value-aux)) + return ::cl_zeta(aux); // -> CLN + } + std::clog << "zeta(" << x + << "): Does anybody know good way to calculate this numerically?" + << std::endl; + return numeric(0); } @@ -1497,17 +1497,17 @@ const numeric zeta(const numeric & x) * This is only a stub! */ const numeric lgamma(const numeric & x) { - std::clog << "lgamma(" << x - << "): Does anybody know good way to calculate this numerically?" - << std::endl; - return numeric(0); + std::clog << "lgamma(" << x + << "): Does anybody know good way to calculate this numerically?" + << std::endl; + return numeric(0); } const numeric tgamma(const numeric & x) { - std::clog << "tgamma(" << x - << "): Does anybody know good way to calculate this numerically?" - << std::endl; - return numeric(0); + std::clog << "tgamma(" << x + << "): Does anybody know good way to calculate this numerically?" + << std::endl; + return numeric(0); } @@ -1515,10 +1515,10 @@ const numeric tgamma(const numeric & x) * This is only a stub! */ const numeric psi(const numeric & x) { - std::clog << "psi(" << x - << "): Does anybody know good way to calculate this numerically?" - << std::endl; - return numeric(0); + std::clog << "psi(" << x + << "): Does anybody know good way to calculate this numerically?" + << std::endl; + return numeric(0); } @@ -1526,10 +1526,10 @@ const numeric psi(const numeric & x) * This is only a stub! */ const numeric psi(const numeric & n, const numeric & x) { - std::clog << "psi(" << n << "," << x - << "): Does anybody know good way to calculate this numerically?" - << std::endl; - return numeric(0); + std::clog << "psi(" << n << "," << x + << "): Does anybody know good way to calculate this numerically?" + << std::endl; + return numeric(0); } @@ -1539,9 +1539,9 @@ const numeric psi(const numeric & n, const numeric & x) * @exception range_error (argument must be integer >= 0) */ const numeric factorial(const numeric & n) { - if (!n.is_nonneg_integer()) - throw std::range_error("numeric::factorial(): argument must be integer >= 0"); - return numeric(::factorial(n.to_int())); // -> CLN + if (!n.is_nonneg_integer()) + throw std::range_error("numeric::factorial(): argument must be integer >= 0"); + return numeric(::factorial(n.to_int())); // -> CLN } @@ -1553,13 +1553,13 @@ const numeric factorial(const numeric & n) * @exception range_error (argument must be integer >= -1) */ const numeric doublefactorial(const numeric & n) { - if (n == numeric(-1)) { - return _num1(); - } - if (!n.is_nonneg_integer()) { - throw std::range_error("numeric::doublefactorial(): argument must be integer >= -1"); - } - return numeric(::doublefactorial(n.to_int())); // -> CLN + if (n == numeric(-1)) { + return _num1(); + } + if (!n.is_nonneg_integer()) { + throw std::range_error("numeric::doublefactorial(): argument must be integer >= -1"); + } + return numeric(::doublefactorial(n.to_int())); // -> CLN } @@ -1569,19 +1569,19 @@ const numeric doublefactorial(const numeric & n) * 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) { - if (n.is_integer() && k.is_integer()) { - if (n.is_nonneg_integer()) { - if (k.compare(n)!=1 && k.compare(_num0())!=-1) - return numeric(::binomial(n.to_int(),k.to_int())); // -> CLN - else - return _num0(); - } else { - return _num_1().power(k)*binomial(k-n-_num1(),k); - } - } - - // should really be gamma(n+1)/gamma(r+1)/gamma(n-r+1) or a suitable limit - throw std::range_error("numeric::binomial(): don´t know how to evaluate that."); + if (n.is_integer() && k.is_integer()) { + if (n.is_nonneg_integer()) { + if (k.compare(n)!=1 && k.compare(_num0())!=-1) + return numeric(::binomial(n.to_int(),k.to_int())); // -> CLN + else + return _num0(); + } else { + return _num_1().power(k)*binomial(k-n-_num1(),k); + } + } + + // should really be gamma(n+1)/gamma(r+1)/gamma(n-r+1) or a suitable limit + throw std::range_error("numeric::binomial(): don´t know how to evaluate that."); } @@ -1592,72 +1592,72 @@ const numeric binomial(const numeric & n, const numeric & k) * @exception range_error (argument must be integer >= 0) */ const numeric bernoulli(const numeric & nn) { - if (!nn.is_integer() || nn.is_negative()) - throw std::range_error("numeric::bernoulli(): argument must be integer >= 0"); - - // Method: - // - // The Bernoulli numbers are rational numbers that may be computed using - // the relation - // - // B_n = - 1/(n+1) * sum_{k=0}^{n-1}(binomial(n+1,k)*B_k) - // - // with B(0) = 1. Since the n'th Bernoulli number depends on all the - // previous ones, the computation is necessarily very expensive. There are - // several other ways of computing them, a particularly good one being - // cl_I s = 1; - // cl_I c = n+1; - // cl_RA Bern = 0; - // for (unsigned i=0; i results; - static int highest_result = 0; - // algorithm not applicable to B(0), so just store it - if (results.size()==0) - results.push_back(::cl_RA(1)); - - int n = nn.to_long(); - for (int i=highest_result; i0; --j) { - B = ::cl_I(n*m) * (B+results[j]) / (d1*d2); - n += 4; - m += 2; - d1 -= 1; - d2 -= 2; - } - B = (1 - ((B+1)/(2*i+3))) / (::cl_I(1)<<(2*i+2)); - results.push_back(B); - ++highest_result; - } - return results[n/2]; + if (!nn.is_integer() || nn.is_negative()) + throw std::range_error("numeric::bernoulli(): argument must be integer >= 0"); + + // Method: + // + // The Bernoulli numbers are rational numbers that may be computed using + // the relation + // + // B_n = - 1/(n+1) * sum_{k=0}^{n-1}(binomial(n+1,k)*B_k) + // + // with B(0) = 1. Since the n'th Bernoulli number depends on all the + // previous ones, the computation is necessarily very expensive. There are + // several other ways of computing them, a particularly good one being + // cl_I s = 1; + // cl_I c = n+1; + // cl_RA Bern = 0; + // for (unsigned i=0; i results; + static int highest_result = 0; + // algorithm not applicable to B(0), so just store it + if (results.size()==0) + results.push_back(::cl_RA(1)); + + int n = nn.to_long(); + for (int i=highest_result; i0; --j) { + B = ::cl_I(n*m) * (B+results[j]) / (d1*d2); + n += 4; + m += 2; + d1 -= 1; + d2 -= 2; + } + B = (1 - ((B+1)/(2*i+3))) / (::cl_I(1)<<(2*i+2)); + results.push_back(B); + ++highest_result; + } + return results[n/2]; } @@ -1669,65 +1669,65 @@ const numeric bernoulli(const numeric & nn) * @exception range_error (argument must be an integer) */ const numeric fibonacci(const numeric & n) { - if (!n.is_integer()) - throw std::range_error("numeric::fibonacci(): argument must be integer"); - // Method: - // - // This is based on an implementation that can be found in CLN's example - // directory. There, it is done recursively, which may be more elegant - // than our non-recursive implementation that has to resort to some bit- - // fiddling. This is, however, a matter of taste. - // The following addition formula holds: - // - // F(n+m) = F(m-1)*F(n) + F(m)*F(n+1) for m >= 1, n >= 0. - // - // (Proof: For fixed m, the LHS and the RHS satisfy the same recurrence - // w.r.t. n, and the initial values (n=0, n=1) agree. Hence all values - // agree.) - // Replace m by m+1: - // F(n+m+1) = F(m)*F(n) + F(m+1)*F(n+1) for m >= 0, n >= 0 - // Now put in m = n, to get - // F(2n) = (F(n+1)-F(n))*F(n) + F(n)*F(n+1) = F(n)*(2*F(n+1) - F(n)) - // F(2n+1) = F(n)^2 + F(n+1)^2 - // hence - // F(2n+2) = F(n+1)*(2*F(n) + F(n+1)) - if (n.is_zero()) - return _num0(); - if (n.is_negative()) - if (n.is_even()) - return -fibonacci(-n); - else - return fibonacci(-n); - - ::cl_I u(0); - ::cl_I v(1); - ::cl_I m = The(::cl_I)(*n.value) >> 1L; // floor(n/2); - for (uintL bit=::integer_length(m); bit>0; --bit) { - // Since a squaring is cheaper than a multiplication, better use - // three squarings instead of one multiplication and two squarings. - ::cl_I u2 = ::square(u); - ::cl_I v2 = ::square(v); - if (::logbitp(bit-1, m)) { - v = ::square(u + v) - u2; - u = u2 + v2; - } else { - u = v2 - ::square(v - u); - v = u2 + v2; - } - } - if (n.is_even()) - // Here we don't use the squaring formula because one multiplication - // is cheaper than two squarings. - return u * ((v << 1) - u); - else - return ::square(u) + ::square(v); + if (!n.is_integer()) + throw std::range_error("numeric::fibonacci(): argument must be integer"); + // Method: + // + // This is based on an implementation that can be found in CLN's example + // directory. There, it is done recursively, which may be more elegant + // than our non-recursive implementation that has to resort to some bit- + // fiddling. This is, however, a matter of taste. + // The following addition formula holds: + // + // F(n+m) = F(m-1)*F(n) + F(m)*F(n+1) for m >= 1, n >= 0. + // + // (Proof: For fixed m, the LHS and the RHS satisfy the same recurrence + // w.r.t. n, and the initial values (n=0, n=1) agree. Hence all values + // agree.) + // Replace m by m+1: + // F(n+m+1) = F(m)*F(n) + F(m+1)*F(n+1) for m >= 0, n >= 0 + // Now put in m = n, to get + // F(2n) = (F(n+1)-F(n))*F(n) + F(n)*F(n+1) = F(n)*(2*F(n+1) - F(n)) + // F(2n+1) = F(n)^2 + F(n+1)^2 + // hence + // F(2n+2) = F(n+1)*(2*F(n) + F(n+1)) + if (n.is_zero()) + return _num0(); + if (n.is_negative()) + if (n.is_even()) + return -fibonacci(-n); + else + return fibonacci(-n); + + ::cl_I u(0); + ::cl_I v(1); + ::cl_I m = The(::cl_I)(*n.value) >> 1L; // floor(n/2); + for (uintL bit=::integer_length(m); bit>0; --bit) { + // Since a squaring is cheaper than a multiplication, better use + // three squarings instead of one multiplication and two squarings. + ::cl_I u2 = ::square(u); + ::cl_I v2 = ::square(v); + if (::logbitp(bit-1, m)) { + v = ::square(u + v) - u2; + u = u2 + v2; + } else { + u = v2 - ::square(v - u); + v = u2 + v2; + } + } + if (n.is_even()) + // Here we don't use the squaring formula because one multiplication + // is cheaper than two squarings. + return u * ((v << 1) - u); + else + return ::square(u) + ::square(v); } /** Absolute value. */ numeric abs(const numeric & x) { - return ::abs(*x.value); // -> CLN + return ::abs(*x.value); // -> CLN } @@ -1740,10 +1740,10 @@ numeric abs(const numeric & x) * integer, 0 otherwise. */ numeric mod(const numeric & a, const numeric & b) { - if (a.is_integer() && b.is_integer()) - return ::mod(The(::cl_I)(*a.value), The(::cl_I)(*b.value)); // -> CLN - else - return _num0(); // Throw? + if (a.is_integer() && b.is_integer()) + return ::mod(The(::cl_I)(*a.value), The(::cl_I)(*b.value)); // -> CLN + else + return _num0(); // Throw? } @@ -1753,11 +1753,11 @@ numeric mod(const numeric & a, const numeric & b) * @return a mod b in the range [-iquo(abs(m)-1,2), iquo(abs(m),2)]. */ numeric smod(const numeric & a, const numeric & b) { - if (a.is_integer() && b.is_integer()) { - cl_I b2 = The(::cl_I)(ceiling1(The(::cl_I)(*b.value) / 2)) - 1; - return ::mod(The(::cl_I)(*a.value) + b2, The(::cl_I)(*b.value)) - b2; - } else - return _num0(); // Throw? + if (a.is_integer() && b.is_integer()) { + cl_I b2 = The(::cl_I)(ceiling1(The(::cl_I)(*b.value) / 2)) - 1; + return ::mod(The(::cl_I)(*a.value) + b2, The(::cl_I)(*b.value)) - b2; + } else + return _num0(); // Throw? } @@ -1769,10 +1769,10 @@ numeric smod(const numeric & a, const numeric & b) * @return remainder of a/b if both are integer, 0 otherwise. */ numeric irem(const numeric & a, const numeric & b) { - if (a.is_integer() && b.is_integer()) - return ::rem(The(::cl_I)(*a.value), The(::cl_I)(*b.value)); // -> CLN - else - return _num0(); // Throw? + if (a.is_integer() && b.is_integer()) + return ::rem(The(::cl_I)(*a.value), The(::cl_I)(*b.value)); // -> CLN + else + return _num0(); // Throw? } @@ -1785,15 +1785,15 @@ numeric irem(const numeric & a, const numeric & b) * 0 otherwise. */ numeric irem(const numeric & a, const numeric & b, numeric & q) { - if (a.is_integer() && b.is_integer()) { // -> CLN - cl_I_div_t rem_quo = truncate2(The(::cl_I)(*a.value), The(::cl_I)(*b.value)); - q = rem_quo.quotient; - return rem_quo.remainder; - } - else { - q = _num0(); - return _num0(); // Throw? - } + if (a.is_integer() && b.is_integer()) { // -> CLN + cl_I_div_t rem_quo = truncate2(The(::cl_I)(*a.value), The(::cl_I)(*b.value)); + q = rem_quo.quotient; + return rem_quo.remainder; + } + else { + q = _num0(); + return _num0(); // Throw? + } } @@ -1803,10 +1803,10 @@ numeric irem(const numeric & a, const numeric & b, numeric & q) * @return truncated quotient of a/b if both are integer, 0 otherwise. */ numeric iquo(const numeric & a, const numeric & b) { - if (a.is_integer() && b.is_integer()) - return truncate1(The(::cl_I)(*a.value), The(::cl_I)(*b.value)); // -> CLN - else - return _num0(); // Throw? + if (a.is_integer() && b.is_integer()) + return truncate1(The(::cl_I)(*a.value), The(::cl_I)(*b.value)); // -> CLN + else + return _num0(); // Throw? } @@ -1818,14 +1818,14 @@ numeric iquo(const numeric & a, const numeric & b) * integer, 0 otherwise. */ numeric iquo(const numeric & a, const numeric & b, numeric & r) { - if (a.is_integer() && b.is_integer()) { // -> CLN - cl_I_div_t rem_quo = truncate2(The(::cl_I)(*a.value), The(::cl_I)(*b.value)); - r = rem_quo.remainder; - return rem_quo.quotient; - } else { - r = _num0(); - return _num0(); // Throw? - } + if (a.is_integer() && b.is_integer()) { // -> CLN + cl_I_div_t rem_quo = truncate2(The(::cl_I)(*a.value), The(::cl_I)(*b.value)); + r = rem_quo.remainder; + return rem_quo.quotient; + } else { + r = _num0(); + return _num0(); // Throw? + } } @@ -1839,19 +1839,19 @@ numeric iquo(const numeric & a, const numeric & b, numeric & r) * where imag(z)>0. */ numeric sqrt(const numeric & z) { - return ::sqrt(*z.value); // -> CLN + return ::sqrt(*z.value); // -> CLN } /** Integer numeric square root. */ numeric isqrt(const numeric & x) { - if (x.is_integer()) { - cl_I root; - ::isqrt(The(::cl_I)(*x.value), &root); // -> CLN - return root; - } else - return _num0(); // Throw? + if (x.is_integer()) { + cl_I root; + ::isqrt(The(::cl_I)(*x.value), &root); // -> CLN + return root; + } else + return _num0(); // Throw? } @@ -1861,10 +1861,10 @@ numeric isqrt(const numeric & x) * if they are not. */ numeric gcd(const numeric & a, const numeric & b) { - if (a.is_integer() && b.is_integer()) - return ::gcd(The(::cl_I)(*a.value), The(::cl_I)(*b.value)); // -> CLN - else - return _num1(); + if (a.is_integer() && b.is_integer()) + return ::gcd(The(::cl_I)(*a.value), The(::cl_I)(*b.value)); // -> CLN + else + return _num1(); } @@ -1874,31 +1874,31 @@ numeric gcd(const numeric & a, const numeric & b) * two numbers if they are not. */ numeric lcm(const numeric & a, const numeric & b) { - if (a.is_integer() && b.is_integer()) - return ::lcm(The(::cl_I)(*a.value), The(::cl_I)(*b.value)); // -> CLN - else - return *a.value * *b.value; + if (a.is_integer() && b.is_integer()) + return ::lcm(The(::cl_I)(*a.value), The(::cl_I)(*b.value)); // -> CLN + else + return *a.value * *b.value; } /** Floating point evaluation of Archimedes' constant Pi. */ ex PiEvalf(void) { - return numeric(::cl_pi(cl_default_float_format)); // -> CLN + return numeric(::cl_pi(cl_default_float_format)); // -> CLN } /** Floating point evaluation of Euler's constant gamma. */ ex EulerEvalf(void) { - return numeric(::cl_eulerconst(cl_default_float_format)); // -> CLN + return numeric(::cl_eulerconst(cl_default_float_format)); // -> CLN } /** Floating point evaluation of Catalan's constant. */ ex CatalanEvalf(void) { - return numeric(::cl_catalanconst(cl_default_float_format)); // -> CLN + return numeric(::cl_catalanconst(cl_default_float_format)); // -> CLN } @@ -1906,39 +1906,39 @@ ex CatalanEvalf(void) // be 61 (<64) while cl_float_format(18)=65. We want to have a cl_LF instead // of cl_SF, cl_FF or cl_DF but everything else is basically arbitrary. _numeric_digits::_numeric_digits() - : digits(17) + : digits(17) { - assert(!too_late); - too_late = true; - cl_default_float_format = ::cl_float_format(17); + assert(!too_late); + too_late = true; + cl_default_float_format = ::cl_float_format(17); } _numeric_digits& _numeric_digits::operator=(long prec) { - digits=prec; - cl_default_float_format = ::cl_float_format(prec); - return *this; + digits=prec; + cl_default_float_format = ::cl_float_format(prec); + return *this; } _numeric_digits::operator long() { - return (long)digits; + return (long)digits; } void _numeric_digits::print(std::ostream & os) const { - debugmsg("_numeric_digits print", LOGLEVEL_PRINT); - os << digits; + debugmsg("_numeric_digits print", LOGLEVEL_PRINT); + os << digits; } std::ostream& operator<<(std::ostream& os, const _numeric_digits & e) { - e.print(os); - return os; + e.print(os); + return os; } ////////// diff --git a/ginac/numeric.h b/ginac/numeric.h index c5086f43..b579a3be 100644 --- a/ginac/numeric.h +++ b/ginac/numeric.h @@ -28,7 +28,7 @@ #include "ex.h" class cl_N; // We want to include cln.h only in numeric.cpp in order to - // avoid namespace pollution and keep compile-time low. + // avoid namespace pollution and keep compile-time low. #ifndef NO_NAMESPACE_GINAC namespace GiNaC { @@ -49,158 +49,158 @@ class _numeric_digits { // member functions public: - _numeric_digits(); - _numeric_digits& operator=(long prec); - operator long(); - void print(std::ostream & os) const; + _numeric_digits(); + _numeric_digits& operator=(long prec); + operator long(); + void print(std::ostream & os) const; // member variables private: - long digits; - static bool too_late; + long digits; + static bool too_late; }; /** This class is a wrapper around CLN-numbers within the GiNaC class * hierarchy. Objects of this type may directly be created by the user.*/ class numeric : public basic { - GINAC_DECLARE_REGISTERED_CLASS(numeric, basic) + GINAC_DECLARE_REGISTERED_CLASS(numeric, basic) // friends - friend const numeric exp(const numeric & x); - friend const numeric log(const numeric & x); - friend const numeric sin(const numeric & x); - friend const numeric cos(const numeric & x); - friend const numeric tan(const numeric & x); - friend const numeric asin(const numeric & x); - friend const numeric acos(const numeric & x); - friend const numeric atan(const numeric & x); - friend const numeric atan(const numeric & y, const numeric & x); - friend const numeric sinh(const numeric & x); - friend const numeric cosh(const numeric & x); - friend const numeric tanh(const numeric & x); - friend const numeric asinh(const numeric & x); - friend const numeric acosh(const numeric & x); - friend const numeric atanh(const numeric & x); - friend const numeric Li2(const numeric & x); - friend const numeric zeta(const numeric & x); - friend const numeric fibonacci(const numeric & n); - friend numeric abs(const numeric & x); - friend numeric mod(const numeric & a, const numeric & b); - friend numeric smod(const numeric & a, const numeric & b); - friend numeric irem(const numeric & a, const numeric & b); - friend numeric irem(const numeric & a, const numeric & b, numeric & q); - friend numeric iquo(const numeric & a, const numeric & b); - friend numeric iquo(const numeric & a, const numeric & b, numeric & r); - friend numeric sqrt(const numeric & x); - friend numeric isqrt(const numeric & x); - friend numeric gcd(const numeric & a, const numeric & b); - friend numeric lcm(const numeric & a, const numeric & b); + friend const numeric exp(const numeric & x); + friend const numeric log(const numeric & x); + friend const numeric sin(const numeric & x); + friend const numeric cos(const numeric & x); + friend const numeric tan(const numeric & x); + friend const numeric asin(const numeric & x); + friend const numeric acos(const numeric & x); + friend const numeric atan(const numeric & x); + friend const numeric atan(const numeric & y, const numeric & x); + friend const numeric sinh(const numeric & x); + friend const numeric cosh(const numeric & x); + friend const numeric tanh(const numeric & x); + friend const numeric asinh(const numeric & x); + friend const numeric acosh(const numeric & x); + friend const numeric atanh(const numeric & x); + friend const numeric Li2(const numeric & x); + friend const numeric zeta(const numeric & x); + friend const numeric fibonacci(const numeric & n); + friend numeric abs(const numeric & x); + friend numeric mod(const numeric & a, const numeric & b); + friend numeric smod(const numeric & a, const numeric & b); + friend numeric irem(const numeric & a, const numeric & b); + friend numeric irem(const numeric & a, const numeric & b, numeric & q); + friend numeric iquo(const numeric & a, const numeric & b); + friend numeric iquo(const numeric & a, const numeric & b, numeric & r); + friend numeric sqrt(const numeric & x); + friend numeric isqrt(const numeric & x); + friend numeric gcd(const numeric & a, const numeric & b); + friend numeric lcm(const numeric & a, const numeric & b); // member functions - // default constructor, destructor, copy constructor assignment - // operator and helpers + // default constructor, destructor, copy constructor assignment + // operator and helpers public: - numeric(); - ~numeric(); - numeric(const numeric & other); - const numeric & operator=(const numeric & other); + numeric(); + ~numeric(); + numeric(const numeric & other); + const numeric & operator=(const numeric & other); protected: - void copy(const numeric & other); - void destroy(bool call_parent); + void copy(const numeric & other); + void destroy(bool call_parent); - // other constructors + // other constructors public: - explicit numeric(int i); - explicit numeric(unsigned int i); - explicit numeric(long i); - explicit numeric(unsigned long i); - explicit numeric(long numer, long denom); - explicit numeric(double d); - explicit numeric(const char *); - numeric(const cl_N & z); - - // functions overriding virtual functions from bases classes + explicit numeric(int i); + explicit numeric(unsigned int i); + explicit numeric(long i); + explicit numeric(unsigned long i); + explicit numeric(long numer, long denom); + explicit numeric(double d); + explicit numeric(const char *); + numeric(const cl_N & z); + + // functions overriding virtual functions from bases classes public: - basic * duplicate() 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; - 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 to_rational(lst &repl_lst) const; - numeric integer_content(void) const; - ex smod(const numeric &xi) const; - numeric max_coefficient(void) const; + basic * duplicate() 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; + 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 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; - int compare_same_type(const basic & other) const; - bool is_equal_same_type(const basic & other) const; - unsigned calchash(void) const; + ex derivative(const symbol & s) const; + int compare_same_type(const basic & other) 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) + // new virtual functions which can be overridden by derived classes + // (none) - // non-virtual functions in this class + // non-virtual functions in this class public: - numeric add(const numeric & other) const; - numeric sub(const numeric & other) const; - numeric mul(const numeric & other) const; - numeric div(const numeric & other) 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); - numeric inverse(void) const; - int csgn(void) const; - ::cl_N* clnptr(void) const { return value; } /**< ptr to representation. */ - 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; - bool is_integer(void) const; - bool is_pos_integer(void) const; - bool is_nonneg_integer(void) const; - bool is_even(void) const; - bool is_odd(void) const; - bool is_prime(void) const; - bool is_rational(void) const; - 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; - int to_int(void) const; - long to_long(void) const; - double to_double(void) const; - const numeric real(void) const; - const numeric imag(void) const; - const numeric numer(void) const; - const numeric denom(void) const; - int int_length(void) const; + numeric add(const numeric & other) const; + numeric sub(const numeric & other) const; + numeric mul(const numeric & other) const; + numeric div(const numeric & other) 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); + numeric inverse(void) const; + int csgn(void) const; + ::cl_N* clnptr(void) const { return value; } /**< ptr to representation. */ + 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; + bool is_integer(void) const; + bool is_pos_integer(void) const; + bool is_nonneg_integer(void) const; + bool is_even(void) const; + bool is_odd(void) const; + bool is_prime(void) const; + bool is_rational(void) const; + 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; + int to_int(void) const; + long to_long(void) const; + double to_double(void) const; + const numeric real(void) const; + const numeric imag(void) const; + const numeric numer(void) const; + const numeric denom(void) const; + int int_length(void) const; // member variables protected: - static unsigned precedence; - ::cl_N *value; + static unsigned precedence; + ::cl_N *value; }; // global constants @@ -326,7 +326,7 @@ ex CatalanEvalf(void); // utility functions inline const numeric &ex_to_numeric(const ex &e) { - return static_cast(*e.bp); + return static_cast(*e.bp); } diff --git a/ginac/operators.cpp b/ginac/operators.cpp index f0d2eb8d..506f47b7 100644 --- a/ginac/operators.cpp +++ b/ginac/operators.cpp @@ -40,32 +40,32 @@ namespace GiNaC { ex operator+(const ex & lh, const ex & rh) { - debugmsg("operator+(ex,ex)",LOGLEVEL_OPERATOR); - return lh.exadd(rh); + debugmsg("operator+(ex,ex)",LOGLEVEL_OPERATOR); + return lh.exadd(rh); } ex operator-(const ex & lh, const ex & rh) { - debugmsg("operator-(ex,ex)",LOGLEVEL_OPERATOR); - return lh.exadd(rh.exmul(_ex_1())); + debugmsg("operator-(ex,ex)",LOGLEVEL_OPERATOR); + return lh.exadd(rh.exmul(_ex_1())); } ex operator*(const ex & lh, const ex & rh) { - debugmsg("operator*(ex,ex)",LOGLEVEL_OPERATOR); - return lh.exmul(rh); + debugmsg("operator*(ex,ex)",LOGLEVEL_OPERATOR); + return lh.exmul(rh); } ex operator/(const ex & lh, const ex & rh) { - debugmsg("operator/(ex,ex)",LOGLEVEL_OPERATOR); - return lh.exmul(power(rh,_ex_1())); + debugmsg("operator/(ex,ex)",LOGLEVEL_OPERATOR); + return lh.exmul(power(rh,_ex_1())); } ex operator%(const ex & lh, const ex & rh) { - debugmsg("operator%(ex,ex)",LOGLEVEL_OPERATOR); - return lh.exncmul(rh); + debugmsg("operator%(ex,ex)",LOGLEVEL_OPERATOR); + return lh.exncmul(rh); } @@ -73,26 +73,26 @@ ex operator%(const ex & lh, const ex & rh) numeric operator+(const numeric & lh, const numeric & rh) { - debugmsg("operator+(numeric,numeric)",LOGLEVEL_OPERATOR); - return lh.add(rh); + debugmsg("operator+(numeric,numeric)",LOGLEVEL_OPERATOR); + return lh.add(rh); } numeric operator-(const numeric & lh, const numeric & rh) { - debugmsg("operator-(numeric,numeric)",LOGLEVEL_OPERATOR); - return lh.sub(rh); + debugmsg("operator-(numeric,numeric)",LOGLEVEL_OPERATOR); + return lh.sub(rh); } numeric operator*(const numeric & lh, const numeric & rh) { - debugmsg("operator*(numeric,numeric)",LOGLEVEL_OPERATOR); - return lh.mul(rh); + debugmsg("operator*(numeric,numeric)",LOGLEVEL_OPERATOR); + return lh.mul(rh); } numeric operator/(const numeric & lh, const numeric & rh) { - debugmsg("operator/(numeric,ex)",LOGLEVEL_OPERATOR); - return lh.div(rh); + debugmsg("operator/(numeric,ex)",LOGLEVEL_OPERATOR); + return lh.div(rh); } @@ -100,32 +100,32 @@ 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); + debugmsg("operator+=(ex,ex)",LOGLEVEL_OPERATOR); + return (lh=lh+rh); } const ex & operator-=(ex & lh, const ex & rh) { - debugmsg("operator-=(ex,ex)",LOGLEVEL_OPERATOR); - return (lh=lh-rh); + debugmsg("operator-=(ex,ex)",LOGLEVEL_OPERATOR); + return (lh=lh-rh); } const ex & operator*=(ex & lh, const ex & rh) { - debugmsg("operator*=(ex,ex)",LOGLEVEL_OPERATOR); - return (lh=lh*rh); + debugmsg("operator*=(ex,ex)",LOGLEVEL_OPERATOR); + return (lh=lh*rh); } const ex & operator/=(ex & lh, const ex & rh) { - debugmsg("operator/=(ex,ex)",LOGLEVEL_OPERATOR); - return (lh=lh/rh); + debugmsg("operator/=(ex,ex)",LOGLEVEL_OPERATOR); + return (lh=lh/rh); } const ex & operator%=(ex & lh, const ex & rh) { - debugmsg("operator%=(ex,ex)",LOGLEVEL_OPERATOR); - return (lh=lh%rh); + debugmsg("operator%=(ex,ex)",LOGLEVEL_OPERATOR); + return (lh=lh%rh); } @@ -133,139 +133,139 @@ const ex & operator%=(ex & lh, const ex & rh) const numeric & operator+=(numeric & lh, const numeric & rh) { - debugmsg("operator+=(numeric,numeric)",LOGLEVEL_OPERATOR); - return (lh=lh.add(rh)); + debugmsg("operator+=(numeric,numeric)",LOGLEVEL_OPERATOR); + return (lh=lh.add(rh)); } const numeric & operator-=(numeric & lh, const numeric & rh) { - debugmsg("operator-=(numeric,numeric)",LOGLEVEL_OPERATOR); - return (lh=lh.sub(rh)); + debugmsg("operator-=(numeric,numeric)",LOGLEVEL_OPERATOR); + return (lh=lh.sub(rh)); } const numeric & operator*=(numeric & lh, const numeric & rh) { - debugmsg("operator*=(numeric,numeric)",LOGLEVEL_OPERATOR); - return (lh=lh.mul(rh)); + debugmsg("operator*=(numeric,numeric)",LOGLEVEL_OPERATOR); + return (lh=lh.mul(rh)); } const numeric & operator/=(numeric & lh, const numeric & rh) { - debugmsg("operator/=(numeric,numeric)",LOGLEVEL_OPERATOR); - return (lh=lh.div(rh)); + debugmsg("operator/=(numeric,numeric)",LOGLEVEL_OPERATOR); + return (lh=lh.div(rh)); } // unary operators ex operator+(const ex & lh) { - debugmsg("operator+(ex)",LOGLEVEL_OPERATOR); - return lh; + debugmsg("operator+(ex)",LOGLEVEL_OPERATOR); + return lh; } ex operator-(const ex & lh) { - debugmsg("operator-(ex)",LOGLEVEL_OPERATOR); - return lh.exmul(_ex_1()); + debugmsg("operator-(ex)",LOGLEVEL_OPERATOR); + return lh.exmul(_ex_1()); } numeric operator+(const numeric & lh) { - debugmsg("operator+(numeric)",LOGLEVEL_OPERATOR); - return lh; + debugmsg("operator+(numeric)",LOGLEVEL_OPERATOR); + return lh; } numeric operator-(const numeric & lh) { - debugmsg("operator-(numeric)",LOGLEVEL_OPERATOR); - return _num_1()*lh; + debugmsg("operator-(numeric)",LOGLEVEL_OPERATOR); + return _num_1()*lh; } /** Numeric prefix increment. Adds 1 and returns incremented number. */ numeric& operator++(numeric & rh) { - debugmsg("operator++(numeric)",LOGLEVEL_OPERATOR); - rh = rh+_num1(); - return rh; + debugmsg("operator++(numeric)",LOGLEVEL_OPERATOR); + rh = rh+_num1(); + return rh; } /** Numeric prefix decrement. Subtracts 1 and returns decremented number. */ numeric& operator--(numeric & rh) { - debugmsg("operator--(numeric)",LOGLEVEL_OPERATOR); - rh = rh-_num1(); - return rh; + debugmsg("operator--(numeric)",LOGLEVEL_OPERATOR); + rh = rh-_num1(); + return rh; } /** Numeric postfix increment. Returns the number and leaves the original * incremented by 1. */ numeric operator++(numeric & lh, int) { - debugmsg("operator++(numeric,int)",LOGLEVEL_OPERATOR); - numeric tmp = lh; - lh = lh+_num1(); - return tmp; + debugmsg("operator++(numeric,int)",LOGLEVEL_OPERATOR); + numeric tmp = lh; + lh = lh+_num1(); + return tmp; } /** Numeric Postfix decrement. Returns the number and leaves the original * decremented by 1. */ numeric operator--(numeric & lh, int) { - debugmsg("operator--(numeric,int)",LOGLEVEL_OPERATOR); - numeric tmp = lh; - lh = lh-_num1(); - return tmp; + debugmsg("operator--(numeric,int)",LOGLEVEL_OPERATOR); + numeric tmp = lh; + lh = lh-_num1(); + return tmp; } // binary relational operators ex with ex relational operator==(const ex & lh, const ex & rh) { - debugmsg("operator==(ex,ex)",LOGLEVEL_OPERATOR); - return relational(lh,rh,relational::equal); + debugmsg("operator==(ex,ex)",LOGLEVEL_OPERATOR); + return relational(lh,rh,relational::equal); } relational operator!=(const ex & lh, const ex & rh) { - debugmsg("operator!=(ex,ex)",LOGLEVEL_OPERATOR); - return relational(lh,rh,relational::not_equal); + debugmsg("operator!=(ex,ex)",LOGLEVEL_OPERATOR); + return relational(lh,rh,relational::not_equal); } relational operator<(const ex & lh, const ex & rh) { - debugmsg("operator<(ex,ex)",LOGLEVEL_OPERATOR); - return relational(lh,rh,relational::less); + debugmsg("operator<(ex,ex)",LOGLEVEL_OPERATOR); + return relational(lh,rh,relational::less); } relational operator<=(const ex & lh, const ex & rh) { - debugmsg("operator<=(ex,ex)",LOGLEVEL_OPERATOR); - return relational(lh,rh,relational::less_or_equal); + debugmsg("operator<=(ex,ex)",LOGLEVEL_OPERATOR); + return relational(lh,rh,relational::less_or_equal); } relational operator>(const ex & lh, const ex & rh) { - debugmsg("operator>(ex,ex)",LOGLEVEL_OPERATOR); - return relational(lh,rh,relational::greater); + debugmsg("operator>(ex,ex)",LOGLEVEL_OPERATOR); + return relational(lh,rh,relational::greater); } relational operator>=(const ex & lh, const ex & rh) { - debugmsg("operator>=(ex,ex)",LOGLEVEL_OPERATOR); - return relational(lh,rh,relational::greater_or_equal); + debugmsg("operator>=(ex,ex)",LOGLEVEL_OPERATOR); + return relational(lh,rh,relational::greater_or_equal); } // input/output stream operators std::ostream & operator<<(std::ostream & os, const ex & e) { - e.print(os); - return os; + e.print(os); + return os; } std::istream & operator>>(std::istream & is, ex & e) { - throw (std::logic_error("expression input from streams not implemented")); + throw (std::logic_error("expression input from streams not implemented")); } #ifndef NO_NAMESPACE_GINAC diff --git a/ginac/power.cpp b/ginac/power.cpp index 53cafc52..2b6049ba 100644 --- a/ginac/power.cpp +++ b/ginac/power.cpp @@ -52,43 +52,43 @@ typedef std::vector intvector; power::power() : basic(TINFO_power) { - debugmsg("power default constructor",LOGLEVEL_CONSTRUCT); + debugmsg("power default constructor",LOGLEVEL_CONSTRUCT); } power::~power() { - debugmsg("power destructor",LOGLEVEL_DESTRUCT); - destroy(0); + debugmsg("power destructor",LOGLEVEL_DESTRUCT); + destroy(0); } power::power(const power & other) { - debugmsg("power copy constructor",LOGLEVEL_CONSTRUCT); - copy(other); + debugmsg("power copy constructor",LOGLEVEL_CONSTRUCT); + copy(other); } const power & power::operator=(const power & other) { - debugmsg("power operator=",LOGLEVEL_ASSIGNMENT); - if (this != &other) { - destroy(1); - copy(other); - } - return *this; + debugmsg("power operator=",LOGLEVEL_ASSIGNMENT); + if (this != &other) { + destroy(1); + copy(other); + } + return *this; } // protected void power::copy(const power & other) { - inherited::copy(other); - basis=other.basis; - exponent=other.exponent; + inherited::copy(other); + basis=other.basis; + exponent=other.exponent; } void power::destroy(bool call_parent) { - if (call_parent) inherited::destroy(call_parent); + if (call_parent) inherited::destroy(call_parent); } ////////// @@ -99,14 +99,14 @@ void power::destroy(bool call_parent) power::power(const ex & lh, const ex & rh) : basic(TINFO_power), basis(lh), exponent(rh) { - debugmsg("power constructor from ex,ex",LOGLEVEL_CONSTRUCT); - GINAC_ASSERT(basis.return_type()==return_types::commutative); + debugmsg("power constructor 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); - GINAC_ASSERT(basis.return_type()==return_types::commutative); + debugmsg("power constructor from ex,numeric",LOGLEVEL_CONSTRUCT); + GINAC_ASSERT(basis.return_type()==return_types::commutative); } ////////// @@ -116,23 +116,23 @@ 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); - n.find_ex("basis", basis, sym_lst); - n.find_ex("exponent", exponent, sym_lst); + debugmsg("power constructor from archive_node", LOGLEVEL_CONSTRUCT); + n.find_ex("basis", basis, sym_lst); + n.find_ex("exponent", exponent, sym_lst); } /** Unarchive the object. */ ex power::unarchive(const archive_node &n, const lst &sym_lst) { - return (new power(n, sym_lst))->setflag(status_flags::dynallocated); + return (new power(n, sym_lst))->setflag(status_flags::dynallocated); } /** Archive the object. */ void power::archive(archive_node &n) const { - inherited::archive(n); - n.add_ex("basis", basis); - n.add_ex("exponent", exponent); + inherited::archive(n); + n.add_ex("basis", basis); + n.add_ex("exponent", exponent); } ////////// @@ -143,378 +143,378 @@ void power::archive(archive_node &n) const basic * power::duplicate() const { - debugmsg("power duplicate",LOGLEVEL_DUPLICATE); - return new power(*this); + debugmsg("power duplicate",LOGLEVEL_DUPLICATE); + return new power(*this); } void power::print(std::ostream & os, unsigned upper_precedence) const { - debugmsg("power print",LOGLEVEL_PRINT); - if (exponent.is_equal(_ex1_2())) { - os << "sqrt(" << basis << ")"; - } else { - if (precedence<=upper_precedence) os << "("; - basis.print(os,precedence); - os << "^"; - exponent.print(os,precedence); - if (precedence<=upper_precedence) os << ")"; - } + debugmsg("power print",LOGLEVEL_PRINT); + if (exponent.is_equal(_ex1_2())) { + os << "sqrt(" << basis << ")"; + } else { + if (precedence<=upper_precedence) os << "("; + basis.print(os,precedence); + os << "^"; + exponent.print(os,precedence); + if (precedence<=upper_precedence) os << ")"; + } } void power::printraw(std::ostream & os) const { - debugmsg("power printraw",LOGLEVEL_PRINT); + debugmsg("power printraw",LOGLEVEL_PRINT); - os << "power("; - basis.printraw(os); - os << ","; - exponent.printraw(os); - os << ",hash=" << hashvalue << ",flags=" << flags << ")"; + os << "power("; + basis.printraw(os); + os << ","; + exponent.printraw(os); + os << ",hash=" << hashvalue << ",flags=" << flags << ")"; } void power::printtree(std::ostream & os, unsigned indent) const { - debugmsg("power printtree",LOGLEVEL_PRINT); + debugmsg("power printtree",LOGLEVEL_PRINT); - os << std::string(indent,' ') << "power: " - << "hash=" << hashvalue - << " (0x" << std::hex << hashvalue << std::dec << ")" - << ", flags=" << flags << std::endl; - basis.printtree(os, indent+delta_indent); - exponent.printtree(os, indent+delta_indent); + os << std::string(indent,' ') << "power: " + << "hash=" << hashvalue + << " (0x" << std::hex << hashvalue << std::dec << ")" + << ", flags=" << flags << std::endl; + basis.printtree(os, indent+delta_indent); + exponent.printtree(os, indent+delta_indent); } 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 - if (exp == 1) { - x.printcsrc(os, type, 0); - } else if (exp == 2) { - x.printcsrc(os, type, 0); - os << "*"; - x.printcsrc(os, type, 0); - } else if (exp & 1) { - x.printcsrc(os, 0); - os << "*"; - print_sym_pow(os, type, x, exp-1); - } else { - os << "("; - print_sym_pow(os, type, x, exp >> 1); - os << ")*("; - print_sym_pow(os, type, x, exp >> 1); - os << ")"; - } + // Optimal output of integer powers of symbols to aid compiler CSE + if (exp == 1) { + x.printcsrc(os, type, 0); + } else if (exp == 2) { + x.printcsrc(os, type, 0); + os << "*"; + x.printcsrc(os, type, 0); + } else if (exp & 1) { + x.printcsrc(os, 0); + os << "*"; + print_sym_pow(os, type, x, exp-1); + } else { + os << "("; + print_sym_pow(os, type, x, exp >> 1); + os << ")*("; + print_sym_pow(os, type, x, exp >> 1); + os << ")"; + } } void power::printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const { - debugmsg("power print csrc", LOGLEVEL_PRINT); - - // Integer powers of symbols are printed in a special, optimized way - if (exponent.info(info_flags::integer) && - (is_ex_exactly_of_type(basis, symbol) || - is_ex_exactly_of_type(basis, constant))) { - int exp = ex_to_numeric(exponent).to_int(); - if (exp > 0) - os << "("; - else { - exp = -exp; - if (type == csrc_types::ctype_cl_N) - os << "recip("; - else - os << "1.0/("; - } - print_sym_pow(os, type, static_cast(*basis.bp), exp); - os << ")"; - - // ^-1 is printed as "1.0/" or with the recip() function of CLN - } else if (exponent.compare(_num_1()) == 0) { - if (type == csrc_types::ctype_cl_N) - os << "recip("; - else - os << "1.0/("; - basis.bp->printcsrc(os, type, 0); - os << ")"; - - // Otherwise, use the pow() or expt() (CLN) functions - } else { - if (type == csrc_types::ctype_cl_N) - os << "expt("; - else - os << "pow("; - basis.bp->printcsrc(os, type, 0); - os << ","; - exponent.bp->printcsrc(os, type, 0); - os << ")"; - } + debugmsg("power print csrc", LOGLEVEL_PRINT); + + // Integer powers of symbols are printed in a special, optimized way + if (exponent.info(info_flags::integer) && + (is_ex_exactly_of_type(basis, symbol) || + is_ex_exactly_of_type(basis, constant))) { + int exp = ex_to_numeric(exponent).to_int(); + if (exp > 0) + os << "("; + else { + exp = -exp; + if (type == csrc_types::ctype_cl_N) + os << "recip("; + else + os << "1.0/("; + } + print_sym_pow(os, type, static_cast(*basis.bp), exp); + os << ")"; + + // ^-1 is printed as "1.0/" or with the recip() function of CLN + } else if (exponent.compare(_num_1()) == 0) { + if (type == csrc_types::ctype_cl_N) + os << "recip("; + else + os << "1.0/("; + basis.bp->printcsrc(os, type, 0); + os << ")"; + + // Otherwise, use the pow() or expt() (CLN) functions + } else { + if (type == csrc_types::ctype_cl_N) + os << "expt("; + else + os << "pow("; + basis.bp->printcsrc(os, type, 0); + os << ","; + exponent.bp->printcsrc(os, type, 0); + os << ")"; + } } bool power::info(unsigned inf) const { - switch (inf) { - case info_flags::polynomial: - case info_flags::integer_polynomial: - case info_flags::cinteger_polynomial: - case info_flags::rational_polynomial: - case info_flags::crational_polynomial: - return exponent.info(info_flags::nonnegint); - case info_flags::rational_function: - return exponent.info(info_flags::integer); - case info_flags::algebraic: - return (!exponent.info(info_flags::integer) || - basis.info(inf)); - } - return inherited::info(inf); + switch (inf) { + case info_flags::polynomial: + case info_flags::integer_polynomial: + case info_flags::cinteger_polynomial: + case info_flags::rational_polynomial: + case info_flags::crational_polynomial: + return exponent.info(info_flags::nonnegint); + case info_flags::rational_function: + return exponent.info(info_flags::integer); + case info_flags::algebraic: + return (!exponent.info(info_flags::integer) || + basis.info(inf)); + } + return inherited::info(inf); } unsigned power::nops() const { - return 2; + return 2; } ex & power::let_op(int i) { - GINAC_ASSERT(i>=0); - GINAC_ASSERT(i<2); + GINAC_ASSERT(i>=0); + GINAC_ASSERT(i<2); - return i==0 ? basis : exponent; + return i==0 ? basis : exponent; } int power::degree(const symbol & s) const { - if (is_exactly_of_type(*exponent.bp,numeric)) { - if ((*basis.bp).compare(s)==0) - return ex_to_numeric(exponent).to_int(); - else - return basis.degree(s) * ex_to_numeric(exponent).to_int(); - } - return 0; + if (is_exactly_of_type(*exponent.bp,numeric)) { + if ((*basis.bp).compare(s)==0) + return ex_to_numeric(exponent).to_int(); + else + return basis.degree(s) * ex_to_numeric(exponent).to_int(); + } + return 0; } int power::ldegree(const symbol & s) const { - if (is_exactly_of_type(*exponent.bp,numeric)) { - if ((*basis.bp).compare(s)==0) - return ex_to_numeric(exponent).to_int(); - else - return basis.ldegree(s) * ex_to_numeric(exponent).to_int(); - } - return 0; + if (is_exactly_of_type(*exponent.bp,numeric)) { + if ((*basis.bp).compare(s)==0) + return ex_to_numeric(exponent).to_int(); + else + return basis.ldegree(s) * ex_to_numeric(exponent).to_int(); + } + return 0; } ex power::coeff(const symbol & s, int n) const { - if ((*basis.bp).compare(s)!=0) { - // basis not equal to s - if (n==0) { - return *this; - } else { - return _ex0(); - } - } else if (is_exactly_of_type(*exponent.bp,numeric)&& - (static_cast(*exponent.bp).compare(numeric(n))==0)) { - return _ex1(); - } + if ((*basis.bp).compare(s)!=0) { + // basis not equal to s + if (n==0) { + return *this; + } else { + return _ex0(); + } + } else if (is_exactly_of_type(*exponent.bp,numeric)&& + (static_cast(*exponent.bp).compare(numeric(n))==0)) { + return _ex1(); + } - return _ex0(); + return _ex0(); } ex power::eval(int level) const { - // simplifications: ^(x,0) -> 1 (0^0 handled here) - // ^(x,1) -> x - // ^(0,c1) -> 0 or exception (depending on real value of c1) - // ^(1,x) -> 1 - // ^(c1,c2) -> *(c1^n,c1^(c2-n)) (c1, c2 numeric(), 0<(c2-n)<1 except if c1,c2 are rational, but c1^c2 is not) - // ^(^(x,c1),c2) -> ^(x,c1*c2) (c1, c2 numeric(), c2 integer or -1 < c1 <= 1, case c1=1 should not happen, see below!) - // ^(*(x,y,z),c1) -> *(x^c1,y^c1,z^c1) (c1 integer) - // ^(*(x,c1),c2) -> ^(x,c2)*c1^c2 (c1, c2 numeric(), c1>0) - // ^(*(x,c1),c2) -> ^(-x,c2)*c1^c2 (c1, c2 numeric(), c1<0) - - debugmsg("power eval",LOGLEVEL_MEMBER_FUNCTION); - - if ((level==1) && (flags & status_flags::evaluated)) - return *this; - else if (level == -max_recursion_level) - throw(std::runtime_error("max recursion level reached")); - - const ex & ebasis = level==1 ? basis : basis.eval(level-1); - const ex & eexponent = level==1 ? exponent : exponent.eval(level-1); - - bool basis_is_numerical = 0; - bool exponent_is_numerical = 0; - numeric * num_basis; - numeric * num_exponent; - - if (is_exactly_of_type(*ebasis.bp,numeric)) { - basis_is_numerical = 1; - num_basis = static_cast(ebasis.bp); - } - if (is_exactly_of_type(*eexponent.bp,numeric)) { - exponent_is_numerical = 1; - num_exponent = static_cast(eexponent.bp); - } - - // ^(x,0) -> 1 (0^0 also handled here) - 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())) - return ebasis; - - // ^(0,c1) -> 0 or exception (depending on real value of c1) - if (ebasis.is_zero() && exponent_is_numerical) { - if ((num_exponent->real()).is_zero()) - throw (std::domain_error("power::eval(): pow(0,I) is undefined")); - else if ((num_exponent->real()).is_negative()) - throw (pole_error("power::eval(): division by zero",1)); - else - return _ex0(); - } - - // ^(1,x) -> 1 - if (ebasis.is_equal(_ex1())) - return _ex1(); - - if (basis_is_numerical && exponent_is_numerical) { - // ^(c1,c2) -> c1^c2 (c1, c2 numeric(), - // 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); - - if ((!basis_is_crational || !exponent_is_crational) - || res.is_crational()) { - return res; - } - GINAC_ASSERT(!num_exponent->is_integer()); // has been handled by now - // ^(c1,n/m) -> *(c1^q,c1^(n/m-q)), 0<(n/m-h)<1, q integer - if (basis_is_crational && exponent_is_crational - && num_exponent->is_real() - && !num_exponent->is_integer()) { - numeric n = num_exponent->numer(); - numeric m = num_exponent->denom(); - numeric r; - numeric q = iquo(n, m, r); - if (r.is_negative()) { - r = r.add(m); - q = q.sub(_num1()); - } - if (q.is_zero()) // the exponent was in the allowed range 0<(n/m)<1 - return this->hold(); - 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); - } - } - } - - // ^(^(x,c1),c2) -> ^(x,c1*c2) - // (c1, c2 numeric(), c2 integer or -1 < c1 <= 1, - // case c1==1 should not happen, see below!) - if (exponent_is_numerical && is_ex_exactly_of_type(ebasis,power)) { - const power & sub_power = ex_to_power(ebasis); - const ex & sub_basis = sub_power.basis; - const ex & sub_exponent = sub_power.exponent; - 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) { - return power(sub_basis,num_sub_exponent.mul(*num_exponent)); - } - } - } - - // ^(*(x,y,z),c1) -> *(x^c1,y^c1,z^c1) (c1 integer) - if (exponent_is_numerical && num_exponent->is_integer() && - is_ex_exactly_of_type(ebasis,mul)) { - return expand_mul(ex_to_mul(ebasis), *num_exponent); - } - - // ^(*(...,x;c1),c2) -> ^(*(...,x;1),c2)*c1^c2 (c1, c2 numeric(), c1>0) - // ^(*(...,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); - if (!mulref.overall_coeff.is_equal(_ex1())) { - 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(); - mulp->clearflag(status_flags::evaluated); - mulp->clearflag(status_flags::hash_calculated); - return (new mul(power(*mulp,exponent), - power(num_coeff,*num_exponent)))-> - setflag(status_flags::dynallocated); - } 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(); - mulp->clearflag(status_flags::evaluated); - mulp->clearflag(status_flags::hash_calculated); - return (new mul(power(*mulp,exponent), - power(abs(num_coeff),*num_exponent)))-> - setflag(status_flags::dynallocated); - } - } - } - } - } - - if (are_ex_trivially_equal(ebasis,basis) && - are_ex_trivially_equal(eexponent,exponent)) { - return this->hold(); - } - return (new power(ebasis, eexponent))->setflag(status_flags::dynallocated | - status_flags::evaluated); + // simplifications: ^(x,0) -> 1 (0^0 handled here) + // ^(x,1) -> x + // ^(0,c1) -> 0 or exception (depending on real value of c1) + // ^(1,x) -> 1 + // ^(c1,c2) -> *(c1^n,c1^(c2-n)) (c1, c2 numeric(), 0<(c2-n)<1 except if c1,c2 are rational, but c1^c2 is not) + // ^(^(x,c1),c2) -> ^(x,c1*c2) (c1, c2 numeric(), c2 integer or -1 < c1 <= 1, case c1=1 should not happen, see below!) + // ^(*(x,y,z),c1) -> *(x^c1,y^c1,z^c1) (c1 integer) + // ^(*(x,c1),c2) -> ^(x,c2)*c1^c2 (c1, c2 numeric(), c1>0) + // ^(*(x,c1),c2) -> ^(-x,c2)*c1^c2 (c1, c2 numeric(), c1<0) + + debugmsg("power eval",LOGLEVEL_MEMBER_FUNCTION); + + if ((level==1) && (flags & status_flags::evaluated)) + return *this; + else if (level == -max_recursion_level) + throw(std::runtime_error("max recursion level reached")); + + const ex & ebasis = level==1 ? basis : basis.eval(level-1); + const ex & eexponent = level==1 ? exponent : exponent.eval(level-1); + + bool basis_is_numerical = 0; + bool exponent_is_numerical = 0; + numeric * num_basis; + numeric * num_exponent; + + if (is_exactly_of_type(*ebasis.bp,numeric)) { + basis_is_numerical = 1; + num_basis = static_cast(ebasis.bp); + } + if (is_exactly_of_type(*eexponent.bp,numeric)) { + exponent_is_numerical = 1; + num_exponent = static_cast(eexponent.bp); + } + + // ^(x,0) -> 1 (0^0 also handled here) + 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())) + return ebasis; + + // ^(0,c1) -> 0 or exception (depending on real value of c1) + if (ebasis.is_zero() && exponent_is_numerical) { + if ((num_exponent->real()).is_zero()) + throw (std::domain_error("power::eval(): pow(0,I) is undefined")); + else if ((num_exponent->real()).is_negative()) + throw (pole_error("power::eval(): division by zero",1)); + else + return _ex0(); + } + + // ^(1,x) -> 1 + if (ebasis.is_equal(_ex1())) + return _ex1(); + + if (basis_is_numerical && exponent_is_numerical) { + // ^(c1,c2) -> c1^c2 (c1, c2 numeric(), + // 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); + + if ((!basis_is_crational || !exponent_is_crational) + || res.is_crational()) { + return res; + } + GINAC_ASSERT(!num_exponent->is_integer()); // has been handled by now + // ^(c1,n/m) -> *(c1^q,c1^(n/m-q)), 0<(n/m-h)<1, q integer + if (basis_is_crational && exponent_is_crational + && num_exponent->is_real() + && !num_exponent->is_integer()) { + numeric n = num_exponent->numer(); + numeric m = num_exponent->denom(); + numeric r; + numeric q = iquo(n, m, r); + if (r.is_negative()) { + r = r.add(m); + q = q.sub(_num1()); + } + if (q.is_zero()) // the exponent was in the allowed range 0<(n/m)<1 + return this->hold(); + 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); + } + } + } + + // ^(^(x,c1),c2) -> ^(x,c1*c2) + // (c1, c2 numeric(), c2 integer or -1 < c1 <= 1, + // case c1==1 should not happen, see below!) + if (exponent_is_numerical && is_ex_exactly_of_type(ebasis,power)) { + const power & sub_power = ex_to_power(ebasis); + const ex & sub_basis = sub_power.basis; + const ex & sub_exponent = sub_power.exponent; + 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) { + return power(sub_basis,num_sub_exponent.mul(*num_exponent)); + } + } + } + + // ^(*(x,y,z),c1) -> *(x^c1,y^c1,z^c1) (c1 integer) + if (exponent_is_numerical && num_exponent->is_integer() && + is_ex_exactly_of_type(ebasis,mul)) { + return expand_mul(ex_to_mul(ebasis), *num_exponent); + } + + // ^(*(...,x;c1),c2) -> ^(*(...,x;1),c2)*c1^c2 (c1, c2 numeric(), c1>0) + // ^(*(...,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); + if (!mulref.overall_coeff.is_equal(_ex1())) { + 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(); + mulp->clearflag(status_flags::evaluated); + mulp->clearflag(status_flags::hash_calculated); + return (new mul(power(*mulp,exponent), + power(num_coeff,*num_exponent)))-> + setflag(status_flags::dynallocated); + } 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(); + mulp->clearflag(status_flags::evaluated); + mulp->clearflag(status_flags::hash_calculated); + return (new mul(power(*mulp,exponent), + power(abs(num_coeff),*num_exponent)))-> + setflag(status_flags::dynallocated); + } + } + } + } + } + + if (are_ex_trivially_equal(ebasis,basis) && + are_ex_trivially_equal(eexponent,exponent)) { + return this->hold(); + } + return (new power(ebasis, eexponent))->setflag(status_flags::dynallocated | + status_flags::evaluated); } ex power::evalf(int level) const { - debugmsg("power evalf",LOGLEVEL_MEMBER_FUNCTION); + debugmsg("power evalf",LOGLEVEL_MEMBER_FUNCTION); - ex ebasis; - ex eexponent; - - if (level==1) { - ebasis = basis; - eexponent = exponent; - } else if (level == -max_recursion_level) { - throw(std::runtime_error("max recursion level reached")); - } else { - ebasis = basis.evalf(level-1); - if (!is_ex_exactly_of_type(eexponent,numeric)) - eexponent = exponent.evalf(level-1); - else - eexponent = exponent; - } + ex ebasis; + ex eexponent; + + if (level==1) { + ebasis = basis; + eexponent = exponent; + } else if (level == -max_recursion_level) { + throw(std::runtime_error("max recursion level reached")); + } else { + ebasis = basis.evalf(level-1); + if (!is_ex_exactly_of_type(eexponent,numeric)) + eexponent = exponent.evalf(level-1); + else + eexponent = exponent; + } - return power(ebasis,eexponent); + return power(ebasis,eexponent); } ex power::subs(const lst & ls, const lst & lr) const { - const ex & subsed_basis=basis.subs(ls,lr); - const ex & subsed_exponent=exponent.subs(ls,lr); + const ex & subsed_basis=basis.subs(ls,lr); + const ex & subsed_exponent=exponent.subs(ls,lr); - if (are_ex_trivially_equal(basis,subsed_basis)&& - are_ex_trivially_equal(exponent,subsed_exponent)) { - return *this; - } - - return power(subsed_basis, subsed_exponent); + if (are_ex_trivially_equal(basis,subsed_basis)&& + are_ex_trivially_equal(exponent,subsed_exponent)) { + return *this; + } + + return power(subsed_basis, subsed_exponent); } ex power::simplify_ncmul(const exvector & v) const { - return inherited::simplify_ncmul(v); + return inherited::simplify_ncmul(v); } // protected @@ -523,82 +523,82 @@ ex power::simplify_ncmul(const exvector & v) const * @see ex::diff */ ex power::derivative(const symbol & s) const { - if (exponent.info(info_flags::real)) { - // D(b^r) = r * b^(r-1) * D(b) (faster than the formula below) - epvector newseq; - newseq.reserve(2); - newseq.push_back(expair(basis, exponent - _ex1())); - newseq.push_back(expair(basis.diff(s), _ex1())); - return mul(newseq, exponent); - } else { - // D(b^e) = b^e * (D(e)*ln(b) + e*D(b)/b) - return mul(power(basis, exponent), - add(mul(exponent.diff(s), log(basis)), - mul(mul(exponent, basis.diff(s)), power(basis, -1)))); - } + if (exponent.info(info_flags::real)) { + // D(b^r) = r * b^(r-1) * D(b) (faster than the formula below) + epvector newseq; + newseq.reserve(2); + newseq.push_back(expair(basis, exponent - _ex1())); + newseq.push_back(expair(basis.diff(s), _ex1())); + return mul(newseq, exponent); + } else { + // D(b^e) = b^e * (D(e)*ln(b) + e*D(b)/b) + return mul(power(basis, exponent), + add(mul(exponent.diff(s), log(basis)), + mul(mul(exponent, basis.diff(s)), power(basis, -1)))); + } } int power::compare_same_type(const basic & other) const { - GINAC_ASSERT(is_exactly_of_type(other, power)); - const power & o=static_cast(const_cast(other)); + GINAC_ASSERT(is_exactly_of_type(other, power)); + const power & o=static_cast(const_cast(other)); - int cmpval; - cmpval=basis.compare(o.basis); - if (cmpval==0) { - return exponent.compare(o.exponent); - } - return cmpval; + int cmpval; + cmpval=basis.compare(o.basis); + if (cmpval==0) { + return exponent.compare(o.exponent); + } + return cmpval; } unsigned power::return_type(void) const { - return basis.return_type(); + return basis.return_type(); } unsigned power::return_type_tinfo(void) const { - return basis.return_type_tinfo(); + return basis.return_type_tinfo(); } ex power::expand(unsigned options) const { - if (flags & status_flags::expanded) - return *this; - - ex expanded_basis = basis.expand(options); - - if (!is_ex_exactly_of_type(exponent,numeric) || - !ex_to_numeric(exponent).is_integer()) { - if (are_ex_trivially_equal(basis,expanded_basis)) { - return this->hold(); - } else { - return (new power(expanded_basis,exponent))-> - setflag(status_flags::dynallocated | - status_flags::expanded); - } - } - - // integer numeric exponent - const numeric & num_exponent = ex_to_numeric(exponent); - int int_exponent = num_exponent.to_int(); - - if (int_exponent > 0 && is_ex_exactly_of_type(expanded_basis,add)) { - return expand_add(ex_to_add(expanded_basis), int_exponent); - } - - 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)) { - return this->hold(); - } else { - return (new power(expanded_basis,exponent))-> - setflag(status_flags::dynallocated | - status_flags::expanded); - } + if (flags & status_flags::expanded) + return *this; + + ex expanded_basis = basis.expand(options); + + if (!is_ex_exactly_of_type(exponent,numeric) || + !ex_to_numeric(exponent).is_integer()) { + if (are_ex_trivially_equal(basis,expanded_basis)) { + return this->hold(); + } else { + return (new power(expanded_basis,exponent))-> + setflag(status_flags::dynallocated | + status_flags::expanded); + } + } + + // integer numeric exponent + const numeric & num_exponent = ex_to_numeric(exponent); + int int_exponent = num_exponent.to_int(); + + if (int_exponent > 0 && is_ex_exactly_of_type(expanded_basis,add)) { + return expand_add(ex_to_add(expanded_basis), int_exponent); + } + + 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)) { + return this->hold(); + } else { + return (new power(expanded_basis,exponent))-> + setflag(status_flags::dynallocated | + status_flags::expanded); + } } ////////// @@ -615,102 +615,102 @@ ex power::expand(unsigned options) const * @see power::expand */ ex power::expand_add(const add & a, int n) const { - if (n==2) - return expand_add_2(a); - - int m = a.nops(); - exvector sum; - sum.reserve((n+1)*(m-1)); - intvector k(m-1); - intvector k_cum(m-1); // k_cum[l]:=sum(i=0,l,k[l]); - intvector upper_limit(m-1); - int l; - - for (int l=0; lsetflag(status_flags::dynallocated)); - - // increment k[] - l=m-2; - while ((l>=0)&&((++k[l])>upper_limit[l])) { - 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 ); + if (n==2) + return expand_add_2(a); + + int m = a.nops(); + exvector sum; + sum.reserve((n+1)*(m-1)); + intvector k(m-1); + intvector k_cum(m-1); // k_cum[l]:=sum(i=0,l,k[l]); + intvector upper_limit(m-1); + int l; + + for (int l=0; lsetflag(status_flags::dynallocated)); + + // increment k[] + l=m-2; + while ((l>=0)&&((++k[l])>upper_limit[l])) { + 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 ); } @@ -718,128 +718,128 @@ ex power::expand_add(const add & a, int n) const * @see power::expand_add */ ex power::expand_add_2(const add & a) const { - epvector sum; - unsigned a_nops=a.nops(); - sum.reserve((a_nops*(a_nops+1))/2); - 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; - - GINAC_ASSERT(!is_ex_exactly_of_type(r,add)); - GINAC_ASSERT(!is_ex_exactly_of_type(r,power)|| - !is_ex_exactly_of_type(ex_to_power(r).exponent,numeric)|| - !ex_to_numeric(ex_to_power(r).exponent).is_pos_integer()|| - !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()),_ex1())); - } else { - sum.push_back(expair((new power(r,_ex2()))->setflag(status_flags::dynallocated), - _ex1())); - } - } else { - if (is_ex_exactly_of_type(r,mul)) { - sum.push_back(expair(expand_mul(ex_to_mul(r),_num2()), - ex_to_numeric(c).power_dyn(_num2()))); - } else { - sum.push_back(expair((new power(r,_ex2()))->setflag(status_flags::dynallocated), - ex_to_numeric(c).power_dyn(_num2()))); - } - } - - for (epvector::const_iterator cit1=cit0+1; cit1!=last; ++cit1) { - 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())) { - 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 ); + epvector sum; + unsigned a_nops=a.nops(); + sum.reserve((a_nops*(a_nops+1))/2); + 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; + + GINAC_ASSERT(!is_ex_exactly_of_type(r,add)); + GINAC_ASSERT(!is_ex_exactly_of_type(r,power)|| + !is_ex_exactly_of_type(ex_to_power(r).exponent,numeric)|| + !ex_to_numeric(ex_to_power(r).exponent).is_pos_integer()|| + !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()),_ex1())); + } else { + sum.push_back(expair((new power(r,_ex2()))->setflag(status_flags::dynallocated), + _ex1())); + } + } else { + if (is_ex_exactly_of_type(r,mul)) { + sum.push_back(expair(expand_mul(ex_to_mul(r),_num2()), + ex_to_numeric(c).power_dyn(_num2()))); + } else { + sum.push_back(expair((new power(r,_ex2()))->setflag(status_flags::dynallocated), + ex_to_numeric(c).power_dyn(_num2()))); + } + } + + for (epvector::const_iterator cit1=cit0+1; cit1!=last; ++cit1) { + 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())) { + 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 ); } /** Expand factors of m in m^n where m is a mul and n is and integer * @see power::expand */ ex power::expand_mul(const mul & m, const numeric & n) const { - if (n.is_equal(_num0())) - return _ex1(); - - epvector distrseq; - distrseq.reserve(m.seq.size()); - epvector::const_iterator last = m.seq.end(); - epvector::const_iterator cit = m.seq.begin(); - while (cit!=last) { - if (is_ex_exactly_of_type((*cit).rest,numeric)) { - distrseq.push_back(m.combine_pair_with_coeff_to_pair(*cit,n)); - } else { - // it is safe not to call mul::combine_pair_with_coeff_to_pair() - // since n is an integer - distrseq.push_back(expair((*cit).rest, - ex_to_numeric((*cit).coeff).mul(n))); - } - ++cit; - } - return (new mul(distrseq,ex_to_numeric(m.overall_coeff).power_dyn(n))) - ->setflag(status_flags::dynallocated); + if (n.is_equal(_num0())) + return _ex1(); + + epvector distrseq; + distrseq.reserve(m.seq.size()); + epvector::const_iterator last = m.seq.end(); + epvector::const_iterator cit = m.seq.begin(); + while (cit!=last) { + if (is_ex_exactly_of_type((*cit).rest,numeric)) { + distrseq.push_back(m.combine_pair_with_coeff_to_pair(*cit,n)); + } else { + // it is safe not to call mul::combine_pair_with_coeff_to_pair() + // since n is an integer + distrseq.push_back(expair((*cit).rest, + ex_to_numeric((*cit).coeff).mul(n))); + } + ++cit; + } + return (new mul(distrseq,ex_to_numeric(m.overall_coeff).power_dyn(n))) + ->setflag(status_flags::dynallocated); } /* ex power::expand_commutative_3(const ex & basis, const numeric & exponent, - unsigned options) const + unsigned options) const { - // obsolete + // obsolete - exvector distrseq; - epvector splitseq; + exvector distrseq; + epvector splitseq; - const add & addref=static_cast(*basis.bp); + const add & addref=static_cast(*basis.bp); - splitseq=addref.seq; - splitseq.pop_back(); - ex first_operands=add(splitseq); - ex last_operand=addref.recombine_pair_to_ex(*(addref.seq.end()-1)); - - int n=exponent.to_int(); - for (int k=0; k<=n; k++) { - distrseq.push_back(binomial(n,k)*power(first_operands,numeric(k))* - power(last_operand,numeric(n-k))); - } - return ex((new add(distrseq))->setflag(status_flags::expanded | - status_flags::dynallocated )). - expand(options); + splitseq=addref.seq; + splitseq.pop_back(); + ex first_operands=add(splitseq); + ex last_operand=addref.recombine_pair_to_ex(*(addref.seq.end()-1)); + + int n=exponent.to_int(); + for (int k=0; k<=n; k++) { + distrseq.push_back(binomial(n,k)*power(first_operands,numeric(k))* + power(last_operand,numeric(n-k))); + } + return ex((new add(distrseq))->setflag(status_flags::expanded | + status_flags::dynallocated )). + expand(options); } */ /* ex power::expand_noncommutative(const ex & basis, const numeric & exponent, - unsigned options) const + unsigned options) const { - ex rest_power=ex(power(basis,exponent.add(_num_1()))). - expand(options | expand_options::internal_do_not_expand_power_operands); + ex rest_power=ex(power(basis,exponent.add(_num_1()))). + expand(options | expand_options::internal_do_not_expand_power_operands); - return ex(mul(rest_power,basis),0). - expand(options | expand_options::internal_do_not_expand_mul_operands); + return ex(mul(rest_power,basis),0). + expand(options | expand_options::internal_do_not_expand_mul_operands); } */ @@ -862,7 +862,7 @@ const type_info & typeid_power=typeid(some_power); ex sqrt(const ex & a) { - return power(a,_ex1_2()); + return power(a,_ex1_2()); } #ifndef NO_NAMESPACE_GINAC diff --git a/ginac/power.h b/ginac/power.h index afc59f33..d765d382 100644 --- a/ginac/power.h +++ b/ginac/power.h @@ -37,72 +37,72 @@ class add; * representing exponentiation. */ class power : public basic { - GINAC_DECLARE_REGISTERED_CLASS(power, basic) + GINAC_DECLARE_REGISTERED_CLASS(power, basic) - friend class mul; + friend class mul; // member functions - // default constructor, destructor, copy constructor assignment operator and helpers + // default constructor, destructor, copy constructor assignment operator and helpers public: - power(); - ~power(); - power(const power & other); - const power & operator=(const power & other); + power(); + ~power(); + power(const power & other); + const power & operator=(const power & other); protected: - void copy(const power & other); - void destroy(bool call_parent); + void copy(const power & other); + void destroy(bool call_parent); - // other constructors + // other constructors public: - power(const ex & lh, const ex & rh); - power(const ex & lh, const numeric & rh); + power(const ex & lh, const ex & rh); + power(const ex & lh, const numeric & rh); - // functions overriding virtual functions from bases classes + // functions overriding virtual functions from bases classes public: - basic * duplicate() 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; - bool info(unsigned inf) const; - unsigned nops() const; - ex & let_op(int i); - int degree(const symbol & s) const; - int ldegree(const symbol & s) const; - ex coeff(const symbol & s, int n = 1) const; - ex eval(int level=0) const; - ex evalf(int level=0) const; - ex series(const relational & s, int order, unsigned options = 0) const; - ex subs(const lst & ls, const lst & lr) const; - ex normal(lst &sym_lst, lst &repl_lst, int level = 0) const; - ex to_rational(lst &repl_lst) const; - ex simplify_ncmul(const exvector & v) const; + basic * duplicate() 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; + bool info(unsigned inf) const; + unsigned nops() const; + ex & let_op(int i); + int degree(const symbol & s) const; + int ldegree(const symbol & s) const; + ex coeff(const symbol & s, int n = 1) const; + ex eval(int level=0) const; + ex evalf(int level=0) const; + ex series(const relational & s, int order, unsigned options = 0) const; + ex subs(const lst & ls, const lst & lr) const; + ex normal(lst &sym_lst, lst &repl_lst, int level = 0) const; + ex to_rational(lst &repl_lst) const; + ex simplify_ncmul(const exvector & v) const; protected: - ex derivative(const symbol & s) const; - int compare_same_type(const basic & other) const; - unsigned return_type(void) const; - unsigned return_type_tinfo(void) const; - ex expand(unsigned options = 0) const; - - // new virtual functions which can be overridden by derived classes - // none - - // non-virtual functions in this class + ex derivative(const symbol & s) const; + int compare_same_type(const basic & other) const; + unsigned return_type(void) const; + unsigned return_type_tinfo(void) const; + ex expand(unsigned options = 0) const; + + // new virtual functions which can be overridden by derived classes + // none + + // non-virtual functions in this class protected: - ex expand_add(const add & a, int n) const; - ex expand_add_2(const add & a) const; - ex expand_mul(const mul & m, const numeric & n) const; - //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; + ex expand_add(const add & a, int n) const; + ex expand_add_2(const add & a) const; + ex expand_mul(const mul & m, const numeric & n) const; + //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; - static unsigned precedence; + ex basis; + ex exponent; + static unsigned precedence; }; // global constants diff --git a/ginac/pseries.cpp b/ginac/pseries.cpp index f55c0fed..419da735 100644 --- a/ginac/pseries.cpp +++ b/ginac/pseries.cpp @@ -47,43 +47,43 @@ GINAC_IMPLEMENT_REGISTERED_CLASS(pseries, basic) pseries::pseries() : basic(TINFO_pseries) { - debugmsg("pseries default constructor", LOGLEVEL_CONSTRUCT); + debugmsg("pseries default constructor", LOGLEVEL_CONSTRUCT); } pseries::~pseries() { - debugmsg("pseries destructor", LOGLEVEL_DESTRUCT); - destroy(false); + debugmsg("pseries destructor", LOGLEVEL_DESTRUCT); + destroy(false); } pseries::pseries(const pseries &other) { - debugmsg("pseries copy constructor", LOGLEVEL_CONSTRUCT); - copy(other); + debugmsg("pseries copy constructor", LOGLEVEL_CONSTRUCT); + copy(other); } const pseries &pseries::operator=(const pseries & other) { - debugmsg("pseries operator=", LOGLEVEL_ASSIGNMENT); - if (this != &other) { - destroy(true); - copy(other); - } - return *this; + debugmsg("pseries operator=", LOGLEVEL_ASSIGNMENT); + if (this != &other) { + destroy(true); + copy(other); + } + return *this; } void pseries::copy(const pseries &other) { - inherited::copy(other); - seq = other.seq; - var = other.var; - point = other.point; + inherited::copy(other); + seq = other.seq; + var = other.var; + point = other.point; } void pseries::destroy(bool call_parent) { - if (call_parent) - inherited::destroy(call_parent); + if (call_parent) + inherited::destroy(call_parent); } @@ -101,13 +101,13 @@ void pseries::destroy(bool call_parent) * @param ops_ vector of {coefficient, power} pairs (coefficient must not be zero) * @return newly constructed pseries */ pseries::pseries(const ex &rel_, const epvector &ops_) - : basic(TINFO_pseries), seq(ops_) + : basic(TINFO_pseries), seq(ops_) { - debugmsg("pseries constructor 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(); - var = *static_cast(rel_.lhs().bp); + debugmsg("pseries constructor 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(); + var = *static_cast(rel_.lhs().bp); } @@ -118,37 +118,37 @@ pseries::pseries(const ex &rel_, const epvector &ops_) /** 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); - for (unsigned int i=0; true; ++i) { - ex rest; - ex coeff; - if (n.find_ex("coeff", rest, sym_lst, i) && n.find_ex("power", coeff, sym_lst, i)) - seq.push_back(expair(rest, coeff)); - else - break; - } - n.find_ex("var", var, sym_lst); - n.find_ex("point", point, sym_lst); + debugmsg("pseries constructor from archive_node", LOGLEVEL_CONSTRUCT); + for (unsigned int i=0; true; ++i) { + ex rest; + ex coeff; + if (n.find_ex("coeff", rest, sym_lst, i) && n.find_ex("power", coeff, sym_lst, i)) + seq.push_back(expair(rest, coeff)); + else + break; + } + n.find_ex("var", var, sym_lst); + n.find_ex("point", point, sym_lst); } /** Unarchive the object. */ ex pseries::unarchive(const archive_node &n, const lst &sym_lst) { - return (new pseries(n, sym_lst))->setflag(status_flags::dynallocated); + return (new pseries(n, sym_lst))->setflag(status_flags::dynallocated); } /** Archive the object. */ void pseries::archive(archive_node &n) const { - inherited::archive(n); - epvector::const_iterator i = seq.begin(), iend = seq.end(); - while (i != iend) { - n.add_ex("coeff", i->rest); - n.add_ex("power", i->coeff); - ++i; - } - n.add_ex("var", var); - n.add_ex("point", point); + inherited::archive(n); + epvector::const_iterator i = seq.begin(), iend = seq.end(); + while (i != iend) { + n.add_ex("coeff", i->rest); + n.add_ex("power", i->coeff); + ++i; + } + n.add_ex("var", var); + n.add_ex("point", point); } ////////// @@ -157,96 +157,96 @@ void pseries::archive(archive_node &n) const basic *pseries::duplicate() const { - debugmsg("pseries duplicate", LOGLEVEL_DUPLICATE); - return new pseries(*this); + debugmsg("pseries duplicate", LOGLEVEL_DUPLICATE); + return new pseries(*this); } void pseries::print(std::ostream &os, unsigned upper_precedence) const { - debugmsg("pseries print", LOGLEVEL_PRINT); - for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) { - // omit zero terms - if (i->rest.is_zero()) - continue; - // print a sign, if needed - if (i!=seq.begin()) - os << '+'; - if (!is_order_function(i->rest)) { - // print 'rest', i.e. the expansion coefficient - if (i->rest.info(info_flags::numeric) && - i->rest.info(info_flags::positive)) { - os << i->rest; - } else - os << "(" << i->rest << ')'; - // print 'coeff', something like (x-1)^42 - if (!i->coeff.is_zero()) { - os << '*'; - if (!point.is_zero()) - os << '(' << var-point << ')'; - else - os << var; - if (i->coeff.compare(_ex1())) { - os << '^'; - if (i->coeff.info(info_flags::negative)) - os << '(' << i->coeff << ')'; - else - os << i->coeff; - } - } - } else { - os << Order(power(var-point,i->coeff)); - } - } + debugmsg("pseries print", LOGLEVEL_PRINT); + for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) { + // omit zero terms + if (i->rest.is_zero()) + continue; + // print a sign, if needed + if (i!=seq.begin()) + os << '+'; + if (!is_order_function(i->rest)) { + // print 'rest', i.e. the expansion coefficient + if (i->rest.info(info_flags::numeric) && + i->rest.info(info_flags::positive)) { + os << i->rest; + } else + os << "(" << i->rest << ')'; + // print 'coeff', something like (x-1)^42 + if (!i->coeff.is_zero()) { + os << '*'; + if (!point.is_zero()) + os << '(' << var-point << ')'; + else + os << var; + if (i->coeff.compare(_ex1())) { + os << '^'; + if (i->coeff.info(info_flags::negative)) + os << '(' << i->coeff << ')'; + else + os << i->coeff; + } + } + } else { + os << Order(power(var-point,i->coeff)); + } + } } void pseries::printraw(std::ostream &os) const { - debugmsg("pseries printraw", LOGLEVEL_PRINT); - os << "pseries(" << var << ";" << point << ";"; - for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) { - os << "(" << (*i).rest << "," << (*i).coeff << "),"; - } - os << ")"; + debugmsg("pseries printraw", LOGLEVEL_PRINT); + os << "pseries(" << var << ";" << point << ";"; + for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) { + os << "(" << (*i).rest << "," << (*i).coeff << "),"; + } + os << ")"; } void pseries::printtree(std::ostream & os, unsigned indent) const { - debugmsg("pseries printtree",LOGLEVEL_PRINT); - os << std::string(indent,' ') << "pseries " - << ", hash=" << hashvalue - << " (0x" << std::hex << hashvalue << std::dec << ")" - << ", flags=" << flags << std::endl; - for (unsigned i=0; i= seq.size()) - throw (std::out_of_range("op() out of range")); - return seq[i].rest * power(var - point, seq[i].coeff); + if (i < 0 || unsigned(i) >= seq.size()) + throw (std::out_of_range("op() out of range")); + return seq[i].rest * power(var - point, seq[i].coeff); } ex &pseries::let_op(int i) { - throw (std::logic_error("let_op not defined for pseries")); + throw (std::logic_error("let_op not defined for pseries")); } @@ -255,25 +255,25 @@ ex &pseries::let_op(int i) * series is examined termwise. */ int pseries::degree(const symbol &s) const { - if (var.is_equal(s)) { - // Return last exponent - if (seq.size()) - return ex_to_numeric((*(seq.end() - 1)).coeff).to_int(); - else - return 0; - } else { - epvector::const_iterator it = seq.begin(), itend = seq.end(); - if (it == itend) - return 0; - int max_pow = INT_MIN; - while (it != itend) { - int pow = it->rest.degree(s); - if (pow > max_pow) - max_pow = pow; - ++it; - } - return max_pow; - } + if (var.is_equal(s)) { + // Return last exponent + if (seq.size()) + return ex_to_numeric((*(seq.end() - 1)).coeff).to_int(); + else + return 0; + } else { + epvector::const_iterator it = seq.begin(), itend = seq.end(); + if (it == itend) + return 0; + int max_pow = INT_MIN; + while (it != itend) { + int pow = it->rest.degree(s); + if (pow > max_pow) + max_pow = pow; + ++it; + } + return max_pow; + } } /** Return degree of lowest power of the series. This is usually the exponent @@ -283,125 +283,125 @@ int pseries::degree(const symbol &s) const * I.e.: (1-x) + (1-x)^2 + Order((1-x)^3) has ldegree(x) 1, not 0. */ int pseries::ldegree(const symbol &s) const { - if (var.is_equal(s)) { - // Return first exponent - if (seq.size()) - return ex_to_numeric((*(seq.begin())).coeff).to_int(); - else - return 0; - } else { - epvector::const_iterator it = seq.begin(), itend = seq.end(); - if (it == itend) - return 0; - int min_pow = INT_MAX; - while (it != itend) { - int pow = it->rest.ldegree(s); - if (pow < min_pow) - min_pow = pow; - ++it; - } - return min_pow; - } + if (var.is_equal(s)) { + // Return first exponent + if (seq.size()) + return ex_to_numeric((*(seq.begin())).coeff).to_int(); + else + return 0; + } else { + epvector::const_iterator it = seq.begin(), itend = seq.end(); + if (it == itend) + return 0; + int min_pow = INT_MAX; + while (it != itend) { + int pow = it->rest.ldegree(s); + if (pow < min_pow) + min_pow = pow; + ++it; + } + return min_pow; + } } ex pseries::coeff(const symbol &s, int n) const { - if (var.is_equal(s)) { - if (seq.size() == 0) - return _ex0(); - - // Binary search in sequence for given power - numeric looking_for = numeric(n); - int lo = 0, hi = seq.size() - 1; - while (lo <= hi) { - int mid = (lo + hi) / 2; - GINAC_ASSERT(is_ex_exactly_of_type(seq[mid].coeff, numeric)); - int cmp = ex_to_numeric(seq[mid].coeff).compare(looking_for); - switch (cmp) { - case -1: - lo = mid + 1; - break; - case 0: - return seq[mid].rest; - case 1: - hi = mid - 1; - break; - default: - throw(std::logic_error("pseries::coeff: compare() didn't return -1, 0 or 1")); - } - } - return _ex0(); - } else - return convert_to_poly().coeff(s, n); + if (var.is_equal(s)) { + if (seq.size() == 0) + return _ex0(); + + // Binary search in sequence for given power + numeric looking_for = numeric(n); + int lo = 0, hi = seq.size() - 1; + while (lo <= hi) { + int mid = (lo + hi) / 2; + GINAC_ASSERT(is_ex_exactly_of_type(seq[mid].coeff, numeric)); + int cmp = ex_to_numeric(seq[mid].coeff).compare(looking_for); + switch (cmp) { + case -1: + lo = mid + 1; + break; + case 0: + return seq[mid].rest; + case 1: + hi = mid - 1; + break; + default: + throw(std::logic_error("pseries::coeff: compare() didn't return -1, 0 or 1")); + } + } + return _ex0(); + } else + return convert_to_poly().coeff(s, n); } ex pseries::collect(const symbol &s) const { - return *this; + return *this; } /** Evaluate coefficients. */ ex pseries::eval(int level) const { - if (level == 1) - return this->hold(); - - if (level == -max_recursion_level) - throw (std::runtime_error("pseries::eval(): recursion limit exceeded")); - - // Construct a new series with evaluated coefficients - epvector new_seq; - new_seq.reserve(seq.size()); - epvector::const_iterator it = seq.begin(), itend = seq.end(); - while (it != itend) { - new_seq.push_back(expair(it->rest.eval(level-1), it->coeff)); - ++it; - } - return (new pseries(relational(var,point), new_seq))->setflag(status_flags::dynallocated | status_flags::evaluated); + if (level == 1) + return this->hold(); + + if (level == -max_recursion_level) + throw (std::runtime_error("pseries::eval(): recursion limit exceeded")); + + // Construct a new series with evaluated coefficients + epvector new_seq; + new_seq.reserve(seq.size()); + epvector::const_iterator it = seq.begin(), itend = seq.end(); + while (it != itend) { + new_seq.push_back(expair(it->rest.eval(level-1), it->coeff)); + ++it; + } + return (new pseries(relational(var,point), new_seq))->setflag(status_flags::dynallocated | status_flags::evaluated); } /** Evaluate coefficients numerically. */ ex pseries::evalf(int level) const { - if (level == 1) - return *this; - - if (level == -max_recursion_level) - throw (std::runtime_error("pseries::evalf(): recursion limit exceeded")); - - // Construct a new series with evaluated coefficients - epvector new_seq; - new_seq.reserve(seq.size()); - epvector::const_iterator it = seq.begin(), itend = seq.end(); - while (it != itend) { - new_seq.push_back(expair(it->rest.evalf(level-1), it->coeff)); - ++it; - } - return (new pseries(relational(var,point), new_seq))->setflag(status_flags::dynallocated | status_flags::evaluated); + if (level == 1) + return *this; + + if (level == -max_recursion_level) + throw (std::runtime_error("pseries::evalf(): recursion limit exceeded")); + + // Construct a new series with evaluated coefficients + epvector new_seq; + new_seq.reserve(seq.size()); + epvector::const_iterator it = seq.begin(), itend = seq.end(); + while (it != itend) { + new_seq.push_back(expair(it->rest.evalf(level-1), it->coeff)); + ++it; + } + return (new pseries(relational(var,point), new_seq))->setflag(status_flags::dynallocated | status_flags::evaluated); } ex pseries::subs(const lst & ls, const lst & lr) const { - // If expansion variable is being substituted, convert the series to a - // polynomial and do the substitution there because the result might - // no longer be a power series - if (ls.has(var)) - return convert_to_poly(true).subs(ls, lr); - - // Otherwise construct a new series with substituted coefficients and - // expansion point - epvector newseq; - newseq.reserve(seq.size()); - epvector::const_iterator it = seq.begin(), itend = seq.end(); - while (it != itend) { - newseq.push_back(expair(it->rest.subs(ls, lr), it->coeff)); - ++it; - } - return (new pseries(relational(var,point.subs(ls, lr)), newseq))->setflag(status_flags::dynallocated); + // If expansion variable is being substituted, convert the series to a + // polynomial and do the substitution there because the result might + // no longer be a power series + if (ls.has(var)) + return convert_to_poly(true).subs(ls, lr); + + // Otherwise construct a new series with substituted coefficients and + // expansion point + epvector newseq; + newseq.reserve(seq.size()); + epvector::const_iterator it = seq.begin(), itend = seq.end(); + while (it != itend) { + newseq.push_back(expair(it->rest.subs(ls, lr), it->coeff)); + ++it; + } + return (new pseries(relational(var,point.subs(ls, lr)), newseq))->setflag(status_flags::dynallocated); } @@ -410,13 +410,13 @@ ex pseries::subs(const lst & ls, const lst & lr) const * @see ex::diff */ ex pseries::expand(unsigned options) const { - epvector newseq; - newseq.reserve(seq.size()); - for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) - newseq.push_back(expair(i->rest.expand(), i->coeff)); - return (new pseries(relational(var,point), newseq)) - ->setflag(status_flags::dynallocated | - status_flags::expanded); + epvector newseq; + newseq.reserve(seq.size()); + for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) + newseq.push_back(expair(i->rest.expand(), i->coeff)); + return (new pseries(relational(var,point), newseq)) + ->setflag(status_flags::dynallocated | + status_flags::expanded); } @@ -425,25 +425,25 @@ ex pseries::expand(unsigned options) const * @see ex::diff */ ex pseries::derivative(const symbol & s) const { - if (s == var) { - epvector new_seq; - epvector::const_iterator it = seq.begin(), itend = seq.end(); - - // FIXME: coeff might depend on var - while (it != itend) { - if (is_order_function(it->rest)) { - new_seq.push_back(expair(it->rest, it->coeff - 1)); - } else { - ex c = it->rest * it->coeff; - if (!c.is_zero()) - new_seq.push_back(expair(c, it->coeff - 1)); - } - ++it; - } - return pseries(relational(var,point), new_seq); - } else { - return *this; - } + if (s == var) { + epvector new_seq; + epvector::const_iterator it = seq.begin(), itend = seq.end(); + + // FIXME: coeff might depend on var + while (it != itend) { + if (is_order_function(it->rest)) { + new_seq.push_back(expair(it->rest, it->coeff - 1)); + } else { + ex c = it->rest * it->coeff; + if (!c.is_zero()) + new_seq.push_back(expair(c, it->coeff - 1)); + } + ++it; + } + return pseries(relational(var,point), new_seq); + } else { + return *this; + } } @@ -456,25 +456,25 @@ ex pseries::derivative(const symbol & s) const * @param no_order flag: discard higher order terms */ ex pseries::convert_to_poly(bool no_order) const { - ex e; - epvector::const_iterator it = seq.begin(), itend = seq.end(); - - while (it != itend) { - if (is_order_function(it->rest)) { - if (!no_order) - e += Order(power(var - point, it->coeff)); - } else - e += it->rest * power(var - point, it->coeff); - ++it; - } - return e; + ex e; + epvector::const_iterator it = seq.begin(), itend = seq.end(); + + while (it != itend) { + if (is_order_function(it->rest)) { + if (!no_order) + e += Order(power(var - point, it->coeff)); + } else + e += it->rest * power(var - point, it->coeff); + ++it; + } + return e; } /** Returns true if there is no order term, i.e. the series terminates and * false otherwise. */ bool pseries::is_terminating(void) const { - return !is_order_function((seq.end()-1)->rest); + return !is_order_function((seq.end()-1)->rest); } @@ -486,33 +486,33 @@ bool pseries::is_terminating(void) const * @see ex::series */ ex basic::series(const relational & r, int order, unsigned options) const { - epvector seq; - numeric fac(1); - ex deriv = *this; - ex coeff = deriv.subs(r); - const symbol *s = static_cast(r.lhs().bp); - - if (!coeff.is_zero()) - seq.push_back(expair(coeff, numeric(0))); - - int n; - for (n=1; n(r.lhs().bp); + + if (!coeff.is_zero()) + seq.push_back(expair(coeff, numeric(0))); + + int n; + for (n=1; n(r.lhs().bp); - - if (this->is_equal(*s)) { - if (order > 0 && !point.is_zero()) - seq.push_back(expair(point, _ex0())); - if (order > 1) - seq.push_back(expair(_ex1(), _ex1())); - else - seq.push_back(expair(Order(_ex1()), numeric(order))); - } else - seq.push_back(expair(*this, _ex0())); - return pseries(r, seq); + epvector seq; + const ex point = r.rhs(); + GINAC_ASSERT(is_ex_exactly_of_type(r.lhs(),symbol)); + const symbol *s = static_cast(r.lhs().bp); + + if (this->is_equal(*s)) { + if (order > 0 && !point.is_zero()) + seq.push_back(expair(point, _ex0())); + if (order > 1) + seq.push_back(expair(_ex1(), _ex1())); + else + seq.push_back(expair(Order(_ex1()), numeric(order))); + } else + seq.push_back(expair(*this, _ex0())); + return pseries(r, seq); } @@ -545,70 +545,70 @@ ex symbol::series(const relational & r, int order, unsigned options) const * @return the sum as a pseries */ ex pseries::add_series(const pseries &other) const { - // Adding two series with different variables or expansion points - // results in an empty (constant) series - if (!is_compatible_to(other)) { - epvector nul; - nul.push_back(expair(Order(_ex1()), _ex0())); - return pseries(relational(var,point), nul); - } - - // Series addition - epvector new_seq; - epvector::const_iterator a = seq.begin(); - epvector::const_iterator b = other.seq.begin(); - epvector::const_iterator a_end = seq.end(); - epvector::const_iterator b_end = other.seq.end(); - int pow_a = INT_MAX, pow_b = INT_MAX; - for (;;) { - // If a is empty, fill up with elements from b and stop - if (a == a_end) { - while (b != b_end) { - new_seq.push_back(*b); - ++b; - } - break; - } else - pow_a = ex_to_numeric((*a).coeff).to_int(); - - // If b is empty, fill up with elements from a and stop - if (b == b_end) { - while (a != a_end) { - new_seq.push_back(*a); - ++a; - } - break; - } else - pow_b = ex_to_numeric((*b).coeff).to_int(); - - // a and b are non-empty, compare powers - if (pow_a < pow_b) { - // a has lesser power, get coefficient from a - new_seq.push_back(*a); - if (is_order_function((*a).rest)) - break; - ++a; - } else if (pow_b < pow_a) { - // b has lesser power, get coefficient from b - new_seq.push_back(*b); - if (is_order_function((*b).rest)) - break; - ++b; - } else { - // Add coefficient of a and b - if (is_order_function((*a).rest) || is_order_function((*b).rest)) { - new_seq.push_back(expair(Order(_ex1()), (*a).coeff)); - break; // Order term ends the sequence - } else { - ex sum = (*a).rest + (*b).rest; - if (!(sum.is_zero())) - new_seq.push_back(expair(sum, numeric(pow_a))); - ++a; - ++b; - } - } - } - return pseries(relational(var,point), new_seq); + // Adding two series with different variables or expansion points + // results in an empty (constant) series + if (!is_compatible_to(other)) { + epvector nul; + nul.push_back(expair(Order(_ex1()), _ex0())); + return pseries(relational(var,point), nul); + } + + // Series addition + epvector new_seq; + epvector::const_iterator a = seq.begin(); + epvector::const_iterator b = other.seq.begin(); + epvector::const_iterator a_end = seq.end(); + epvector::const_iterator b_end = other.seq.end(); + int pow_a = INT_MAX, pow_b = INT_MAX; + for (;;) { + // If a is empty, fill up with elements from b and stop + if (a == a_end) { + while (b != b_end) { + new_seq.push_back(*b); + ++b; + } + break; + } else + pow_a = ex_to_numeric((*a).coeff).to_int(); + + // If b is empty, fill up with elements from a and stop + if (b == b_end) { + while (a != a_end) { + new_seq.push_back(*a); + ++a; + } + break; + } else + pow_b = ex_to_numeric((*b).coeff).to_int(); + + // a and b are non-empty, compare powers + if (pow_a < pow_b) { + // a has lesser power, get coefficient from a + new_seq.push_back(*a); + if (is_order_function((*a).rest)) + break; + ++a; + } else if (pow_b < pow_a) { + // b has lesser power, get coefficient from b + new_seq.push_back(*b); + if (is_order_function((*b).rest)) + break; + ++b; + } else { + // Add coefficient of a and b + if (is_order_function((*a).rest) || is_order_function((*b).rest)) { + new_seq.push_back(expair(Order(_ex1()), (*a).coeff)); + break; // Order term ends the sequence + } else { + ex sum = (*a).rest + (*b).rest; + if (!(sum.is_zero())) + new_seq.push_back(expair(sum, numeric(pow_a))); + ++a; + ++b; + } + } + } + return pseries(relational(var,point), new_seq); } @@ -617,27 +617,27 @@ ex pseries::add_series(const pseries &other) const * @see ex::series */ ex add::series(const relational & r, int order, unsigned options) const { - ex acc; // Series accumulator - - // Get first term from overall_coeff - acc = overall_coeff.series(r, order, options); - - // Add remaining terms - epvector::const_iterator it = seq.begin(); - epvector::const_iterator itend = seq.end(); - for (; it!=itend; ++it) { - ex op; - if (is_ex_exactly_of_type(it->rest, pseries)) - op = it->rest; - else - op = it->rest.series(r, order, options); - if (!it->coeff.is_equal(_ex1())) - op = ex_to_pseries(op).mul_const(ex_to_numeric(it->coeff)); - - // Series addition - acc = ex_to_pseries(acc).add_series(ex_to_pseries(op)); - } - return acc; + ex acc; // Series accumulator + + // Get first term from overall_coeff + acc = overall_coeff.series(r, order, options); + + // Add remaining terms + epvector::const_iterator it = seq.begin(); + epvector::const_iterator itend = seq.end(); + for (; it!=itend; ++it) { + ex op; + if (is_ex_exactly_of_type(it->rest, pseries)) + op = it->rest; + else + op = it->rest.series(r, order, options); + if (!it->coeff.is_equal(_ex1())) + op = ex_to_pseries(op).mul_const(ex_to_numeric(it->coeff)); + + // Series addition + acc = ex_to_pseries(acc).add_series(ex_to_pseries(op)); + } + return acc; } @@ -648,18 +648,18 @@ ex add::series(const relational & r, int order, unsigned options) const * @return the product as a pseries */ ex pseries::mul_const(const numeric &other) const { - epvector new_seq; - new_seq.reserve(seq.size()); - - epvector::const_iterator it = seq.begin(), itend = seq.end(); - while (it != itend) { - if (!is_order_function(it->rest)) - new_seq.push_back(expair(it->rest * other, it->coeff)); - else - new_seq.push_back(*it); - ++it; - } - return pseries(relational(var,point), new_seq); + epvector new_seq; + new_seq.reserve(seq.size()); + + epvector::const_iterator it = seq.begin(), itend = seq.end(); + while (it != itend) { + if (!is_order_function(it->rest)) + new_seq.push_back(expair(it->rest * other, it->coeff)); + else + new_seq.push_back(*it); + ++it; + } + return pseries(relational(var,point), new_seq); } @@ -670,50 +670,50 @@ ex pseries::mul_const(const numeric &other) const * @return the product as a pseries */ ex pseries::mul_series(const pseries &other) const { - // Multiplying two series with different variables or expansion points - // results in an empty (constant) series - if (!is_compatible_to(other)) { - epvector nul; - nul.push_back(expair(Order(_ex1()), _ex0())); - return pseries(relational(var,point), nul); - } - - // Series multiplication - epvector new_seq; - - const symbol *s = static_cast(var.bp); - int a_max = degree(*s); - int b_max = other.degree(*s); - int a_min = ldegree(*s); - int b_min = other.ldegree(*s); - int cdeg_min = a_min + b_min; - int cdeg_max = a_max + b_max; - - int higher_order_a = INT_MAX; - int higher_order_b = INT_MAX; - if (is_order_function(coeff(*s, a_max))) - higher_order_a = a_max + b_min; - if (is_order_function(other.coeff(*s, b_max))) - higher_order_b = b_max + a_min; - int higher_order_c = std::min(higher_order_a, higher_order_b); - if (cdeg_max >= higher_order_c) - cdeg_max = higher_order_c - 1; - - for (int cdeg=cdeg_min; cdeg<=cdeg_max; ++cdeg) { - ex co = _ex0(); - // c(i)=a(0)b(i)+...+a(i)b(0) - for (int i=a_min; cdeg-i>=b_min; ++i) { - ex a_coeff = coeff(*s, i); - ex b_coeff = other.coeff(*s, cdeg-i); - if (!is_order_function(a_coeff) && !is_order_function(b_coeff)) - co += a_coeff * b_coeff; - } - if (!co.is_zero()) - new_seq.push_back(expair(co, numeric(cdeg))); - } - if (higher_order_c < INT_MAX) - new_seq.push_back(expair(Order(_ex1()), numeric(higher_order_c))); - return pseries(relational(var,point), new_seq); + // Multiplying two series with different variables or expansion points + // results in an empty (constant) series + if (!is_compatible_to(other)) { + epvector nul; + nul.push_back(expair(Order(_ex1()), _ex0())); + return pseries(relational(var,point), nul); + } + + // Series multiplication + epvector new_seq; + + const symbol *s = static_cast(var.bp); + int a_max = degree(*s); + int b_max = other.degree(*s); + int a_min = ldegree(*s); + int b_min = other.ldegree(*s); + int cdeg_min = a_min + b_min; + int cdeg_max = a_max + b_max; + + int higher_order_a = INT_MAX; + int higher_order_b = INT_MAX; + if (is_order_function(coeff(*s, a_max))) + higher_order_a = a_max + b_min; + if (is_order_function(other.coeff(*s, b_max))) + higher_order_b = b_max + a_min; + int higher_order_c = std::min(higher_order_a, higher_order_b); + if (cdeg_max >= higher_order_c) + cdeg_max = higher_order_c - 1; + + for (int cdeg=cdeg_min; cdeg<=cdeg_max; ++cdeg) { + ex co = _ex0(); + // c(i)=a(0)b(i)+...+a(i)b(0) + for (int i=a_min; cdeg-i>=b_min; ++i) { + ex a_coeff = coeff(*s, i); + ex b_coeff = other.coeff(*s, cdeg-i); + if (!is_order_function(a_coeff) && !is_order_function(b_coeff)) + co += a_coeff * b_coeff; + } + if (!co.is_zero()) + new_seq.push_back(expair(co, numeric(cdeg))); + } + if (higher_order_c < INT_MAX) + new_seq.push_back(expair(Order(_ex1()), numeric(higher_order_c))); + return pseries(relational(var,point), new_seq); } @@ -722,30 +722,30 @@ ex pseries::mul_series(const pseries &other) const * @see ex::series */ ex mul::series(const relational & r, int order, unsigned options) const { - ex acc; // Series accumulator - - // Get first term from overall_coeff - acc = overall_coeff.series(r, order, options); - - // Multiply with remaining terms - epvector::const_iterator it = seq.begin(); - epvector::const_iterator itend = seq.end(); - for (; it!=itend; ++it) { - ex op = it->rest; - if (op.info(info_flags::numeric)) { - // series * const (special case, faster) - ex f = power(op, it->coeff); - acc = ex_to_pseries(acc).mul_const(ex_to_numeric(f)); - continue; - } else if (!is_ex_exactly_of_type(op, pseries)) - op = op.series(r, order, options); - if (!it->coeff.is_equal(_ex1())) - op = ex_to_pseries(op).power_const(ex_to_numeric(it->coeff), order); - - // Series multiplication - acc = ex_to_pseries(acc).mul_series(ex_to_pseries(op)); - } - return acc; + ex acc; // Series accumulator + + // Get first term from overall_coeff + acc = overall_coeff.series(r, order, options); + + // Multiply with remaining terms + epvector::const_iterator it = seq.begin(); + epvector::const_iterator itend = seq.end(); + for (; it!=itend; ++it) { + ex op = it->rest; + if (op.info(info_flags::numeric)) { + // series * const (special case, faster) + ex f = power(op, it->coeff); + acc = ex_to_pseries(acc).mul_const(ex_to_numeric(f)); + continue; + } else if (!is_ex_exactly_of_type(op, pseries)) + op = op.series(r, order, options); + if (!it->coeff.is_equal(_ex1())) + op = ex_to_pseries(op).power_const(ex_to_numeric(it->coeff), order); + + // Series multiplication + acc = ex_to_pseries(acc).mul_series(ex_to_pseries(op)); + } + return acc; } @@ -755,55 +755,55 @@ ex mul::series(const relational & r, int order, unsigned options) const * @param deg truncation order of series calculation */ ex pseries::power_const(const numeric &p, int deg) const { - int i; - const symbol *s = static_cast(var.bp); - int ldeg = ldegree(*s); - - // Calculate coefficients of powered series - exvector co; - co.reserve(deg); - ex co0; - co.push_back(co0 = power(coeff(*s, ldeg), p)); - bool all_sums_zero = true; - for (i=1; i(var.bp); + int ldeg = ldegree(*s); + + // Calculate coefficients of powered series + exvector co; + co.reserve(deg); + ex co0; + co.push_back(co0 = power(coeff(*s, ldeg), p)); + bool all_sums_zero = true; + for (i=1; icoeff = i->coeff + deg; - return pseries(relational(var, point), newseq); + epvector newseq(seq); + for (epvector::iterator i=newseq.begin(); i!=newseq.end(); ++i) + i->coeff = i->coeff + deg; + return pseries(relational(var, point), newseq); } @@ -812,54 +812,54 @@ pseries pseries::shift_exponents(int deg) const * @see ex::series */ ex power::series(const relational & r, int order, unsigned options) const { - ex e; - if (!is_ex_exactly_of_type(basis, pseries)) { - // Basis is not a series, may there be a singulary? - if (!exponent.info(info_flags::negint)) - return basic::series(r, order, options); - - // Expression is of type something^(-int), check for singularity - if (!basis.subs(r).is_zero()) - return basic::series(r, order, options); - - // Singularity encountered, expand basis into series - e = basis.series(r, order, options); - } else { - // Basis is a series - e = basis; - } - - // Power e - return ex_to_pseries(e).power_const(ex_to_numeric(exponent), order); + ex e; + if (!is_ex_exactly_of_type(basis, pseries)) { + // Basis is not a series, may there be a singulary? + if (!exponent.info(info_flags::negint)) + return basic::series(r, order, options); + + // Expression is of type something^(-int), check for singularity + if (!basis.subs(r).is_zero()) + return basic::series(r, order, options); + + // Singularity encountered, expand basis into series + e = basis.series(r, order, options); + } else { + // Basis is a series + e = basis; + } + + // Power e + return ex_to_pseries(e).power_const(ex_to_numeric(exponent), order); } /** Re-expansion of a pseries object. */ ex pseries::series(const relational & r, int order, unsigned options) const { - const ex p = r.rhs(); - GINAC_ASSERT(is_ex_exactly_of_type(r.lhs(),symbol)); - const symbol *s = static_cast(r.lhs().bp); - - if (var.is_equal(*s) && point.is_equal(p)) { - if (order > degree(*s)) - return *this; - else { - epvector new_seq; - epvector::const_iterator it = seq.begin(), itend = seq.end(); - while (it != itend) { - int o = ex_to_numeric(it->coeff).to_int(); - if (o >= order) { - new_seq.push_back(expair(Order(_ex1()), o)); - break; - } - new_seq.push_back(*it); - ++it; - } - return pseries(r, new_seq); - } - } else - return convert_to_poly().series(r, order, options); + const ex p = r.rhs(); + GINAC_ASSERT(is_ex_exactly_of_type(r.lhs(),symbol)); + const symbol *s = static_cast(r.lhs().bp); + + if (var.is_equal(*s) && point.is_equal(p)) { + if (order > degree(*s)) + return *this; + else { + epvector new_seq; + epvector::const_iterator it = seq.begin(), itend = seq.end(); + while (it != itend) { + int o = ex_to_numeric(it->coeff).to_int(); + if (o >= order) { + new_seq.push_back(expair(Order(_ex1()), o)); + break; + } + new_seq.push_back(*it); + ++it; + } + return pseries(r, new_seq); + } + } else + return convert_to_poly().series(r, order, options); } @@ -874,23 +874,23 @@ ex pseries::series(const relational & r, int order, unsigned options) const * @return an expression holding a pseries object */ ex ex::series(const ex & r, int order, unsigned options) const { - GINAC_ASSERT(bp!=0); - ex e; - relational rel_; - - if (is_ex_exactly_of_type(r,relational)) - rel_ = ex_to_relational(r); - else if (is_ex_exactly_of_type(r,symbol)) - rel_ = relational(r,_ex0()); - else - throw (std::logic_error("ex::series(): expansion point has unknown type")); - - try { - e = bp->series(rel_, order, options); - } catch (std::exception &x) { - throw (std::logic_error(std::string("unable to compute series (") + x.what() + ")")); - } - return e; + GINAC_ASSERT(bp!=0); + ex e; + relational rel_; + + if (is_ex_exactly_of_type(r,relational)) + rel_ = ex_to_relational(r); + else if (is_ex_exactly_of_type(r,symbol)) + rel_ = relational(r,_ex0()); + else + throw (std::logic_error("ex::series(): expansion point has unknown type")); + + try { + e = bp->series(rel_, order, options); + } catch (std::exception &x) { + throw (std::logic_error(std::string("unable to compute series (") + x.what() + ")")); + } + return e; } diff --git a/ginac/pseries.h b/ginac/pseries.h index 48975724..eb0ef77d 100644 --- a/ginac/pseries.h +++ b/ginac/pseries.h @@ -36,65 +36,65 @@ namespace GiNaC { * Other classes must provide members to convert into this type. */ class pseries : public basic { - GINAC_DECLARE_REGISTERED_CLASS(pseries, basic) + GINAC_DECLARE_REGISTERED_CLASS(pseries, basic) - // default constructor, destructor, copy constructor, assignment operator and helpers + // default constructor, destructor, copy constructor, assignment operator and helpers public: - pseries(); - ~pseries(); - pseries(const pseries &other); - const pseries &operator=(const pseries &other); + pseries(); + ~pseries(); + pseries(const pseries &other); + const pseries &operator=(const pseries &other); protected: - void copy(const pseries &other); - void destroy(bool call_parent); + void copy(const pseries &other); + void destroy(bool call_parent); - // other constructors + // other constructors public: - pseries(const ex &rel_, const epvector &ops_); + pseries(const ex &rel_, const epvector &ops_); - // functions overriding virtual functions from base classes + // functions overriding virtual functions from base classes public: - basic *duplicate() 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; - unsigned nops(void) const; - ex op(int i) const; - ex &let_op(int i); - int degree(const symbol &s) const; - int ldegree(const symbol &s) const; - ex coeff(const symbol &s, int n = 1) const; - ex collect(const symbol &s) const; - ex eval(int level=0) const; - ex evalf(int level=0) const; - ex series(const relational & r, int order, unsigned options = 0) const; - ex subs(const lst & ls, const lst & lr) const; - ex normal(lst &sym_lst, lst &repl_lst, int level = 0) const; - ex expand(unsigned options = 0) const; + basic *duplicate() 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; + unsigned nops(void) const; + ex op(int i) const; + ex &let_op(int i); + int degree(const symbol &s) const; + int ldegree(const symbol &s) const; + ex coeff(const symbol &s, int n = 1) const; + ex collect(const symbol &s) const; + ex eval(int level=0) const; + ex evalf(int level=0) const; + ex series(const relational & r, int order, unsigned options = 0) const; + ex subs(const lst & ls, const lst & lr) const; + ex normal(lst &sym_lst, lst &repl_lst, int level = 0) const; + ex expand(unsigned options = 0) const; protected: - ex derivative(const symbol & s) const; + ex derivative(const symbol & s) const; - // non-virtual functions in this class + // non-virtual functions in this class public: - ex convert_to_poly(bool no_order = false) const; - bool is_compatible_to(const pseries &other) const {return var.compare(other.var) == 0 && point.compare(other.point) == 0;} - bool is_zero(void) const {return seq.size() == 0;} - bool is_terminating(void) const; - ex add_series(const pseries &other) const; - ex mul_const(const numeric &other) const; - ex mul_series(const pseries &other) const; - ex power_const(const numeric &p, int deg) const; - pseries shift_exponents(int deg) const; + ex convert_to_poly(bool no_order = false) const; + bool is_compatible_to(const pseries &other) const {return var.compare(other.var) == 0 && point.compare(other.point) == 0;} + bool is_zero(void) const {return seq.size() == 0;} + bool is_terminating(void) const; + ex add_series(const pseries &other) const; + ex mul_const(const numeric &other) const; + ex mul_series(const pseries &other) const; + ex power_const(const numeric &p, int deg) const; + pseries shift_exponents(int deg) const; protected: - /** Vector of {coefficient, power} pairs */ - epvector seq; + /** Vector of {coefficient, power} pairs */ + epvector seq; - /** Series variable (holds a symbol) */ - ex var; + /** Series variable (holds a symbol) */ + ex var; - /** Expansion point */ - ex point; + /** Expansion point */ + ex point; }; // global constants @@ -110,7 +110,7 @@ extern const type_info & typeid_pseries; * @see is_ex_of_type */ inline const pseries &ex_to_pseries(const ex &e) { - return static_cast(*e.bp); + return static_cast(*e.bp); } /** Convert the pseries object embedded in an expression to an ordinary @@ -123,12 +123,12 @@ inline const pseries &ex_to_pseries(const ex &e) * @see pseries::convert_to_poly */ inline ex series_to_poly(const ex &e) { - return (static_cast(*e.bp).convert_to_poly(true)); + return (static_cast(*e.bp).convert_to_poly(true)); } inline bool is_terminating(const pseries & s) { - return s.is_terminating(); + return s.is_terminating(); } #ifndef NO_NAMESPACE_GINAC diff --git a/ginac/registrar.h b/ginac/registrar.h index 8c2e6d68..8eb4d31d 100644 --- a/ginac/registrar.h +++ b/ginac/registrar.h @@ -45,37 +45,37 @@ extern registered_class_info *first_registered_class; /** This structure stores information about a registered GiNaC class. */ struct registered_class_info { - registered_class_info(const char *n, const char *s, unsigned int k, unarch_func f) - : name(n), super(s), tinfo_key(k), unarchive(f) - { - // Add structure to list - next = first_registered_class; - first_registered_class = this; - } - - registered_class_info *next; /**< Pointer to next registered_class_info in list. */ - const char *name; /**< Class name. */ - const char *super; /**< Name of superclass. */ - unsigned int tinfo_key; /**< TINFO_* key. */ - unarch_func unarchive; /**< Pointer to unarchiving function. */ + registered_class_info(const char *n, const char *s, unsigned int k, unarch_func f) + : name(n), super(s), tinfo_key(k), unarchive(f) + { + // Add structure to list + next = first_registered_class; + first_registered_class = this; + } + + registered_class_info *next; /**< Pointer to next registered_class_info in list. */ + const char *name; /**< Class name. */ + const char *super; /**< Name of superclass. */ + unsigned int tinfo_key; /**< TINFO_* key. */ + unarch_func unarchive; /**< Pointer to unarchiving function. */ }; /** Macro for inclusion in the declaration of each registered class. */ #define GINAC_DECLARE_REGISTERED_CLASS(classname, supername) \ public: \ - typedef supername inherited; \ - static registered_class_info reg_info; \ - virtual const char *class_name(void) const; \ - classname(const archive_node &n, const lst &sym_lst); \ - virtual void archive(archive_node &n) const; \ - static ex unarchive(const archive_node &n, const lst &sym_lst); \ + typedef supername inherited; \ + static registered_class_info reg_info; \ + virtual const char *class_name(void) const; \ + classname(const archive_node &n, const lst &sym_lst); \ + virtual void archive(archive_node &n) const; \ + static ex unarchive(const archive_node &n, const lst &sym_lst); \ private: /** Macro for inclusion in the implementation of each registered class. */ #define GINAC_IMPLEMENT_REGISTERED_CLASS(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;} + registered_class_info classname::reg_info(#classname, #supername, TINFO_##classname, &classname::unarchive); \ + const char *classname::class_name(void) const {return reg_info.name;} /** Find TINFO_* key by class name. */ diff --git a/ginac/relational.cpp b/ginac/relational.cpp index b2726acd..a71a90af 100644 --- a/ginac/relational.cpp +++ b/ginac/relational.cpp @@ -42,44 +42,44 @@ GINAC_IMPLEMENT_REGISTERED_CLASS(relational, basic) relational::relational() : basic(TINFO_relational) { - debugmsg("relational default constructor",LOGLEVEL_CONSTRUCT); + debugmsg("relational default constructor",LOGLEVEL_CONSTRUCT); } relational::~relational() { - debugmsg("relational destructor",LOGLEVEL_DESTRUCT); - destroy(0); + debugmsg("relational destructor",LOGLEVEL_DESTRUCT); + destroy(0); } relational::relational(const relational & other) { - debugmsg("relational copy constructor",LOGLEVEL_CONSTRUCT); - copy(other); + debugmsg("relational copy constructor",LOGLEVEL_CONSTRUCT); + copy(other); } const relational & relational::operator=(const relational & other) { - debugmsg("relational operator=",LOGLEVEL_ASSIGNMENT); - if (this != &other) { - destroy(1); - copy(other); - } - return *this; + debugmsg("relational operator=",LOGLEVEL_ASSIGNMENT); + if (this != &other) { + destroy(1); + copy(other); + } + return *this; } // protected void relational::copy(const relational & other) { - basic::copy(other); - lh=other.lh; - rh=other.rh; - o=other.o; + basic::copy(other); + lh=other.lh; + rh=other.rh; + o=other.o; } void relational::destroy(bool call_parent) { - if (call_parent) basic::destroy(call_parent); + if (call_parent) basic::destroy(call_parent); } ////////// @@ -90,10 +90,10 @@ void relational::destroy(bool call_parent) relational::relational(const ex & lhs, const ex & rhs, operators oper) : basic(TINFO_relational) { - debugmsg("relational constructor ex,ex,operator",LOGLEVEL_CONSTRUCT); - lh=lhs; - rh=rhs; - o=oper; + debugmsg("relational constructor ex,ex,operator",LOGLEVEL_CONSTRUCT); + lh=lhs; + rh=rhs; + o=oper; } ////////// @@ -103,28 +103,28 @@ 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); - unsigned int opi; - if (!(n.find_unsigned("op", opi))) - throw (std::runtime_error("unknown relational operator in archive")); - o = (operators)opi; - n.find_ex("lh", lh, sym_lst); - n.find_ex("rh", rh, sym_lst); + debugmsg("relational constructor from archive_node", LOGLEVEL_CONSTRUCT); + unsigned int opi; + if (!(n.find_unsigned("op", opi))) + throw (std::runtime_error("unknown relational operator in archive")); + o = (operators)opi; + n.find_ex("lh", lh, sym_lst); + n.find_ex("rh", rh, sym_lst); } /** Unarchive the object. */ ex relational::unarchive(const archive_node &n, const lst &sym_lst) { - return (new relational(n, sym_lst))->setflag(status_flags::dynallocated); + return (new relational(n, sym_lst))->setflag(status_flags::dynallocated); } /** Archive the object. */ void relational::archive(archive_node &n) const { - inherited::archive(n); - n.add_ex("lh", lh); - n.add_ex("rh", rh); - n.add_unsigned("op", o); + inherited::archive(n); + n.add_ex("lh", lh); + n.add_ex("rh", rh); + n.add_unsigned("op", o); } ////////// @@ -135,213 +135,213 @@ void relational::archive(archive_node &n) const basic * relational::duplicate() const { - debugmsg("relational duplicate",LOGLEVEL_DUPLICATE); - return new relational(*this); + debugmsg("relational duplicate",LOGLEVEL_DUPLICATE); + return new relational(*this); } void relational::print(std::ostream & os, unsigned upper_precedence) const { - debugmsg("relational print",LOGLEVEL_PRINT); - if (precedence<=upper_precedence) os << "("; - lh.print(os,precedence); - switch (o) { - case equal: - os << "=="; - break; - case not_equal: - os << "!="; - break; - case less: - os << "<"; - break; - case less_or_equal: - os << "<="; - break; - case greater: - os << ">"; - break; - case greater_or_equal: - os << ">="; - break; - default: - os << "(INVALID RELATIONAL OPERATOR)"; - } - rh.print(os,precedence); - if (precedence<=upper_precedence) os << ")"; + debugmsg("relational print",LOGLEVEL_PRINT); + if (precedence<=upper_precedence) os << "("; + lh.print(os,precedence); + switch (o) { + case equal: + os << "=="; + break; + case not_equal: + os << "!="; + break; + case less: + os << "<"; + break; + case less_or_equal: + os << "<="; + break; + case greater: + os << ">"; + break; + case greater_or_equal: + os << ">="; + break; + default: + os << "(INVALID RELATIONAL OPERATOR)"; + } + rh.print(os,precedence); + if (precedence<=upper_precedence) os << ")"; } void relational::printraw(std::ostream & os) const { - debugmsg("relational printraw",LOGLEVEL_PRINT); - os << "RELATIONAL("; - lh.printraw(os); - os << ","; - rh.printraw(os); - os << ","; - switch (o) { - case equal: - os << "=="; - break; - case not_equal: - os << "!="; - break; - case less: - os << "<"; - break; - case less_or_equal: - os << "<="; - break; - case greater: - os << ">"; - break; - case greater_or_equal: - os << ">="; - break; - default: - os << "(INVALID RELATIONAL OPERATOR)"; - } - os << ")"; + debugmsg("relational printraw",LOGLEVEL_PRINT); + os << "RELATIONAL("; + lh.printraw(os); + os << ","; + rh.printraw(os); + os << ","; + switch (o) { + case equal: + os << "=="; + break; + case not_equal: + os << "!="; + break; + case less: + os << "<"; + break; + case less_or_equal: + os << "<="; + break; + case greater: + os << ">"; + break; + case greater_or_equal: + os << ">="; + break; + default: + os << "(INVALID RELATIONAL OPERATOR)"; + } + os << ")"; } void relational::printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const { - debugmsg("relational print csrc", LOGLEVEL_PRINT); - if (precedence<=upper_precedence) - os << "("; - - // Print left-hand expression - lh.bp->printcsrc(os, type, precedence); - - // Print relational operator - switch (o) { - case equal: - os << "=="; - break; - case not_equal: - os << "!="; - break; - case less: - os << "<"; - break; - case less_or_equal: - os << "<="; - break; - case greater: - os << ">"; - break; - case greater_or_equal: - os << ">="; - break; - default: - os << "(INVALID RELATIONAL OPERATOR)"; - break; - } - - // Print right-hand operator - rh.bp->printcsrc(os, type, precedence); - - if (precedence <= upper_precedence) - os << ")"; + debugmsg("relational print csrc", LOGLEVEL_PRINT); + if (precedence<=upper_precedence) + os << "("; + + // Print left-hand expression + lh.bp->printcsrc(os, type, precedence); + + // Print relational operator + switch (o) { + case equal: + os << "=="; + break; + case not_equal: + os << "!="; + break; + case less: + os << "<"; + break; + case less_or_equal: + os << "<="; + break; + case greater: + os << ">"; + break; + case greater_or_equal: + os << ">="; + break; + default: + os << "(INVALID RELATIONAL OPERATOR)"; + break; + } + + // Print right-hand operator + rh.bp->printcsrc(os, type, precedence); + + if (precedence <= upper_precedence) + os << ")"; } bool relational::info(unsigned inf) const { - switch (inf) { - case info_flags::relation: - return 1; - case info_flags::relation_equal: - return o==equal; - case info_flags::relation_not_equal: - return o==not_equal; - case info_flags::relation_less: - return o==less; - case info_flags::relation_less_or_equal: - return o==less_or_equal; - case info_flags::relation_greater: - return o==greater; - case info_flags::relation_greater_or_equal: - return o==greater_or_equal; - } - return 0; + switch (inf) { + case info_flags::relation: + return 1; + case info_flags::relation_equal: + return o==equal; + case info_flags::relation_not_equal: + return o==not_equal; + case info_flags::relation_less: + return o==less; + case info_flags::relation_less_or_equal: + return o==less_or_equal; + case info_flags::relation_greater: + return o==greater; + case info_flags::relation_greater_or_equal: + return o==greater_or_equal; + } + return 0; } unsigned relational::nops() const { - return 2; + return 2; } ex & relational::let_op(int i) { - GINAC_ASSERT(i>=0); - GINAC_ASSERT(i<2); + GINAC_ASSERT(i>=0); + GINAC_ASSERT(i<2); - return i==0 ? lh : rh; + return i==0 ? lh : rh; } - + ex relational::eval(int level) const { - if (level==1) { - return this->hold(); - } - 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 ); + if (level==1) { + return this->hold(); + } + 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 ); } ex relational::evalf(int level) const { - if (level==1) { - return *this; - } - 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); + if (level==1) { + return *this; + } + 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); } ex relational::simplify_ncmul(const exvector & v) const { - return lh.simplify_ncmul(v); + return lh.simplify_ncmul(v); } // protected int relational::compare_same_type(const basic & other) const { - GINAC_ASSERT(is_exactly_of_type(other, relational)); - const relational & oth=static_cast(const_cast(other)); - - int cmpval; - - if (o == oth.o) { - cmpval=lh.compare(oth.lh); - if (cmpval==0) { - return rh.compare(oth.rh); - } else { - return cmpval; - } - } - if (o(const_cast(other)); + + int cmpval; + + if (o == oth.o) { + cmpval=lh.compare(oth.lh); + if (cmpval==0) { + return rh.compare(oth.rh); + } else { + return cmpval; + } + } + if (o=b) == true - // a false result means the comparison is either false or undecidable - // (except for !=, where true means unequal or undecidable) - ex df=lh-rh; - if (!is_ex_exactly_of_type(df,numeric)) { - return o==not_equal ? true : false; // cannot decide on non-numerical results - } - int cmpval=ex_to_numeric(df).compare(_num0()); - switch (o) { - case equal: - return cmpval==0; - break; - case not_equal: - return cmpval!=0; - break; - case less: - return cmpval<0; - break; - case less_or_equal: - return cmpval<=0; - break; - case greater: - return cmpval>0; - break; - case greater_or_equal: - return cmpval>=0; - break; - default: - throw(std::logic_error("invalid relational operator")); - } - return 0; + // please note that (a=b) == true + // a false result means the comparison is either false or undecidable + // (except for !=, where true means unequal or undecidable) + ex df=lh-rh; + if (!is_ex_exactly_of_type(df,numeric)) { + return o==not_equal ? true : false; // cannot decide on non-numerical results + } + int cmpval=ex_to_numeric(df).compare(_num0()); + switch (o) { + case equal: + return cmpval==0; + break; + case not_equal: + return cmpval!=0; + break; + case less: + return cmpval<0; + break; + case less_or_equal: + return cmpval<=0; + break; + case greater: + return cmpval>0; + break; + case greater_or_equal: + return cmpval>=0; + break; + default: + throw(std::logic_error("invalid relational operator")); + } + return 0; } ////////// diff --git a/ginac/relational.h b/ginac/relational.h index 48b59719..118e494c 100644 --- a/ginac/relational.h +++ b/ginac/relational.h @@ -34,68 +34,68 @@ namespace GiNaC { * relation between them. */ class relational : public basic { - GINAC_DECLARE_REGISTERED_CLASS(relational, basic) + GINAC_DECLARE_REGISTERED_CLASS(relational, basic) // types public: - enum operators { equal, - not_equal, - less, - less_or_equal, - greater, - greater_or_equal - }; - + enum operators { equal, + not_equal, + less, + less_or_equal, + greater, + greater_or_equal + }; + // member functions - // default constructor, destructor, copy constructor assignment operator and helpers + // default constructor, destructor, copy constructor assignment operator and helpers public: - relational(); - ~relational(); - relational(const relational & other); - const relational & operator=(const relational & other); + relational(); + ~relational(); + relational(const relational & other); + const relational & operator=(const relational & other); protected: - void copy(const relational & other); - void destroy(bool call_parent); + void copy(const relational & other); + void destroy(bool call_parent); - // other constructors + // other constructors public: - relational(const ex & lhs, const ex & rhs, operators oper=equal); - - // functions overriding virtual functions from bases classes + relational(const ex & lhs, const ex & rhs, operators oper=equal); + + // functions overriding virtual functions from bases classes public: - basic * duplicate() const; - void print(std::ostream & os, unsigned upper_precedence=0) const; - void printraw(std::ostream & os) const; - void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence=0) const; - bool info(unsigned inf) const; - unsigned nops() const; - ex & let_op(int i); - 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 simplify_ncmul(const exvector & v) const; + basic * duplicate() const; + void print(std::ostream & os, unsigned upper_precedence=0) const; + void printraw(std::ostream & os) const; + void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence=0) const; + bool info(unsigned inf) const; + unsigned nops() const; + ex & let_op(int i); + 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 simplify_ncmul(const exvector & v) const; protected: - int compare_same_type(const basic & other) const; - unsigned return_type(void) const; - unsigned return_type_tinfo(void) const; + int compare_same_type(const basic & other) const; + unsigned return_type(void) const; + unsigned return_type_tinfo(void) const; - // new virtual functions which can be overridden by derived classes + // new virtual functions which can be overridden by derived classes public: - virtual ex lhs(void) const; - virtual ex rhs(void) const; + virtual ex lhs(void) const; + virtual ex rhs(void) const; - // non-virtual functions in this class + // non-virtual functions in this class public: - operator bool(void) const; - + operator bool(void) const; + // member variables - + protected: - ex lh; - ex rh; - operators o; - static unsigned precedence; + ex lh; + ex rh; + operators o; + static unsigned precedence; }; // global constants diff --git a/ginac/remember.cpp b/ginac/remember.cpp index 21e19716..2c442162 100644 --- a/ginac/remember.cpp +++ b/ginac/remember.cpp @@ -36,22 +36,22 @@ namespace GiNaC { ////////// remember_table_entry::remember_table_entry(function const & f, ex const & r) : - hashvalue(f.gethash()), seq(f.seq), result(r) + hashvalue(f.gethash()), seq(f.seq), result(r) { - ++last_access=access_counter; - successful_hits=0; + ++last_access=access_counter; + successful_hits=0; } bool remember_table_entry::is_equal(function const & f) const { - GINAC_ASSERT(f.seq.size()==seq.size()); - if (f.gethash()!=hashvalue) return false; - for (unsigned i=0; i=max_assoc_size)) { - // table is full, we must delete an older entry - GINAC_ASSERT(size()>0); // there must be at least one entry + 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 - switch (remember_strategy) { - case remember_strategies::delete_cyclic: - // delete oldest entry (first in list) - erase(begin()); - break; - case remember_strategies::delete_lru: - { - // delete least recently used entry - iterator it=begin(); - iterator lowest_access_it=it; - unsigned long lowest_access=it->get_last_access(); - ++it; - while (it!=end()) { - if (it->get_last_access()get_last_access(); - lowest_access_it=it; - } - ++it; - } - erase(lowest_access_it); - } - break; - case remember_strategies::delete_lfu: - { - // delete least frequently used entry - iterator it=begin(); - iterator lowest_hits_it=it; - unsigned lowest_hits=it->get_successful_hits(); - ++it; - while (it!=end()) { - if (it->get_successful_hits()get_successful_hits(); - lowest_hits_it=it; - } - ++it; - } - erase(lowest_hits_it); - } - break; - default: - throw(std::logic_error("remember_table_list::add_entry(): invalid remember_strategy")); - } - GINAC_ASSERT(size()==max_assoc_size-1); - } - push_back(remember_table_entry(f,result)); + switch (remember_strategy) { + case remember_strategies::delete_cyclic: + // delete oldest entry (first in list) + erase(begin()); + break; + case remember_strategies::delete_lru: + { + // delete least recently used entry + iterator it=begin(); + iterator lowest_access_it=it; + unsigned long lowest_access=it->get_last_access(); + ++it; + while (it!=end()) { + if (it->get_last_access()get_last_access(); + lowest_access_it=it; + } + ++it; + } + erase(lowest_access_it); + } + break; + case remember_strategies::delete_lfu: + { + // delete least frequently used entry + iterator it=begin(); + iterator lowest_hits_it=it; + unsigned lowest_hits=it->get_successful_hits(); + ++it; + while (it!=end()) { + if (it->get_successful_hits()get_successful_hits(); + lowest_hits_it=it; + } + ++it; + } + erase(lowest_hits_it); + } + break; + default: + throw(std::logic_error("remember_table_list::add_entry(): invalid remember_strategy")); + } + GINAC_ASSERT(size()==max_assoc_size-1); + } + push_back(remember_table_entry(f,result)); } bool remember_table_list::lookup_entry(function const & f, ex & result) const { - for (const_iterator cit=begin(); cit!=end(); ++cit) { - if (cit->is_equal(f)) { - result=cit->get_result(); - return true; - } - } - return false; + for (const_iterator cit=begin(); cit!=end(); ++cit) { + if (cit->is_equal(f)) { + result=cit->get_result(); + return true; + } + } + return false; } ////////// @@ -139,54 +139,54 @@ bool remember_table_list::lookup_entry(function const & f, ex & result) const remember_table::remember_table() { - table_size=0; - max_assoc_size=0; - remember_strategy=remember_strategies::delete_never; + table_size=0; + max_assoc_size=0; + remember_strategy=remember_strategies::delete_never; } remember_table::remember_table(unsigned s, unsigned as, unsigned strat) : - max_assoc_size(as), remember_strategy(strat) + max_assoc_size(as), remember_strategy(strat) { - // we keep max_assoc_size and remember_strategy if we need to clear - // all entries + // 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(); + // use some power of 2 next to s + table_size=1 << log2(s); + init_table(); } bool remember_table::lookup_entry(function const & f, ex & result) const { - unsigned entry=f.gethash() & (table_size-1); - GINAC_ASSERT(entry & remember_table::remember_tables(void) { - static std::vector * rt = new std::vector; - return *rt; + static std::vector * rt = new std::vector; + return *rt; } #ifndef NO_NAMESPACE_GINAC diff --git a/ginac/remember.h b/ginac/remember.h index 78ce547e..0d9bb687 100644 --- a/ginac/remember.h +++ b/ginac/remember.h @@ -33,68 +33,68 @@ namespace GiNaC { class function; class ex; - + /** A single entry in the remember table of a function. - Needs to be a friend of class function to access 'seq'. - 'last_access' and 'successful_hits' are updated at each successful - 'is_equal'. */ + Needs to be a friend of class function to access 'seq'. + 'last_access' and 'successful_hits' are updated at each successful + 'is_equal'. */ class remember_table_entry { public: - remember_table_entry(function const & f, ex const & r); - bool is_equal(function const & f) const; - ex get_result(void) const { return result; } - unsigned long get_last_access(void) const { return last_access; } - unsigned long get_successful_hits(void) const { return successful_hits; }; + remember_table_entry(function const & f, ex const & r); + bool is_equal(function const & f) const; + ex get_result(void) const { return result; } + unsigned long get_last_access(void) const { return last_access; } + unsigned long get_successful_hits(void) const { return successful_hits; }; protected: - unsigned hashvalue; - exvector seq; - ex result; - mutable unsigned long last_access; - mutable unsigned successful_hits; - static unsigned long access_counter; + unsigned hashvalue; + exvector seq; + ex result; + mutable unsigned long last_access; + mutable unsigned successful_hits; + static unsigned long access_counter; }; /** A list of entries in the remember table having some least - significant bits of the hashvalue in common. */ + significant bits of the hashvalue in common. */ class remember_table_list : public std::list { public: - remember_table_list(unsigned as, unsigned strat); - void add_entry(function const & f, ex const & result); - bool lookup_entry(function const & f, ex & result) const; + remember_table_list(unsigned as, unsigned strat); + void add_entry(function const & f, ex const & result); + bool lookup_entry(function const & f, ex & result) const; protected: - unsigned max_assoc_size; - unsigned remember_strategy; + unsigned max_assoc_size; + unsigned remember_strategy; }; /** The remember table is organized like an n-fold associative cache - in a microprocessor. The table has a width of 's' (which is rounded - to table_size, some power of 2 near 's', internally) and a depth of 'as' - (unless you choose that entries are never discarded). The place where - an entry is stored depends on the hashvalue of the parameters of the - function (this corresponds to the address of byte to be cached). - The 'log_2(table_size)' least significant bits of this hashvalue - give the slot in which the entry will be stored or looked up. - Each slot can take up to 'as' entries. If a slot is full, an older - entry is removed by one of the following strategies: - - oldest entry (the first one in the list) - - least recently used (the one with the lowest 'last_access') - - least frequently used (the one with the lowest 'successful_hits') - or all entries are kept which means that the table grows indefinitely. */ + in a microprocessor. The table has a width of 's' (which is rounded + to table_size, some power of 2 near 's', internally) and a depth of 'as' + (unless you choose that entries are never discarded). The place where + an entry is stored depends on the hashvalue of the parameters of the + function (this corresponds to the address of byte to be cached). + The 'log_2(table_size)' least significant bits of this hashvalue + give the slot in which the entry will be stored or looked up. + Each slot can take up to 'as' entries. If a slot is full, an older + entry is removed by one of the following strategies: + - oldest entry (the first one in the list) + - least recently used (the one with the lowest 'last_access') + - least frequently used (the one with the lowest 'successful_hits') + or all entries are kept which means that the table grows indefinitely. */ class remember_table : public std::vector { public: - remember_table(); - remember_table(unsigned s, unsigned as, unsigned strat); - bool lookup_entry(function const & f, ex & result) const; - void add_entry(function const & f, ex const & result); - void clear_all_entries(void); - void show_statistics(std::ostream & os, unsigned level) const; - static std::vector & remember_tables(void); + remember_table(); + remember_table(unsigned s, unsigned as, unsigned strat); + bool lookup_entry(function const & f, ex & result) const; + void add_entry(function const & f, ex const & result); + void clear_all_entries(void); + void show_statistics(std::ostream & os, unsigned level) const; + static std::vector & remember_tables(void); protected: - void init_table(void); - unsigned table_size; - unsigned max_assoc_size; - unsigned remember_strategy; + void init_table(void); + unsigned table_size; + unsigned max_assoc_size; + unsigned remember_strategy; }; #ifndef NO_NAMESPACE_GINAC diff --git a/ginac/simp_lor.cpp b/ginac/simp_lor.cpp index 4865561a..3c9cb453 100644 --- a/ginac/simp_lor.cpp +++ b/ginac/simp_lor.cpp @@ -47,46 +47,46 @@ namespace GiNaC { simp_lor::simp_lor() : type(invalid) { - debugmsg("simp_lor default constructor",LOGLEVEL_CONSTRUCT); - tinfo_key=TINFO_simp_lor; + debugmsg("simp_lor default constructor",LOGLEVEL_CONSTRUCT); + tinfo_key=TINFO_simp_lor; } simp_lor::~simp_lor() { - debugmsg("simp_lor destructor",LOGLEVEL_DESTRUCT); - destroy(0); + debugmsg("simp_lor destructor",LOGLEVEL_DESTRUCT); + destroy(0); } simp_lor::simp_lor(const simp_lor & other) { - debugmsg("simp_lor copy constructor",LOGLEVEL_CONSTRUCT); - copy (other); + debugmsg("simp_lor copy constructor",LOGLEVEL_CONSTRUCT); + copy (other); } const simp_lor & simp_lor::operator=(const simp_lor & other) { - debugmsg("simp_lor operator=",LOGLEVEL_ASSIGNMENT); - if (this != &other) { - destroy(1); - copy(other); - } - return *this; + debugmsg("simp_lor operator=",LOGLEVEL_ASSIGNMENT); + if (this != &other) { + destroy(1); + copy(other); + } + return *this; } // protected void simp_lor::copy(const simp_lor & other) { - indexed::copy(other); - type=other.type; - name=other.name; + indexed::copy(other); + type=other.type; + name=other.name; } void simp_lor::destroy(bool call_parent) { - if (call_parent) { - indexed::destroy(call_parent); - } + if (call_parent) { + indexed::destroy(call_parent); + } } ////////// @@ -97,40 +97,40 @@ void simp_lor::destroy(bool call_parent) simp_lor::simp_lor(simp_lor_types const t) : type(t) { - debugmsg("simp_lor constructor from simp_lor_types",LOGLEVEL_CONSTRUCT); - tinfo_key=TINFO_simp_lor; + debugmsg("simp_lor constructor from simp_lor_types",LOGLEVEL_CONSTRUCT); + tinfo_key=TINFO_simp_lor; } simp_lor::simp_lor(simp_lor_types const t, const ex & i1, const ex & i2) : - indexed(i1,i2), type(t) + indexed(i1,i2), type(t) { - debugmsg("simp_lor constructor from simp_lor_types,ex,ex",LOGLEVEL_CONSTRUCT); - tinfo_key=TINFO_simp_lor; - GINAC_ASSERT(all_of_type_lorentzidx()); + debugmsg("simp_lor constructor from simp_lor_types,ex,ex",LOGLEVEL_CONSTRUCT); + tinfo_key=TINFO_simp_lor; + GINAC_ASSERT(all_of_type_lorentzidx()); } simp_lor::simp_lor(simp_lor_types const t, const std::string & n, const ex & i1) : - indexed(i1), type(t), name(n) + indexed(i1), type(t), name(n) { - debugmsg("simp_lor constructor from simp_lor_types,string,ex",LOGLEVEL_CONSTRUCT); - tinfo_key=TINFO_simp_lor; - GINAC_ASSERT(all_of_type_lorentzidx()); + debugmsg("simp_lor constructor from simp_lor_types,string,ex",LOGLEVEL_CONSTRUCT); + tinfo_key=TINFO_simp_lor; + GINAC_ASSERT(all_of_type_lorentzidx()); } simp_lor::simp_lor(simp_lor_types const t, const std::string & n, const exvector & iv) : - indexed(iv), type(t), name(n) + indexed(iv), type(t), name(n) { - debugmsg("simp_lor constructor from simp_lor_types,string,exvector",LOGLEVEL_CONSTRUCT); - tinfo_key=TINFO_simp_lor; - GINAC_ASSERT(all_of_type_lorentzidx()); + debugmsg("simp_lor constructor from simp_lor_types,string,exvector",LOGLEVEL_CONSTRUCT); + tinfo_key=TINFO_simp_lor; + GINAC_ASSERT(all_of_type_lorentzidx()); } simp_lor::simp_lor(simp_lor_types const t, const std::string & n, exvector * ivp) : - indexed(ivp), type(t), name(n) + indexed(ivp), type(t), name(n) { - debugmsg("simp_lor constructor from simp_lor_types,string,exvector*",LOGLEVEL_CONSTRUCT); - tinfo_key=TINFO_simp_lor; - GINAC_ASSERT(all_of_type_lorentzidx()); + debugmsg("simp_lor constructor from simp_lor_types,string,exvector*",LOGLEVEL_CONSTRUCT); + tinfo_key=TINFO_simp_lor; + GINAC_ASSERT(all_of_type_lorentzidx()); } ////////// @@ -141,145 +141,145 @@ simp_lor::simp_lor(simp_lor_types const t, const std::string & n, exvector * ivp basic * simp_lor::duplicate() const { - debugmsg("simp_lor duplicate",LOGLEVEL_DUPLICATE); - return new simp_lor(*this); + debugmsg("simp_lor duplicate",LOGLEVEL_DUPLICATE); + return new simp_lor(*this); } void simp_lor::printraw(std::ostream & os) const { - debugmsg("simp_lor printraw",LOGLEVEL_PRINT); - os << "simp_lor(type=" << (unsigned)type - << ",name=" << name << ",indices="; - printrawindices(os); - os << ",hash=" << hashvalue << ",flags=" << flags << ")"; + debugmsg("simp_lor printraw",LOGLEVEL_PRINT); + os << "simp_lor(type=" << (unsigned)type + << ",name=" << name << ",indices="; + printrawindices(os); + os << ",hash=" << hashvalue << ",flags=" << flags << ")"; } void simp_lor::printtree(std::ostream & os, unsigned indent) const { - debugmsg("simp_lor printtree",LOGLEVEL_PRINT); - os << std::string(indent,' ') << "simp_lor object: " - << "type=" << (unsigned)type - << ", name=" << name << ", "; - os << seq.size() << " indices" << std::endl; - printtreeindices(os,indent); - os << std::string(indent,' ') << "hash=" << hashvalue - << " (0x" << std::hex << hashvalue << std::dec << ")" - << ", flags=" << flags << std::endl; + debugmsg("simp_lor printtree",LOGLEVEL_PRINT); + os << std::string(indent,' ') << "simp_lor object: " + << "type=" << (unsigned)type + << ", name=" << name << ", "; + os << seq.size() << " indices" << std::endl; + printtreeindices(os,indent); + os << std::string(indent,' ') << "hash=" << hashvalue + << " (0x" << std::hex << hashvalue << std::dec << ")" + << ", flags=" << flags << std::endl; } void simp_lor::print(std::ostream & os, unsigned upper_precedence) const { - debugmsg("simp_lor print",LOGLEVEL_PRINT); - switch (type) { - case simp_lor_g: - os << "g"; - break; - case simp_lor_vec: - os << name; - break; - case invalid: - default: - os << "INVALID_SIMP_LOR_OBJECT"; - break; - } - printindices(os); + debugmsg("simp_lor print",LOGLEVEL_PRINT); + switch (type) { + case simp_lor_g: + os << "g"; + break; + case simp_lor_vec: + os << name; + break; + case invalid: + default: + os << "INVALID_SIMP_LOR_OBJECT"; + break; + } + printindices(os); } void simp_lor::printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const { - debugmsg("simp_lor print csrc",LOGLEVEL_PRINT); - print(os,upper_precedence); + debugmsg("simp_lor print csrc",LOGLEVEL_PRINT); + print(os,upper_precedence); } bool simp_lor::info(unsigned inf) const { - return indexed::info(inf); + return indexed::info(inf); } ex simp_lor::eval(int level) const { - if (type==simp_lor_g) { - // canonicalize indices - exvector iv=seq; - int sig=canonicalize_indices(iv,false); // symmetric - if (sig!=INT_MAX) { - // something has changed while sorting indices, more evaluations later - if (sig==0) return _ex0(); - return ex(sig)*simp_lor(type,name,iv); - } - const lorentzidx & idx1=ex_to_lorentzidx(seq[0]); - const lorentzidx & idx2=ex_to_lorentzidx(seq[1]); - if ((!idx1.is_symbolic())&&(!idx2.is_symbolic())) { - // both indices are numeric - if ((idx1.get_value()==idx2.get_value())) { - // both on diagonal - if (idx1.get_value()==0) { - // (0,0) - return _ex1(); - } else { - if (idx1.is_covariant()!=idx2.is_covariant()) { - // (_i,~i) or (~i,_i), i=1..3 - return _ex1(); - } else { - // (_i,_i) or (~i,~i), i=1..3 - return _ex_1(); - } - } - } else { - // at least one off-diagonal - return _ex0(); - } - } else if (idx1.is_symbolic() && - idx1.is_co_contra_pair(idx2)) { - return Dim()-idx1.get_dim_parallel_space(); - } - } - - return this->hold(); -} - + if (type==simp_lor_g) { + // canonicalize indices + exvector iv=seq; + int sig=canonicalize_indices(iv,false); // symmetric + if (sig!=INT_MAX) { + // something has changed while sorting indices, more evaluations later + if (sig==0) return _ex0(); + return ex(sig)*simp_lor(type,name,iv); + } + const lorentzidx & idx1=ex_to_lorentzidx(seq[0]); + const lorentzidx & idx2=ex_to_lorentzidx(seq[1]); + if ((!idx1.is_symbolic())&&(!idx2.is_symbolic())) { + // both indices are numeric + if ((idx1.get_value()==idx2.get_value())) { + // both on diagonal + if (idx1.get_value()==0) { + // (0,0) + return _ex1(); + } else { + if (idx1.is_covariant()!=idx2.is_covariant()) { + // (_i,~i) or (~i,_i), i=1..3 + return _ex1(); + } else { + // (_i,_i) or (~i,~i), i=1..3 + return _ex_1(); + } + } + } else { + // at least one off-diagonal + return _ex0(); + } + } else if (idx1.is_symbolic() && + idx1.is_co_contra_pair(idx2)) { + return Dim()-idx1.get_dim_parallel_space(); + } + } + + return this->hold(); +} + // protected int simp_lor::compare_same_type(const basic & other) const { - GINAC_ASSERT(other.tinfo() == TINFO_simp_lor); - const simp_lor *o = static_cast(&other); - if (type==o->type) { - if (name==o->name) { - return indexed::compare_same_type(other); - } - return name.compare(o->name); - } - return type < o->type ? -1 : 1; + GINAC_ASSERT(other.tinfo() == TINFO_simp_lor); + const simp_lor *o = static_cast(&other); + if (type==o->type) { + if (name==o->name) { + return indexed::compare_same_type(other); + } + return name.compare(o->name); + } + return type < o->type ? -1 : 1; } bool simp_lor::is_equal_same_type(const basic & other) const { - GINAC_ASSERT(other.tinfo() == TINFO_simp_lor); - const simp_lor *o = static_cast(&other); - if (type!=o->type) return false; - if (name!=o->name) return false; - return indexed::is_equal_same_type(other); + GINAC_ASSERT(other.tinfo() == TINFO_simp_lor); + const simp_lor *o = static_cast(&other); + if (type!=o->type) return false; + if (name!=o->name) return false; + return indexed::is_equal_same_type(other); } unsigned simp_lor::return_type(void) const { - return return_types::commutative; + return return_types::commutative; } unsigned simp_lor::return_type_tinfo(void) const { - return tinfo_key; + return tinfo_key; } ex simp_lor::thisexprseq(const exvector & v) const { - return simp_lor(type,name,v); + return simp_lor(type,name,v); } ex simp_lor::thisexprseq(exvector * vp) const { - return simp_lor(type,name,vp); + return simp_lor(type,name,vp); } ////////// @@ -296,11 +296,11 @@ ex simp_lor::thisexprseq(exvector * vp) const bool simp_lor::all_of_type_lorentzidx(void) const { - // used only inside of ASSERTs - for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { - if (!is_ex_of_type(*cit,lorentzidx)) return false; - } - return true; + // used only inside of ASSERTs + for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { + if (!is_ex_of_type(*cit,lorentzidx)) return false; + } + return true; } ////////// @@ -322,141 +322,141 @@ const type_info & typeid_simp_lor = typeid(some_simp_lor); simp_lor lor_g(const ex & mu, const ex & nu) { - return simp_lor(simp_lor::simp_lor_g,mu,nu); + return simp_lor(simp_lor::simp_lor_g,mu,nu); } simp_lor lor_vec(const std::string & n, const ex & mu) { - return simp_lor(simp_lor::simp_lor_vec,n,mu); + return simp_lor(simp_lor::simp_lor_vec,n,mu); } ex simplify_simp_lor_mul(const ex & m, const scalar_products & sp) { - GINAC_ASSERT(is_ex_exactly_of_type(m,mul)); - exvector v_contracted; - - // collect factors in an exvector, store squares twice - unsigned n=m.nops(); - v_contracted.reserve(2*n); - for (unsigned i=0; i0) { - reg(v2,v1,sp); - return; - } - spm[make_key(v1,v2)]=sp; + if (v1.compare_same_type(v2)>0) { + reg(v2,v1,sp); + return; + } + spm[make_key(v1,v2)]=sp; } bool scalar_products::is_defined(const simp_lor & v1, const simp_lor & v2) const { - if (v1.compare_same_type(v2)>0) { - return is_defined(v2,v1); - } - return spm.find(make_key(v1,v2))!=spm.end(); + if (v1.compare_same_type(v2)>0) { + return is_defined(v2,v1); + } + return spm.find(make_key(v1,v2))!=spm.end(); } ex scalar_products::evaluate(const simp_lor & v1, const simp_lor & v2) const { - if (v1.compare_same_type(v2)>0) { - return evaluate(v2,v1); - } - return spm.find(make_key(v1,v2))->second; + if (v1.compare_same_type(v2)>0) { + return evaluate(v2,v1); + } + return spm.find(make_key(v1,v2))->second; } void scalar_products::debugprint(void) const { - std::cerr << "map size=" << spm.size() << std::endl; - for (spmap::const_iterator cit=spm.begin(); cit!=spm.end(); ++cit) { - const spmapkey & k=(*cit).first; - std::cerr << "item key=((" << k.first.first - << "," << k.first.second << "),"; - k.second.printraw(cerr); - cerr << ") value=" << (*cit).second << std::endl; - } + std::cerr << "map size=" << spm.size() << std::endl; + for (spmap::const_iterator cit=spm.begin(); cit!=spm.end(); ++cit) { + const spmapkey & k=(*cit).first; + std::cerr << "item key=((" << k.first.first + << "," << k.first.second << "),"; + k.second.printraw(cerr); + cerr << ") value=" << (*cit).second << std::endl; + } } spmapkey scalar_products::make_key(const simp_lor & v1, const simp_lor & v2) { - GINAC_ASSERT(v1.type==simp_lor::simp_lor_vec); - GINAC_ASSERT(v2.type==simp_lor::simp_lor_vec); - lorentzidx anon=ex_to_lorentzidx(v1.seq[0]).create_anonymous_representative(); - GINAC_ASSERT(anon.is_equal_same_type(ex_to_lorentzidx(v2.seq[0]).create_anonymous_representative())); - return spmapkey(strstrpair(v1.name,v2.name),anon); + GINAC_ASSERT(v1.type==simp_lor::simp_lor_vec); + GINAC_ASSERT(v2.type==simp_lor::simp_lor_vec); + lorentzidx anon=ex_to_lorentzidx(v1.seq[0]).create_anonymous_representative(); + GINAC_ASSERT(anon.is_equal_same_type(ex_to_lorentzidx(v2.seq[0]).create_anonymous_representative())); + return spmapkey(strstrpair(v1.name,v2.name),anon); } #ifndef NO_NAMESPACE_GINAC diff --git a/ginac/simp_lor.h b/ginac/simp_lor.h index 677a4c25..940e110e 100644 --- a/ginac/simp_lor.h +++ b/ginac/simp_lor.h @@ -41,25 +41,25 @@ typedef std::pair spmapkey; class spmapkey_is_less { public: - bool operator()(const spmapkey & lh, const spmapkey & rh) const - { - /* - cerr << "spmapkey_is_less" << endl; - cerr << "lh=((" << lh.first.first - << "," << lh.first.second << "),"; - lh.second.printraw(cerr); - cerr << ")" << endl; - - cerr << "rh=((" << rh.first.first - << "," << rh.first.second << "),"; - rh.second.printraw(cerr); - cerr << ")" << endl; - */ - bool res=lh.first & structure::registered_structures(void) { - static std::vector * rs = new std::vector; - return *rs; + static std::vector * rs = new std::vector; + return *rs; } // public unsigned structure::register_new(const char * nm) { - registered_structure_info rsi={nm}; - registered_structures().push_back(rsi); - return registered_structures().size()-1; + registered_structure_info rsi={nm}; + registered_structures().push_back(rsi); + return registered_structures().size()-1; } ////////// diff --git a/ginac/structure.h b/ginac/structure.h index 358e6ce6..972e1123 100644 --- a/ginac/structure.h +++ b/ginac/structure.h @@ -30,51 +30,51 @@ namespace GiNaC { #endif // ndef NO_NAMESPACE_GINAC struct registered_structure_info { - const char * name; + const char * name; }; /** The class structure is used to implement user defined classes - with named members which behave similar to ordinary C structs. - structure is an 'abstract' base class (it is possible but not - meaningful to make instances), the user defined structures - will be create by the perl script structure.pl */ + with named members which behave similar to ordinary C structs. + structure is an 'abstract' base class (it is possible but not + meaningful to make instances), the user defined structures + will be create by the perl script structure.pl */ class structure : public basic { // member functions - // default constructor, destructor, copy constructor assignment operator and helpers + // default constructor, destructor, copy constructor assignment operator and helpers public: - structure(); - ~structure(); - structure(const structure & other); - const structure & operator=(const structure & other); + structure(); + ~structure(); + structure(const structure & other); + const structure & operator=(const structure & other); protected: - void copy(const structure & other); - void destroy(bool call_parent); + void copy(const structure & other); + void destroy(bool call_parent); - // other constructors - // none + // other constructors + // none - // functions overriding virtual functions from bases classes + // functions overriding virtual functions from bases classes public: - basic * duplicate() const; - void printraw(std::ostream & os) const; - void print(std::ostream & os, unsigned upper_precedence=0) const; - void printtree(std::ostream & os, unsigned indent) const; - void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence=0) const; + basic * duplicate() const; + void printraw(std::ostream & os) const; + void print(std::ostream & os, unsigned upper_precedence=0) const; + void printtree(std::ostream & os, unsigned indent) const; + void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence=0) const; protected: - int compare_same_type(const basic & other) const; - bool is_equal_same_type(const basic & other) const; - - // new virtual functions which can be overridden by derived classes - // none - - // non-virtual functions in this class + int compare_same_type(const basic & other) const; + bool is_equal_same_type(const basic & other) const; + + // new virtual functions which can be overridden by derived classes + // none + + // non-virtual functions in this class protected: - static std::vector & registered_structures(void); + static std::vector & registered_structures(void); public: - static unsigned register_new(const char * nm); + static unsigned register_new(const char * nm); // member variables // none diff --git a/ginac/symbol.cpp b/ginac/symbol.cpp index b7408fa6..1e2561ab 100644 --- a/ginac/symbol.cpp +++ b/ginac/symbol.cpp @@ -42,42 +42,42 @@ GINAC_IMPLEMENT_REGISTERED_CLASS(symbol, basic) symbol::symbol() : inherited(TINFO_symbol) { - debugmsg("symbol default constructor", LOGLEVEL_CONSTRUCT); - serial = next_serial++; - name = autoname_prefix()+ToString(serial); - asexinfop = new assigned_ex_info; - setflag(status_flags::evaluated); + debugmsg("symbol default constructor", LOGLEVEL_CONSTRUCT); + serial = next_serial++; + name = autoname_prefix()+ToString(serial); + asexinfop = new assigned_ex_info; + setflag(status_flags::evaluated); } symbol::~symbol() { - debugmsg("symbol destructor", LOGLEVEL_DESTRUCT); - destroy(0); + debugmsg("symbol destructor", LOGLEVEL_DESTRUCT); + destroy(0); } symbol::symbol(const symbol & other) { - debugmsg("symbol copy constructor", LOGLEVEL_CONSTRUCT); - copy(other); + debugmsg("symbol copy constructor", LOGLEVEL_CONSTRUCT); + copy(other); } void symbol::copy(const symbol & other) { - inherited::copy(other); - name = other.name; - serial = other.serial; - asexinfop = other.asexinfop; - ++asexinfop->refcount; + inherited::copy(other); + name = other.name; + serial = other.serial; + asexinfop = other.asexinfop; + ++asexinfop->refcount; } void symbol::destroy(bool call_parent) { - if (--asexinfop->refcount == 0) { - delete asexinfop; - } - if (call_parent) { - inherited::destroy(call_parent); - } + if (--asexinfop->refcount == 0) { + delete asexinfop; + } + if (call_parent) { + inherited::destroy(call_parent); + } } // how should the following be interpreted? @@ -94,11 +94,11 @@ void symbol::destroy(bool call_parent) symbol::symbol(const std::string & initname) : inherited(TINFO_symbol) { - debugmsg("symbol constructor from string", LOGLEVEL_CONSTRUCT); - name = initname; - serial = next_serial++; - asexinfop = new assigned_ex_info; - setflag(status_flags::evaluated); + debugmsg("symbol constructor from string", LOGLEVEL_CONSTRUCT); + name = initname; + serial = next_serial++; + asexinfop = new assigned_ex_info; + setflag(status_flags::evaluated); } ////////// @@ -108,32 +108,32 @@ 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); - serial = next_serial++; - if (!(n.find_string("name", name))) - name = autoname_prefix() + ToString(serial); - asexinfop = new assigned_ex_info; - setflag(status_flags::evaluated); + debugmsg("symbol constructor from archive_node", LOGLEVEL_CONSTRUCT); + serial = next_serial++; + if (!(n.find_string("name", name))) + name = autoname_prefix() + ToString(serial); + asexinfop = new assigned_ex_info; + setflag(status_flags::evaluated); } /** Unarchive the object. */ ex symbol::unarchive(const archive_node &n, const lst &sym_lst) { - ex s = (new symbol(n, sym_lst))->setflag(status_flags::dynallocated); + 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; ihold(); + return this->hold(); } bool symbol::has(const ex & other) const { - if (is_equal(*other.bp)) return true; - return false; + if (is_equal(*other.bp)) return true; + return false; } int symbol::degree(const symbol & s) const { - return compare_same_type(s)==0 ? 1 : 0; + return compare_same_type(s)==0 ? 1 : 0; } int symbol::ldegree(const symbol & s) const { - return compare_same_type(s)==0 ? 1 : 0; + return compare_same_type(s)==0 ? 1 : 0; } ex symbol::coeff(const symbol & s, int n) const { - if (compare_same_type(s)==0) { - return n==1 ? _ex1() : _ex0(); - } else { - return n==0 ? *this : _ex0(); - } + if (compare_same_type(s)==0) { + return n==1 ? _ex1() : _ex0(); + } else { + return n==0 ? *this : _ex0(); + } } ex symbol::eval(int level) const { - if (level == -max_recursion_level) { - throw(std::runtime_error("max recursion level reached")); - } - - if (asexinfop->is_assigned) { - setflag(status_flags::evaluated); - if (level==1) { - return (asexinfop->assigned_expression); - } else { - return (asexinfop->assigned_expression).eval(level); - } - } else { - return this->hold(); - } + if (level == -max_recursion_level) { + throw(std::runtime_error("max recursion level reached")); + } + + if (asexinfop->is_assigned) { + setflag(status_flags::evaluated); + if (level==1) { + return (asexinfop->assigned_expression); + } else { + return (asexinfop->assigned_expression).eval(level); + } + } else { + return this->hold(); + } } ex symbol::subs(const lst & ls, const lst & lr) const { - GINAC_ASSERT(ls.nops()==lr.nops()); + GINAC_ASSERT(ls.nops()==lr.nops()); #ifdef DO_GINAC_ASSERT - for (unsigned i=0; i(&other); - if (serial==o->serial) return 0; - return serial < o->serial ? -1 : 1; + GINAC_ASSERT(is_of_type(other,symbol)); + const symbol *o = static_cast(&other); + if (serial==o->serial) return 0; + return serial < o->serial ? -1 : 1; } bool symbol::is_equal_same_type(const basic & other) const { - GINAC_ASSERT(is_of_type(other,symbol)); - const symbol *o = static_cast(&other); - return serial==o->serial; + GINAC_ASSERT(is_of_type(other,symbol)); + const symbol *o = static_cast(&other); + return serial==o->serial; } unsigned symbol::return_type(void) const { - return return_types::commutative; + return return_types::commutative; } unsigned symbol::return_type_tinfo(void) const { - return tinfo_key; + return tinfo_key; } unsigned symbol::calchash(void) const { - // return golden_ratio_hash(tinfo()) ^ serial; - hashvalue=golden_ratio_hash(golden_ratio_hash(0x55555555U ^ serial)); - setflag(status_flags::hash_calculated); - return hashvalue; + // return golden_ratio_hash(tinfo()) ^ serial; + hashvalue=golden_ratio_hash(golden_ratio_hash(0x55555555U ^ serial)); + setflag(status_flags::hash_calculated); + return hashvalue; } ////////// @@ -320,26 +320,26 @@ unsigned symbol::calchash(void) const void symbol::assign(const ex & value) { - asexinfop->is_assigned=1; - asexinfop->assigned_expression=value; - clearflag(status_flags::evaluated); + asexinfop->is_assigned=1; + asexinfop->assigned_expression=value; + clearflag(status_flags::evaluated); } void symbol::unassign(void) { - if (asexinfop->is_assigned) { - asexinfop->is_assigned=0; - asexinfop->assigned_expression=_ex0(); - } - setflag(status_flags::evaluated); + if (asexinfop->is_assigned) { + asexinfop->is_assigned=0; + asexinfop->assigned_expression=_ex0(); + } + setflag(status_flags::evaluated); } // private std::string & symbol::autoname_prefix(void) { - static std::string * s=new std::string("symbol"); - return *s; + static std::string * s=new std::string("symbol"); + return *s; } ////////// diff --git a/ginac/symbol.h b/ginac/symbol.h index bd37892f..d547b1d6 100644 --- a/ginac/symbol.h +++ b/ginac/symbol.h @@ -39,77 +39,77 @@ namespace GiNaC { * first place. */ class symbol : public basic { - GINAC_DECLARE_REGISTERED_CLASS(symbol, basic) + GINAC_DECLARE_REGISTERED_CLASS(symbol, basic) // types - /** Symbols as keys to expressions. */ - 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! - }; - + /** Symbols as keys to expressions. */ + 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! + }; + // member functions - // default constructor, destructor, copy constructor assignment operator and helpers + // default constructor, destructor, copy constructor assignment operator and helpers public: - symbol(); - ~symbol(); - symbol(const symbol & other); + symbol(); + ~symbol(); + symbol(const symbol & other); protected: - void copy(const symbol & other); - void destroy(bool call_parent); + void copy(const symbol & other); + void destroy(bool call_parent); - // other constructors + // other constructors public: - explicit symbol(const std::string & initname); + explicit symbol(const std::string & initname); - // functions overriding virtual functions from base classes + // functions overriding virtual functions from base classes public: - basic * duplicate() 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; - bool info(unsigned inf) const; - ex expand(unsigned options = 0) const; - bool has(const ex & other) const; - int degree(const symbol & s) const; - int ldegree(const symbol & s) const; - ex coeff(const symbol & s, int n = 1) const; - ex eval(int level = 0) const; - ex series(const relational & s, int order, unsigned options = 0) const; - ex normal(lst &sym_lst, lst &repl_lst, int level = 0) const; - ex to_rational(lst &repl_lst) const; - ex subs(const lst & ls, const lst & lr) const; + basic * duplicate() 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; + bool info(unsigned inf) const; + ex expand(unsigned options = 0) const; + bool has(const ex & other) const; + int degree(const symbol & s) const; + int ldegree(const symbol & s) const; + ex coeff(const symbol & s, int n = 1) const; + ex eval(int level = 0) const; + ex series(const relational & s, int order, unsigned options = 0) const; + ex normal(lst &sym_lst, lst &repl_lst, int level = 0) const; + ex to_rational(lst &repl_lst) const; + ex subs(const lst & ls, const lst & lr) const; protected: - ex derivative(const symbol & s) const; - int compare_same_type(const basic & other) const; - bool is_equal_same_type(const basic & other) const; - unsigned return_type(void) const; - unsigned return_type_tinfo(void) const; - unsigned calchash(void) const; - - // non-virtual functions in this class + ex derivative(const symbol & s) const; + int compare_same_type(const basic & other) const; + bool is_equal_same_type(const basic & other) const; + unsigned return_type(void) const; + unsigned return_type_tinfo(void) const; + unsigned calchash(void) const; + + // non-virtual functions in this class public: - void assign(const ex & value); - void unassign(void); - void setname(const std::string & n) { name = n; } - std::string getname(void) const { return name; } + void assign(const ex & value); + void unassign(void); + void setname(const std::string & n) { name = n; } + std::string getname(void) const { return name; } private: - std::string & autoname_prefix(void); + std::string & autoname_prefix(void); // member variables protected: - assigned_ex_info * asexinfop; - unsigned serial; //!< unique serial number for comparision - std::string name; + assigned_ex_info * asexinfop; + unsigned serial; //!< unique serial number for comparision + std::string name; private: - static unsigned next_serial; + static unsigned next_serial; }; // global constants diff --git a/ginac/utils.cpp b/ginac/utils.cpp index 513b5796..c4e5bbc4 100644 --- a/ginac/utils.cpp +++ b/ginac/utils.cpp @@ -31,15 +31,15 @@ namespace GiNaC { /** ctor for pole_error exception class. */ pole_error::pole_error(const std::string& what_arg, int degree) - : domain_error(what_arg) + : domain_error(what_arg) { - deg = degree; + deg = degree; } /** Return the degree of the pole_error exception class. */ int pole_error::degree(void) const { - return deg; + return deg; } // some compilers (e.g. cygwin) define a macro log2, causing confusion @@ -47,9 +47,9 @@ int pole_error::degree(void) const /** Integer binary logarithm */ unsigned log2(unsigned n) { - unsigned k; - for (k = 0; n > 1; n >>= 1) ++k; - return k; + unsigned k; + for (k = 0; n > 1; n >>= 1) ++k; + return k; } #endif @@ -57,12 +57,12 @@ unsigned log2(unsigned n) * @return -1, 0, or 1 */ int compare_pointers(const void * a, const void * b) { - if (ab) { - return 1; - } - return 0; + if (ab) { + return 1; + } + return 0; } ////////// @@ -72,687 +72,687 @@ int compare_pointers(const void * a, const void * b) // numeric -120 const numeric & _num_120(void) { - const static ex e = ex(numeric(-120)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(-120)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex_120(void) { - static ex * e = new ex(_num_120()); - return *e; + static ex * e = new ex(_num_120()); + return *e; } // numeric -60 const numeric & _num_60(void) { - const static ex e = ex(numeric(-60)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(-60)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex_60(void) { - static ex * e = new ex(_num_60()); - return *e; + static ex * e = new ex(_num_60()); + return *e; } // numeric -48 const numeric & _num_48(void) { - const static ex e = ex(numeric(-48)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(-48)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex_48(void) { - static ex * e = new ex(_num_48()); - return *e; + static ex * e = new ex(_num_48()); + return *e; } // numeric -30 const numeric & _num_30(void) { - const static ex e = ex(numeric(-30)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(-30)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex_30(void) { - static ex * e = new ex(_num_30()); - return *e; + static ex * e = new ex(_num_30()); + return *e; } // numeric -25 const numeric & _num_25(void) { - const static ex e = ex(numeric(-25)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(-25)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex_25(void) { - static ex * e = new ex(_num_25()); - return *e; + static ex * e = new ex(_num_25()); + return *e; } // numeric -24 const numeric & _num_24(void) { - const static ex e = ex(numeric(-24)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(-24)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex_24(void) { - static ex * e = new ex(_num_24()); - return *e; + static ex * e = new ex(_num_24()); + return *e; } // numeric -20 const numeric & _num_20(void) { - const static ex e = ex(numeric(-20)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(-20)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex_20(void) { - static ex * e = new ex(_num_20()); - return *e; + static ex * e = new ex(_num_20()); + return *e; } // numeric -18 const numeric & _num_18(void) { - const static ex e = ex(numeric(-18)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(-18)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex_18(void) { - static ex * e = new ex(_num_18()); - return *e; + static ex * e = new ex(_num_18()); + return *e; } // numeric -15 const numeric & _num_15(void) { - const static ex e = ex(numeric(-15)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(-15)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex_15(void) { - static ex * e = new ex(_num_15()); - return *e; + static ex * e = new ex(_num_15()); + return *e; } // numeric -12 const numeric & _num_12(void) { - const static ex e = ex(numeric(-12)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(-12)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex_12(void) { - static ex * e = new ex(_num_12()); - return *e; + static ex * e = new ex(_num_12()); + return *e; } // numeric -11 const numeric & _num_11(void) { - const static ex e = ex(numeric(-11)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(-11)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex_11(void) { - static ex * e = new ex(_num_11()); - return *e; + static ex * e = new ex(_num_11()); + return *e; } // numeric -10 const numeric & _num_10(void) { - const static ex e = ex(numeric(-10)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(-10)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex_10(void) { - static ex * e = new ex(_num_10()); - return *e; + static ex * e = new ex(_num_10()); + return *e; } // numeric -9 const numeric & _num_9(void) { - const static ex e = ex(numeric(-9)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(-9)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex_9(void) { - static ex * e = new ex(_num_9()); - return *e; + static ex * e = new ex(_num_9()); + return *e; } // numeric -8 const numeric & _num_8(void) { - const static ex e = ex(numeric(-8)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(-8)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex_8(void) { - static ex * e = new ex(_num_8()); - return *e; + static ex * e = new ex(_num_8()); + return *e; } // numeric -7 const numeric & _num_7(void) { - const static ex e = ex(numeric(-7)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(-7)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex_7(void) { - static ex * e = new ex(_num_7()); - return *e; + static ex * e = new ex(_num_7()); + return *e; } // numeric -6 const numeric & _num_6(void) { - const static ex e = ex(numeric(-6)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(-6)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex_6(void) { - static ex * e = new ex(_num_6()); - return *e; + static ex * e = new ex(_num_6()); + return *e; } // numeric -5 const numeric & _num_5(void) { - const static ex e = ex(numeric(-5)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(-5)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex_5(void) { - static ex * e = new ex(_num_5()); - return *e; + static ex * e = new ex(_num_5()); + return *e; } // numeric -4 const numeric & _num_4(void) { - const static ex e = ex(numeric(-4)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(-4)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex_4(void) { - static ex * e = new ex(_num_4()); - return *e; + static ex * e = new ex(_num_4()); + return *e; } // numeric -3 const numeric & _num_3(void) { - const static ex e = ex(numeric(-3)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(-3)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex_3(void) { - static ex * e = new ex(_num_3()); - return *e; + static ex * e = new ex(_num_3()); + return *e; } // numeric -2 const numeric & _num_2(void) { - const static ex e = ex(numeric(-2)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(-2)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex_2(void) { - static ex * e = new ex(_num_2()); - return *e; + static ex * e = new ex(_num_2()); + return *e; } // numeric -1 const numeric & _num_1(void) { - const static ex e = ex(numeric(-1)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(-1)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex_1(void) { - static ex * e = new ex(_num_1()); - return *e; + static ex * e = new ex(_num_1()); + return *e; } // numeric -1/2 const numeric & _num_1_2(void) { - const static ex e = ex(numeric(-1,2)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(-1,2)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex_1_2(void) { - static ex * e = new ex(_num_1_2()); - return *e; + static ex * e = new ex(_num_1_2()); + return *e; } // numeric -1/3 const numeric & _num_1_3(void) { - const static ex e = ex(numeric(-1,3)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(-1,3)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex_1_3(void) { - static ex * e = new ex(_num_1_3()); - return *e; + static ex * e = new ex(_num_1_3()); + return *e; } // numeric -1/4 const numeric & _num_1_4(void) { - const static ex e = ex(numeric(-1,4)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(-1,4)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex_1_4(void) { - static ex * e = new ex(_num_1_4()); - return *e; + static ex * e = new ex(_num_1_4()); + return *e; } // numeric 0 const numeric & _num0(void) { - const static ex e = ex(numeric(0)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(0)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex0(void) { - static ex * e = new ex(_num0()); - return *e; + static ex * e = new ex(_num0()); + return *e; } // numeric 1/4 const numeric & _num1_4(void) { - const static ex e = ex(numeric(1,4)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(1,4)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex1_4(void) { - static ex * e = new ex(_num1_4()); - return *e; + static ex * e = new ex(_num1_4()); + return *e; } // numeric 1/3 const numeric & _num1_3(void) { - const static ex e = ex(numeric(1,3)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(1,3)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex1_3(void) { - static ex * e = new ex(_num1_3()); - return *e; + static ex * e = new ex(_num1_3()); + return *e; } // numeric 1/2 const numeric & _num1_2(void) { - const static ex e = ex(numeric(1,2)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(1,2)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex1_2(void) { - static ex * e = new ex(_num1_2()); - return *e; + static ex * e = new ex(_num1_2()); + return *e; } // numeric 1 const numeric & _num1(void) { - const static ex e = ex(numeric(1)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(1)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex1(void) { - static ex * e = new ex(_num1()); - return *e; + static ex * e = new ex(_num1()); + return *e; } // numeric 2 const numeric & _num2(void) { - const static ex e = ex(numeric(2)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(2)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex2(void) { - static ex * e = new ex(_num2()); - return *e; + static ex * e = new ex(_num2()); + return *e; } // numeric 3 const numeric & _num3(void) { - const static ex e = ex(numeric(3)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(3)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex3(void) { - static ex * e = new ex(_num3()); - return *e; + static ex * e = new ex(_num3()); + return *e; } // numeric 4 const numeric & _num4(void) { - const static ex e = ex(numeric(4)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(4)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex4(void) { - static ex * e = new ex(_num4()); - return *e; + static ex * e = new ex(_num4()); + return *e; } // numeric 5 const numeric & _num5(void) { - const static ex e = ex(numeric(5)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(5)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex5(void) { - static ex * e = new ex(_num5()); - return *e; + static ex * e = new ex(_num5()); + return *e; } // numeric 6 const numeric & _num6(void) { - const static ex e = ex(numeric(6)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(6)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex6(void) { - static ex * e = new ex(_num6()); - return *e; + static ex * e = new ex(_num6()); + return *e; } // numeric 7 const numeric & _num7(void) { - const static ex e = ex(numeric(7)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(7)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex7(void) { - static ex * e = new ex(_num7()); - return *e; + static ex * e = new ex(_num7()); + return *e; } // numeric 8 const numeric & _num8(void) { - const static ex e = ex(numeric(8)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(8)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex8(void) { - static ex * e = new ex(_num8()); - return *e; + static ex * e = new ex(_num8()); + return *e; } // numeric 9 const numeric & _num9(void) { - const static ex e = ex(numeric(9)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(9)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex9(void) { - static ex * e = new ex(_num9()); - return *e; + static ex * e = new ex(_num9()); + return *e; } // numeric 10 const numeric & _num10(void) { - const static ex e = ex(numeric(10)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(10)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex10(void) { - static ex * e = new ex(_num10()); - return *e; + static ex * e = new ex(_num10()); + return *e; } // numeric 11 const numeric & _num11(void) { - const static ex e = ex(numeric(11)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(11)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex11(void) { - static ex * e = new ex(_num11()); - return *e; + static ex * e = new ex(_num11()); + return *e; } // numeric 12 const numeric & _num12(void) { - const static ex e = ex(numeric(12)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(12)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex12(void) { - static ex * e = new ex(_num12()); - return *e; + static ex * e = new ex(_num12()); + return *e; } // numeric 15 const numeric & _num15(void) { - const static ex e = ex(numeric(15)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(15)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex15(void) { - static ex * e = new ex(_num15()); - return *e; + static ex * e = new ex(_num15()); + return *e; } // numeric 18 const numeric & _num18(void) { - const static ex e = ex(numeric(18)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(18)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex18(void) { - static ex * e = new ex(_num18()); - return *e; + static ex * e = new ex(_num18()); + return *e; } // numeric 20 const numeric & _num20(void) { - const static ex e = ex(numeric(20)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(20)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex20(void) { - static ex * e = new ex(_num20()); - return *e; + static ex * e = new ex(_num20()); + return *e; } // numeric 24 const numeric & _num24(void) { - const static ex e = ex(numeric(24)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(24)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex24(void) { - static ex * e = new ex(_num24()); - return *e; + static ex * e = new ex(_num24()); + return *e; } // numeric 25 const numeric & _num25(void) { - const static ex e = ex(numeric(25)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(25)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex25(void) { - static ex * e = new ex(_num25()); - return *e; + static ex * e = new ex(_num25()); + return *e; } // numeric 30 const numeric & _num30(void) { - const static ex e = ex(numeric(30)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(30)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex30(void) { - static ex * e = new ex(_num30()); - return *e; + static ex * e = new ex(_num30()); + return *e; } // numeric 48 const numeric & _num48(void) { - const static ex e = ex(numeric(48)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(48)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex48(void) { - static ex * e = new ex(_num48()); - return *e; + static ex * e = new ex(_num48()); + return *e; } // numeric 60 const numeric & _num60(void) { - const static ex e = ex(numeric(60)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(60)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex60(void) { - static ex * e = new ex(_num60()); - return *e; + static ex * e = new ex(_num60()); + return *e; } // numeric 120 const numeric & _num120(void) { - const static ex e = ex(numeric(120)); - const static numeric * n = static_cast(e.bp); - return *n; + const static ex e = ex(numeric(120)); + const static numeric * n = static_cast(e.bp); + return *n; } const ex & _ex120(void) { - static ex * e = new ex(_num120()); - return *e; + static ex * e = new ex(_num120()); + return *e; } // comment skeleton for header files @@ -760,24 +760,24 @@ const ex & _ex120(void) // member functions - // default constructor, destructor, copy constructor assignment operator and helpers - // none + // default constructor, destructor, copy constructor assignment operator and helpers + // none - // other constructors - // none + // other constructors + // none - // functions overriding virtual functions from bases classes - // none - - // new virtual functions which can be overridden by derived classes - // none + // functions overriding virtual functions from bases classes + // none + + // new virtual functions which can be overridden by derived classes + // none - // non-virtual functions in this class - // none + // non-virtual functions in this class + // none // member variables // none - + // comment skeleton for implementation files diff --git a/ginac/utils.h b/ginac/utils.h index 2aff369f..b7d47c49 100644 --- a/ginac/utils.h +++ b/ginac/utils.h @@ -38,9 +38,9 @@ namespace GiNaC { template std::string ToString(const T & t) { - char buf[256]; - std::ostrstream(buf,sizeof(buf)) << t << std::ends; - return buf; + char buf[256]; + std::ostrstream(buf,sizeof(buf)) << t << std::ends; + return buf; } /** Exception class thrown by classes which provide their own series expansion @@ -50,10 +50,10 @@ class do_taylor {}; /** Exception class thrown when a singularity is encountered. */ class pole_error : public std::domain_error { public: - explicit pole_error(const std::string& what_arg, int degree); - int degree(void) const; + explicit pole_error(const std::string& what_arg, int degree); + int degree(void) const; private: - int deg; + int deg; }; // some compilers (e.g. cygwin) define a macro log2, causing confusion @@ -67,16 +67,16 @@ int compare_pointers(const void * a, const void * b); * (upper bits get cleared). */ inline unsigned rotate_left_31(unsigned n) { - // clear highest bit and shift 1 bit to the left - n=(n & 0x7FFFFFFFU) << 1; + // clear highest bit and shift 1 bit to the left + n=(n & 0x7FFFFFFFU) << 1; - // overflow? clear highest bit and set lowest bit - if (n & 0x80000000U) { - n=(n & 0x7FFFFFFFU) | 0x00000001U; - } - GINAC_ASSERT(n<0x80000000U); + // overflow? clear highest bit and set lowest bit + if (n & 0x80000000U) { + n=(n & 0x7FFFFFFFU) | 0x00000001U; + } + GINAC_ASSERT(n<0x80000000U); - return n; + return n; } /** Golden ratio hash function. */ @@ -86,9 +86,9 @@ inline unsigned golden_ratio_hash(unsigned n) #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); + 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" @@ -96,7 +96,7 @@ inline unsigned golden_ratio_hash(unsigned n) 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: + // unfortunately, not ANSI-compliant: unsigned long long l = n * 0x4f1bbcddLL; return (l & 0x7fffffffU) ^ (l >> 32); #else @@ -106,70 +106,70 @@ inline unsigned golden_ratio_hash(unsigned n) // modified from stl_algo.h: always do com(*first1,*first2) instead of comp(*first2,*first1) template + class Compare> 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)); + 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 + class OutputIterator, class Compare> 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); - } + 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) { - if (s.size() < 2) - return 0; - int sigma = 1; - for (typename std::vector::iterator i=s.begin(); i!=s.end()-1; ++i) { - for (typename std::vector::iterator j=i+1; j!=s.end(); ++j) { - if (*i == *j) - return 0; - if (*i > *j) { - iter_swap(i,j); - sigma = -sigma; - } - } - } - return sigma; + if (s.size() < 2) + return 0; + int sigma = 1; + for (typename std::vector::iterator i=s.begin(); i!=s.end()-1; ++i) { + for (typename std::vector::iterator j=i+1; j!=s.end(); ++j) { + if (*i == *j) + return 0; + if (*i > *j) { + iter_swap(i,j); + sigma = -sigma; + } + } + } + return sigma; } // Collection of `construct on first use' wrappers for safely avoiding -- 2.44.0