]> www.ginac.de Git - ginac.git/blobdiff - ginac/expairseq.cpp
Fix mul::conjugate().
[ginac.git] / ginac / expairseq.cpp
index bff206f9b42c5f2c4329f704d2a4400da010658c..90ec763528c7374542eac6e026da263b7e7de33f 100644 (file)
@@ -3,7 +3,7 @@
  *  Implementation of sequences of expression pairs. */
 
 /*
- *  GiNaC Copyright (C) 1999-2006 Johannes Gutenberg University Mainz, Germany
+ *  GiNaC Copyright (C) 1999-2011 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 "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 <algorithm>
 #if EXPAIRSEQ_USE_HASHTAB
 #include <cmath>
 #endif // EXPAIRSEQ_USE_HASHTAB
+#include <iostream>
+#include <iterator>
+#include <stdexcept>
+#include <string>
 
 namespace GiNaC {
 
@@ -68,9 +69,9 @@ public:
 
 // public
 
-expairseq::expairseq() : inherited(&expairseq::tinfo_static)
+expairseq::expairseq() 
 #if EXPAIRSEQ_USE_HASHTAB
-                                                   , hashtabsize(0)
+       : hashtabsize(0)
 #endif // EXPAIRSEQ_USE_HASHTAB
 {}
 
@@ -107,20 +108,20 @@ void expairseq::copy(const expairseq &other)
 // other constructors
 //////////
 
-expairseq::expairseq(const ex &lh, const ex &rh) : inherited(&expairseq::tinfo_static)
+expairseq::expairseq(const ex &lh, const ex &rh)
 {
        construct_from_2_ex(lh,rh);
        GINAC_ASSERT(is_canonical());
 }
 
-expairseq::expairseq(const exvector &v) : inherited(&expairseq::tinfo_static)
+expairseq::expairseq(const exvector &v)
 {
        construct_from_exvector(v);
        GINAC_ASSERT(is_canonical());
 }
 
 expairseq::expairseq(const epvector &v, const ex &oc, bool do_index_renaming)
-  : inherited(&expairseq::tinfo_static), overall_coeff(oc)
+  :  overall_coeff(oc)
 {
        GINAC_ASSERT(is_a<numeric>(oc));
        construct_from_epvector(v, do_index_renaming);
@@ -128,7 +129,7 @@ expairseq::expairseq(const epvector &v, const ex &oc, bool do_index_renaming)
 }
 
 expairseq::expairseq(std::auto_ptr<epvector> vp, const ex &oc, bool do_index_renaming)
-  : inherited(&expairseq::tinfo_static), overall_coeff(oc)
+  :  overall_coeff(oc)
 {
        GINAC_ASSERT(vp.get()!=0);
        GINAC_ASSERT(is_a<numeric>(oc));
@@ -140,18 +141,20 @@ 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) 
 {
-       for (unsigned int i=0; true; i++) {
+       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;
+       seq.reserve((last-first)/2);
+
+       for (archive_node::archive_node_cit loc = first; loc < last;) {
                ex rest;
                ex coeff;
-               if (n.find_ex("rest", rest, sym_lst, i) && n.find_ex("coeff", coeff, sym_lst, i))
-                       seq.push_back(expair(rest, coeff));
-               else
-                       break;
+               n.find_ex_by_loc(loc++, rest, sym_lst);
+               n.find_ex_by_loc(loc++, coeff, sym_lst);
+               seq.push_back(expair(rest, coeff));
        }
 
        n.find_ex("overall_coeff", overall_coeff, sym_lst);
@@ -172,7 +175,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
@@ -263,6 +265,26 @@ void expairseq::do_print_tree(const print_tree & c, unsigned level) const
 
 bool expairseq::info(unsigned inf) const
 {
+       switch(inf) {
+               case info_flags::expanded:
+                       return (flags & status_flags::expanded);
+               case info_flags::has_indices: {
+                       if (flags & status_flags::has_indices)
+                               return true;
+                       else if (flags & status_flags::has_no_indices)
+                               return false;
+                       for (epvector::const_iterator i = seq.begin(); i != seq.end(); ++i) {
+                               if (i->rest.info(info_flags::has_indices)) {
+                                       this->setflag(status_flags::has_indices);
+                                       this->clearflag(status_flags::has_no_indices);
+                                       return true;
+                               }
+                       }
+                       this->clearflag(status_flags::has_indices);
+                       this->setflag(status_flags::has_no_indices);
+                       return false;
+               }
+       }
        return inherited::info(inf);
 }
 
@@ -349,9 +371,7 @@ ex expairseq::conjugate() const
                return *this;
        }
        ex result = thisexpairseq(newepv ? *newepv : seq, x);
-       if (newepv) {
-               delete newepv;
-       }
+       delete newepv;
        return result;
 }
 
@@ -366,12 +386,12 @@ bool expairseq::is_polynomial(const ex & var) const
        return true;
 }
 
-bool expairseq::match(const ex & pattern, lst & repl_lst) const
+bool expairseq::match(const ex & pattern, exmap & repl_lst) const
 {
        // This differs from basic::match() because we want "a+b+c+d" to
        // match "d+*+b" with "*" being "a+c", and we want to honor commutativity
 
-       if (this->tinfo() == ex_to<basic>(pattern).tinfo()) {
+       if (typeid(*this) == typeid(ex_to<basic>(pattern))) {
 
                // Check whether global wildcard (one that matches the "rest of the
                // expression", like "*" above) is present
@@ -402,20 +422,10 @@ bool expairseq::match(const ex & pattern, lst & repl_lst) const
                                continue;
                        exvector::iterator it = ops.begin(), itend = ops.end();
                        while (it != itend) {
-                               lst::const_iterator last_el = repl_lst.end();
-                               --last_el;
                                if (it->match(p, repl_lst)) {
                                        ops.erase(it);
                                        goto found;
                                }
-                               while(true) {
-                                       lst::const_iterator next_el = last_el;
-                                       ++next_el;
-                                       if(next_el == repl_lst.end())
-                                               break;
-                                       else
-                                               repl_lst.remove_last();
-                               }
                                ++it;
                        }
                        return false; // no match found
@@ -433,11 +443,11 @@ 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 (lst::const_iterator it = repl_lst.begin(); it != repl_lst.end(); ++it) {
-                               if (it->op(0).is_equal(global_wildcard))
-                                       return rest.is_equal(it->op(1));
+                       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);
                        }
-                       repl_lst.append(global_wildcard == rest);
+                       repl_lst[global_wildcard] = rest;
                        return true;
 
                } else {
@@ -600,7 +610,7 @@ unsigned expairseq::return_type() const
 
 unsigned expairseq::calchash() const
 {
-       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) {
@@ -778,8 +788,8 @@ void expairseq::construct_from_2_ex_via_exvector(const ex &lh, const ex &rh)
 
 void expairseq::construct_from_2_ex(const ex &lh, const ex &rh)
 {
-       if (ex_to<basic>(lh).tinfo()==this->tinfo()) {
-               if (ex_to<basic>(rh).tinfo()==this->tinfo()) {
+       if (typeid(ex_to<basic>(lh)) == typeid(*this)) {
+               if (typeid(ex_to<basic>(rh)) == typeid(*this)) {
 #if EXPAIRSEQ_USE_HASHTAB
                        unsigned totalsize = ex_to<expairseq>(lh).seq.size() +
                                             ex_to<expairseq>(rh).seq.size();
@@ -787,8 +797,8 @@ void expairseq::construct_from_2_ex(const ex &lh, const ex &rh)
                                construct_from_2_ex_via_exvector(lh,rh);
                        } else {
 #endif // EXPAIRSEQ_USE_HASHTAB
-                               if(is_a<mul>(lh))
-                               {
+                               if (is_a<mul>(lh) && lh.info(info_flags::has_indices) && 
+                                       rh.info(info_flags::has_indices)) {
                                        ex newrh=rename_dummy_indices_uniquely(lh, rh);
                                        construct_from_2_expairseq(ex_to<expairseq>(lh),
                                                                   ex_to<expairseq>(newrh));
@@ -813,7 +823,7 @@ void expairseq::construct_from_2_ex(const ex &lh, const ex &rh)
 #endif // EXPAIRSEQ_USE_HASHTAB
                        return;
                }
-       } else if (ex_to<basic>(rh).tinfo()==this->tinfo()) {
+       } else if (typeid(ex_to<basic>(rh)) == typeid(*this)) {
 #if EXPAIRSEQ_USE_HASHTAB
                unsigned totalsize=ex_to<expairseq>(rh).seq.size()+1;
                if (calc_hashtabsize(totalsize)!=0) {
@@ -1022,61 +1032,6 @@ void expairseq::construct_from_epvector(const epvector &v, bool do_index_renamin
 #endif // EXPAIRSEQ_USE_HASHTAB
 }
 
-// Class to handle the renaming of dummy indices. It holds a vector of
-// indices that are being used in the expression so-far. If the same
-// index occurs again as a dummy index in a factor, it is to be renamed.
-// Unless dummy index renaming was swichted of, of course ;-) .
-class make_flat_inserter
-{
-       public:
-               make_flat_inserter(const epvector &epv, bool b): do_renaming(b)
-               {
-                       if (!do_renaming)
-                               return;
-                       for (epvector::const_iterator i=epv.begin(); i!=epv.end(); ++i)
-                               if(are_ex_trivially_equal(i->coeff, _ex1))
-                                       combine_indices(i->rest.get_free_indices());
-               }
-               make_flat_inserter(const exvector &v, bool b): do_renaming(b)
-               {
-                       if (!do_renaming)
-                               return;
-                       for (exvector::const_iterator i=v.begin(); i!=v.end(); ++i)
-                               combine_indices(i->get_free_indices());
-               }
-               ex handle_factor(const ex &x, const ex &coeff)
-               {
-                       if (!do_renaming)
-                               return x;
-                       exvector dummies_of_factor;
-                       if (coeff == _ex1)
-                               dummies_of_factor = get_all_dummy_indices_safely(x);
-                       else if (coeff == _ex2)
-                               dummies_of_factor = x.get_free_indices();
-                       else
-                               return x;
-                       if (dummies_of_factor.size() == 0)
-                               return x;
-                       sort(dummies_of_factor.begin(), dummies_of_factor.end(), ex_is_less());
-                       ex new_factor = rename_dummy_indices_uniquely(used_indices,
-                               dummies_of_factor, x);
-                       combine_indices(dummies_of_factor);
-                       return new_factor;
-               }
-       private:
-               void combine_indices(const exvector &dummies_of_factor)
-               {
-                       exvector new_dummy_indices;
-                       set_union(used_indices.begin(), used_indices.end(),
-                               dummies_of_factor.begin(), dummies_of_factor.end(),
-                               std::back_insert_iterator<exvector>(new_dummy_indices), ex_is_less());
-                       used_indices.swap(new_dummy_indices);
-               }
-               bool do_renaming;
-               exvector used_indices;
-};
-
-
 /** Combine this expairseq with argument exvector.
  *  It cares for associativity as well as for special handling of numerics. */
 void expairseq::make_flat(const exvector &v)
@@ -1087,13 +1042,17 @@ void expairseq::make_flat(const exvector &v)
        // and their cumulative number of operands
        int nexpairseqs = 0;
        int noperands = 0;
+       bool do_idx_rename = false;
        
        cit = v.begin();
        while (cit!=v.end()) {
-               if (ex_to<basic>(*cit).tinfo()==this->tinfo()) {
+               if (typeid(ex_to<basic>(*cit)) == typeid(*this)) {
                        ++nexpairseqs;
                        noperands += ex_to<expairseq>(*cit).seq.size();
                }
+               if (is_a<mul>(*this) && (!do_idx_rename) &&
+                               cit->info(info_flags::has_indices))
+                       do_idx_rename = true;
                ++cit;
        }
        
@@ -1101,10 +1060,10 @@ void expairseq::make_flat(const exvector &v)
        seq.reserve(v.size()+noperands-nexpairseqs);
        
        // copy elements and split off numerical part
-       make_flat_inserter mf(v, this->tinfo()==&mul::tinfo_static);
+       make_flat_inserter mf(v, do_idx_rename);
        cit = v.begin();
        while (cit!=v.end()) {
-               if (ex_to<basic>(*cit).tinfo()==this->tinfo()) {
+               if (typeid(ex_to<basic>(*cit)) == typeid(*this)) {
                        ex newfactor = mf.handle_factor(*cit, _ex1);
                        const expairseq &subseqref = ex_to<expairseq>(newfactor);
                        combine_overall_coeff(subseqref.overall_coeff);
@@ -1135,15 +1094,20 @@ void expairseq::make_flat(const epvector &v, bool do_index_renaming)
        // and their cumulative number of operands
        int nexpairseqs = 0;
        int noperands = 0;
+       bool really_need_rename_inds = false;
        
        cit = v.begin();
        while (cit!=v.end()) {
-               if (ex_to<basic>(cit->rest).tinfo()==this->tinfo()) {
+               if (typeid(ex_to<basic>(cit->rest)) == typeid(*this)) {
                        ++nexpairseqs;
                        noperands += ex_to<expairseq>(cit->rest).seq.size();
                }
+               if ((!really_need_rename_inds) && is_a<mul>(*this) &&
+                               cit->rest.info(info_flags::has_indices))
+                       really_need_rename_inds = true;
                ++cit;
        }
+       do_index_renaming = do_index_renaming && really_need_rename_inds;
        
        // reserve seq and coeffseq which will hold all operands
        seq.reserve(v.size()+noperands-nexpairseqs);
@@ -1152,7 +1116,7 @@ void expairseq::make_flat(const epvector &v, bool do_index_renaming)
        // copy elements and split off numerical part
        cit = v.begin();
        while (cit!=v.end()) {
-               if (ex_to<basic>(cit->rest).tinfo()==this->tinfo() &&
+               if ((typeid(ex_to<basic>(cit->rest)) == typeid(*this)) &&
                    this->can_make_flat(*cit)) {
                        ex newrest = mf.handle_factor(cit->rest, cit->coeff);
                        const expairseq &subseqref = ex_to<expairseq>(newrest);