Slice works... fix the 'major bug'

This commit is contained in:
Christian Zimmermann 2017-02-28 19:29:52 +01:00
parent 2c12332abb
commit 27ddea16f6
11 changed files with 215 additions and 128 deletions

View file

@ -6,7 +6,7 @@ namespace MultiArrayTools
/************************ /************************
* IndefinitIndexBase * * IndefinitIndexBase *
************************/ ************************/
IndefinitIndexBase::~IndefinitIndexBase() IndefinitIndexBase::~IndefinitIndexBase()
{ {
freeLinked(); freeLinked();
@ -17,26 +17,31 @@ namespace MultiArrayTools
size_t IndefinitIndexBase::pos() const size_t IndefinitIndexBase::pos() const
{ {
assert(not virt());
return mPos; return mPos;
} }
const std::string& IndefinitIndexBase::name() const const std::string& IndefinitIndexBase::name() const
{ {
assert(not virt());
return mName; return mName;
} }
void IndefinitIndexBase::name(const std::string& str) void IndefinitIndexBase::name(const std::string& str)
{ {
assert(not virt());
mName = str; mName = str;
} }
void IndefinitIndexBase::name(const Name& nm) void IndefinitIndexBase::name(const Name& nm)
{ {
assert(not virt());
mName = nm.own(); mName = nm.own();
} }
bool IndefinitIndexBase::link(IndefinitIndexBase* toLink) bool IndefinitIndexBase::link(IndefinitIndexBase* toLink)
{ {
assert(not virt());
if(toLink->rangeType() != rangeType() and toLink->name() == name()){ if(toLink->rangeType() != rangeType() and toLink->name() == name()){
assert(0); assert(0);
// throw !! // throw !!
@ -72,11 +77,13 @@ namespace MultiArrayTools
bool IndefinitIndexBase::linked() const bool IndefinitIndexBase::linked() const
{ {
assert(not virt());
return mLinked != nullptr; return mLinked != nullptr;
} }
void IndefinitIndexBase::setPos(size_t pos) void IndefinitIndexBase::setPos(size_t pos)
{ {
assert(not virt());
mPos = pos; mPos = pos;
if(linked()){ if(linked()){
mLinked->setPos(mPos); mLinked->setPos(mPos);
@ -86,22 +93,26 @@ namespace MultiArrayTools
size_t IndefinitIndexBase::max() const size_t IndefinitIndexBase::max() const
{ {
assert(not virt());
return static_cast<size_t>( -1 ); return static_cast<size_t>( -1 );
} }
size_t IndefinitIndexBase::outOfRange() const size_t IndefinitIndexBase::outOfRange() const
{ {
assert(not virt());
int res = pos() - max() + 1; int res = pos() - max() + 1;
return res > 0 ? static_cast<size_t>(res) : 0; return res > 0 ? static_cast<size_t>(res) : 0;
} }
bool IndefinitIndexBase::toNull() const bool IndefinitIndexBase::toNull() const
{ {
assert(not virt());
return true; return true;
} }
void IndefinitIndexBase::evalMajor() void IndefinitIndexBase::evalMajor()
{ {
assert(not virt());
if(not master()){ if(not master()){
mMajor->eval(); mMajor->eval();
} }
@ -109,11 +120,13 @@ namespace MultiArrayTools
bool IndefinitIndexBase::master() bool IndefinitIndexBase::master()
{ {
assert(not virt());
return mMajor == nullptr; return mMajor == nullptr;
} }
void IndefinitIndexBase::subOrd(IndefinitIndexBase* major) void IndefinitIndexBase::subOrd(IndefinitIndexBase* major)
{ {
assert(not virt());
mMajor = major; mMajor = major;
} }
@ -127,33 +140,31 @@ namespace MultiArrayTools
template <class Index> template <class Index>
size_t IndexBase<Index>::max() const size_t IndexBase<Index>::max() const
{ {
assert(not virt());
return mRange->size(); return mRange->size();
} }
template <class Index> template <class Index>
bool IndexBase<Index>::toNull() const bool IndexBase<Index>::toNull() const
{ {
assert(not virt());
return mRange == nullptr; return mRange == nullptr;
} }
template <class Index> template <class Index>
void IndexBase<Index>::assignRange(RangeBase<Index> const* range) void IndexBase<Index>::assignRange(RangeBase<Index> const* range)
{ {
assert(not virt());
if(toNull()){ if(toNull()){
mRange = range; mRange = range;
} }
} }
/*
template <class Index> template <class Index>
void IndexBase<Index>::eval() void IndexBase<Index>::eval()
{ {
CHECK;
setPos( evaluate(*dynamic_cast<Index const*>( this )) ); setPos( evaluate(*dynamic_cast<Index const*>( this )) );
} }*/
template <class Index>
void IndexBase<Index>::copyPos(const Index& in)
{
IIB::setPos(in.pos());
}
} }

View file

@ -56,6 +56,8 @@ namespace MultiArrayTools
virtual bool master(); virtual bool master();
virtual void subOrd(IndefinitIndexBase* major); virtual void subOrd(IndefinitIndexBase* major);
virtual bool virt() const { return true; }
protected: protected:
@ -83,9 +85,8 @@ namespace MultiArrayTools
virtual void assignRange(RangeBase<Index> const* range); virtual void assignRange(RangeBase<Index> const* range);
virtual void eval() override; //virtual void eval() override;
virtual void copyPos(const Index& in) = 0;
virtual void copyPos(const Index& in);
protected: protected:

View file

@ -16,9 +16,9 @@ namespace MultiArrayTools
} }
template <typename T> template <typename T>
IndefinitIndexBase* MultiArrayOperationBase<T>::index() IndefinitIndexBase& MultiArrayOperationBase<T>::index()
{ {
return mIibPtr; return *mIibPtr;
} }
/********************************* /*********************************
@ -43,7 +43,7 @@ namespace MultiArrayTools
MultiArrayOperationRoot<T,Range>::makeSlice(MultiArrayOperationRoot<T,RangeX>& in) MultiArrayOperationRoot<T,Range>::makeSlice(MultiArrayOperationRoot<T,RangeX>& in)
{ {
Slice<T,Range,RangeX>& sl = dynamic_cast<Slice<T,Range,RangeX>&>( mArrayRef ); Slice<T,Range,RangeX>& sl = dynamic_cast<Slice<T,Range,RangeX>&>( mArrayRef );
sl.set(in.mArrayRef, name(), &in.index(), in.name()); sl.set(in.mArrayRef, name(), dynamic_cast<typename RangeX::IndexType&>( in.index() ), in.name());
return *this; return *this;
} }
@ -186,6 +186,13 @@ namespace MultiArrayTools
{ {
return mNm; return mNm;
} }
template <typename T, class Range>
MultiArrayOperationRoot<T,Range>& MultiArrayOperationRoot<T,Range>::operator[](const IndexType& ind)
{
mIndex.copyPos(ind);
return *this;
}
/***************************** /*****************************
* MultiArrayOperation * * MultiArrayOperation *

View file

@ -21,7 +21,7 @@ namespace MultiArrayTools
virtual ~MultiArrayOperationBase(); virtual ~MultiArrayOperationBase();
virtual size_t argNum() const = 0; virtual size_t argNum() const = 0;
IndefinitIndexBase* index(); IndefinitIndexBase& index();
virtual void linkIndicesTo(IndefinitIndexBase* target) const = 0; virtual void linkIndicesTo(IndefinitIndexBase* target) const = 0;
virtual T& get() = 0; virtual T& get() = 0;
@ -72,8 +72,6 @@ namespace MultiArrayTools
virtual size_t argNum() const override; virtual size_t argNum() const override;
IndexType& index();
// set index -> implement !!!!! // set index -> implement !!!!!
MultiArrayOperationRoot<T,Range>& operator[](const IndexType& ind); MultiArrayOperationRoot<T,Range>& operator[](const IndexType& ind);

View file

@ -147,9 +147,116 @@ namespace MultiArrayTools
target.template getIndex<0>().copyPos( source.template getIndex<0>() ); target.template getIndex<0>().copyPos( source.template getIndex<0>() );
} }
}; };
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 <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();
std::get<N>(i) -= 1;
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();
std::get<0>(i) -= 1;
}
};
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... Indices>
MultiIndex<Indices...>::MultiIndex(const MultiIndex<Indices...>& in) :
IndexBase<MultiIndex<Indices...> >(in),
mIPack(in.mIPack)
{
// THAT's the point:
IndexSubOrder<sizeof...(Indices)-1>::subOrd(mIPack, this);
IIB::mPos = evaluate(*this);
}
template <class... Indices>
MultiIndex<Indices...>& MultiIndex<Indices...>::operator=(const MultiIndex<Indices...>& in)
{
IndexBase<MultiIndex<Indices...> >::operator=(in);
mIPack = in.mIPack;
// THAT's the point:
IndexSubOrder<sizeof...(Indices)-1>::subOrd(mIPack, this);
IIB::mPos = evaluate(*this);
return *this;
}
template <class... Indices>
MultiIndex<Indices...>::MultiIndex(RangeBase<MultiIndex<Indices...> > const* range) :
IndexBase<MultiIndex<Indices...> >(range),
mIPack()
{
operator=(IB::mRange->begin());
IIB::mPos = evaluate(*this);
}
template <class... Indices> template <class... Indices>
MultiIndex<Indices...>::MultiIndex(RangeBase<MultiIndex<Indices...> > const* range, MultiIndex<Indices...>::MultiIndex(RangeBase<MultiIndex<Indices...> > const* range,
Indices&&... inds) : IndexBase<MultiIndex<Indices...> >(range), Indices&&... inds) : IndexBase<MultiIndex<Indices...> >(range),
@ -168,11 +275,12 @@ namespace MultiArrayTools
IIB::mPos = evaluate(*this); IIB::mPos = evaluate(*this);
} }
/*
template <class... Indices> template <class... Indices>
MultiIndex<Indices...>::~MultiIndex() MultiIndex<Indices...>::~MultiIndex()
{ {
IndexSubOrder<sizeof...(Indices)-1>::subOrd(mIPack, nullptr); IndexSubOrder<sizeof...(Indices)-1>::subOrd(mIPack, nullptr);
} }*/
template <class... Indices> template <class... Indices>
MultiIndex<Indices...>& MultiIndex<Indices...>::operator++() MultiIndex<Indices...>& MultiIndex<Indices...>::operator++()
@ -377,6 +485,12 @@ namespace MultiArrayTools
{ {
PositionCopy<sizeof...(Indices)-1>::copyPos(*this, in); PositionCopy<sizeof...(Indices)-1>::copyPos(*this, in);
} }
template <class... Indices>
void MultiIndex<Indices...>::eval()
{
IIB::setPos( evaluate( *this ) );
}
/* /*
template <size_t N> template <size_t N>
@ -434,87 +548,11 @@ namespace MultiArrayTools
return std::get<N>(mSpace); return std::get<N>(mSpace);
} }
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> template <class... Ranges>
size_t MultiRange<Ranges...>::size() const size_t MultiRange<Ranges...>::size() const
{ {
return TupleSize<sizeof...(Ranges)-1>::getSize(mSpace); 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();
std::get<N>(i) -= 1;
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();
std::get<0>(i) -= 1;
}
};
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> template <class... Ranges>
MultiRangeType MultiRange<Ranges...>::type() const MultiRangeType MultiRange<Ranges...>::type() const
@ -523,6 +561,12 @@ namespace MultiArrayTools
RangeVecBuilder<sizeof...(Ranges)-1>::buildRangeVec(rvec, mSpace); RangeVecBuilder<sizeof...(Ranges)-1>::buildRangeVec(rvec, mSpace);
return MultiRangeType(rvec); return MultiRangeType(rvec);
} }
template <class... Ranges>
const typename MultiRange<Ranges...>::SpaceType& MultiRange<Ranges...>::space() const
{
return mSpace;
}
template <class... Ranges> template <class... Ranges>
MultiIndex<typename Ranges::IndexType...> MultiRange<Ranges...>::begin() const MultiIndex<typename Ranges::IndexType...> MultiRange<Ranges...>::begin() const

View file

@ -30,15 +30,22 @@ namespace MultiArrayTools
public: public:
DEFAULT_MEMBERS(MultiIndex); MultiIndex() = default;
// NO DEFAULT HERE !!!
// ( have to subord sub-indices (mMajor) correctly, and not only copy their mMajor pointer to 'in'
// which is not major any more in copies!! )
MultiIndex(const MultiIndex& in);
MultiIndex& operator=(const MultiIndex& in);
MultiIndex(RangeBase<MultiIndex<Indices...> > const* range);
MultiIndex(RangeBase<MultiIndex<Indices...> > const* range, MultiIndex(RangeBase<MultiIndex<Indices...> > const* range,
Indices&&... inds); Indices&&... inds);
MultiIndex(RangeBase<MultiIndex<Indices...> > const* range, MultiIndex(RangeBase<MultiIndex<Indices...> > const* range,
const IndexPack& ipack); const IndexPack& ipack);
virtual ~MultiIndex(); //virtual ~MultiIndex();
virtual MultiIndex& operator++() override; virtual MultiIndex& operator++() override;
virtual MultiIndex& operator--() override; virtual MultiIndex& operator--() override;
@ -72,7 +79,10 @@ namespace MultiArrayTools
virtual void linkTo(IndefinitIndexBase* target) override; virtual void linkTo(IndefinitIndexBase* target) override;
virtual void copyPos(const MultiIndex<Indices...>& in) override; virtual void copyPos(const MultiIndex<Indices...>& in) override;
virtual void eval() override;
virtual bool virt() const override { return false; }
//virtual void assignRange(RangeBase<MultiIndex<Indices...> > const* range) override; //virtual void assignRange(RangeBase<MultiIndex<Indices...> > const* range) override;
}; };
@ -101,7 +111,8 @@ namespace MultiArrayTools
auto getRange() const -> decltype( std::get<N>(SpaceType()) ); auto getRange() const -> decltype( std::get<N>(SpaceType()) );
size_t size() const override; size_t size() const override;
const SpaceType& space() const;
virtual MultiRangeType type() const override; virtual MultiRangeType type() const override;
virtual MultiIndex<typename Ranges::IndexType...> begin() const override; virtual MultiIndex<typename Ranges::IndexType...> begin() const override;

View file

@ -149,12 +149,15 @@ namespace MultiArrayTools
target->link(this); target->link(this);
} }
/*
template <typename U, RangeType TYPE> template <typename U, RangeType TYPE>
SingleIndex<U,TYPE>& SingleIndex<U,TYPE>::operator=(const U& upos) void SingleIndex<U,TYPE>::copyPos(const SingleIndex<U,TYPE>& in)
{ {
IIB::setPos( dynamic_cast<SingleRange<U,TYPE> const*>( IB::mRange )->get(upos) ); IIB::setPos(in.pos());
return *this; }
}*/
template <typename U, RangeType TYPE>
void SingleIndex<U,TYPE>::eval()
{
IIB::setPos( evaluate( *this ) );
}
} }

View file

@ -48,6 +48,12 @@ namespace MultiArrayTools
virtual size_t dim() const override; // = 1 virtual size_t dim() const override; // = 1
virtual void linkTo(IndefinitIndexBase* target) override; virtual void linkTo(IndefinitIndexBase* target) override;
virtual void copyPos(const SingleIndex& in) override;
virtual void eval() override;
virtual bool virt() const override { return false; }
protected: protected:
virtual size_t evaluate(const SingleIndex& in) const override; virtual size_t evaluate(const SingleIndex& in) const override;
}; };

View file

@ -18,16 +18,16 @@ namespace MultiArrayTools
template <typename T, class Range, class MARange> template <typename T, class Range, class MARange>
void Slice<T,Range,MARange>::set(MultiArrayBase<T,MARange>& multiArrayRef, void Slice<T,Range,MARange>::set(MultiArrayBase<T,MARange>& multiArrayRef,
const Name& ownNm, // for correct linkage const Name& ownNm, // for correct linkage
IndefinitIndexBase* MAPtr, // for desired slice position const typename MARange::IndexType& MAIdx, // for desired slice position
const Name& MANm) // for correct linkage) const Name& MANm) // for correct linkage)
{ {
mMultiArrayPtr = &multiArrayRef; mMultiArrayPtr = &multiArrayRef;
mMAPtr.reset(new typename MARange::IndexType( dynamic_cast<typename MARange::IndexType&>( *MAPtr ) ) ); mMAIdx = MAIdx;
mOwnPtr.reset(new typename Range::IndexType()); mOwnIdx = MAB::mRange->begin();
mMAPtr->name(MANm); mMAIdx.name(MANm);
mOwnPtr->name(ownNm); mOwnIdx.name(ownNm);
mMAPtr->linkTo(mOwnPtr.get()); mMAIdx.linkTo(&mOwnIdx);
} }
template <typename T, class Range, class MARange> template <typename T, class Range, class MARange>
@ -45,14 +45,16 @@ namespace MultiArrayTools
template <typename T, class Range, class MARange> template <typename T, class Range, class MARange>
T& Slice<T,Range,MARange>::operator[](const typename Range::IndexType& i) T& Slice<T,Range,MARange>::operator[](const typename Range::IndexType& i)
{ {
dynamic_cast<typename Range::IndexType&>(*mOwnPtr).copyPos(i); mOwnIdx.copyPos(i);
return (*mMultiArrayPtr)[ dynamic_cast<typename MARange::IndexType&>( *mMAPtr ) ]; mOwnIdx = i.pos();
return (*mMultiArrayPtr)[ mMAIdx ];
} }
template <typename T, class Range, class MARange> template <typename T, class Range, class MARange>
const T& Slice<T,Range,MARange>::operator[](const typename Range::IndexType& i) const const T& Slice<T,Range,MARange>::operator[](const typename Range::IndexType& i) const
{ {
dynamic_cast<typename Range::IndexType&>(*mOwnPtr).copyPos(i); mOwnIdx.copyPos(i);
return (*mMultiArrayPtr)[ dynamic_cast<typename MARange::IndexType&>( *mMAPtr ) ]; mOwnIdx = i.pos();
return (*mMultiArrayPtr)[ mMAIdx ];
} }
} }

View file

@ -36,14 +36,16 @@ namespace MultiArrayTools
void set(MultiArrayBase<T,MARange>& multiArrayRef, void set(MultiArrayBase<T,MARange>& multiArrayRef,
const Name& ownNm, const Name& ownNm,
IndefinitIndexBase* MAPtr, const typename MARange::IndexType& MAIdx,
const Name& MANm); const Name& MANm);
private: private:
MultiArrayBase<T,MARange>* mMultiArrayPtr = nullptr; MultiArrayBase<T,MARange>* mMultiArrayPtr = nullptr;
std::shared_ptr<IndefinitIndexBase> mMAPtr; // idx ptr for original MA Range mutable typename Range::IndexType mOwnIdx;
std::shared_ptr<IndefinitIndexBase> mOwnPtr; // idx ptr for own Range mutable typename MARange::IndexType mMAIdx;
//std::shared_ptr<IndefinitIndexBase> mMAPtr; // idx ptr for original MA Range
//std::shared_ptr<IndefinitIndexBase> mOwnPtr; // idx ptr for own Range
//Index mSlicePos; //Index mSlicePos;
}; };

View file

@ -359,13 +359,14 @@ namespace {
auto i1 = i.template getIndex<0>(); auto i1 = i.template getIndex<0>();
auto i2 = i.template getIndex<1>(); auto i2 = i.template getIndex<1>();
auto i3 = i.template getIndex<2>(); auto i3 = i.template getIndex<2>();
CHECK;
Slice2d3dAny sl(ra); Slice2d3dAny sl(ra);
CHECK;
sl("alpha","gamma") = ma("alpha","beta","gamma")[i(i1 = 0, i2 = 2, i3 = 0)]; sl("alpha","gamma") = ma("alpha","beta","gamma")[i(i1 = 0, i2 = 2, i3 = 0)];
EXPECT_EQ(sl.size(), 6); EXPECT_EQ(sl.size(), 6);
Slice2d3dAny sl2(rb); Slice2d3dAny sl2(rb);
sl("alpha","beta") = ma("alpha","beta","gamma")[i(i1 = 0, i2 = 0, i3 = 1)]; sl2("alpha","beta") = ma("alpha","beta","gamma")[i(i1 = 0, i2 = 0, i3 = 1)];
EXPECT_EQ(sl.size(), 12); EXPECT_EQ(sl2.size(), 12);
} }
TEST_F(SliceTest, CorrectContent) TEST_F(SliceTest, CorrectContent)
@ -376,12 +377,13 @@ namespace {
auto i3 = i.template getIndex<2>(); auto i3 = i.template getIndex<2>();
Slice2d3dAny sl(ra); Slice2d3dAny sl(ra);
sl("alpha","gamma") = ma("alpha","beta","gamma")[i(i1 = 0, i2 = 2, i3 = 0)]; sl("alpha","gamma") = ma("alpha","beta","gamma")[i(i1 = 0, i2 = 2, i3 = 0)];
CHECK;
auto j = sl.begin(); auto j = sl.begin();
auto j1 = j.template getIndex<0>(); auto j1 = j.template getIndex<0>();
auto j2 = j.template getIndex<1>(); auto j2 = j.template getIndex<1>();
CHECK;
EXPECT_EQ(sl[j(j1 = 0, j2 = 0)], 9); EXPECT_EQ(sl[j(j1 = 0, j2 = 0)], 9);
CHECK;
EXPECT_EQ(sl[j(j1 = 0, j2 = 1)], 54); EXPECT_EQ(sl[j(j1 = 0, j2 = 1)], 54);
EXPECT_EQ(sl[j(j1 = 1, j2 = 0)], -10); EXPECT_EQ(sl[j(j1 = 1, j2 = 0)], -10);