From: Christian Bauer Date: Fri, 4 May 2001 23:55:36 +0000 (+0000) Subject: - symbols can have a LaTeX name, e.g. symbol s("s", "\\sigma"); X-Git-Tag: release_0-8-3~24 X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=commitdiff_plain;h=f7a07ae7330a3543bb00aa7b659e2624d6c440c7 - symbols can have a LaTeX name, e.g. symbol s("s", "\\sigma"); - LaTeX output of indexed objects and tensors is much nicer - simplify_indexed() can do arbitrary contractions in Dirac gamma strings - constructing expressions like (x * dirac_ONE() + dirac_ONE()) * dirac_gamma(mu) resulted in an exception because mul::simplify_ncmul() wasn't implemented (maybe afrink didn't anticipate that an implementation would really be needed...) --- diff --git a/ginac/clifford.cpp b/ginac/clifford.cpp index 8a8bfe09..5a69cfd5 100644 --- a/ginac/clifford.cpp +++ b/ginac/clifford.cpp @@ -139,9 +139,9 @@ DEFAULT_COMPARE(diracone) DEFAULT_COMPARE(diracgamma) DEFAULT_COMPARE(diracgamma5) -DEFAULT_PRINT(diracone, "ONE") -DEFAULT_PRINT(diracgamma, "gamma") -DEFAULT_PRINT(diracgamma5, "gamma5") +DEFAULT_PRINT_LATEX(diracone, "ONE", "\\mathbb{1}") +DEFAULT_PRINT_LATEX(diracgamma, "gamma", "\\gamma") +DEFAULT_PRINT_LATEX(diracgamma5, "gamma5", "{\\gamma^5}") /** Contraction of a gamma matrix with something else. */ bool diracgamma::contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const @@ -151,34 +151,35 @@ bool diracgamma::contract_with(exvector::iterator self, exvector::iterator other GINAC_ASSERT(is_ex_of_type(self->op(0), diracgamma)); unsigned char rl = ex_to_clifford(*self).get_representation_label(); - if (is_ex_of_type(other->op(0), diracgamma)) { + if (is_ex_of_type(*other, clifford)) { ex dim = ex_to_idx(self->op(1)).get_dim(); - // gamma~mu*gamma.mu = dim*ONE + // gamma~mu gamma.mu = dim ONE if (other - self == 1) { *self = dim; *other = dirac_ONE(rl); return true; - // gamma~mu*gamma~alpha*gamma.mu = (2-dim)*gamma~alpha + // gamma~mu gamma~alpha gamma.mu = (2-dim) gamma~alpha } else if (other - self == 2 && is_ex_of_type(self[1], clifford)) { *self = 2 - dim; *other = _ex1(); return true; - // gamma~mu*gamma~alpha*gamma~beta*gamma.mu = 4*g~alpha~beta+(dim-4)*gamam~alpha*gamma~beta + // gamma~mu gamma~alpha gamma~beta gamma.mu = 4 g~alpha~beta + (dim-4) gamam~alpha gamma~beta } 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(rl) + (dim - 4) * self[1] * self[2]; + *self = 4 * lorentz_g(self[1].op(1), self[2].op(1)) * dirac_ONE(rl) + (dim - 4) * self[1] * self[2]; self[1] = _ex1(); self[2] = _ex1(); *other = _ex1(); return true; - // gamma~mu*gamma~alpha*gamma~beta*gamma~delta*gamma.mu = -2*gamma~delta*gamma~beta*gamma~alpha+(4-dim)*gamma~alpha*gamma~beta*gamma~delta +#if 0 + // gamma~mu gamma~alpha gamma~beta gamma~delta gamma.mu = -2 gamma~delta gamma~beta gamma~alpha + (4-dim) gamma~alpha gamma~beta gamma~delta } else if (other - self == 4 && is_ex_of_type(self[1], clifford) && is_ex_of_type(self[2], clifford) @@ -189,6 +190,30 @@ bool diracgamma::contract_with(exvector::iterator self, exvector::iterator other self[3] = _ex1(); *other = _ex1(); return true; +#endif + + // gamma~mu S gamma~alpha gamma.mu = 2 gamma~alpha S - gamma~mu S gamma.mu gamma~alpha + // (commutate contracted indices towards each other, simplify_indexed() + // will re-expand and re-run the simplification) + } else { + exvector::iterator it = self + 1, next_to_last = other - 1; + while (it != other) { + if (!is_ex_of_type(*it, clifford)) + return false; + it++; + } + + it = self + 1; + ex S = _ex1(); + while (it != next_to_last) { + S *= *it; + *it++ = _ex1(); + } + + *self = 2 * (*next_to_last) * S - (*self) * S * (*other) * (*next_to_last); + *next_to_last = _ex1(); + *other = _ex1(); + return true; } } @@ -364,12 +389,12 @@ ex dirac_trace(const ex & e, unsigned char rl) if (has_gamma5) { // Trace of gamma5 * odd number of gammas and trace of - // gamma5 * gamma_mu * gamma_nu are zero + // gamma5 * gamma.mu * gamma.nu are zero if ((num & 1) == 0 || num == 3) return _ex0(); // Tr gamma5 S_2k = - // epsilon0123_mu1_mu2_mu3_mu4 * Tr gamma_mu1 gamma_mu2 gamma_mu3 gamma_mu4 S_2k + // epsilon0123.mu1.mu2.mu3.mu4 * Tr gamma.mu1 gamma.mu2 gamma.mu3 gamma.mu4 S_2k ex dim = ex_to_idx(e.op(1).op(1)).get_dim(); varidx mu1((new symbol)->setflag(status_flags::dynallocated), dim), mu2((new symbol)->setflag(status_flags::dynallocated), dim), @@ -393,17 +418,17 @@ ex dirac_trace(const ex & e, unsigned char rl) if ((num & 1) == 1) return _ex0(); - // Tr gamma_mu gamma_nu = 4 g_mu_nu + // Tr gamma.mu gamma.nu = 4 g.mu.nu if (num == 2) return 4 * lorentz_g(e.op(0).op(1), e.op(1).op(1)); // Traces of 4 or more gammas are computed recursively: - // Tr gamma_mu1 gamma_mu2 ... gamma_mun = - // + eta_mu1_mu2 * Tr gamma_mu3 ... gamma_mun - // - eta_mu1_mu3 * Tr gamma_mu2 gamma_mu4 ... gamma_mun - // + eta_mu1_mu4 * Tr gamma_mu3 gamma_mu3 gamma_mu5 ... gamma_mun + // Tr gamma.mu1 gamma.mu2 ... gamma.mun = + // + g.mu1.mu2 * Tr gamma.mu3 ... gamma.mun + // - g.mu1.mu3 * Tr gamma.mu2 gamma.mu4 ... gamma.mun + // + g.mu1.mu4 * Tr gamma.mu3 gamma.mu3 gamma.mu5 ... gamma.mun // - ... - // + eta_mu1_mun * Tr gamma_mu2 ... gamma_mu(n-1) + // + g.mu1.mun * Tr gamma.mu2 ... gamma.mu(n-1) exvector v(num - 2); int sign = 1; const ex &ix1 = e.op(0).op(1); diff --git a/ginac/color.cpp b/ginac/color.cpp index e36c1cbe..77cf89c4 100644 --- a/ginac/color.cpp +++ b/ginac/color.cpp @@ -145,7 +145,7 @@ DEFAULT_COMPARE(su3t) DEFAULT_COMPARE(su3f) DEFAULT_COMPARE(su3d) -DEFAULT_PRINT(su3one, "ONE") +DEFAULT_PRINT_LATEX(su3one, "ONE", "\\mathbb{1}") DEFAULT_PRINT(su3t, "T") DEFAULT_PRINT(su3f, "f") DEFAULT_PRINT(su3d, "d") diff --git a/ginac/constant.cpp b/ginac/constant.cpp index c056a96a..e86a2964 100644 --- a/ginac/constant.cpp +++ b/ginac/constant.cpp @@ -41,7 +41,7 @@ GINAC_IMPLEMENT_REGISTERED_CLASS(constant, basic) // public -constant::constant() : basic(TINFO_constant), name(""), ef(0), number(0), serial(next_serial++) +constant::constant() : basic(TINFO_constant), ef(0), number(0), serial(next_serial++) { debugmsg("constant default ctor",LOGLEVEL_CONSTRUCT); } @@ -53,6 +53,7 @@ void constant::copy(const constant & other) { inherited::copy(other); name = other.name; + TeX_name = other.TeX_name; serial = other.serial; ef = other.ef; if (other.number != 0) @@ -74,17 +75,25 @@ void constant::destroy(bool call_parent) // public -constant::constant(const std::string & initname, evalffunctype efun) +constant::constant(const std::string & initname, evalffunctype efun, const std::string & texname) : basic(TINFO_constant), name(initname), ef(efun), number(0), serial(next_serial++) { debugmsg("constant ctor from string, function",LOGLEVEL_CONSTRUCT); + if (texname.empty()) + TeX_name = "\\mbox{" + name + "}"; + else + TeX_name = texname; setflag(status_flags::evaluated); } -constant::constant(const std::string & initname, const numeric & initnumber) +constant::constant(const std::string & initname, const numeric & initnumber, const std::string & texname) : basic(TINFO_constant), name(initname), ef(0), number(new numeric(initnumber)), serial(next_serial++) { debugmsg("constant ctor from string, numeric",LOGLEVEL_CONSTRUCT); + if (texname.empty()) + TeX_name = "\\mbox{" + name + "}"; + else + TeX_name = texname; setflag(status_flags::evaluated); } @@ -135,16 +144,9 @@ void constant::print(const print_context & c, unsigned level) const c.s << std::string(level, ' ') << name << " (" << class_name() << ")" << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec << std::endl; - } else if (is_of_type(c, print_latex)) { - if (name=="Pi") - c.s << "\\pi"; - else if (name=="Euler") - c.s << "\\gamma_E"; - else if (name=="Catalan") - c.s << "G"; - else - c.s << "\\mbox{"+name+"}"; - } else + } else if (is_of_type(c, print_latex)) + c.s << TeX_name; + else c.s << name; } @@ -237,13 +239,13 @@ unsigned constant::next_serial = 0; ////////// /** Pi. (3.14159...) Diverts straight into CLN for evalf(). */ -const constant Pi("Pi", PiEvalf); +const constant Pi("Pi", PiEvalf, "\\pi"); /** Euler's constant. (0.57721...) Sometimes called Euler-Mascheroni constant. * Diverts straight into CLN for evalf(). */ -const constant Euler("Euler", EulerEvalf); +const constant Euler("Euler", EulerEvalf, "\\gamma_E"); /** Catalan's constant. (0.91597...) Diverts straight into CLN for evalf(). */ -const constant Catalan("Catalan", CatalanEvalf); +const constant Catalan("Catalan", CatalanEvalf, "G"); } // namespace GiNaC diff --git a/ginac/constant.h b/ginac/constant.h index fdf06615..bf85b382 100644 --- a/ginac/constant.h +++ b/ginac/constant.h @@ -43,8 +43,8 @@ class constant : public basic // other ctors public: - constant(const std::string & initname, evalffunctype efun = 0); - constant(const std::string & initname, const numeric & initnumber); + constant(const std::string & initname, evalffunctype efun = 0, const std::string & texname = std::string()); + constant(const std::string & initname, const numeric & initnumber, const std::string & texname = std::string()); // functions overriding virtual functions from bases classes public: @@ -67,10 +67,11 @@ protected: // member variables private: - std::string name; ///< printname of this constant + std::string name; ///< printname of this constant + std::string TeX_name; ///< LaTeX name evalffunctype ef; - numeric *number; ///< numerical value this constant evalf()s to - unsigned serial; ///< unique serial number for comparison + numeric *number; ///< numerical value this constant evalf()s to + unsigned serial; ///< unique serial number for comparison static unsigned next_serial; }; diff --git a/ginac/idx.cpp b/ginac/idx.cpp index 9f31a9ad..44427a6a 100644 --- a/ginac/idx.cpp +++ b/ginac/idx.cpp @@ -136,11 +136,12 @@ void idx::print(const print_context & c, unsigned level) const } else { - c.s << "."; + if (!is_of_type(c, print_latex)) + c.s << "."; bool need_parens = !(is_ex_exactly_of_type(value, numeric) || is_ex_of_type(value, symbol)); if (need_parens) c.s << "("; - c.s << value; + value.print(c); if (need_parens) c.s << ")"; } @@ -162,14 +163,16 @@ void varidx::print(const print_context & c, unsigned level) const } else { - if (covariant) - c.s << "."; - else - c.s << "~"; + if (!is_of_type(c, print_latex)) { + if (covariant) + c.s << "."; + else + c.s << "~"; + } bool need_parens = !(is_ex_exactly_of_type(value, numeric) || is_ex_of_type(value, symbol)); if (need_parens) c.s << "("; - c.s << value; + value.print(c); if (need_parens) c.s << ")"; } diff --git a/ginac/indexed.cpp b/ginac/indexed.cpp index 6fbe40b9..3c7005e2 100644 --- a/ginac/indexed.cpp +++ b/ginac/indexed.cpp @@ -199,14 +199,20 @@ void indexed::print(const print_context & c, unsigned level) const } else { + bool is_tex = is_of_type(c, print_latex); const ex & base = seq[0]; bool need_parens = is_ex_exactly_of_type(base, add) || is_ex_exactly_of_type(base, mul) - || is_ex_exactly_of_type(base, ncmul) || is_ex_exactly_of_type(base, power); + || is_ex_exactly_of_type(base, ncmul) || is_ex_exactly_of_type(base, power) + || is_ex_of_type(base, indexed); + if (is_tex) + c.s << "{"; if (need_parens) c.s << "("; base.print(c); if (need_parens) c.s << ")"; + if (is_tex) + c.s << "}"; printindices(c, level); } } @@ -409,10 +415,40 @@ ex indexed::expand(unsigned options) const void indexed::printindices(const print_context & c, unsigned level) const { if (seq.size() > 1) { + exvector::const_iterator it=seq.begin() + 1, itend = seq.end(); - while (it != itend) { - it->print(c, level); - it++; + + if (is_of_type(c, print_latex)) { + + // TeX output: group by variance + bool first = true; + bool covariant = true; + + while (it != itend) { + bool cur_covariant = (is_ex_of_type(*it, varidx) ? ex_to_varidx(*it).is_covariant() : true); + if (first || cur_covariant != covariant) { + if (!first) + c.s << "}"; + covariant = cur_covariant; + if (covariant) + c.s << "_{"; + else + c.s << "^{"; + } + it->print(c, level); + c.s << " "; + first = false; + it++; + } + c.s << "}"; + + } else { + + // Ordinary output + while (it != itend) { + it->print(c, level); + it++; + } } } } @@ -631,11 +667,12 @@ try_again: if (contracted) { contraction_done: if (is_ex_exactly_of_type(*it1, add) || is_ex_exactly_of_type(*it2, add) - || is_ex_exactly_of_type(*it1, mul) || is_ex_exactly_of_type(*it2, mul)) { + || is_ex_exactly_of_type(*it1, mul) || is_ex_exactly_of_type(*it2, mul) + || is_ex_exactly_of_type(*it1, ncmul) || is_ex_exactly_of_type(*it2, ncmul)) { // One of the factors became a sum or product: // re-expand expression and run again - ex r = non_commutative ? ex(ncmul(v)) : ex(mul(v)); + ex r = (non_commutative ? ex(ncmul(v)) : ex(mul(v))); return simplify_indexed(r, free_indices, sp); } diff --git a/ginac/mul.cpp b/ginac/mul.cpp index 27451f6b..75f74b4b 100644 --- a/ginac/mul.cpp +++ b/ginac/mul.cpp @@ -405,7 +405,16 @@ ex mul::evalf(int level) const ex mul::simplify_ncmul(const exvector & v) const { - throw(std::logic_error("mul::simplify_ncmul() should never have been called!")); + if (seq.size()==0) { + return inherited::simplify_ncmul(v); + } + + // Find first noncommutative element and call its simplify_ncmul() + for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { + if (cit->rest.return_type() == return_types::noncommutative) + return cit->rest.simplify_ncmul(v); + } + return inherited::simplify_ncmul(v); } // protected diff --git a/ginac/symbol.cpp b/ginac/symbol.cpp index bebb8776..29d46bbf 100644 --- a/ginac/symbol.cpp +++ b/ginac/symbol.cpp @@ -41,7 +41,7 @@ GINAC_IMPLEMENT_REGISTERED_CLASS_NO_CTORS(symbol, basic) symbol::symbol() : inherited(TINFO_symbol), serial(next_serial++) { debugmsg("symbol default ctor", LOGLEVEL_CONSTRUCT); - name = autoname_prefix()+ToString(serial); + name = TeX_name = autoname_prefix()+ToString(serial); asexinfop = new assigned_ex_info; setflag(status_flags::evaluated | status_flags::expanded); } @@ -51,6 +51,7 @@ void symbol::copy(const symbol & other) { inherited::copy(other); name = other.name; + TeX_name = other.TeX_name; serial = other.serial; asexinfop = other.asexinfop; ++asexinfop->refcount; @@ -80,6 +81,17 @@ symbol::symbol(const std::string & initname) : inherited(TINFO_symbol) { debugmsg("symbol ctor from string", LOGLEVEL_CONSTRUCT); name = initname; + TeX_name = default_TeX_name(); + serial = next_serial++; + asexinfop = new assigned_ex_info; + setflag(status_flags::evaluated | status_flags::expanded); +} + +symbol::symbol(const std::string & initname, const std::string & texname) : inherited(TINFO_symbol) +{ + debugmsg("symbol ctor from string", LOGLEVEL_CONSTRUCT); + name = initname; + TeX_name = texname; serial = next_serial++; asexinfop = new assigned_ex_info; setflag(status_flags::evaluated | status_flags::expanded); @@ -96,6 +108,8 @@ symbol::symbol(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst serial = next_serial++; if (!(n.find_string("name", name))) name = autoname_prefix() + ToString(serial); + if (!(n.find_string("TeXname", TeX_name))) + TeX_name = default_TeX_name(); asexinfop = new assigned_ex_info; setflag(status_flags::evaluated); } @@ -118,6 +132,8 @@ void symbol::archive(archive_node &n) const { inherited::archive(n); n.add_string("name", name); + if (TeX_name != default_TeX_name()) + n.add_string("TeX_name", TeX_name); } ////////// @@ -143,25 +159,9 @@ void symbol::print(const print_context & c, unsigned level) const << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec << std::endl; - } else if (is_of_type(c, print_latex)) { - if (name=="alpha" || name=="beta" || name=="gamma" - || name=="delta" || name=="epsilon" || name=="varepsilon" - || name=="zeta" || name=="eta" || name=="theta" - || name=="vartheta" || name=="iota" || name=="kappa" - || name=="lambda" || name=="mu" || name=="nu" - || name=="xi" || name=="omicron" || name=="pi" - || name=="varpi" || name=="rho" || name=="varrho" - || name=="sigma" || name=="varsigma" || name=="tau" - || name=="upsilon" || name=="phi" || name=="varphix" - || name=="chi" || name=="psi" || name=="omega" - || name=="Gamma" || name=="Delta" || name=="Theta" - || name=="Lambda" || name=="Xi" || name=="Pi" - || name=="Sigma" || name=="Upsilon" || name=="Phi" - || name=="Psi" || name=="Omega") - c.s << "\\" << name; - else - c.s << name; - } else + } else if (is_of_type(c, print_latex)) + c.s << TeX_name; + else c.s << name; } @@ -313,6 +313,28 @@ std::string & symbol::autoname_prefix(void) return *s; } +/** Return default TeX name for symbol. This recognizes some greek letters. */ +std::string symbol::default_TeX_name(void) const +{ + if (name=="alpha" || name=="beta" || name=="gamma" + || name=="delta" || name=="epsilon" || name=="varepsilon" + || name=="zeta" || name=="eta" || name=="theta" + || name=="vartheta" || name=="iota" || name=="kappa" + || name=="lambda" || name=="mu" || name=="nu" + || name=="xi" || name=="omicron" || name=="pi" + || name=="varpi" || name=="rho" || name=="varrho" + || name=="sigma" || name=="varsigma" || name=="tau" + || name=="upsilon" || name=="phi" || name=="varphix" + || name=="chi" || name=="psi" || name=="omega" + || name=="Gamma" || name=="Delta" || name=="Theta" + || name=="Lambda" || name=="Xi" || name=="Pi" + || name=="Sigma" || name=="Upsilon" || name=="Phi" + || name=="Psi" || name=="Omega") + return "\\" + name; + else + return name; +} + ////////// // static member variables ////////// diff --git a/ginac/symbol.h b/ginac/symbol.h index 1f494cf2..aec27aee 100644 --- a/ginac/symbol.h +++ b/ginac/symbol.h @@ -68,6 +68,7 @@ protected: // other ctors public: explicit symbol(const std::string & initname); + explicit symbol(const std::string & initname, const std::string & texname); // functions overriding virtual functions from base classes public: @@ -99,13 +100,15 @@ public: std::string get_name(void) const { return name; } private: std::string & autoname_prefix(void); + std::string default_TeX_name(void) const; // member variables protected: assigned_ex_info * asexinfop; ///< ptr to assigned expression, deprecated - unsigned serial; ///< unique serial number for comparison - std::string name; ///< printname of this symbol + unsigned serial; ///< unique serial number for comparison + std::string name; ///< printname of this symbol + std::string TeX_name; ///< LaTeX name of this symbol private: static unsigned next_serial; }; diff --git a/ginac/tensor.cpp b/ginac/tensor.cpp index d16bbfce..928c6568 100644 --- a/ginac/tensor.cpp +++ b/ginac/tensor.cpp @@ -162,10 +162,10 @@ int tensepsilon::compare_same_type(const basic & other) const return inherited::compare_same_type(other); } -DEFAULT_PRINT(tensdelta, "delta") +DEFAULT_PRINT_LATEX(tensdelta, "delta", "\\delta") DEFAULT_PRINT(tensmetric, "g") -DEFAULT_PRINT(minkmetric, "eta") -DEFAULT_PRINT(tensepsilon, "eps") +DEFAULT_PRINT_LATEX(minkmetric, "eta", "\\eta") +DEFAULT_PRINT_LATEX(tensepsilon, "eps", "\\epsilon") /** Automatic symbolic evaluation of an indexed delta tensor. */ ex tensdelta::eval_indexed(const basic & i) const diff --git a/ginac/utils.h b/ginac/utils.h index c2a5f232..79719feb 100644 --- a/ginac/utils.h +++ b/ginac/utils.h @@ -301,6 +301,18 @@ void classname::print(const print_context & c, unsigned level) const \ c.s << text; \ } +#define DEFAULT_PRINT_LATEX(classname, text, latex) \ +void classname::print(const print_context & c, unsigned level) const \ +{ \ + debugmsg(#classname " print", LOGLEVEL_PRINT); \ + if (is_of_type(c, print_tree)) \ + inherited::print(c, level); \ + else if (is_of_type(c, print_latex)) \ + c.s << latex; \ + else \ + c.s << text; \ +} + } // namespace GiNaC #endif // ndef __GINAC_UTILS_H__