+ GINAC_ASSERT(ls.nops() == lr.nops());
+
+ // First look for index substitutions
+ for (unsigned i=0; i<ls.nops(); i++) {
+ if (is_equal(*(ls.op(i)).bp)) {
+
+ // Substitution index->index
+ if (is_ex_of_type(lr.op(i), idx))
+ return lr.op(i);
+
+ // Otherwise substitute value
+ idx *i_copy = static_cast<idx *>(duplicate());
+ i_copy->value = lr.op(i);
+ i_copy->clearflag(status_flags::hash_calculated);
+ return i_copy->setflag(status_flags::dynallocated);
+ }
+ }
+
+ // None, substitute objects in value (not in dimension)
+ const ex &subsed_value = value.subs(ls, lr);
+ if (are_ex_trivially_equal(value, subsed_value))
+ return *this;
+
+ idx *i_copy = static_cast<idx *>(duplicate());
+ i_copy->value = subsed_value;
+ i_copy->clearflag(status_flags::hash_calculated);
+ return i_copy->setflag(status_flags::dynallocated);