#include "multi_range.h" namespace MultiArrayTools { /******************* * MultiIndexBase * *******************/ namespace { template struct IndexGetter { template static IndefinitIndexBase& getIndex(MultiIndex& in, size_t n) { if(n == N){ return in.getIndex(); } else { return getIndex(in, n); } } }; template <> struct IndexGetter<0> { template static IndefinitIndexBase& getIndex(MultiIndex& in, size_t n) { return in.getIndex<0>(); } }; template struct Evaluation { template static size_t evaluate(const MultiIndex& index) { const auto& subIndex = index.getIndex(0); return Evaluation::evaluate(index) * subIndex.size() + subIndex.pos(); } }; template <> struct Evaluation<0> { template static size_t evaluate(const MultiIndex& index) { const auto& subIndex = index.getIndex<0>(0); return subIndex.pos(); } }; template inline void plus(MultiIndex& index, size_t digit, int num) { IndefinitIndexBase& si = index.getIndex(digit); si.setPos( si.pos() + num ); size_t oor = si.outOfRange(); if(oor and digit != MultiIndex::mult - 1){ plus(index, digit + 1, 1); plus(index, digit, oor - si.max()); } } template struct TupleNamer { template static void nameTuple(IndexPack& iPack, Name& name) { std::get(iPack).name(name.get(N)); nameTuple(iPack, name); } }; template <> struct TupleNamer<0> { template static void nameTuple(IndexPack& iPack, Name& name) { std::get<0>(iPack).name(name.get(0)); } }; } template MultiIndex::MultiIndex(Indices&&... inds) : mIPack(std::make_tuple(inds...)) {} template MultiIndex& MultiIndex::operator++() { setPos( IIB::pos() + 1 ); plus(*this, 0, 1); return *this; } template MultiIndex& MultiIndex::operator--() { setPos( IIB::pos() - 1 ); plus(*this, 0, -1); return *this; } template MultiIndex& MultiIndex::operator+=(int n) { setPos( IIB::pos() + n ); plus(*this, 0, n); return *this; } template MultiIndex& MultiIndex::operator-=(int n) { setPos( IIB::pos() - n ); plus(*this, 0, 0-n); return *this; } template size_t MultiIndex::evaluate(const MultiIndex& in) const { return Evaluation::evaluate(in); } template void MultiIndex::name(const Name& nm) { name(nm.own()); if(nm.size() >= sizeof...(Indices)){ TupleNamer::nameTuple(mIPack, nm); } else { Name nm2 = nm; nm2.autoName(sizeof...(Indices)); TupleNamer::nameTuple(mIPack, nm); } } template size_t MultiIndex::dim() const { size_t res = 1; for(size_t i = 0; i != sizeof...(Indices); ++i){ res *= getIndex(i).dim(); } return res; } template bool MultiIndex::link(IndefinitIndexBase* toLink) { if(toLink->rangeType() != IIB::rangeType() and toLink->name() == name()){ // throw !! } if(toLink->rangeType() == IIB::rangeType() and toLink->name() == name()){ if(IIB::mLinked == toLink){ return true; // dont link twice the same } else if(IIB::mLinked == nullptr){ IIB::mLinked = toLink; return true; } else { return IIB::mLinked->link(toLink); } } else { return linkLower(toLink); } } template template auto MultiIndex::getIndex(size_t x) -> decltype(std::get(MultiIndex::IndexPack())) { return std::get(mIPack); } template template auto MultiIndex::getIndex(size_t x) const -> decltype(std::get(MultiIndex::IndexPack())) { return std::get(mIPack); } template IndefinitIndexBase& MultiIndex::get(size_t n) { if(n >= sizeof...(Indices)){ // throw !! } MultiIndex* t = this; return IndexGetter::getIndex(*t, n); } template const IndefinitIndexBase& MultiIndex::get(size_t n) const { if(n >= sizeof...(Indices)){ // throw !! } MultiIndex* t = this; return IndexGetter::getIndex(*t, n); } template bool MultiIndex::linkLower(IndefinitIndexBase* toLink) { bool res = false; for(size_t i = 0; i != sizeof...(Indices); ++i){ res |= getIndex(i).link(toLink); } return res; } template void MultiIndex::linkTo(IndefinitIndexBase* target) { target->link(this); for(size_t i = 0; i != sizeof...(Indices); ++i){ getIndex(i).linkTo(target); } } /****************** * MultiRange * ******************/ template template auto MultiRange::get() -> decltype( std::get(MultiRange::SpaceType()) ) { return std::get(mSpace); } template template auto MultiRange::get() const -> decltype( std::get(MultiRange::SpaceType()) ) { return std::get(mSpace); } template MultiIndex MultiRange::begin() const { return MultiIndex(/*!!!!!!*/); } template MultiIndex MultiRange::end() const { return MultiIndex(/*!!!!!!*/); } }