From: Jens Vollinga Date: Fri, 1 Apr 2005 18:23:40 +0000 (+0000) Subject: * Applied Vladimir Kisil's patches (bug in clifford_prime and clifford_to_lst, X-Git-Tag: release_1-4-0~188 X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=commitdiff_plain;h=d1685a40ef5de308936ed0faf8c10c66960a60cc * Applied Vladimir Kisil's patches (bug in clifford_prime and clifford_to_lst, 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. --- diff --git a/check/exam_clifford.cpp b/check/exam_clifford.cpp index 0df5ebb7..ec7946cd 100644 --- a/check/exam_clifford.cpp +++ b/check/exam_clifford.cpp @@ -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; } diff --git a/doc/tutorial/ginac.texi b/doc/tutorial/ginac.texi index e0ae80b1..86ca84a5 100644 --- a/doc/tutorial/ginac.texi +++ b/doc/tutorial/ginac.texi @@ -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 & rls, const ex & trONE = 4); +ex dirac_trace(const ex & e, const std::set & 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(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: diff --git a/ginac/clifford.cpp b/ginac/clifford.cpp index d629d5b4..8854d616 100644 --- a/ginac/clifford.cpp +++ b/ginac/clifford.cpp @@ -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(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(e) // || is_a(e) || is_a(e) - || is_a(e)) { - return e.map(fcn); + if (is_a(e_) // || is_a(e) || is_a(e) + || is_a(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(e) && is_a(e.op(0))) { return -e; - } else if (is_a(e) || is_a(e) // || is_a(e) || is_a(e) - || is_a(e) || is_a(e)) { + } else if (is_a(e) || is_a(e) || is_a(e) //|| is_a(e) || is_a(e) + || is_a(e) || is_a(e)) { return e.map(fcn); } else if (is_a(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(e) && is_a(e.op(0))) { - return 1; + pointer_to_map_function_1arg fcn(remove_dirac_ONE, rl); + if (is_a(e) && ex_to(e).get_representation_label() >= rl) { + if (is_a(e.op(0))) + return 1; + else + throw(std::invalid_argument("Expression is a non-scalar Clifford number!")); } else if (is_a(e) || is_a(e) || is_a(e) // || is_a(e) || is_a(e) - || is_a(e) || is_a(e)) { + || is_a(e) || is_a(e)) { return e.map(fcn); } else if (is_a(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(mu).is_dim_numeric()) throw(std::invalid_argument("Index should have a numeric dimension")); - unsigned dim = (ex_to(ex_to(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(v)) { - if (ex_to(v).cols() > ex_to(v).rows()) { - min = ex_to(v).rows(); - max = ex_to(v).cols(); - } else { - min = ex_to(v).cols(); - max = ex_to(v).rows(); - } - if (min == 1) { - if (dim == max) - if (is_a(mu)) // need to swap variance - return indexed(v, ex_to(mu).toggle_variance()) * c; +ex lst_to_clifford(const ex & v, const ex & e) { + unsigned min, max; + + if (is_a(e)) { + varidx mu = ex_to(e.op(1)); + unsigned dim = (ex_to(mu.get_dim())).to_int(); + + if (is_a(v)) { + if (ex_to(v).cols() > ex_to(v).rows()) { + min = ex_to(v).rows(); + max = ex_to(v).cols(); + } else { + min = ex_to(v).cols(); + max = ex_to(v).rows(); + } + if (min == 1) { + if (dim == max) + return indexed(v, ex_to(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(v)) { + if (dim == ex_to(v).nops()) + return indexed(matrix(dim, 1, ex_to(v)), ex_to(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(v)) { - if (dim == ex_to(v).nops()) - return indexed(matrix(dim, 1, ex_to(v)), ex_to(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(c)); varidx mu = ex_to(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(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(G)) - D = ex_to(G.op(1)).get_dim(); - else if (is_a(G)) - D = ex_to(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(v) && ! is_a(v)) throw(std::invalid_argument("parameter v should be either vector or list")); + + if (is_a(G)) { + cu = G; + } else { + if (is_a(G)) + D = ex_to(G.op(1)).get_dim(); + else if (is_a(G)) + D = ex_to(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); } diff --git a/ginac/clifford.h b/ginac/clifford.h index 0f0ebfa4..921f5017 100644 --- a/ginac/clifford.h +++ b/ginac/clifford.h @@ -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