From 5bd0e922f4cf24ceb4631e57dc4bc326c62d715d Mon Sep 17 00:00:00 2001
From: "Vladimir V. Kisil" <kisilv@maths.leeds.ac.uk>
Date: Tue, 9 Aug 2016 18:28:13 +0100
Subject: [PATCH] Proper functions to make clifford_bar() and clifford_star()

Previously operations clifford_bar() and clifford_star() called
conjugate() method. This results in reversion of all non-commutative
entries (not only Clifford units) and produced complex conjugation
of all non-real items. The new routine operates on Clifford units only.

Signed-off-by: Vladimir V. Kisil <kisilv@maths.leeds.ac.uk>
---
 check/exam_clifford.cpp | 38 +++++++++++++++++++++++++++++++++++++-
 doc/tutorial/ginac.texi |  7 +++----
 ginac/clifford.cpp      | 42 ++++++++++++++++++++++++++++++++++++++++++
 ginac/clifford.h        | 10 +++++++---
 4 files changed, 89 insertions(+), 8 deletions(-)

diff --git a/check/exam_clifford.cpp b/check/exam_clifford.cpp
index 6b1f53f..c49d4af 100644
--- a/check/exam_clifford.cpp
+++ b/check/exam_clifford.cpp
@@ -542,12 +542,46 @@ static unsigned clifford_check8()
 {
 	unsigned result = 0;
 
-	realsymbol a("a");
+	realsymbol a("a"), b("b"), x("x");
 	varidx mu(symbol("mu", "\\mu"), 1);
 
 	ex e = clifford_unit(mu, diag_matrix({-1})), e0 = e.subs(mu==0);
 	result += ( exp(a*e0)*e0*e0 == -exp(e0*a) ) ? 0 : 1;
 
+	ex P=color_T(idx(a,8))*color_T(idx(b,8))*(x*dirac_ONE()+sqrt(x-1)*e0),
+		P_prime=color_T(idx(a,8))*color_T(idx(b,8))*(x*dirac_ONE()-sqrt(x-1)*e0);
+
+	result += check_equal(clifford_prime(P), P_prime);
+	result += check_equal(clifford_star(P), P);
+	result += check_equal(clifford_bar(P), P_prime);
+
+	return result;
+}
+
+static unsigned clifford_check9()
+{
+	unsigned result = 0;
+
+	realsymbol a("a"), b("b"), x("x");;
+	varidx mu(symbol("mu", "\\mu"), 4),  nu(symbol("nu", "\\nu"), 4);
+
+	ex e = clifford_unit(mu, lorentz_g(mu, nu)), e0 = e.subs(mu==0),
+		e1 = e.subs(mu==1), e2 = e.subs(mu==2), e3 = e.subs(mu==3),
+		one = dirac_ONE();
+
+	ex P=color_T(idx(a,8))*color_T(idx(b,8))
+		*(x*one+sqrt(x-1)*e0+sqrt(x-2)*e0*e1 +sqrt(x-3)*e0*e1*e2 +sqrt(x-4)*e0*e1*e2*e3),
+		P_prime=color_T(idx(a,8))*color_T(idx(b,8))
+		*(x*one-sqrt(x-1)*e0+sqrt(x-2)*e0*e1 -sqrt(x-3)*e0*e1*e2 +sqrt(x-4)*e0*e1*e2*e3),
+		P_star=color_T(idx(a,8))*color_T(idx(b,8))
+		*(x*one+sqrt(x-1)*e0+sqrt(x-2)*e1*e0 +sqrt(x-3)*e2*e1*e0 +sqrt(x-4)*e3*e2*e1*e0),
+		P_bar=color_T(idx(a,8))*color_T(idx(b,8))
+		*(x*one-sqrt(x-1)*e0+sqrt(x-2)*e1*e0 -sqrt(x-3)*e2*e1*e0 +sqrt(x-4)*e3*e2*e1*e0);
+
+	result += check_equal(clifford_prime(P), P_prime);
+	result += check_equal(clifford_star(P), P_star);
+	result += check_equal(clifford_bar(P), P_bar);
+
 	return result;
 }
 
@@ -618,6 +652,8 @@ unsigned exam_clifford()
 
 	result += clifford_check8(); cout << '.' << flush;
 
+	result += clifford_check9(); cout << '.' << flush;
+
 	return result;
 }
 
diff --git a/doc/tutorial/ginac.texi b/doc/tutorial/ginac.texi
index b69455d..804e29d 100644
--- a/doc/tutorial/ginac.texi
+++ b/doc/tutorial/ginac.texi
@@ -3486,14 +3486,13 @@ There are several functions for (anti-)automorphisms of Clifford algebras:
 
 @example
     ex clifford_prime(const ex & e)
-    inline ex clifford_star(const ex & e) @{ return e.conjugate(); @}
-    inline ex clifford_bar(const ex & e) @{ return clifford_prime(e.conjugate()); @}
+    inline ex clifford_star(const ex & e)
+    inline ex clifford_bar(const ex & e)
 @end example
 
 The automorphism of a Clifford algebra @code{clifford_prime()} simply
 changes signs of all Clifford units in the expression. The reversion
-of a Clifford algebra @code{clifford_star()} coincides with the
-@code{conjugate()} method and effectively reverses the order of Clifford
+of a Clifford algebra @code{clifford_star()} reverses the order of Clifford
 units in any product. Finally the main anti-automorphism
 of a Clifford algebra @code{clifford_bar()} is the composition of the
 previous two, i.e. it makes the reversion and changes signs of all Clifford units
diff --git a/ginac/clifford.cpp b/ginac/clifford.cpp
index 57d6ce6..174294e 100644
--- a/ginac/clifford.cpp
+++ b/ginac/clifford.cpp
@@ -1087,6 +1087,48 @@ next_sym:	;
 	}
 }
 
+ex clifford_star_bar(const ex & e, bool do_bar, unsigned options)
+{
+	pointer_to_map_function_2args<bool, unsigned> fcn(clifford_star_bar, do_bar, options | 1);
+
+	 // is a child, no need to expand
+	ex e1= (options & 1 ? e : e.expand());
+
+	if (is_a<ncmul>(e1) ) { // reversing order of clifford units
+		exvector ev, cv;
+		ev.reserve(e1.nops());
+		cv.reserve(e1.nops());
+		// separate clifford and non-clifford entries
+		for (int i= 0; i < e1.nops(); ++i) {
+			if (is_a<clifford>(e1.op(i)) && is_a<cliffordunit>(e1.op(i).op(0)))
+				cv.push_back(e1.op(i));
+			else
+				ev.push_back(e1.op(i));
+		}
+		for (auto i=cv.end(); i!=cv.begin();) { // reverse order of Clifford units
+			--i;
+			ev.push_back(i->conjugate());
+		}
+		// For clifford_bar an odd number of clifford units reverts the sign
+		if (do_bar && (cv.size() % 2 == 1))
+			return -dynallocate<ncmul>(std::move(ev));
+		else
+			return dynallocate<ncmul>(std::move(ev));
+	} else if (is_a<clifford>(e1) && is_a<cliffordunit>(e1.op(0))) {
+		if (do_bar)
+			return -e;
+		else
+			return e;
+	// apply the procedure to the base of of power
+	} else if (is_a<power>(e1)) {
+		return pow(clifford_star_bar(e1.op(0), do_bar, 0), e1.op(1));
+	// recurse into subexpressions
+	} else if (is_a<add>(e1) || is_a<mul>(e1) || e.info(info_flags::list)) {
+		return e1.map(fcn);
+	} else // nothing meaningful can be done
+		return e;
+}
+
 ex clifford_prime(const ex & e)
 {
 	pointer_to_map_function fcn(clifford_prime);
diff --git a/ginac/clifford.h b/ginac/clifford.h
index 9708b0b..0402f93 100644
--- a/ginac/clifford.h
+++ b/ginac/clifford.h
@@ -282,12 +282,16 @@ ex canonicalize_clifford(const ex & e);
  *  clifford units. */
 ex clifford_prime(const ex & e);
 
+/** An auxillary function performing clifford_star() and clifford_bar().*/
+ex clifford_star_bar(const ex & e, bool do_bar, unsigned options);
+
 /** Main anti-automorphism of the Clifford algebra: makes reversion
  *  and changes signs of all clifford units. */
-inline ex clifford_bar(const ex & e) { return clifford_prime(e.conjugate()); }
+inline ex clifford_bar(const ex & e) { return clifford_star_bar(e, true, 0); }
 
-/** Reversion of the Clifford algebra, coincides with the conjugate(). */
-inline ex clifford_star(const ex & e) { return e.conjugate(); }
+/** Reversion of the Clifford algebra, reverse the order of all clifford units
+ *  in ncmul. */
+inline ex clifford_star(const ex & e) { return clifford_star_bar(e, false, 0); }
 
 /** Replaces dirac_ONE's (with a representation_label no less than rl) in e with 1.
  *  For the default value rl = 0 remove all of them. Aborts if e contains any 
-- 
2.8.1

