cnorxz/src/pack_num.h

419 lines
11 KiB
C
Raw Normal View History

// -*- C++ -*-
2017-08-04 11:27:47 +02:00
#ifndef __pack_num_h__
#define __pack_num_h__
#include <cstdlib>
#include <type_traits>
#include <tuple>
#include <memory>
2017-08-04 11:27:47 +02:00
#include "base_def.h"
namespace MultiArrayHelper
{
2017-08-04 11:27:47 +02:00
using namespace MultiArrayTools;
template <size_t N>
struct PackNum
{
template <class IndexType>
static IndexBase& getIndex(IndexType& in, size_t n)
{
if(n == N){
return in.template get<N>();
}
else {
return PackNum<N-1>::getIndex(in, n);
}
}
template <class IndexType>
static const IndexBase& getIndex(const IndexType& in, size_t n)
{
if(n == N){
return in.template get<N>();
}
else {
return PackNum<N-1>::getIndex(in, n);
}
}
template <class IndexType>
static std::shared_ptr<const IndexBase> getIndexPtr(const IndexType& in, size_t n)
{
if(n == N){
return in.template getPtr<N>();
}
else {
return PackNum<N-1>::getIndexPtr(in, n);
}
}
2017-08-29 17:52:08 +02:00
template <class... Indices>
static void lock(std::tuple<std::shared_ptr<Indices>...>& ip,
std::shared_ptr<const IndexBase>& toLock)
{
std::get<N>(ip)->lock(toLock);
PackNum<N-1>::lock(ip, toLock);
}
template <class... Indices>
2017-08-29 17:52:08 +02:00
static void initBlockSizes(std::array<size_t,sizeof...(Indices)+1>& bs,
std::tuple<std::shared_ptr<Indices>...>& ip)
{
2017-08-30 17:56:38 +02:00
if(N == sizeof...(Indices)+1){
2017-08-29 17:52:08 +02:00
std::get<N>(bs) = 1;
}
else {
std::get<N>(bs) = PackNum<sizeof...(Indices)-N-1>::blockSize(ip);
PackNum<N-1>::initBlockSizes(bs, ip);
}
}
template <class... Indices>
2017-08-30 17:56:38 +02:00
static inline void pp(std::tuple<std::shared_ptr<Indices>...>& ip)
{
auto& si = *std::get<N>(ip);
2017-08-30 17:56:38 +02:00
if(si.last()){
si = 0;
2017-08-04 14:57:19 +02:00
PackNum<N-1>::pp(ip);
}
else {
++si;
}
2017-08-30 17:56:38 +02:00
}
template <class... Indices>
static inline size_t pp(std::tuple<std::shared_ptr<Indices>...>& ip,
std::array<size_t,sizeof...(Indices)>& bs,
std::shared_ptr<const IndexBase>& idxPtr)
{
auto siPtr = std::get<N>(ip);
if(siPtr.get() == idxPtr.get()){
return std::get<N>(bs) + PackNum<N-1>::pp(ip);
2017-08-29 17:52:08 +02:00
}
else {
2017-08-30 17:56:38 +02:00
if(siPtr->last()){
(*siPtr) = 0;
return PackNum<N-1>::pp(ip, bs) - siPtr->max() + 1;
}
else {
return siPtr->pp(idxPtr);
}
2017-08-29 17:52:08 +02:00
}
}
2017-08-30 17:56:38 +02:00
template <class... Indices>
2017-08-30 17:56:38 +02:00
static inline void mm(std::tuple<std::shared_ptr<Indices>...>& ip)
{
auto& si = *std::get<N>(ip);
2017-08-30 17:56:38 +02:00
if(si.first()){
si = si.max();
2017-08-04 14:57:19 +02:00
PackNum<N-1>::mm(ip);
}
else {
--si;
}
2017-08-30 17:56:38 +02:00
}
template <class... Indices>
static inline size_t mm(std::tuple<std::shared_ptr<Indices>...>& ip,
std::array<size_t,sizeof...(Indices)>& bs,
std::shared_ptr<const IndexBase>& idx)
{
auto siPtr = std::get<N>(ip);
if(siPtr.get() == idxPtr.get()){
return std::get<N>(bs) + PackNum<N-1>::mm(ip);
2017-08-29 17:52:08 +02:00
}
else {
2017-08-30 17:56:38 +02:00
if(siPtr->first()){
return PackNum<N-1>::mm(ip, bs) - siPtr->max() + 1;
}
else {
return siPtr->pp(idx);
}
2017-08-29 17:52:08 +02:00
}
}
template <class RangeTuple>
static size_t getSize(const RangeTuple& rt)
{
2017-08-04 14:57:19 +02:00
return std::get<N>(rt)->size() * PackNum<N-1>::getSize(rt);
}
2017-08-04 14:57:19 +02:00
template <class IndexPack, class MetaType>
static void getMetaPos(MetaType& target,
const IndexPack& source)
{
std::get<N>(target) = std::get<N>(source)->meta();
PackNum<N-1>::getMetaPos(target, source);
}
2017-08-04 11:27:47 +02:00
template <class IndexPack, typename MetaType>
static void setMeta(IndexPack& target, const MetaType& source)
{
2017-08-04 14:57:19 +02:00
std::get<N>(target)->at( std::get<N>(source) );
PackNum<N-1>::setMeta(target, source);
}
template <class IndexPack>
static void setIndexPack(IndexPack& iPack, size_t pos)
{
2017-08-07 11:22:42 +02:00
auto& i = *std::get<N>(iPack).get();
const size_t ownPos = pos % i.max();
i = ownPos;
PackNum<N-1>::setIndexPack(iPack, (pos - ownPos) / i.max() );
}
template <class MRange, class... Indices>
static void construct(std::tuple<std::shared_ptr<Indices>...>& ip,
const MRange& range)
{
2017-08-04 14:57:19 +02:00
typedef typename std::remove_reference<decltype(range.template get<N>())>::type SubRangeType;
typedef typename SubRangeType::IndexType SubIndexType;
typedef typename std::remove_reference<decltype(*std::get<N>(ip).get())>::type TypeFromIndexPack;
static_assert(std::is_same<SubIndexType,TypeFromIndexPack>::value,
"inconsiśtent types");
2017-08-04 14:57:19 +02:00
std::get<N>(ip) = std::shared_ptr<SubIndexType>( new SubIndexType( range.template getPtr<N>() ) );
PackNum<N-1>::construct(ip, range);
}
/*
2017-08-04 11:27:47 +02:00
template <template<class...> class IndexType, class... Indices>
static void copy(std::tuple<std::shared_ptr<Indices>...>& ip,
const IndexType<Indices...>& ind)
{
2017-08-04 14:57:19 +02:00
typedef typename std::remove_reference<decltype(ind.template get<N>())>::type SubIndexType;
std::get<N>(ip) = std::shared_ptr<SubIndexType>( new SubIndexType( ind.template get<N>() ) );
PackNum<N-1>::copy(ip, ind);
}
*/
2017-08-11 11:30:27 +02:00
template <template<class...> class IndexType, class... Indices>
static void copyInst(std::tuple<std::shared_ptr<Indices>...>& ip,
const IndexType<Indices...>& ind)
{
std::get<N>(ip) = ind.template getPtr<N>() ;
PackNum<N-1>::copyInst(ip, ind);
2017-08-11 11:30:27 +02:00
}
template <class... Indices>
static size_t makePos(const std::tuple<std::shared_ptr<Indices>...>& iPtrTup)
{
auto ID = std::get<N>(iPtrTup)->id();
return std::get<N>(iPtrTup)->pos() +
PackNum<N-1>::makePos(iPtrTup) * std::get<N>(iPtrTup)->max();
}
template <class Pack, class IndexType, class... Indices>
static void swapIndices(Pack& ipack, const std::shared_ptr<IndexType>& nind,
const std::shared_ptr<Indices>&... ninds)
{
std::get<std::tuple_size<Pack>::value-N-1>(ipack) = nind;
PackNum<N-1>::swapIndices(ipack, ninds...);
}
template <class... Indices>
static size_t blockSize(const std::tuple<std::shared_ptr<Indices>...>& pack)
{
return std::get<sizeof...(Indices)-N-1>(pack)->max() * PackNum<N-1>::blockSize(pack);
}
2017-08-11 15:26:10 +02:00
template <typename T, class Func, class ArgTuple, class... Args>
static T unpackArgs(const ArgTuple& tp, const Args&... args)
{
return PackNum<N-1>::template unpackArgs<T,Func>(tp, std::get<N>(tp).get(), args...);
}
2017-08-30 17:56:38 +02:00
template <class... Ops>
static void makeBlockTypeVec(std::vector<std::pair<BlockType,size_t> >& btv,
const std::tuple<Ops...>& ops,
std::shared_ptr<const IndexBase>& idxPtr)
{
auto& subvec = std::get<N>(ops).block(idxPtr);
btv.insert(btv.end(), subvec.begin(), subvec.end() );
PackNum<N-1>::makeBlockTypeVec(btv, ops, idxPtr);
}
};
template<>
struct PackNum<0>
{
template <class MultiIndex>
2017-08-04 11:27:47 +02:00
static IndexBase& getIndex(MultiIndex& in, size_t n)
{
return in.template get<0>();
}
template <class MultiIndex>
2017-08-04 11:27:47 +02:00
static const IndexBase& getIndex(const MultiIndex& in, size_t n)
{
return in.template get<0>();
}
template <class IndexType>
static std::shared_ptr<const IndexBase> getIndexPtr(const IndexType& in, size_t n)
{
return in.template getPtr<0>();
}
2017-08-29 17:52:08 +02:00
template <class... Indices>
static void lock(std::tuple<std::shared_ptr<Indices>...>& ip,
std::shared_ptr<const IndexBase>& toLock)
{
std::get<0>(ip)->lock(toLock);
}
template <class... Indices>
static void initBlockSizes(std::array<size_t,sizeof...(Indices)+1>& bs,
std::tuple<std::shared_ptr<Indices>...>& ip)
{
std::get<0>(bs) = PackNum<sizeof...(Indices)-1>::blockSize(ip);
}
2017-08-30 17:56:38 +02:00
template <class... Indices>
static inline void pp(std::tuple<std::shared_ptr<Indices>...>& ip)
{
auto& si = *std::get<0>(ip);
++si;
}
template <class... Indices>
2017-08-29 17:52:08 +02:00
static inline size_t pp(std::tuple<std::shared_ptr<Indices>...>& ip,
std::array<size_t,sizeof...(Indices)+1>& bs)
{
auto& si = *std::get<0>(ip);
2017-08-29 17:52:08 +02:00
if(si.locked()){
si = si.max()+1;
return std::get<0>(bs) - std::get<1>(bs) + 1;
}
else {
++si;
return 1;
}
}
2017-08-30 17:56:38 +02:00
template <class... Indices>
static inline size_t mm(std::tuple<std::shared_ptr<Indices>...>& ip)
{
auto& si = *std::get<0>(ip);
--si;
}
template <class... Indices>
2017-08-29 17:52:08 +02:00
static inline size_t mm(std::tuple<std::shared_ptr<Indices>...>& ip,
std::array<size_t,sizeof...(Indices)>& bs)
{
auto& si = *std::get<0>(ip);
2017-08-29 17:52:08 +02:00
if(si.locked()){
si = 0;
--si;
return std::get<0>(bs) - std::get<1>(bs) + 1;
}
else {
--si;
return 1;
}
}
template <class RangeTuple>
static size_t getSize(const RangeTuple& rt)
{
2017-08-04 14:57:19 +02:00
return std::get<0>(rt)->size();
}
2017-08-04 14:57:19 +02:00
template <class IndexPack, class MetaType>
static void getMetaPos(MetaType& target,
const IndexPack& source)
{
std::get<0>(target) = std::get<0>(source)->meta();
}
2017-08-04 11:27:47 +02:00
template <class IndexPack, typename MetaType>
static void setMeta(IndexPack& target, const MetaType& source)
{
2017-08-04 14:57:19 +02:00
std::get<0>(target)->at( std::get<0>( source ) );
}
template <class IndexPack>
static void setIndexPack(IndexPack& iPack, size_t pos)
{
2017-08-07 11:22:42 +02:00
auto& i = *std::get<0>(iPack);
const size_t ownPos = pos % i.max();
i = ownPos;
}
template <class MRange, class... Indices>
static void construct(std::tuple<std::shared_ptr<Indices>...>& ip,
const MRange& range)
{
2017-08-04 14:57:19 +02:00
typedef typename std::remove_reference<decltype(range.template get<0>())>::type SubRangeType;
typedef typename SubRangeType::IndexType SubIndexType;
typedef typename std::remove_reference<decltype(*std::get<0>(ip).get())>::type TypeFromIndexPack;
static_assert(std::is_same<SubIndexType,TypeFromIndexPack>::value,
"inconsiśtent types");
2017-08-04 14:57:19 +02:00
std::get<0>(ip) = std::shared_ptr<SubIndexType>( new SubIndexType( range.template getPtr<0>() ) );
}
/*
2017-08-04 11:27:47 +02:00
template <template<class...> class IndexType, class... Indices>
static void copy(std::tuple<std::shared_ptr<Indices>...>& ip,
const IndexType<Indices...>& ind)
{
2017-08-04 14:57:19 +02:00
typedef typename std::remove_reference<decltype(ind.template get<0>())>::type SubIndexType;
std::get<0>(ip) = std::shared_ptr<SubIndexType>( new SubIndexType( ind.template get<0>() ) );
}
*/
2017-08-11 11:30:27 +02:00
template <template<class...> class IndexType, class... Indices>
static void copyInst(std::tuple<std::shared_ptr<Indices>...>& ip,
const IndexType<Indices...>& ind)
{
std::get<0>(ip) = ind.template getPtr<0>();
}
template <class... Indices>
static size_t makePos(const std::tuple<std::shared_ptr<Indices>...>& iPtrTup)
{
auto ID = std::get<0>(iPtrTup)->id();
return std::get<0>(iPtrTup)->pos();
}
template <class Pack, class IndexType>
static void swapIndices(Pack& ipack, const std::shared_ptr<IndexType>& nind)
{
std::get<std::tuple_size<Pack>::value-1>(ipack) = nind;
}
template <class... Indices>
static size_t blockSize(const std::tuple<std::shared_ptr<Indices>...>& pack)
{
return std::get<sizeof...(Indices)-1>(pack)->max();
}
2017-08-11 15:26:10 +02:00
template <typename T, class Func, class ArgTuple, class... Args>
static T unpackArgs(const ArgTuple& tp, const Args&... args)
{
static_assert(sizeof...(Args) == std::tuple_size<ArgTuple>::value-1,
"inconsistent number of arguments");
static Func f;
return f(std::get<0>(tp).get(), args...);
}
2017-08-30 17:56:38 +02:00
template <class... Ops>
static void makeBlockTypeVec(std::vector<std::pair<BlockType,size_t> >& btv,
const std::tuple<Ops...>& ops,
std::shared_ptr<const IndexBase>& idxPtr)
{
auto& subvec = std::get<0>(ops).block(idxPtr);
btv.insert(btv.end(), subvec.begin(), subvec.end() );
}
};
} // end namespace MultiArrayHelper
2017-08-04 11:27:47 +02:00
#endif