#include "IndexIterator.hh" #include "properties/IndexInherit.hh" using namespace cadabra; index_iterator::index_iterator(const Properties& k) : iterator_base(), properties(&k) { } index_iterator index_iterator::create(const Properties& k, const iterator_base& other) { index_iterator ret(k); ret.node=other.node; ret.halt=other; ret.walk=other; ret.roof=other; ret.halt.skip_children(); ++ret.halt; ret.operator++(); return ret; } index_iterator::index_iterator(const index_iterator& other) : iterator_base(other.node), halt(other.halt), walk(other.walk), roof(other.roof), properties(other.properties) { } bool index_iterator::operator!=(const index_iterator& other) const { if(other.node!=this->node) return true; else return false; } bool index_iterator::operator==(const index_iterator& other) const { if(other.node==this->node) return true; else return false; } // \bar{\prod{A}{B}} 's indices are undefined, as \bar inherits // the Product property of \prod. So the worst-case scenario is // of the type \bar{\hat{A_\mu}} in which the objects with Inherit // property are strictly nested. However, we can also have // things like \bar{\diff{\diff{A_\mu}_{\nu}}_{\rho}}, for which // we have to collect indices at multiple levels. /* \bar{?}::Accent. \bar{\diff{\diff{A_\mu}_{\nu}}_{\rho}}; @indexlist(%); \diff{\diff{A_{\mu}}_{\nu}}_{\rho}; @indexlist(%); \diff{\diff{A}_{\nu}}_{\rho}; @indexlist(%); \bar{\psi_{m}} * \Gamma_{q n p} * \psi_{m} * H_{n p q}; @indexlist(%); q*A_{d c b a}; @indexlist(%); A_{d c b a}*q; @indexlist(%); \diff{\phi}_s A_\mu \diff{\phi}_t; @indexlist(%); \Gamma_{a b c}; @indexlist(%); \diff{\sin(x_\mu)}_{\nu}; @indexlist(%); \equals{A_{i}}{B_{i j} Z_{j}}; @indexlist(%); */ index_iterator& index_iterator::operator+=(unsigned int num) { while(num != 0) { --num; operator++(); } return *this; } index_iterator& index_iterator::operator++() { assert(this->node!=0); // Increment the iterator. As long as we are at an inherit // node, keep incrementing. As long as the parent does not inherit, // and as long as we are not at the top node, // skip children. As long as we are not at an index, keep incrementing. const IndexInherit *this_inh=0, *parent_inh=0; while(walk!=halt) { this_inh=properties->get(walk); if(this_inh==0 && (walk!=roof && walk.node->parent!=0)) { parent_inh=properties->get(walk.node->parent); if(parent_inh==0) walk.skip_children(); } ++walk; if(walk!=halt) if(walk->is_index()) break; // if(this_inh==false && walk->is_index()) // break; } if(walk==halt) { this->node=0; return *this; } else { this->node=walk.node; } return *this; } index_iterator index_iterator::begin(const Properties& properties, const iterator_base& it, int offset) { index_iterator ret=index_iterator::create(properties,it); if(offset>0) ret+=offset; return ret; } index_iterator index_iterator::end(const Properties& properties, const iterator_base& it) { index_iterator tmp=create(properties, it); tmp.node=0; return tmp; } index_iterator& index_iterator::operator=(const index_iterator& other) { iterator_base::operator=(other); halt=other.halt; walk=other.walk; roof=other.roof; properties=other.properties; return *this; } //size_t number_of_indices(const Properties& pr, Ex::iterator it) // { // unsigned int res=0; // index_iterator indit=index_iterator::begin(pr, it); // while(indit!=index_iterator::end(pr, it)) { // ++res; // ++indit; // } // return res; // }