X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Fidx.cpp;h=63d29971bff122f3e34e40ba9a6eb866acbd7717;hp=89373cc465ad4a770607cc98de49f55d95c563b5;hb=319edd89b3a1062a23a659416db7aa9117df3a94;hpb=094911eb78cacb6f2877a70c9ac74766df58ccea diff --git a/ginac/idx.cpp b/ginac/idx.cpp index 89373cc4..63d29971 100644 --- a/ginac/idx.cpp +++ b/ginac/idx.cpp @@ -3,7 +3,7 @@ * Implementation of GiNaC's indices. */ /* - * GiNaC Copyright (C) 1999-2001 Johannes Gutenberg University Mainz, Germany + * GiNaC Copyright (C) 1999-2002 Johannes Gutenberg University Mainz, Germany * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,35 +20,39 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include #include "idx.h" #include "symbol.h" #include "lst.h" +#include "relational.h" +#include "print.h" #include "archive.h" #include "utils.h" -#include "debugmsg.h" namespace GiNaC { GINAC_IMPLEMENT_REGISTERED_CLASS(idx, basic) GINAC_IMPLEMENT_REGISTERED_CLASS(varidx, idx) +GINAC_IMPLEMENT_REGISTERED_CLASS(spinidx, varidx) ////////// -// default constructor, destructor, copy constructor assignment operator and helpers +// default ctor, dtor, copy ctor, assignment operator and helpers ////////// -idx::idx() : inherited(TINFO_idx) -{ - debugmsg("idx default constructor", LOGLEVEL_CONSTRUCT); -} +idx::idx() : inherited(TINFO_idx) {} varidx::varidx() : covariant(false) { - debugmsg("varidx default constructor", LOGLEVEL_CONSTRUCT); tinfo_key = TINFO_varidx; } +spinidx::spinidx() : dotted(false) +{ + tinfo_key = TINFO_spinidx; +} + void idx::copy(const idx & other) { inherited::copy(other); @@ -62,17 +66,15 @@ void varidx::copy(const varidx & other) covariant = other.covariant; } -void idx::destroy(bool call_parent) +void spinidx::copy(const spinidx & other) { - if (call_parent) - inherited::destroy(call_parent); + inherited::copy(other); + dotted = other.dotted; } -void varidx::destroy(bool call_parent) -{ - if (call_parent) - inherited::destroy(call_parent); -} +DEFAULT_DESTROY(idx) +DEFAULT_DESTROY(varidx) +DEFAULT_DESTROY(spinidx) ////////// // other constructors @@ -80,7 +82,6 @@ void varidx::destroy(bool call_parent) idx::idx(const ex & v, const ex & d) : inherited(TINFO_idx), value(v), dim(d) { - debugmsg("idx constructor from ex,ex", LOGLEVEL_CONSTRUCT); if (is_dim_numeric()) if (!dim.info(info_flags::posint)) throw(std::invalid_argument("dimension of space must be a positive integer")); @@ -88,35 +89,32 @@ idx::idx(const ex & v, const ex & d) : inherited(TINFO_idx), value(v), dim(d) varidx::varidx(const ex & v, const ex & d, bool cov) : inherited(v, d), covariant(cov) { - debugmsg("varidx constructor from ex,ex,bool", LOGLEVEL_CONSTRUCT); tinfo_key = TINFO_varidx; } +spinidx::spinidx(const ex & v, const ex & d, bool cov, bool dot) : inherited(v, d, cov), dotted(dot) +{ + tinfo_key = TINFO_spinidx; +} + ////////// // archiving ////////// idx::idx(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) { - debugmsg("idx constructor from archive_node", LOGLEVEL_CONSTRUCT); n.find_ex("value", value, sym_lst); n.find_ex("dim", dim, sym_lst); } varidx::varidx(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) { - debugmsg("varidx constructor from archive_node", LOGLEVEL_CONSTRUCT); n.find_bool("covariant", covariant); } -ex idx::unarchive(const archive_node &n, const lst &sym_lst) +spinidx::spinidx(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) { - return (new idx(n, sym_lst))->setflag(status_flags::dynallocated); -} - -ex varidx::unarchive(const archive_node &n, const lst &sym_lst) -{ - return (new varidx(n, sym_lst))->setflag(status_flags::dynallocated); + n.find_bool("dotted", dotted); } void idx::archive(archive_node &n) const @@ -132,63 +130,124 @@ void varidx::archive(archive_node &n) const n.add_bool("covariant", covariant); } -////////// -// functions overriding virtual functions from bases classes -////////// - -void idx::printraw(std::ostream & os) const +void spinidx::archive(archive_node &n) const { - debugmsg("idx printraw", LOGLEVEL_PRINT); - - os << class_name() << "("; - value.printraw(os); - os << ",dim="; - dim.printraw(os); - os << ",hash=" << hashvalue << ",flags=" << flags; - os << ")"; + inherited::archive(n); + n.add_bool("dotted", dotted); } -void idx::printtree(std::ostream & os, unsigned indent) const -{ - debugmsg("idx printtree",LOGLEVEL_PRINT); +DEFAULT_UNARCHIVE(idx) +DEFAULT_UNARCHIVE(varidx) +DEFAULT_UNARCHIVE(spinidx) - os << std::string(indent, ' ') << "type=" << class_name(); - value.printtree(os, indent + delta_indent); - os << std::string(indent, ' '); - os << ", hash=" << hashvalue - << " (0x" << std::hex << hashvalue << std::dec << ")" - << ", flags=" << flags << std::endl; -} +////////// +// functions overriding virtual functions from base classes +////////// -void idx::print(std::ostream & os, unsigned upper_precedence) const +void idx::print(const print_context & c, unsigned level) const { - debugmsg("idx print", LOGLEVEL_PRINT); - - os << "."; - - bool need_parens = !(is_ex_exactly_of_type(value, numeric) || is_ex_of_type(value, symbol)); - if (need_parens) - os << "("; - os << value; - if (need_parens) - os << ")"; + if (is_of_type(c, print_tree)) { + + c.s << std::string(level, ' ') << class_name() + << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec + << std::endl; + unsigned delta_indent = static_cast(c).delta_indent; + value.print(c, level + delta_indent); + dim.print(c, level + delta_indent); + + } else { + + if (is_a(c)) + 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 << "("; + value.print(c); + if (need_parens) + c.s << ")"; + if (is_a(c)) + c.s << "}"; + } } -void varidx::print(std::ostream & os, unsigned upper_precedence) const +void varidx::print(const print_context & c, unsigned level) const { - debugmsg("varidx print", LOGLEVEL_PRINT); - - if (covariant) - os << "."; - else - os << "~"; + if (is_of_type(c, print_tree)) { + + c.s << std::string(level, ' ') << class_name() + << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec + << (covariant ? ", covariant" : ", contravariant") + << std::endl; + unsigned delta_indent = static_cast(c).delta_indent; + value.print(c, level + delta_indent); + dim.print(c, level + delta_indent); + + } else { + if (is_a(c)) + c.s << "{"; + else { + 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 << "("; + value.print(c); + if (need_parens) + c.s << ")"; + if (is_a(c)) + c.s << "}"; + } +} - bool need_parens = !(is_ex_exactly_of_type(value, numeric) || is_ex_of_type(value, symbol)); - if (need_parens) - os << "("; - os << value; - if (need_parens) - os << ")"; +void spinidx::print(const print_context & c, unsigned level) const +{ + if (is_of_type(c, print_tree)) { + + c.s << std::string(level, ' ') << class_name() + << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec + << (covariant ? ", covariant" : ", contravariant") + << (dotted ? ", dotted" : ", undotted") + << std::endl; + unsigned delta_indent = static_cast(c).delta_indent; + value.print(c, level + delta_indent); + dim.print(c, level + delta_indent); + + } else { + + bool is_tex = is_of_type(c, print_latex); + if (is_tex) { + if (covariant) + c.s << "_{"; + else + c.s << "^{"; + } else { + if (covariant) + c.s << "."; + else + c.s << "~"; + } + if (dotted) { + if (is_tex) + c.s << "\\dot{"; + else + c.s << "*"; + } + bool need_parens = !(is_ex_exactly_of_type(value, numeric) || is_ex_of_type(value, symbol)); + if (need_parens) + c.s << "("; + value.print(c); + if (need_parens) + c.s << ")"; + if (is_tex && dotted) + c.s << "}"; + if (is_tex) + c.s << "}"; + } } bool idx::info(unsigned inf) const @@ -198,11 +257,23 @@ bool idx::info(unsigned inf) const return inherited::info(inf); } +unsigned idx::nops() const +{ + // don't count the dimension as that is not really a sub-expression + return 1; +} + +ex & idx::let_op(int i) +{ + GINAC_ASSERT(i == 0); + return value; +} + /** Returns order relation between two indices of the same type. The order * must be such that dummy indices lie next to each other. */ int idx::compare_same_type(const basic & other) const { - GINAC_ASSERT(is_of_type(other, idx)); + GINAC_ASSERT(is_a(other)); const idx &o = static_cast(other); int cmpval = value.compare(o.value); @@ -211,9 +282,17 @@ int idx::compare_same_type(const basic & other) const return dim.compare(o.dim); } +bool idx::match_same_type(const basic & other) const +{ + GINAC_ASSERT(is_a(other)); + const idx &o = static_cast(other); + + return dim.is_equal(o.dim); +} + int varidx::compare_same_type(const basic & other) const { - GINAC_ASSERT(is_of_type(other, varidx)); + GINAC_ASSERT(is_a(other)); const varidx &o = static_cast(other); int cmpval = inherited::compare_same_type(other); @@ -226,13 +305,56 @@ int varidx::compare_same_type(const basic & other) const return 0; } -ex idx::subs(const lst & ls, const lst & lr) const +bool varidx::match_same_type(const basic & other) const +{ + GINAC_ASSERT(is_a(other)); + const varidx &o = static_cast(other); + + if (covariant != o.covariant) + return false; + return inherited::match_same_type(other); +} + +int spinidx::compare_same_type(const basic & other) const +{ + GINAC_ASSERT(is_a(other)); + const spinidx &o = static_cast(other); + + // Check dottedness first so dummy indices will end up next to each other + if (dotted != o.dotted) + return dotted ? -1 : 1; + + int cmpval = inherited::compare_same_type(other); + if (cmpval) + return cmpval; + + return 0; +} + +bool spinidx::match_same_type(const basic & other) const +{ + GINAC_ASSERT(is_a(other)); + const spinidx &o = static_cast(other); + + if (dotted != o.dotted) + return false; + return inherited::match_same_type(other); +} + +/** By default, basic::evalf would evaluate the index value but we don't want + * a.1 to become a.(1.0). */ +ex idx::evalf(int level) const +{ + return *this; +} + +ex idx::subs(const lst & ls, const lst & lr, bool no_pattern) const { GINAC_ASSERT(ls.nops() == lr.nops()); // First look for index substitutions for (unsigned i=0; i(ls.op(i)))) { // Substitution index->index if (is_ex_of_type(lr.op(i), idx)) @@ -241,20 +363,30 @@ ex idx::subs(const lst & ls, const lst & lr) const // Otherwise substitute value idx *i_copy = static_cast(duplicate()); i_copy->value = lr.op(i); + i_copy->clearflag(status_flags::hash_calculated); return i_copy->setflag(status_flags::dynallocated); } } // None, substitute objects in value (not in dimension) - const ex &subsed_value = value.subs(ls, lr); + const ex &subsed_value = value.subs(ls, lr, no_pattern); if (are_ex_trivially_equal(value, subsed_value)) return *this; idx *i_copy = static_cast(duplicate()); i_copy->value = subsed_value; + i_copy->clearflag(status_flags::hash_calculated); return i_copy->setflag(status_flags::dynallocated); } +/** Implementation of ex::diff() for an index always returns 0. + * + * @see ex::diff */ +ex idx::derivative(const symbol & s) const +{ + return _ex0; +} + ////////// // new virtual functions ////////// @@ -263,7 +395,8 @@ bool idx::is_dummy_pair_same_type(const basic & other) const { const idx &o = static_cast(other); - // Only pure symbols form dummy pairs, "2n+1" doesn't + // Only pure symbols form dummy pairs, numeric indices and expressions + // like "2n+1" don't if (!is_ex_of_type(value, symbol)) return false; @@ -271,8 +404,12 @@ bool idx::is_dummy_pair_same_type(const basic & other) const if (!value.is_equal(o.value)) return false; - // Also the dimension - return dim.is_equal(o.dim); + // Dimensions need not be equal but must be comparable (so we can + // determine the minimum dimension of contractions) + if (dim.is_equal(o.dim)) + return true; + + return (dim < o.dim || dim > o.dim || (is_a(dim) && is_a(o.dim)) || (is_a(dim) && is_a(o.dim))); } bool varidx::is_dummy_pair_same_type(const basic & other) const @@ -286,10 +423,40 @@ bool varidx::is_dummy_pair_same_type(const basic & other) const return inherited::is_dummy_pair_same_type(other); } +bool spinidx::is_dummy_pair_same_type(const basic & other) const +{ + const spinidx &o = static_cast(other); + + // Dottedness must be the same + if (dotted != o.dotted) + return false; + + return inherited::is_dummy_pair_same_type(other); +} + + ////////// // non-virtual functions ////////// +ex idx::replace_dim(const ex & new_dim) const +{ + idx *i_copy = static_cast(duplicate()); + i_copy->dim = new_dim; + i_copy->clearflag(status_flags::hash_calculated); + return i_copy->setflag(status_flags::dynallocated); +} + +ex idx::minimal_dim(const idx & other) const +{ + if (dim.is_equal(other.dim) || dim < other.dim || (is_a(dim) && is_a(other.dim))) + return dim; + else if (dim > other.dim || (is_a(dim) && is_a(other.dim))) + return other.dim; + else + throw (std::runtime_error("idx::minimal_dim: index dimensions cannot be ordered")); +} + ex varidx::toggle_variance(void) const { varidx *i_copy = static_cast(duplicate()); @@ -298,6 +465,23 @@ ex varidx::toggle_variance(void) const return i_copy->setflag(status_flags::dynallocated); } +ex spinidx::toggle_dot(void) const +{ + spinidx *i_copy = static_cast(duplicate()); + i_copy->dotted = !i_copy->dotted; + i_copy->clearflag(status_flags::hash_calculated); + return i_copy->setflag(status_flags::dynallocated); +} + +ex spinidx::toggle_variance_dot(void) const +{ + spinidx *i_copy = static_cast(duplicate()); + i_copy->covariant = !i_copy->covariant; + i_copy->dotted = !i_copy->dotted; + i_copy->clearflag(status_flags::hash_calculated); + return i_copy->setflag(status_flags::dynallocated); +} + ////////// // global functions ////////// @@ -318,7 +502,47 @@ bool is_dummy_pair(const ex & e1, const ex & e2) if (!is_ex_of_type(e1, idx) || !is_ex_of_type(e2, idx)) return false; - return is_dummy_pair(ex_to_idx(e1), ex_to_idx(e2)); + return is_dummy_pair(ex_to(e1), ex_to(e2)); +} + +void find_free_and_dummy(exvector::const_iterator it, exvector::const_iterator itend, exvector & out_free, exvector & out_dummy) +{ + out_free.clear(); + out_dummy.clear(); + + // No indices? Then do nothing + if (it == itend) + return; + + // Only one index? Then it is a free one if it's not numeric + if (itend - it == 1) { + if (ex_to(*it).is_symbolic()) + out_free.push_back(*it); + return; + } + + // Sort index vector. This will cause dummy indices come to lie next + // to each other (because the sort order is defined to guarantee this). + exvector v(it, itend); + shaker_sort(v.begin(), v.end(), ex_is_less(), ex_swap()); + + // Find dummy pairs and free indices + it = v.begin(); itend = v.end(); + exvector::const_iterator last = it++; + while (it != itend) { + if (is_dummy_pair(*it, *last)) { + out_dummy.push_back(*last); + it++; + if (it == itend) + return; + } else { + if (!it->is_equal(*last) && ex_to(*last).is_symbolic()) + out_free.push_back(*last); + } + last = it++; + } + if (ex_to(*last).is_symbolic()) + out_free.push_back(*last); } } // namespace GiNaC