+/** Rename dummy indices in an expression.
+ *
+ * @param e Expression to be worked on
+ * @param local_dummy_indices The set of dummy indices that appear in the
+ * expression "e"
+ * @param global_dummy_indices The set of dummy indices that have appeared
+ * before and which we would like to use in "e", too. This gets updated
+ * by the function */
+static ex rename_dummy_indices(const ex & e, exvector & global_dummy_indices, exvector & local_dummy_indices)
+{
+ int global_size = global_dummy_indices.size(),
+ local_size = local_dummy_indices.size();
+
+ // Any local dummy indices at all?
+ if (local_size == 0)
+ return e;
+
+ if (global_size < local_size) {
+
+ // More local indices than we encountered before, add the new ones
+ // to the global set
+ int remaining = local_size - global_size;
+ exvector::const_iterator it = local_dummy_indices.begin(), itend = local_dummy_indices.end();
+ while (it != itend && remaining > 0) {
+ if (find_if(global_dummy_indices.begin(), global_dummy_indices.end(), bind2nd(ex_is_equal(), *it)) == global_dummy_indices.end()) {
+ global_dummy_indices.push_back(*it);
+ global_size++;
+ remaining--;
+ }
+ it++;
+ }
+ }
+
+ // Replace index symbols in expression
+ GINAC_ASSERT(local_size <= global_size);
+ bool all_equal = true;
+ lst local_syms, global_syms;
+ for (unsigned i=0; i<local_size; i++) {
+ ex loc_sym = local_dummy_indices[i].op(0);
+ ex glob_sym = global_dummy_indices[i].op(0);
+ if (!loc_sym.is_equal(glob_sym)) {
+ all_equal = false;
+ local_syms.append(loc_sym);
+ global_syms.append(glob_sym);
+ }
+ }
+ if (all_equal)
+ return e;
+ else
+ return e.subs(local_syms, global_syms);
+}
+