#ifndef __rpack_num_h__ #define __rpack_num_h__ #include namespace MultiArrayHelper { using namespace MultiArrayTools; template size_t mkTotalDim() { return Index1::totalDim(); } template size_t mkTotalDim() { return Index1::totalDim() * mkTotalDim(); } template struct SubProp { static constexpr size_t ISSTATIC = RangeType::ISSTATIC & SubProp::ISSTATIC; static constexpr size_t SIZE = RangeType::SIZE * SubProp::SIZE; }; template <> struct SubProp { static constexpr size_t ISSTATIC = 1; static constexpr size_t SIZE = 1; }; template inline size_t getStepSize(const Index& ii, std::intptr_t j); template struct RPackNum { template static void initBlockSizes(std::array& bs, std::tuple...>& ip) { std::get(bs) = RPackNum::blockSize(ip); RPackNum::initBlockSizes(bs, ip); } template static inline void pp(std::tuple...>& ip) { auto& si = *std::get(ip); if(si.last()){ si = 0; RPackNum::pp(ip); } else { ++si; } } template static inline int pp(std::tuple...>& ip, std::array& bs, std::intptr_t idxPtrNum) { auto& siPtr = std::get(ip); //VCHECK(siPtr.id()); if(reinterpret_cast(siPtr.get()) == idxPtrNum){ return RPackNum::pp(ip, bs, idxPtrNum); } else { int tmp = siPtr->pp(idxPtrNum); if(siPtr->pos() == siPtr->max()){ (*siPtr) = 0; return RPackNum::pp(ip, bs, idxPtrNum) - siPtr->max() + 1; } else { return tmp * std::get(bs); } } } template static inline void mm(std::tuple...>& ip) { auto& si = *std::get(ip); if(si.first()){ si = si.max() - 1; RPackNum::mm(ip); } else { --si; } } // !!!! template static inline int mm(std::tuple...>& ip, std::array& bs, std::intptr_t idxPtrNum) { auto& siPtr = std::get(ip); if(reinterpret_cast(siPtr.get()) == idxPtrNum){ return std::get(bs) + RPackNum::mm(ip, bs, idxPtrNum); } else { if(siPtr->first()){ (*siPtr) = siPtr->max() - 1; return RPackNum::mm(ip, bs, idxPtrNum) - siPtr->max() + 1; } else { return siPtr->mm(idxPtrNum); } } } template static size_t getSize(const RangeTuple& rt) { return std::get(rt)->size() * RPackNum::getSize(rt); } template static void getMetaPos(MetaType& target, const IndexPack& source) { std::get(target) = std::get(source)->meta(); RPackNum::getMetaPos(target, source); } template static void setMeta(IndexPack& target, const MetaType& source) { std::get(target)->at( std::get(source) ); RPackNum::setMeta(target, source); } template static void setIndexPack(IndexPack& iPack, size_t pos) { auto& i = *std::get(iPack).get(); const size_t ownPos = pos % i.max(); i = ownPos; RPackNum::setIndexPack(iPack, (pos - ownPos) / i.max() ); } template static void construct(std::tuple...>& ip, const MRange& range) { typedef typename std::remove_reference())>::type SubRangeType; typedef typename SubRangeType::IndexType SubIndexType; typedef typename std::remove_reference(ip).get())>::type TypeFromIndexPack; static_assert(std::is_same::value, "inconsiśtent types"); std::get(ip) = std::shared_ptr( new SubIndexType( range.template getPtr() ) ); RPackNum::construct(ip, range); } template static void copyInst(std::tuple...>& ip, const IndexType& ind) { std::get(ip) = ind.template getPtr() ; RPackNum::copyInst(ip, ind); } template static inline size_t makePos(const std::tuple...>& iPtrTup) { //const auto& idx = *std::get(iPtrTup); return std::get(iPtrTup)->pos() + RPackNum::makePos(iPtrTup) * std::get(iPtrTup)->max(); } template static inline size_t makePos(const std::tuple...>& iPtrTup, const std::array& blockSize) { return RPackNum::makePos(iPtrTup, blockSize) + std::get(iPtrTup)->pos() * std::get(blockSize); } template static void swapIndices(Pack& ipack, const std::shared_ptr& nind, const std::shared_ptr&... ninds) { std::get::value-N-1>(ipack) = nind; RPackNum::swapIndices(ipack, ninds...); } template static size_t blockSize(const std::tuple...>& pack) { return std::get(pack)->max() * RPackNum::blockSize(pack); } template static void RangesToVec(const std::tuple...>& rst, std::vector >& v) { v[N] = std::get(rst); RPackNum::RangesToVec(rst, v); } template static void printIndex(const std::tuple...>& ip, size_t offset) { std::get(ip)->print(offset); RPackNum::printIndex(ip, offset); } template static void checkDefaultable() { static_assert( Range::defaultable, "not defaultable" ); RPackNum::template checkDefaultable(); } template static auto mkFor(const IndexPack& ipack, Exprs exs) -> decltype(std::get::value-N-1>(ipack) ->ifor( RPackNum::mkFor(ipack, exs) ) ) { return std::get::value-N-1>(ipack) ->ifor( RPackNum::mkFor(ipack, exs) ); } template static auto mkForh(const IndexPack& ipack, Exprs exs) -> decltype(std::get::value-N-1>(ipack) ->iforh( RPackNum::mkForh(ipack, exs) ) ) { return std::get::value-N-1>(ipack) ->iforh( RPackNum::mkForh(ipack, exs) ); } template static inline void getStepSizeX(const Index& ii, std::intptr_t j, size_t& ss, size_t& sx) { //constexpr size_t DIM = Index::sDim(); const auto& ni = ii.template get(); const size_t max = ni.max(); const size_t tmp = getStepSize(ni, j); //VCHECK(tmp); ss += tmp * sx; //VCHECK(ss); sx *= max; RPackNum::getStepSizeX(ii, j, ss, sx); } }; template<> struct RPackNum<0> { template static void initBlockSizes(std::array& bs, std::tuple...>& ip) { std::get<0>(bs) = RPackNum::blockSize(ip); } template static inline void pp(std::tuple...>& ip) { auto& si = *std::get<0>(ip); ++si; } template static inline int pp(std::tuple...>& ip, std::array& bs, std::intptr_t idxPtrNum) { auto& siPtr = std::get<0>(ip); if(reinterpret_cast(siPtr.get()) == idxPtrNum){ return std::get<0>(bs); } else { int tmp = siPtr->pp(idxPtrNum); return tmp * std::get<1>(bs); } } template static inline void mm(std::tuple...>& ip) { auto& si = *std::get<0>(ip); --si; } template static inline int mm(std::tuple...>& ip, std::array& bs, std::intptr_t idxPtrNum) { auto& siPtr = std::get<0>(ip); if(reinterpret_cast(siPtr.get()) == idxPtrNum){ return std::get<0>(bs); //return 1; } else { return siPtr->mm(idxPtrNum); } } template static size_t getSize(const RangeTuple& rt) { return std::get<0>(rt)->size(); } template static void getMetaPos(MetaType& target, const IndexPack& source) { std::get<0>(target) = std::get<0>(source)->meta(); } template static void setMeta(IndexPack& target, const MetaType& source) { std::get<0>(target)->at( std::get<0>( source ) ); } template static void setIndexPack(IndexPack& iPack, size_t pos) { auto& i = *std::get<0>(iPack); const size_t ownPos = pos % i.max(); i = ownPos; } template static void construct(std::tuple...>& ip, const MRange& range) { typedef typename std::remove_reference())>::type SubRangeType; typedef typename SubRangeType::IndexType SubIndexType; typedef typename std::remove_reference(ip).get())>::type TypeFromIndexPack; static_assert(std::is_same::value, "inconsiśtent types"); std::get<0>(ip) = std::shared_ptr( new SubIndexType( range.template getPtr<0>() ) ); } template static void copyInst(std::tuple...>& ip, const IndexType& ind) { std::get<0>(ip) = ind.template getPtr<0>(); } template static inline size_t makePos(const std::tuple...>& iPtrTup) { return std::get<0>(iPtrTup)->pos(); } template static inline size_t makePos(const std::tuple...>& iPtrTup, const std::array& blockSize) { return std::get<0>(iPtrTup)->pos() * std::get<1>(blockSize); } template static void swapIndices(Pack& ipack, const std::shared_ptr& nind) { std::get::value-1>(ipack) = nind; } template static size_t blockSize(const std::tuple...>& pack) { return 1; } template static void RangesToVec(const std::tuple...>& rst, std::vector >& v) { v[0] = std::get<0>(rst); } template static void printIndex(const std::tuple...>& ip, size_t offset) { std::get<0>(ip)->print(offset); } template static void checkDefaultable() { static_assert( Range::defaultable, "not defaultable" ); } template static auto mkFor(const IndexPack& ipack, Exprs exs) -> decltype(std::get::value-1>(ipack) ->ifor(exs) ) { return std::get::value-1>(ipack)->ifor(exs); } template static auto mkForh(const IndexPack& ipack, Exprs exs) -> decltype(std::get::value-1>(ipack) ->iforh(exs) ) { return std::get::value-1>(ipack)->iforh(exs); } template static inline void getStepSizeX(const Index& ii, std::intptr_t j, size_t& ss, size_t& sx) { //constexpr size_t DIM = Index::sDim(); const auto& ni = ii.template get<0>(); const size_t max = ni.max(); const size_t tmp = getStepSize(ni, j); //VCHECK(tmp); ss += tmp * sx; //VCHECK(ss); sx *= max; } }; template struct SSG { template static inline size_t getStepSize(const Index& ii, std::intptr_t j) { size_t ss = 0; size_t sx = 1; constexpr size_t DIM = Index::sDim(); RPackNum::getStepSizeX(ii, j, ss, sx); return ss; } }; template <> struct SSG { template static inline size_t getStepSize(const Index& ii, std::intptr_t j) { //VCHECK(ii.ptrNum()); //VCHECK(j); return ii.ptrNum() == j ? 1 : 0; } }; template inline size_t getStepSize(const Index& ii, std::intptr_t j) { constexpr IndexType IT = Index::sType(); return SSG::getStepSize(ii, j); } } // end namespace MultiArrayHelper #endif