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@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"));