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 {
|
|
|
|
return getIndex<N-1>(in, n);
|
|
|
|
}
|
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>();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
const auto& subIndex = index.getIndex<N>(0);
|
|
|
|
return Evaluation<N-1>::evaluate(index) * subIndex.size() + subIndex.pos();
|
|
|
|
}
|
|
|
|
};
|
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)
|
|
|
|
{
|
|
|
|
const auto& subIndex = index.getIndex<0>(0);
|
|
|
|
return subIndex.pos();
|
|
|
|
}
|
|
|
|
};
|
2017-02-16 13:12:20 +01:00
|
|
|
|
|
|
|
template <class MultiIndex>
|
|
|
|
inline void plus(MultiIndex& index, size_t digit, int num)
|
|
|
|
{
|
|
|
|
IndefinitIndexBase& si = index.getIndex(digit);
|
|
|
|
si.setPos( si.pos() + num );
|
|
|
|
size_t oor = si.outOfRange();
|
|
|
|
if(oor and digit != MultiIndex::mult - 1){
|
|
|
|
plus(index, digit + 1, 1);
|
2017-02-17 18:10:03 +01:00
|
|
|
plus(index, digit, oor - 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));
|
|
|
|
nameTuple<N-1>(iPack, name);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
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-16 13:12:20 +01:00
|
|
|
}
|
|
|
|
|
2017-02-17 18:10:03 +01:00
|
|
|
template <class... Indices>
|
|
|
|
MultiIndex<Indices...>::MultiIndex(Indices&&... inds) : mIPack(std::make_tuple(inds...)) {}
|
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-17 18:10:03 +01:00
|
|
|
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--()
|
2017-02-16 13:12:20 +01:00
|
|
|
{
|
2017-02-17 18:10:03 +01:00
|
|
|
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-17 18:10:03 +01:00
|
|
|
setPos( IIB::pos() + n );
|
2017-02-16 13:12:20 +01:00
|
|
|
plus(*this, 0, n);
|
|
|
|
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-17 18:10:03 +01:00
|
|
|
setPos( IIB::pos() - n );
|
2017-02-16 13:12:20 +01:00
|
|
|
plus(*this, 0, 0-n);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class... Indices>
|
|
|
|
size_t MultiIndex<Indices...>::evaluate(const MultiIndex<Indices...>& in) const
|
|
|
|
{
|
2017-02-17 18:10:03 +01:00
|
|
|
return Evaluation<sizeof...(Indices)-1>::evaluate(in);
|
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)
|
|
|
|
{
|
|
|
|
name(nm.own());
|
|
|
|
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-17 18:10:03 +01:00
|
|
|
TupleNamer<sizeof...(Indices)-1>::nameTuple(mIPack, nm);
|
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-16 13:12:20 +01:00
|
|
|
res *= getIndex(i).dim();
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class... Indices>
|
|
|
|
bool MultiIndex<Indices...>::link(IndefinitIndexBase* toLink)
|
|
|
|
{
|
2017-02-17 18:10:03 +01:00
|
|
|
if(toLink->rangeType() != IIB::rangeType() and toLink->name() == name()){
|
2017-02-16 13:12:20 +01:00
|
|
|
// throw !!
|
|
|
|
}
|
|
|
|
|
2017-02-17 18:10:03 +01:00
|
|
|
if(toLink->rangeType() == IIB::rangeType() and toLink->name() == name()){
|
|
|
|
if(IIB::mLinked == toLink){
|
2017-02-16 13:12:20 +01:00
|
|
|
return true; // dont link twice the same
|
|
|
|
}
|
2017-02-17 18:10:03 +01:00
|
|
|
else if(IIB::mLinked == nullptr){
|
|
|
|
IIB::mLinked = toLink;
|
2017-02-16 13:12:20 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else {
|
2017-02-17 18:10:03 +01:00
|
|
|
return IIB::mLinked->link(toLink);
|
2017-02-16 13:12:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return linkLower(toLink);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-17 18:10:03 +01:00
|
|
|
auto MultiIndex<Indices...>::getIndex(size_t x) -> decltype(std::get<N>(MultiIndex<Indices...>::IndexPack()))
|
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-17 18:10:03 +01:00
|
|
|
auto MultiIndex<Indices...>::getIndex(size_t x) const ->
|
|
|
|
decltype(std::get<N>(MultiIndex<Indices...>::IndexPack()))
|
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-17 18:10:03 +01:00
|
|
|
return IndexGetter<sizeof...(Indices)>::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 !!
|
|
|
|
}
|
|
|
|
MultiIndex<Indices...>* t = this;
|
2017-02-17 18:10:03 +01:00
|
|
|
return IndexGetter<sizeof...(Indices)>::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-16 13:12:20 +01:00
|
|
|
res |= getIndex(i).link(toLink);
|
|
|
|
}
|
|
|
|
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-16 13:12:20 +01:00
|
|
|
getIndex(i).linkTo(target);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************
|
|
|
|
* MultiRange *
|
|
|
|
******************/
|
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-17 18:10:03 +01:00
|
|
|
auto MultiRange<Ranges...>::get() -> 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>
|
|
|
|
auto MultiRange<Ranges...>::get() const -> decltype( std::get<N>(MultiRange<Ranges...>::SpaceType()) )
|
|
|
|
{
|
|
|
|
return std::get<N>(mSpace);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class... Ranges>
|
|
|
|
MultiIndex<typename Ranges::IndexType...> MultiRange<Ranges...>::begin() const
|
|
|
|
{
|
|
|
|
return MultiIndex<typename Ranges::IndexType...>(/*!!!!!!*/);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class... Ranges>
|
|
|
|
MultiIndex<typename Ranges::IndexType...> MultiRange<Ranges...>::end() const
|
|
|
|
{
|
|
|
|
return MultiIndex<typename Ranges::IndexType...>(/*!!!!!!*/);
|
|
|
|
}
|
2017-02-16 13:12:20 +01:00
|
|
|
}
|