return false;
}
-/** Return degree of highest power in symbol s. */
+/** Return degree of highest power in object s. */
int basic::degree(const ex & s) const
{
return 0;
}
-/** Return degree of lowest power in symbol s. */
+/** Return degree of lowest power in object s. */
int basic::ldegree(const ex & s) const
{
return 0;
}
-/** Return coefficient of degree n in symbol s. */
+/** Return coefficient of degree n in object s. */
ex basic::coeff(const ex & s, int n) const
{
return n==0 ? *this : _ex0();
}
-/** Sort expression in terms of powers of some symbol.
- * @param s symbol to sort in. */
-ex basic::collect(const ex & s) const
+/** Sort expression in terms of powers of some object(s).
+ * @param s object(s) to sort in
+ * @param distributed recursive or distributed form (only used when s is a list) */
+ex basic::collect(const ex & s, bool distributed) const
{
ex x;
- for (int n=this->ldegree(s); n<=this->degree(s); ++n)
- x += this->coeff(s,n)*power(s,n);
+ if (is_ex_of_type(s, lst)) {
+
+ // List of objects specified
+ if (s.nops() == 1)
+ return collect(s.op(0));
+
+ else if (distributed) {
+
+ // Get lower/upper degree of all symbols in list
+ int num = s.nops();
+ struct sym_info {
+ ex sym;
+ int ldeg, deg;
+ int cnt; // current degree, 'counter'
+ ex coeff; // coefficient for degree 'cnt'
+ };
+ sym_info *si = new sym_info[num];
+ ex c = *this;
+ for (int i=0; i<num; i++) {
+ si[i].sym = s.op(i);
+ si[i].ldeg = si[i].cnt = this->ldegree(si[i].sym);
+ si[i].deg = this->degree(si[i].sym);
+ c = si[i].coeff = c.coeff(si[i].sym, si[i].cnt);
+ }
+
+ while (true) {
+
+ // Calculate coeff*x1^c1*...*xn^cn
+ ex y = _ex1();
+ for (int i=0; i<num; i++) {
+ int cnt = si[i].cnt;
+ y *= power(si[i].sym, cnt);
+ }
+ x += y * si[num - 1].coeff;
+
+ // Increment counters
+ int n = num - 1;
+ while (true) {
+ si[n].cnt++;
+ if (si[n].cnt <= si[n].deg) {
+ // Update coefficients
+ ex c;
+ if (n == 0)
+ c = *this;
+ else
+ c = si[n - 1].coeff;
+ for (int i=n; i<num; i++)
+ c = si[i].coeff = c.coeff(si[i].sym, si[i].cnt);
+ break;
+ }
+ if (n == 0)
+ goto done;
+ si[n].cnt = si[n].ldeg;
+ n--;
+ }
+ }
+
+done: delete[] si;
+
+ } else {
+
+ // Recursive form
+ x = *this;
+ for (int n=s.nops()-1; n>=0; n--)
+ x = x.collect(s[n]);
+ }
+
+ } else {
+
+ // Only one object specified
+ for (int n=this->ldegree(s); n<=this->degree(s); ++n)
+ x += this->coeff(s,n)*power(s,n);
+ }
// correct for lost fractional arguments and return
return x + (*this - x).expand();
virtual int degree(const ex & s) const;
virtual int ldegree(const ex & s) const;
virtual ex coeff(const ex & s, int n = 1) const;
- virtual ex collect(const ex & s) const;
+ virtual ex collect(const ex & s, bool distributed = false) const;
virtual ex eval(int level = 0) const;
virtual ex evalf(int level = 0) const;
virtual ex series(const relational & r, int order, unsigned options = 0) const;
GINAC_IMPLEMENT_REGISTERED_CLASS(clifford, indexed)
GINAC_IMPLEMENT_REGISTERED_CLASS(diracone, tensor)
GINAC_IMPLEMENT_REGISTERED_CLASS(diracgamma, tensor)
+GINAC_IMPLEMENT_REGISTERED_CLASS(diracgamma5, tensor)
//////////
// default constructor, destructor, copy constructor assignment operator and helpers
//////////
-clifford::clifford()
+clifford::clifford() : representation_label(0)
{
debugmsg("clifford default constructor", LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_clifford;
}
-DEFAULT_COPY(clifford)
+void clifford::copy(const clifford & other)
+{
+ inherited::copy(other);
+ representation_label = other.representation_label;
+}
+
DEFAULT_DESTROY(clifford)
DEFAULT_CTORS(diracone)
DEFAULT_CTORS(diracgamma)
+DEFAULT_CTORS(diracgamma5)
//////////
// other constructors
//////////
+/** Construct object without any indices. This constructor is for internal
+ * use only. Use the dirac_ONE() function instead.
+ * @see dirac_ONE */
+clifford::clifford(const ex & b, unsigned char rl) : inherited(b), representation_label(rl)
+{
+ debugmsg("clifford constructor from ex", LOGLEVEL_CONSTRUCT);
+ tinfo_key = TINFO_clifford;
+}
+
/** Construct object with one Lorentz index. This constructor is for internal
* use only. Use the dirac_gamma() function instead.
* @see dirac_gamma */
-clifford::clifford(const ex & b, const ex & mu) : inherited(b, mu)
+clifford::clifford(const ex & b, const ex & mu, unsigned char rl) : inherited(b, mu), representation_label(rl)
{
debugmsg("clifford constructor from ex,ex", LOGLEVEL_CONSTRUCT);
GINAC_ASSERT(is_ex_of_type(mu, varidx));
tinfo_key = TINFO_clifford;
}
-/** Construct object without any indices. This constructor is for internal
- * use only. Use the dirac_one() function instead.
- * @see dirac_one */
-clifford::clifford(const ex & b) : inherited(b)
+clifford::clifford(unsigned char rl, const exvector & v, bool discardable) : inherited(indexed::unknown, v, discardable), representation_label(rl)
{
- debugmsg("clifford constructor from ex", LOGLEVEL_CONSTRUCT);
+ debugmsg("clifford constructor from unsigned char,exvector", LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_clifford;
}
-clifford::clifford(const exvector & v, bool discardable) : inherited(indexed::unknown, v, discardable)
+clifford::clifford(unsigned char rl, exvector * vp) : inherited(indexed::unknown, vp), representation_label(rl)
{
- debugmsg("clifford constructor from exvector", LOGLEVEL_CONSTRUCT);
- tinfo_key = TINFO_clifford;
-}
-
-clifford::clifford(exvector * vp) : inherited(indexed::unknown, vp)
-{
- debugmsg("clifford constructor from exvector *", LOGLEVEL_CONSTRUCT);
+ debugmsg("clifford constructor from unsigned char,exvector *", LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_clifford;
}
// archiving
//////////
-DEFAULT_ARCHIVING(clifford)
+clifford::clifford(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
+{
+ debugmsg("clifford constructor from archive_node", LOGLEVEL_CONSTRUCT);
+ unsigned rl;
+ n.find_unsigned("label", rl);
+ representation_label = rl;
+}
+
+void clifford::archive(archive_node &n) const
+{
+ inherited::archive(n);
+ n.add_unsigned("label", representation_label);
+}
+
+DEFAULT_UNARCHIVE(clifford)
DEFAULT_ARCHIVING(diracone)
DEFAULT_ARCHIVING(diracgamma)
+DEFAULT_ARCHIVING(diracgamma5)
//////////
// functions overriding virtual functions from bases classes
int clifford::compare_same_type(const basic & other) const
{
+ GINAC_ASSERT(other.tinfo() == TINFO_clifford);
+ const clifford &o = static_cast<const clifford &>(other);
+
+ if (representation_label != o.representation_label) {
+ // different representation label
+ return representation_label < o.representation_label ? -1 : 1;
+ }
+
return inherited::compare_same_type(other);
}
DEFAULT_COMPARE(diracone)
DEFAULT_COMPARE(diracgamma)
+DEFAULT_COMPARE(diracgamma5)
+
DEFAULT_PRINT(diracone, "ONE")
DEFAULT_PRINT(diracgamma, "gamma")
+DEFAULT_PRINT(diracgamma5, "gamma5")
/** Contraction of a gamma matrix with something else. */
bool diracgamma::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const
// gamma~mu*gamma.mu = dim*ONE
if (other - self == 1) {
*self = dim;
- *other = dirac_one();
+ *other = dirac_ONE();
return true;
// gamma~mu*gamma~alpha*gamma.mu = (2-dim)*gamma~alpha
} else if (other - self == 3
&& is_ex_of_type(self[1], clifford)
&& is_ex_of_type(self[2], clifford)) {
- *self = 4 * metric_tensor(self[1].op(1), self[2].op(1)) * dirac_one() + (dim - 4) * self[1] * self[2];
+ *self = 4 * metric_tensor(self[1].op(1), self[2].op(1)) * dirac_ONE() + (dim - 4) * self[1] * self[2];
self[1] = _ex1();
self[2] = _ex1();
*other = _ex1();
}
/** Perform automatic simplification on noncommutative product of clifford
- * objects. This removes superfluous ONEs. */
+ * objects. This removes superfluous ONEs, permutes gamma5's to the front
+ * and removes squares of gamma objects. */
ex clifford::simplify_ncmul(const exvector & v) const
{
exvector s;
s.reserve(v.size());
- exvector::const_iterator it = v.begin(), itend = v.end();
- while (it != itend) {
- if (!is_ex_of_type(it->op(0), diracone))
- s.push_back(*it);
- it++;
+ // Remove superfluous ONEs
+ exvector::const_iterator cit = v.begin(), citend = v.end();
+ while (cit != citend) {
+ if (!is_ex_of_type(cit->op(0), diracone))
+ s.push_back(*cit);
+ cit++;
+ }
+
+ bool something_changed = false;
+ int sign = 1;
+
+ // Anticommute gamma5's to the front
+ if (s.size() >= 2) {
+ exvector::iterator first = s.begin(), next_to_last = s.end() - 2;
+ while (true) {
+ exvector::iterator it = next_to_last;
+ while (true) {
+ exvector::iterator it2 = it + 1;
+ if (!is_ex_of_type(it->op(0), diracgamma5) && is_ex_of_type(it2->op(0), diracgamma5)) {
+ it->swap(*it2);
+ sign = -sign;
+ something_changed = true;
+ }
+ if (it == first)
+ break;
+ it--;
+ }
+ if (next_to_last == first)
+ break;
+ next_to_last--;
+ }
+ }
+
+ // Remove squares of gamma5
+ while (s.size() >= 2 && is_ex_of_type(s[0].op(0), diracgamma5) && is_ex_of_type(s[1].op(0), diracgamma5)) {
+ s.erase(s.begin(), s.begin() + 2);
+ something_changed = true;
+ }
+
+ // Remove equal adjacent gammas
+ if (s.size() >= 2) {
+ exvector::iterator it = s.begin(), itend = s.end() - 1;
+ while (it != itend) {
+ ex & a = it[0];
+ ex & b = it[1];
+ if (is_ex_of_type(a.op(0), diracgamma) && is_ex_of_type(b.op(0), diracgamma)) {
+ const ex & ia = a.op(1);
+ const ex & ib = b.op(1);
+ if (ia.is_equal(ib)) {
+ a = lorentz_g(ia, ib);
+ b = dirac_ONE();
+ something_changed = true;
+ }
+ }
+ it++;
+ }
}
if (s.size() == 0)
- return clifford(diracone());
- else if (s.size() == v.size())
- return simplified_ncmul(v);
+ return clifford(diracone()) * sign;
+ if (something_changed)
+ return nonsimplified_ncmul(s) * sign;
else
- return simplified_ncmul(s);
+ return simplified_ncmul(s) * sign;
}
ex clifford::thisexprseq(const exvector & v) const
{
- return clifford(v);
+ return clifford(representation_label, v);
}
ex clifford::thisexprseq(exvector * vp) const
{
- return clifford(vp);
+ return clifford(representation_label, vp);
}
//////////
// global functions
//////////
-ex dirac_one(void)
+ex dirac_ONE(unsigned char rl)
{
- return clifford(diracone());
+ return clifford(diracone(), rl);
}
-ex dirac_gamma(const ex & mu)
+ex dirac_gamma(const ex & mu, unsigned char rl)
{
if (!is_ex_of_type(mu, varidx))
throw(std::invalid_argument("index of Dirac gamma must be of type varidx"));
- return clifford(diracgamma(), mu);
+ return clifford(diracgamma(), mu, rl);
+}
+
+ex dirac_gamma5(unsigned char rl)
+{
+ return clifford(diracgamma5(), rl);
}
} // namespace GiNaC
/** This class holds an object representing an element of the Clifford
* algebra (the Dirac gamma matrices). These objects only carry Lorentz
- * indices. Spinor indices are hidden. */
+ * indices. Spinor indices are hidden. A representation label (an unsigned
+ * 8-bit integer) is used to distinguish elements from different Clifford
+ * algebras (objects with different labels commute). */
class clifford : public indexed
{
GINAC_DECLARE_REGISTERED_CLASS(clifford, indexed)
// other constructors
public:
- clifford(const ex & b);
- clifford(const ex & b, const ex & mu);
+ clifford(const ex & b, unsigned char rl = 0);
+ clifford(const ex & b, const ex & mu, unsigned char rl = 0);
// internal constructors
- clifford(const exvector & v, bool discardable = false);
- clifford(exvector * vp); // vp will be deleted
+ clifford(unsigned char rl, const exvector & v, bool discardable = false);
+ clifford(unsigned char rl, exvector * vp); // vp will be deleted
// functions overriding virtual functions from base classes
protected:
ex thisexprseq(const exvector & v) const;
ex thisexprseq(exvector * vp) const;
unsigned return_type(void) const { return return_types::noncommutative; }
- unsigned return_type_tinfo(void) const { return TINFO_clifford; }
+ unsigned return_type_tinfo(void) const { return TINFO_clifford + representation_label; }
+
+ // member variables
+private:
+ unsigned char representation_label; /**< Representation label to distinguish independent spin lines */
};
};
+/** This class represents the Dirac gamma5 object. */
+class diracgamma5 : public tensor
+{
+ GINAC_DECLARE_REGISTERED_CLASS(diracgamma5, tensor)
+
+ // functions overriding virtual functions from bases classes
+public:
+ void print(const print_context & c, unsigned level = 0) const;
+};
+
+
// global functions
inline const clifford &ex_to_clifford(const ex &e)
{
/** Create a Clifford unity object.
*
+ * @param rl Representation label
* @return newly constructed object */
-ex dirac_one(void);
+ex dirac_ONE(unsigned char rl = 0);
/** Create a Dirac gamma object.
*
* @param mu Index (must be of class varidx or a derived class)
+ * @param rl Representation label
* @return newly constructed gamma object */
-ex dirac_gamma(const ex & mu);
+ex dirac_gamma(const ex & mu, unsigned char rl = 0);
+
+/** Create a Dirac gamma5 object.
+ *
+ * @param rl Representation label
+ * @return newly constructed object */
+ex dirac_gamma5(unsigned char rl = 0);
} // namespace GiNaC
/** Construct object without any color index. This constructor is for
* internal use only. Use the color_ONE() function instead.
* @see color_ONE */
-color::color(const ex & b, unsigned rl) : inherited(b), representation_label(rl)
+color::color(const ex & b, unsigned char rl) : inherited(b), representation_label(rl)
{
- debugmsg("color constructor from ex,unsigned", LOGLEVEL_CONSTRUCT);
+ debugmsg("color constructor from ex,unsigned char", LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_color;
}
/** Construct object with one color index. This constructor is for internal
* use only. Use the color_T() function instead.
* @see color_T */
-color::color(const ex & b, const ex & i1, unsigned rl) : inherited(b, i1), representation_label(rl)
+color::color(const ex & b, const ex & i1, unsigned char rl) : inherited(b, i1), representation_label(rl)
{
- debugmsg("color constructor from ex,ex,unsigned", LOGLEVEL_CONSTRUCT);
+ debugmsg("color constructor from ex,ex,unsigned char", LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_color;
}
-color::color(unsigned rl, const exvector & v, bool discardable) : inherited(indexed::unknown, v, discardable), representation_label(rl)
+color::color(unsigned char rl, const exvector & v, bool discardable) : inherited(indexed::unknown, v, discardable), representation_label(rl)
{
- debugmsg("color constructor from unsigned,exvector", LOGLEVEL_CONSTRUCT);
+ debugmsg("color constructor from unsigned char,exvector", LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_color;
}
-color::color(unsigned rl, exvector * vp) : inherited(indexed::unknown, vp), representation_label(rl)
+color::color(unsigned char rl, exvector * vp) : inherited(indexed::unknown, vp), representation_label(rl)
{
- debugmsg("color constructor from unsigned,exvector *", LOGLEVEL_CONSTRUCT);
+ debugmsg("color constructor from unsigned char,exvector *", LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_color;
}
color::color(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
{
debugmsg("color constructor from archive_node", LOGLEVEL_CONSTRUCT);
- n.find_unsigned("representation", representation_label);
+ unsigned rl;
+ n.find_unsigned("label", rl);
+ representation_label = rl;
}
void color::archive(archive_node &n) const
{
inherited::archive(n);
- n.add_unsigned("representation", representation_label);
+ n.add_unsigned("label", representation_label);
}
DEFAULT_UNARCHIVE(color)
// global functions
//////////
-ex color_ONE(unsigned rl)
+ex color_ONE(unsigned char rl)
{
return color(su3one(), rl);
}
-ex color_T(const ex & a, unsigned rl)
+ex color_T(const ex & a, unsigned char rl)
{
if (!is_ex_of_type(a, idx))
throw(std::invalid_argument("indices of color_T must be of type idx"));
/** This class holds a generator T_a or the unity element of the Lie algebra
* of SU(3), as used for calculations in quantum chromodynamics. A
- * representation label (an unsigned integer) is used to distinguish
- * elements from different Lie algebra representations (only objects with
- * the same label "interact" with each other). These objects implement an
- * abstract representation of the group, not a specific matrix
- * representation. The indices used for color objects should not have a
- * variance. */
+ * representation label (an unsigned 8-bit integer) is used to distinguish
+ * elements from different Lie algebras (objects with different labels
+ * commute). These objects implement an abstract representation of the
+ * group, not a specific matrix representation. The indices used for color
+ * objects should not have a variance. */
class color : public indexed
{
GINAC_DECLARE_REGISTERED_CLASS(color, indexed)
// other constructors
public:
- color(const ex & b, unsigned rl = 0);
- color(const ex & b, const ex & i1, unsigned rl = 0);
+ color(const ex & b, unsigned char rl = 0);
+ color(const ex & b, const ex & i1, unsigned char rl = 0);
// internal constructors
- color(unsigned rl, const exvector & v, bool discardable = false);
- color(unsigned rl, exvector * vp); // vp will be deleted
+ color(unsigned char rl, const exvector & v, bool discardable = false);
+ color(unsigned char rl, exvector * vp); // vp will be deleted
// functions overriding virtual functions from base classes
protected:
ex thisexprseq(const exvector & v) const;
ex thisexprseq(exvector * vp) const;
unsigned return_type(void) const { return return_types::noncommutative; }
- unsigned return_type_tinfo(void) const { return TINFO_color; }
+ unsigned return_type_tinfo(void) const { return TINFO_color + representation_label; }
// member variables
private:
- unsigned representation_label; /**< Representation label to distinguish independent color matrices coming from separated fermion lines */
+ unsigned char representation_label; /**< Representation label to distinguish independent color matrices coming from separated fermion lines */
};
*
* @param rl Representation label
* @return newly constructed unity element */
-ex color_ONE(unsigned rl = 0);
+ex color_ONE(unsigned char rl = 0);
/** Create an su(3) generator.
*
* @param a Index
* @param rl Representation label
* @return newly constructed unity generator */
-ex color_T(const ex & a, unsigned rl = 0);
+ex color_T(const ex & a, unsigned char rl = 0);
/** Create an su(3) antisymmetric structure constant.
*
return bp->coeff(s,n);
}
-ex ex::collect(const ex & s) const
+ex ex::collect(const ex & s, bool distributed) const
{
GINAC_ASSERT(bp!=0);
- return bp->collect(s);
+ return bp->collect(s, distributed);
}
ex ex::eval(int level) const
ex to_rational(lst &repl_lst) const;
ex smod(const numeric &xi) const;
numeric max_coefficient(void) const;
- ex collect(const ex & s) const;
+ ex collect(const ex & s, bool distributed = false) const;
ex eval(int level = 0) const;
ex evalf(int level = 0) const;
ex diff(const symbol & s, unsigned nth = 1) const;
inline ex to_rational(const ex & thisex, lst & repl_lst)
{ return thisex.to_rational(repl_lst); }
-inline ex collect(const ex & thisex, const ex & s)
-{ return thisex.collect(s); }
+inline ex collect(const ex & thisex, const ex & s, bool distributed = false)
+{ return thisex.collect(s, distributed); }
inline ex eval(const ex & thisex, int level = 0)
{ return thisex.eval(level); }
}
/** Does nothing. */
-ex pseries::collect(const ex &s) const
+ex pseries::collect(const ex &s, bool distributed) const
{
return *this;
}
int degree(const ex &s) const;
int ldegree(const ex &s) const;
ex coeff(const ex &s, int n = 1) const;
- ex collect(const ex &s) const;
+ ex collect(const ex &s, bool distributed = false) const;
ex eval(int level=0) const;
ex evalf(int level=0) const;
ex series(const relational & r, int order, unsigned options = 0) const;
const unsigned TINFO_pseries = 0x000a0001U;
const unsigned TINFO_indexed = 0x000b0001U;
-const unsigned TINFO_color = 0x000b1001U;
-const unsigned TINFO_clifford = 0x000b1002U;
+const unsigned TINFO_color = 0x000b1000U;
+// reserved up to 0x000b10ffU
+// for color algebras (only used for return_type_tinfo())
+const unsigned TINFO_clifford = 0x000b1100U;
+// reserved up to 0x000b11ffU
+// for clifford algebras (only used for return_type_tinfo())
const unsigned TINFO_structure = 0x000c0001U;
// reserved up to 0x000cffffU
const unsigned TINFO_su3t = 0x000e1009U;
const unsigned TINFO_su3f = 0x000e100aU;
const unsigned TINFO_su3d = 0x000e100bU;
-const unsigned TINFO_diracgamma = 0x000e100cU;
-const unsigned TINFO_diracone = 0x000e100dU;
+const unsigned TINFO_diracone = 0x000e100cU;
+const unsigned TINFO_diracgamma = 0x000e100dU;
+const unsigned TINFO_diracgamma5 = 0x000e100eU;
} // namespace GiNaC