]> www.ginac.de Git - ginac.git/blobdiff - ginac/add.cpp
Happy New Year!
[ginac.git] / ginac / add.cpp
index 74c8d815ca1a6fe0fd197138a86b18c0f8ab8232..6c83e2a7028ba67b83fa9e4b2ba6e308c6bf3236 100644 (file)
@@ -3,7 +3,7 @@
  *  Implementation of GiNaC's sums of expressions. */
 
 /*
- *  GiNaC Copyright (C) 1999-2015 Johannes Gutenberg University Mainz, Germany
+ *  GiNaC Copyright (C) 1999-2019 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
@@ -86,6 +86,13 @@ add::add(const epvector & v, const ex & oc)
        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;
@@ -240,15 +247,6 @@ bool add::info(unsigned inf) const
                                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);
 }
@@ -307,18 +305,18 @@ ex add::coeff(const ex & s, int n) const
                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
@@ -326,15 +324,19 @@ ex add::coeff(const ex & s, int n) const
  *  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
-{
-       epvector evaled = evalchildren(level);
-       if (!evaled.empty()) {
-               // do more evaluation later
-               return (new add(std::move(evaled), overall_coeff))->
-                       setflag(status_flags::dynallocated);
+ */
+ex add::eval() const
+{
+       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())) {
+               // start over evaluating a new object
+               return dynallocate<add>(std::move(evaled), overall_coeff);
        }
 
 #ifdef DO_GINAC_ASSERT
@@ -342,14 +344,8 @@ ex add::eval(int level) const
                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;
@@ -359,28 +355,7 @@ 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
-       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();
 }
 
@@ -411,7 +386,7 @@ ex add::evalm() const
        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
@@ -452,8 +427,7 @@ ex add::real_part() 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
@@ -470,8 +444,7 @@ 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
@@ -495,9 +468,9 @@ ex add::derivative(const symbol & y) 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
@@ -524,13 +497,13 @@ return_type_t add::return_type_tinfo() 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
@@ -538,12 +511,12 @@ 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);
 }
@@ -555,20 +528,20 @@ expair add::combine_ex_with_coeff_to_pair(const ex & e,
        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);
@@ -593,7 +566,7 @@ ex add::recombine_pair_to_ex(const expair & p) const
        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
@@ -602,8 +575,7 @@ 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