]> www.ginac.de Git - ginac.git/blobdiff - ginac/simp_lor.cpp
* New funny timing added: compute an antipode in Yukawa theory.
[ginac.git] / ginac / simp_lor.cpp
index 5e289aa60b47c10152fc5e44d11f686209aa3859..0734439efa10b5b2c68d2b821a68438fceb20bc9 100644 (file)
@@ -1,9 +1,10 @@
 /** @file simp_lor.cpp
  *
  *  Implementation of GiNaC's simp_lor objects.
- *  No real implementation yet, to be done.    
- *
- *  GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
+ *  No real implementation yet, to be done.     */
+
+/*
+ *  GiNaC Copyright (C) 1999-2001 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
 #include "simp_lor.h"
 #include "ex.h"
 #include "mul.h"
-#include "symbol.h"
+#include "archive.h"
+#include "debugmsg.h"
+#include "utils.h"
+
+namespace GiNaC {
+
+GINAC_IMPLEMENT_REGISTERED_CLASS(simp_lor, indexed)
 
 //////////
 // default constructor, destructor, copy constructor assignment operator and helpers
 
 simp_lor::simp_lor() : type(invalid)
 {
-    debugmsg("simp_lor default constructor",LOGLEVEL_CONSTRUCT);
-    tinfo_key=TINFO_simp_lor;
-}
-
-simp_lor::~simp_lor()
-{
-    debugmsg("simp_lor destructor",LOGLEVEL_DESTRUCT);
-    destroy(0);
-}
-
-simp_lor::simp_lor(simp_lor const & other)
-{
-    debugmsg("simp_lor copy constructor",LOGLEVEL_CONSTRUCT);
-    copy (other);
-}
-
-simp_lor const & simp_lor::operator=(simp_lor const & other)
-{
-    debugmsg("simp_lor operator=",LOGLEVEL_ASSIGNMENT);
-    if (this != &other) {
-        destroy(1);
-        copy(other);
-    }
-    return *this;
+       debugmsg("simp_lor default constructor",LOGLEVEL_CONSTRUCT);
+       tinfo_key=TINFO_simp_lor;
 }
 
 // protected
 
-void simp_lor::copy(simp_lor const & other)
+void simp_lor::copy(const simp_lor & other)
 {
-    indexed::copy(other);
-    type=other.type;
-    name=other.name;
+       indexed::copy(other);
+       type=other.type;
+       name=other.name;
 }
 
 void simp_lor::destroy(bool call_parent)
 {
-    if (call_parent) {
-        indexed::destroy(call_parent);
-    }
+       if (call_parent) {
+               indexed::destroy(call_parent);
+       }
 }
 
 //////////
@@ -90,189 +75,215 @@ void simp_lor::destroy(bool call_parent)
 
 simp_lor::simp_lor(simp_lor_types const t) : type(t)
 {
-    debugmsg("simp_lor constructor from simp_lor_types",LOGLEVEL_CONSTRUCT);
-    tinfo_key=TINFO_simp_lor;
+       debugmsg("simp_lor constructor from simp_lor_types",LOGLEVEL_CONSTRUCT);
+       tinfo_key=TINFO_simp_lor;
 }
 
-simp_lor::simp_lor(simp_lor_types const t, ex const & i1, ex const & i2) :
-    indexed(i1,i2), type(t)
+simp_lor::simp_lor(simp_lor_types const t, const ex & i1, const ex & i2)
+  : indexed(i1,i2), type(t)
 {
-    debugmsg("simp_lor constructor from simp_lor_types,ex,ex",LOGLEVEL_CONSTRUCT);
-    tinfo_key=TINFO_simp_lor;
-    ASSERT(all_of_type_lorentzidx());
+       debugmsg("simp_lor constructor from simp_lor_types,ex,ex",LOGLEVEL_CONSTRUCT);
+       tinfo_key=TINFO_simp_lor;
+       GINAC_ASSERT(all_of_type_lorentzidx());
 }
 
-simp_lor::simp_lor(simp_lor_types const t, string const & n, ex const & i1) :
-    indexed(i1), type(t), name(n)
+simp_lor::simp_lor(simp_lor_types const t, const std::string & n, const ex & i1)
+  : indexed(i1), type(t), name(n)
 {
-    debugmsg("simp_lor constructor from simp_lor_types,string,ex",LOGLEVEL_CONSTRUCT);
-    tinfo_key=TINFO_simp_lor;
-    ASSERT(all_of_type_lorentzidx());
+       debugmsg("simp_lor constructor from simp_lor_types,string,ex",LOGLEVEL_CONSTRUCT);
+       tinfo_key=TINFO_simp_lor;
+       GINAC_ASSERT(all_of_type_lorentzidx());
 }
 
-simp_lor::simp_lor(simp_lor_types const t, string const & n, exvector const & iv) :
-    indexed(iv), type(t), name(n)
+simp_lor::simp_lor(simp_lor_types const t, const std::string & n, const exvector & iv)
+  : indexed(iv), type(t), name(n)
 {
-    debugmsg("simp_lor constructor from simp_lor_types,string,exvector",LOGLEVEL_CONSTRUCT);
-    tinfo_key=TINFO_simp_lor;
-    ASSERT(all_of_type_lorentzidx());
+       debugmsg("simp_lor constructor from simp_lor_types,string,exvector",LOGLEVEL_CONSTRUCT);
+       tinfo_key=TINFO_simp_lor;
+       GINAC_ASSERT(all_of_type_lorentzidx());
 }
 
-simp_lor::simp_lor(simp_lor_types const t, string const & n, exvector * ivp) :
-    indexed(ivp), type(t), name(n)
+simp_lor::simp_lor(simp_lor_types const t, const std::string & n, exvector * ivp)
+  : indexed(ivp), type(t), name(n)
 {
-    debugmsg("simp_lor constructor from simp_lor_types,string,exvector*",LOGLEVEL_CONSTRUCT);
-    tinfo_key=TINFO_simp_lor;
-    ASSERT(all_of_type_lorentzidx());
+       debugmsg("simp_lor constructor from simp_lor_types,string,exvector*",LOGLEVEL_CONSTRUCT);
+       tinfo_key=TINFO_simp_lor;
+       GINAC_ASSERT(all_of_type_lorentzidx());
 }
 
 //////////
-// functions overriding virtual functions from bases classes
+// archiving
 //////////
 
-// public
-
-basic * simp_lor::duplicate() const
+/** Construct object from archive_node. */
+simp_lor::simp_lor(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
 {
-    debugmsg("simp_lor duplicate",LOGLEVEL_DUPLICATE);
-    return new simp_lor(*this);
+       debugmsg("simp_lor constructor from archive_node", LOGLEVEL_CONSTRUCT);
+       unsigned int ty;
+       if (!(n.find_unsigned("type", ty)))
+               throw (std::runtime_error("unknown simp_lor type in archive"));
+       type = (simp_lor_types)ty;
+       n.find_string("name", name);
 }
 
-void simp_lor::printraw(ostream & os) const
+/** Unarchive the object. */
+ex simp_lor::unarchive(const archive_node &n, const lst &sym_lst)
 {
-    debugmsg("simp_lor printraw",LOGLEVEL_PRINT);
-    os << "simp_lor(type=" << (unsigned)type
-       << ",name=" << name << ",indices=";
-    printrawindices(os);
-    os << ",hash=" << hashvalue << ",flags=" << flags << ")";
+       return (new simp_lor(n, sym_lst))->setflag(status_flags::dynallocated);
 }
 
-void simp_lor::printtree(ostream & os, unsigned indent) const
+/** Archive the object. */
+void simp_lor::archive(archive_node &n) const
 {
-    debugmsg("simp_lor printtree",LOGLEVEL_PRINT);
-    os << string(indent,' ') << "simp_lor object: "
-       << "type=" << (unsigned)type
-       << ", name=" << name << ", ";
-    os << seq.size() << " indices" << endl;
-    printtreeindices(os,indent);
-    os << string(indent,' ') << "hash=" << hashvalue
-       << " (0x" << hex << hashvalue << dec << ")"
-       << ", flags=" << flags << endl;
+       inherited::archive(n);
+       n.add_unsigned("type", type);
+       n.add_string("name", name);
 }
 
-void simp_lor::print(ostream & os, unsigned upper_precedence) const
-{
-    debugmsg("simp_lor print",LOGLEVEL_PRINT);
-    switch (type) {
-    case simp_lor_g:
-        os << "g";
-        break;
-    case simp_lor_vec:
-        os << name;
-        break;
-    case invalid:
-    default:
-        os << "INVALID_SIMP_LOR_OBJECT";
-        break;
-    }
-    printindices(os);
+
+//////////
+// functions overriding virtual functions from bases classes
+//////////
+
+// public
+
+void simp_lor::printraw(std::ostream & os) const
+{
+       debugmsg("simp_lor printraw",LOGLEVEL_PRINT);
+       os << "simp_lor(type=" << (unsigned)type
+          << ",name=" << name << ",indices=";
+       printrawindices(os);
+       os << ",hash=" << hashvalue << ",flags=" << flags << ")";
+}
+
+void simp_lor::printtree(std::ostream & os, unsigned indent) const
+{
+       debugmsg("simp_lor printtree",LOGLEVEL_PRINT);
+       os << std::string(indent,' ') << "simp_lor object: "
+          << "type=" << (unsigned)type
+          << ", name=" << name << ", ";
+       os << seq.size() << " indices" << std::endl;
+       printtreeindices(os,indent);
+       os << std::string(indent,' ') << "hash=" << hashvalue
+          << " (0x" << std::hex << hashvalue << std::dec << ")"
+          << ", flags=" << flags << std::endl;
+}
+
+void simp_lor::print(std::ostream & os, unsigned upper_precedence) const
+{
+       debugmsg("simp_lor print",LOGLEVEL_PRINT);
+       switch (type) {
+       case simp_lor_g:
+               os << "g";
+               break;
+       case simp_lor_vec:
+               os << name;
+               break;
+       case invalid:
+       default:
+               os << "INVALID_SIMP_LOR_OBJECT";
+               break;
+       }
+       printindices(os);
 }
 
-void simp_lor::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
+void simp_lor::printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const
 {
-    debugmsg("simp_lor print csrc",LOGLEVEL_PRINT);
-    print(os,upper_precedence);
+       debugmsg("simp_lor print csrc",LOGLEVEL_PRINT);
+       print(os,upper_precedence);
 }
 
 bool simp_lor::info(unsigned inf) const
 {
-    return indexed::info(inf);
+       return indexed::info(inf);
 }
 
 ex simp_lor::eval(int level) const
 {
-    if (type==simp_lor_g) {
-        // canonicalize indices
-        exvector iv=seq;
-        int sig=canonicalize_indices(iv,false); // symmetric
-        if (sig!=INT_MAX) {
-            // something has changed while sorting indices, more evaluations later
-            if (sig==0) return exZERO();
-            return ex(sig)*simp_lor(type,name,iv);
-        }
-        lorentzidx const & idx1=ex_to_lorentzidx(seq[0]);
-        lorentzidx const & idx2=ex_to_lorentzidx(seq[1]);
-        if ((!idx1.is_symbolic())&&(!idx2.is_symbolic())) {
-            // both indices are numeric
-            if ((idx1.get_value()==idx2.get_value())) {
-                // both on diagonal
-                if (idx1.get_value()==0) {
-                    // (0,0)
-                    return exONE();
-                } else {
-                    if (idx1.is_covariant()!=idx2.is_covariant()) {
-                        // (_i,~i) or (~i,_i), i=1..3
-                        return exONE();
-                    } else {
-                        // (_i,_i) or (~i,~i), i=1..3
-                        return exMINUSONE();
-                    }
-                }
-            } else {
-                // at least one off-diagonal
-                return exZERO();
-            }
-        } else if (idx1.is_symbolic() &&
-                   idx1.is_co_contra_pair(idx2)) {
-            return Dim()-idx1.get_dim_parallel_space();
-        }
-    }
-
-    return this->hold();
-}
-    
+       if (type==simp_lor_g) {
+               // canonicalize indices
+               exvector iv=seq;
+               int sig=canonicalize_indices(iv,false); // symmetric
+               if (sig!=INT_MAX) {
+                       // something has changed while sorting indices, more evaluations later
+                       if (sig==0) return _ex0();
+                       return ex(sig)*simp_lor(type,name,iv);
+               }
+               const lorentzidx & idx1=ex_to_lorentzidx(seq[0]);
+               const lorentzidx & idx2=ex_to_lorentzidx(seq[1]);
+               if ((!idx1.is_symbolic())&&(!idx2.is_symbolic())) {
+                       // both indices are numeric
+                       if ((idx1.get_value()==idx2.get_value())) {
+                               // both on diagonal
+                               if (idx1.get_value()==0) {
+                                       // (0,0)
+                                       return _ex1();
+                               } else {
+                                       if (idx1.is_covariant()!=idx2.is_covariant()) {
+                                               // (_i,~i) or (~i,_i), i=1..3
+                                               return _ex1();
+                                       } else {
+                                               // (_i,_i) or (~i,~i), i=1..3
+                                               return _ex_1();
+                                       }
+                               }
+                       } else {
+                               // at least one off-diagonal
+                               return _ex0();
+                       }
+               } else if (idx1.is_symbolic() && idx1.is_co_contra_pair(idx2)) {
+                       if (idx1.is_orthogonal_only())
+                               return Dim() - idx1.get_dim_parallel_space();
+                       else
+                               return Dim();
+               }
+       }
+
+       return this->hold();
+}
+       
 // protected
 
-int simp_lor::compare_same_type(basic const & other) const
+int simp_lor::compare_same_type(const basic & other) const
 {
-    ASSERT(other.tinfo() == TINFO_simp_lor);
-    const simp_lor *o = static_cast<const simp_lor *>(&other);
-    if (type==o->type) {
-        if (name==o->name) {
-            return indexed::compare_same_type(other);
-        }
-        return name.compare(o->name);
-    }
-    return type < o->type ? -1 : 1;
+       GINAC_ASSERT(other.tinfo() == TINFO_simp_lor);
+       const simp_lor *o = static_cast<const simp_lor *>(&other);
+       if (type==o->type) {
+               if (name==o->name) {
+                       return indexed::compare_same_type(other);
+               }
+               return name.compare(o->name);
+       }
+       return type < o->type ? -1 : 1;
 }
 
-bool simp_lor::is_equal_same_type(basic const & other) const
+bool simp_lor::is_equal_same_type(const basic & other) const
 {
-    ASSERT(other.tinfo() == TINFO_simp_lor);
-    const simp_lor *o = static_cast<const simp_lor *>(&other);
-    if (type!=o->type) return false;
-    if (name!=o->name) return false;
-    return indexed::is_equal_same_type(other);
+       GINAC_ASSERT(other.tinfo() == TINFO_simp_lor);
+       const simp_lor *o = static_cast<const simp_lor *>(&other);
+       if (type!=o->type) return false;
+       if (name!=o->name) return false;
+       return indexed::is_equal_same_type(other);
 }
 
 unsigned simp_lor::return_type(void) const
 {
-    return return_types::commutative;
+       return return_types::commutative;
 }
    
 unsigned simp_lor::return_type_tinfo(void) const
 {
-    return tinfo_key;
+       return tinfo_key;
 }
 
-ex simp_lor::thisexprseq(exvector const & v) const
+ex simp_lor::thisexprseq(const exvector & v) const
 {
-    return simp_lor(type,name,v);
+       return simp_lor(type,name,v);
 }
 
 ex simp_lor::thisexprseq(exvector * vp) const
 {
-    return simp_lor(type,name,vp);
+       return simp_lor(type,name,vp);
 }
 
 //////////
@@ -289,11 +300,11 @@ ex simp_lor::thisexprseq(exvector * vp) const
 
 bool simp_lor::all_of_type_lorentzidx(void) const
 {
-    // used only inside of ASSERTs
-    for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
-        if (!is_ex_of_type(*cit,lorentzidx)) return false;
-    }
-    return true;
+       // used only inside of ASSERTs
+       for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
+               if (!is_ex_of_type(*cit,lorentzidx)) return false;
+       }
+       return true;
 }
 
 //////////
@@ -302,212 +313,196 @@ bool simp_lor::all_of_type_lorentzidx(void) const
 
 // none
 
-//////////
-// global constants
-//////////
-
-const simp_lor some_simp_lor;
-type_info const & typeid_simp_lor=typeid(some_simp_lor);
-
 //////////
 // friend functions
 //////////
 
-simp_lor lor_g(ex const & mu, ex const & nu)
+simp_lor lor_g(const ex & mu, const ex & nu)
 {
-    return simp_lor(simp_lor::simp_lor_g,mu,nu);
+       return simp_lor(simp_lor::simp_lor_g,mu,nu);
 }
 
-simp_lor lor_vec(string const & n, ex const & mu)
+simp_lor lor_vec(const std::string & n, const ex & mu)
 {
-    return simp_lor(simp_lor::simp_lor_vec,n,mu);
+       return simp_lor(simp_lor::simp_lor_vec,n,mu);
 }
 
-ex simplify_simp_lor_mul(ex const & m, scalar_products const & sp)
+ex simplify_simp_lor_mul(const ex & m, const scalar_products & sp)
 {
-    ASSERT(is_ex_exactly_of_type(m,mul));
-    exvector v_contracted;
+       GINAC_ASSERT(is_ex_exactly_of_type(m,mul));
+       exvector v_contracted;
+
+       // collect factors in an exvector, store squares twice
+       unsigned n=m.nops();
+       v_contracted.reserve(2*n);
+       for (unsigned i=0; i<n; ++i) {
+               ex f=m.op(i);
+               if (is_ex_exactly_of_type(f,power)&&f.op(1).is_equal(_ex2())) {
+                       v_contracted.push_back(f.op(0));
+                       v_contracted.push_back(f.op(0));
+               } else {
+                       v_contracted.push_back(f);
+               }
+       }
 
-    // collect factors in an exvector, store squares twice
-    int n=m.nops();
-    v_contracted.reserve(2*n);
-    for (int i=0; i<n; ++i) {
-        ex f=m.op(i);
-        if (is_ex_exactly_of_type(f,power)&&f.op(1).is_equal(exTWO())) {
-            v_contracted.push_back(f.op(0));
-            v_contracted.push_back(f.op(0));
-        } else {
-            v_contracted.push_back(f);
+       unsigned replacements;
+       bool something_changed=false;
+
+       exvector::iterator it=v_contracted.begin();
+       while (it!=v_contracted.end()) {
+               // process only lor_g objects
+               if (is_ex_exactly_of_type(*it,simp_lor) &&
+                       (ex_to_simp_lor(*it).type==simp_lor::simp_lor_g)) {
+                       const simp_lor & g=ex_to_simp_lor(*it);
+                       GINAC_ASSERT(g.seq.size()==2);
+                       const idx & first_idx=ex_to_lorentzidx(g.seq[0]);
+                       const idx & second_idx=ex_to_lorentzidx(g.seq[1]);
+                       // g_{mu,mu} should have been contracted in simp_lor::eval()
+                       GINAC_ASSERT(!first_idx.is_equal(second_idx));
+                       ex saved_g=*it; // save to restore it later
+
+                       // try to contract first index
+                       replacements=0;
+                       if (first_idx.is_symbolic()) {
+                               replacements = subs_index_in_exvector(v_contracted, first_idx.toggle_covariant(),second_idx);
+                               if (replacements==0) {
+                                       // not contracted, restore g object
+                                       *it=saved_g;
+                               } else {
+                                       // a contracted index should occur exactly once
+                                       GINAC_ASSERT(replacements==1);
+                                       *it=_ex1();
+                                       something_changed=true;
+                               }
+                       }
+
+                       // try second index only if first was not contracted
+                       if ((replacements==0)&&(second_idx.is_symbolic())) {
+                               // first index not contracted, *it is again the original g object
+                               replacements = subs_index_in_exvector(v_contracted, second_idx.toggle_covariant(),first_idx);
+                               if (replacements==0) {
+                                       // not contracted except in itself, restore g object
+                                       *it=saved_g;
+                               } else {
+                                       // a contracted index should occur exactly once
+                                       GINAC_ASSERT(replacements==1);
+                                       *it=_ex1();
+                                       something_changed=true;
+                               }
+                       }
+               }
+               ++it;
        }
-    }
-
-    unsigned replacements;
-    bool something_changed=false;
-
-    exvector::iterator it=v_contracted.begin();
-    while (it!=v_contracted.end()) {
-        // process only lor_g objects
-        if (is_ex_exactly_of_type(*it,simp_lor) &&
-            (ex_to_simp_lor(*it).type==simp_lor::simp_lor_g)) {
-            simp_lor const & g=ex_to_simp_lor(*it);
-            ASSERT(g.seq.size()==2);
-            idx const & first_idx=ex_to_lorentzidx(g.seq[0]);
-            idx const & second_idx=ex_to_lorentzidx(g.seq[1]);
-            // g_{mu,mu} should have been contracted in simp_lor::eval()
-            ASSERT(!first_idx.is_equal(second_idx));
-            ex saved_g=*it; // save to restore it later
-
-            // try to contract first index
-            replacements=0;
-            if (first_idx.is_symbolic()) {
-                replacements = subs_index_in_exvector(v_contracted,
-                                   first_idx.toggle_covariant(),second_idx);
-                if (replacements==0) {
-                    // not contracted, restore g object
-                    *it=saved_g;
-                } else {
-                    // a contracted index should occur exactly once
-                    ASSERT(replacements==1);
-                    *it=exONE();
-                    something_changed=true;
-                }
-            }
-
-            // try second index only if first was not contracted
-            if ((replacements==0)&&(second_idx.is_symbolic())) {
-                // first index not contracted, *it is again the original g object
-                replacements = subs_index_in_exvector(v_contracted,
-                                   second_idx.toggle_covariant(),first_idx);
-                if (replacements==0) {
-                    // not contracted except in itself, restore g object
-                    *it=saved_g;
-                } else {
-                    // a contracted index should occur exactly once
-                    ASSERT(replacements==1);
-                    *it=exONE();
-                    something_changed=true;
-                }
-            }
-        }
-        ++it;
-    }
-
-    // process only lor_vec objects
-    bool jump_to_next=false;
-    exvector::iterator it1=v_contracted.begin();
-    while (it1!=v_contracted.end()-1) {
-        if (is_ex_exactly_of_type(*it1,simp_lor) && 
-            (ex_to_simp_lor(*it1).type==simp_lor::simp_lor_vec)) {
-            exvector::iterator it2=it1+1;
-            while ((it2!=v_contracted.end())&&!jump_to_next) {
-                if (is_ex_exactly_of_type(*it2,simp_lor) && 
-                    (ex_to_simp_lor(*it2).type==simp_lor::simp_lor_vec)) {
-                    simp_lor const & vec1=ex_to_simp_lor(*it1);
-                    simp_lor const & vec2=ex_to_simp_lor(*it2);
-                    ASSERT(vec1.seq.size()==1);
-                    ASSERT(vec2.seq.size()==1);
-                    lorentzidx const & idx1=ex_to_lorentzidx(vec1.seq[0]);
-                    lorentzidx const & idx2=ex_to_lorentzidx(vec2.seq[0]);
-                    if (idx1.is_symbolic() &&
-                        idx1.is_co_contra_pair(idx2) &&
-                        sp.is_defined(vec1,vec2)) {
-                        *it1=sp.evaluate(vec1,vec2);
-                        *it2=exONE();
-                        something_changed=true;
-                        jump_to_next=true;
-                    }
-                }
-                ++it2;
-            }
-            jump_to_next=false;
-        }
-        ++it1;
-    }
-    if (something_changed) {
-        return mul(v_contracted);
-    }
-    return m;
-}
-
-ex simplify_simp_lor(ex const & e, scalar_products const & sp)
-{
-    // all simplification is done on expanded objects
-    ex e_expanded=e.expand();
-
-    // simplification of sum=sum of simplifications
-    if (is_ex_exactly_of_type(e_expanded,add)) {
-        ex sum=exZERO();
-        for (int i=0; i<e_expanded.nops(); ++i) {
-            sum += simplify_simp_lor(e_expanded.op(i),sp);
-        }
-        return sum;
-    }
-
-    // simplification of commutative product=commutative product of simplifications
-    if (is_ex_exactly_of_type(e_expanded,mul)) {
-        return simplify_simp_lor_mul(e,sp);
-    }
-
-    // cannot do anything
-    return e_expanded;
-}
-
-ex Dim(void)
-{
-    static symbol * d=new symbol("dim");
-    return *d;
+
+       // process only lor_vec objects
+       bool jump_to_next=false;
+       exvector::iterator it1=v_contracted.begin();
+       while (it1!=v_contracted.end()-1) {
+               if (is_ex_exactly_of_type(*it1,simp_lor) && 
+                       (ex_to_simp_lor(*it1).type==simp_lor::simp_lor_vec)) {
+                       exvector::iterator it2=it1+1;
+                       while ((it2!=v_contracted.end())&&!jump_to_next) {
+                               if (is_ex_exactly_of_type(*it2,simp_lor) && 
+                                       (ex_to_simp_lor(*it2).type==simp_lor::simp_lor_vec)) {
+                                       const simp_lor & vec1=ex_to_simp_lor(*it1);
+                                       const simp_lor & vec2=ex_to_simp_lor(*it2);
+                                       GINAC_ASSERT(vec1.seq.size()==1);
+                                       GINAC_ASSERT(vec2.seq.size()==1);
+                                       const lorentzidx & idx1=ex_to_lorentzidx(vec1.seq[0]);
+                                       const lorentzidx & idx2=ex_to_lorentzidx(vec2.seq[0]);
+                                       if (idx1.is_symbolic() &&
+                                               idx1.is_co_contra_pair(idx2) &&
+                                               sp.is_defined(vec1,vec2)) {
+                                               *it1=sp.evaluate(vec1,vec2);
+                                               *it2=_ex1();
+                                               something_changed=true;
+                                               jump_to_next=true;
+                                       }
+                               }
+                               ++it2;
+                       }
+                       jump_to_next=false;
+               }
+               ++it1;
+       }
+       if (something_changed) {
+               return mul(v_contracted);
+       }
+       return m;
+}
+
+ex simplify_simp_lor(const ex & e, const scalar_products & sp)
+{
+       // all simplification is done on expanded objects
+       ex e_expanded = e.expand();
+
+       // simplification of sum=sum of simplifications
+       if (is_ex_exactly_of_type(e_expanded,add)) {
+               ex sum=_ex0();
+               for (unsigned i=0; i<e_expanded.nops(); ++i)
+                       sum += simplify_simp_lor(e_expanded.op(i),sp);
+
+               return sum;
+       }
+
+       // simplification of commutative product=commutative product of simplifications
+       if (is_ex_exactly_of_type(e_expanded,mul)) {
+               return simplify_simp_lor_mul(e,sp);
+       }
+
+       // cannot do anything
+       return e_expanded;
 }
 
 //////////
 // helper classes
 //////////
 
-void scalar_products::reg(simp_lor const & v1, simp_lor const & v2,
-                          ex const & sp)
+void scalar_products::reg(const simp_lor & v1, const simp_lor & v2,
+                          const ex & sp)
 {
-    if (v1.compare_same_type(v2)>0) {
-        reg(v2,v1,sp);
-        return;
-    }
-    spm[make_key(v1,v2)]=sp;
+       if (v1.compare_same_type(v2)>0) {
+               reg(v2,v1,sp);
+               return;
+       }
+       spm[make_key(v1,v2)]=sp;
 }
 
-bool scalar_products::is_defined(simp_lor const & v1, simp_lor const & v2) const
+bool scalar_products::is_defined(const simp_lor & v1, const simp_lor & v2) const
 {
-    if (v1.compare_same_type(v2)>0) {
-        return is_defined(v2,v1);
-    }
-    return spm.find(make_key(v1,v2))!=spm.end();
+       if (v1.compare_same_type(v2)>0) {
+               return is_defined(v2,v1);
+       }
+       return spm.find(make_key(v1,v2))!=spm.end();
 }
 
-ex scalar_products::evaluate(simp_lor const & v1, simp_lor const & v2) const
+ex scalar_products::evaluate(const simp_lor & v1, const simp_lor & v2) const
 {
-    if (v1.compare_same_type(v2)>0) {
-        return evaluate(v2,v1);
-    }
-    return spm.find(make_key(v1,v2))->second;
+       if (v1.compare_same_type(v2)>0)
+               return evaluate(v2, v1);
+       
+       return (*spm.find(make_key(v1,v2))).second;
 }
 
 void scalar_products::debugprint(void) const
 {
-    cerr << "map size=" << spm.size() << endl;
-    for (spmap::const_iterator cit=spm.begin(); cit!=spm.end(); ++cit) {
-        spmapkey const & k=(*cit).first;
-        cerr << "item key=((" << k.first.first
-             << "," << k.first.second << "),";
-        k.second.printraw(cerr);
-        cerr << ") value=" << (*cit).second << endl;
-    }
+       std::cerr << "map size=" << spm.size() << std::endl;
+       for (spmap::const_iterator cit=spm.begin(); cit!=spm.end(); ++cit) {
+               const spmapkey & k=(*cit).first;
+               std::cerr << "item key=((" << k.first.first
+                         << "," << k.first.second << "),";
+               k.second.printraw(std::cerr);
+               std::cerr << ") value=" << (*cit).second << std::endl;
+       }
 }
 
-spmapkey scalar_products::make_key(simp_lor const & v1, simp_lor const & v2)
+spmapkey scalar_products::make_key(const simp_lor & v1, const simp_lor & v2)
 {
-    ASSERT(v1.type==simp_lor::simp_lor_vec);
-    ASSERT(v2.type==simp_lor::simp_lor_vec);
-    lorentzidx anon=ex_to_lorentzidx(v1.seq[0]).create_anonymous_representative();
-    ASSERT(anon.is_equal_same_type(ex_to_lorentzidx(v2.seq[0]).create_anonymous_representative()));
-    return spmapkey(strstrpair(v1.name,v2.name),anon);
+       GINAC_ASSERT(v1.type==simp_lor::simp_lor_vec);
+       GINAC_ASSERT(v2.type==simp_lor::simp_lor_vec);
+       lorentzidx anon=ex_to_lorentzidx(v1.seq[0]).create_anonymous_representative();
+       GINAC_ASSERT(anon.is_equal_same_type(ex_to_lorentzidx(v2.seq[0]).create_anonymous_representative()));
+       return spmapkey(strstrpair(v1.name,v2.name),anon);
 }
 
-
-
+} // namespace GiNaC