- // Otherwise substitute value
- idx *i_copy = static_cast<idx *>(duplicate());
- i_copy->value = lr.op(i);
- return i_copy->setflag(status_flags::dynallocated);
- }
+int spinidx::compare_same_type(const basic & other) const
+{
+ GINAC_ASSERT(is_a<spinidx>(other));
+ const spinidx &o = static_cast<const spinidx &>(other);
+
+ // Check dottedness first so dummy indices will end up next to each other
+ if (dotted != o.dotted)
+ return dotted ? -1 : 1;
+
+ int cmpval = inherited::compare_same_type(other);
+ if (cmpval)
+ return cmpval;
+
+ return 0;
+}
+
+bool spinidx::match_same_type(const basic & other) const
+{
+ GINAC_ASSERT(is_a<spinidx>(other));
+ const spinidx &o = static_cast<const spinidx &>(other);
+
+ if (dotted != o.dotted)
+ return false;
+ return inherited::match_same_type(other);
+}
+
+/** By default, basic::evalf would evaluate the index value but we don't want
+ * a.1 to become a.(1.0). */
+ex idx::evalf(int level) const
+{
+ return *this;
+}
+
+ex idx::subs(const exmap & m, unsigned options) const
+{
+ // First look for index substitutions
+ exmap::const_iterator it = m.find(*this);
+ if (it != m.end()) {
+
+ // Substitution index->index
+ if (is_a<idx>(it->second))
+ return it->second;
+
+ // Otherwise substitute value
+ idx *i_copy = duplicate();
+ i_copy->value = it->second;
+ i_copy->clearflag(status_flags::hash_calculated);
+ return i_copy->setflag(status_flags::dynallocated);