GiNaC-devel
Threads by month
- ----- 2026 -----
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2000 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 1999 -----
- December
- November
- October
- September
- 1311 discussions
Dear All,
I recently noticed that GiNaC incorrectly expands products with
dummy index summations, which is illustrated by the following program:
#include <iostream>
#include <ginac/ginac.h>
using namespace std;
using namespace GiNaC;
#include <stdexcept>
int main(){
realsymbol a("a"), b("b"), c("c"), d("d");
varidx mu(symbol("mu", "\\mu"), 2);
try {
ex e;
e = (indexed(a, mu)*indexed(b, mu.toggle_variance())+1)*indexed(c, mu)*indexed(d, mu.toggle_variance());
cout << e.expand() << endl;
// -> d.mu*c~mu*b.mu*a~mu+d.mu*c~mu
e = pow(indexed(a, mu)*indexed(b, mu.toggle_variance())+1, 2);
cout << e.expand() << endl;
// -> 1+2*b.mu*a~mu+(b.mu)^2*(a~mu)^2
} catch (exception &p) {
cerr << "Got problem: " << p.what() << endl;
}
}
I made a patch to mul.cpp, ncmul.cpp, power.cpp which _partially_ fix
this problem. The bigger test looks now like that:
#include <iostream>
#include <ginac/ginac.h>
using namespace std;
using namespace GiNaC;
#include <stdexcept>
int main(){
realsymbol a("a"), b("b"), c("c"), d("d");
varidx mu(symbol("mu", "\\mu"), 2), nu(symbol("nu", "\\nu"), 2);
try {
ex e;
e = (indexed(a, mu)*indexed(b, mu.toggle_variance())+1)*indexed(c, mu)*indexed(d, mu.toggle_variance());
cout << e.expand() << endl << endl;
// -> d.mu*c~mu*b.symbol6*a~symbol6+d.mu*c~mu
e = indexed(c, mu)*indexed(d, mu.toggle_variance())*(indexed(a, mu)*indexed(b, mu.toggle_variance())+1);
cout << e.expand() << endl << endl;
// -> d.mu*c~mu+d.mu*a~symbol7*b.symbol7*c~mu
e = (1+indexed(c, mu)*indexed(d, mu.toggle_variance()))*(indexed(a, mu)*indexed(b, mu.toggle_variance())+1);
cout << e.expand() << endl << endl;
// -> 1+b.mu*a~mu+b.mu*c~symbol8*a~mu*d.symbol8+d.mu*c~mu
e = pow(2*indexed(a, mu)*indexed(b, mu.toggle_variance())+1, 2);
cout << e.expand() << endl << endl;
// -> 1+4*b.mu*a~mu*b.symbol9*a~symbol9+4*b.mu*a~mu
e = pow(2*indexed(a, mu)*indexed(b, mu.toggle_variance())+1, 3);
cout << e.expand() << endl << endl;
// -> 1+6*b.mu*a~mu+12*b.mu*a~mu*a~symbol10*b.symbol10+8*b.symbol12*a~symbol12*b.mu*a~symbol11*b.symbol11*a~mu
e = (indexed(a, mu, nu)*dirac_gamma(mu.toggle_variance()) * dirac_gamma(nu.toggle_variance()) + dirac_ONE())
* indexed(b, mu, nu)*dirac_gamma(mu.toggle_variance()) * dirac_gamma(nu.toggle_variance());
cout << e.expand() << endl << endl;
// -> (gamma.mu*gamma.nu*gamma.mu*gamma.nu)*a~mu~nu*b~mu~nu+(gamma.mu*gamma.nu)*b~mu~nu
e = (indexed(a, mu, nu)*dirac_gamma(mu.toggle_variance()) * dirac_gamma(nu.toggle_variance()) + dirac_ONE())
*( indexed(b, mu, nu)*dirac_gamma(mu.toggle_variance()) * dirac_gamma(nu.toggle_variance()) + dirac_ONE());
cout << e.expand() << endl << endl;
// -> b~symbol16~symbol17*a~mu~nu*(gamma.mu*gamma.nu*gamma.symbol16*gamma.symbol17)+ONE+(gamma.mu*gamma.nu)*a~mu~nu+(gamma.mu*gamma.nu)*b~mu~nu
e = (indexed(a, mu, nu)*dirac_gamma(mu.toggle_variance()) * dirac_gamma(nu.toggle_variance()) + dirac_ONE())
* indexed(b, mu.toggle_variance(), nu.toggle_variance())*dirac_gamma(mu) * dirac_gamma(nu);
cout << e.expand() << endl << endl;
// -> (gamma.mu*gamma.nu*gamma~mu*gamma~nu)*a~mu~nu*b.mu.nu+(gamma~mu*gamma~nu)*b.mu.nu
e = pow(indexed(a, mu, nu)*dirac_gamma(mu.toggle_variance()) * dirac_gamma(nu.toggle_variance()), 2);
cout << e.expand() << endl << endl;
// -> (gamma.mu*gamma.nu*gamma.symbol18*gamma.symbol19)*a~mu~nu*a~symbol18~symbol19
e = pow(2*indexed(a, mu, nu)*dirac_gamma(mu.toggle_variance()) * dirac_gamma(nu.toggle_variance())+dirac_ONE(), 2);
cout << e.expand() << endl << endl;
// -> 4*(gamma.mu*gamma.nu*gamma.symbol18*gamma.symbol19)*a~mu~nu*a~symbol18~symbol19+ONE+4*(gamma.mu*gamma.nu)*a~mu~nu
e = pow(2*indexed(a, mu, nu)*dirac_gamma(mu.toggle_variance()) * dirac_gamma(nu.toggle_variance())+dirac_ONE(), 3);
cout << e.expand() << endl << endl;
// -> ONE+8*a~symbol26~symbol27*a~mu~nu*a~symbol28~symbol29*(gamma.mu*gamma.nu*gamma.symbol26*gamma.symbol27*gamma.symbol28*gamma.symbol29)+6*(gamma.mu*gamma.nu)*a~mu~nu+4*(gamma.mu*gamma.nu*gamma.symbol24*gamma.symbol25)*a~mu~nu*a~symbol24~symbol25+4*a~symbol22~symbol23*a~mu~nu*(gamma.mu*gamma.nu*gamma.symbol22*gamma.symbol23)+4*a~symbol20~symbol21*a~mu~nu*(gamma.mu*gamma.nu*gamma.symbol20*gamma.symbol21)
} catch (exception &p) {
cerr << "Got problem: " << p.what() << endl;
}
}
So the problem remains in the cases when one dummy index belongs to
non-commutative part of product and other---to a commutative part. I do
not know how to fix this situation in a simple way.
I sent my patch as an attachment to a separate letter to this list
(which will be likely hold till moderator's approval). It includes as
well a slightly redesigned version of my previous patch for indexed.cpp
and clifford.cpp (from the Thu Apr 28 18:17:55 CEST 2005).
Best regards,
Vladimir
--
Vladimir V. Kisil email: kisilv(a)maths.leeds.ac.uk
-- www: http://maths.leeds.ac.uk/~kisilv/
1
0
Hi,
GiNaC 1.3.1 is out and available. The changes are:
- integral() and eval_integ() can be used from ginsh.
- Integrals can be series-expanded.
- Fixed a library initialization problem.
- GiNaC compiles from tarball even if lex/flex is missing.
- Fixed bugs in canonicalize_clifford(), clifford_prime() and
clifford_to_lst().
- clifford_moebius_map(), remove_dirac_ONE() and LaTeX output of
Clifford objects now care about representation labels.
- Fixed bug in gcd.
- Better output for slashed expressions.
As always, this release can be downloaded from
ftp://ftpthep.physik.uni-mainz.de/pub/GiNaC/
Enjoy,
Jens
1
0
This is the end of previous patch.
--
Vladimir V. Kisil email: kisilv(a)maths.leeds.ac.uk
-- www: http://maths.leeds.ac.uk/~kisilv/
Index: check/exam_clifford.cpp
===================================================================
RCS file: /home/cvs/GiNaC/check/exam_clifford.cpp,v
retrieving revision 1.24
diff -r1.24 exam_clifford.cpp
24a25,26
> const numeric half(1, 2);
>
27c29
< ex e = e1 - e2;
---
> ex e = normal(e1 - e2);
29,30c31,32
< clog << e1 << "-" << e2 << " erroneously returned "
< << e << " instead of 0" << endl;
---
> clog << "(" << e1 << ") - (" << e2 << ") erroneously returned "
> << e << " instead of 0" << endl;
38c40
< ex e = simplify_indexed(e1) - e2;
---
> ex e = normal(simplify_indexed(e1) - e2);
40,41c42,43
< clog << "simplify_indexed(" << e1 << ")-" << e2 << " erroneously returned "
< << e << " instead of 0" << endl;
---
> clog << "simplify_indexed(" << e1 << ") - (" << e2 << ") erroneously returned "
> << e << " instead of 0" << endl;
46a49,88
> static unsigned check_equal_lst(const ex &e1, const ex &e2)
> {
> for(int i = 0; i++; i < e1.nops()) {
> ex e = e1.op(i) - e2.op(i);
> if (!e.is_zero()) {
> clog << "(" << e1 << ") - (" << e2 << ") erroneously returned "
> << e << " instead of 0 (in the entry " << i << ")" << endl;
> return 1;
> }
> }
> return 0;
> }
>
> static unsigned check_equal_simplify_term(const ex &e1, const ex &e2, varidx &mu)
> {
> ex e = expand_dummy_sum(normal(simplify_indexed(e1) - e2), true);
>
> for (int j=0; j<4; j++) {
> ex esub = e.subs(lst(mu == idx(j, mu.get_dim()), mu.toggle_variance() == idx(j, mu.get_dim())));
> if (!(canonicalize_clifford(esub).is_zero())) {
> clog << "simplify_indexed(" << e1 << ") - (" << e2 << ") erroneously returned "
> << canonicalize_clifford(esub) << " instead of 0 for mu=" << j << endl;
> return 1;
> }
> }
> return 0;
> }
>
> static unsigned check_equal_simplify_term2(const ex &e1, const ex &e2)
> {
> ex e = expand_dummy_sum(normal(simplify_indexed(e1) - e2), true);
> if (!(canonicalize_clifford(e).is_zero())) {
> clog << "simplify_indexed(" << e1 << ") - (" << e2 << ") erroneously returned "
> << canonicalize_clifford(e) << " instead of 0" << endl;
> return 1;
> }
> return 0;
> }
>
>
264a307
>
271c314,316
< ex G = A;
---
> matrix A_symm(4,4), A2(4, 4);
> A_symm = A.add(A.transpose()).mul(half);
> A2 = A_symm.mul(A_symm);
273,274d317
< matrix A2(4, 4);
< A2 = A.mul(A);
276c319
<
---
> bool anticommuting = ex_to<clifford>(clifford_unit(nu, A)).is_anticommuting();
280,281c323,324
< e = dirac_ONE() * clifford_unit(mu, G) * dirac_ONE();
< result += check_equal(e, clifford_unit(mu, G));
---
> e = dirac_ONE(2) * clifford_unit(mu, A, 2) * dirac_ONE(2);
> result += check_equal(e, clifford_unit(mu, A, 2));
283,284c326,327
< e = clifford_unit(varidx(2, 4), G) * clifford_unit(varidx(1, 4), G)
< * clifford_unit(varidx(1, 4), G) * clifford_unit(varidx(2, 4), G);
---
> e = clifford_unit(idx(2, 4), A) * clifford_unit(idx(1, 4), A)
> * clifford_unit(idx(1, 4), A) * clifford_unit(idx(2, 4), A);
287c330,334
< e = clifford_unit(nu, G) * clifford_unit(nu.toggle_variance(), G);
---
> e = clifford_unit(varidx(2, 4), A) * clifford_unit(varidx(1, 4), A)
> * clifford_unit(varidx(1, 4), A) * clifford_unit(varidx(2, 4), A);
> result += check_equal(e, A(1, 1) * A(2, 2) * dirac_ONE());
>
> e = clifford_unit(nu, A) * clifford_unit(nu.toggle_variance(), A);
290,291c337,338
< e = clifford_unit(nu, G) * clifford_unit(nu, G);
< result += check_equal_simplify(e, indexed(G, sy_symm(), nu, nu) * dirac_ONE());
---
> e = clifford_unit(nu, A) * clifford_unit(nu, A);
> result += check_equal_simplify(e, indexed(A_symm, sy_symm(), nu, nu) * dirac_ONE());
293,294c340,341
< e = clifford_unit(nu, G) * clifford_unit(nu.toggle_variance(), G) * clifford_unit(mu, G);
< result += check_equal_simplify(e, A.trace() * clifford_unit(mu, G));
---
> e = clifford_unit(nu, A) * clifford_unit(nu.toggle_variance(), A) * clifford_unit(mu, A);
> result += check_equal_simplify(e, A.trace() * clifford_unit(mu, A));
296,297c343,347
< e = clifford_unit(nu, G) * clifford_unit(mu, G) * clifford_unit(nu.toggle_variance(), G);
< result += check_equal_simplify(e, 2*indexed(G, sy_symm(), mu, mu)*clifford_unit(mu, G) - A.trace()*clifford_unit(mu, G));
---
> e = clifford_unit(nu, A) * clifford_unit(mu, A) * clifford_unit(nu.toggle_variance(), A);
> if (anticommuting)
> result += check_equal_simplify(e, 2*indexed(A_symm, sy_symm(), mu, mu)*clifford_unit(mu, A) - A.trace()*clifford_unit(mu, A));
>
> result += check_equal_simplify_term(e, 2 * indexed(A_symm, sy_symm(), nu.toggle_variance(), mu) *clifford_unit(nu, A)-A.trace()*clifford_unit(mu, A), mu);
299,300c349,350
< e = clifford_unit(nu, G) * clifford_unit(nu.toggle_variance(), G)
< * clifford_unit(mu, G) * clifford_unit(mu.toggle_variance(), G);
---
> e = clifford_unit(nu, A) * clifford_unit(nu.toggle_variance(), A)
> * clifford_unit(mu, A) * clifford_unit(mu.toggle_variance(), A);
303,304c353,354
< e = clifford_unit(mu, G) * clifford_unit(nu, G)
< * clifford_unit(nu.toggle_variance(), G) * clifford_unit(mu.toggle_variance(), G);
---
> e = clifford_unit(mu, A) * clifford_unit(nu, A)
> * clifford_unit(nu.toggle_variance(), A) * clifford_unit(mu.toggle_variance(), A);
307,323c357,370
< e = clifford_unit(mu, G) * clifford_unit(nu, G)
< * clifford_unit(mu.toggle_variance(), G) * clifford_unit(nu.toggle_variance(), G);
< result += check_equal_simplify(e, 2*A2.trace()*dirac_ONE() - pow(A.trace(), 2)*dirac_ONE());
<
< e = clifford_unit(mu.toggle_variance(), G) * clifford_unit(nu, G)
< * clifford_unit(mu, G) * clifford_unit(nu.toggle_variance(), G);
< result += check_equal_simplify(e, 2*A2.trace()*dirac_ONE() - pow(A.trace(), 2)*dirac_ONE());
<
< e = clifford_unit(nu.toggle_variance(), G) * clifford_unit(rho.toggle_variance(), G)
< * clifford_unit(mu, G) * clifford_unit(rho, G) * clifford_unit(nu, G);
< e = e.simplify_indexed().collect(clifford_unit(mu, G));
< result += check_equal(e, (pow(A.trace(), 2)+4-4*A.trace()*indexed(A, mu, mu)) * clifford_unit(mu, G));
<
< e = clifford_unit(nu.toggle_variance(), G) * clifford_unit(rho, G)
< * clifford_unit(mu, G) * clifford_unit(rho.toggle_variance(), G) * clifford_unit(nu, G);
< e = e.simplify_indexed().collect(clifford_unit(mu, G));
< result += check_equal(e, (pow(A.trace(), 2)+4-4*A.trace()*indexed(A, mu, mu))* clifford_unit(mu, G));
---
> e = clifford_unit(mu, A) * clifford_unit(nu, A)
> * clifford_unit(mu.toggle_variance(), A) * clifford_unit(nu.toggle_variance(), A);
> if (anticommuting)
> result += check_equal_simplify(e, 2*A2.trace()*dirac_ONE() - pow(A.trace(), 2)*dirac_ONE());
>
> result += check_equal_simplify_term2(e, 2*indexed(A_symm, sy_symm(), nu.toggle_variance(), mu.toggle_variance()) * clifford_unit(mu, A) * clifford_unit(nu, A) - pow(A.trace(), 2)*dirac_ONE());
>
> e = clifford_unit(mu.toggle_variance(), A) * clifford_unit(nu, A)
> * clifford_unit(mu, A) * clifford_unit(nu.toggle_variance(), A);
> if (anticommuting) {
> result += check_equal_simplify(e, 2*A2.trace()*dirac_ONE() - pow(A.trace(), 2)*dirac_ONE());
> e1 = remove_dirac_ONE(simplify_indexed(e));
> result += check_equal(e1, 2*A2.trace() - pow(A.trace(), 2));
> }
325,327c372
< // canonicalize_clifford() checks
< e = clifford_unit(mu, G) * clifford_unit(nu, G) + clifford_unit(nu, G) * clifford_unit(mu, G);
< result += check_equal(canonicalize_clifford(e), 2*dirac_ONE()*indexed(G, sy_symm(), mu, nu));
---
> result += check_equal_simplify_term2(e, 2*indexed(A_symm, nu, mu) * clifford_unit(mu.toggle_variance(), A) * clifford_unit(nu.toggle_variance(), A) - pow(A.trace(), 2)*dirac_ONE());
329,338c374,406
< e = (clifford_unit(mu, G) * clifford_unit(nu, G) * clifford_unit(lam, G)
< + clifford_unit(nu, G) * clifford_unit(lam, G) * clifford_unit(mu, G)
< + clifford_unit(lam, G) * clifford_unit(mu, G) * clifford_unit(nu, G)
< - clifford_unit(nu, G) * clifford_unit(mu, G) * clifford_unit(lam, G)
< - clifford_unit(lam, G) * clifford_unit(nu, G) * clifford_unit(mu, G)
< - clifford_unit(mu, G) * clifford_unit(lam, G) * clifford_unit(nu, G)) / 6
< + indexed(G, sy_symm(), mu, nu) * clifford_unit(lam, G)
< - indexed(G, sy_symm(), mu, lam) * clifford_unit(nu, G)
< + indexed(G, sy_symm(), nu, lam) * clifford_unit(mu, G)
< - clifford_unit(mu, G) * clifford_unit(nu, G) * clifford_unit(lam, G);
---
> e = clifford_unit(nu.toggle_variance(), A) * clifford_unit(rho.toggle_variance(), A)
> * clifford_unit(mu, A) * clifford_unit(rho, A) * clifford_unit(nu, A);
> e = e.simplify_indexed().collect(clifford_unit(mu, A));
> if (anticommuting)
> result += check_equal(e, (4*indexed(A2, sy_symm(), mu, mu) - 4 * indexed(A_symm, sy_symm(), mu, mu)*A.trace() +pow(A.trace(), 2)) * clifford_unit(mu, A));
>
> result += check_equal_simplify_term(e, 4* indexed(A_symm, sy_symm(), nu.toggle_variance(), rho)*indexed(A_symm, sy_symm(), rho.toggle_variance(), mu) *clifford_unit(nu, A)
> - 2*A.trace() * (clifford_unit(rho, A) * indexed(A_symm, sy_symm(), rho.toggle_variance(), mu)
> +clifford_unit(nu, A) * indexed(A_symm, sy_symm(), nu.toggle_variance(), mu)) + pow(A.trace(),2)* clifford_unit(mu, A), mu);
>
> e = clifford_unit(nu.toggle_variance(), A) * clifford_unit(rho, A)
> * clifford_unit(mu, A) * clifford_unit(rho.toggle_variance(), A) * clifford_unit(nu, A);
> e = e.simplify_indexed().collect(clifford_unit(mu, A));
> if (anticommuting)
> result += check_equal(e, (4*indexed(A2, sy_symm(), mu, mu) - 4*indexed(A_symm, sy_symm(), mu, mu)*A.trace() +pow(A.trace(), 2))* clifford_unit(mu, A));
>
> result += check_equal_simplify_term(e, 4* indexed(A_symm, sy_symm(), nu.toggle_variance(), rho)*indexed(A_symm, sy_symm(), rho.toggle_variance(), mu) *clifford_unit(nu, A)
> - 2*A.trace() * (clifford_unit(rho, A) * indexed(A_symm, sy_symm(), rho.toggle_variance(), mu)
> +clifford_unit(nu, A) * indexed(A_symm, sy_symm(), nu.toggle_variance(), mu)) + pow(A.trace(),2)* clifford_unit(mu, A), mu);
>
> e = clifford_unit(mu, A) * clifford_unit(nu, A) + clifford_unit(nu, A) * clifford_unit(mu, A);
> result += check_equal(canonicalize_clifford(e), 2*dirac_ONE()*indexed(A_symm, sy_symm(), mu, nu));
>
> e = (clifford_unit(mu, A) * clifford_unit(nu, A) * clifford_unit(lam, A)
> + clifford_unit(nu, A) * clifford_unit(lam, A) * clifford_unit(mu, A)
> + clifford_unit(lam, A) * clifford_unit(mu, A) * clifford_unit(nu, A)
> - clifford_unit(nu, A) * clifford_unit(mu, A) * clifford_unit(lam, A)
> - clifford_unit(lam, A) * clifford_unit(nu, A) * clifford_unit(mu, A)
> - clifford_unit(mu, A) * clifford_unit(lam, A) * clifford_unit(nu, A)) / 6
> + indexed(A_symm, sy_symm(), mu, nu) * clifford_unit(lam, A)
> - indexed(A_symm, sy_symm(), mu, lam) * clifford_unit(nu, A)
> + indexed(A_symm, sy_symm(), nu, lam) * clifford_unit(mu, A)
> - clifford_unit(mu, A) * clifford_unit(nu, A) * clifford_unit(lam, A);
344,345c412,413
< 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);
---
> ex c = clifford_unit(nu, A, 1);
> e = lst_to_clifford(lst(t, x, y, z), mu, A, 1) * lst_to_clifford(lst(1, 2, 3, 4), c);
347c415,443
< result += check_equal((e*e1).simplify_indexed().normal(), dirac_ONE(1));
---
> result += check_equal_lst((e*e1).simplify_indexed(), dirac_ONE(1));
>
> // Moebius map (both forms) checks for symmetric metrics only
> matrix M1(2, 2), M2(2, 2);
> c = clifford_unit(nu, A);
>
> e = clifford_moebius_map(0, dirac_ONE(),
> dirac_ONE(), 0, lst(t, x, y, z), A); // this is just the inversion
> M1 = 0, dirac_ONE(),
> dirac_ONE(), 0;
> e1 = clifford_moebius_map(M1, lst(t, x, y, z), A); // the inversion again
> result += check_equal_lst(e, e1);
>
> e1 = clifford_to_lst(clifford_inverse(lst_to_clifford(lst(t, x, y, z), mu, A)), c);
> result += check_equal_lst(e, e1);
>
> e = clifford_moebius_map(dirac_ONE(), lst_to_clifford(lst(1, 2, 3, 4), nu, A),
> 0, dirac_ONE(), lst(t, x, y, z), A); //this is just a shift
> M2 = dirac_ONE(), lst_to_clifford(lst(1, 2, 3, 4), c),
> 0, dirac_ONE();
> e1 = clifford_moebius_map(M2, lst(t, x, y, z), c); // the same shift
> result += check_equal_lst(e, e1);
>
> result += check_equal(e, lst(t+1, x+2, y+3, z+4));
>
> // Check the group law for Moebius maps
> e = clifford_moebius_map(M1, ex_to<lst>(e1), c); //composition of M1 and M2
> e1 = clifford_moebius_map(M1.mul(M2), lst(t, x, y, z), c); // the product M1*M2
> result += check_equal_lst(e, e1);
352c448,449
< static unsigned clifford_check7()
---
>
> static unsigned clifford_check7(const ex & G, const symbol & dim)
358d454
< symbol dim("D");
362c458
< ex e;
---
> ex e, G_base;
364c460,463
< ex G = minkmetric();
---
> if (is_a<indexed>(G))
> G_base = G.op(0);
> else
> G_base = G;
389,404c488,519
< // canonicalize_clifford() checks
< e = clifford_unit(mu, G) * clifford_unit(nu, G) + clifford_unit(nu, G) * clifford_unit(mu, G);
< result += check_equal(canonicalize_clifford(e), 2*dirac_ONE()*indexed(G, sy_symm(), mu, nu));
<
< e = (clifford_unit(mu, G) * clifford_unit(nu, G) * clifford_unit(lam, G)
< + clifford_unit(nu, G) * clifford_unit(lam, G) * clifford_unit(mu, G)
< + clifford_unit(lam, G) * clifford_unit(mu, G) * clifford_unit(nu, G)
< - clifford_unit(nu, G) * clifford_unit(mu, G) * clifford_unit(lam, G)
< - clifford_unit(lam, G) * clifford_unit(nu, G) * clifford_unit(mu, G)
< - clifford_unit(mu, G) * clifford_unit(lam, G) * clifford_unit(nu, G)) / 6
< + indexed(G, sy_symm(), mu, nu) * clifford_unit(lam, G)
< - indexed(G, sy_symm(), mu, lam) * clifford_unit(nu, G)
< + indexed(G, sy_symm(), nu, lam) * clifford_unit(mu, G)
< - clifford_unit(mu, G) * clifford_unit(nu, G) * clifford_unit(lam, G);
< result += check_equal(canonicalize_clifford(e), 0);
<
---
> // canonicalize_clifford() checks, only for symmetric metrics
> if (ex_to<symmetry>(ex_to<indexed>(ex_to<clifford>(clifford_unit(mu, G)).get_metric()).get_symmetry()).has_symmetry()) {
> e = clifford_unit(mu, G) * clifford_unit(nu, G) + clifford_unit(nu, G) * clifford_unit(mu, G);
> result += check_equal(canonicalize_clifford(e), 2*dirac_ONE()*indexed(G_base, sy_symm(), nu, mu));
>
> e = (clifford_unit(mu, G) * clifford_unit(nu, G) * clifford_unit(lam, G)
> + clifford_unit(nu, G) * clifford_unit(lam, G) * clifford_unit(mu, G)
> + clifford_unit(lam, G) * clifford_unit(mu, G) * clifford_unit(nu, G)
> - clifford_unit(nu, G) * clifford_unit(mu, G) * clifford_unit(lam, G)
> - clifford_unit(lam, G) * clifford_unit(nu, G) * clifford_unit(mu, G)
> - clifford_unit(mu, G) * clifford_unit(lam, G) * clifford_unit(nu, G)) / 6
> + indexed(G_base, sy_symm(), mu, nu) * clifford_unit(lam, G)
> - indexed(G_base, sy_symm(), mu, lam) * clifford_unit(nu, G)
> + indexed(G_base, sy_symm(), nu, lam) * clifford_unit(mu, G)
> - clifford_unit(mu, G) * clifford_unit(nu, G) * clifford_unit(lam, G);
> result += check_equal(canonicalize_clifford(e), 0);
> } else {
> e = clifford_unit(mu, G) * clifford_unit(nu, G) + clifford_unit(nu, G) * clifford_unit(mu, G);
> result += check_equal(canonicalize_clifford(e), dirac_ONE()*(indexed(G_base, mu, nu) + indexed(G_base, nu, mu)));
>
> e = (clifford_unit(mu, G) * clifford_unit(nu, G) * clifford_unit(lam, G)
> + clifford_unit(nu, G) * clifford_unit(lam, G) * clifford_unit(mu, G)
> + clifford_unit(lam, G) * clifford_unit(mu, G) * clifford_unit(nu, G)
> - clifford_unit(nu, G) * clifford_unit(mu, G) * clifford_unit(lam, G)
> - clifford_unit(lam, G) * clifford_unit(nu, G) * clifford_unit(mu, G)
> - clifford_unit(mu, G) * clifford_unit(lam, G) * clifford_unit(nu, G)) / 6
> + half * (indexed(G_base, mu, nu) + indexed(G_base, nu, mu)) * clifford_unit(lam, G)
> - half * (indexed(G_base, mu, lam) + indexed(G_base, lam, mu)) * clifford_unit(nu, G)
> + half * (indexed(G_base, nu, lam) + indexed(G_base, lam, nu)) * clifford_unit(mu, G)
> - clifford_unit(mu, G) * clifford_unit(nu, G) * clifford_unit(lam, G);
> result += check_equal(canonicalize_clifford(e), 0);
> }
420a536,545
> // anticommuting, symmetric examples
> result += clifford_check6(ex_to<matrix>(diag_matrix(lst(-1, 1, 1, 1)))); cout << '.' << flush;
> result += clifford_check6(ex_to<matrix>(diag_matrix(lst(-1, -1, -1, -1)))); cout << '.' << flush;
> result += clifford_check6(ex_to<matrix>(diag_matrix(lst(-1, 1, 1, -1)))); cout << '.' << flush;
> result += clifford_check6(ex_to<matrix>(diag_matrix(lst(-1, 0, 1, -1)))); cout << '.' << flush;
> result += clifford_check6(ex_to<matrix>(diag_matrix(lst(-3, 0, 2, -1)))); cout << '.' << flush;
>
> realsymbol s("s"), t("t"); // symbolic entries in matric
> result += clifford_check6(ex_to<matrix>(diag_matrix(lst(-1, 1, s, t)))); cout << '.' << flush;
>
422,425c547,550
< A = -1, 0, 0, 0,
< 0, 1, 0, 0,
< 0, 0, 1, 0,
< 0, 0, 0, 1;
---
> A = 1, 0, 0, 0, // anticommuting, not symmetric, Tr=0
> 0, -1, 0, 0,
> 0, 0, 0, -1,
> 0, 0, 1, 0;
428,431c553,556
< A = -1, 0, 0, 0,
< 0,-1, 0, 0,
< 0, 0,-1, 0,
< 0, 0, 0,-1;
---
> A = 1, 0, 0, 0, // anticommuting, not symmetric, Tr=2
> 0, 1, 0, 0,
> 0, 0, 0, -1,
> 0, 0, 1, 0;
433,437c558,562
<
< A = -1, 0, 0, 0,
< 0, 1, 0, 0,
< 0, 0, 1, 0,
< 0, 0, 0,-1;
---
>
> A = 1, 0, 0, 0, // not anticommuting, symmetric, Tr=0
> 0, -1, 0, 0,
> 0, 0, 0, -1,
> 0, 0, -1, 0;
440,443c565,568
< A = -1, 0, 0, 0,
< 0, 0, 0, 0,
< 0, 0, 1, 0,
< 0, 0, 0,-1;
---
> A = 1, 0, 0, 0, // not anticommuting, symmetric, Tr=2
> 0, 1, 0, 0,
> 0, 0, 0, -1,
> 0, 0, -1, 0;
446c571,581
< result += clifford_check7(); cout << '.' << flush;
---
> A = 1, 1, 0, 0, // not anticommuting, not symmetric, Tr=4
> 0, 1, 1, 0,
> 0, 0, 1, 1,
> 0, 0, 0, 1;
> result += clifford_check6(A); cout << '.' << flush;
>
> symbol dim("D");
> result += clifford_check7(minkmetric(), dim); cout << '.' << flush;
>
> varidx chi(symbol("chi"), dim), xi(symbol("xi"), dim);
> result += clifford_check7(lorentz_g(xi, chi), dim); cout << '.' << flush;
1
0
Dear All,
Here is a new patch for the clifford.cpp, which is even too
large to fin in one message. Thus the tail is sent separately.
It relays on two other additions:
1. A patch to add.cpp, which I posted here on Wed Apr 20 12:07:29 CEST
2005. It seems that a more fundamental solutions is required here, so
my code is only a temporary one.
2. An additional function expand_dummy_sum() in indexed.cpp. It shares
a portion of common code with simplify_indexed() and I put this piece
into a separate auxiliary procedure product_to_exvector().
The main changes to clifford.cpp itself are as follows:
1. There are now two different simplifications paths in
clifford::contract_with() depending on if Clifford units are
anticommuting or not. This information is now stored in a new member
variable
bool anticommuting;
The difference in results of contractions can be seen from
exam_clifford.cpp.
2. The present code should work now with non-symmetric metric as
well. At present it always result in a symmetrised metric
M(i,j)+M(j,i), but this should change when more functions from
geometric algebras will be added.
3. Exams in exam_clifford.cpp cover now all defined functions in the
majority of possible parameter variations.
4. Many small corrections.
5. Those changes are reflected in ginac.texi
Best wishes,
Vladimir
--
Vladimir V. Kisil email: kisilv(a)maths.leeds.ac.uk
-- www: http://maths.leeds.ac.uk/~kisilv/
Index: doc/tutorial/ginac.texi
===================================================================
RCS file: /home/cvs/GiNaC/doc/tutorial/ginac.texi,v
retrieving revision 1.165
diff -r1.165 ginac.texi
2569a2570,2610
> @cindex @code{expand_dummy_sum()}
> A dummy index summation like
> @tex
> $ a_i b^i$
> @end tex
> @ifnottex
> a.i b~i
> @end ifnottex
> can be expanded for indexes with numeric
> dimensions (e.g. 3) into the explicit sum like
> @tex
> $a_1b^1+a_2b^2+a_3b^3 $.
> @end tex
> @ifnottex
> a.1 b~1 + a.2 b~2 + a.3 b~3.
> @end ifnottex
> This performed by the function
>
> @example
> ex expand_dummy_sum(const ex & e, bool subs_idx = false);
> @end example
>
> which takes an expression @code{e} and returns the expanded sum for all
> dummy indexes with numeric dimensions. If the parameter @code{subs_idx}
> is set to @code{true} then all substitutions are made by @code{idx} class
> indexes, i.e. without variance. In this case the above sum
> @tex
> $ a_i b^i$
> @end tex
> @ifnottex
> a.i b~i
> @end ifnottex
> will be expanded to
> @tex
> $a_1b_1+a_2b_2+a_3b_3 $.
> @end tex
> @ifnottex
> a.1 b.1 + a.2 b.2 + a.3 b.3.
> @end ifnottex
>
>
3192c3233
< $e_i e_j + e_j e_i = M(i, j) $
---
> $e_i e_j + e_j e_i = M(i, j) + M(j, i) $
3195c3236
< e~i e~j + e~j e~i = M(i, j)
---
> e~i e~j + e~j e~i = M(i, j) + M(j, i)
3197,3199c3238,3241
< 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
---
> for some bilinear form (@code{metric})
> @math{M(i, j)}, which may be non-symmetric (see arXiv:math.QA/9911180)
> and contain symbolic entries. Such generators are created by the
> function
3202c3244,3245
< ex clifford_unit(const ex & mu, const ex & metr, unsigned char rl = 0);
---
> ex clifford_unit(const ex & mu, const ex & metr, unsigned char rl = 0,
> bool anticommuting = false);
3206c3249,3251
< generators, @code{metr} defines the metric @math{M(i, j)} and can be
---
> generators, an index @code{mu} with a numeric value may be of type
> @code{idx} as well.
> Parameter @code{metr} defines the metric @math{M(i, j)} and can be
3208,3212c3253,3277
< object, optional parameter @code{rl} allows to distinguish different
< Clifford algebras (which will commute with each other). Note that the call
< @code{clifford_unit(mu, minkmetric())} creates something very close to
< @code{dirac_gamma(mu)}. The method @code{clifford::get_metric()} returns a
< metric defining this Clifford number.
---
> object. Optional parameter @code{rl} allows to distinguish different
> Clifford algebras, which will commute with each other. The last
> optional parameter @code{anticommuting} defines if the anticommuting
> assumption (i.e.
> @tex
> $e_i e_j + e_j e_i = 0$)
> @end tex
> @ifnottex
> e~i e~j + e~j e~i = 0)
> @end ifnottex
> will be used for contraction of Clifford units. If the @code{metric} is
> supplied by a @code{matrix} object, then the value of
> @code{anticommuting} is calculated automatically and the supplied one
> will be ignored. One can overcome this by giving @code{metric} through
> matrix wrapped into an @code{indexed} object.
>
> Note that the call @code{clifford_unit(mu, minkmetric())} creates
> something very close to @code{dirac_gamma(mu)}, although
> @code{dirac_gamma} have more efficient simplification mechanism.
> @cindex @code{clifford::get_metric()}
> The method @code{clifford::get_metric()} returns a metric defining this
> Clifford number.
> @cindex @code{clifford::is_anticommuting()}
> The method @code{clifford::is_anticommuting()} returns the
> @code{anticommuting} property of a unit.
3221c3286,3288
< since this may yield some further automatic simplifications.
---
> since this may yield some further automatic simplifications. Again, for a
> metric defined through a @code{matrix} such a symmetry is detected
> automatically.
3246c3313,3314
< @code{pow(e0, 2) = 1}, @code{pow(e1, 2) = -1}, @code{pow(e2, 2) = 0} and @code{pow(e3, 2) = s}.
---
> @code{pow(e0, 2) = 1}, @code{pow(e1, 2) = -1}, @code{pow(e2, 2) = 0} and
> @code{pow(e3, 2) = s}.
3254c3322
< unsigned char rl = 0);
---
> unsigned char rl = 0, bool anticommuting = false);
3276c3344
< @code{clifford_unit(mu, metr, rl)}. The previous code may be rewritten
---
> @code{clifford_unit(mu, metr, rl, anticommuting)}. The previous code may be rewritten
3324c3392
< is zero or is not a @code{numeric} for some @samp{k}
---
> is zero or is not @code{numeric} for some @samp{k}
3413c3481
< The last provided function is
---
> The next provided function is
3419c3487
< unsigned char rl = 0);
---
> unsigned char rl = 0, bool anticommuting = false);
3421c3489
< unsigned char rl = 0);
---
> unsigned char rl = 0, bool anticommuting = false);
3427,3436c3495,3518
< 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
---
> the metric of the surrounding (pseudo-)Euclidean space. This can be an
> indexed object, tensormetric, matrix or a Clifford unit, in the later
> case the optional parameters @code{rl} and @code{anticommuting} are ignored
> even if supplied. The returned value of this function is a list of
> components of the resulting vector.
>
> @cindex @code{clifford_max_label()}
> Finally the function
>
> @example
> char clifford_max_label(const ex & e, bool ignore_ONE = false);
> @end example
>
> can detect a presence of Clifford objects in the expression @code{e}: if
> such objects are found it returns the maximal
> @code{representation_label} of them, otherwise @code{-1}. The optional
> parameter @code{ignore_ONE} indicates if @code{dirac_ONE} objects should
> be ignored during the search.
>
> 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
Index: ginac/add.cpp
===================================================================
RCS file: /home/cvs/GiNaC/ginac/add.cpp,v
retrieving revision 1.76
diff -r1.76 add.cpp
31a32,33
> #include "clifford.h"
> #include "ncmul.h"
293a296,298
> std::auto_ptr<epvector> coeffseq_cliff(new epvector);
> char rl = clifford_max_label(s);
> bool do_clifford = (rl != -1), nonscalar = false;
299c304,311
< if (!restcoeff.is_zero())
---
> if (!restcoeff.is_zero()) {
> if (do_clifford)
> if (clifford_max_label(restcoeff) == -1)
> coeffseq_cliff->push_back(combine_ex_with_coeff_to_pair(ncmul(restcoeff, dirac_ONE(rl)), i->coeff));
> else {
> coeffseq_cliff->push_back(combine_ex_with_coeff_to_pair(restcoeff, i->coeff));
> nonscalar = true;
> }
300a313
> }
304c317,318
< return (new add(coeffseq, n==0 ? overall_coeff : _ex0))->setflag(status_flags::dynallocated);
---
> return (new add(nonscalar? coeffseq_cliff : coeffseq,
> n==0 ? overall_coeff : _ex0))->setflag(status_flags::dynallocated);
Index: ginac/indexed.h
===================================================================
RCS file: /home/cvs/GiNaC/ginac/indexed.h,v
retrieving revision 1.50
diff -r1.50 indexed.h
252a253,263
> /** This function returns the given expression with expanded sums
> * for all dummy indexes summation, where dimensionality of
> * the dummy index is numeric.
> * Optionally all indexes with a variance will be substituted by
> * indices with the corresponding numeric values without variance.
> *
> * @param e the given expression
> * @param subs_idx indicates if variance of dummy indixes should be neglected
> */
> ex expand_dummy_sum(const ex & e, bool subs_idx = false);
>
Index: ginac/indexed.cpp
===================================================================
RCS file: /home/cvs/GiNaC/ginac/indexed.cpp,v
retrieving revision 1.94
diff -r1.94 indexed.cpp
672,674c672,674
< /** Simplify product of indexed expressions (commutative, noncommutative and
< * simple squares), return list of free indices. */
< ex simplify_indexed_product(const ex & e, exvector & free_indices, exvector & dummy_indices, const scalar_products & sp)
---
> /* An auxiliary function used by simplify_indexed() and expand_dummy_sum()
> * It returns an exvector of factors from the supplied product*/
> static void product_to_exvector(const ex &e, exvector &v, bool &non_commutative)
678c678
< bool non_commutative = is_exactly_a<ncmul>(e);
---
> non_commutative = is_exactly_a<ncmul>(e);
681d680
< exvector v;
703a703,715
> }
>
> /** Simplify product of indexed expressions (commutative, noncommutative and
> * simple squares), return list of free indices. */
> ex simplify_indexed_product(const ex & e, exvector & free_indices, exvector & dummy_indices, const scalar_products & sp)
> {
> // Collect factors in an exvector
> exvector v;
>
> // Remember whether the product was commutative or noncommutative
> // (because we chop it into factors and need to reassemble later)
> bool non_commutative;
> product_to_exvector(e, v, non_commutative);
1278a1291,1352
> }
>
> ex expand_dummy_sum(const ex &e, bool subs_idx)
> {
> ex e_expanded = e.expand();
> pointer_to_map_function_1arg<bool> fcn(expand_dummy_sum, subs_idx);
> if (is_a<add>(e_expanded))
> return e_expanded.map(fcn);
> else if (is_a<ncmul>(e_expanded) || is_a<mul>(e_expanded) || is_a<power>(e_expanded)) {
> exvector p;
> bool nc;
> product_to_exvector(e_expanded, p, nc);
> exvector::const_iterator ip = p.begin(), ipend = p.end();
> exvector v;
> while (ip != ipend) {
> if (is_a<indexed>(*ip)) {
> v = ex_to<indexed>(*ip).get_dummy_indices();
> exvector::const_iterator ip1 = ip+1;
> while (ip1 != ipend) {
> if (is_a<indexed>(*ip1)) {
> exvector v1 = ex_to<indexed>(*ip).get_dummy_indices(ex_to<indexed>(*ip1));
> v.insert(v.end(), v1.begin(), v1.end());
> }
> ip1++;
> }
> exvector::const_iterator it = v.begin(), itend = v.end();
> while (it != itend) {
> varidx nu = ex_to<varidx>(*it);
> if (nu.is_dim_numeric()) {
> ex en = 0;
> for (int i=0; i < ex_to<numeric>(nu.get_dim()).to_int(); i++)
> if (is_a<varidx>(nu) && !subs_idx)
> en += e_expanded.subs(lst(nu == varidx(i, nu.get_dim(), true), nu.toggle_variance() == varidx(i, nu.get_dim())));
> else
> en += e_expanded.subs(lst(nu == idx(i, nu.get_dim()), nu.toggle_variance() == idx(i, nu.get_dim())));
> return expand_dummy_sum(en, subs_idx);
> }
> it++;
> }
> }
> ip++;
> }
> return e;
> } else if (is_a<indexed>(e_expanded)) {
> exvector v = ex_to<indexed>(e_expanded).get_dummy_indices();
> exvector::const_iterator it = v.begin(), itend = v.end();
> while (it != itend) {
> varidx nu = ex_to<varidx>(*it);
> if (nu.is_dim_numeric()) {
> ex en = 0;
> for (int i=0; i < ex_to<numeric>(nu.get_dim()).to_int(); i++)
> if (is_a<varidx>(nu) && !subs_idx)
> en += e_expanded.subs(lst(nu == varidx(i, nu.get_dim(), true), nu.toggle_variance() == varidx(i, nu.get_dim())));
> else
> en += e_expanded.subs(lst(nu == idx(i, nu.get_dim()), nu.toggle_variance() == idx(i, nu.get_dim())));
> return expand_dummy_sum(en, subs_idx);
> }
> it++;
> }
> return e;
> } else
> return e;
Index: ginac/clifford.h
===================================================================
RCS file: /home/cvs/GiNaC/ginac/clifford.h,v
retrieving revision 1.57
diff -r1.57 clifford.h
47,48c47,48
< clifford(const ex & b, unsigned char rl = 0);
< clifford(const ex & b, const ex & mu, const ex & metr, unsigned char rl = 0);
---
> clifford(const ex & b, unsigned char rl = 0, bool anticommut = false);
> clifford(const ex & b, const ex & mu, const ex & metr, unsigned char rl = 0, bool anticommut = false);
51,52c51,52
< clifford(unsigned char rl, const ex & metr, const exvector & v, bool discardable = false);
< clifford(unsigned char rl, const ex & metr, std::auto_ptr<exvector> vp);
---
> clifford(unsigned char rl, const ex & metr, bool anticommut, const exvector & v, bool discardable = false);
> clifford(unsigned char rl, const ex & metr, bool anticommut, std::auto_ptr<exvector> vp);
69c69
< ex get_metric(const ex & i, const ex & j) const;
---
> ex get_metric(const ex & i, const ex & j, bool symmetrised = false) const;
70a71
> bool is_anticommuting() const { return anticommuting; } //**< See the member variable anticommuting */
79c80,81
< ex metric;
---
> ex metric; /**< Metric of the space, all constructors make it an indexed object */
> bool anticommuting; /**< Simplifications for anticommuting units is much simpler and we need this info readily available */
196c198
< * @param metr Metric (should be of class tensmetric or a derived class, or a matrix)
---
> * @param metr Metric (should be indexed, tensmetric or a derived class, or a matrix)
199c201
< ex clifford_unit(const ex & mu, const ex & metr, unsigned char rl = 0);
---
> ex clifford_unit(const ex & mu, const ex & metr, unsigned char rl = 0, bool anticommuting = false);
287a290,296
> /** Returns the maximal representation label of a clifford object
> * if e contains at least one, otherwise returns -1
> *
> * @param e Expression to be processed
> * @ignore_ONE defines if clifford_ONE should be ignored in the search*/
> char clifford_max_label(const ex & e, bool ignore_ONE = false);
>
298c307
< * @param metr Metric (should be of class tensmetric or a derived class, or a matrix)
---
> * @param metr Metric (should be indexed, tensmetric or a derived class, or a matrix)
302c311
< 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 & mu, const ex & metr, unsigned char rl = 0, bool anticommuting = false);
329a339
> * @param anticommuting indicates if Clifford units anticommutes
331c341
< 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 & a, const ex & b, const ex & c, const ex & d, const ex & v, const ex & G, unsigned char rl = 0, bool anticommuting = false);
339a350
> * @param anticommuting indicates if Clifford units anticommutes
341c352
< ex clifford_moebius_map(const ex & M, 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, bool anticommuting = false);
Index: ginac/clifford.cpp
===================================================================
RCS file: /home/cvs/GiNaC/ginac/clifford.cpp,v
retrieving revision 1.88
diff -r1.88 clifford.cpp
80,81c80,81
<
< clifford::clifford() : representation_label(0), metric(default_metric())
---
>
> clifford::clifford() : representation_label(0), metric(default_metric()), anticommuting(false)
100c100
< clifford::clifford(const ex & b, unsigned char rl) : inherited(b), representation_label(rl), metric(0)
---
> clifford::clifford(const ex & b, unsigned char rl, bool anticommut) : inherited(b), representation_label(rl), metric(0), anticommuting(anticommut)
109c109
< clifford::clifford(const ex & b, const ex & mu, const ex & metr, unsigned char rl) : inherited(b, mu), representation_label(rl), metric(metr)
---
> clifford::clifford(const ex & b, const ex & mu, const ex & metr, unsigned char rl, bool anticommut) : inherited(b, mu), representation_label(rl), metric(metr), anticommuting(anticommut)
115c115
< clifford::clifford(unsigned char rl, const ex & metr, const exvector & v, bool discardable) : inherited(not_symmetric(), v, discardable), representation_label(rl), metric(metr)
---
> clifford::clifford(unsigned char rl, const ex & metr, bool anticommut, const exvector & v, bool discardable) : inherited(not_symmetric(), v, discardable), representation_label(rl), metric(metr), anticommuting(anticommut)
120c120
< clifford::clifford(unsigned char rl, const ex & metr, std::auto_ptr<exvector> vp) : inherited(not_symmetric(), vp), representation_label(rl), metric(metr)
---
> clifford::clifford(unsigned char rl, const ex & metr, bool anticommut, std::auto_ptr<exvector> vp) : inherited(not_symmetric(), vp), representation_label(rl), metric(metr), anticommuting(anticommut)
134a135
> n.find_bool("anticommuting", anticommuting);
141a143
> n.add_bool("anticommuting", anticommuting);
156c158
< ex clifford::get_metric(const ex & i, const ex & j) const
---
> ex clifford::get_metric(const ex & i, const ex & j, bool symmetrised) const
158c160,170
< return indexed(metric, symmetric2(), i, j);
---
> if (is_a<indexed>(metric)) {
> if (symmetrised && !(ex_to<symmetry>(ex_to<indexed>(metric).get_symmetry()).has_symmetry())) {
> if (is_a<matrix>(metric.op(0)))
> return indexed((ex_to<matrix>(metric.op(0)).add(ex_to<matrix>(metric.op(0)).transpose())).mul(numeric(1,2)),
> symmetric2(), i, j);
> else
> return simplify_indexed(indexed(metric.op(0)*_ex1_2, i, j) + indexed(metric.op(0)*_ex1_2, j, i));
> } else
> return indexed(metric.op(0), ex_to<symmetry>(ex_to<indexed>(metric).get_symmetry()), i, j);
> } else // should not really happen since all constructors but clifford() make the metric an indexed object
> return indexed(metric, i, j);
164c176
< return get_metric().is_equal(ex_to<clifford>(other).get_metric());
---
> return same_metric(ex_to<clifford>(other).get_metric());
378,384c390,396
< for (int i=0; i<v.size();i++) {
< if (!is_a<clifford>(v[i]) && is_a<indexed>(v[i])
< && ex_to<clifford>(c).same_metric(v[i])
< && (ex_to<varidx>(c.op(1)) == ex_to<indexed>(v[i]).get_indices()[0]
< || ex_to<varidx>(c.op(1)).toggle_variance() == ex_to<indexed>(v[i]).get_indices()[0])) {
< return ++i; // next to found
< }
---
> for (size_t i=0; i<v.size(); i++) {
> if (is_a<indexed>(v[i]) && !is_a<clifford>(v[i])
> && ((ex_to<varidx>(c.op(1)) == ex_to<indexed>(v[i]).get_indices()[0]
> && ex_to<varidx>(c.op(1)) == ex_to<indexed>(v[i]).get_indices()[1])
> || (ex_to<varidx>(c.op(1)).toggle_variance() == ex_to<indexed>(v[i]).get_indices()[0]
> && ex_to<varidx>(c.op(1)).toggle_variance() == ex_to<indexed>(v[i]).get_indices()[1])))
> return i; // the index of the found
386c398
< return 0; //nothing found
---
> return -1; //nothing found
397c409
<
---
>
406,408c418,430
< int prev_square = find_same_metric(v, self[0]);
< varidx d((new symbol)->setflag(status_flags::dynallocated), ex_to<idx>(self->op(1)).get_dim());
< ex squared_metric = unit.get_metric(self->op(1), d) * unit.get_metric(d.toggle_variance(), other->op(1));
---
> int prev_square = find_same_metric(v, *self);
> const varidx d((new symbol)->setflag(status_flags::dynallocated), ex_to<idx>(self->op(1)).get_dim()),
> in1((new symbol)->setflag(status_flags::dynallocated), ex_to<idx>(self->op(1)).get_dim()),
> in2((new symbol)->setflag(status_flags::dynallocated), ex_to<idx>(self->op(1)).get_dim());
> ex squared_metric;
> if (prev_square > -1)
> squared_metric = simplify_indexed(indexed(v[prev_square].op(0), in1, d)
> * unit.get_metric(d.toggle_variance(), in2, true)).op(0);
>
> exvector::iterator before_other = other - 1;
> const varidx & mu = ex_to<varidx>(self->op(1));
> const varidx & mu_toggle = ex_to<varidx>(other->op(1));
> const varidx & alpha = ex_to<varidx>(before_other->op(1));
412,414c434,436
< if (prev_square != 0) {
< *self = squared_metric;
< v[prev_square-1] = _ex1;
---
> if (prev_square > -1) {
> *self = indexed(squared_metric, mu, mu_toggle);
> v[prev_square] = _ex1;
416c438
< *self = unit.get_metric(self->op(1), other->op(1));
---
> *self = unit.get_metric(mu, mu_toggle, true);
420,436c442,469
< // e~mu e~alpha e.mu = (2e~alpha^2-Tr) e~alpha
< } else if (other - self == 2
< && is_a<clifford>(self[1])) {
<
< const ex & ia = self[1].op(1);
< const ex & ib = self[1].op(1);
< if (is_a<tensmetric>(unit.get_metric()))
< *self = 2 - unit.get_metric(self->op(1), other->op(1));
< else if (prev_square != 0) {
< *self = 2-squared_metric;
< v[prev_square-1] = _ex1;
< } else
< *self = 2*unit.get_metric(ia, ib) - unit.get_metric(self->op(1), other->op(1));
< *other = _ex1;
< return true;
<
< // e~mu S e~alpha e.mu = 2 e~alpha^3 S - e~mu S e.mu e~alpha
---
> } else if (other - self == 2) {
> if (is_a<clifford>(*before_other) && ex_to<clifford>(*before_other).get_representation_label() == rl) {
> if (ex_to<clifford>(*self).is_anticommuting()) {
> // e~mu e~alpha e.mu = (2*pow(e~alpha, 2) -Tr(B)) e~alpha
> if (prev_square > -1) {
> *self = 2 * indexed(squared_metric, alpha, alpha)
> - indexed(squared_metric, mu, mu_toggle);
> v[prev_square] = _ex1;
> } else
> *self = 2 * unit.get_metric(alpha, alpha, true) - unit.get_metric(mu, mu_toggle, true);
> *other = _ex1;
> return true;
>
> } else {
> // e~mu e~alpha e.mu = 2*e~mu B(alpha, mu.toggle_variance())-Tr(B) e~alpha
> *self = 2 * (*self) * unit.get_metric(alpha, mu_toggle, true) - unit.get_metric(mu, mu_toggle, true) * (*before_other);
> *before_other = _ex1;
> *other = _ex1;
> return true;
> }
> } else {
> // e~mu S e.mu = Tr S ONE
> *self = unit.get_metric(mu, mu_toggle, true);
> *other = dirac_ONE(rl);
> return true;
> }
> } else {
> // e~mu S e~alpha e.mu = 2 e~mu S B(alpha, mu.toggle_variance()) - e~mu S e.mu e~alpha
439,452c472,475
< } else {
< exvector::iterator it = self + 1, next_to_last = other - 1;
< while (it != other) {
< if (!is_a<clifford>(*it))
< return false;
< ++it;
< }
<
< it = self + 1;
< ex S = _ex1;
< while (it != next_to_last) {
< S *= *it;
< *it++ = _ex1;
< }
---
> if (std::find_if(self + 1, other, is_not_a_clifford()) != other)
> return false;
>
> ex S = ncmul(exvector(self + 1, before_other), true);
454,464c477,490
< const ex & ia = next_to_last->op(1);
< const ex & ib = next_to_last->op(1);
< if (is_a<tensmetric>(unit.get_metric()))
< *self = 2 * (*next_to_last) * S - (*self) * S * (*other) * (*next_to_last);
< else if (prev_square != 0) {
< *self = 2 * (*next_to_last) * S - (*self) * S * (*other) * (*next_to_last)*unit.get_metric(self->op(1),self->op(1));
< v[prev_square-1] = _ex1;
< } else
< *self = 2 * (*next_to_last) * S* unit.get_metric(ia,ib) - (*self) * S * (*other) * (*next_to_last);
< *next_to_last = _ex1;
< *other = _ex1;
---
> if (is_a<clifford>(*before_other) && ex_to<clifford>(*before_other).get_representation_label() == rl)
> if (ex_to<clifford>(*self).is_anticommuting())
> if (prev_square > -1)
> *self = 2 * (*before_other) * S * indexed(squared_metric, alpha, alpha)
> - (*self) * S * (*other) * (*before_other);
> else
> *self = 2 * (*before_other) * S * unit.get_metric(alpha, alpha, true) - (*self) * S * (*other) * (*before_other);
> else
> *self = 2 * (*self) * S * unit.get_metric(alpha, mu_toggle, true) - (*self) * S * (*other) * (*before_other);
> else
> // simply commutes
> *self = (*self) * S * (*other) * (*before_other);
>
> std::fill(self + 1, other + 1, _ex1);
467d492
<
469d493
<
583c607
< a = ex_to<clifford>(a).get_metric(ia, ib);
---
> a = ex_to<clifford>(a).get_metric(ia, ib, true);
633c657
< return clifford(diracone(), representation_label) * sign;
---
> return dirac_ONE(representation_label) * sign;
642c666
< return clifford(representation_label, get_metric(), v);
---
> return clifford(representation_label, get_metric(), is_anticommuting(), v);
647c671
< return clifford(representation_label, get_metric(), vp);
---
> return clifford(representation_label, get_metric(), is_anticommuting(), vp);
672c696
< return clifford(ONE, rl);
---
> return clifford(ONE, rl, false);
675c699
< ex clifford_unit(const ex & mu, const ex & metr, unsigned char rl)
---
> ex clifford_unit(const ex & mu, const ex & metr, unsigned char rl, bool anticommuting)
679,680c703,704
< if (!is_a<varidx>(mu))
< throw(std::invalid_argument("index of Clifford unit must be of type varidx"));
---
> if (!is_a<idx>(mu))
> throw(std::invalid_argument("clifford_unit(): index of Clifford unit must be of type idx or varidx"));
682,687c706,739
< if (is_a<indexed>(metr))
< return clifford(unit, mu, metr.op(0), rl);
< else if(is_a<tensmetric>(metr) || is_a<matrix>(metr))
< return clifford(unit, mu, metr, rl);
< else
< throw(std::invalid_argument("metric for Clifford unit must be of type indexed, tensormetric or matrix"));
---
> if (ex_to<idx>(mu).is_symbolic() && !is_a<varidx>(mu))
> throw(std::invalid_argument("clifford_unit(): symbolic index of Clifford unit must be of type varidx (not idx)"));
>
> if (is_a<indexed>(metr)) {
> exvector indices = ex_to<indexed>(metr).get_indices();
> if ((indices.size() == 2) && is_a<varidx>(indices[0]) && is_a<varidx>(indices[1]))
> return clifford(unit, mu, metr, rl, anticommuting);
> else
> throw(std::invalid_argument("clifford_unit(): metric for Clifford unit must be indexed exactly by two indices of same type as the given index"));
> } else if (is_a<tensmetric>(metr)) {
> static varidx xi((new symbol)->setflag(status_flags::dynallocated), ex_to<varidx>(mu).get_dim()),
> chi((new symbol)->setflag(status_flags::dynallocated), ex_to<varidx>(mu).get_dim());
> return clifford(unit, mu, indexed(metr, xi, chi), rl, anticommuting);
> } else if (is_a<matrix>(metr)) {
> matrix M = ex_to<matrix>(metr);
> unsigned n = M.rows();
> bool symmetric = true;
> anticommuting = true;
>
> static varidx xi((new symbol)->setflag(status_flags::dynallocated), n),
> chi((new symbol)->setflag(status_flags::dynallocated), n);
> if ((n == M.cols()) && (n == ex_to<varidx>(mu).get_dim())) {
> for (unsigned i = 0; i < n; i++)
> for (unsigned j = i+1; j < n; j++) {
> if (M(i, j) != M(j, i))
> symmetric = false;
> if (M(i, j) != -M(j, i))
> anticommuting = false;
> }
> return clifford(unit, mu, indexed(metr, symmetric?symmetric2():not_symmetric(), xi, chi), rl, anticommuting);
> } else
> throw(std::invalid_argument("clifford_unit(): metric for Clifford unit must be a square matrix with the same dimensions as index"));
> } else
> throw(std::invalid_argument("clifford_unit(): metric for Clifford unit must be of type indexed, tensormetric or matrix"));
695c747
< throw(std::invalid_argument("index of Dirac gamma must be of type varidx"));
---
> throw(std::invalid_argument("dirac_gamma(): index of Dirac gamma must be of type varidx"));
697c749,751
< return clifford(gamma, mu, default_metric(), rl);
---
> static varidx xi((new symbol)->setflag(status_flags::dynallocated), ex_to<varidx>(mu).get_dim()),
> chi((new symbol)->setflag(status_flags::dynallocated), ex_to<varidx>(mu).get_dim());
> return clifford(gamma, mu, indexed(default_metric(), symmetric2(), xi, chi), rl, true);
987c1041
< it[0] = (ex_to<clifford>(save0).get_metric(i1, i2) * b1 * b2).simplify_indexed();
---
> it[0] = (ex_to<clifford>(save0).get_metric(i1, i2, true) * b1 * b2).simplify_indexed();
1019c1073
< ex remove_dirac_ONE(const ex & e, unsigned char rl)
---
> ex remove_dirac_ONE(const ex & e, unsigned char rl)
1026c1080
< throw(std::invalid_argument("Expression is a non-scalar Clifford number!"));
---
> throw(std::invalid_argument("remove_dirac_ONE(): expression is a non-scalar Clifford number!"));
1035a1090,1105
> char clifford_max_label(const ex & e, bool ignore_ONE)
> {
> if (is_a<clifford>(e))
> if (ignore_ONE && is_a<diracone>(e.op(0)))
> return -1;
> else
> return ex_to<clifford>(e).get_representation_label();
> else {
> char rl = -1;
> for (size_t i=0; i < e.nops(); i++)
> rl = (rl > clifford_max_label(e.op(i), ignore_ONE)) ? rl : clifford_max_label(e.op(i), ignore_ONE);
> return rl;
> }
> }
>
>
1047c1117
< throw(std::invalid_argument("Cannot find inverse of Clifford number with zero norm!"));
---
> throw(std::invalid_argument("clifford_inverse(): cannot find inverse of Clifford number with zero norm!"));
1050c1120
< ex lst_to_clifford(const ex & v, const ex & mu, const ex & metr, unsigned char rl)
---
> ex lst_to_clifford(const ex & v, const ex & mu, const ex & metr, unsigned char rl, bool anticommuting)
1053,1054c1123,1124
< throw(std::invalid_argument("Index should have a numeric dimension"));
< ex e = clifford_unit(mu, metr, rl);
---
> throw(std::invalid_argument("lst_to_clifford(): Index should have a numeric dimension"));
> ex e = clifford_unit(mu, metr, rl, anticommuting);
1077c1147
< throw(std::invalid_argument("Dimensions of vector and clifford unit mismatch"));
---
> throw(std::invalid_argument("lst_to_clifford(): dimensions of vector and clifford unit mismatch"));
1079c1149
< throw(std::invalid_argument("First argument should be a vector vector"));
---
> throw(std::invalid_argument("lst_to_clifford(): first argument should be a vector vector"));
1084c1154
< throw(std::invalid_argument("List length and dimension of clifford unit mismatch"));
---
> throw(std::invalid_argument("lst_to_clifford(): list length and dimension of clifford unit mismatch"));
1086c1156
< throw(std::invalid_argument("Cannot construct from anything but list or vector"));
---
> throw(std::invalid_argument("lst_to_clifford(): cannot construct from anything but list or vector"));
1088c1158
< throw(std::invalid_argument("The second argument should be a Clifford unit"));
---
> throw(std::invalid_argument("lst_to_clifford(): the second argument should be a Clifford unit"));
1090c1160
<
---
>
1109c1179
< throw(std::invalid_argument("Expression is a Clifford multi-vector"));
---
> throw(std::invalid_argument("get_clifford_comp(): expression is a Clifford multi-vector"));
1134c1204
< throw(std::invalid_argument("Expression is not a Clifford vector to the given units"));
---
> throw(std::invalid_argument("get_clifford_comp(): expression is not a Clifford vector to the given units"));
1144c1214
< throw(std::invalid_argument("Expression is not usable as a Clifford vector"));
---
> throw(std::invalid_argument("get_clifford_comp(): expression is not usable as a Clifford vector"));
1153c1223
< throw(std::invalid_argument("Index should have a numeric dimension"));
---
> throw(std::invalid_argument("clifford_to_lst(): index should have a numeric dimension"));
1176c1246
< 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 clifford_moebius_map(const ex & a, const ex & b, const ex & c, const ex & d, const ex & v, const ex & G, unsigned char rl, bool anticommuting)
1181c1251
< throw(std::invalid_argument("parameter v should be either vector or list"));
---
> throw(std::invalid_argument("clifford_moebius_map(): parameter v should be either vector or list"));
1190c1260
< else throw(std::invalid_argument("metric should be an indexed object, matrix, or a Clifford unit"));
---
> else throw(std::invalid_argument("clifford_moebius_map(): metric should be an indexed object, matrix, or a Clifford unit"));
1193c1263
< cu = clifford_unit(mu, G, rl);
---
> cu = clifford_unit(mu, G, rl, anticommuting);
1195c1265
<
---
>
1201c1271
< ex clifford_moebius_map(const ex & M, const ex & v, const ex & G, unsigned char rl)
---
> ex clifford_moebius_map(const ex & M, const ex & v, const ex & G, unsigned char rl, bool anticommuting)
1205c1275
< ex_to<matrix>(M)(1,0), ex_to<matrix>(M)(1,1), v, G, rl);
---
> ex_to<matrix>(M)(1,0), ex_to<matrix>(M)(1,1), v, G, rl, anticommuting);
1207c1277
< throw(std::invalid_argument("parameter M should be a matrix"));
---
> throw(std::invalid_argument("clifford_moebius_map(): parameter M should be a matrix"));
1
0
Dear All,
Working on further patches to clifford.cpp I found that such a
simple program
#include <iostream>
#include <ginac/ginac.h>
using namespace std;
using namespace GiNaC;
#include <stdexcept>
int main(){
realsymbol a("a");
varidx nu(symbol("nu", "\\nu"), 2), mu(symbol("mu", "\\mu"), 2);
try {
ex e = a* dirac_gamma(nu) + 2*dirac_gamma(nu);
cout << e.collect(dirac_gamma(nu)) << endl;
// -> (2+a)*gamma~nu
e = dirac_gamma(mu)* dirac_gamma(nu) + dirac_gamma(nu);
cout << e.collect(dirac_gamma(nu)) << endl;
// Raised exception:
// add::eval(): sum of non-commutative objects has non-zero numeric term
} catch (exception &p) {
cerr << "Got problem: " << p.what() << endl;
}
}
raises an exception in the second output statement. I think everyone
would like it can produce something like "(ONE+gamma~mu)*gamma~nu"
instead. And first output should remain "(2+a)*gamma~nu" and not
became "(2*ONE+a*ONE)*gamma~nu" on the other hand.
I am not sure that is the best way to achieve it but propose a patch
which seems to solve it. It introduces one more utility function
clifford_max_label() at clifford.cpp, which returns the maximal
representation label of non-commutative Clifford object in the
expression. Besides that there is also a patch to add::coeff() in
add.cpp. I wrote it in mind to reduce unwonted overheads for
expression without any Clifford numbers.
After this issue will be rectified some more patches to clifford.cpp
will follow.
Best wishes,
Vladimir
--
Vladimir V. Kisil email: kisilv(a)maths.leeds.ac.uk
-- www: http://maths.leeds.ac.uk/~kisilv/
Index: ginac/clifford.h
===================================================================
RCS file: /home/cvs/GiNaC/ginac/clifford.h,v
retrieving revision 1.56
diff -r1.56 clifford.h
285a286,292
> /** Returns the maximal representation label of a clifford object
> * if e contains at least one, otherwise returns -1
> *
> * @param e Expression to be processed
> * @ignore_ONE defines if clifford_ONE should be ignored in the search*/
> ex clifford_max_label(const ex & e, bool ignore_ONE = false);
>
Index: ginac/clifford.cpp
===================================================================
RCS file: /home/cvs/GiNaC/ginac/clifford.cpp,v
retrieving revision 1.86
diff -r1.86 clifford.cpp
1035a1084,1100
> ex clifford_max_label(const ex & e, bool ignore_ONE)
> {
> if (is_a<clifford>(e))
> if (ignore_ONE && is_a<diracone>(e.op(0)))
> return _ex_1;
> else
> return ex_to<clifford>(e).get_representation_label();
> else {
> ex rl = _ex_1;
> for (size_t i=0; i < e.nops(); i++)
> rl = ex_to<numeric>(rl - clifford_max_label(e.op(i), ignore_ONE)).is_positive()?
> rl : clifford_max_label(e.op(i), ignore_ONE);
> return rl;
> }
> }
Index: ginac/add.cpp
===================================================================
RCS file: /home/cvs/GiNaC/ginac/add.cpp,v
retrieving revision 1.76
diff -r1.76 add.cpp
31a32
> #include "clifford.h"
293a295,297
> std::auto_ptr<epvector> coeffseq_cliff(new epvector);
> ex rl = clifford_max_label(s);
> bool do_clifford = (!rl.is_equal(_ex_1)), nonscalar = false;
299c303,310
< if (!restcoeff.is_zero())
---
> if (!restcoeff.is_zero()) {
> if (do_clifford)
> if (clifford_max_label(restcoeff).is_equal(_ex_1))
> coeffseq_cliff->push_back(combine_ex_with_coeff_to_pair(mul(restcoeff,dirac_ONE(ex_to<numeric>(rl).to_int())), i->coeff));
> else {
> coeffseq_cliff->push_back(combine_ex_with_coeff_to_pair(restcoeff, i->coeff));
> nonscalar = true;
> }
300a312
> }
304c316,317
< return (new add(coeffseq, n==0 ? overall_coeff : _ex0))->setflag(status_flags::dynallocated);
---
> return (new add(nonscalar? coeffseq_cliff : coeffseq,
> n==0 ? overall_coeff : _ex0))->setflag(status_flags::dynallocated);
3
3
Dear developers,
I found out that dirac_slash(p+q,4) is printed as "q+p\". I think this is
confusing and that "(q+p)\" would be much clearer. A patch is attached.
Best wishes,
Chris
2
1
Hi Fausto,
I am not sure about your problem, but maybe the following might help
you.
On Sat, Apr 09, 2005 at 12:13:30PM +0200, Fausto Saporito wrote:
> I'm using autoconf 2.59 is it the right version?
That version works fine with GiNaC.
> What is the exact procedure to generate a configure? I didn't find any
> autogen.sh script, so I tried to use the autogen.sh present in GiNaC
> cvs tree.
Use
autoreconf -i
That does the job those autogen.sh scripts normally take care of.
It's part of the autoconf package.
> /sw/share/aclocal/pth.m4:55: warning: underquoted definition of
> _AC_PTH_VERBOSE
> /sw/share/aclocal/pth.m4:61: warning: underquoted definition of
> AC_CHECK_PTH
> /sw/share/aclocal/pkg.m4:5: warning: underquoted definition of
> PKG_CHECK_MODULES
> /sw/share/aclocal/libgcrypt.m4:23: warning: underquoted definition of
> AM_PATH_LIBGCRYPT
> /sw/share/aclocal/gtk.m4:7: warning: underquoted definition of
> AM_PATH_GTK
> /sw/share/aclocal/glib.m4:8: warning: underquoted definition of
> AM_PATH_GLIB
The automake files of GiNaC are set up for older versions of automake,
like automake 1.4. Newer versions (and there are plenty of them!)
produce these warnings. It's kind of annoying but basically harmless.
> + Running autoheader: autoheader: warning: missing template: CL_USE_GMP
> autoheader: Use AC_DEFINE([CL_USE_GMP], [], [Description])
> autoheader: warning: missing template: CL_VERSION
> autoheader: warning: missing template: CL_VERSION_MAJOR
> autoheader: warning: missing template: CL_VERSION_MINOR
> autoheader: warning: missing template: CL_VERSION_PATCHLEVEL
> done.
> + Running automake: configure.ac: no proper invocation of
> AM_INIT_AUTOMAKE was found.
> configure.ac: You should verify that configure.ac invokes
> AM_INIT_AUTOMAKE,
> configure.ac: that aclocal.m4 is present in the top-level directory,
> configure.ac: and that aclocal.m4 was recently regenerated (using
> aclocal).
> configure.ac: installing `autoconf/missing'
> automake: no `Makefile.am' found for any configure output
> done.
This is not harmless anymore ;-) What's your version of automake?
Regards,
Jens
2
1
Hello,
I have a problem generating configure under Mac OS X 1.3 with Fink.
When I run autoconf I don't receive any errors, but when I run
configure script I have after a while,
checking whether make sets $(MAKE)... yes
checking for gcc... gcc
checking for C compiler default output file name... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables...
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ANSI C... none needed
checking how to run the C preprocessor... gcc -E
checking for g++... g++
checking whether we are using the GNU C++ compiler... yes
checking whether g++ accepts -g... yes
checking how to run the C++ preprocessor... g++ -E
./configure: line 3318: CL_AS_UNDERSCORE: command not found
checking for ranlib... ranlib
checking for a BSD-compatible install... /usr/bin/install -c
./configure: line 3478: syntax error near unexpected token `autoconf'
./configure: line 3478: `
CL_CANONICAL_HOST(autoconf)'
I'm using autoconf 2.59 is it the right version?
What is the exact procedure to generate a configure? I didn't find any
autogen.sh script, so I tried to use the autogen.sh present in GiNaC
cvs tree.
When I run autogen.sh I have some warnings:
+ Running aclocal: /sw/share/aclocal/pth.m4:43: warning: underquoted
definition of _AC_PTH_ERROR
run info '(automake)Extending aclocal'
or see
http://sources.redhat.com/automake/automake.html#Extending-aclocal
/sw/share/aclocal/pth.m4:55: warning: underquoted definition of
_AC_PTH_VERBOSE
/sw/share/aclocal/pth.m4:61: warning: underquoted definition of
AC_CHECK_PTH
/sw/share/aclocal/pkg.m4:5: warning: underquoted definition of
PKG_CHECK_MODULES
/sw/share/aclocal/libgcrypt.m4:23: warning: underquoted definition of
AM_PATH_LIBGCRYPT
/sw/share/aclocal/gtk.m4:7: warning: underquoted definition of
AM_PATH_GTK
/sw/share/aclocal/glib.m4:8: warning: underquoted definition of
AM_PATH_GLIB
done.
+ Running libtoolize: done.
+ Running autoheader: autoheader: warning: missing template: CL_USE_GMP
autoheader: Use AC_DEFINE([CL_USE_GMP], [], [Description])
autoheader: warning: missing template: CL_VERSION
autoheader: warning: missing template: CL_VERSION_MAJOR
autoheader: warning: missing template: CL_VERSION_MINOR
autoheader: warning: missing template: CL_VERSION_PATCHLEVEL
done.
+ Running automake: configure.ac: no proper invocation of
AM_INIT_AUTOMAKE was found.
configure.ac: You should verify that configure.ac invokes
AM_INIT_AUTOMAKE,
configure.ac: that aclocal.m4 is present in the top-level directory,
configure.ac: and that aclocal.m4 was recently regenerated (using
aclocal).
configure.ac: installing `autoconf/missing'
automake: no `Makefile.am' found for any configure output
done.
+ Running autoconf: done.
Any idea?
thanks a lot,
Fausto
2
1
Hi Vladimir,
I applied your and C.Dams' patch now. But I also applied a forgotten
patch from you from December that changes
ex clifford::get_metric(const ex & i, const ex & j) const
from
return indexed(metric, symmetric2(), i, j);
to
return indexed(metric, i, j);
With this December patch the exams for clifford fail with
----------clifford objects:
2*ONE*[[-1,0,0,0],[0,0,0,0],[0,0,1,0],[0,0,0,-1]]~nu~mu-2*[[-1,0,0,0],[0,0,0,0],[0,0,1,0],[0,0,0,-1]]~mu~nu*ONE
erroneously return ed
2*ONE*[[-1,0,0,0],[0,0,0,0],[0,0,1,0],[0,0,0,-1]]~nu~mu-2*[[-1,0,0,0],[0,0,0,0],[0,0,1,0],[0,0,0,-1]]~mu~nu*ONE
instead of 0
[[-1,0,0,0],[0,0,0,0],[0,0,1,0],[0,0,0,-1]]~mu~nu*e~lambda-[[-1,0,0,0],[0,0,0,0],[0,0,1,0],[0,0,0,-1]]~nu~mu*e~lambda-0
erroneousl y returned
[[-1,0,0,0],[0,0,0,0],[0,0,1,0],[0,0,0,-1]]~mu~nu*e~lambda-[[-1,0,0,0],[0,0,0,0],[0,0,1,0],[0,0,0,-1]]~nu~mu*e~lambda
i nstead of 0
Without it, it produces no error.
The December patch makes sense to me, because the tutorial promises that
one can use non-symmetric metrics. Am I wrong here? So, what should I do
about it?
Regards,
Jens
1
0
Dear All,
Apologies for flooding this list, but
1. I found one more bug in clifford_prime(): it did not map itself on
the usual (commutative) products "mul".
2. I also changed the behaviour of remove_dirac_ONE() slightly: it is
now aware of representation_label for Clifford numbers. API and
default behaviour remain the same (but not a binary compatibility).
So here is the cumulative patch to my previous post on Tue Mar 29
13:34:13.
Best wishes,
Vladimir
--
Vladimir V. Kisil email: kisilv(a)maths.leeds.ac.uk
-- www: http://maths.leeds.ac.uk/~kisilv/
Index: doc/tutorial/ginac.texi
===================================================================
RCS file: /home/cvs/GiNaC/doc/tutorial/ginac.texi,v
retrieving revision 1.162
diff -r1.162 ginac.texi
3178,3181c3178,3190
< 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
3188c3197
< 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
3196c3205
< 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
3200c3209
< ex e = clifford_unit(mu, indexed(B, sy_symm(), i, j));
---
> ex e = clifford_unit(mu, indexed(M, sy_symm(), i, j));
3211,3214c3220,3222
< 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));
3218a3227
> ex e3 = e.subs(nu == 3);
3223,3224c3232,3238
< 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
3231a3246
> ex lst_to_clifford(const ex & v, const ex & e);
3234,3237c3249,3268
< 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
3242,3248c3273,3279
< 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);
3261,3262c3292,3305
< @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
---
> @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 none of
3266c3309,3315
< @samp{(e c.k + c.k e)/pow(c.k, 2)}. If @samp{pow(c.k, 2) = 0} for some @samp{k}
---
> @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}
3292a3342,3344
> @ifnottex
> e*
> @end ifnottex
3296a3349,3351
> @ifnottex
> @code{\bar@{e@}}
> @end ifnottex
3309c3364
< $||e||^2 = e\overline{e}$
---
> $||e||^2 = e\overline{e}$.
3311,3312c3366,3369
< . 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
3320c3377
< $e^{-1} = e/||e||^2$
---
> $e^{-1} = \overline{e}/||e||^2$.
3322c3379,3382
< . If
---
> @ifnottex
> @math{e^@{-1@} = \bar@{e@}/||e||^2}
> @end ifnottex
> If
3325a3386,3388
> @ifnottex
> @math{||e||=0}
> @end ifnottex
3350,3354c3413,3418
< 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
3356a3421,3453
> 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
Index: ginac/clifford.h
===================================================================
RCS file: /home/cvs/GiNaC/ginac/clifford.h,v
retrieving revision 1.55
diff -r1.55 clifford.h
278,279c278,284
< /** 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);
292a298
> * @param e Clifford unit object
294a301
> ex lst_to_clifford(const ex & v, const ex & e);
304c311,312
< * @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*/
318,319c326,328
< * @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*/
327,328c336,338
< * @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*/
Index: ginac/clifford.cpp
===================================================================
RCS file: /home/cvs/GiNaC/ginac/clifford.cpp,v
retrieving revision 1.84
diff -r1.84 clifford.cpp
216c216,217
< } else
---
> } else {
> c.s << "\\clifford[" << int(representation_label) << "]";
217a219
> }
227c229
< DEFAULT_PRINT_LATEX(diracone, "ONE", "\\mathbb{1}")
---
> DEFAULT_PRINT_LATEX(diracone, "ONE", "\\mathbf{1}")
940c942
< ex canonicalize_clifford(const ex & e)
---
> ex canonicalize_clifford(const ex & e_)
944,946c946,948
< 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);
947a950
> ex e=simplify_indexed(e_);
1007,1008c1010,1011
< } 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)) {
1016c1019
< ex remove_dirac_ONE(const ex & e)
---
> ex remove_dirac_ONE(const ex & e, unsigned char rl)
1018,1020c1021,1026
< 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!"));
1022c1028
< || is_a<matrix>(e) || is_a<lst>(e)) {
---
> || is_a<matrix>(e) || is_a<lst>(e)) {
1046d1051
< unsigned min, max;
1049,1050c1054,1056
< 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);
> }
1052,1063c1058,1075
< 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;
1065c1077,1082
< 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;
1067c1084
< throw(std::invalid_argument("Dimensions of vector and clifford unit mismatch"));
---
> throw(std::invalid_argument("List length and dimension of clifford unit mismatch"));
1069,1074c1086
< 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"));
1076c1088
< throw(std::invalid_argument("Cannot construct from anything but list or vector"));
---
> throw(std::invalid_argument("The second argument should be a Clifford unit"));
1146c1158,1159
< 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))))
1165,1171c1178
< 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;
1173,1174d1179
< varidx mu((new symbol)->setflag(status_flags::dynallocated), D);
<
1176a1182,1194
>
> 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);
> }
1178c1196
< x = lst_to_clifford(v, mu, G, rl);
---
> x = lst_to_clifford(v, cu);
1180d1197
< ex cu = clifford_unit(mu, G);
Index: check/exam_clifford.cpp
===================================================================
RCS file: /home/cvs/GiNaC/check/exam_clifford.cpp,v
retrieving revision 1.23
diff -r1.23 exam_clifford.cpp
344c344,345
< 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);
346c347
< result += check_equal((e*e1).simplify_indexed().normal(), dirac_ONE());
---
> result += check_equal((e*e1).simplify_indexed().normal(), dirac_ONE(1));
1
0