X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Fidx.cpp;h=90ac3a425a35bfd6b2158e60b40eb8e8d36277fb;hp=89373cc465ad4a770607cc98de49f55d95c563b5;hb=08af38543754f923653d73fd84625bb8a35b0136;hpb=094911eb78cacb6f2877a70c9ac74766df58ccea diff --git a/ginac/idx.cpp b/ginac/idx.cpp index 89373cc4..90ac3a42 100644 --- a/ginac/idx.cpp +++ b/ginac/idx.cpp @@ -25,6 +25,7 @@ #include "idx.h" #include "symbol.h" #include "lst.h" +#include "print.h" #include "archive.h" #include "utils.h" #include "debugmsg.h" @@ -33,6 +34,7 @@ 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 @@ -49,6 +51,12 @@ varidx::varidx() : covariant(false) tinfo_key = TINFO_varidx; } +spinidx::spinidx() : dotted(false) +{ + debugmsg("spinidx default constructor", LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_spinidx; +} + void idx::copy(const idx & other) { inherited::copy(other); @@ -62,17 +70,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 @@ -92,6 +98,12 @@ varidx::varidx(const ex & v, const ex & d, bool cov) : inherited(v, d), covarian tinfo_key = TINFO_varidx; } +spinidx::spinidx(const ex & v, const ex & d, bool cov, bool dot) : inherited(v, d, cov), dotted(dot) +{ + debugmsg("spinidx constructor from ex,ex,bool,bool", LOGLEVEL_CONSTRUCT); + tinfo_key = TINFO_spinidx; +} + ////////// // archiving ////////// @@ -109,14 +121,10 @@ varidx::varidx(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst n.find_bool("covariant", covariant); } -ex idx::unarchive(const archive_node &n, const lst &sym_lst) -{ - return (new idx(n, sym_lst))->setflag(status_flags::dynallocated); -} - -ex varidx::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 varidx(n, sym_lst))->setflag(status_flags::dynallocated); + debugmsg("spinidx constructor from archive_node", LOGLEVEL_CONSTRUCT); + n.find_bool("dotted", dotted); } void idx::archive(archive_node &n) const @@ -132,63 +140,116 @@ 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 ////////// -void idx::printraw(std::ostream & os) const +void idx::print(const print_context & c, unsigned level) const { - debugmsg("idx printraw", LOGLEVEL_PRINT); + debugmsg("idx print", LOGLEVEL_PRINT); - os << class_name() << "("; - value.printraw(os); - os << ",dim="; - dim.printraw(os); - os << ",hash=" << hashvalue << ",flags=" << flags; - 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_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 << "("; + value.print(c); + if (need_parens) + c.s << ")"; + } } -void idx::printtree(std::ostream & os, unsigned indent) const +void varidx::print(const print_context & c, unsigned level) const { - debugmsg("idx printtree",LOGLEVEL_PRINT); + debugmsg("varidx print", 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)) { -void idx::print(std::ostream & os, unsigned upper_precedence) const -{ - debugmsg("idx print", LOGLEVEL_PRINT); + 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); - os << "."; + } else { - 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_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 << "("; + value.print(c); + if (need_parens) + 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 << ")"; + debugmsg("spinidx print", LOGLEVEL_PRINT); + + 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 << "~"; + } + 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 << "}"; + } } bool idx::info(unsigned inf) const @@ -198,6 +259,18 @@ 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 @@ -226,6 +299,24 @@ int varidx::compare_same_type(const basic & other) const return 0; } +int spinidx::compare_same_type(const basic & other) const +{ + GINAC_ASSERT(is_of_type(other, spinidx)); + const spinidx &o = static_cast(other); + + int cmpval = inherited::compare_same_type(other); + if (cmpval) + return cmpval; + + // Check variance and dottedness last so dummy indices will end up next to each other + if (covariant != o.covariant) + return covariant ? -1 : 1; + if (dotted != o.dotted) + return dotted ? -1 : 1; + + return 0; +} + ex idx::subs(const lst & ls, const lst & lr) const { GINAC_ASSERT(ls.nops() == lr.nops()); @@ -241,6 +332,7 @@ 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); } } @@ -252,6 +344,7 @@ ex idx::subs(const lst & ls, const lst & lr) const 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); } @@ -286,6 +379,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 ////////// @@ -298,6 +403,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 ////////// @@ -321,4 +443,90 @@ bool is_dummy_pair(const ex & e1, const ex & e2) 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++; + } +} + + +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_idx(*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); + sort_index_vector(v); + + // 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_idx(*last).is_symbolic()) + out_free.push_back(*last); + } + last = it++; + } + if (ex_to_idx(*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