2017-02-16 13:12:20 +01:00
|
|
|
|
2017-02-17 18:10:03 +01:00
|
|
|
#include "multi_range.h"
|
2017-02-16 13:12:20 +01:00
|
|
|
|
|
|
|
namespace MultiArrayTools
|
|
|
|
{
|
|
|
|
/*******************
|
|
|
|
* MultiIndexBase *
|
|
|
|
*******************/
|
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
2017-02-17 18:10:03 +01:00
|
|
|
template <size_t N>
|
|
|
|
struct IndexGetter
|
|
|
|
{
|
|
|
|
template <class MultiIndex>
|
|
|
|
static IndefinitIndexBase& getIndex(MultiIndex& in, size_t n)
|
|
|
|
{
|
|
|
|
if(n == N){
|
|
|
|
return in.getIndex<N>();
|
|
|
|
}
|
|
|
|
else {
|
2017-02-20 17:18:53 +01:00
|
|
|
return IndexGetter<N-1>::getIndex(in, n);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class MultiIndex>
|
|
|
|
static const IndefinitIndexBase& getIndex(const MultiIndex& in, size_t n)
|
|
|
|
{
|
|
|
|
if(n == N){
|
|
|
|
return in.getIndex<N>();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return IndexGetter<N-1>::getIndex(in, n);
|
2017-02-17 18:10:03 +01:00
|
|
|
}
|
2017-02-16 13:12:20 +01:00
|
|
|
}
|
2017-02-17 18:10:03 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct IndexGetter<0>
|
2017-02-16 13:12:20 +01:00
|
|
|
{
|
2017-02-17 18:10:03 +01:00
|
|
|
template <class MultiIndex>
|
|
|
|
static IndefinitIndexBase& getIndex(MultiIndex& in, size_t n)
|
|
|
|
{
|
|
|
|
return in.getIndex<0>();
|
|
|
|
}
|
2017-02-20 17:18:53 +01:00
|
|
|
|
|
|
|
template <class MultiIndex>
|
|
|
|
static const IndefinitIndexBase& getIndex(const MultiIndex& in, size_t n)
|
|
|
|
{
|
|
|
|
return in.getIndex<0>();
|
|
|
|
}
|
2017-02-17 18:10:03 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
template <size_t N>
|
|
|
|
struct Evaluation
|
2017-02-16 13:12:20 +01:00
|
|
|
{
|
2017-02-17 18:10:03 +01:00
|
|
|
template <class MultiIndex>
|
|
|
|
static size_t evaluate(const MultiIndex& index)
|
|
|
|
{
|
2017-02-21 17:41:48 +01:00
|
|
|
const auto& subIndex = index.template getIndex<N>();
|
2017-02-20 19:14:22 +01:00
|
|
|
return Evaluation<N-1>::evaluate(index) * subIndex.max() + subIndex.pos();
|
2017-02-17 18:10:03 +01:00
|
|
|
}
|
|
|
|
};
|
2017-02-16 13:12:20 +01:00
|
|
|
|
2017-02-17 18:10:03 +01:00
|
|
|
template <>
|
|
|
|
struct Evaluation<0>
|
2017-02-16 13:12:20 +01:00
|
|
|
{
|
2017-02-17 18:10:03 +01:00
|
|
|
template <class MultiIndex>
|
|
|
|
static size_t evaluate(const MultiIndex& index)
|
|
|
|
{
|
2017-02-21 17:41:48 +01:00
|
|
|
const auto& subIndex = index.template getIndex<0>();
|
2017-02-20 19:14:22 +01:00
|
|
|
return subIndex.pos();
|
2017-02-17 18:10:03 +01:00
|
|
|
}
|
|
|
|
};
|
2017-02-16 13:12:20 +01:00
|
|
|
|
|
|
|
template <class MultiIndex>
|
|
|
|
inline void plus(MultiIndex& index, size_t digit, int num)
|
|
|
|
{
|
2017-02-20 17:18:53 +01:00
|
|
|
IndefinitIndexBase& si = index.get(digit);
|
2017-02-16 13:12:20 +01:00
|
|
|
si.setPos( si.pos() + num );
|
|
|
|
size_t oor = si.outOfRange();
|
2017-02-22 00:43:38 +01:00
|
|
|
if(oor and digit != 0){
|
|
|
|
plus(index, digit - 1, 1);
|
2017-02-22 13:34:32 +01:00
|
|
|
plus(index, digit, -si.max());
|
2017-02-16 13:12:20 +01:00
|
|
|
}
|
|
|
|
}
|
2017-02-16 16:06:23 +01:00
|
|
|
|
|
|
|
template <size_t N>
|
2017-02-17 18:10:03 +01:00
|
|
|
struct TupleNamer
|
2017-02-16 16:06:23 +01:00
|
|
|
{
|
2017-02-17 18:10:03 +01:00
|
|
|
template <class IndexPack, class Name>
|
|
|
|
static void nameTuple(IndexPack& iPack, Name& name)
|
|
|
|
{
|
|
|
|
std::get<N>(iPack).name(name.get(N));
|
2017-02-20 17:18:53 +01:00
|
|
|
TupleNamer<N-1>::nameTuple(iPack, name);
|
2017-02-17 18:10:03 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-02-16 16:06:23 +01:00
|
|
|
template <>
|
2017-02-17 18:10:03 +01:00
|
|
|
struct TupleNamer<0>
|
2017-02-16 16:06:23 +01:00
|
|
|
{
|
2017-02-17 18:10:03 +01:00
|
|
|
template <class IndexPack, class Name>
|
|
|
|
static void nameTuple(IndexPack& iPack, Name& name)
|
|
|
|
{
|
|
|
|
std::get<0>(iPack).name(name.get(0));
|
|
|
|
}
|
|
|
|
};
|
2017-02-22 13:34:32 +01:00
|
|
|
|
|
|
|
template <size_t N>
|
|
|
|
struct IndexSubOrder
|
|
|
|
{
|
|
|
|
template <class IndexPack>
|
|
|
|
static void subOrd(IndexPack& iPack, IndefinitIndexBase* major)
|
|
|
|
{
|
|
|
|
std::get<N>(iPack).subOrd(major);
|
|
|
|
IndexSubOrder<N-1>::subOrd(iPack, major);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct IndexSubOrder<0>
|
|
|
|
{
|
|
|
|
template <class IndexPack>
|
|
|
|
static void subOrd(IndexPack& iPack, IndefinitIndexBase* major)
|
|
|
|
{
|
|
|
|
std::get<0>(iPack).subOrd(major);
|
|
|
|
}
|
|
|
|
};
|
2017-02-16 13:12:20 +01:00
|
|
|
}
|
|
|
|
|
2017-02-17 18:10:03 +01:00
|
|
|
template <class... Indices>
|
2017-02-21 17:41:48 +01:00
|
|
|
MultiIndex<Indices...>::MultiIndex(RangeBase<MultiIndex<Indices...> > const* range,
|
|
|
|
Indices&&... inds) : IndexBase<MultiIndex<Indices...> >(range),
|
|
|
|
mIPack(std::make_tuple(inds...))
|
2017-02-20 17:18:53 +01:00
|
|
|
{
|
2017-02-22 13:34:32 +01:00
|
|
|
IndexSubOrder<sizeof...(Indices)-1>::subOrd(mIPack, this);
|
2017-02-20 17:18:53 +01:00
|
|
|
IIB::mPos = evaluate(*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class... Indices>
|
2017-02-21 17:41:48 +01:00
|
|
|
MultiIndex<Indices...>::MultiIndex(RangeBase<MultiIndex<Indices...> > const* range,
|
|
|
|
const IndexPack& ipack) : IndexBase<MultiIndex<Indices...> >(range),
|
|
|
|
mIPack(ipack)
|
2017-02-20 17:18:53 +01:00
|
|
|
{
|
2017-02-22 13:34:32 +01:00
|
|
|
IndexSubOrder<sizeof...(Indices)-1>::subOrd(mIPack, this);
|
2017-02-20 17:18:53 +01:00
|
|
|
IIB::mPos = evaluate(*this);
|
|
|
|
}
|
2017-02-22 19:06:23 +01:00
|
|
|
|
|
|
|
template <class... Indices>
|
|
|
|
MultiIndex<Indices...>::~MultiIndex()
|
|
|
|
{
|
|
|
|
IndexSubOrder<sizeof...(Indices)-1>::subOrd(mIPack, nullptr);
|
|
|
|
}
|
|
|
|
|
2017-02-16 13:12:20 +01:00
|
|
|
template <class... Indices>
|
2017-02-17 18:10:03 +01:00
|
|
|
MultiIndex<Indices...>& MultiIndex<Indices...>::operator++()
|
2017-02-16 13:12:20 +01:00
|
|
|
{
|
2017-02-22 00:43:38 +01:00
|
|
|
plus(*this, sizeof...(Indices)-1, 1);
|
|
|
|
IIB::setPos( evaluate(*this) );
|
2017-02-16 13:12:20 +01:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class... Indices>
|
2017-02-17 18:10:03 +01:00
|
|
|
MultiIndex<Indices...>& MultiIndex<Indices...>::operator--()
|
2017-02-16 13:12:20 +01:00
|
|
|
{
|
2017-02-20 17:18:53 +01:00
|
|
|
IIB::setPos( IIB::pos() - 1 );
|
2017-02-16 13:12:20 +01:00
|
|
|
plus(*this, 0, -1);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class... Indices>
|
2017-02-17 18:10:03 +01:00
|
|
|
MultiIndex<Indices...>& MultiIndex<Indices...>::operator+=(int n)
|
2017-02-16 13:12:20 +01:00
|
|
|
{
|
2017-02-22 13:34:32 +01:00
|
|
|
plus(*this, sizeof...(Indices)-1, 1);
|
|
|
|
IIB::setPos( evaluate(*this) );
|
2017-02-16 13:12:20 +01:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class... Indices>
|
2017-02-17 18:10:03 +01:00
|
|
|
MultiIndex<Indices...>& MultiIndex<Indices...>::operator-=(int n)
|
2017-02-16 13:12:20 +01:00
|
|
|
{
|
2017-02-20 17:18:53 +01:00
|
|
|
IIB::setPos( IIB::pos() - n );
|
2017-02-16 13:12:20 +01:00
|
|
|
plus(*this, 0, 0-n);
|
|
|
|
return *this;
|
|
|
|
}
|
2017-02-20 17:18:53 +01:00
|
|
|
|
2017-02-22 00:43:38 +01:00
|
|
|
template <class... Indices>
|
|
|
|
bool MultiIndex<Indices...>::operator==(const MultiIndex<Indices...>& in)
|
|
|
|
{
|
|
|
|
return IB::mRange == in.mRange and IIB::pos() == in.pos();
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class... Indices>
|
|
|
|
bool MultiIndex<Indices...>::operator!=(const MultiIndex<Indices...>& in)
|
|
|
|
{
|
|
|
|
return IB::mRange != in.mRange or IIB::pos() != in.pos();
|
|
|
|
}
|
|
|
|
|
2017-02-20 17:18:53 +01:00
|
|
|
template <class... Indices>
|
|
|
|
IndefinitIndexBase& MultiIndex<Indices...>::operator=(size_t pos)
|
|
|
|
{
|
|
|
|
IIB::setPos( pos );
|
2017-02-20 19:14:22 +01:00
|
|
|
//setIndexPack(mIPack, pos); // -> implement !!!
|
2017-02-20 17:18:53 +01:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class... Indices>
|
|
|
|
MultiRangeType MultiIndex<Indices...>::rangeType() const
|
|
|
|
{
|
|
|
|
return IB::mRange->type();
|
|
|
|
}
|
2017-02-16 13:12:20 +01:00
|
|
|
|
|
|
|
template <class... Indices>
|
|
|
|
size_t MultiIndex<Indices...>::evaluate(const MultiIndex<Indices...>& in) const
|
|
|
|
{
|
2017-02-22 00:43:38 +01:00
|
|
|
size_t res = Evaluation<sizeof...(Indices)-1>::evaluate(in);
|
|
|
|
return res;
|
2017-02-16 13:12:20 +01:00
|
|
|
}
|
|
|
|
|
2017-02-16 16:06:23 +01:00
|
|
|
template <class... Indices>
|
|
|
|
void MultiIndex<Indices...>::name(const Name& nm)
|
|
|
|
{
|
2017-02-21 21:47:40 +01:00
|
|
|
IIB::mName = nm.own();
|
2017-02-16 16:06:23 +01:00
|
|
|
if(nm.size() >= sizeof...(Indices)){
|
2017-02-17 18:10:03 +01:00
|
|
|
TupleNamer<sizeof...(Indices)-1>::nameTuple(mIPack, nm);
|
2017-02-16 16:06:23 +01:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
Name nm2 = nm;
|
|
|
|
nm2.autoName(sizeof...(Indices));
|
2017-02-21 21:47:40 +01:00
|
|
|
TupleNamer<sizeof...(Indices)-1>::nameTuple(mIPack, nm2);
|
2017-02-16 16:06:23 +01:00
|
|
|
}
|
|
|
|
}
|
2017-02-20 17:18:53 +01:00
|
|
|
|
|
|
|
template <class... Indices>
|
|
|
|
MultiIndex<Indices...>& MultiIndex<Indices...>::operator()(Indices&&... inds)
|
|
|
|
{
|
|
|
|
mIPack = std::make_tuple(inds...);
|
2017-02-22 13:34:32 +01:00
|
|
|
IndexSubOrder<sizeof...(Indices)-1>::subOrd(mIPack, this);
|
2017-02-20 17:18:53 +01:00
|
|
|
IIB::mPos = evaluate(*this);
|
|
|
|
return *this;
|
|
|
|
}
|
2017-02-21 17:41:48 +01:00
|
|
|
|
|
|
|
template <class... Indices>
|
|
|
|
MultiIndex<Indices...>& MultiIndex<Indices...>::operator()(const Indices&... inds)
|
|
|
|
{
|
|
|
|
mIPack = std::make_tuple(Indices(inds)...);
|
2017-02-22 13:34:32 +01:00
|
|
|
IndexSubOrder<sizeof...(Indices)-1>::subOrd(mIPack, this);
|
2017-02-21 17:41:48 +01:00
|
|
|
IIB::mPos = evaluate(*this);
|
|
|
|
return *this;
|
|
|
|
}
|
2017-02-16 16:06:23 +01:00
|
|
|
|
2017-02-16 13:12:20 +01:00
|
|
|
template <class... Indices>
|
|
|
|
size_t MultiIndex<Indices...>::dim() const
|
|
|
|
{
|
|
|
|
size_t res = 1;
|
2017-02-17 18:10:03 +01:00
|
|
|
for(size_t i = 0; i != sizeof...(Indices); ++i){
|
2017-02-20 17:18:53 +01:00
|
|
|
res *= get(i).dim();
|
2017-02-16 13:12:20 +01:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class... Indices>
|
|
|
|
bool MultiIndex<Indices...>::link(IndefinitIndexBase* toLink)
|
|
|
|
{
|
2017-02-22 19:06:23 +01:00
|
|
|
if(toLink->rangeType() != rangeType() and
|
|
|
|
toLink->name() == IIB::name() and
|
|
|
|
not (IIB::name() == "master")){
|
2017-02-16 13:12:20 +01:00
|
|
|
// throw !!
|
2017-02-22 13:34:32 +01:00
|
|
|
assert(0);
|
2017-02-16 13:12:20 +01:00
|
|
|
}
|
2017-02-20 19:14:22 +01:00
|
|
|
if(toLink->rangeType() == rangeType() and toLink->name() == IIB::name()){
|
2017-02-22 19:06:23 +01:00
|
|
|
if(IIB::mLinked == toLink or IIB::mSoftLinked == toLink){
|
2017-02-16 13:12:20 +01:00
|
|
|
return true; // dont link twice the same
|
|
|
|
}
|
2017-02-22 19:06:23 +01:00
|
|
|
else if(IIB::mLinked == nullptr and IIB::mSoftLinked == nullptr){
|
2017-02-17 18:10:03 +01:00
|
|
|
IIB::mLinked = toLink;
|
2017-02-16 13:12:20 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else {
|
2017-02-22 19:06:23 +01:00
|
|
|
if(IIB::mLinked == nullptr){
|
|
|
|
return IIB::mSoftLinked->link(toLink);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return IIB::mLinked->link(toLink);
|
|
|
|
}
|
2017-02-16 13:12:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2017-02-22 13:34:32 +01:00
|
|
|
if(linkLower(toLink)){
|
2017-02-22 19:06:23 +01:00
|
|
|
IIB::mSoftLinked = IIB::mLinked;
|
2017-02-22 13:34:32 +01:00
|
|
|
IIB::mLinked = nullptr;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return false;
|
|
|
|
}
|
2017-02-16 13:12:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-17 18:10:03 +01:00
|
|
|
template <class... Indices>
|
2017-02-16 13:12:20 +01:00
|
|
|
template <size_t N>
|
2017-02-21 17:41:48 +01:00
|
|
|
typename std::tuple_element<N, std::tuple<Indices...> >::type& MultiIndex<Indices...>::getIndex()
|
2017-02-16 13:12:20 +01:00
|
|
|
{
|
|
|
|
return std::get<N>(mIPack);
|
|
|
|
}
|
2017-02-17 18:10:03 +01:00
|
|
|
|
|
|
|
template <class... Indices>
|
2017-02-16 13:12:20 +01:00
|
|
|
template <size_t N>
|
2017-02-21 17:41:48 +01:00
|
|
|
typename std::tuple_element<N, std::tuple<Indices...> >::type const& MultiIndex<Indices...>::getIndex() const
|
2017-02-16 13:12:20 +01:00
|
|
|
{
|
|
|
|
return std::get<N>(mIPack);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class... Indices>
|
2017-02-17 18:10:03 +01:00
|
|
|
IndefinitIndexBase& MultiIndex<Indices...>::get(size_t n)
|
2017-02-16 13:12:20 +01:00
|
|
|
{
|
2017-02-17 18:10:03 +01:00
|
|
|
if(n >= sizeof...(Indices)){
|
2017-02-16 13:12:20 +01:00
|
|
|
// throw !!
|
|
|
|
}
|
|
|
|
MultiIndex<Indices...>* t = this;
|
2017-02-20 17:18:53 +01:00
|
|
|
return IndexGetter<sizeof...(Indices)-1>::getIndex(*t, n);
|
2017-02-16 13:12:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class... Indices>
|
2017-02-17 18:10:03 +01:00
|
|
|
const IndefinitIndexBase& MultiIndex<Indices...>::get(size_t n) const
|
2017-02-16 13:12:20 +01:00
|
|
|
{
|
2017-02-17 18:10:03 +01:00
|
|
|
if(n >= sizeof...(Indices)){
|
2017-02-16 13:12:20 +01:00
|
|
|
// throw !!
|
|
|
|
}
|
2017-02-20 17:18:53 +01:00
|
|
|
MultiIndex<Indices...> const* t = this;
|
|
|
|
return IndexGetter<sizeof...(Indices)-1>::getIndex(*t, n);
|
2017-02-16 13:12:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class... Indices>
|
|
|
|
bool MultiIndex<Indices...>::linkLower(IndefinitIndexBase* toLink)
|
|
|
|
{
|
|
|
|
bool res = false;
|
2017-02-17 18:10:03 +01:00
|
|
|
for(size_t i = 0; i != sizeof...(Indices); ++i){
|
2017-02-20 17:18:53 +01:00
|
|
|
res |= get(i).link(toLink);
|
2017-02-16 13:12:20 +01:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class... Indices>
|
|
|
|
void MultiIndex<Indices...>::linkTo(IndefinitIndexBase* target)
|
|
|
|
{
|
|
|
|
target->link(this);
|
2017-02-17 18:10:03 +01:00
|
|
|
for(size_t i = 0; i != sizeof...(Indices); ++i){
|
2017-02-20 17:18:53 +01:00
|
|
|
get(i).linkTo(target);
|
2017-02-16 13:12:20 +01:00
|
|
|
}
|
|
|
|
}
|
2017-02-21 17:41:48 +01:00
|
|
|
/*
|
|
|
|
template <size_t N>
|
|
|
|
struct RangeAssigner
|
|
|
|
{
|
|
|
|
template <class... Indices>
|
|
|
|
static void assignRange(const RangeBase<MultiIndex<Indices...> >& multiRange,
|
|
|
|
MultiIndex<Indices...>& multiIndex)
|
|
|
|
{
|
|
|
|
multiIndex.template getIndex<N>().assignRange(nullptr &multiRange.template getRange<N>());
|
|
|
|
RangeAssigner<N-1>::assignRange(multiRange, multiIndex);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct RangeAssigner<0>
|
|
|
|
{
|
|
|
|
template <class... Indices>
|
|
|
|
static void assignRange(const RangeBase<MultiIndex<Indices...> >& multiRange,
|
|
|
|
MultiIndex<Indices...>& multiIndex)
|
|
|
|
{
|
|
|
|
multiIndex.template getIndex<0>().assignRange(nullptr &multiRange.template getRange<0>());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class... Indices>
|
|
|
|
void MultiIndex<Indices...>::assignRange(RangeBase<MultiIndex<Indices...> > const* range)
|
|
|
|
{
|
|
|
|
if(IB::toNull()){
|
|
|
|
IB::mRange = range;
|
|
|
|
}
|
|
|
|
MultiIndex<Indices...>& thisRef = *this;
|
|
|
|
RangeAssigner<sizeof...(Indices)-1>::assignRange(*range, thisRef);
|
|
|
|
}*/
|
2017-02-16 13:12:20 +01:00
|
|
|
|
2017-02-21 17:41:48 +01:00
|
|
|
|
2017-02-16 13:12:20 +01:00
|
|
|
/******************
|
|
|
|
* MultiRange *
|
|
|
|
******************/
|
2017-02-17 18:10:03 +01:00
|
|
|
|
2017-02-20 17:18:53 +01:00
|
|
|
template <class... Ranges>
|
|
|
|
MultiRange<Ranges...>::MultiRange(const Ranges&... rs) : mSpace(std::make_tuple(rs...)) {}
|
|
|
|
|
2017-02-17 18:10:03 +01:00
|
|
|
template <class... Ranges>
|
2017-02-16 13:12:20 +01:00
|
|
|
template <size_t N>
|
2017-02-20 17:18:53 +01:00
|
|
|
auto MultiRange<Ranges...>::getRange() -> decltype( std::get<N>(MultiRange<Ranges...>::SpaceType()) )
|
2017-02-16 13:12:20 +01:00
|
|
|
{
|
|
|
|
return std::get<N>(mSpace);
|
|
|
|
}
|
2017-02-17 18:10:03 +01:00
|
|
|
|
|
|
|
template <class... Ranges>
|
|
|
|
template <size_t N>
|
2017-02-20 17:18:53 +01:00
|
|
|
auto MultiRange<Ranges...>::getRange() const -> decltype( std::get<N>(MultiRange<Ranges...>::SpaceType()) )
|
2017-02-17 18:10:03 +01:00
|
|
|
{
|
|
|
|
return std::get<N>(mSpace);
|
|
|
|
}
|
|
|
|
|
2017-02-20 17:18:53 +01:00
|
|
|
template <size_t N>
|
|
|
|
struct TupleSize
|
|
|
|
{
|
|
|
|
template <class RangeTuple>
|
|
|
|
static size_t getSize(const RangeTuple& rt)
|
|
|
|
{
|
|
|
|
return std::get<N>(rt).size() * TupleSize<N-1>::getSize(rt);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct TupleSize<0>
|
|
|
|
{
|
|
|
|
template <class RangeTuple>
|
|
|
|
static size_t getSize(const RangeTuple& rt)
|
|
|
|
{
|
|
|
|
return std::get<0>(rt).size();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class... Ranges>
|
|
|
|
size_t MultiRange<Ranges...>::size() const
|
|
|
|
{
|
|
|
|
return TupleSize<sizeof...(Ranges)-1>::getSize(mSpace);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <size_t N>
|
|
|
|
struct IndexSetter
|
|
|
|
{
|
|
|
|
template <class... Ranges>
|
|
|
|
static void setBegin(std::tuple<typename Ranges::IndexType...>& i, const std::tuple<Ranges...>& r)
|
|
|
|
{
|
|
|
|
std::get<N>(i) = std::get<N>(r).begin();
|
|
|
|
IndexSetter<N-1>::setBegin(i,r);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class... Ranges>
|
|
|
|
static void setEnd(std::tuple<typename Ranges::IndexType...>& i, const std::tuple<Ranges...>& r)
|
|
|
|
{
|
|
|
|
std::get<N>(i) = std::get<N>(r).end();
|
2017-02-22 00:43:38 +01:00
|
|
|
std::get<N>(i) -= 1;
|
2017-02-20 17:18:53 +01:00
|
|
|
IndexSetter<N-1>::setEnd(i,r);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct IndexSetter<0>
|
|
|
|
{
|
|
|
|
template <class... Ranges>
|
|
|
|
static void setBegin(std::tuple<typename Ranges::IndexType...>& i, const std::tuple<Ranges...>& r)
|
|
|
|
{
|
|
|
|
std::get<0>(i) = std::get<0>(r).begin();
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class... Ranges>
|
|
|
|
static void setEnd(std::tuple<typename Ranges::IndexType...>& i, const std::tuple<Ranges...>& r)
|
|
|
|
{
|
|
|
|
std::get<0>(i) = std::get<0>(r).end();
|
2017-02-22 00:43:38 +01:00
|
|
|
std::get<0>(i) -= 1;
|
2017-02-20 17:18:53 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <size_t N>
|
|
|
|
struct RangeVecBuilder
|
|
|
|
{
|
|
|
|
template <class... Ranges>
|
|
|
|
static void buildRangeVec(std::vector<MultiRangeType>& rvec, const std::tuple<Ranges...>& rs)
|
|
|
|
{
|
|
|
|
rvec.push_back(std::get<sizeof...(Ranges)-N-1>(rs).type());
|
|
|
|
RangeVecBuilder<N-1>::buildRangeVec(rvec, rs);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
template <>
|
|
|
|
struct RangeVecBuilder<0>
|
|
|
|
{
|
|
|
|
template <class... Ranges>
|
|
|
|
static void buildRangeVec(std::vector<MultiRangeType>& rvec, const std::tuple<Ranges...>& rs)
|
|
|
|
{
|
|
|
|
rvec.push_back(std::get<sizeof...(Ranges)-1>(rs).type());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class... Ranges>
|
|
|
|
MultiRangeType MultiRange<Ranges...>::type() const
|
|
|
|
{
|
|
|
|
std::vector<MultiRangeType> rvec;
|
|
|
|
RangeVecBuilder<sizeof...(Ranges)-1>::buildRangeVec(rvec, mSpace);
|
|
|
|
return MultiRangeType(rvec);
|
|
|
|
}
|
|
|
|
|
2017-02-17 18:10:03 +01:00
|
|
|
template <class... Ranges>
|
|
|
|
MultiIndex<typename Ranges::IndexType...> MultiRange<Ranges...>::begin() const
|
|
|
|
{
|
2017-02-20 17:18:53 +01:00
|
|
|
std::tuple<typename Ranges::IndexType...> is;
|
|
|
|
IndexSetter<sizeof...(Ranges)-1>::setBegin(is,mSpace);
|
2017-02-21 17:41:48 +01:00
|
|
|
return MultiIndex<typename Ranges::IndexType...>(this, is);
|
2017-02-17 18:10:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class... Ranges>
|
|
|
|
MultiIndex<typename Ranges::IndexType...> MultiRange<Ranges...>::end() const
|
|
|
|
{
|
2017-02-20 17:18:53 +01:00
|
|
|
std::tuple<typename Ranges::IndexType...> is;
|
|
|
|
IndexSetter<sizeof...(Ranges)-1>::setEnd(is,mSpace);
|
2017-02-22 00:43:38 +01:00
|
|
|
return ++MultiIndex<typename Ranges::IndexType...>(this, is);
|
2017-02-17 18:10:03 +01:00
|
|
|
}
|
2017-02-16 13:12:20 +01:00
|
|
|
}
|