+/* Function object for STL sort() */
+struct ex_is_less {
+ bool operator() (const ex &lh, const ex &rh) const
+ {
+ return lh.compare(rh) < 0;
+ }
+};
+
+/** 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;
+
+ sort(local_dummy_indices.begin(), local_dummy_indices.end(), ex_is_less());
+
+ 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) {
+ exvector::const_iterator git = global_dummy_indices.begin(), gitend = global_dummy_indices.end();
+ while (git != gitend) {
+ if (it->is_equal(*git))
+ goto found;
+ git++;
+ }
+ global_dummy_indices.push_back(*it);
+ global_size++;
+ remaining--;
+found: it++;
+ }
+ sort(global_dummy_indices.begin(), global_dummy_indices.end(), ex_is_less());
+ }
+
+ // 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);
+}
+