]> www.ginac.de Git - ginac.git/blobdiff - ginac/ncmul.cpp
- New tinfo mechanism
[ginac.git] / ginac / ncmul.cpp
index dd0c7bdc07d0fee84c03ade49504b13375c16a3c..efa4af5bce7bc48b7a1e19a5c6aca2cdba49fdac 100644 (file)
@@ -3,7 +3,7 @@
  *  Implementation of GiNaC's non-commutative products of expressions. */
 
 /*
- *  GiNaC Copyright (C) 1999-2003 Johannes Gutenberg University Mainz, Germany
+ *  GiNaC Copyright (C) 1999-2006 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
@@ -17,7 +17,7 @@
  *
  *  You should have received a copy of the GNU General Public License
  *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
 #include <algorithm>
 #include "ex.h"
 #include "add.h"
 #include "mul.h"
+#include "clifford.h"
+#include "color.h"
 #include "matrix.h"
-#include "print.h"
 #include "archive.h"
+#include "indexed.h"
 #include "utils.h"
 
 namespace GiNaC {
 
-GINAC_IMPLEMENT_REGISTERED_CLASS(ncmul, exprseq)
+GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(ncmul, exprseq,
+  print_func<print_context>(&ncmul::do_print).
+  print_func<print_tree>(&ncmul::do_print_tree).
+  print_func<print_csrc>(&ncmul::do_print_csrc).
+  print_func<print_python_repr>(&ncmul::do_print_csrc))
+
 
 //////////
 // default constructor
@@ -43,7 +50,7 @@ GINAC_IMPLEMENT_REGISTERED_CLASS(ncmul, exprseq)
 
 ncmul::ncmul()
 {
-       tinfo_key = TINFO_ncmul;
+       tinfo_key = &ncmul::tinfo_static;
 }
 
 //////////
@@ -54,40 +61,40 @@ ncmul::ncmul()
 
 ncmul::ncmul(const ex & lh, const ex & rh) : inherited(lh,rh)
 {
-       tinfo_key = TINFO_ncmul;
+       tinfo_key = &ncmul::tinfo_static;
 }
 
 ncmul::ncmul(const ex & f1, const ex & f2, const ex & f3) : inherited(f1,f2,f3)
 {
-       tinfo_key = TINFO_ncmul;
+       tinfo_key = &ncmul::tinfo_static;
 }
 
 ncmul::ncmul(const ex & f1, const ex & f2, const ex & f3,
              const ex & f4) : inherited(f1,f2,f3,f4)
 {
-       tinfo_key = TINFO_ncmul;
+       tinfo_key = &ncmul::tinfo_static;
 }
 
 ncmul::ncmul(const ex & f1, const ex & f2, const ex & f3,
              const ex & f4, const ex & f5) : inherited(f1,f2,f3,f4,f5)
 {
-       tinfo_key = TINFO_ncmul;
+       tinfo_key = &ncmul::tinfo_static;
 }
 
 ncmul::ncmul(const ex & f1, const ex & f2, const ex & f3,
              const ex & f4, const ex & f5, const ex & f6) : inherited(f1,f2,f3,f4,f5,f6)
 {
-       tinfo_key = TINFO_ncmul;
+       tinfo_key = &ncmul::tinfo_static;
 }
 
 ncmul::ncmul(const exvector & v, bool discardable) : inherited(v,discardable)
 {
-       tinfo_key = TINFO_ncmul;
+       tinfo_key = &ncmul::tinfo_static;
 }
 
-ncmul::ncmul(exvector * vp) : inherited(vp)
+ncmul::ncmul(std::auto_ptr<exvector> vp) : inherited(vp)
 {
-       tinfo_key = TINFO_ncmul;
+       tinfo_key = &ncmul::tinfo_static;
 }
 
 //////////
@@ -102,26 +109,15 @@ DEFAULT_ARCHIVING(ncmul)
 
 // public
 
-void ncmul::print(const print_context & c, unsigned level) const
+void ncmul::do_print(const print_context & c, unsigned level) const
 {
-       if (is_a<print_tree>(c)) {
-
-               inherited::print(c, level);
-
-       } else if (is_a<print_csrc>(c) || is_a<print_python_repr>(c)) {
-
-               c.s << class_name() << "(";
-               exvector::const_iterator it = seq.begin(), itend = seq.end()-1;
-               while (it != itend) {
-                       it->print(c, precedence());
-                       c.s << ",";
-                       it++;
-               }
-               it->print(c, precedence());
-               c.s << ")";
+       printseq(c, '(', '*', ')', precedence(), level);
+}
 
-       } else
-               printseq(c, '(', '*', ')', precedence(), level);
+void ncmul::do_print_csrc(const print_context & c, unsigned level) const
+{
+       c.s << class_name();
+       printseq(c, '(', ',', ')', precedence(), precedence());
 }
 
 bool ncmul::info(unsigned inf) const
@@ -134,7 +130,8 @@ typedef std::vector<int> intvector;
 ex ncmul::expand(unsigned options) const
 {
        // First, expand the children
-       exvector expanded_seq = expandchildren(options);
+       std::auto_ptr<exvector> vp = expandchildren(options);
+       const exvector &expanded_seq = vp.get() ? *vp : this->seq;
        
        // Now, look for all the factors that are sums and remember their
        // position and number of terms.
@@ -158,9 +155,13 @@ ex ncmul::expand(unsigned options) const
        }
 
        // If there are no sums, we are done
-       if (number_of_adds == 0)
-               return (new ncmul(expanded_seq, true))->
-                       setflag(status_flags::dynallocated | (options == 0 ? status_flags::expanded : 0));
+       if (number_of_adds == 0) {
+               if (vp.get())
+                       return (new ncmul(vp))->
+                               setflag(status_flags::dynallocated | (options == 0 ? status_flags::expanded : 0));
+               else
+                       return *this;
+       }
 
        // Now, form all possible products of the terms of the sums with the
        // remaining factors, and add them together
@@ -169,10 +170,26 @@ ex ncmul::expand(unsigned options) const
 
        intvector k(number_of_adds);
 
+       /* Rename indices in the static members of the product */
+       exvector expanded_seq_mod;
+       size_t j = 0;
+       exvector va;
+
+       for (size_t i=0; i<expanded_seq.size(); i++) {
+               if (i == positions_of_adds[j]) {
+                       expanded_seq_mod.push_back(_ex1);
+                       j++;
+               } else {
+                       expanded_seq_mod.push_back(rename_dummy_indices_uniquely(va, expanded_seq[i], true));
+               }
+       }
+
        while (true) {
-               exvector term = expanded_seq;
-               for (size_t i=0; i<number_of_adds; i++)
-                       term[positions_of_adds[i]] = expanded_seq[positions_of_adds[i]].op(k[i]);
+               exvector term = expanded_seq_mod;
+               for (size_t i=0; i<number_of_adds; i++) {
+                       term[positions_of_adds[i]] = rename_dummy_indices_uniquely(va, expanded_seq[positions_of_adds[i]].op(k[i]), true);
+               }
+
                distrseq.push_back((new ncmul(term, true))->
                                    setflag(status_flags::dynallocated | (options == 0 ? status_flags::expanded : 0)));
 
@@ -192,6 +209,9 @@ ex ncmul::expand(unsigned options) const
 
 int ncmul::degree(const ex & s) const
 {
+       if (is_equal(ex_to<basic>(s)))
+               return 1;
+
        // Sum up degrees of factors
        int deg_sum = 0;
        exvector::const_iterator i = seq.begin(), end = seq.end();
@@ -204,6 +224,9 @@ int ncmul::degree(const ex & s) const
 
 int ncmul::ldegree(const ex & s) const
 {
+       if (is_equal(ex_to<basic>(s)))
+               return 1;
+
        // Sum up degrees of factors
        int deg_sum = 0;
        exvector::const_iterator i = seq.begin(), end = seq.end();
@@ -216,6 +239,9 @@ int ncmul::ldegree(const ex & s) const
 
 ex ncmul::coeff(const ex & s, int n) const
 {
+       if (is_equal(ex_to<basic>(s)))
+               return n==1 ? _ex1 : _ex0;
+
        exvector coeffseq;
        coeffseq.reserve(seq.size());
 
@@ -315,7 +341,7 @@ ex ncmul::eval(int level) const
        
        // ncmul(x) -> x
        if (assocseq.size()==1) return *(seq.begin());
-
        // ncmul() -> 1
        if (assocseq.empty()) return _ex1;
 
@@ -373,19 +399,32 @@ ex ncmul::eval(int level) const
 
                size_t assoc_num = assocseq.size();
                exvectorvector evv;
-               unsignedvector rttinfos;
+               std::vector<const basic*> rttinfos;
                evv.reserve(assoc_num);
                rttinfos.reserve(assoc_num);
 
                cit = assocseq.begin(), citend = assocseq.end();
                while (cit != citend) {
-                       unsigned ti = cit->return_type_tinfo();
+                       const basic* ti = cit->return_type_tinfo();
                        size_t rtt_num = rttinfos.size();
                        // search type in vector of known types
                        for (i=0; i<rtt_num; ++i) {
-                               if (ti == rttinfos[i]) {
-                                       evv[i].push_back(*cit);
-                                       break;
+                               tinfo_t tinf = ti->tinfo();
+                               if (tinf == rttinfos[i]->tinfo()) {
+                                       if (tinf == &clifford::tinfo_static) {
+                                               if (((clifford*)ti)->get_representation_label() == ((clifford*)rttinfos[i])->get_representation_label()) {
+                                                       evv[i].push_back(*cit);
+                                                       break;
+                                               }
+                                       } else if (tinf == &color::tinfo_static) {
+                                               if (((color*)ti)->get_representation_label() == ((color*)rttinfos[i])->get_representation_label()) {
+                                                       evv[i].push_back(*cit);
+                                                       break;
+                                               }
+                                       } else {
+                                               evv[i].push_back(*cit);
+                                               break;
+                                       }
                                }
                        }
                        if (i >= rtt_num) {
@@ -409,8 +448,9 @@ ex ncmul::eval(int level) const
 #endif // def DO_GINAC_ASSERT
                
                // if all elements are of same type, simplify the string
-               if (evv_num == 1)
+               if (evv_num == 1) {
                        return evv[0][0].eval_ncmul(evv[0]);
+               }
                
                exvector splitseq;
                splitseq.reserve(evv_num);
@@ -427,7 +467,7 @@ ex ncmul::eval(int level) const
 ex ncmul::evalm() const
 {
        // Evaluate children first
-       exvector *s = new exvector;
+       std::auto_ptr<exvector> s(new exvector);
        s->reserve(seq.size());
        exvector::const_iterator it = seq.begin(), itend = seq.end();
        while (it != itend) {
@@ -446,7 +486,6 @@ ex ncmul::evalm() const
                        prod = prod.mul(ex_to<matrix>(*it));
                        it++;
                }
-               delete s;
                return prod;
        }
 
@@ -459,11 +498,30 @@ ex ncmul::thiscontainer(const exvector & v) const
        return (new ncmul(v))->setflag(status_flags::dynallocated);
 }
 
-ex ncmul::thiscontainer(exvector * vp) const
+ex ncmul::thiscontainer(std::auto_ptr<exvector> vp) const
 {
        return (new ncmul(vp))->setflag(status_flags::dynallocated);
 }
 
+ex ncmul::conjugate() const
+{
+       if (return_type() != return_types::noncommutative) {
+               return exprseq::conjugate();
+       }
+
+       if (return_type_tinfo()->tinfo() != &clifford::tinfo_static) {
+               return exprseq::conjugate();
+       }
+
+       exvector ev;
+       ev.reserve(nops());
+       for (const_iterator i=end(); i!=begin();) {
+               --i;
+               ev.push_back(i->conjugate());
+       }
+       return (new ncmul(ev, true))->setflag(status_flags::dynallocated).eval();
+}
+
 // protected
 
 /** Implementation of ex::diff() for a non-commutative product. It applies
@@ -511,22 +569,35 @@ unsigned ncmul::return_type() const
                }
                if ((rt == return_types::noncommutative) && (!all_commutative)) {
                        // another nc element found, compare type_infos
-                       if (noncommutative_element->return_type_tinfo() != i->return_type_tinfo()) {
-                               // diffent types -> mul is ncc
-                               return return_types::noncommutative_composite;
+                       if (noncommutative_element->return_type_tinfo()->tinfo() == &clifford::tinfo_static) {
+                               if (i->return_type_tinfo()->tinfo() != &clifford::tinfo_static ||
+                                   ((clifford*)(noncommutative_element->return_type_tinfo()))->get_representation_label() !=
+                                   ((clifford*)(i->return_type_tinfo()))->get_representation_label()) {
+                                       // diffent types -> mul is ncc
+                                       return return_types::noncommutative_composite;
+                               }
+                       } else if (noncommutative_element->return_type_tinfo()->tinfo() == &color::tinfo_static) {
+                               if (i->return_type_tinfo()->tinfo() != &color::tinfo_static ||
+                                   ((color*)(noncommutative_element->return_type_tinfo()))->get_representation_label() !=
+                                   ((color*)(i->return_type_tinfo()))->get_representation_label()) {
+                                       // diffent types -> mul is ncc
+                                       return return_types::noncommutative_composite;
+                               }
+                       } else if (noncommutative_element->return_type_tinfo()->tinfo() != i->return_type_tinfo()->tinfo()) {
+                                       return return_types::noncommutative_composite;
                        }
                }
                ++i;
        }
        // all factors checked
-       GINAC_ASSERT(!all_commutative); // not all factors should commute, because this is a ncmul();
+       GINAC_ASSERT(!all_commutative); // not all factors should commutate, because this is a ncmul();
        return all_commutative ? return_types::commutative : return_types::noncommutative;
 }
    
-unsigned ncmul::return_type_tinfo() const
+const basic* ncmul::return_type_tinfo() const
 {
        if (seq.empty())
-               return tinfo_key;
+               return this;
 
        // return type_info of first noncommutative element
        exvector::const_iterator i = seq.begin(), end = seq.end();
@@ -537,7 +608,7 @@ unsigned ncmul::return_type_tinfo() const
        }
 
        // no noncommutative element found, should not happen
-       return tinfo_key;
+       return this;
 }
 
 //////////
@@ -550,16 +621,34 @@ unsigned ncmul::return_type_tinfo() const
 // non-virtual functions in this class
 //////////
 
-exvector ncmul::expandchildren(unsigned options) const
+std::auto_ptr<exvector> ncmul::expandchildren(unsigned options) const
 {
-       exvector s;
-       s.reserve(seq.size());
-       exvector::const_iterator it = seq.begin(), itend = seq.end();
-       while (it != itend) {
-               s.push_back(it->expand(options));
-               it++;
+       const_iterator cit = this->seq.begin(), end = this->seq.end();
+       while (cit != end) {
+               const ex & expanded_ex = cit->expand(options);
+               if (!are_ex_trivially_equal(*cit, expanded_ex)) {
+
+                       // copy first part of seq which hasn't changed
+                       std::auto_ptr<exvector> s(new exvector(this->seq.begin(), cit));
+                       reserve(*s, this->seq.size());
+
+                       // insert changed element
+                       s->push_back(expanded_ex);
+                       ++cit;
+
+                       // copy rest
+                       while (cit != end) {
+                               s->push_back(cit->expand(options));
+                               ++cit;
+                       }
+
+                       return s;
+               }
+
+               ++cit;
        }
-       return s;
+
+       return std::auto_ptr<exvector>(0); // nothing has changed
 }
 
 const exvector & ncmul::get_factors() const