- 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);
+ return trONE * lorentz_g(e.op(0).op(1), e.op(1).op(1));
+
+ exvector iv;
+ iv.reserve(num);
+ for (unsigned i=0; i<num; i++)
+ iv.push_back(e.op(i).op(1));
+
+ return trONE * trace_string(iv.begin(), num);
+ }
+
+ } 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_ex_of_type(rhs_expanded, ncmul)) {
+ srl.let_op(i) = (lhs == canonicalize_clifford(rhs_expanded));
+ continue;
+
+ } else if (!is_ex_of_type(rhs.op(0), clifford))
+ 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_ex_of_type(it->op(0), diracgamma5))
+ it++;
+ while (it != next_to_last) {
+ if (it[0].op(1).compare(it[1].op(1)) > 0) {
+ ex save0 = it[0], save1 = it[1];
+ it[0] = lorentz_g(it[0].op(1), it[1].op(1));
+ 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;