X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Fidx.cpp;h=160bc378f563550e1b5491ca272704954ca77428;hp=d8e8e70c6368b4a3f6116f1cfbe0d58be1f6a384;hb=bb2670b06c0f98ef1a4fcb193826d65363a302dd;hpb=61b8ecb02c8212efbc15f59face8a9c620dc823c diff --git a/ginac/idx.cpp b/ginac/idx.cpp index d8e8e70c..160bc378 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,38 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include #include "idx.h" #include "symbol.h" #include "lst.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,8 +65,15 @@ void varidx::copy(const varidx & other) covariant = other.covariant; } +void spinidx::copy(const spinidx & other) +{ + inherited::copy(other); + dotted = other.dotted; +} + DEFAULT_DESTROY(idx) DEFAULT_DESTROY(varidx) +DEFAULT_DESTROY(spinidx) ////////// // other constructors @@ -71,7 +81,6 @@ DEFAULT_DESTROY(varidx) 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")); @@ -79,27 +88,34 @@ 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); } +spinidx::spinidx(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) +{ + n.find_bool("dotted", dotted); +} + void idx::archive(archive_node &n) const { inherited::archive(n); @@ -113,66 +129,127 @@ void varidx::archive(archive_node &n) const n.add_bool("covariant", covariant); } +void spinidx::archive(archive_node &n) const +{ + inherited::archive(n); + n.add_bool("dotted", dotted); +} + DEFAULT_UNARCHIVE(idx) DEFAULT_UNARCHIVE(varidx) +DEFAULT_UNARCHIVE(spinidx) ////////// -// functions overriding virtual functions from bases classes +// functions overriding virtual functions from base classes ////////// -void idx::printraw(std::ostream & os) const -{ - debugmsg("idx printraw", LOGLEVEL_PRINT); - - os << class_name() << "("; - value.printraw(os); - os << ",dim="; - dim.printraw(os); - os << ",hash=" << hashvalue << ",flags=" << flags; - os << ")"; -} - -void idx::printtree(std::ostream & os, unsigned indent) const +void idx::print(const print_context & c, unsigned level) const { - debugmsg("idx printtree",LOGLEVEL_PRINT); - - 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; + 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 idx::print(std::ostream & os, unsigned upper_precedence) const +void varidx::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 + << (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)) { + if (covariant) + c.s << "_{"; + else + 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 << "}"; + } } -void varidx::print(std::ostream & os, unsigned upper_precedence) const +void spinidx::print(const print_context & c, unsigned level) const { - debugmsg("varidx print", LOGLEVEL_PRINT); - - if (covariant) - os << "."; - else - 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 + << (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 @@ -182,11 +259,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); @@ -195,9 +284,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); @@ -210,13 +307,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)) @@ -225,20 +365,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 ////////// @@ -270,6 +420,18 @@ 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 ////////// @@ -282,6 +444,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 ////////// @@ -302,32 +481,9 @@ 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)); -} - -/** Bring a vector of indices into a canonic order. Dummy indices will lie - * next to each other after the sorting. */ -static void sort_index_vector(exvector &v) -{ - // Nothing to sort if less than 2 elements - if (v.size() < 2) - return; - - // Simple bubble sort algorithm should be sufficient for the small - // number of indices expected - exvector::iterator it1 = v.begin(), itend = v.end(), next_to_last_idx = itend - 1; - while (it1 != next_to_last_idx) { - exvector::iterator it2 = it1 + 1; - while (it2 != itend) { - if (it1->compare(*it2) > 0) - it1->swap(*it2); - it2++; - } - it1++; - } + 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(); @@ -339,7 +495,7 @@ void find_free_and_dummy(exvector::const_iterator it, exvector::const_iterator i // Only one index? Then it is a free one if it's not numeric if (itend - it == 1) { - if (ex_to_idx(*it).is_symbolic()) + if (ex_to(*it).is_symbolic()) out_free.push_back(*it); return; } @@ -347,7 +503,7 @@ void find_free_and_dummy(exvector::const_iterator it, exvector::const_iterator i // 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); - sort_index_vector(v); + shaker_sort(v.begin(), v.end(), ex_is_less(), ex_swap()); // Find dummy pairs and free indices it = v.begin(); itend = v.end(); @@ -359,36 +515,13 @@ void find_free_and_dummy(exvector::const_iterator it, exvector::const_iterator i if (it == itend) return; } else { - if (!it->is_equal(*last) && ex_to_idx(*last).is_symbolic()) + if (!it->is_equal(*last) && ex_to(*last).is_symbolic()) out_free.push_back(*last); } last = it++; } - if (ex_to_idx(*last).is_symbolic()) + if (ex_to(*last).is_symbolic()) out_free.push_back(*last); } -exvector index_set_difference(const exvector & set1, const exvector & set2) -{ - exvector ret; - - exvector::const_iterator ait = set1.begin(), aitend = set1.end(); - while (ait != aitend) { - exvector::const_iterator bit = set2.begin(), bitend = set2.end(); - bool found = false; - while (bit != bitend) { - if (ait->is_equal(*bit)) { - found = true; - break; - } - bit++; - } - if (!found) - ret.push_back(*ait); - ait++; - } - - return ret; -} - } // namespace GiNaC