* Applied Vladimir Kisil's patches (bug in clifford_prime and clifford_to_lst,
authorJens Vollinga <vollinga@thep.physik.uni-mainz.de>
Fri, 1 Apr 2005 18:23:40 +0000 (18:23 +0000)
committerJens Vollinga <vollinga@thep.physik.uni-mainz.de>
Fri, 1 Apr 2005 18:23:40 +0000 (18:23 +0000)
  remove_dirac_ONE honors representation_label, improved clifford
  documentation, better LaTeX output).
* Chris Dams' patch applied to correct canonicalize_clifford.
* Truncated some lines in the tutorial that were too long for printing nicely.

check/exam_clifford.cpp
doc/tutorial/ginac.texi
ginac/clifford.cpp
ginac/clifford.h

index 0df5ebb..ec7946c 100644 (file)
@@ -341,9 +341,10 @@ static unsigned clifford_check6(const matrix & A)
        // lst_to_clifford() and clifford_inverse()  check
        symbol x("x"), y("y"), t("t"), z("z");
        
-       e = lst_to_clifford(lst(t, x, y, z), mu, G) * lst_to_clifford(lst(1, 2, 3, 4), nu, G);
+       ex c = clifford_unit(nu, G, 1);
+       e = lst_to_clifford(lst(t, x, y, z), mu, G, 1) * lst_to_clifford(lst(1, 2, 3, 4), c);
        e1 = clifford_inverse(e);
-       result += check_equal((e*e1).simplify_indexed().normal(), dirac_ONE());
+       result += check_equal((e*e1).simplify_indexed().normal(), dirac_ONE(1));
 
        return result;
 }
index e0ae80b..86ca84a 100644 (file)
@@ -1943,7 +1943,8 @@ ex diag_matrix(const lst & l);
 ex unit_matrix(unsigned x);
 ex unit_matrix(unsigned r, unsigned c);
 ex symbolic_matrix(unsigned r, unsigned c, const string & base_name);
-ex symbolic_matrix(unsigned r, unsigned c, const string & base_name, const string & tex_base_name);
+ex symbolic_matrix(unsigned r, unsigned c, const string & base_name,
+                   const string & tex_base_name);
 @end example
 
 @code{diag_matrix()} constructs a diagonal matrix given the list of diagonal
@@ -2113,7 +2114,8 @@ Matrices may also be inverted using the @code{ex matrix::inverse()}
 method and linear systems may be solved with:
 
 @example
-matrix matrix::solve(const matrix & vars, const matrix & rhs, unsigned algo=solve_algo::automatic) const;
+matrix matrix::solve(const matrix & vars, const matrix & rhs,
+                     unsigned algo=solve_algo::automatic) const;
 @end example
 
 Assuming the matrix object this method is applied on is an @code{m}
@@ -2784,7 +2786,8 @@ dimensions:
 @example
 ex epsilon_tensor(const ex & i1, const ex & i2);
 ex epsilon_tensor(const ex & i1, const ex & i2, const ex & i3);
-ex lorentz_eps(const ex & i1, const ex & i2, const ex & i3, const ex & i4, bool pos_sig = false);
+ex lorentz_eps(const ex & i1, const ex & i2, const ex & i3, const ex & i4,
+               bool pos_sig = false);
 @end example
 
 The first two functions create an epsilon tensor in 2 or 3 Euclidean
@@ -3084,7 +3087,8 @@ To calculate the trace of an expression containing strings of Dirac gammas
 you use one of the functions
 
 @example
-ex dirac_trace(const ex & e, const std::set<unsigned char> & rls, const ex & trONE = 4);
+ex dirac_trace(const ex & e, const std::set<unsigned char> & rls,
+               const ex & trONE = 4);
 ex dirac_trace(const ex & e, const lst & rll, const ex & trONE = 4);
 ex dirac_trace(const ex & e, unsigned char rl = 0, const ex & trONE = 4);
 @end example
@@ -3097,13 +3101,18 @@ element, which defaults to 4.
 
 The @code{dirac_trace()} function is a linear functional that is equal to the
 ordinary matrix trace only in @math{D = 4} dimensions. In particular, the
-functional is not cyclic in @math{D != 4} dimensions when acting on
+functional is not cyclic in
+@tex $D \ne 4$
+@end tex
+dimensions when acting on
 expressions containing @samp{gamma5}, so it's not a proper trace. This
 @samp{gamma5} scheme is described in greater detail in
 @cite{The Role of gamma5 in Dimensional Regularization}.
 
 The value of the trace itself is also usually different in 4 and in
-@math{D != 4} dimensions:
+@tex $D \ne 4$
+@end tex
+dimensions:
 
 @example
 @{
@@ -3175,17 +3184,26 @@ A generic Clifford algebra, i.e. a
 $2^n$
 @end tex
 dimensional algebra with
-generators @samp{e~k} satisfying the identities 
-@samp{e~i e~j + e~j e~i = B(i, j)} for some matrix (@code{metric})
-@math{B(i, j)}, which may be non-symmetric. Such generators are created
-by the function
+generators 
+@tex $e_k$
+@end tex 
+satisfying the identities 
+@tex
+$e_i e_j + e_j e_i = M(i, j) $
+@end tex
+@ifnottex
+e~i e~j + e~j e~i = M(i, j)
+@end ifnottex
+for some matrix (@code{metric})
+@math{M(i, j)}, which may be non-symmetric and containing symbolic
+entries. Such generators are created by the function
 
 @example
     ex clifford_unit(const ex & mu, const ex & metr, unsigned char rl = 0);
 @end example
 
 where @code{mu} should be a @code{varidx} class object indexing the
-generators, @code{metr} defines the metric @math{B(i, j)} and can be
+generators, @code{metr} defines the metric @math{M(i, j)} and can be
 represented by a square @code{matrix}, @code{tensormetric} or @code{indexed} class
 object, optional parameter @code{rl} allows to distinguish different
 Clifford algebras (which will commute with each other). Note that the call
@@ -3193,11 +3211,11 @@ Clifford algebras (which will commute with each other). Note that the call
 @code{dirac_gamma(mu)}. The method @code{clifford::get_metric()} returns a
 metric defining this Clifford number.
 
-If the matrix @math{B(i, j)} is in fact symmetric you may prefer to create
+If the matrix @math{M(i, j)} is in fact symmetric you may prefer to create
 the Clifford algebra units with a call like that
 
 @example
-    ex e = clifford_unit(mu, indexed(B, sy_symm(), i, j));
+    ex e = clifford_unit(mu, indexed(M, sy_symm(), i, j));
 @end example
 
 since this may yield some further automatic simplifications.
@@ -3208,20 +3226,25 @@ ways. For example
 @example
 @{
     ... 
-    varidx nu(symbol("nu"), 3);
-    matrix M(3, 3) = 1, 0, 0,
-                     0,-1, 0,
-                     0, 0, 0;
+    varidx nu(symbol("nu"), 4);
+    realsymbol s("s");
+    ex M = diag_matrix(lst(1, -1, 0, s));
     ex e = clifford_unit(nu, M);
     ex e0 = e.subs(nu == 0);
     ex e1 = e.subs(nu == 1);
     ex e2 = e.subs(nu == 2);
+    ex e3 = e.subs(nu == 3);
     ...
 @}
 @end example
 
-will produce three generators of a Clifford algebra with properties
-@code{pow(e0, 2) = 1},  @code{pow(e1, 2) = -1} and   @code{pow(e2, 2) = 0}. 
+will produce four anti-commuting generators of a Clifford algebra with properties
+@tex
+$e_0^2=1 $, $e_1^2=-1$,  $e_2^2=0$ and $e_3^2=s$.
+@end tex
+@ifnottex
+@code{pow(e0, 2) = 1},  @code{pow(e1, 2) = -1},   @code{pow(e2, 2) = 0} and   @code{pow(e3, 2) = s}. 
+@end ifnottex
 
 @cindex @code{lst_to_clifford()}
 A similar effect can be achieved from the function
@@ -3229,23 +3252,40 @@ A similar effect can be achieved from the function
 @example
     ex lst_to_clifford(const ex & v, const ex & mu,  const ex & metr,
                        unsigned char rl = 0);
+    ex lst_to_clifford(const ex & v, const ex & e);
 @end example
 
-which converts a list or vector @samp{v = (v~0, v~1, ..., v~n)} into
-the Clifford number @samp{v~0 e.0 + v~1 e.1 + ... + v~n e.n} with @samp{e.k}
-being created by @code{clifford_unit(mu, metr, rl)}. The previous code
-may be rewritten with the help of @code{lst_to_clifford()} as follows
+which converts a list or vector 
+@tex
+$v = (v^0, v^1, ..., v^n)$
+@end tex
+@ifnottex
+@samp{v = (v~0, v~1, ..., v~n)} 
+@end ifnottex
+into the
+Clifford number 
+@tex
+$v^0 e_0 + v^1 e_1 + ... + v^n e_n$
+@end tex
+@ifnottex
+@samp{v~0 e.0 + v~1 e.1 + ... + v~n e.n}
+@end ifnottex
+with @samp{e.k}
+directly supplied in the second form of the procedure. In the first form
+the Clifford unit @samp{e.k} is generated by the call of
+@code{clifford_unit(mu, metr, rl)}. The previous code may be rewritten
+with the help of @code{lst_to_clifford()} as follows
 
 @example
 @{
     ...
-    varidx nu(symbol("nu"), 3);
-    matrix M(3, 3) = 1, 0, 0,
-                     0,-1, 0,
-                     0, 0, 0;
-    ex e0 = lst_to_clifford(lst(1, 0, 0), nu, M);
-    ex e1 = lst_to_clifford(lst(0, 1, 0), nu, M);
-    ex e2 = lst_to_clifford(lst(0, 0, 1), nu, M);
+    varidx nu(symbol("nu"), 4);
+    realsymbol s("s");
+    ex M = diag_matrix(lst(1, -1, 0, s));
+    ex e0 = lst_to_clifford(lst(1, 0, 0, 0), nu, M);
+    ex e1 = lst_to_clifford(lst(0, 1, 0, 0), nu, M);
+    ex e2 = lst_to_clifford(lst(0, 0, 1, 0), nu, M);
+    ex e3 = lst_to_clifford(lst(0, 0, 0, 1), nu, M);
   ...
 @}
 @end example
@@ -3258,12 +3298,30 @@ There is the inverse function
 @end example
 
 which takes an expression @code{e} and tries to find a list
-@samp{v = (v~0, v~1, ..., v~n)} such that @samp{e = v~0 c.0 + v~1 c.1 + ...
-+ v~n c.n} with respect to the given Clifford units @code{c} and none of
-@samp{v~k} contains the Clifford units @code{c} (of course, this
+@tex
+$v = (v^0, v^1, ..., v^n)$
+@end tex
+@ifnottex
+@samp{v = (v~0, v~1, ..., v~n)} 
+@end ifnottex
+such that 
+@tex
+$e = v^0 c_0 + v^1 c_1 + ... + v^n c_n$
+@end tex
+@ifnottex
+@samp{e = v~0 c.0 + v~1 c.1 + ... + v~n c.n}
+@end ifnottex
+with respect to the given Clifford units @code{c} and with none of the
+@samp{v~k} containing Clifford units @code{c} (of course, this
 may be impossible). This function can use an @code{algebraic} method
-(default) or a symbolic one. With the @code{algebraic} method @samp{v~k} are calculated as
-@samp{(e c.k + c.k e)/pow(c.k, 2)}.  If @samp{pow(c.k, 2) = 0} for some @samp{k}
+(default) or a symbolic one. With the @code{algebraic} method the @samp{v~k} are calculated as
+@tex
+$(e c_k + c_k e)/c_k^2$. If $c_k^2$
+@end tex
+@ifnottex
+@samp{(e c.k + c.k e)/pow(c.k, 2)}.   If @samp{pow(c.k, 2)} 
+@end ifnottex
+is zero or is not a @code{numeric} for some @samp{k}
 then the method will be automatically changed to symbolic. The same effect
 is obtained by the assignment (@code{algebraic = false}) in the procedure call.
 
@@ -3290,10 +3348,16 @@ in a product. These functions correspond to the notations
 @tex
 $e^*$
 @end tex
+@ifnottex
+e*
+@end ifnottex
 and
 @tex
 $\overline{e}$
 @end tex
+@ifnottex
+@code{\bar@{e@}}
+@end ifnottex
 used in Clifford algebra textbooks.
 
 @cindex @code{clifford_norm()}
@@ -3306,10 +3370,12 @@ The function
 @cindex @code{clifford_inverse()}
 calculates the norm of a Clifford number from the expression
 @tex
-$||e||^2 = e\overline{e}$
+$||e||^2 = e\overline{e}$.
 @end tex
-. The inverse of a Clifford expression is returned
-by the function
+@ifnottex
+@code{||e||^2 = e \bar@{e@}}
+@end ifnottex
+ The inverse of a Clifford expression is returned by the function
 
 @example
     ex clifford_inverse(const ex & e);
@@ -3317,12 +3383,18 @@ by the function
 
 which calculates it as 
 @tex
-$e^{-1} = e/||e||^2$
+$e^{-1} = \overline{e}/||e||^2$.
 @end tex
-. If
+@ifnottex
+@math{e^@{-1@} = \bar@{e@}/||e||^2}
+@end ifnottex
+ If
 @tex
 $||e|| = 0$
 @end tex
+@ifnottex
+@math{||e||=0}
+@end ifnottex
 then an exception is raised.
 
 @cindex @code{remove_dirac_ONE()}
@@ -3343,17 +3415,53 @@ The last provided function is
 @cindex @code{clifford_moebius_map()}
 @example
     ex clifford_moebius_map(const ex & a, const ex & b, const ex & c,
-                            const ex & d, const ex & v, const ex & G, unsigned char rl = 0);
-    ex clifford_moebius_map(const ex & M, const ex & v, const ex & G, unsigned char rl = 0);
+                            const ex & d, const ex & v, const ex & G,
+                            unsigned char rl = 0);
+    ex clifford_moebius_map(const ex & M, const ex & v, const ex & G,
+                            unsigned char rl = 0);
 @end example 
 
-It takes a list or vector @code{v} and makes the Moebius
-(conformal or linear-fractional) transformation @samp{v ->
-(av+b)/(cv+d)} defined by the matrix @samp{M = [[a, b], [c, d]]}. The
-parameter @code{G} defines the metric of the surrounding
-(pseudo-)Euclidean space. The returned value of this function is a list
+It takes a list or vector @code{v} and makes the Moebius (conformal or
+linear-fractional) transformation @samp{v -> (av+b)/(cv+d)} defined by
+the matrix @samp{M = [[a, b], [c, d]]}. The parameter @code{G} defines
+the metric of the surrounding (pseudo-)Euclidean space. This can be a
+matrix or a Clifford unit, in the later case the parameter @code{rl} is
+ignored even if supplied.  The returned value of this function is a list
 of components of the resulting vector.
 
+LaTeX output for Clifford units looks like @code{\clifford[1]@{e@}^@{@{\nu@}@}},
+where @code{1} is the @code{representation_label} and @code{\nu} is the
+index of the corresponding unit. This provides a flexible typesetting
+with a suitable defintion of the @code{\clifford} command. For example, the
+definition 
+@example
+    \newcommand@{\clifford@}[1][]@{@}
+@end example
+typesets all Clifford units identically, while the alternative definition
+@example
+    \newcommand@{\clifford@}[2][]@{\ifcase #1 #2\or \tilde@{#2@} \or \breve@{#2@} \fi@}
+@end example
+prints units with @code{representation_label=0} as 
+@tex
+$e$,
+@end tex
+@ifnottex
+@code{e},
+@end ifnottex
+with @code{representation_label=1} as 
+@tex
+$\tilde{e}$
+@end tex
+@ifnottex
+@code{\tilde@{e@}}
+@end ifnottex
+ and with @code{representation_label=2} as 
+@tex
+$\breve{e}$.
+@end tex
+@ifnottex
+@code{\breve@{e@}}.
+@end ifnottex
 
 @cindex @code{color} (class)
 @subsection Color algebra
@@ -4817,9 +4925,11 @@ together with @code{find()}:
 
 @example
 > a=expand((sin(x)+sin(y))*(1+p+q)*(1+d));
-d*p*sin(x)+p*sin(x)+q*d*sin(x)+q*sin(y)+d*sin(x)+q*d*sin(y)+sin(y)+d*sin(y)+q*sin(x)+d*sin(y)*p+sin(x)+sin(y)*p
+d*p*sin(x)+p*sin(x)+q*d*sin(x)+q*sin(y)+d*sin(x)+q*d*sin(y)+sin(y)+d*sin(y)
++q*sin(x)+d*sin(y)*p+sin(x)+sin(y)*p
 > collect(a,@{p,q@});
-d*sin(x)+(d*sin(x)+sin(y)+d*sin(y)+sin(x))*p+(d*sin(x)+sin(y)+d*sin(y)+sin(x))*q+sin(y)+d*sin(y)+sin(x)
+d*sin(x)+(d*sin(x)+sin(y)+d*sin(y)+sin(x))*p
++(d*sin(x)+sin(y)+d*sin(y)+sin(x))*q+sin(y)+d*sin(y)+sin(x)
 > collect(a,find(a,sin($1)));
 (1+q+d+q*d+d*p+p)*sin(y)+(1+q+d+q*d+d*p+p)*sin(x)
 > collect(a,@{find(a,sin($1)),p,q@});
@@ -5808,7 +5918,8 @@ matrix operations that comes in handy when a system of linear equations
 needs to be solved:
 
 @example
-ex lsolve(const ex &eqns, const ex &symbols, unsigned options=solve_algo::automatic);
+ex lsolve(const ex & eqns, const ex & symbols,
+          unsigned options = solve_algo::automatic);
 @end example
 
 Here, @code{eqns} is a @code{lst} of equalities (i.e. class
@@ -5887,7 +5998,8 @@ format to the default, use the @code{dflt} manipulator:
 
 @example
     // ...
-    cout << latex;            // all output to cout will be in LaTeX format from now on
+    cout << latex;            // all output to cout will be in LaTeX format from
+                              // now on
     cout << e << endl;        // prints '4.5 i+\frac@{3@}@{2@} x^@{2@}'
     cout << sin(x/2) << endl; // prints '\sin(\frac@{1@}@{2@} x)'
     cout << dflt;             // revert to default output format
@@ -5978,7 +6090,8 @@ For example, the code snippet
 will print
 
 @example
-    @{(-\ln(\circ))@}+@{(-\gamma_E)@} \circ+@{(\frac@{1@}@{12@} \pi^@{2@})@} \circ^@{2@}+\mathcal@{O@}(\circ^@{3@})
+    @{(-\ln(\circ))@}+@{(-\gamma_E)@} \circ+@{(\frac@{1@}@{12@} \pi^@{2@})@} \circ^@{2@}
+    +\mathcal@{O@}(\circ^@{3@})
 @end example
 
 @cindex @code{index_dimensions}
@@ -6806,7 +6919,8 @@ int main()
     // our own one
     set_print_func<power, print_latex>(my_print_power_as_latex);
 
-    // this prints "-1+@{@{(y+x)@}@}\uparrow@{2@}-3 \frac@{@{x@}\uparrow@{3@}@}@{@{y@}\uparrow@{2@}@}"
+    // this prints "-1+@{@{(y+x)@}@}\uparrow@{2@}-3 \frac@{@{x@}\uparrow@{3@}@}@{@{y@}
+    //              \uparrow@{2@}@}"
     cout << e << endl;
 @}
 @end example
@@ -7150,7 +7264,8 @@ inline bool operator==(const sprod_s & lhs, const sprod_s & rhs)
 
 inline bool operator<(const sprod_s & lhs, const sprod_s & rhs)
 @{
-    return lhs.left.compare(rhs.left) < 0 ? true : lhs.right.compare(rhs.right) < 0;
+    return lhs.left.compare(rhs.left) < 0
+           ? true : lhs.right.compare(rhs.right) < 0;
 @}
 @end example
 
@@ -8208,7 +8323,8 @@ For packages configured using GNU automake, GiNaC also provides
 a macro to automate the process of checking for GiNaC.
 
 @example
-AM_PATH_GINAC([@var{MINIMUM-VERSION}, [@var{ACTION-IF-FOUND} [, @var{ACTION-IF-NOT-FOUND}]]])
+AM_PATH_GINAC([@var{MINIMUM-VERSION}, [@var{ACTION-IF-FOUND}
+              [, @var{ACTION-IF-NOT-FOUND}]]])
 @end example
 
 This macro:
index d629d5b..8854d61 100644 (file)
@@ -155,7 +155,7 @@ DEFAULT_ARCHIVING(diracgammaR)
 
 ex clifford::get_metric(const ex & i, const ex & j) const
 {
-       return indexed(metric, symmetric2(), i, j);
+       return indexed(metric, i, j);
 }
 
 bool clifford::same_metric(const ex & other) const
@@ -213,8 +213,10 @@ void clifford::do_print_latex(const print_latex & c, unsigned level) const
                c.s << "{";
                seq[0].print(c, level);
                c.s << "\\hspace{-1.0ex}/}";
-       } else
+       } else {
+               c.s << "\\clifford[" << int(representation_label) << "]";
                this->print_dispatch<inherited>(c, level);
+       }
 }
 
 DEFAULT_COMPARE(diracone)
@@ -224,7 +226,7 @@ DEFAULT_COMPARE(diracgamma5)
 DEFAULT_COMPARE(diracgammaL)
 DEFAULT_COMPARE(diracgammaR)
 
-DEFAULT_PRINT_LATEX(diracone, "ONE", "\\mathbb{1}")
+DEFAULT_PRINT_LATEX(diracone, "ONE", "\\mathbf{1}")
 DEFAULT_PRINT_LATEX(cliffordunit, "e", "e")
 DEFAULT_PRINT_LATEX(diracgamma, "gamma", "\\gamma")
 DEFAULT_PRINT_LATEX(diracgamma5, "gamma5", "{\\gamma^5}")
@@ -937,14 +939,15 @@ ex dirac_trace(const ex & e, unsigned char rl, const ex & trONE)
 }
 
 
-ex canonicalize_clifford(const ex & e)
+ex canonicalize_clifford(const ex & e_)
 {
        pointer_to_map_function fcn(canonicalize_clifford);
 
-       if (is_a<matrix>(e)    // || is_a<pseries>(e) || is_a<integral>(e)
-               || is_a<lst>(e)) {
-               return e.map(fcn);
+       if (is_a<matrix>(e_)    // || is_a<pseries>(e) || is_a<integral>(e)
+               || is_a<lst>(e_)) {
+               return e_.map(fcn);
        } else {
+               ex e=simplify_indexed(e_);
                // Scan for any ncmul objects
                exmap srl;
                ex aux = e.to_rational(srl);
@@ -1004,8 +1007,8 @@ ex clifford_prime(const ex & e)
        pointer_to_map_function fcn(clifford_prime);
        if (is_a<clifford>(e) && is_a<cliffordunit>(e.op(0))) {
                return -e;
-       } else if (is_a<add>(e) || is_a<ncmul>(e)  // || is_a<pseries>(e) || is_a<integral>(e)
-                       || is_a<matrix>(e) || is_a<lst>(e)) {
+       } else if (is_a<add>(e) || is_a<ncmul>(e) || is_a<mul>(e) //|| is_a<pseries>(e) || is_a<integral>(e)
+                          || is_a<matrix>(e) || is_a<lst>(e)) {
                return e.map(fcn);
        } else if (is_a<power>(e)) {
                return pow(clifford_prime(e.op(0)), e.op(1));
@@ -1013,13 +1016,16 @@ ex clifford_prime(const ex & e)
                return e;
 }
 
-ex remove_dirac_ONE(const ex & e)
+ex remove_dirac_ONE(const ex & e,  unsigned char rl)
 {
-       pointer_to_map_function fcn(remove_dirac_ONE);
-       if (is_a<clifford>(e) && is_a<diracone>(e.op(0))) {
-               return 1;
+       pointer_to_map_function_1arg<unsigned char> fcn(remove_dirac_ONE, rl);
+       if (is_a<clifford>(e) && ex_to<clifford>(e).get_representation_label() >= rl) {
+               if (is_a<diracone>(e.op(0)))
+                       return 1;
+               else
+                       throw(std::invalid_argument("Expression is a non-scalar Clifford number!"));
        } else if (is_a<add>(e) || is_a<ncmul>(e) || is_a<mul>(e)  // || is_a<pseries>(e) || is_a<integral>(e)
-                       || is_a<matrix>(e) || is_a<lst>(e)) {
+                          || is_a<matrix>(e) || is_a<lst>(e)) {
                return e.map(fcn);
        } else if (is_a<power>(e)) {
                return pow(remove_dirac_ONE(e.op(0)), e.op(1));
@@ -1043,37 +1049,43 @@ ex clifford_inverse(const ex & e)
 
 ex lst_to_clifford(const ex & v, const ex & mu, const ex & metr, unsigned char rl)
 {
-       unsigned min, max;
        if (!ex_to<idx>(mu).is_dim_numeric())
                throw(std::invalid_argument("Index should have a numeric dimension"));
-       unsigned dim = (ex_to<numeric>(ex_to<idx>(mu).get_dim())).to_int();
-       ex c = clifford_unit(mu, metr, rl);
+       ex e = clifford_unit(mu, metr, rl);
+       return lst_to_clifford(v, e);
+}
 
-       if (is_a<matrix>(v)) {
-               if (ex_to<matrix>(v).cols() > ex_to<matrix>(v).rows()) {
-                       min = ex_to<matrix>(v).rows();
-                       max = ex_to<matrix>(v).cols();
-               } else {
-                       min = ex_to<matrix>(v).cols();
-                       max = ex_to<matrix>(v).rows();
-               }
-               if (min == 1) {
-                       if (dim == max)
-                               if (is_a<varidx>(mu)) // need to swap variance
-                                       return indexed(v, ex_to<varidx>(mu).toggle_variance()) * c;
+ex lst_to_clifford(const ex & v, const ex & e) {
+       unsigned min, max;
+
+       if (is_a<clifford>(e)) {
+               varidx mu = ex_to<varidx>(e.op(1));
+               unsigned dim = (ex_to<numeric>(mu.get_dim())).to_int();
+
+               if (is_a<matrix>(v)) {
+                       if (ex_to<matrix>(v).cols() > ex_to<matrix>(v).rows()) {
+                               min = ex_to<matrix>(v).rows();
+                               max = ex_to<matrix>(v).cols();
+                       } else {
+                               min = ex_to<matrix>(v).cols();
+                               max = ex_to<matrix>(v).rows();
+                       }
+                       if (min == 1) {
+                               if (dim == max)
+                                       return indexed(v, ex_to<varidx>(mu).toggle_variance()) * e;
                                else
-                                       return indexed(v, mu) * c;
+                                       throw(std::invalid_argument("Dimensions of vector and clifford unit mismatch"));
+                       } else
+                               throw(std::invalid_argument("First argument should be a vector vector"));
+               } else if (is_a<lst>(v)) {
+                       if (dim == ex_to<lst>(v).nops())
+                               return indexed(matrix(dim, 1, ex_to<lst>(v)), ex_to<varidx>(mu).toggle_variance()) * e;
                        else
-                               throw(std::invalid_argument("Dimensions of vector and clifford unit mismatch"));
+                               throw(std::invalid_argument("List length and dimension of clifford unit mismatch"));
                } else
-                       throw(std::invalid_argument("First argument should be a vector vector"));
-       } else if (is_a<lst>(v)) {
-               if (dim == ex_to<lst>(v).nops())
-                       return indexed(matrix(dim, 1, ex_to<lst>(v)), ex_to<varidx>(mu).toggle_variance()) * c;
-               else
-                       throw(std::invalid_argument("List length and dimension of clifford unit mismatch"));
+                       throw(std::invalid_argument("Cannot construct from anything but list or vector"));
        } else
-               throw(std::invalid_argument("Cannot construct from anything but list or vector"));
+               throw(std::invalid_argument("The second argument should be a Clifford unit"));
 }
  
 /** Auxiliary structure to define a function for striping one Clifford unit
@@ -1133,7 +1145,7 @@ static ex get_clifford_comp(const ex & e, const ex & c)
 }
 
 
-lst clifford_to_lst (const ex & e, const ex & c, bool algebraic)
+lst clifford_to_lst(const ex & e, const ex & c, bool algebraic)
 {
        GINAC_ASSERT(is_a<clifford>(c));
        varidx mu = ex_to<varidx>(c.op(1));
@@ -1143,7 +1155,8 @@ lst clifford_to_lst (const ex & e, const ex & c, bool algebraic)
 
        if (algebraic) // check if algebraic method is applicable
                for (unsigned int i = 0; i < D; i++) 
-                       if (pow(c.subs(mu == i), 2) == 0)
+                       if (pow(c.subs(mu == i), 2).is_zero() 
+                               or (not is_a<numeric>(pow(c.subs(mu == i), 2))))
                                algebraic = false;
        lst V; 
        if (algebraic) 
@@ -1162,22 +1175,26 @@ lst clifford_to_lst (const ex & e, const ex & c, bool algebraic)
 
 ex clifford_moebius_map(const ex & a, const ex & b, const ex & c, const ex & d, const ex & v, const ex & G, unsigned char rl)
 {
-       ex x, D;
-       if (is_a<indexed>(G)) 
-               D = ex_to<varidx>(G.op(1)).get_dim();
-       else if (is_a<matrix>(G)) 
-               D = ex_to<matrix>(G).rows();
-       else
-               throw(std::invalid_argument("metric should be an indexed object or matrix"));
+       ex x, D, cu;
        
-       varidx mu((new symbol)->setflag(status_flags::dynallocated), D);
-                  
        if (! is_a<matrix>(v) && ! is_a<lst>(v))
                throw(std::invalid_argument("parameter v should be either vector or list"));
+       
+       if (is_a<clifford>(G)) {
+               cu = G;
+       } else {
+               if (is_a<indexed>(G)) 
+                       D = ex_to<varidx>(G.op(1)).get_dim();
+               else if (is_a<matrix>(G)) 
+                       D = ex_to<matrix>(G).rows(); 
+               else throw(std::invalid_argument("metric should be an indexed object, matrix, or a Clifford unit"));
+               
+               varidx mu((new symbol)->setflag(status_flags::dynallocated), D);
+               cu = clifford_unit(mu, G, rl);
+       }
 
-       x = lst_to_clifford(v, mu, G, rl);
+       x = lst_to_clifford(v, cu); 
        ex e = simplify_indexed(canonicalize_clifford((a * x + b) * clifford_inverse(c * x + d)));
-       ex cu = clifford_unit(mu, G);
        return clifford_to_lst(e, cu, false);
 }
 
index 0f0ebfa..921f501 100644 (file)
@@ -191,7 +191,7 @@ ex dirac_ONE(unsigned char rl = 0);
 /** Create a Clifford unit object.
  *
  *  @param mu Index (must be of class varidx or a derived class)
- *  @param metr Metric (should be of class tensmetric or a derived class, or a symmetric matrix)
+ *  @param metr Metric (should be of class tensmetric or a derived class, or a matrix)
  *  @param rl Representation label
  *  @return newly constructed Clifford unit object */
 ex clifford_unit(const ex & mu, const ex & metr, unsigned char rl = 0);
@@ -275,8 +275,13 @@ inline ex clifford_bar(const ex & e) { return clifford_prime(e.conjugate()); }
 /** Reversion of the Clifford algebra, coincides with the conjugate(). */
 inline ex clifford_star(const ex & e) { return e.conjugate(); }
 
-/** Replaces all dirac_ONE's in e with 1 (effectively removing them). */
-ex remove_dirac_ONE(const ex & e);
+/** 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 
+ *  clifford_unit with representation_label to be removed.
+ *  
+ *  @param e Expression to be processed
+ *  @param rl Value of representation label */
+ex remove_dirac_ONE(const ex & e, unsigned char rl = 0);
 
 /** Calculation of the norm in the Clifford algebra. */
 ex clifford_norm(const ex & e);
@@ -288,10 +293,12 @@ ex clifford_inverse(const ex & e);
  *
  *  @param v List or vector of coordinates
  *  @param mu Index (must be of class varidx or a derived class)
- *  @param metr Metric (should be of class tensmetric or a derived class, or a symmetric matrix)
+ *  @param metr Metric (should be of class tensmetric or a derived class, or a matrix)
  *  @param rl Representation label
+ *  @param e Clifford unit object
  *  @return Clifford vector with given components */
 ex lst_to_clifford(const ex & v, const ex & mu,  const ex & metr, unsigned char rl = 0);
+ex lst_to_clifford(const ex & v, const ex & e);
 
 /** An inverse function to lst_to_clifford(). For given Clifford vector extracts
  *  its components with respect to given Clifford unit. Obtained components may 
@@ -301,7 +308,8 @@ ex lst_to_clifford(const ex & v, const ex & mu,  const ex & metr, unsigned char
  *  
  *  @param e Clifford expression to be decomposed into components
  *  @param c Clifford unit defining the metric for splitting (should have numeric dimension of indices)
- *  @param algebraic Use algebraic or symbolic algorithm for extractions */
+ *  @param algebraic Use algebraic or symbolic algorithm for extractions 
+ *  @return List of components of a Clifford vector*/
 lst clifford_to_lst(const ex & e, const ex & c, bool algebraic=true);
 
 /** Calculations of Moebius transformations (conformal map) defined by a 2x2 Clifford matrix
@@ -315,8 +323,9 @@ lst clifford_to_lst(const ex & e, const ex & c, bool algebraic=true);
  *  @param c (2,1) entry of the defining matrix
  *  @param d (2,2) entry of the defining matrix
  *  @param v Vector to be transformed
- *  @param G Metric of the surrounding space
- *  @param rl Representation label */
+ *  @param G Metric of the surrounding space, may be a Clifford unit then the next parameter is ignored
+ *  @param rl Representation label 
+ *  @return List of components of the transformed vector*/
 ex clifford_moebius_map(const ex & a, const ex & b, const ex & c, const ex & d, const ex & v, const ex & G, unsigned char rl = 0);
 
 /** The second form of Moebius transformations defined by a 2x2 Clifford matrix M
@@ -324,8 +333,9 @@ ex clifford_moebius_map(const ex & a, const ex & b, const ex & c, const ex & d,
  * 
  *  @param M the defining matrix
  *  @param v Vector to be transformed
- *  @param G Metric of the surrounding space
- *  @param rl Representation label */
+ *  @param G Metric of the surrounding space, may be a Clifford unit then the next parameter is ignored
+ *  @param rl Representation label 
+ *  @return List of components of the transformed vector*/
 ex clifford_moebius_map(const ex & M, const ex & v, const ex & G, unsigned char rl = 0);
 
 } // namespace GiNaC