+
+/** Specialization of is_exactly_a<idx>(obj) for idx objects. */
+template<> inline bool is_exactly_a<idx>(const basic & obj)
+{
+ return obj.tinfo()==TINFO_idx;
+}
+
+/** Specialization of is_exactly_a<varidx>(obj) for varidx objects. */
+template<> inline bool is_exactly_a<varidx>(const basic & obj)
+{
+ return obj.tinfo()==TINFO_varidx;
+}
+
+/** Specialization of is_exactly_a<spinidx>(obj) for spinidx objects. */
+template<> inline bool is_exactly_a<spinidx>(const basic & obj)
+{
+ return obj.tinfo()==TINFO_spinidx;
+}
+
+/** Check whether two indices form a dummy pair. */
+bool is_dummy_pair(const idx & i1, const idx & i2);
+
+/** Check whether two expressions form a dummy index pair. */
+bool is_dummy_pair(const ex & e1, const ex & e2);
+
+/** Given a vector of indices, split them into two vectors, one containing
+ * the free indices, the other containing the dummy indices (numeric
+ * indices are neither free nor dummy ones).
+ *
+ * @param it Pointer to start of index vector
+ * @param itend Pointer to end of index vector
+ * @param out_free Vector of free indices (returned, sorted)
+ * @param out_dummy Vector of dummy indices (returned, sorted) */
+void find_free_and_dummy(exvector::const_iterator it, exvector::const_iterator itend, exvector & out_free, exvector & out_dummy);
+
+/** Given a vector of indices, split them into two vectors, one containing
+ * the free indices, the other containing the dummy indices (numeric
+ * indices are neither free nor dummy ones).
+ *
+ * @param v Index vector
+ * @param out_free Vector of free indices (returned, sorted)
+ * @param out_dummy Vector of dummy indices (returned, sorted) */
+inline void find_free_and_dummy(const exvector & v, exvector & out_free, exvector & out_dummy)