// -*- C++ -*- #ifndef __pack_num_h__ #define __pack_num_h__ #include //#include #include #include #include "base_def.h" #include "xfor/exttype.h" namespace MultiArrayHelper { template struct Application { template static inline auto apply(std::shared_ptr f, Ts... as) -> decltype((*f)(as...)) { return (*f)(as...); } }; template <> struct Application { template static inline auto apply(std::shared_ptr f, Ts... as) -> decltype(OpFunction::apply(as...)) { return OpFunction::apply(as...); } }; template struct PackNum { template static auto mkElemOperation(const MA& ma, const ITuple& ituple, IPtrs... iptrs) -> decltype(PackNum::mkElemOperation(ma, ituple, std::get(ituple), iptrs...)) { return PackNum::mkElemOperation(ma, ituple, std::get(ituple), iptrs...); } template static void printTuple(std::ostream& out, const std::tuple& tp) { out << std::get(tp) << ", "; PackNum::printTuple(out, tp); } template static auto mkSteps(std::intptr_t ii, const std::tuple& otp) -> decltype(PackNum::mkSteps(ii, otp).extend( std::get(otp).rootSteps(ii)) ) { return PackNum::mkSteps(ii, otp).extend( std::get(otp).rootSteps(ii)); } template static void mkExt(std::array& out, const std::array& siar, const OpClass& second) { std::get(out) = second.rootSteps( std::get(siar) ); PackNum::mkExt(out, siar, second); } template static inline T mkOpExpr(std::shared_ptr f, const ETuple& pos, const OpTuple& ops, const Args&... args) { typedef typename std::remove_reference(ops))>::type NextOpType; static_assert(LAST > NextOpType::SIZE, "inconsistent array positions"); static constexpr size_t NEXT = LAST - NextOpType::SIZE; typedef decltype(std::get(ops).get(Getter::template getX( pos ))) ArgT; return PackNum::template mkOpExpr ( f, pos, ops, std::get(ops).get(Getter::template getX( pos )), args...); } template static auto mkLoop( const OpTuple& ot, Expr exp ) -> decltype(std::get(ot).loop( PackNum::mkLoop(ot,exp) )) { return std::get(ot).loop( PackNum::mkLoop(ot,exp) ); } template static void mkSliceBlocks(std::array& blocks, const ContainerIndex& index, const Op& op, size_t total = 1) { const size_t tmp = op.rootSteps(reinterpret_cast ( index.template getPtr().get() ) ) .val(); std::get(blocks) = tmp; PackNum::template mkSliceBlocks(blocks, index, op, total * tmp); } template static bool checkIfSameInstance(const std::tuple...>& rtp1, const std::tuple...>& rtp2) { return std::get(rtp1).get() == std::get(rtp2).get() and PackNum::checkIfSameInstance(rtp1,rtp2); } template static inline auto mkMapOp(const MA& ma, const ITuple& itp, const std::shared_ptr&... inds) -> decltype(PackNum::mkMapOp(ma, itp, std::get(itp), inds...)) { return PackNum::mkMapOp(ma, itp, std::get(itp), inds...); } template static inline void setOpPos(const OpTuple& ot, const ETuple& et) { typedef typename std::remove_reference(ot))>::type NextOpType; static_assert(LAST > NextOpType::SIZE, "inconsistent array positions"); static constexpr size_t NEXT = LAST - NextOpType::SIZE; std::get( ot ).set( Getter::template getX( et ) ); PackNum::template setOpPos(ot, et); } }; template<> struct PackNum<0> { template static auto mkElemOperation(const MA& ma, const ITuple& ituple, IPtrs... iptrs) -> decltype(ma(iptrs...)) { return ma(iptrs...); } template static void printTuple(std::ostream& out, const std::tuple& tp) { out << std::get(tp); } template static auto mkSteps(std::intptr_t ii, const std::tuple& otp) -> decltype(std::get<0>(otp).rootSteps(ii)) { return std::get<0>(otp).rootSteps(ii); } template static void mkExt(std::array& out, const std::array& siar, const OpClass& second) { std::get<0>(out) = second.rootSteps( std::get<0>(siar) ); } template static inline T mkOpExpr(std::shared_ptr f, const ETuple& pos, const OpTuple& ops, const Args&... args) { typedef typename std::remove_reference(ops))>::type NextOpType; static constexpr size_t NEXT = LAST - NextOpType::SIZE; static_assert(NEXT == 0, "inconsistent array positions"); typedef decltype(std::get<0>(ops).get(Getter<0>::template getX( pos ))) ArgT; return Application::template apply(f, std::get<0>(ops).get(Getter<0>::template getX( pos )), args...); //return OpFunction::apply(std::get<0>(ops).get(Getter<0>::template getX( pos )), args...); } template static auto mkLoop( const OpTuple& ot, Expr exp ) -> decltype(std::get<0>(ot).loop( exp )) { return std::get<0>(ot).loop( exp ); } template static void mkSliceBlocks(std::array& blocks, const ContainerIndex& index, const Op& op, size_t total = 1) { const size_t tmp = op.rootSteps(reinterpret_cast ( index.template getPtr<0>().get() ) ) .val(); std::get<1>(blocks) = tmp; std::get<0>(blocks) = total * tmp; // this is not correct, but not used so far ... !!! } template static bool checkIfSameInstance(const std::tuple...>& rtp1, const std::tuple...>& rtp2) { return std::get<0>(rtp1).get() == std::get<0>(rtp2).get(); } template static inline auto mkMapOp(const MA& ma, const ITuple& itp, const std::shared_ptr&... inds) -> decltype(ma.exec(std::get<0>(itp), inds...)) { return ma.exec(std::get<0>(itp), inds...); } template static inline void setOpPos(const OpTuple& ot, const ETuple& et) { typedef typename std::remove_reference(et))>::type NextOpType; static_assert(LAST > NextOpType::SIZE, "inconsistent array positions"); static constexpr size_t NEXT = LAST - NextOpType::SIZE; std::get<0>( ot ).set( Getter::template getX( et ) ); } }; } // end namespace MultiArrayHelper #endif