X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Fadd.cpp;h=36bb2011013efee1abbe28fbc3ea38433dc1791d;hp=5f714fef36b4a393ae00d34c12cd0df7db8c5f45;hb=acae7ab5a4dc94d1f54ba794f32f5764cdb4d704;hpb=5631205a455c42a32ce9d50b6c99df0f1ad6b4e7 diff --git a/ginac/add.cpp b/ginac/add.cpp index 5f714fef..36bb2011 100644 --- a/ginac/add.cpp +++ b/ginac/add.cpp @@ -3,7 +3,7 @@ * Implementation of GiNaC's sums of expressions. */ /* - * GiNaC Copyright (C) 1999-2009 Johannes Gutenberg University Mainz, Germany + * GiNaC Copyright (C) 1999-2015 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 @@ -28,6 +28,7 @@ #include "utils.h" #include "clifford.h" #include "ncmul.h" +#include "compiler.h" #include #include @@ -85,11 +86,10 @@ add::add(const epvector & v, const ex & oc) GINAC_ASSERT(is_canonical()); } -add::add(std::auto_ptr vp, const ex & oc) +add::add(epvector && vp, const ex & oc) { - GINAC_ASSERT(vp.get()!=0); overall_coeff = oc; - construct_from_epvector(*vp); + construct_from_epvector(std::move(vp)); GINAC_ASSERT(is_canonical()); } @@ -259,6 +259,16 @@ bool add::info(unsigned inf) const return inherited::info(inf); } +bool add::is_polynomial(const ex & var) const +{ + for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) { + if (!(i->rest).is_polynomial(var)) { + return false; + } + } + return true; +} + int add::degree(const ex & s) const { int deg = std::numeric_limits::min(); @@ -295,9 +305,9 @@ int add::ldegree(const ex & s) const ex add::coeff(const ex & s, int n) const { - std::auto_ptr coeffseq(new epvector); - std::auto_ptr coeffseq_cliff(new epvector); - char rl = clifford_max_label(s); + epvector coeffseq; + epvector coeffseq_cliff; + int rl = clifford_max_label(s); bool do_clifford = (rl != -1); bool nonscalar = false; @@ -305,21 +315,21 @@ ex add::coeff(const ex & s, int n) const epvector::const_iterator i = seq.begin(), end = seq.end(); while (i != end) { ex restcoeff = i->rest.coeff(s, n); - if (!restcoeff.is_zero()) { - if (do_clifford) { - if (clifford_max_label(restcoeff) == -1) { - coeffseq_cliff->push_back(combine_ex_with_coeff_to_pair(ncmul(restcoeff, dirac_ONE(rl)), i->coeff)); + if (!restcoeff.is_zero()) { + if (do_clifford) { + if (clifford_max_label(restcoeff) == -1) { + coeffseq_cliff.push_back(combine_ex_with_coeff_to_pair(ncmul(restcoeff, dirac_ONE(rl)), i->coeff)); } else { - coeffseq_cliff->push_back(combine_ex_with_coeff_to_pair(restcoeff, i->coeff)); + coeffseq_cliff.push_back(combine_ex_with_coeff_to_pair(restcoeff, i->coeff)); nonscalar = true; - } + } } - coeffseq->push_back(combine_ex_with_coeff_to_pair(restcoeff, i->coeff)); + coeffseq.push_back(combine_ex_with_coeff_to_pair(restcoeff, i->coeff)); } ++i; } - return (new add(nonscalar ? coeffseq_cliff : coeffseq, + return (new add(nonscalar ? std::move(coeffseq_cliff) : std::move(coeffseq), n==0 ? overall_coeff : _ex0))->setflag(status_flags::dynallocated); } @@ -332,20 +342,17 @@ ex add::coeff(const ex & s, int n) const * @param level cut-off in recursive evaluation */ ex add::eval(int level) const { - std::auto_ptr evaled_seqp = evalchildren(level); - if (evaled_seqp.get()) { + epvector evaled = evalchildren(level); + if (!evaled.empty()) { // do more evaluation later - return (new add(evaled_seqp, overall_coeff))-> - setflag(status_flags::dynallocated); + return (new add(std::move(evaled), overall_coeff))-> + setflag(status_flags::dynallocated); } - + #ifdef DO_GINAC_ASSERT epvector::const_iterator i = seq.begin(), end = seq.end(); while (i != end) { GINAC_ASSERT(!is_exactly_a(i->rest)); - if (is_exactly_a(i->rest)) - dbgprint(); - GINAC_ASSERT(!is_exactly_a(i->rest)); ++i; } #endif // def DO_GINAC_ASSERT @@ -366,6 +373,33 @@ ex add::eval(int level) const } else if (!overall_coeff.is_zero() && seq[0].rest.return_type() != return_types::commutative) { throw (std::logic_error("add::eval(): sum of non-commutative objects has non-zero numeric term")); } + + // if any terms in the sum still are purely numeric, then they are more + // appropriately collected into the overall coefficient + epvector::const_iterator last = seq.end(); + epvector::const_iterator j = seq.begin(); + int terms_to_collect = 0; + while (j != last) { + if (unlikely(is_a(j->rest))) + ++terms_to_collect; + ++j; + } + if (terms_to_collect) { + epvector s; + s.reserve(seq_size - terms_to_collect); + numeric oc = *_num1_p; + j = seq.begin(); + while (j != last) { + if (unlikely(is_a(j->rest))) + oc = oc.mul(ex_to(j->rest)).mul(ex_to(j->coeff)); + else + s.push_back(*j); + ++j; + } + return (new add(std::move(s), ex_to(overall_coeff).add_dyn(oc))) + ->setflag(status_flags::dynallocated); + } + return this->hold(); } @@ -373,8 +407,8 @@ ex add::evalm() const { // Evaluate children first and add up all matrices. Stop if there's one // term that is not a matrix. - std::auto_ptr s(new epvector); - s->reserve(seq.size()); + epvector s; + s.reserve(seq.size()); bool all_matrices = true; bool first_term = true; @@ -383,7 +417,7 @@ ex add::evalm() const epvector::const_iterator it = seq.begin(), itend = seq.end(); while (it != itend) { const ex &m = recombine_pair_to_ex(*it).evalm(); - s->push_back(split_ex_to_pair(m)); + s.push_back(split_ex_to_pair(m)); if (is_a(m)) { if (first_term) { sum = ex_to(m); @@ -398,7 +432,7 @@ ex add::evalm() const if (all_matrices) return sum + overall_coeff; else - return (new add(s, overall_coeff))->setflag(status_flags::dynallocated); + return (new add(std::move(s), overall_coeff))->setflag(status_flags::dynallocated); } ex add::conjugate() const @@ -477,18 +511,18 @@ ex add::eval_ncmul(const exvector & v) const * @see ex::diff */ ex add::derivative(const symbol & y) const { - std::auto_ptr s(new epvector); - s->reserve(seq.size()); + epvector s; + s.reserve(seq.size()); // Only differentiate the "rest" parts of the expairs. This is faster // than the default implementation in basic::derivative() although // if performs the same function (differentiate each term). epvector::const_iterator i = seq.begin(), end = seq.end(); while (i != end) { - s->push_back(combine_ex_with_coeff_to_pair(i->rest.diff(y), i->coeff)); + s.push_back(combine_ex_with_coeff_to_pair(i->rest.diff(y), i->coeff)); ++i; } - return (new add(s, _ex0))->setflag(status_flags::dynallocated); + return (new add(std::move(s), _ex0))->setflag(status_flags::dynallocated); } int add::compare_same_type(const basic & other) const @@ -519,9 +553,9 @@ ex add::thisexpairseq(const epvector & v, const ex & oc, bool do_index_renaming) } // Note: do_index_renaming is ignored because it makes no sense for an add. -ex add::thisexpairseq(std::auto_ptr vp, const ex & oc, bool do_index_renaming) const +ex add::thisexpairseq(epvector && vp, const ex & oc, bool do_index_renaming) const { - return (new add(vp,oc))->setflag(status_flags::dynallocated); + return (new add(std::move(vp), oc))->setflag(status_flags::dynallocated); } expair add::split_ex_to_pair(const ex & e) const @@ -540,7 +574,7 @@ expair add::split_ex_to_pair(const ex & e) const } expair add::combine_ex_with_coeff_to_pair(const ex & e, - const ex & c) const + const ex & c) const { GINAC_ASSERT(is_exactly_a(c)); if (is_exactly_a(e)) { @@ -566,7 +600,7 @@ expair add::combine_ex_with_coeff_to_pair(const ex & e, } expair add::combine_pair_with_coeff_to_pair(const expair & p, - const ex & c) const + const ex & c) const { GINAC_ASSERT(is_exactly_a(p.coeff)); GINAC_ASSERT(is_exactly_a(c)); @@ -578,7 +612,7 @@ expair add::combine_pair_with_coeff_to_pair(const expair & p, return expair(p.rest,ex_to(p.coeff).mul_dyn(ex_to(c))); } - + ex add::recombine_pair_to_ex(const expair & p) const { if (ex_to(p.coeff).is_equal(*_num1_p)) @@ -589,13 +623,12 @@ ex add::recombine_pair_to_ex(const expair & p) const ex add::expand(unsigned options) const { - std::auto_ptr vp = expandchildren(options); - if (vp.get() == 0) { - // the terms have not changed, so it is safe to declare this expanded + epvector expanded = expandchildren(options); + if (expanded.empty()) return (options == 0) ? setflag(status_flags::expanded) : *this; - } - return (new add(vp, overall_coeff))->setflag(status_flags::dynallocated | (options == 0 ? status_flags::expanded : 0)); + return (new add(std::move(expanded), overall_coeff))->setflag(status_flags::dynallocated | + (options == 0 ? status_flags::expanded : 0)); } } // namespace GiNaC