start refactoring mrange + index interface offset (not finished)
This commit is contained in:
parent
59267fb040
commit
a880d1e0db
3 changed files with 299 additions and 591 deletions
|
@ -45,7 +45,10 @@ namespace CNORXZ
|
||||||
|
|
||||||
SizeT dim() const { return THIS().dim(); }
|
SizeT dim() const { return THIS().dim(); }
|
||||||
auto range() const { return THIS().range(); }
|
auto range() const { return THIS().range(); }
|
||||||
|
// TODO: getStepSize(PtrId iptr) !!!!
|
||||||
SizeT getStepSize(SizeT n) const { return THIS().getStepSize(n); }
|
SizeT getStepSize(SizeT n) const { return THIS().getStepSize(n); }
|
||||||
|
Int getOffset(PtrId iptr) const
|
||||||
|
{ if(mRel) if(iptr == mRel->ptrId()) return mPos - mRel.pos(); return 0; }
|
||||||
|
|
||||||
String stringMeta() const { return THIS().stringMeta(); }
|
String stringMeta() const { return THIS().stringMeta(); }
|
||||||
auto meta() const { return THIS().meta(); }
|
auto meta() const { return THIS().meta(); }
|
||||||
|
@ -74,6 +77,7 @@ namespace CNORXZ
|
||||||
IndexInterface(SizeT pos);
|
IndexInterface(SizeT pos);
|
||||||
|
|
||||||
PtrId mPtrId = 0;
|
PtrId mPtrId = 0;
|
||||||
|
IndexPtr<I,MetaType> mRel;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class I, typename MetaType>
|
template <class I, typename MetaType>
|
||||||
|
|
241
src/include/ranges/mrange.cc.h
Normal file
241
src/include/ranges/mrange.cc.h
Normal file
|
@ -0,0 +1,241 @@
|
||||||
|
|
||||||
|
#ifndef __cxz_mrange_cc_h__
|
||||||
|
#define __cxz_mrange_cc_h__
|
||||||
|
|
||||||
|
#include "mrange.h"
|
||||||
|
#include "range_helper.h"
|
||||||
|
#include "statics/static_for.h"
|
||||||
|
|
||||||
|
namespace CNORXZ
|
||||||
|
{
|
||||||
|
/**************
|
||||||
|
* MIndex *
|
||||||
|
**************/
|
||||||
|
|
||||||
|
template <class... Indices>
|
||||||
|
template <class MRange>
|
||||||
|
MIndex<Indices...>::MIndex(const Sptr<MRange>& range) :
|
||||||
|
IndexInterface<MIndex<Indices...>,Tuple<typename Indices::MetaType...> >(0)
|
||||||
|
{
|
||||||
|
std::get<sizeof...(Indices)>(mBlockSizes) = 1;
|
||||||
|
sfor_mn<sizeof...(Indices),0>
|
||||||
|
( [&](auto i) {
|
||||||
|
auto r = range->template getPtr<i>();
|
||||||
|
std::get<i>(mIPack) = r->beginPtr();
|
||||||
|
*std::get<i>(mIPack) = 0;
|
||||||
|
|
||||||
|
std::get<i>(mBlockSizes) = sfor_p<i,sizeof...(Indices)>
|
||||||
|
( [&](auto j) { return std::get<j>(mIPack)->max(); } ,
|
||||||
|
[&](auto a, auto b) { return a * b; });
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
IB::mPos = sfor_m<sizeof...(Indices),0>
|
||||||
|
( [&](auto i) { return std::get<i>(mIPack); },
|
||||||
|
[&](auto a, auto b) {return a->pos() + b*a->max();}, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Indices>
|
||||||
|
MIndex<Indices...>& MIndex<Indices...>::operator()(Sptr<Indices>&... indices)
|
||||||
|
{
|
||||||
|
return (*this)(std::make_tuple(indices...));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Indices>
|
||||||
|
MIndex<Indices...>& MIndex<Indices...>::operator()(const Tuple<Sptr<Indices>...>& indices)
|
||||||
|
{
|
||||||
|
sfor_pn<0,sizeof...(Indices)>
|
||||||
|
( [&](auto i) { std::get<i>(mIPack) = std::get<i>(indices); return 0; } );
|
||||||
|
RangeHelper::setIndexPack<sizeof...(Indices)-1>(mIPack, IB::mPos);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Indices>
|
||||||
|
MIndex<Indices...>& MIndex<Indices...>::operator=(SizeT pos)
|
||||||
|
{
|
||||||
|
IB::mPos = pos;
|
||||||
|
RangeHelper::setIndexPack<sizeof...(Indices)-1>(mIPack, pos);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Indices>
|
||||||
|
MIndex<Indices...>& MIndex<Indices...>::operator++()
|
||||||
|
{
|
||||||
|
sfor_m<sizeof...(Indices),0>
|
||||||
|
( [&](auto i) {
|
||||||
|
auto& si = *std::get<i>( mIPack );
|
||||||
|
if(si.last() and i != 0) { si = 0; return true; }
|
||||||
|
else { ++si; return false; }
|
||||||
|
return false;
|
||||||
|
} );
|
||||||
|
++IB::mPos;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Indices>
|
||||||
|
MIndex<Indices...>& MIndex<Indices...>::operator--()
|
||||||
|
{
|
||||||
|
sfor_m<sizeof...(Indices),0>
|
||||||
|
( [&](auto i) {
|
||||||
|
auto& si = *std::get<i>( mIPack );
|
||||||
|
if(si.first() and i != 0) { si = si.max()-1; return true; }
|
||||||
|
else { --si; return false; }
|
||||||
|
return false;
|
||||||
|
} );
|
||||||
|
--IB::mPos;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class... Indices>
|
||||||
|
int MIndex<Indices...>::pp(PtrId idxPtrNum)
|
||||||
|
{
|
||||||
|
const int tmp = RangeHelper::ppx<sizeof...(Indices)-1>(mIPack, mBlockSizes, idxPtrNum);
|
||||||
|
IB::mPos += tmp;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Indices>
|
||||||
|
int MIndex<Indices...>::mm(PtrId idxPtrNum)
|
||||||
|
{
|
||||||
|
const int tmp = RangeHelper::mmx<sizeof...(Indices)-1>(mIPack, mBlockSizes, idxPtrNum);
|
||||||
|
IB::mPos -= tmp;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Indices>
|
||||||
|
String MIndex<Indices...>::stringMeta() const
|
||||||
|
{
|
||||||
|
return std::dynamic_pointer_cast<RangeType>( IB::mRangePtr )->stringMeta(IB::mPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Indices>
|
||||||
|
typename MIndex<Indices...>::MetaType MIndex<Indices...>::meta() const
|
||||||
|
{
|
||||||
|
MetaType metaTuple;
|
||||||
|
sfor_pn<0,sizeof...(Indices)>
|
||||||
|
( [&](auto i) { std::get<i>(metaTuple) = std::get<i>(mIPack)->meta(); return 0; } );
|
||||||
|
return metaTuple;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Indices>
|
||||||
|
MIndex<Indices...>& MIndex<Indices...>::at(const MetaType& metaPos)
|
||||||
|
{
|
||||||
|
sfor_pn<0,sizeof...(Indices)>
|
||||||
|
( [&](auto i) { std::get<i>(mIPack)->at( std::get<i>(metaPos) ); return 0; } );
|
||||||
|
IB::mPos = sfor_m<sizeof...(Indices),0>
|
||||||
|
( [&](auto i) { return std::get<i>(mIPack); },
|
||||||
|
[&](auto a, auto b) {return a->pos() + b*a->max();}, 0 );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Indices>
|
||||||
|
SizeT MIndex<Indices...>::dim()
|
||||||
|
{
|
||||||
|
return sizeof...(Indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Indices>
|
||||||
|
Sptr<typename MIndex<Indices...>::RangeType>
|
||||||
|
MIndex<Indices...>::range()
|
||||||
|
{
|
||||||
|
return std::dynamic_pointer_cast<RangeType>( mRangePtr );
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Indices>
|
||||||
|
SizeT MIndex<Indices...>::getStepSize(SizeT n)
|
||||||
|
{
|
||||||
|
if(n >= sizeof...(Indices)){
|
||||||
|
assert(0);
|
||||||
|
// throw !!
|
||||||
|
}
|
||||||
|
return mBlockSizes[n+1];
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
template <class... Indices>
|
||||||
|
template <class Exprs>
|
||||||
|
auto MIndex<Indices...>::ifor(SizeT step, Exprs exs) const
|
||||||
|
{
|
||||||
|
return RangeHelper::mkFor<0>(step, mIPack, mBlockSizes, exs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Indices>
|
||||||
|
template <class Exprs>
|
||||||
|
auto MIndex<Indices...>::iforh(SizeT step, Exprs exs) const
|
||||||
|
{
|
||||||
|
return RangeHelper::mkForh<0>(step, mIPack, mBlockSizes, exs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Indices>
|
||||||
|
template <class Exprs>
|
||||||
|
auto MIndex<Indices...>::pifor(SizeT step, Exprs exs) const
|
||||||
|
{
|
||||||
|
return RangeHelper::mkPFor<0>(step, mIPack, mBlockSizes, exs);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* MRangeFactory *
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
template <class... Ranges>
|
||||||
|
MRangeFactory<Ranges...>::MRangeFactory(const Sptr<Ranges>&... rs)
|
||||||
|
{
|
||||||
|
mProd = Sptr< MRange<Ranges...> >( new MRange<Ranges...>( rs... ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Ranges>
|
||||||
|
MRangeFactory<Ranges...>::MRangeFactory(const typename MRange<Ranges...>::Space& st)
|
||||||
|
{
|
||||||
|
mProd = Sptr< MRange<Ranges...> >( new MRange<Ranges...>( st ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Ranges>
|
||||||
|
Sptr<RangeBase> MRangeFactory<Ranges...>::create()
|
||||||
|
{
|
||||||
|
mProd = checkIfCreated( std::dynamic_pointer_cast<oType>( mProd )->mSpace );
|
||||||
|
setSelf();
|
||||||
|
return mProd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************
|
||||||
|
* MRange *
|
||||||
|
******************/
|
||||||
|
|
||||||
|
template <class... Ranges>
|
||||||
|
MRange<Ranges...>::MRange(const Sptr<Ranges>&... rs) : mSpace(std::make_tuple(rs...)) {}
|
||||||
|
|
||||||
|
template <class... Ranges>
|
||||||
|
MRange<Ranges...>::MRange(const Space& space) : mSpace( space ) {}
|
||||||
|
|
||||||
|
template <class... Ranges>
|
||||||
|
SizeT MRange<Ranges...>::getMeta(const MetaType& metaPos) const
|
||||||
|
{
|
||||||
|
return RangeHelper::getMeta<sizeof...(Ranges)-1>(mSpace,metaPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Ranges>
|
||||||
|
SizeT MRange<Ranges...>::dim() const
|
||||||
|
{
|
||||||
|
return sdim;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Ranges>
|
||||||
|
SizeT MRange<Ranges...>::size() const
|
||||||
|
{
|
||||||
|
return sfor_p<0,sizeof...(Ranges)>
|
||||||
|
( [&](auto i) { return std::get<i>(mSpace)->size(); },
|
||||||
|
[&](auto a, auto b) { return a * b; } );
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Ranges>
|
||||||
|
String MRange<Ranges...>::stringMeta(SizeT pos) const
|
||||||
|
{
|
||||||
|
auto i = begin();
|
||||||
|
i = pos;
|
||||||
|
return "[" + RangeHelper::getStringMeta<0>(i) + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,106 +1,66 @@
|
||||||
// -*- C++ -*-
|
// -*- C++ -*-
|
||||||
|
|
||||||
#ifndef __cxz_multi_range_h__
|
#ifndef __cxz_mrange_h__
|
||||||
#define __cxz_multi_range_h__
|
#define __cxz_mrange_h__
|
||||||
|
|
||||||
#include "base/base.h"
|
#include "base/base.h"
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include "range_base.h"
|
#include "range_base.h"
|
||||||
#include "index_base.h"
|
#include "index_base.h"
|
||||||
|
|
||||||
#include "range_helper.h"
|
|
||||||
//#include "multi_range_factory_product_map.h"
|
|
||||||
|
|
||||||
#include "statics/static_for.h"
|
|
||||||
|
|
||||||
namespace CNORXZ
|
namespace CNORXZ
|
||||||
{
|
{
|
||||||
|
|
||||||
template <class... Indices>
|
template <class... Indices>
|
||||||
class MultiIndex : public IndexInterface<MultiIndex<Indices...>,
|
class MIndex : public IndexInterface<MIndex<Indices...>,
|
||||||
Tuple<typename Indices::MetaType...> >
|
Tuple<typename Indices::MetaType...> >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef IndexInterface<MultiIndex<Indices...>,
|
typedef IndexInterface<MIndex<Indices...>,
|
||||||
Tuple<typename Indices::MetaType...> > IB;
|
Tuple<typename Indices::MetaType...> > IB;
|
||||||
typedef Tuple<Sptr<Indices>...> IndexPack;
|
typedef Tuple<Sptr<Indices>...> IndexPack;
|
||||||
typedef Tuple<typename Indices::MetaType...> MetaType;
|
typedef Tuple<typename Indices::MetaType...> MetaType;
|
||||||
typedef MultiRange<typename Indices::RangeType...> RangeType;
|
typedef MRange<typename Indices::RangeType...> RangeType;
|
||||||
typedef MultiIndex IType;
|
|
||||||
|
|
||||||
static constexpr IndexType sType() { return IndexType::MULTI; }
|
|
||||||
static constexpr SizeT sDim() { return sizeof...(Indices); }
|
|
||||||
static constexpr SizeT totalDim() { return (... * Indices::totalDim()); }
|
|
||||||
|
|
||||||
static constexpr SpaceType STYPE = SpaceType::ANY;
|
|
||||||
static constexpr bool PARALLEL = TupleElem<0,Tuple<Indices...>>::type::PARALLEL;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
IndexPack mIPack;
|
|
||||||
Arr<SizeT,sizeof...(Indices)+1> mBlockSizes;
|
|
||||||
MultiIndex() = default;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
const IndexPack& pack() const { return mIPack; }
|
|
||||||
|
|
||||||
// NO DEFAULT HERE !!!
|
// NO DEFAULT HERE !!!
|
||||||
// ( have to assign sub-indices (ptr!) correctly )
|
// ( have to assign sub-indices (ptr!) correctly )
|
||||||
|
MIndex(const MIndex& i);
|
||||||
|
MIndex(MIndex&& i);
|
||||||
|
MIndex& operator=(const MIndex& i);
|
||||||
|
MIndex& operator=(MIndex&& i);
|
||||||
|
|
||||||
template <class MRange>
|
MIndex(const RangePtr& range, SizeT pos = 0);
|
||||||
MultiIndex(const Sptr<MRange>& range);
|
|
||||||
|
|
||||||
template <SizeT DIR>
|
// replace sub-index instances; only use if you know what you are doing!
|
||||||
MultiIndex& up();
|
MIndex& operator()(Sptr<Indices>&... indices);
|
||||||
|
MIndex& operator()(const MIndex& indices);
|
||||||
|
|
||||||
template <SizeT DIR>
|
const IndexPack& pack() const { return mIPack; }
|
||||||
MultiIndex& down();
|
const auto& getBlockSizes() const { return mBlockSizes; }
|
||||||
|
|
||||||
template <SizeT N>
|
|
||||||
auto get() const -> decltype( *std::get<N>( mIPack ) )&;
|
|
||||||
|
|
||||||
template <SizeT N>
|
|
||||||
auto getPtr() const -> decltype( std::get<N>( mIPack ) )&;
|
|
||||||
|
|
||||||
template <SizeT N>
|
|
||||||
SizeT getBlockSize() const { return std::get<N>(mBlockSizes); }
|
|
||||||
|
|
||||||
// raplace instances (in contrast to its analogon in ConstContainerIndex
|
MIndex& operator=(SizeT pos);
|
||||||
// MultiIndices CANNOT be influences be its subindices, so there is
|
MIndex& operator++();
|
||||||
// NO foreign/external controll)
|
MIndex& operator--();
|
||||||
// Do NOT share index instances between two or more MultiIndex instances
|
MIndex operator+(Int n) const;
|
||||||
MultiIndex& operator()(Sptr<Indices>&... indices);
|
MIndex operator-(Int n) const;
|
||||||
MultiIndex& operator()(const Tuple<Sptr<Indices>...>& indices);
|
MIndex& operator+=(Int n);
|
||||||
|
MIndex& operator-=(Int n);
|
||||||
|
|
||||||
// ==== >>>>> STATIC POLYMORPHISM <<<<< ====
|
SizeT operator*() const;
|
||||||
|
SizeT operator->() const;
|
||||||
IndexType type() const;
|
|
||||||
|
|
||||||
MultiIndex& operator=(SizeT pos);
|
|
||||||
|
|
||||||
MultiIndex& operator++();
|
|
||||||
MultiIndex& operator--();
|
|
||||||
|
|
||||||
int pp(PtrId idxPtrNum);
|
int pp(PtrId idxPtrNum);
|
||||||
int mm(PtrId idxPtrNum);
|
int mm(PtrId idxPtrNum);
|
||||||
|
|
||||||
std::string stringMeta() const;
|
|
||||||
MetaType meta() const;
|
|
||||||
MultiIndex& at(const MetaType& metaPos);
|
|
||||||
|
|
||||||
SizeT dim();
|
SizeT dim();
|
||||||
bool first();
|
|
||||||
bool last();
|
|
||||||
Sptr<RangeType> range();
|
Sptr<RangeType> range();
|
||||||
|
|
||||||
template <SizeT N>
|
|
||||||
auto getPtr() -> decltype( std::get<N>( mIPack ) )&;
|
|
||||||
|
|
||||||
SizeT getStepSize(SizeT n);
|
SizeT getStepSize(SizeT n);
|
||||||
|
|
||||||
|
String stringMeta() const;
|
||||||
|
MetaType meta() const;
|
||||||
|
MIndex& at(const MetaType& metaPos);
|
||||||
|
|
||||||
|
/*
|
||||||
template <class Exprs>
|
template <class Exprs>
|
||||||
auto ifor(SizeT step, Exprs exs) const;
|
auto ifor(SizeT step, Exprs exs) const;
|
||||||
|
|
||||||
|
@ -109,559 +69,62 @@ namespace CNORXZ
|
||||||
|
|
||||||
template <class Exprs>
|
template <class Exprs>
|
||||||
auto pifor(SizeT step, Exprs exs) const;
|
auto pifor(SizeT step, Exprs exs) const;
|
||||||
|
*/
|
||||||
|
private:
|
||||||
|
MIndex() = default;
|
||||||
|
|
||||||
|
IndexPack mIPack;
|
||||||
|
Arr<SizeT,sizeof...(Indices)+1> mBlockSizes;
|
||||||
|
Sptr<RangeType> mRange;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************************
|
|
||||||
* MultiRangeFactory *
|
|
||||||
*************************/
|
|
||||||
|
|
||||||
// NOT THREAD SAVE
|
// NOT THREAD SAVE
|
||||||
template <class... Ranges>
|
template <class... Ranges>
|
||||||
class MultiRangeFactory : public RangeFactoryBase
|
class MRangeFactory : public RangeFactoryBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef MultiRange<Ranges...> oType;
|
MRangeFactory() = delete;
|
||||||
|
MRangeFactory(const Sptr<Ranges>&... rs);
|
||||||
|
MRangeFactory(const Tuple<Sptr<Ranges>...>& rs);
|
||||||
|
|
||||||
MultiRangeFactory() = delete;
|
|
||||||
MultiRangeFactory(const Sptr<Ranges>&... rs);
|
|
||||||
MultiRangeFactory(const typename MultiRange<Ranges...>::Space& space);
|
|
||||||
|
|
||||||
virtual Sptr<RangeBase> create() override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
virtual void make() override final;
|
||||||
Sptr<RangeBase> checkIfCreated(const Tuple<Sptr<Ranges>...>& ptp);
|
|
||||||
|
Tuple<Sptr<Ranges>...> mRs;
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************
|
|
||||||
* MultiRange *
|
|
||||||
******************/
|
|
||||||
|
|
||||||
template <class... Ranges>
|
template <class... Ranges>
|
||||||
class MultiRange : public RangeInterface<MultiIndex<typename Ranges::IndexType...> >
|
class MRange : public RangeInterface<MIndex<typename Ranges::IndexType...> >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef RangeBase RB;
|
typedef RangeBase RB;
|
||||||
typedef Tuple<Sptr<Ranges>...> Space;
|
typedef MIndex<typename Ranges::IndexType...> IndexType;
|
||||||
typedef MultiIndex<typename Ranges::IndexType...> IndexType;
|
|
||||||
typedef Tuple<typename Ranges::IndexType::MetaType...> MetaType;
|
typedef Tuple<typename Ranges::IndexType::MetaType...> MetaType;
|
||||||
typedef MultiRange RangeType;
|
|
||||||
typedef MultiRangeFactory<Ranges...> FType;
|
|
||||||
|
|
||||||
protected:
|
const Space& space() const;
|
||||||
MultiRange() = delete;
|
|
||||||
MultiRange(const MultiRange& in) = delete;
|
|
||||||
MultiRange& operator=(const MultiRange& in) = delete;
|
|
||||||
|
|
||||||
MultiRange(const Sptr<Ranges>&... rs);
|
|
||||||
MultiRange(const Space& space);
|
|
||||||
|
|
||||||
Space mSpace;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
static const SizeT sdim = sizeof...(Ranges);
|
|
||||||
|
|
||||||
template <SizeT N>
|
|
||||||
auto get() const -> decltype( *std::get<N>( mSpace ) )&;
|
|
||||||
|
|
||||||
SizeT getMeta(const MetaType& metaPos) const;
|
SizeT getMeta(const MetaType& metaPos) const;
|
||||||
|
|
||||||
template <SizeT N>
|
|
||||||
auto getPtr() const -> decltype( std::get<N>( mSpace ) )&;
|
|
||||||
|
|
||||||
virtual Sptr<RangeBase> sub(SizeT num) const override;
|
virtual Sptr<RangeBase> sub(SizeT num) const override;
|
||||||
|
|
||||||
virtual SizeT dim() const final;
|
virtual SizeT dim() const final;
|
||||||
virtual SizeT size() const final;
|
virtual SizeT size() const final;
|
||||||
|
|
||||||
virtual SpaceType spaceType() const final;
|
virtual String stringMeta(SizeT pos) const final;
|
||||||
virtual DataHeader dataHeader() const final;
|
|
||||||
|
|
||||||
virtual Vector<SizeT> typeNum() const final;
|
|
||||||
virtual SizeT cmeta(char* target, SizeT pos) const final;
|
|
||||||
virtual SizeT cmetaSize() const final;
|
|
||||||
virtual std::string stringMeta(SizeT pos) const final;
|
|
||||||
virtual Vector<char> data() const final;
|
|
||||||
|
|
||||||
const Space& space() const;
|
friend MRangeFactory<Ranges...>;
|
||||||
|
|
||||||
virtual IndexType begin() const final;
|
|
||||||
virtual IndexType end() const final;
|
|
||||||
|
|
||||||
template <class... ERanges>
|
protected:
|
||||||
auto cat(const Sptr<MultiRange<ERanges...> >& erange)
|
MRange() = delete;
|
||||||
-> Sptr<MultiRange<Ranges...,ERanges...> >;
|
MRange(const MRange& in) = delete;
|
||||||
|
MRange& operator=(const MRange& in) = delete;
|
||||||
|
|
||||||
friend MultiRangeFactory<Ranges...>;
|
Tuple<Sptr<Ranges>...> mRs;
|
||||||
|
|
||||||
static constexpr bool HASMETACONT = false;
|
|
||||||
static constexpr bool defaultable = false;
|
|
||||||
static constexpr SizeT ISSTATIC = (... & Ranges::ISSTATIC);
|
|
||||||
static constexpr SizeT SIZE = (... * Ranges::SIZE);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================= *
|
|
||||||
* --- TEMPLATE CODE --- *
|
|
||||||
* ========================= */
|
|
||||||
|
|
||||||
namespace CNORXZ
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
using namespace CNORXZInternal;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -> define in range_base.cc
|
|
||||||
Sptr<RangeFactoryBase> mkMULTI(const char** dp);
|
|
||||||
|
|
||||||
/******************
|
|
||||||
* MultiIndex *
|
|
||||||
******************/
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
template <class MRange>
|
|
||||||
MultiIndex<Indices...>::MultiIndex(const Sptr<MRange>& range) :
|
|
||||||
IndexInterface<MultiIndex<Indices...>,Tuple<typename Indices::MetaType...> >(range, 0)
|
|
||||||
{
|
|
||||||
std::get<sizeof...(Indices)>(mBlockSizes) = 1;
|
|
||||||
sfor_mn<sizeof...(Indices),0>
|
|
||||||
( [&](auto i) {
|
|
||||||
auto r = range->template getPtr<i>();
|
|
||||||
std::get<i>(mIPack) = r->beginPtr();
|
|
||||||
*std::get<i>(mIPack) = 0;
|
|
||||||
|
|
||||||
std::get<i>(mBlockSizes) = sfor_p<i,sizeof...(Indices)>
|
|
||||||
( [&](auto j) { return std::get<j>(mIPack)->max(); } ,
|
|
||||||
[&](auto a, auto b) { return a * b; });
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
IB::mPos = sfor_m<sizeof...(Indices),0>
|
|
||||||
( [&](auto i) { return std::get<i>(mIPack); },
|
|
||||||
[&](auto a, auto b) {return a->pos() + b*a->max();}, 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
template <SizeT DIR>
|
|
||||||
MultiIndex<Indices...>& MultiIndex<Indices...>::up()
|
|
||||||
{
|
|
||||||
static_assert(DIR < sizeof...(Indices), "DIR exceeds number of sub-indices");
|
|
||||||
IB::mPos += sfor_p<DIR,sizeof...(Indices)>
|
|
||||||
( [&](auto i) { return std::get<i>(mIPack)->max(); },
|
|
||||||
[&](auto a, auto b) { return a * b; } );
|
|
||||||
sfor_m<DIR+1,0>
|
|
||||||
( [&](auto i) {
|
|
||||||
auto& si = *std::get<i>( mIPack );
|
|
||||||
if(si.last() and i != 0) { si = 0; return true; }
|
|
||||||
else { ++si; return false; }
|
|
||||||
return false;
|
|
||||||
} );
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
template <SizeT DIR>
|
|
||||||
MultiIndex<Indices...>& MultiIndex<Indices...>::down()
|
|
||||||
{
|
|
||||||
static_assert(DIR < sizeof...(Indices), "DIR exceeds number of sub-indices");
|
|
||||||
IB::mPos -= sfor_p<DIR,sizeof...(Indices)>
|
|
||||||
( [&](auto i) { return std::get<i>(mIPack)->max(); },
|
|
||||||
[&](auto a, auto b) { return a * b; } );
|
|
||||||
sfor_m<DIR+1,0>
|
|
||||||
( [&](auto i) {
|
|
||||||
auto& si = *std::get<i>( mIPack );
|
|
||||||
if(si.first() and i != 0) { si = si.max()-1; return true; }
|
|
||||||
else { --si; return false; }
|
|
||||||
return false;
|
|
||||||
} );
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
template <SizeT N>
|
|
||||||
auto MultiIndex<Indices...>::get() const -> decltype( *std::get<N>( mIPack ) )&
|
|
||||||
{
|
|
||||||
return *std::get<N>(mIPack);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
template <SizeT N>
|
|
||||||
auto MultiIndex<Indices...>::getPtr() const -> decltype( std::get<N>( mIPack ) )&
|
|
||||||
{
|
|
||||||
return std::get<N>(mIPack);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
MultiIndex<Indices...>& MultiIndex<Indices...>::operator()(Sptr<Indices>&... indices)
|
|
||||||
{
|
|
||||||
return (*this)(std::make_tuple(indices...));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
MultiIndex<Indices...>& MultiIndex<Indices...>::operator()(const Tuple<Sptr<Indices>...>& indices)
|
|
||||||
{
|
|
||||||
sfor_pn<0,sizeof...(Indices)>
|
|
||||||
( [&](auto i) { std::get<i>(mIPack) = std::get<i>(indices); return 0; } );
|
|
||||||
RangeHelper::setIndexPack<sizeof...(Indices)-1>(mIPack, IB::mPos);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
IndexType MultiIndex<Indices...>::type() const
|
|
||||||
{
|
|
||||||
return IndexType::MULTI;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
MultiIndex<Indices...>& MultiIndex<Indices...>::operator=(SizeT pos)
|
|
||||||
{
|
|
||||||
IB::mPos = pos;
|
|
||||||
RangeHelper::setIndexPack<sizeof...(Indices)-1>(mIPack, pos);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
MultiIndex<Indices...>& MultiIndex<Indices...>::operator++()
|
|
||||||
{
|
|
||||||
sfor_m<sizeof...(Indices),0>
|
|
||||||
( [&](auto i) {
|
|
||||||
auto& si = *std::get<i>( mIPack );
|
|
||||||
if(si.last() and i != 0) { si = 0; return true; }
|
|
||||||
else { ++si; return false; }
|
|
||||||
return false;
|
|
||||||
} );
|
|
||||||
++IB::mPos;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
MultiIndex<Indices...>& MultiIndex<Indices...>::operator--()
|
|
||||||
{
|
|
||||||
sfor_m<sizeof...(Indices),0>
|
|
||||||
( [&](auto i) {
|
|
||||||
auto& si = *std::get<i>( mIPack );
|
|
||||||
if(si.first() and i != 0) { si = si.max()-1; return true; }
|
|
||||||
else { --si; return false; }
|
|
||||||
return false;
|
|
||||||
} );
|
|
||||||
--IB::mPos;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
int MultiIndex<Indices...>::pp(PtrId idxPtrNum)
|
|
||||||
{
|
|
||||||
const int tmp = RangeHelper::ppx<sizeof...(Indices)-1>(mIPack, mBlockSizes, idxPtrNum);
|
|
||||||
IB::mPos += tmp;
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
int MultiIndex<Indices...>::mm(PtrId idxPtrNum)
|
|
||||||
{
|
|
||||||
const int tmp = RangeHelper::mmx<sizeof...(Indices)-1>(mIPack, mBlockSizes, idxPtrNum);
|
|
||||||
IB::mPos -= tmp;
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
std::string MultiIndex<Indices...>::stringMeta() const
|
|
||||||
{
|
|
||||||
return std::dynamic_pointer_cast<RangeType>( IB::mRangePtr )->stringMeta(IB::mPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
typename MultiIndex<Indices...>::MetaType MultiIndex<Indices...>::meta() const
|
|
||||||
{
|
|
||||||
MetaType metaTuple;
|
|
||||||
sfor_pn<0,sizeof...(Indices)>
|
|
||||||
( [&](auto i) { std::get<i>(metaTuple) = std::get<i>(mIPack)->meta(); return 0; } );
|
|
||||||
return metaTuple;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
MultiIndex<Indices...>& MultiIndex<Indices...>::at(const MetaType& metaPos)
|
|
||||||
{
|
|
||||||
sfor_pn<0,sizeof...(Indices)>
|
|
||||||
( [&](auto i) { std::get<i>(mIPack)->at( std::get<i>(metaPos) ); return 0; } );
|
|
||||||
IB::mPos = sfor_m<sizeof...(Indices),0>
|
|
||||||
( [&](auto i) { return std::get<i>(mIPack); },
|
|
||||||
[&](auto a, auto b) {return a->pos() + b*a->max();}, 0 );
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
SizeT MultiIndex<Indices...>::dim()
|
|
||||||
{
|
|
||||||
return sizeof...(Indices);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
bool MultiIndex<Indices...>::first()
|
|
||||||
{
|
|
||||||
return IB::mPos == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
bool MultiIndex<Indices...>::last()
|
|
||||||
{
|
|
||||||
return IB::mPos == IB::mMax - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
Sptr<typename MultiIndex<Indices...>::RangeType>
|
|
||||||
MultiIndex<Indices...>::range()
|
|
||||||
{
|
|
||||||
return std::dynamic_pointer_cast<RangeType>( IB::mRangePtr );
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
template <SizeT N>
|
|
||||||
auto MultiIndex<Indices...>::getPtr() -> decltype( std::get<N>( mIPack ) )&
|
|
||||||
{
|
|
||||||
return std::get<N>(mIPack);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
SizeT MultiIndex<Indices...>::getStepSize(SizeT n)
|
|
||||||
{
|
|
||||||
if(n >= sizeof...(Indices)){
|
|
||||||
assert(0);
|
|
||||||
// throw !!
|
|
||||||
}
|
|
||||||
return mBlockSizes[n+1];
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
template <class Exprs>
|
|
||||||
auto MultiIndex<Indices...>::ifor(SizeT step, Exprs exs) const
|
|
||||||
{
|
|
||||||
return RangeHelper::mkFor<0>(step, mIPack, mBlockSizes, exs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
template <class Exprs>
|
|
||||||
auto MultiIndex<Indices...>::iforh(SizeT step, Exprs exs) const
|
|
||||||
{
|
|
||||||
return RangeHelper::mkForh<0>(step, mIPack, mBlockSizes, exs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
template <class Exprs>
|
|
||||||
auto MultiIndex<Indices...>::pifor(SizeT step, Exprs exs) const
|
|
||||||
{
|
|
||||||
return RangeHelper::mkPFor<0>(step, mIPack, mBlockSizes, exs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************
|
|
||||||
* MultiRangeFactory *
|
|
||||||
*************************/
|
|
||||||
|
|
||||||
template <class... Ranges>
|
|
||||||
MultiRangeFactory<Ranges...>::MultiRangeFactory(const Sptr<Ranges>&... rs)
|
|
||||||
{
|
|
||||||
mProd = Sptr< MultiRange<Ranges...> >( new MultiRange<Ranges...>( rs... ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Ranges>
|
|
||||||
MultiRangeFactory<Ranges...>::MultiRangeFactory(const typename MultiRange<Ranges...>::Space& st)
|
|
||||||
{
|
|
||||||
mProd = Sptr< MultiRange<Ranges...> >( new MultiRange<Ranges...>( st ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Ranges>
|
|
||||||
Sptr<RangeBase> MultiRangeFactory<Ranges...>::create()
|
|
||||||
{
|
|
||||||
mProd = checkIfCreated( std::dynamic_pointer_cast<oType>( mProd )->mSpace );
|
|
||||||
setSelf();
|
|
||||||
return mProd;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Ranges>
|
|
||||||
Sptr<RangeBase> MultiRangeFactory<Ranges...>::checkIfCreated(const Tuple<Sptr<Ranges>...>& ptp)
|
|
||||||
{
|
|
||||||
Sptr<RangeBase> out;
|
|
||||||
bool check = false;
|
|
||||||
for(auto& x: MultiRangeFactoryProductMap::mAleadyCreated){
|
|
||||||
if(x.second.size() == sizeof...(Ranges)){
|
|
||||||
check = sfor_p<0,sizeof...(Ranges)>
|
|
||||||
( [&](auto i) { return reinterpret_cast<PtrId>( std::get<i>(ptp).get() ) == x.second[i]; },
|
|
||||||
[&](auto a, auto b) { return a and b; } );
|
|
||||||
if(check){
|
|
||||||
out = x.first;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(not check){
|
|
||||||
Vector<PtrId> pv(sizeof...(Ranges));
|
|
||||||
sfor_pn<0,sizeof...(Ranges)>
|
|
||||||
( [&](auto i) { pv[i] = reinterpret_cast<PtrId>( std::get<i>(ptp).get() ); return 0; } );
|
|
||||||
MultiRangeFactoryProductMap::mAleadyCreated[mProd] = pv;
|
|
||||||
out = mProd;
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************
|
|
||||||
* MultiRange *
|
|
||||||
******************/
|
|
||||||
|
|
||||||
template <class... Ranges>
|
|
||||||
MultiRange<Ranges...>::MultiRange(const Sptr<Ranges>&... rs) : mSpace(std::make_tuple(rs...)) {}
|
|
||||||
|
|
||||||
template <class... Ranges>
|
|
||||||
MultiRange<Ranges...>::MultiRange(const Space& space) : mSpace( space ) {}
|
|
||||||
|
|
||||||
template <class... Ranges>
|
|
||||||
template <SizeT N>
|
|
||||||
auto MultiRange<Ranges...>::get() const -> decltype( *std::get<N>( mSpace ) )&
|
|
||||||
{
|
|
||||||
return *std::get<N>(mSpace);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Ranges>
|
|
||||||
SizeT MultiRange<Ranges...>::getMeta(const MetaType& metaPos) const
|
|
||||||
{
|
|
||||||
return RangeHelper::getMeta<sizeof...(Ranges)-1>(mSpace,metaPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Ranges>
|
|
||||||
template <SizeT N>
|
|
||||||
auto MultiRange<Ranges...>::getPtr() const -> decltype( std::get<N>( mSpace ) )&
|
|
||||||
{
|
|
||||||
return std::get<N>(mSpace);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Indices>
|
|
||||||
Sptr<RangeBase> MultiRange<Indices...>::sub(SizeT num) const
|
|
||||||
{
|
|
||||||
assert(num < sizeof...(Indices));
|
|
||||||
return sforx_p<0,sizeof...(Indices)>
|
|
||||||
( [&](auto i) { return std::dynamic_pointer_cast<RangeBase>(std::get<i>(mSpace)); },
|
|
||||||
[&](auto i) { return num != i;} );
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Ranges>
|
|
||||||
SizeT MultiRange<Ranges...>::dim() const
|
|
||||||
{
|
|
||||||
return sdim;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Ranges>
|
|
||||||
SizeT MultiRange<Ranges...>::size() const
|
|
||||||
{
|
|
||||||
return sfor_p<0,sizeof...(Ranges)>
|
|
||||||
( [&](auto i) { return std::get<i>(mSpace)->size(); },
|
|
||||||
[&](auto a, auto b) { return a * b; } );
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Ranges>
|
|
||||||
SpaceType MultiRange<Ranges...>::spaceType() const
|
|
||||||
{
|
|
||||||
return SpaceType::ANY;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Ranges>
|
|
||||||
const typename MultiRange<Ranges...>::Space& MultiRange<Ranges...>::space() const
|
|
||||||
{
|
|
||||||
return mSpace;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Ranges>
|
|
||||||
Vector<SizeT> MultiRange<Ranges...>::typeNum() const
|
|
||||||
{
|
|
||||||
Vector<SizeT> o;
|
|
||||||
RangeHelper::getTypeNum<sizeof...(Ranges)-1>(o,mSpace);
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Ranges>
|
|
||||||
SizeT MultiRange<Ranges...>::cmeta(char* target, SizeT pos) const
|
|
||||||
{
|
|
||||||
const SizeT off = cmetaSize();
|
|
||||||
MetaType* xtarget = reinterpret_cast<MetaType*>(target);
|
|
||||||
return RangeHelper::getCMeta<sizeof...(Ranges)-1>(xtarget,pos,mSpace,off);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Ranges>
|
|
||||||
SizeT MultiRange<Ranges...>::cmetaSize() const
|
|
||||||
{
|
|
||||||
return RangeHelper::getCMetaSize<0>(mSpace);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Ranges>
|
|
||||||
std::string MultiRange<Ranges...>::stringMeta(SizeT pos) const
|
|
||||||
{
|
|
||||||
auto i = begin();
|
|
||||||
i = pos;
|
|
||||||
return "[" + RangeHelper::getStringMeta<0>(i) + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Ranges>
|
|
||||||
Vector<char> MultiRange<Ranges...>::data() const
|
|
||||||
{
|
|
||||||
DataHeader h = dataHeader();
|
|
||||||
Vector<char> out;
|
|
||||||
//out.reserve(h.metaSize + sizeof(DataHeader));
|
|
||||||
char* hcp = reinterpret_cast<char*>(&h);
|
|
||||||
out.insert(out.end(), hcp, hcp + sizeof(DataHeader));
|
|
||||||
sfor_pn<0,sizeof...(Ranges)>
|
|
||||||
( [&](auto i) {
|
|
||||||
Vector<char> part = std::get<i>(mSpace)->data();
|
|
||||||
out.insert(out.end(), part.begin(), part.end());
|
|
||||||
return 0;
|
|
||||||
} );
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Ranges>
|
|
||||||
DataHeader MultiRange<Ranges...>::dataHeader() const
|
|
||||||
{
|
|
||||||
DataHeader h;
|
|
||||||
h.spaceType = static_cast<int>( SpaceType::ANY );
|
|
||||||
h.metaSize = sizeof...(Ranges);
|
|
||||||
h.multiple = 1;
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Ranges>
|
|
||||||
typename MultiRange<Ranges...>::IndexType MultiRange<Ranges...>::begin() const
|
|
||||||
{
|
|
||||||
MultiIndex<typename Ranges::IndexType...>
|
|
||||||
i( std::dynamic_pointer_cast<MultiRange<Ranges...> >
|
|
||||||
( Sptr<RangeBase>( RB::mThis ) ) );
|
|
||||||
i = 0;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Ranges>
|
|
||||||
typename MultiRange<Ranges...>::IndexType MultiRange<Ranges...>::end() const
|
|
||||||
{
|
|
||||||
MultiIndex<typename Ranges::IndexType...>
|
|
||||||
i( std::dynamic_pointer_cast<MultiRange<Ranges...> >
|
|
||||||
( Sptr<RangeBase>( RB::mThis )) );
|
|
||||||
i = size();
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Ranges>
|
|
||||||
template <class... ERanges>
|
|
||||||
auto MultiRange<Ranges...>::cat(const Sptr<MultiRange<ERanges...> >& erange)
|
|
||||||
-> Sptr<MultiRange<Ranges...,ERanges...> >
|
|
||||||
{
|
|
||||||
auto crange = std::tuple_cat(mSpace, erange->space());
|
|
||||||
MultiRangeFactory<Ranges...,ERanges...> rf(crange);
|
|
||||||
return std::dynamic_pointer_cast<MultiRange<Ranges...,ERanges...> >(rf.create());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue