X-Git-Url: https://ginac.de/ginac.git//ginac.git?a=blobdiff_plain;f=ginac%2Fexpairseq.cpp;h=a67eb4e0d1504e2f525559ccb71e37e296d8348d;hb=f532e05bf7638c592ee609943c349739500480bf;hp=18aba0dbdcb8900587ce5cc746efebf5b064db80;hpb=c532971f9e99886781437912ae1655719284ac2f;p=ginac.git diff --git a/ginac/expairseq.cpp b/ginac/expairseq.cpp index 18aba0db..a67eb4e0 100644 --- a/ginac/expairseq.cpp +++ b/ginac/expairseq.cpp @@ -3,7 +3,7 @@ * Implementation of sequences of expression pairs. */ /* - * GiNaC Copyright (C) 1999-2015 Johannes Gutenberg University Mainz, Germany + * GiNaC Copyright (C) 1999-2018 Johannes Gutenberg University Mainz, Germany * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,10 +32,12 @@ #include "utils.h" #include "hash_seed.h" #include "indexed.h" +#include "compiler.h" #include #include #include +#include #include #include @@ -95,12 +97,11 @@ expairseq::expairseq(const epvector &v, const ex &oc, bool do_index_renaming) GINAC_ASSERT(is_canonical()); } -expairseq::expairseq(std::auto_ptr vp, const ex &oc, bool do_index_renaming) +expairseq::expairseq(epvector && vp, const ex &oc, bool do_index_renaming) : overall_coeff(oc) { - GINAC_ASSERT(vp.get()!=0); GINAC_ASSERT(is_a(oc)); - construct_from_epvector(*vp, do_index_renaming); + construct_from_epvector(std::move(vp), do_index_renaming); GINAC_ASSERT(is_canonical()); } @@ -111,12 +112,12 @@ expairseq::expairseq(std::auto_ptr vp, const ex &oc, bool do_index_ren void expairseq::read_archive(const archive_node &n, lst &sym_lst) { inherited::read_archive(n, sym_lst); - archive_node::archive_node_cit first = n.find_first("rest"); - archive_node::archive_node_cit last = n.find_last("coeff"); + auto first = n.find_first("rest"); + auto last = n.find_last("coeff"); ++last; seq.reserve((last-first)/2); - for (archive_node::archive_node_cit loc = first; loc < last;) { + for (auto loc = first; loc < last;) { ex rest; ex coeff; n.find_ex_by_loc(loc++, rest, sym_lst); @@ -133,11 +134,9 @@ void expairseq::read_archive(const archive_node &n, lst &sym_lst) 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; + for (auto & i : seq) { + n.add_ex("rest", i.rest); + n.add_ex("coeff", i.coeff); } n.add_ex("overall_coeff", overall_coeff); } @@ -187,8 +186,8 @@ bool expairseq::info(unsigned inf) const return true; else if (flags & status_flags::has_no_indices) return false; - for (epvector::const_iterator i = seq.begin(); i != seq.end(); ++i) { - if (i->rest.info(info_flags::has_indices)) { + for (auto & i : seq) { + if (i.rest.info(info_flags::has_indices)) { this->setflag(status_flags::has_indices); this->clearflag(status_flags::has_no_indices); return true; @@ -220,46 +219,43 @@ ex expairseq::op(size_t i) const ex expairseq::map(map_function &f) const { - std::auto_ptr v(new epvector); - v->reserve(seq.size()+1); + epvector v; + v.reserve(seq.size()+1); - epvector::const_iterator cit = seq.begin(), last = seq.end(); - while (cit != last) { - v->push_back(split_ex_to_pair(f(recombine_pair_to_ex(*cit)))); - ++cit; - } + for (auto & it : seq) + v.push_back(split_ex_to_pair(f(recombine_pair_to_ex(it)))); if (overall_coeff.is_equal(default_overall_coeff())) - return thisexpairseq(v, default_overall_coeff(), true); + return thisexpairseq(std::move(v), default_overall_coeff(), true); else { ex newcoeff = f(overall_coeff); if(is_a(newcoeff)) - return thisexpairseq(v, newcoeff, true); + return thisexpairseq(std::move(v), newcoeff, true); else { - v->push_back(split_ex_to_pair(newcoeff)); - return thisexpairseq(v, default_overall_coeff(), true); + v.push_back(split_ex_to_pair(newcoeff)); + return thisexpairseq(std::move(v), default_overall_coeff(), true); } } } /** Perform coefficient-wise automatic term rewriting rules in this class. */ -ex expairseq::eval(int level) const +ex expairseq::eval() const { - if ((level==1) && (flags &status_flags::evaluated)) + if (flags &status_flags::evaluated) return *this; - - std::auto_ptr vp = evalchildren(level); - if (vp.get() == 0) + + const epvector evaled = evalchildren(); + if (!evaled.empty()) + return dynallocate(std::move(evaled), overall_coeff).setflag(status_flags::evaluated); + else return this->hold(); - - return (new expairseq(vp, overall_coeff))->setflag(status_flags::dynallocated | status_flags::evaluated); } epvector* conjugateepvector(const epvector&epv) { - epvector *newepv = 0; - for (epvector::const_iterator i=epv.begin(); i!=epv.end(); ++i) { - if(newepv) { + epvector *newepv = nullptr; + for (auto i=epv.begin(); i!=epv.end(); ++i) { + if (newepv) { newepv->push_back(i->conjugate()); continue; } @@ -269,7 +265,7 @@ epvector* conjugateepvector(const epvector&epv) } newepv = new epvector; newepv->reserve(epv.size()); - for (epvector::const_iterator j=epv.begin(); j!=i; ++j) { + for (auto j=epv.begin(); j!=i; ++j) { newepv->push_back(*j); } newepv->push_back(x); @@ -279,14 +275,15 @@ epvector* conjugateepvector(const epvector&epv) ex expairseq::conjugate() const { - epvector* newepv = conjugateepvector(seq); + std::unique_ptr newepv(conjugateepvector(seq)); ex x = overall_coeff.conjugate(); - if (!newepv && are_ex_trivially_equal(x, overall_coeff)) { + if (newepv) { + return thisexpairseq(std::move(*newepv), x); + } + if (are_ex_trivially_equal(x, overall_coeff)) { return *this; } - ex result = thisexpairseq(newepv ? *newepv : seq, x); - delete newepv; - return result; + return thisexpairseq(seq, x); } bool expairseq::match(const ex & pattern, exmap & repl_lst) const @@ -329,7 +326,7 @@ bool expairseq::match(const ex & pattern, exmap & repl_lst) const ex p = pattern.op(i); if (has_global_wildcard && p.is_equal(global_wildcard)) continue; - exvector::iterator it = ops.begin(), itend = ops.end(); + auto it = ops.begin(), itend = ops.end(); while (it != itend) { if (it->match(p, tmp_repl)) { ops.erase(it); @@ -347,14 +344,14 @@ found: ; // it has already been matched before, in which case the matches // must be equal) size_t num = ops.size(); - std::auto_ptr vp(new epvector); - vp->reserve(num); + epvector vp; + vp.reserve(num); for (size_t i=0; ipush_back(split_ex_to_pair(ops[i])); - ex rest = thisexpairseq(vp, default_overall_coeff()); - for (exmap::const_iterator it = tmp_repl.begin(); it != tmp_repl.end(); ++it) { - if (it->first.is_equal(global_wildcard)) { - if (rest.is_equal(it->second)) { + vp.push_back(split_ex_to_pair(ops[i])); + ex rest = thisexpairseq(std::move(vp), default_overall_coeff()); + for (auto & it : tmp_repl) { + if (it.first.is_equal(global_wildcard)) { + if (rest.is_equal(it.second)) { repl_lst = tmp_repl; return true; } @@ -381,9 +378,9 @@ found: ; ex expairseq::subs(const exmap & m, unsigned options) const { - std::auto_ptr vp = subschildren(m, options); - if (vp.get()) - return ex_to(thisexpairseq(vp, overall_coeff, (options & subs_options::no_index_renaming) == 0)); + epvector subsed = subschildren(m, options); + if (!subsed.empty()) + return ex_to(thisexpairseq(std::move(subsed), overall_coeff, (options & subs_options::no_index_renaming) == 0)); else if ((options & subs_options::algebraic) && is_exactly_a(*this)) return static_cast(this)->algebraic_subs_mul(m, options); else @@ -408,12 +405,9 @@ int expairseq::compare_same_type(const basic &other) const if (cmpval!=0) return cmpval; - epvector::const_iterator cit1 = seq.begin(); - epvector::const_iterator cit2 = o.seq.begin(); - epvector::const_iterator last1 = seq.end(); - epvector::const_iterator last2 = o.seq.end(); - - for (; (cit1!=last1)&&(cit2!=last2); ++cit1, ++cit2) { + auto cit1 = seq.begin(), last1 = seq.end(); + auto cit2 = o.seq.begin(), last2 = o.seq.end(); + for (; (cit1!=last1) && (cit2!=last2); ++cit1, ++cit2) { cmpval = (*cit1).compare(*cit2); if (cmpval!=0) return cmpval; } @@ -436,13 +430,10 @@ bool expairseq::is_equal_same_type(const basic &other) const if (!overall_coeff.is_equal(o.overall_coeff)) return false; - 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; + auto cit2 = o.seq.begin(); + for (auto & cit1 : seq) { + if (!cit1.is_equal(*cit2)) + return false; ++cit2; } @@ -457,14 +448,10 @@ unsigned expairseq::return_type() const unsigned expairseq::calchash() const { unsigned v = make_hash_seed(typeid(*this)); - epvector::const_iterator i = seq.begin(); - const epvector::const_iterator end = seq.end(); - while (i != end) { - v ^= i->rest.gethash(); - // rotation spoils commutativity! + for (auto & i : seq) { + v ^= i.rest.gethash(); v = rotate_left(v); - v ^= i->coeff.gethash(); - ++i; + v ^= i.coeff.gethash(); } v ^= overall_coeff.gethash(); @@ -480,13 +467,11 @@ unsigned expairseq::calchash() const ex expairseq::expand(unsigned options) const { - std::auto_ptr vp = expandchildren(options); - if (vp.get()) - return thisexpairseq(vp, overall_coeff); - else { - // The terms have not changed, so it is safe to declare this expanded - return (options == 0) ? setflag(status_flags::expanded) : *this; + epvector expanded = expandchildren(options); + if (!expanded.empty()) { + return thisexpairseq(std::move(expanded), overall_coeff); } + return (options == 0) ? setflag(status_flags::expanded) : *this; } ////////// @@ -508,9 +493,9 @@ ex expairseq::thisexpairseq(const epvector &v, const ex &oc, bool do_index_renam return expairseq(v, oc, do_index_renaming); } -ex expairseq::thisexpairseq(std::auto_ptr vp, const ex &oc, bool do_index_renaming) const +ex expairseq::thisexpairseq(epvector && vp, const ex &oc, bool do_index_renaming) const { - return expairseq(vp, oc, do_index_renaming); + return expairseq(std::move(vp), oc, do_index_renaming); } void expairseq::printpair(const print_context & c, const expair & p, unsigned upper_precedence) const @@ -528,8 +513,8 @@ void expairseq::printseq(const print_context & c, char delim, { if (this_precedence <= upper_precedence) c.s << "("; - epvector::const_iterator it, it_last = seq.end() - 1; - for (it=seq.begin(); it!=it_last; ++it) { + auto it = seq.begin(), it_last = seq.end() - 1; + for (; it!=it_last; ++it) { printpair(c, *it, this_precedence); c.s << delim; } @@ -575,7 +560,7 @@ expair expairseq::combine_pair_with_coeff_to_pair(const expair &p, * @see expairseq::split_ex_to_pair() */ 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) @@ -614,19 +599,11 @@ bool expairseq::can_make_flat(const expair &p) const // 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); -} - void expairseq::construct_from_2_ex(const ex &lh, const ex &rh) { - if (typeid(ex_to(lh)) == typeid(*this)) { - if (typeid(ex_to(rh)) == typeid(*this)) { + const std::type_info& typeid_this = typeid(*this); + if (typeid(ex_to(lh)) == typeid_this) { + if (typeid(ex_to(rh)) == typeid_this) { if (is_a(lh) && lh.info(info_flags::has_indices) && rh.info(info_flags::has_indices)) { ex newrh=rename_dummy_indices_uniquely(lh, rh); @@ -641,7 +618,7 @@ void expairseq::construct_from_2_ex(const ex &lh, const ex &rh) construct_from_expairseq_ex(ex_to(lh), rh); return; } - } else if (typeid(ex_to(rh)) == typeid(*this)) { + } else if (typeid(ex_to(rh)) == typeid_this) { construct_from_expairseq_ex(ex_to(rh),lh); return; } @@ -690,10 +667,8 @@ void expairseq::construct_from_2_expairseq(const expairseq &s1, 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(); + auto first1 = s1.seq.begin(), last1 = s1.seq.end(); + auto first2 = s2.seq.begin(), last2 = s2.seq.end(); seq.reserve(s1.seq.size()+s2.seq.size()); @@ -733,9 +708,9 @@ void expairseq::construct_from_2_expairseq(const expairseq &s1, } if (needs_further_processing) { - epvector v = seq; - seq.clear(); - construct_from_epvector(v); + // Clear seq and start over. + epvector v = std::move(seq); + construct_from_epvector(std::move(v)); } } @@ -749,8 +724,7 @@ void expairseq::construct_from_expairseq_ex(const expairseq &s, return; } - epvector::const_iterator first = s.seq.begin(); - epvector::const_iterator last = s.seq.end(); + auto first = s.seq.begin(), last = s.seq.end(); expair p = split_ex_to_pair(e); seq.reserve(s.seq.size()+1); @@ -795,9 +769,9 @@ void expairseq::construct_from_expairseq_ex(const expairseq &s, } if (needs_further_processing) { - epvector v = seq; - seq.clear(); - construct_from_epvector(v); + // Clear seq and start over. + epvector v = std::move(seq); + construct_from_epvector(std::move(v)); } } @@ -825,28 +799,37 @@ void expairseq::construct_from_epvector(const epvector &v, bool do_index_renamin combine_same_terms_sorted_seq(); } +void expairseq::construct_from_epvector(epvector &&v, bool do_index_renaming) +{ + // 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(std::move(v), do_index_renaming); + canonicalize(); + combine_same_terms_sorted_seq(); +} + /** Combine this expairseq with argument exvector. * It cares for associativity as well as for special handling of numerics. */ void expairseq::make_flat(const exvector &v) { - exvector::const_iterator cit; - // count number of operands which are of same expairseq derived type // and their cumulative number of operands int nexpairseqs = 0; int noperands = 0; bool do_idx_rename = false; - - cit = v.begin(); - while (cit!=v.end()) { - if (typeid(ex_to(*cit)) == typeid(*this)) { + + const std::type_info& typeid_this = typeid(*this); + for (auto & cit : v) { + if (typeid(ex_to(cit)) == typeid_this) { ++nexpairseqs; - noperands += ex_to(*cit).seq.size(); + noperands += ex_to(cit).seq.size(); } if (is_a(*this) && (!do_idx_rename) && - cit->info(info_flags::has_indices)) + cit.info(info_flags::has_indices)) do_idx_rename = true; - ++cit; } // reserve seq and coeffseq which will hold all operands @@ -854,26 +837,22 @@ void expairseq::make_flat(const exvector &v) // copy elements and split off numerical part make_flat_inserter mf(v, do_idx_rename); - cit = v.begin(); - while (cit!=v.end()) { - if (typeid(ex_to(*cit)) == typeid(*this)) { - ex newfactor = mf.handle_factor(*cit, _ex1); + for (auto & cit : v) { + if (typeid(ex_to(cit)) == typeid_this) { + ex newfactor = mf.handle_factor(cit, _ex1); const expairseq &subseqref = ex_to(newfactor); 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; + for (auto & cit_s : subseqref.seq) { + seq.push_back(cit_s); } } else { - if (is_exactly_a(*cit)) - combine_overall_coeff(*cit); + if (is_exactly_a(cit)) + combine_overall_coeff(cit); else { - ex newfactor = mf.handle_factor(*cit, _ex1); + ex newfactor = mf.handle_factor(cit, _ex1); seq.push_back(split_ex_to_pair(newfactor)); } } - ++cit; } } @@ -881,24 +860,21 @@ void expairseq::make_flat(const exvector &v) * It cares for associativity as well as for special handling of numerics. */ void expairseq::make_flat(const epvector &v, bool do_index_renaming) { - epvector::const_iterator cit; - // count number of operands which are of same expairseq derived type // and their cumulative number of operands int nexpairseqs = 0; int noperands = 0; bool really_need_rename_inds = false; - - cit = v.begin(); - while (cit!=v.end()) { - if (typeid(ex_to(cit->rest)) == typeid(*this)) { + + const std::type_info& typeid_this = typeid(*this); + for (auto & cit : v) { + if (typeid(ex_to(cit.rest)) == typeid_this) { ++nexpairseqs; - noperands += ex_to(cit->rest).seq.size(); + noperands += ex_to(cit.rest).seq.size(); } if ((!really_need_rename_inds) && is_a(*this) && - cit->rest.info(info_flags::has_indices)) + cit.rest.info(info_flags::has_indices)) really_need_rename_inds = true; - ++cit; } do_index_renaming = do_index_renaming && really_need_rename_inds; @@ -907,35 +883,28 @@ void expairseq::make_flat(const epvector &v, bool do_index_renaming) make_flat_inserter mf(v, do_index_renaming); // copy elements and split off numerical part - cit = v.begin(); - while (cit!=v.end()) { - if ((typeid(ex_to(cit->rest)) == typeid(*this)) && - this->can_make_flat(*cit)) { - ex newrest = mf.handle_factor(cit->rest, cit->coeff); + for (auto & cit : v) { + if (typeid(ex_to(cit.rest)) == typeid_this && + this->can_make_flat(cit)) { + ex newrest = mf.handle_factor(cit.rest, cit.coeff); const expairseq &subseqref = ex_to(newrest); - combine_overall_coeff(ex_to(subseqref.overall_coeff), - ex_to(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(cit_s->coeff).mul_dyn(ex_to(cit->coeff)))); - //seq.push_back(combine_pair_with_coeff_to_pair(*cit_s, - // (*cit).coeff)); - ++cit_s; + combine_overall_coeff(subseqref.overall_coeff, cit.coeff); + for (auto & cit_s : subseqref.seq) { + seq.push_back(expair(cit_s.rest, + ex_to(cit_s.coeff).mul_dyn(ex_to(cit.coeff)))); } } else { - if (cit->is_canonical_numeric()) - combine_overall_coeff(mf.handle_factor(cit->rest, _ex1)); + if (cit.is_canonical_numeric()) + combine_overall_coeff(mf.handle_factor(cit.rest, _ex1)); else { - ex rest = cit->rest; - ex newrest = mf.handle_factor(rest, cit->coeff); + ex rest = cit.rest; + ex newrest = mf.handle_factor(rest, cit.coeff); if (are_ex_trivially_equal(newrest, rest)) - seq.push_back(*cit); + seq.push_back(cit); else - seq.push_back(expair(newrest, cit->coeff)); + seq.push_back(expair(newrest, cit.coeff)); } } - ++cit; } } @@ -956,10 +925,10 @@ void expairseq::combine_same_terms_sorted_seq() bool needs_further_processing = false; - epvector::iterator itin1 = seq.begin(); - epvector::iterator itin2 = itin1+1; - epvector::iterator itout = itin1; - epvector::iterator last = seq.end(); + auto itin1 = seq.begin(); + auto itin2 = itin1 + 1; + auto itout = itin1; + auto 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; @@ -989,9 +958,9 @@ void expairseq::combine_same_terms_sorted_seq() seq.erase(itout,last); if (needs_further_processing) { - epvector v = seq; - seq.clear(); - construct_from_epvector(v); + // Clear seq and start over. + epvector v = std::move(seq); + construct_from_epvector(std::move(v)); } } @@ -1002,8 +971,8 @@ bool expairseq::is_canonical() const if (seq.size() <= 1) return 1; - epvector::const_iterator it = seq.begin(), itend = seq.end(); - epvector::const_iterator it_last = it; + auto it = seq.begin(), itend = seq.end(); + auto it_last = it; for (++it; it!=itend; it_last=it, ++it) { if (!(it_last->is_less(*it) || it_last->is_equal(*it))) { if (!is_exactly_a(it_last->rest) || @@ -1029,111 +998,87 @@ bool expairseq::is_canonical() const return 1; } - /** Member-wise expand the expairs in this sequence. * * @see expairseq::expand() - * @return pointer to epvector containing expanded pairs or zero pointer, - * if no members were changed. */ -std::auto_ptr expairseq::expandchildren(unsigned options) const + * @return epvector containing expanded pairs, empty if no members + * had to be changed. */ +epvector expairseq::expandchildren(unsigned options) const { - const epvector::const_iterator last = seq.end(); - epvector::const_iterator cit = seq.begin(); + auto cit = seq.begin(), last = seq.end(); while (cit!=last) { - const ex &expanded_ex = cit->rest.expand(options); + const ex expanded_ex = cit->rest.expand(options); if (!are_ex_trivially_equal(cit->rest,expanded_ex)) { // something changed, copy seq, eval and return it - std::auto_ptr s(new epvector); - s->reserve(seq.size()); + epvector s; + 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; - } + s.insert(s.begin(), seq.begin(), cit); // copy first changed element - s->push_back(combine_ex_with_coeff_to_pair(expanded_ex, - cit2->coeff)); - ++cit2; + s.push_back(expair(expanded_ex, cit->coeff)); + ++cit; // copy rest - while (cit2!=last) { - s->push_back(combine_ex_with_coeff_to_pair(cit2->rest.expand(options), - cit2->coeff)); - ++cit2; + while (cit != last) { + s.push_back(expair(cit->rest.expand(options), cit->coeff)); + ++cit; } return s; } + ++cit; } - return std::auto_ptr(0); // signalling nothing has changed + return epvector(); // empty signalling nothing has changed } /** Member-wise evaluate the expairs in this sequence. * * @see expairseq::eval() - * @return pointer to epvector containing evaluated pairs or zero pointer, - * if no members were changed. */ -std::auto_ptr expairseq::evalchildren(int level) const + * @return epvector containing evaluated pairs, empty if no members + * had to be changed. */ +epvector expairseq::evalchildren() 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 std::auto_ptr(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(); + auto cit = seq.begin(), last = seq.end(); 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 - std::auto_ptr s(new epvector); - s->reserve(seq.size()); - + const expair evaled_pair = combine_ex_with_coeff_to_pair(cit->rest, cit->coeff); + if (unlikely(!evaled_pair.is_equal(*cit))) { + + // something changed: copy seq, eval and return it + epvector s; + 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; - } + s.insert(s.begin(), seq.begin(), cit); // copy first changed element - s->push_back(combine_ex_with_coeff_to_pair(evaled_ex, - cit2->coeff)); - ++cit2; + s.push_back(evaled_pair); + ++cit; // copy rest - while (cit2!=last) { - s->push_back(combine_ex_with_coeff_to_pair(cit2->rest.eval(level), - cit2->coeff)); - ++cit2; + while (cit != last) { + s.push_back(combine_ex_with_coeff_to_pair(cit->rest, cit->coeff)); + ++cit; } return s; } + ++cit; } - - return std::auto_ptr(0); // signalling nothing has changed + + return epvector(); // signalling nothing has changed } /** Member-wise substitute in this sequence. * * @see expairseq::subs() - * @return pointer to epvector containing pairs after application of subs, - * or NULL pointer if no members were changed. */ -std::auto_ptr expairseq::subschildren(const exmap & m, unsigned options) const + * @return epvector containing expanded pairs, empty if no members + * had to be changed. */ +epvector expairseq::subschildren(const exmap & m, unsigned options) const { // When any of the objects to be substituted is a product or power // we have to recombine the pairs because the numeric coefficients may @@ -1141,8 +1086,8 @@ std::auto_ptr expairseq::subschildren(const exmap & m, unsigned option if (!(options & (subs_options::pattern_is_product | subs_options::pattern_is_not_product))) { // Search the list of substitutions and cache our findings - for (exmap::const_iterator it = m.begin(); it != m.end(); ++it) { - if (is_exactly_a(it->first) || is_exactly_a(it->first)) { + for (auto & it : m) { + if (is_exactly_a(it.first) || is_exactly_a(it.first)) { options |= subs_options::pattern_is_product; break; } @@ -1154,27 +1099,27 @@ std::auto_ptr expairseq::subschildren(const exmap & m, unsigned option if (options & subs_options::pattern_is_product) { // Substitute in the recombined pairs - epvector::const_iterator cit = seq.begin(), last = seq.end(); + auto cit = seq.begin(), last = seq.end(); while (cit != last) { const ex &orig_ex = recombine_pair_to_ex(*cit); const ex &subsed_ex = orig_ex.subs(m, options); if (!are_ex_trivially_equal(orig_ex, subsed_ex)) { - // Something changed, copy seq, subs and return it - std::auto_ptr s(new epvector); - s->reserve(seq.size()); + // Something changed: copy seq, subs and return it + epvector s; + s.reserve(seq.size()); // Copy parts of seq which are known not to have changed - s->insert(s->begin(), seq.begin(), cit); + s.insert(s.begin(), seq.begin(), cit); // Copy first changed element - s->push_back(split_ex_to_pair(subsed_ex)); + s.push_back(split_ex_to_pair(subsed_ex)); ++cit; // Copy rest while (cit != last) { - s->push_back(split_ex_to_pair(recombine_pair_to_ex(*cit).subs(m, options))); + s.push_back(split_ex_to_pair(recombine_pair_to_ex(*cit).subs(m, options))); ++cit; } return s; @@ -1186,26 +1131,27 @@ std::auto_ptr expairseq::subschildren(const exmap & m, unsigned option } else { // Substitute only in the "rest" part of the pairs - epvector::const_iterator cit = seq.begin(), last = seq.end(); + auto cit = seq.begin(), last = seq.end(); while (cit != last) { - const ex &subsed_ex = cit->rest.subs(m, options); - if (!are_ex_trivially_equal(cit->rest, subsed_ex)) { + const ex subsed_rest = cit->rest.subs(m, options); + const expair subsed_pair = combine_ex_with_coeff_to_pair(subsed_rest, cit->coeff); + if (!subsed_pair.is_equal(*cit)) { - // Something changed, copy seq, subs and return it - std::auto_ptr s(new epvector); - s->reserve(seq.size()); + // Something changed: copy seq, subs and return it + epvector s; + s.reserve(seq.size()); // Copy parts of seq which are known not to have changed - s->insert(s->begin(), seq.begin(), cit); + s.insert(s.begin(), seq.begin(), cit); // Copy first changed element - s->push_back(combine_ex_with_coeff_to_pair(subsed_ex, cit->coeff)); + s.push_back(subsed_pair); ++cit; // Copy rest while (cit != last) { - s->push_back(combine_ex_with_coeff_to_pair(cit->rest.subs(m, options), cit->coeff)); + s.push_back(combine_ex_with_coeff_to_pair(cit->rest.subs(m, options), cit->coeff)); ++cit; } return s; @@ -1216,7 +1162,7 @@ std::auto_ptr expairseq::subschildren(const exmap & m, unsigned option } // Nothing has changed - return std::auto_ptr(0); + return epvector(); } //////////