]> www.ginac.de Git - ginac.git/blobdiff - ginac/expairseq.cpp
Add some minor optimizations.
[ginac.git] / ginac / expairseq.cpp
index 6057a85ef0c0f14a3303058ae9cbd7d04a24e16c..b29f3802c13f2be0f0a55977d6b129c00dd2cdad 100644 (file)
@@ -3,7 +3,7 @@
  *  Implementation of sequences of expression pairs. */
 
 /*
- *  GiNaC Copyright (C) 1999-2008 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
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include <iostream>
-#include <algorithm>
-#include <string>
-#include <stdexcept>
-#include <iterator>
-
 #include "expairseq.h"
 #include "lst.h"
 #include "add.h"
 #include "archive.h"
 #include "operators.h"
 #include "utils.h"
+#include "hash_seed.h"
 #include "indexed.h"
+#include "compiler.h"
 
+#include <algorithm>
 #if EXPAIRSEQ_USE_HASHTAB
 #include <cmath>
 #endif // EXPAIRSEQ_USE_HASHTAB
+#include <iostream>
+#include <iterator>
+#include <stdexcept>
+#include <string>
 
 namespace GiNaC {
 
@@ -141,11 +142,9 @@ expairseq::expairseq(std::auto_ptr<epvector> vp, const ex &oc, bool do_index_ren
 // archiving
 //////////
 
-expairseq::expairseq(const archive_node &n, lst &sym_lst) : inherited(n, sym_lst)
-#if EXPAIRSEQ_USE_HASHTAB
-       , hashtabsize(0)
-#endif
+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");
        ++last;
@@ -177,7 +176,6 @@ void expairseq::archive(archive_node &n) const
        n.add_ex("overall_coeff", overall_coeff);
 }
 
-DEFAULT_UNARCHIVE(expairseq)
 
 //////////
 // functions overriding virtual functions from base classes
@@ -374,23 +372,10 @@ ex expairseq::conjugate() const
                return *this;
        }
        ex result = thisexpairseq(newepv ? *newepv : seq, x);
-       if (newepv) {
-               delete newepv;
-       }
+       delete newepv;
        return result;
 }
 
-bool expairseq::is_polynomial(const ex & var) const
-{
-       if (!is_exactly_a<add>(*this) && !is_exactly_a<mul>(*this))
-               return basic::is_polynomial(var);
-       for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) {
-               if (!(i->rest).is_polynomial(var))
-                       return false;
-       }
-       return true;
-}
-
 bool expairseq::match(const ex & pattern, exmap & repl_lst) const
 {
        // This differs from basic::match() because we want "a+b+c+d" to
@@ -410,6 +395,12 @@ bool expairseq::match(const ex & pattern, exmap & repl_lst) const
                        }
                }
 
+               // Even if the expression does not match the pattern, some of
+               // its subexpressions could match it. For example, x^5*y^(-1)
+               // does not match the pattern $0^5, but its subexpression x^5
+               // does. So, save repl_lst in order to not add bogus entries.
+               exmap tmp_repl = repl_lst;
+
                // Unfortunately, this is an O(N^2) operation because we can't
                // sort the pattern in a useful way...
 
@@ -427,7 +418,7 @@ bool expairseq::match(const ex & pattern, exmap & repl_lst) const
                                continue;
                        exvector::iterator it = ops.begin(), itend = ops.end();
                        while (it != itend) {
-                               if (it->match(p, repl_lst)) {
+                               if (it->match(p, tmp_repl)) {
                                        ops.erase(it);
                                        goto found;
                                }
@@ -448,10 +439,16 @@ found:            ;
                        for (size_t i=0; i<num; i++)
                                vp->push_back(split_ex_to_pair(ops[i]));
                        ex rest = thisexpairseq(vp, default_overall_coeff());
-                       for (exmap::const_iterator it = repl_lst.begin(); it != repl_lst.end(); ++it) {
-                               if (it->first.is_equal(global_wildcard))
-                                       return rest.is_equal(it->second);
+                       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)) {
+                                               repl_lst = tmp_repl;
+                                               return true;
+                                       }
+                                       return false;
+                               }
                        }
+                       repl_lst = tmp_repl;
                        repl_lst[global_wildcard] = rest;
                        return true;
 
@@ -459,7 +456,11 @@ found:             ;
 
                        // No global wildcard, then the match fails if there are any
                        // unmatched terms left
-                       return ops.empty();
+                       if (ops.empty()) {
+                               repl_lst = tmp_repl;
+                               return true;
+                       }
+                       return false;
                }
        }
        return inherited::match(pattern, repl_lst);
@@ -469,7 +470,7 @@ ex expairseq::subs(const exmap & m, unsigned options) const
 {
        std::auto_ptr<epvector> vp = subschildren(m, options);
        if (vp.get())
-               return ex_to<basic>(thisexpairseq(vp, overall_coeff, true));
+               return ex_to<basic>(thisexpairseq(vp, overall_coeff, (options & subs_options::no_index_renaming) == 0));
        else if ((options & subs_options::algebraic) && is_exactly_a<mul>(*this))
                return static_cast<const mul *>(this)->algebraic_subs_mul(m, options);
        else
@@ -615,8 +616,7 @@ unsigned expairseq::return_type() const
 
 unsigned expairseq::calchash() const
 {
-       const void* this_tinfo = (const void*)typeid(*this).name();
-       unsigned v = golden_ratio_hash((p_int)this_tinfo);
+       unsigned v = make_hash_seed(typeid(*this));
        epvector::const_iterator i = seq.begin();
        const epvector::const_iterator end = seq.end();
        while (i != end) {
@@ -662,7 +662,7 @@ ex expairseq::expand(unsigned options) const
  *  has (at least) two possible different semantics but we want to inherit
  *  methods thus avoiding code duplication.  Sometimes a method in expairseq
  *  has to create a new one of the same semantics, which cannot be done by a
- *  ctor because the name (add, mul,...) is unknown on the expaiseq level.  In
+ *  ctor because the name (add, mul,...) is unknown on the expairseq level.  In
  *  order for this trick to work a derived class must of course override this
  *  definition. */
 ex expairseq::thisexpairseq(const epvector &v, const ex &oc, bool do_index_renaming) const
@@ -890,7 +890,7 @@ void expairseq::construct_from_2_ex(const ex &lh, const ex &rh)
 }
 
 void expairseq::construct_from_2_expairseq(const expairseq &s1,
-                                                                                  const expairseq &s2)
+                                           const expairseq &s2)
 {
        combine_overall_coeff(s1.overall_coeff);
        combine_overall_coeff(s2.overall_coeff);
@@ -945,7 +945,7 @@ void expairseq::construct_from_2_expairseq(const expairseq &s1,
 }
 
 void expairseq::construct_from_expairseq_ex(const expairseq &s,
-                                                                                       const ex &e)
+                                            const ex &e)
 {
        combine_overall_coeff(s.overall_coeff);
        if (is_exactly_a<numeric>(e)) {
@@ -1010,7 +1010,7 @@ void expairseq::construct_from_exvector(const exvector &v)
 {
        // 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())
+       //                  +(...,x,*(x,c1),*(x,c2)) -> +(...,*(x,1+c1+c2)) (c1, c2 numeric)
        //                  (same for (+,*) -> (*,^)
 
        make_flat(v);
@@ -1026,8 +1026,8 @@ void expairseq::construct_from_epvector(const epvector &v, bool do_index_renamin
 {
        // 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 (+,*) -> (*,^)
+       //                  +(...,x,*(x,c1),*(x,c2)) -> +(...,*(x,1+c1+c2)) (c1, c2 numeric)
+       //                  same for (+,*) -> (*,^)
 
        make_flat(v, do_index_renaming);
 #if EXPAIRSEQ_USE_HASHTAB
@@ -1449,7 +1449,7 @@ bool expairseq::has_coeff_0() const
 }
 
 void expairseq::add_numerics_to_hashtab(epvector::iterator first_numeric,
-                                                                               epvector::const_iterator last_non_zero)
+                                        epvector::const_iterator last_non_zero)
 {
        if (first_numeric == seq.end()) return; // no numerics
        
@@ -1525,7 +1525,7 @@ bool expairseq::is_canonical() const
                return 1;
        
 #if EXPAIRSEQ_USE_HASHTAB
-       if (hashtabsize > 0) return 1; // not canoncalized
+       if (hashtabsize > 0) return 1; // not canonicalized
 #endif // EXPAIRSEQ_USE_HASHTAB
        
        epvector::const_iterator it = seq.begin(), itend = seq.end();
@@ -1611,7 +1611,7 @@ std::auto_ptr<epvector> expairseq::evalchildren(int level) const
        // returns a pointer to a newly created epvector otherwise
        // (which has to be deleted somewhere else)
 
-       if (level==1)
+       if (likely(level==1))
                return std::auto_ptr<epvector>(0);
        
        if (level == -max_recursion_level)