- if (num == 2)
- return 4 * lorentz_g(e.op(0).op(1), e.op(1).op(1));
-
- // Traces of 4 or more gammas are computed recursively:
- // Tr gamma.mu1 gamma.mu2 ... gamma.mun =
- // + g.mu1.mu2 * Tr gamma.mu3 ... gamma.mun
- // - g.mu1.mu3 * Tr gamma.mu2 gamma.mu4 ... gamma.mun
- // + g.mu1.mu4 * Tr gamma.mu3 gamma.mu3 gamma.mu5 ... gamma.mun
- // - ...
- // + g.mu1.mun * Tr gamma.mu2 ... gamma.mu(n-1)
- exvector v(num - 2);
- int sign = 1;
- const ex &ix1 = e.op(0).op(1);
- ex result;
- for (int i=1; i<num; i++) {
- for (int n=1, j=0; n<num; n++) {
- if (n == i)
- continue;
- v[j++] = e.op(n);
+ if (num == 2) {
+ ex b1, i1, b2, i2;
+ base_and_index(e.op(0), b1, i1);
+ base_and_index(e.op(1), b2, i2);
+ return trONE * (lorentz_g(i1, i2) * b1 * b2).simplify_indexed();
+ }
+
+ exvector iv(num), bv(num);
+ for (unsigned i=0; i<num; i++)
+ base_and_index(e.op(i), bv[i], iv[i]);
+
+ return trONE * (trace_string(iv.begin(), num) * mul(bv)).simplify_indexed();
+ }
+
+ } else if (e.nops() > 0) {
+
+ // Trace maps to all other container classes (this includes sums)
+ pointer_to_map_function_2args<unsigned char, const ex &> fcn(dirac_trace, rl, trONE);
+ return e.map(fcn);
+
+ } else
+ return _ex0();
+}
+
+ex canonicalize_clifford(const ex & e)
+{
+ // Scan for any ncmul objects
+ lst srl;
+ ex aux = e.to_rational(srl);
+ for (unsigned i=0; i<srl.nops(); i++) {
+
+ ex lhs = srl.op(i).lhs();
+ ex rhs = srl.op(i).rhs();
+
+ if (is_ex_exactly_of_type(rhs, ncmul)
+ && rhs.return_type() == return_types::noncommutative
+ && is_clifford_tinfo(rhs.return_type_tinfo())) {
+
+ // Expand product, if necessary
+ ex rhs_expanded = rhs.expand();
+ if (!is_a<ncmul>(rhs_expanded)) {
+ srl.let_op(i) = (lhs == canonicalize_clifford(rhs_expanded));
+ continue;
+
+ } else if (!is_a<clifford>(rhs.op(0)))
+ continue;
+
+ exvector v;
+ v.reserve(rhs.nops());
+ for (unsigned j=0; j<rhs.nops(); j++)
+ v.push_back(rhs.op(j));
+
+ // Stupid recursive bubble sort because we only want to swap adjacent gammas
+ exvector::iterator it = v.begin(), next_to_last = v.end() - 1;
+ if (is_a<diracgamma5>(it->op(0)))
+ ++it;
+ while (it != next_to_last) {
+ if (it[0].compare(it[1]) > 0) {
+ ex save0 = it[0], save1 = it[1];
+ ex b1, i1, b2, i2;
+ base_and_index(it[0], b1, i1);
+ base_and_index(it[1], b2, i2);
+ it[0] = (lorentz_g(i1, i2) * b1 * b2).simplify_indexed();
+ it[1] = _ex2();
+ ex sum = ncmul(v);
+ it[0] = save1;
+ it[1] = save0;
+ sum -= ncmul(v, true);
+ srl.let_op(i) = (lhs == canonicalize_clifford(sum));
+ goto next_sym;