cnorxz/src/xfor/xfor.h

120 lines
3.6 KiB
C
Raw Normal View History

2018-01-05 13:56:16 +01:00
#ifndef __xfor_h__
#define __xfor_h__
#include <cstdlib>
#include <memory>
2018-01-08 18:38:13 +01:00
#include <tuple>
2018-01-09 11:37:26 +01:00
#include "xfor/for_utils.h"
2018-01-05 13:56:16 +01:00
namespace MultiArrayHelper
{
2018-01-08 18:38:13 +01:00
template <class IndexClass, class Expr, class... Ops>
2018-01-05 13:56:16 +01:00
class For
{
public:
static size_t layer() { return typename Expr::layer() + 1; }
2018-01-05 13:56:16 +01:00
For(For&& in) = default;
For& operator=(For&& in) = default;
template <typename... Args>
2018-01-08 18:38:13 +01:00
For(const std::shared_ptr<IndexClass>& indPtr,
std::tuple<to_size_t<Ops>...>&& ext, const Args&... args);
2018-01-05 13:56:16 +01:00
2018-01-08 18:38:13 +01:00
For(const std::shared_ptr<IndexClass>& indPtr,
Expr&& expr, std::tuple<to_size_t<Ops>...>&& ext);
template <typename... Args>
For(IndexClass* indPtr,
std::tuple<to_size_t<Ops>...>&& ext, const Args&... args);
For(IndexClass* indPtr,
Expr&& expr, std::tuple<to_size_t<Ops>...>&& ext);
2018-01-08 18:38:13 +01:00
inline void operator()(size_t mlast, const std::tuple<to_size_t<Ops>...>& last) const;
inline void operator()(size_t mlast = 0) const;
2018-01-05 13:56:16 +01:00
private:
For() = default;
IndexClass* mIndPtr;
2018-01-08 18:38:13 +01:00
const Expr mExpr;
const std::tuple<to_size_t<Ops>...> mExt;
2018-01-07 16:57:01 +01:00
};
2018-01-05 13:56:16 +01:00
template <size_t N>
size_t exceptMax(size_t max) { return max; }
template <>
size_t exceptMax<1>(size_t max) { return 1; }
2018-01-08 18:38:13 +01:00
2018-01-05 13:56:16 +01:00
} // namespace MultiArrayHelper
/* ========================= *
* --- TEMPLATE CODE --- *
* ========================= */
namespace MultiArrayHelper
{
2018-01-08 18:38:13 +01:00
template <class IndexClass, class Expr, class... Ops>
2018-01-05 13:56:16 +01:00
template <typename... Args>
2018-01-08 18:38:13 +01:00
For<IndexClass,Expr,Ops...>::For(const std::shared_ptr<IndexClass>& indPtr,
std::tuple<to_size_t<Ops>...>&& ext,
const Args&... args) :
mIndPtr(indPtr.get()), mExpr(args...), mExt(ext) {}
2018-01-05 13:56:16 +01:00
2018-01-08 18:38:13 +01:00
template <class IndexClass, class Expr, class... Ops>
For<IndexClass,Expr,Ops...>::For(const std::shared_ptr<IndexClass>& indPtr,
Expr&& expr, std::tuple<to_size_t<Ops>...>&& ext) :
mIndPtr(indPtr.get()), mExpr(expr), mExt(ext) {}
template <class IndexClass, class Expr, class... Ops>
template <typename... Args>
For<IndexClass,Expr,Ops...>::For(IndexClass* indPtr,
std::tuple<to_size_t<Ops>...>&& ext,
const Args&... args) :
mIndPtr(indPtr), mExpr(args...), mExt(ext) {}
template <class IndexClass, class Expr, class... Ops>
For<IndexClass,Expr,Ops...>::For(IndexClass* indPtr,
Expr&& expr, std::tuple<to_size_t<Ops>...>&& ext) :
2018-01-08 18:38:13 +01:00
mIndPtr(indPtr), mExpr(expr), mExt(ext) {}
2018-01-08 18:38:13 +01:00
template <class IndexClass, class Expr, class... Ops>
inline void For<IndexClass,Expr,Ops...>::operator()(size_t mlast,
const std::tuple<to_size_t<Ops>...>& last) const
2018-01-05 13:56:16 +01:00
{
2018-01-08 18:38:13 +01:00
static const size_t opNum = sizeof...(Ops);
2018-01-05 13:56:16 +01:00
auto& ind = *mIndPtr;
const size_t max = exceptMax<For<IndexClass,Expr,Ops...>::layer()>( ind.max() ); // blocking
for(ind = 0; ind.pos() != max; ++ind){
const size_t mnpos = mlast * max + ind.pos();
const std::tuple<to_size_t<Ops>...> npos = std::move( XFPackNum<opNum-1>::mkPos(ind, mExt, last) );
mExpr(mnpos, npos);
}
}
template <class IndexClass, class Expr, class... Ops>
inline void For<IndexClass,Expr,Ops...>::operator()(size_t mlast) const
{
static const size_t opNum = sizeof...(Ops);
std::tuple<to_size_t<Ops>...> last(to_size_t<Ops>(0)...);
auto& ind = *mIndPtr;
const size_t max = exceptMax<For<IndexClass,Expr,Ops...>::layer()>( ind.max() ); // blocking
2018-01-05 13:56:16 +01:00
for(ind = 0; ind.pos() != max; ++ind){
2018-01-08 18:38:13 +01:00
const size_t mnpos = mlast * max + ind.pos();
2018-01-09 11:37:26 +01:00
const std::tuple<to_size_t<Ops>...> npos = std::move( XFPackNum<opNum-1>::mkPos(ind, mExt, last) );
2018-01-08 18:38:13 +01:00
mExpr(mnpos, npos);
2018-01-05 13:56:16 +01:00
}
}
} // namespace MultiArrayHelper
#endif