- 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);
- }
- }
-
- 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;
- }
-
- // 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;
+ 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);
+ }
+ }
+
+ 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;
+ }
+
+ // 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;