]> www.ginac.de Git - ginac.git/blobdiff - ginac/expairseq.cpp
Make add::eval(), mul::eval() work without compromise.
[ginac.git] / ginac / expairseq.cpp
index 67099f5796395e7d012fb1d4a13484278675e800..9ca4070934e41fd60ea9bc111153279c07fbe0d4 100644 (file)
 #include "utils.h"
 #include "hash_seed.h"
 #include "indexed.h"
+#include "compiler.h"
 
 #include <algorithm>
 #include <iostream>
 #include <iterator>
+#include <memory>
 #include <stdexcept>
 #include <string>
 
@@ -242,9 +244,9 @@ ex expairseq::eval(int level) const
        if ((level==1) && (flags &status_flags::evaluated))
                return *this;
 
-       epvector evaled = evalchildren(level);
+       const epvector evaled = evalchildren(level);
        if (!evaled.empty())
-               return (new expairseq(std::move(evaled), overall_coeff))->setflag(status_flags::dynallocated | status_flags::evaluated);
+               return dynallocate<expairseq>(std::move(evaled), overall_coeff).setflag(status_flags::evaluated);
        else
                return this->hold();
 }
@@ -558,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)
@@ -714,8 +716,8 @@ void expairseq::construct_from_2_expairseq(const expairseq &s1,
        }
        
        if (needs_further_processing) {
-               epvector v = seq;
-               seq.clear();
+               // Clear seq and start over.
+               epvector v = std::move(seq);
                construct_from_epvector(std::move(v));
        }
 }
@@ -775,8 +777,8 @@ void expairseq::construct_from_expairseq_ex(const expairseq &s,
        }
 
        if (needs_further_processing) {
-               epvector v = seq;
-               seq.clear();
+               // Clear seq and start over.
+               epvector v = std::move(seq);
                construct_from_epvector(std::move(v));
        }
 }
@@ -963,8 +965,8 @@ void expairseq::combine_same_terms_sorted_seq()
                seq.erase(itout,last);
 
        if (needs_further_processing) {
-               epvector v = seq;
-               seq.clear();
+               // Clear seq and start over.
+               epvector v = std::move(seq);
                construct_from_epvector(std::move(v));
        }
 }
@@ -1012,7 +1014,7 @@ epvector expairseq::expandchildren(unsigned options) const
 {
        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
@@ -1020,25 +1022,20 @@ epvector expairseq::expandchildren(unsigned options) const
                        s.reserve(seq.size());
                        
                        // copy parts of seq which are known not to have changed
-                       auto 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;
        }
        
@@ -1053,42 +1050,35 @@ epvector expairseq::expandchildren(unsigned options) const
  *    had to be changed. */
 epvector expairseq::evalchildren(int level) const
 {
-       if (level==1)
-               return epvector();  // nothing had to be evaluated
-       
        if (level == -max_recursion_level)
                throw(std::runtime_error("max recursion level reached"));
-       
-       --level;
+
        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
+               const ex evaled_rest = level==1 ? cit->rest : cit->rest.eval(level-1);
+               const expair evaled_pair = combine_ex_with_coeff_to_pair(evaled_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
-                       auto 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) {
+                               const ex evaled_rest = level==1 ? cit->rest : cit->rest.eval(level-1);
+                               s.push_back(combine_ex_with_coeff_to_pair(evaled_rest, cit->coeff));
+                               ++cit;
                        }
-                       return std::move(s);
+                       return s;
                }
+
                ++cit;
        }
 
@@ -1128,7 +1118,7 @@ epvector expairseq::subschildren(const exmap & m, unsigned options) const
                        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
+                               // Something changed: copy seq, subs and return it
                                epvector s;
                                s.reserve(seq.size());
 
@@ -1156,10 +1146,11 @@ epvector expairseq::subschildren(const exmap & m, unsigned options) const
                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
+                               // Something changed: copy seq, subs and return it
                                epvector s;
                                s.reserve(seq.size());
 
@@ -1167,7 +1158,7 @@ epvector expairseq::subschildren(const exmap & m, unsigned options) const
                                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