[GiNaC-devel] Clifford patch

Vladimir Kisil kisilv at maths.leeds.ac.uk
Thu Apr 28 18:17:55 CEST 2005


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




More information about the GiNaC-devel mailing list