X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Findexed.cpp;h=c8b710ae7f1e63690cbb0356e2e1ccc10159f1e0;hp=d772b3f4743bd85ff8c127110f888c34801c0c6c;hb=7bc327c75aaa3118de14dfcee59bcf0fd40e3f4a;hpb=e485c265061056d29de6fb252cd82ebedd41ec41 diff --git a/ginac/indexed.cpp b/ginac/indexed.cpp index d772b3f4..c8b710ae 100644 --- a/ginac/indexed.cpp +++ b/ginac/indexed.cpp @@ -3,7 +3,7 @@ * Implementation of GiNaC's indexed expressions. */ /* - * GiNaC Copyright (C) 1999-2006 Johannes Gutenberg University Mainz, Germany + * GiNaC Copyright (C) 1999-2008 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 @@ -23,6 +23,7 @@ #include #include #include +#include #include "indexed.h" #include "idx.h" @@ -306,7 +307,7 @@ ex indexed::eval(int level) const exvector v = seq; GINAC_ASSERT(is_exactly_a(symtree)); int sig = canonicalize(v.begin() + 1, ex_to(symtree)); - if (sig != INT_MAX) { + if (sig != std::numeric_limits::max()) { // Something has changed while sorting indices, more evaluations later if (sig == 0) return _ex0; @@ -639,60 +640,60 @@ bool reposition_dummy_indices(ex & e, exvector & variant_dummy_indices, exvector { bool something_changed = false; - // Canonicalize wrt indices that are dummies within e. I.e., their - // symbol occurs twice in an index of e. This is only done if there - // is a cyclic symmetry because in that case it may happen that after - // raising/lowering an index the indices get reshuffled by ::eval in - // such a way that the iterators no longer point to the right objects. - if (ex_to(ex_to(e).get_symmetry()).has_cyclic()) { - // Get dummy pairs of varidxes within the indexed object in e. - exvector local_var_dummies; - local_var_dummies.reserve(e.nops()/2); - for (size_t i=1; i(e.op(i))) - continue; - for (size_t j=i+1; jop(0)) { - variant_dummy_indices.erase(k); - break; - } + // Find dummy symbols that occur twice in the same indexed object. + exvector local_var_dummies; + local_var_dummies.reserve(e.nops()/2); + for (size_t i=1; i(e.op(i))) + continue; + for (size_t j=i+1; jop(0)) { + variant_dummy_indices.erase(k); + break; } - break; } + break; } } - // Try all posibilities of raising/lowering and keep the least one in - // the sense of ex_is_less. - ex optimal_e = e; - size_t numpossibs = 1 << local_var_dummies.size(); - for (size_t i=0; i(curr_idx).toggle_variance(); - m[curr_idx] = curr_toggle; - m[curr_toggle] = curr_idx; - } - try_e = e.subs(m, subs_options::no_pattern); - } - if(ex_is_less()(try_e, optimal_e)) - { optimal_e = try_e; - something_changed = true; + } + + // In the case where a dummy symbol occurs twice in the same indexed object + // we try all posibilities of raising/lowering and keep the least one in + // the sense of ex_is_less. + ex optimal_e = e; + size_t numpossibs = 1 << local_var_dummies.size(); + for (size_t i=0; i(curr_idx).toggle_variance(); + m[curr_idx] = curr_toggle; + m[curr_toggle] = curr_idx; } + try_e = e.subs(m, subs_options::no_pattern); + } + if(ex_is_less()(try_e, optimal_e)) + { optimal_e = try_e; + something_changed = true; } - e = optimal_e; } + e = optimal_e; + + if (!is_a(e)) + return true; + + exvector seq = ex_to(e).seq; // If a dummy index is encountered for the first time in the // product, pull it up, otherwise, pull it down - exvector::const_iterator it2, it2start, it2end; - for (it2start = ex_to(e).seq.begin(), it2end = ex_to(e).seq.end(), it2 = it2start + 1; it2 != it2end; ++it2) { + for (exvector::iterator it2 = seq.begin()+1, it2end = seq.end(); + it2 != it2end; ++it2) { if (!is_exactly_a(*it2)) continue; @@ -700,14 +701,20 @@ bool reposition_dummy_indices(ex & e, exvector & variant_dummy_indices, exvector for (vit = variant_dummy_indices.begin(), vitend = variant_dummy_indices.end(); vit != vitend; ++vit) { if (it2->op(0).is_equal(vit->op(0))) { if (ex_to(*it2).is_covariant()) { - e = e.subs(lst( - *it2 == ex_to(*it2).toggle_variance(), - ex_to(*it2).toggle_variance() == *it2 - ), subs_options::no_pattern); + /* + * N.B. we don't want to use + * + * e = e.subs(lst( + * *it2 == ex_to(*it2).toggle_variance(), + * ex_to(*it2).toggle_variance() == *it2 + * ), subs_options::no_pattern); + * + * since this can trigger non-trivial repositioning of indices, + * e.g. due to non-trivial symmetry properties of e, thus + * invalidating iterators + */ + *it2 = ex_to(*it2).toggle_variance(); something_changed = true; - it2 = ex_to(e).seq.begin() + (it2 - it2start); - it2start = ex_to(e).seq.begin(); - it2end = ex_to(e).seq.end(); } moved_indices.push_back(*vit); variant_dummy_indices.erase(vit); @@ -718,11 +725,8 @@ bool reposition_dummy_indices(ex & e, exvector & variant_dummy_indices, exvector for (vit = moved_indices.begin(), vitend = moved_indices.end(); vit != vitend; ++vit) { if (it2->op(0).is_equal(vit->op(0))) { if (ex_to(*it2).is_contravariant()) { - e = e.subs(*it2 == ex_to(*it2).toggle_variance(), subs_options::no_pattern); + *it2 = ex_to(*it2).toggle_variance(); something_changed = true; - it2 = ex_to(e).seq.begin() + (it2 - it2start); - it2start = ex_to(e).seq.begin(); - it2end = ex_to(e).seq.end(); } goto next_index; } @@ -731,6 +735,9 @@ bool reposition_dummy_indices(ex & e, exvector & variant_dummy_indices, exvector next_index: ; } + if (something_changed) + e = ex_to(e).thiscontainer(seq); + return something_changed; }