* Implementation of GiNaC's sums of expressions. */
/*
- * 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
GINAC_ASSERT(is_canonical());
}
+add::add(epvector && vp)
+{
+ overall_coeff = _ex0;
+ construct_from_epvector(std::move(vp));
+ GINAC_ASSERT(is_canonical());
+}
+
add::add(epvector && vp, const ex & oc)
{
overall_coeff = oc;
return true;
return overall_coeff.info(inf);
}
- case info_flags::algebraic: {
- epvector::const_iterator i = seq.begin(), end = seq.end();
- while (i != end) {
- if ((recombine_pair_to_ex(*i).info(inf)))
- return true;
- ++i;
- }
- return false;
- }
}
return inherited::info(inf);
}
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));
+ coeffseq_cliff.push_back(expair(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(expair(restcoeff, i.coeff));
nonscalar = true;
}
}
- coeffseq.push_back(combine_ex_with_coeff_to_pair(restcoeff, i.coeff));
+ coeffseq.push_back(expair(restcoeff, i.coeff));
}
}
- return (new add(nonscalar ? std::move(coeffseq_cliff) : std::move(coeffseq),
- n==0 ? overall_coeff : _ex0))->setflag(status_flags::dynallocated);
+ return dynallocate<add>(nonscalar ? std::move(coeffseq_cliff) : std::move(coeffseq),
+ n==0 ? overall_coeff : _ex0);
}
/** Perform automatic term rewriting rules in this class. In the following
* an expression that contain a plain number.
* - +(;c) -> c
* - +(x;0) -> x
- *
- * @param level cut-off in recursive evaluation */
-ex add::eval(int level) const
+ */
+ex add::eval() const
{
- epvector evaled = evalchildren(level);
+ if (flags & status_flags::evaluated) {
+ GINAC_ASSERT(seq.size()>0);
+ GINAC_ASSERT(seq.size()>1 || !overall_coeff.is_zero());
+ return *this;
+ }
+
+ const epvector evaled = evalchildren();
if (unlikely(!evaled.empty())) {
- // do more evaluation later
- return (new add(std::move(evaled), overall_coeff))->
- setflag(status_flags::dynallocated);
+ // start over evaluating a new object
+ return dynallocate<add>(std::move(evaled), overall_coeff);
}
#ifdef DO_GINAC_ASSERT
GINAC_ASSERT(!is_exactly_a<add>(i.rest));
}
#endif // def DO_GINAC_ASSERT
-
- if (flags & status_flags::evaluated) {
- GINAC_ASSERT(seq.size()>0);
- GINAC_ASSERT(seq.size()>1 || !overall_coeff.is_zero());
- return *this;
- }
-
- int seq_size = seq.size();
+
+ size_t seq_size = seq.size();
if (seq_size == 0) {
// +(;c) -> c
return overall_coeff;
} 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
- int terms_to_collect = 0;
- for (auto & it : seq) {
- if (unlikely(is_a<numeric>(it.rest)))
- ++terms_to_collect;
- }
- if (terms_to_collect) {
- epvector s;
- s.reserve(seq_size - terms_to_collect);
- numeric oc = *_num1_p;
- for (auto & it : seq) {
- if (unlikely(is_a<numeric>(it.rest)))
- oc = oc.mul(ex_to<numeric>(it.rest)).mul(ex_to<numeric>(it.coeff));
- else
- s.push_back(it);
- }
- return (new add(std::move(s), ex_to<numeric>(overall_coeff).add_dyn(oc)))
- ->setflag(status_flags::dynallocated);
- }
-
+
return this->hold();
}
if (all_matrices)
return sum + overall_coeff;
else
- return (new add(std::move(s), overall_coeff))->setflag(status_flags::dynallocated);
+ return dynallocate<add>(std::move(s), overall_coeff);
}
ex add::conjugate() const
if (!rp.is_zero())
v.push_back(split_ex_to_pair(rp));
}
- return (new add(std::move(v), overall_coeff.real_part()))
- -> setflag(status_flags::dynallocated);
+ return dynallocate<add>(std::move(v), overall_coeff.real_part());
}
ex add::imag_part() const
if (!ip.is_zero())
v.push_back(split_ex_to_pair(ip));
}
- return (new add(std::move(v), overall_coeff.imag_part()))
- -> setflag(status_flags::dynallocated);
+ return dynallocate<add>(std::move(v), overall_coeff.imag_part());
}
ex add::eval_ncmul(const exvector & v) const
// than the default implementation in basic::derivative() although
// if performs the same function (differentiate each term).
for (auto & it : seq)
- s.push_back(combine_ex_with_coeff_to_pair(it.rest.diff(y), it.coeff));
+ s.push_back(expair(it.rest.diff(y), it.coeff));
- return (new add(std::move(s), _ex0))->setflag(status_flags::dynallocated);
+ return dynallocate<add>(std::move(s));
}
int add::compare_same_type(const basic & other) const
// Note: do_index_renaming is ignored because it makes no sense for an add.
ex add::thisexpairseq(const epvector & v, const ex & oc, bool do_index_renaming) const
{
- return (new add(v,oc))->setflag(status_flags::dynallocated);
+ return dynallocate<add>(v, oc);
}
// Note: do_index_renaming is ignored because it makes no sense for an add.
ex add::thisexpairseq(epvector && vp, const ex & oc, bool do_index_renaming) const
{
- return (new add(std::move(vp), oc))->setflag(status_flags::dynallocated);
+ return dynallocate<add>(std::move(vp), oc);
}
expair add::split_ex_to_pair(const ex & e) const
if (is_exactly_a<mul>(e)) {
const mul &mulref(ex_to<mul>(e));
const ex &numfactor = mulref.overall_coeff;
- mul *mulcopyp = new mul(mulref);
- mulcopyp->overall_coeff = _ex1;
- mulcopyp->clearflag(status_flags::evaluated);
- mulcopyp->clearflag(status_flags::hash_calculated);
- mulcopyp->setflag(status_flags::dynallocated);
- return expair(*mulcopyp,numfactor);
+ if (numfactor.is_equal(_ex1))
+ return expair(e, _ex1);
+ mul & mulcopy = dynallocate<mul>(mulref);
+ mulcopy.overall_coeff = _ex1;
+ mulcopy.clearflag(status_flags::evaluated | status_flags::hash_calculated);
+ return expair(mulcopy, numfactor);
}
return expair(e,_ex1);
}
if (is_exactly_a<mul>(e)) {
const mul &mulref(ex_to<mul>(e));
const ex &numfactor = mulref.overall_coeff;
- mul *mulcopyp = new mul(mulref);
- mulcopyp->overall_coeff = _ex1;
- mulcopyp->clearflag(status_flags::evaluated);
- mulcopyp->clearflag(status_flags::hash_calculated);
- mulcopyp->setflag(status_flags::dynallocated);
+ if (likely(numfactor.is_equal(_ex1)))
+ return expair(e, c);
+ mul & mulcopy = dynallocate<mul>(mulref);
+ mulcopy.overall_coeff = _ex1;
+ mulcopy.clearflag(status_flags::evaluated | status_flags::hash_calculated);
if (c.is_equal(_ex1))
- return expair(*mulcopyp, numfactor);
- else if (numfactor.is_equal(_ex1))
- return expair(*mulcopyp, c);
+ return expair(mulcopy, numfactor);
else
- return expair(*mulcopyp, ex_to<numeric>(numfactor).mul_dyn(ex_to<numeric>(c)));
+ return expair(mulcopy, ex_to<numeric>(numfactor).mul_dyn(ex_to<numeric>(c)));
} else if (is_exactly_a<numeric>(e)) {
if (c.is_equal(_ex1))
return expair(e, _ex1);
+ if (e.is_equal(_ex1))
+ return expair(c, _ex1);
return expair(ex_to<numeric>(e).mul_dyn(ex_to<numeric>(c)), _ex1);
}
return expair(e, c);
if (ex_to<numeric>(p.coeff).is_equal(*_num1_p))
return p.rest;
else
- return (new mul(p.rest,p.coeff))->setflag(status_flags::dynallocated);
+ return dynallocate<mul>(p.rest, p.coeff);
}
ex add::expand(unsigned options) const
if (expanded.empty())
return (options == 0) ? setflag(status_flags::expanded) : *this;
- return (new add(std::move(expanded), overall_coeff))->setflag(status_flags::dynallocated |
- (options == 0 ? status_flags::expanded : 0));
+ return dynallocate<add>(std::move(expanded), overall_coeff).setflag(options == 0 ? status_flags::expanded : 0);
}
} // namespace GiNaC