X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Fidx.cpp;h=d704cbdd276dac1f9306d71148004b981f4b6e61;hp=89373cc465ad4a770607cc98de49f55d95c563b5;hb=17ee7a6d0c88cd9b33db41fbca2973177b9a8a2f;hpb=094911eb78cacb6f2877a70c9ac74766df58ccea diff --git a/ginac/idx.cpp b/ginac/idx.cpp index 89373cc4..d704cbdd 100644 --- a/ginac/idx.cpp +++ b/ginac/idx.cpp @@ -21,10 +21,12 @@ */ #include +#include #include "idx.h" #include "symbol.h" #include "lst.h" +#include "print.h" #include "archive.h" #include "utils.h" #include "debugmsg.h" @@ -33,6 +35,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 +52,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 +71,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 +99,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 +122,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 +141,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 +// functions overriding virtual functions from base 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 +260,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 @@ -211,6 +285,14 @@ 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_of_type(other, idx)); + 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)); @@ -226,7 +308,50 @@ 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_of_type(other, varidx)); + 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_of_type(other, spinidx)); + 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_of_type(other, spinidx)); + 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()); @@ -241,20 +366,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 ////////// @@ -286,6 +421,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 +445,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 +482,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