+/** Contraction of generator with something else. */
+bool su3t::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const
+{
+ GINAC_ASSERT(is_a<indexed>(*self));
+ GINAC_ASSERT(is_a<indexed>(*other));
+ GINAC_ASSERT(self->nops() == 2);
+ GINAC_ASSERT(is_a<su3t>(self->op(0)));
+ unsigned char rl = ex_to<color>(*self).get_representation_label();
+
+ if (is_exactly_a<su3t>(other->op(0))) {
+
+ // Contraction only makes sense if the represenation labels are equal
+ GINAC_ASSERT(is_a<color>(*other));
+ if (ex_to<color>(*other).get_representation_label() != rl)
+ return false;
+
+ // T.a T.a = 4/3 ONE
+ if (other - self == 1) {
+ *self = numeric(4, 3);
+ *other = color_ONE(rl);
+ return true;
+
+ // T.a T.b T.a = -1/6 T.b
+ } else if (other - self == 2
+ && is_a<color>(self[1])) {
+ *self = numeric(-1, 6);
+ *other = _ex1;
+ return true;
+
+ // T.a S T.a = 1/2 Tr(S) - 1/6 S
+ } else {
+ exvector::iterator it = self + 1;
+ while (it != other) {
+ if (!is_a<color>(*it)) {
+ return false;
+ }
+ it++;
+ }
+
+ it = self + 1;
+ ex S = _ex1;
+ while (it != other) {
+ S *= *it;
+ *it++ = _ex1;
+ }
+
+ *self = color_trace(S, rl) * color_ONE(rl) / 2 - S / 6;
+ *other = _ex1;
+ return true;
+ }
+ }
+
+ return false;
+}
+