From c04863f93fc12fa28ebd20a64d39185ed156676c Mon Sep 17 00:00:00 2001
From: Christian Zimmermann <christian.zimmermann@ur.de>
Date: Thu, 16 Feb 2017 13:12:20 +0100
Subject: [PATCH] reorganize source files

---
 src/index_base.cc            | 129 ++++++++
 src/me.cc                    | 588 -----------------------------------
 src/multi_array.cc           |  39 +++
 src/multi_array_operation.cc | 117 +++++++
 src/multi_range.cc           | 191 ++++++++++++
 src/multi_range.h            |   4 +-
 src/range_base.cc            |  93 ++++++
 src/single_range.cc          |  59 ++++
 src/tuple_helper.cc          |  46 +++
 src/tuple_helper.h           |  37 +--
 10 files changed, 684 insertions(+), 619 deletions(-)
 create mode 100644 src/index_base.cc
 delete mode 100644 src/me.cc
 create mode 100644 src/multi_array.cc
 create mode 100644 src/multi_array_operation.cc
 create mode 100644 src/multi_range.cc
 create mode 100644 src/range_base.cc
 create mode 100644 src/single_range.cc
 create mode 100644 src/tuple_helper.cc

diff --git a/src/index_base.cc b/src/index_base.cc
new file mode 100644
index 0000000..c5ab5a4
--- /dev/null
+++ b/src/index_base.cc
@@ -0,0 +1,129 @@
+
+#include "index_base.h"
+
+namespace MultiArrayTools
+{
+    /************************
+     *  IndefinitIndexBase  *
+     ************************/
+
+    bool IndefinitIndexBase::link(IndefinitIndexBase* toLink)
+    {
+	if(toLink->rangeType() != rangeType() and toLink->name() == name()){
+	    // throw !!
+	}
+	
+	if(toLink->rangeType() == rangeType() and toLink->name() == name()){
+	    if(mLinked == toLink){
+		return true; // dont link twice the same
+	    }
+	    else if(mLinked == nullptr){
+		mLinked = toLink;
+		return true;
+	    }
+	    else {
+		return mLinked->link(toLink);
+	    }
+	}
+	else {
+	    return false;
+	}
+    }
+
+    void IndefinitIndexBase::freeLinked()
+    {
+	if(linked()){
+	    mLinked->freeLinked();
+	    mLinked = nullptr;
+	}
+    }
+
+    bool IndefinitIndexBase::linked() const
+    {
+	return mLinked != nullptr;
+    }
+
+    void IndefinitIndexBase::setPos(size_t pos)
+    {
+	mPos = pos;
+	if(linked()){
+	    mLinked->setPos(pos);
+	}
+    }
+
+    size_t IndefinitIndexBase::max() const
+    {
+	return static_cast<size_t>( -1 );
+    }
+
+    size_t IndefinitIndexBase::outOfRange() const
+    {
+	int res = pos() - max();
+	return res > 0 ? static_cast<size_t>(res) : 0;
+    }
+    
+    /**************
+     *  IndexBase *	     
+     **************/
+
+    template <class Index>
+    Index& IndexBase<Index>::operator=(const Index& in)
+    {
+	setPos( evaluate(in) );
+    }
+
+    template <class Index>
+    Index& IndexBase<Index>::operator=(size_t pos)
+    {
+	setPos( pos );
+	return *this;
+    }
+
+    template <class Index>
+    Index& IndexBase<Index>::operator++()
+    {
+	setPos( ++mPos );
+	return *this;
+    }
+
+    template <class Index>
+    Index& IndexBase<Index>::operator--()
+    {
+	setPos( --mPos );
+	return *this;
+    }
+
+    template <class Index>
+    Index& IndexBase<Index>::operator+=(int n)
+    {
+	setPos( mPos += n );
+	return *this;
+    }
+
+    template <class Index>
+    Index& IndexBase<Index>::operator-=(int n)
+    {
+	setPos( mPos -= n );
+	return *this;
+    }
+
+    template <class Index>
+    bool IndexBase<Index>::operator==(const Index& i)
+    {
+	return mRange == i.mRange and mPos == i.mPos;
+    }
+
+    template <class Index>
+    bool IndexBase<Index>::operator!=(const Index& i)
+    {
+	return mRange != i.mRange or mPos != i.mPos;
+    }
+
+    template <class Index>
+    size_t IndexBase<Index>::max() const
+    {
+	return mRange->size();
+    }
+
+
+}
diff --git a/src/me.cc b/src/me.cc
deleted file mode 100644
index 68558fb..0000000
--- a/src/me.cc
+++ /dev/null
@@ -1,588 +0,0 @@
-// -*- C++ -*-
-
-#include "me.h"
-
-namespace ME
-{
-
-    /*********************
-     *  MultiRangeType   *
-     *********************/
-
-    MultiRangeType& MultiRangeType::operator=(RangeType& type)
-    {
-	setType(type);
-	return *this;
-    }
-    
-    MultiRangeType& MultiRangeType::operator=(const std::vector<MultiRangeType>& multiType)
-    {
-	setMultiType(multiType);
-	return *this;
-    }
-
-    MultiRangeType& MultiRangeType::operator[](size_t num)
-    {
-	return mMultiType->at(num);
-    }
-    
-    const MultiRangeType& MultiRangeType::operator[](size_t num) const
-    {
-	return mMultiType->at(num);
-    }
-    
-    bool MultiRangeType::multi() const
-    {
-	return mType != nullptr;
-    }
-
-    bool MultiRangeType::operator==(const MultiRangeType& in) const
-    {
-	if(multi()){
-	    return *mMultiType == *in.mMultiType;
-	}
-	else {
-	    return mType == in.mType;
-	}
-    }
-    
-    bool MultiRangeType::operator!=(const MultiRangeType& in) const
-    {
-	if(multi()){
-	    return *mMultiType != *in.mMultiType;
-	}
-	else {
-	    return mType != in.mType;
-	}
-    }
-    
-    void MultiRangeType::setType(RangeType type)
-    {
-	mType = type;
-	if(mMultiType != nullptr){
-	    delete mMultiType;
-	}
-	mMultiType = nullptr;
-    }
-    
-    void MultiRangeType::setMultiType(const std::vector<MultiRangeType>& multiType)
-    {
-	mMultiType = new std::vector<MultiRangeType>( multiType );
-	mType = RangeType::NIL;
-    }
-    
-    /******************
-     *   RangeBase    *
-     ******************/
-
-    template <class Index>
-    bool RangeBase<Index>::isSubRange() const
-    {
-	return false;
-    }
-
-    /*********************
-     *   SubRangeBase    *
-     *********************/
-
-    template <class Index>
-    bool SubRangeBase<Index>::isSubRange() const
-    {
-	return true;
-    }
-
-    /********************
-     *   SingleRange    *
-     ********************/
-
-    template <typename U, RangeType TYPE>
-    const U& SingleRange<U,TYPE>::get(size_t pos) const
-    {
-	return mSpace[pos];
-    }
-
-    template <typename U, RangeType TYPE>
-    size_t SingleRange<U,TYPE>::get(const U& metaPos) const
-    {
-	size_t cnt = 0;
-	for(auto& x: mSpace){
-	    if(x == metaPos){
-		return cnt;
-	    }
-	    ++cnt;
-	}
-	return cnt;
-    }
-
-    /************************
-     *  IndefinitIndexBase  *
-     ************************/
-
-    bool IndefinitIndexBase::link(IndefinitIndexBase* toLink)
-    {
-	if(toLink->rangeType() != rangeType() and toLink->name() == name()){
-	    // throw !!
-	}
-	
-	if(toLink->rangeType() == rangeType() and toLink->name() == name()){
-	    if(mLinked == toLink){
-		return true; // dont link twice the same
-	    }
-	    else if(mLinked == nullptr){
-		mLinked = toLink;
-		return true;
-	    }
-	    else {
-		return mLinked->link(toLink);
-	    }
-	}
-	else {
-	    return false;
-	}
-    }
-
-    void IndefinitIndexBase::freeLinked()
-    {
-	if(linked()){
-	    mLinked->freeLinked();
-	    mLinked = nullptr;
-	}
-    }
-
-    bool IndefinitIndexBase::linked() const
-    {
-	return mLinked != nullptr;
-    }
-
-    void IndefinitIndexBase::setPos(size_t pos)
-    {
-	mPos = pos;
-	if(linked()){
-	    mLinked->setPos(pos);
-	}
-    }
-
-    size_t IndefinitIndexBase::max() const
-    {
-	return static_cast<size_t>( -1 );
-    }
-
-    size_t IndefinitIndexBase::outOfRange() const
-    {
-	int res = pos() - max();
-	return res > 0 ? static_cast<size_t>(res) : 0;
-    }
-    
-    /**************
-     *  IndexBase *	     
-     **************/
-
-    template <class Index>
-    Index& IndexBase<Index>::operator=(const Index& in)
-    {
-	setPos( evaluate(in) );
-    }
-
-    template <class Index>
-    Index& IndexBase<Index>::operator=(size_t pos)
-    {
-	setPos( pos );
-	return *this;
-    }
-
-    template <class Index>
-    Index& IndexBase<Index>::operator++()
-    {
-	setPos( ++mPos );
-	return *this;
-    }
-
-    template <class Index>
-    Index& IndexBase<Index>::operator--()
-    {
-	setPos( --mPos );
-	return *this;
-    }
-
-    template <class Index>
-    Index& IndexBase<Index>::operator+=(int n)
-    {
-	setPos( mPos += n );
-	return *this;
-    }
-
-    template <class Index>
-    Index& IndexBase<Index>::operator-=(int n)
-    {
-	setPos( mPos -= n );
-	return *this;
-    }
-
-    template <class Index>
-    bool IndexBase<Index>::operator==(const Index& i)
-    {
-	return mRange == i.mRange and mPos == i.mPos;
-    }
-
-    template <class Index>
-    bool IndexBase<Index>::operator!=(const Index& i)
-    {
-	return mRange != i.mRange or mPos != i.mPos;
-    }
-
-    template <class Index>
-    size_t IndexBase<Index>::max() const
-    {
-	return mRange->size();
-    }
-
-    
-    /********************
-     *  SingleIndexBase *	     
-     ********************/
-    
-    template <typename U, IndexType TYPE>
-    const U& SingleIndexBase<U,TYPE>::getMetaPos() const
-    {
-	return dynamic_cast<SingleRange*>( mRange )->get(mPos);
-    }
-
-    template <typename U, IndexType TYPE>
-    size_t dim() const
-    {
-	return 1;
-    }
-    
-    template <typename U, IndexType TYPE>
-    size_t SingleIndexBase<TYPE>::evaluate(const Index& in)
-    {
-	return in.mPos;
-    }
-
-    template <typename U, IndexType TYPE>
-    void linkTo(IndefinitIndexBase* target)
-    {
-	target->link(this);
-    }    
-
-    /*******************
-     *  MultiIndexBase *	     
-     *******************/
-
-    namespace
-    {
-	template <class MultiIndex, size_t N>
-	IndefinitIndexBase& getIndex(MultiIndex& in, size_t n)
-	{
-	    if(n == N){
-		return in.getIndex<N>();
-	    }
-	    else {
-		return getIndex<N-1>(in, n);
-	    }
-	}
-	
-	template <class MultiIndex>
-	IndefinitIndexBase& getIndex<MultiIndex,0>(MultiIndex& in, size_t n)
-	{
-	    return in.getIndex<0>();
-	}
-		
-	template <size_t N, class MultiIndex>
-	size_t evaluate_x(const MultiIndex& index)
-	{
-	    const auto& subIndex = index.getIndex<N>();
-	    return evaluate_x<N-1>(index) * subIndex.size() + subIndex.pos();
-	}
-
-	template <class MultiIndex>
-	size_t evaluate_x<0>(const MultiIndex& index)
-	{
-	    const auto& subIndex = index.getIndex<0>();
-	    return subIndex.pos();
-	}
-
-	template <class MultiIndex>
-	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);
-		plus(index, digit, oor - max());
-	    }
-	}
-    }
-
-    
-    template <class... Indices>
-    MultiIndex& MultiIndex<Indices...>::operator++()
-    {
-	setPos( pos() + 1 );
-	plus(*this, 0, 1);
-	return *this;
-    }
-
-    template <class... Indices>
-    MultiIndex& MultiIndex<Indices...>::operator--()
-    {
-	setPos( pos() - 1 );
-	plus(*this, 0, -1);
-	return *this;
-    }
-
-    template <class... Indices>
-    MultiIndex& MultiIndex<Indices...>::operator+=(int n)
-    {
-	setPos( pos() + n );
-	plus(*this, 0, n);
-	return *this;
-    }
-
-    template <class... Indices>
-    MultiIndex& MultiIndex<Indices...>::operator-=(int n)
-    {
-	setPos( pos() - n );
-	plus(*this, 0, 0-n);
-	return *this;
-    }
-    
-    template <class... Indices>
-    size_t MultiIndex<Indices...>::evaluate(const MultiIndex<Indices...>& in) const
-    {
-	return evaluate_x<sizeof...(Indices)-1>(in);
-    }
-
-    template <class... Indices>
-    size_t MultiIndex<Indices...>::dim() const
-    {
-	size_t res = 1;
-	for(size_t i = 0; i != sMult; ++i){
-	    res *= getIndex(i).dim();
-	}
-	return res;
-    }
-    
-    template <class... Indices>
-    bool MultiIndex<Indices...>::link(IndefinitIndexBase* toLink)
-    {
-	if(toLink->rangeType() != rangeType() and toLink->name() == name()){
-	    // throw !!
-	}
-	
-	if(toLink->rangeType() == rangeType() and toLink->name() == name()){
-	    if(mLinked == toLink){
-		return true; // dont link twice the same
-	    }
-	    else if(mLinked == nullptr){
-		mLinked = toLink;
-		return true;
-	    }
-	    else {
-		return mLinked->link(toLink);
-	    }
-	}
-	else {
-	    return linkLower(toLink);
-	}
-    }
-
-    template <size_t N>
-    auto& getIndex() -> decltype(std::get<N>(mIPack))
-    {
-	return std::get<N>(mIPack);
-    }
-    
-    template <size_t N>
-    const auto& getIndex() const -> decltype(std::get<N>(mIPack));
-    {
-	return std::get<N>(mIPack);
-    }
-    
-    template <class... Indices>
-    IndefinitIndexBase& MultiIndex<Indices...>::getIndex(size_t n)
-    {
-	if(n >= sMult){
-	    // throw !!
-	}
-	MultiIndex<Indices...>* t = this;
-	return getIndex<sizeof...(Indices)>(*t, n);
-    }
-
-    template <class... Indices>
-    const IndefinitIndexBase& MultiIndex<Indices...>::getIndex(size_t n) const
-    {
-	if(n >= sMult){
-	    // throw !!
-	}
-	MultiIndex<Indices...>* t = this;
-	return getIndex<sizeof...(Indices)>(*t, n);
-    }
-
-    template <class... Indices>
-    bool MultiIndex<Indices...>::linkLower(IndefinitIndexBase* toLink)
-    {
-	bool res = false;
-	for(size_t i = 0; i != sMult; ++i){
-	    res |= getIndex(i).link(toLink);
-	}
-	return res;
-    }
-
-    template <class... Indices>
-    void MultiIndex<Indices...>::linkTo(IndefinitIndexBase* target)
-    {
-	target->link(this);
-	for(size_t i = 0; i != sMult; ++i){
-	    getIndex(i).linkTo(target);
-	}
-    }
-    
-    /*******************
-     *  MultiArray     *	     
-     *******************/
-
-    template <typename... Ranges>
-    void giveNames(const std::string& name, /**/);
-
-    template <typename... Ranges>
-    void giveNames(const std::vector<std::string>& names, /**/);
-
-    /*!!!!  giveNames(...)  !!!!!*/
-    
-    template <typename T, class Range>
-    T& MultiArray<T,Is...>::operator()(const typename Range::indexType& i)
-    {
-	return mCont[ i.pos() ];
-    }
-
-    template <typename T, class Range>
-    const T& MultiArray<T,Is...>::operator()(const typename Range::indexType& i) const
-    {
-	return mCont[ i.pos() ];
-    }
-
-    template <typename T, class Range>
-    template <class... NameTypes>
-    MultiArrayOperation<T,Range>& operator()(const NameTypes&... str) const
-    {
-	auto index = mRange->begin();
-	// give names... !!!
-	return MultiArrayOperation<T,Range>(*this, index);
-    }
-    
-    
-    /*********************************
-     *   MultiArrayOperationBase     *
-     *********************************/
-    
-    template <typename T, class Range>
-    template <class Range2>
-    MultiArrayOperationBase<T,Range>&
-    MultiArrayOperationBase<T,Range>::operator=(const MultiArrayOperationBase<T, Range2>& in)
-    {
-	in.linkIndicesTo(mIibPtr);
-	for(*mIibPtr = mArrayRef.begin(); *mIibPtr != mArrayRef.end(); ++(*mIibPtr)){
-	    // build in vectorization later
-	    get() = in.get();
-	}
-    }
-
-    template <typename T, class Range>
-    template <class Operation, class... Ranges>
-    MultiArrayOperation<Operation>
-    MultiArrayOperationBase<T,Range>::operator()(Operation& op, MultiArrayOperationBase<T,Ranges>&... secs)
-    {
-	return MultiArrayOperationBase<T,Range>(op, secs);
-    }
-    
-    template <typename T, class Range>
-    size_t MultiArrayOperationBase<T,Range>::argNum() const
-    {
-	return 1;
-    }
-
-    template <typename T, class Range>
-    IndefinitIndexBase* MultiArrayOperationBase<T,Range>::index()
-    {
-	return mIibPtr;
-    }
-
-    template <typename T, class Range>
-    void MultiArrayOperationBase<T,Range>::linkIndicesTo(IndefinitIndexBase* target)
-    {
-	mIibPtr->linkTo(target);
-    }
-
-    template <typename T, class Range>
-    T& MultiArrayOperationBase<T,Range>::get()
-    {
-	return mArrayRef(*mIibPtr);
-    }
-
-    template <typename T, class Range>
-    const T& MultiArrayOperationBase<T,Range>::get() const
-    {
-	return mArrayRef(*mIibPtr);
-    }
-
-    /*****************************
-     *   MultiArrayOperation     *
-     *****************************/
-
-    template <class IndexTuple, size_t N>
-    void linkTupleIndicesTo(IndexTuple& itp, IndefinitIndexBase* target)
-    {
-	std::get<N>(itp).linkTo(target);
-	linkTupleIndicesTo<N-1>(itp, target);
-    }
-
-    template <class IndexTuple>
-    void linkTupleIndicesTo<0>(IndexTuple& itp, IndefinitIndexBase* target)
-    {
-	std::get<0>(itp).linkTo(target);
-    }
-
-    template <size_t N, class Operation, class Tuple, class... MBases>
-    auto callOperation(Operation& op, Tuple& tp, MBases&... secs)
-	-> decltype(callOperation(op, tp, std::get<N-1>(tp), secs...))
-    {
-	return callOperation(op, tp, std::get<N-1>(tp), secs...);
-    }
-
-    template <class Operation, class Tuple, class... MBases>
-    auto callOperation<0>(Operation& op, Tuple& tp, MBases&... secs) -> decltype(op(secs.get()...))
-    {
-	return op(secs.get()...);
-    }
-    
-    template <typename T, class Range, class Operation, class... Ranges>
-    size_t MultiArrayOperation<T,Range,Operation,Ranges...>::argNum() const
-    {
-	return sizeof...(Ranges) + 1;
-    }
-
-    template <typename T, class Range, class Operation, class... Ranges>    
-    void MultiArrayOperation<T,Range,Operation,Ranges...>::linkIndicesTo(IndefinitIndexBase* target)
-    {
-	mIibPtr->linkTo(target);
-	linkTupleIndicesTo<sizeof...(Ranges)>(mSecs, target);
-    }
-    
-    template <typename T, class Range, class Operation, class... Ranges>    
-    T& MultiArrayOperation<T,Range,Operation,Ranges...>::get()
-    {
-	mVal = callOperation<sizeof...(Ranges)>(mOp, mSecs);
-	return mVal;
-    }
-
-    template <typename T, class Range, class Operation, class... Ranges>    
-    const T& MultiArrayOperation<T,Range,Operation,Ranges...>::get() const
-    {
-	mVal = callOperation<sizeof...(Ranges)>(mOp, mSecs);
-	return mVal;
-    }
-    
-} // end namespace ME
-
diff --git a/src/multi_array.cc b/src/multi_array.cc
new file mode 100644
index 0000000..b084ded
--- /dev/null
+++ b/src/multi_array.cc
@@ -0,0 +1,39 @@
+
+#include "multi_array.h"
+
+namespace MultiArrayTools
+{
+    /*******************
+     *  MultiArray     *	     
+     *******************/
+
+    template <typename... Ranges>
+    void giveNames(const std::string& name, /**/);
+
+    template <typename... Ranges>
+    void giveNames(const std::vector<std::string>& names, /**/);
+
+    /*!!!!  giveNames(...)  !!!!!*/
+    
+    template <typename T, class Range>
+    T& MultiArray<T,Is...>::operator()(const typename Range::indexType& i)
+    {
+	return mCont[ i.pos() ];
+    }
+
+    template <typename T, class Range>
+    const T& MultiArray<T,Is...>::operator()(const typename Range::indexType& i) const
+    {
+	return mCont[ i.pos() ];
+    }
+
+    template <typename T, class Range>
+    template <class... NameTypes>
+    MultiArrayOperation<T,Range>& operator()(const NameTypes&... str) const
+    {
+	auto index = mRange->begin();
+	// give names... !!!
+	return MultiArrayOperation<T,Range>(*this, index);
+    }
+
+}
diff --git a/src/multi_array_operation.cc b/src/multi_array_operation.cc
new file mode 100644
index 0000000..a05fc72
--- /dev/null
+++ b/src/multi_array_operation.cc
@@ -0,0 +1,117 @@
+
+#include "mutli_array_operation.h"
+
+namespace MultiArrayTools
+{
+    /*********************************
+     *   MultiArrayOperationBase     *
+     *********************************/
+    
+    template <typename T, class Range>
+    template <class Range2>
+    MultiArrayOperationBase<T,Range>&
+    MultiArrayOperationBase<T,Range>::operator=(const MultiArrayOperationBase<T, Range2>& in)
+    {
+	in.linkIndicesTo(mIibPtr);
+	for(*mIibPtr = mArrayRef.begin(); *mIibPtr != mArrayRef.end(); ++(*mIibPtr)){
+	    // build in vectorization later
+	    get() = in.get();
+	}
+    }
+
+    template <typename T, class Range>
+    template <class Operation, class... Ranges>
+    MultiArrayOperation<Operation>
+    MultiArrayOperationBase<T,Range>::operator()(Operation& op, MultiArrayOperationBase<T,Ranges>&... secs)
+    {
+	return MultiArrayOperationBase<T,Range>(op, secs);
+    }
+    
+    template <typename T, class Range>
+    size_t MultiArrayOperationBase<T,Range>::argNum() const
+    {
+	return 1;
+    }
+
+    template <typename T, class Range>
+    IndefinitIndexBase* MultiArrayOperationBase<T,Range>::index()
+    {
+	return mIibPtr;
+    }
+
+    template <typename T, class Range>
+    void MultiArrayOperationBase<T,Range>::linkIndicesTo(IndefinitIndexBase* target)
+    {
+	mIibPtr->linkTo(target);
+    }
+
+    template <typename T, class Range>
+    T& MultiArrayOperationBase<T,Range>::get()
+    {
+	return mArrayRef(*mIibPtr);
+    }
+
+    template <typename T, class Range>
+    const T& MultiArrayOperationBase<T,Range>::get() const
+    {
+	return mArrayRef(*mIibPtr);
+    }
+
+    /*****************************
+     *   MultiArrayOperation     *
+     *****************************/
+
+    template <class IndexTuple, size_t N>
+    void linkTupleIndicesTo(IndexTuple& itp, IndefinitIndexBase* target)
+    {
+	std::get<N>(itp).linkTo(target);
+	linkTupleIndicesTo<N-1>(itp, target);
+    }
+
+    template <class IndexTuple>
+    void linkTupleIndicesTo<0>(IndexTuple& itp, IndefinitIndexBase* target)
+    {
+	std::get<0>(itp).linkTo(target);
+    }
+
+    template <size_t N, class Operation, class Tuple, class... MBases>
+    auto callOperation(Operation& op, Tuple& tp, MBases&... secs)
+	-> decltype(callOperation(op, tp, std::get<N-1>(tp), secs...))
+    {
+	return callOperation(op, tp, std::get<N-1>(tp), secs...);
+    }
+
+    template <class Operation, class Tuple, class... MBases>
+    auto callOperation<0>(Operation& op, Tuple& tp, MBases&... secs) -> decltype(op(secs.get()...))
+    {
+	return op(secs.get()...);
+    }
+    
+    template <typename T, class Range, class Operation, class... Ranges>
+    size_t MultiArrayOperation<T,Range,Operation,Ranges...>::argNum() const
+    {
+	return sizeof...(Ranges) + 1;
+    }
+
+    template <typename T, class Range, class Operation, class... Ranges>    
+    void MultiArrayOperation<T,Range,Operation,Ranges...>::linkIndicesTo(IndefinitIndexBase* target)
+    {
+	mIibPtr->linkTo(target);
+	linkTupleIndicesTo<sizeof...(Ranges)>(mSecs, target);
+    }
+    
+    template <typename T, class Range, class Operation, class... Ranges>    
+    T& MultiArrayOperation<T,Range,Operation,Ranges...>::get()
+    {
+	mVal = callOperation<sizeof...(Ranges)>(mOp, mSecs);
+	return mVal;
+    }
+
+    template <typename T, class Range, class Operation, class... Ranges>    
+    const T& MultiArrayOperation<T,Range,Operation,Ranges...>::get() const
+    {
+	mVal = callOperation<sizeof...(Ranges)>(mOp, mSecs);
+	return mVal;
+    }
+
+}
diff --git a/src/multi_range.cc b/src/multi_range.cc
new file mode 100644
index 0000000..aa6254d
--- /dev/null
+++ b/src/multi_range.cc
@@ -0,0 +1,191 @@
+
+#include "mutli_range.h"
+
+namespace MultiArrayTools
+{
+    /*******************
+     *  MultiIndexBase *	     
+     *******************/
+
+    namespace
+    {
+	template <class MultiIndex, size_t N>
+	IndefinitIndexBase& getIndex(MultiIndex& in, size_t n)
+	{
+	    if(n == N){
+		return in.getIndex<N>();
+	    }
+	    else {
+		return getIndex<N-1>(in, n);
+	    }
+	}
+	
+	template <class MultiIndex>
+	IndefinitIndexBase& getIndex<MultiIndex,0>(MultiIndex& in, size_t n)
+	{
+	    return in.getIndex<0>();
+	}
+		
+	template <size_t N, class MultiIndex>
+	size_t evaluate_x(const MultiIndex& index)
+	{
+	    const auto& subIndex = index.getIndex<N>();
+	    return evaluate_x<N-1>(index) * subIndex.size() + subIndex.pos();
+	}
+
+	template <class MultiIndex>
+	size_t evaluate_x<0>(const MultiIndex& index)
+	{
+	    const auto& subIndex = index.getIndex<0>();
+	    return subIndex.pos();
+	}
+
+	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);
+		plus(index, digit, oor - max());
+	    }
+	}
+    }
+
+    
+    template <class... Indices>
+    MultiIndex& MultiIndex<Indices...>::operator++()
+    {
+	setPos( pos() + 1 );
+	plus(*this, 0, 1);
+	return *this;
+    }
+
+    template <class... Indices>
+    MultiIndex& MultiIndex<Indices...>::operator--()
+    {
+	setPos( pos() - 1 );
+	plus(*this, 0, -1);
+	return *this;
+    }
+
+    template <class... Indices>
+    MultiIndex& MultiIndex<Indices...>::operator+=(int n)
+    {
+	setPos( pos() + n );
+	plus(*this, 0, n);
+	return *this;
+    }
+
+    template <class... Indices>
+    MultiIndex& MultiIndex<Indices...>::operator-=(int n)
+    {
+	setPos( pos() - n );
+	plus(*this, 0, 0-n);
+	return *this;
+    }
+    
+    template <class... Indices>
+    size_t MultiIndex<Indices...>::evaluate(const MultiIndex<Indices...>& in) const
+    {
+	return evaluate_x<sizeof...(Indices)-1>(in);
+    }
+
+    template <class... Indices>
+    size_t MultiIndex<Indices...>::dim() const
+    {
+	size_t res = 1;
+	for(size_t i = 0; i != sMult; ++i){
+	    res *= getIndex(i).dim();
+	}
+	return res;
+    }
+    
+    template <class... Indices>
+    bool MultiIndex<Indices...>::link(IndefinitIndexBase* toLink)
+    {
+	if(toLink->rangeType() != rangeType() and toLink->name() == name()){
+	    // throw !!
+	}
+	
+	if(toLink->rangeType() == rangeType() and toLink->name() == name()){
+	    if(mLinked == toLink){
+		return true; // dont link twice the same
+	    }
+	    else if(mLinked == nullptr){
+		mLinked = toLink;
+		return true;
+	    }
+	    else {
+		return mLinked->link(toLink);
+	    }
+	}
+	else {
+	    return linkLower(toLink);
+	}
+    }
+
+    template <size_t N>
+    auto& MultiIndex<Indices...>::getIndex() -> decltype(std::get<N>(mIPack))
+    {
+	return std::get<N>(mIPack);
+    }
+    
+    template <size_t N>
+    const auto& MultiIndex<Indices...>::getIndex() const -> decltype(std::get<N>(mIPack));
+    {
+	return std::get<N>(mIPack);
+    }
+    
+    template <class... Indices>
+    IndefinitIndexBase& MultiIndex<Indices...>::getIndex(size_t n)
+    {
+	if(n >= sMult){
+	    // throw !!
+	}
+	MultiIndex<Indices...>* t = this;
+	return getIndex<sizeof...(Indices)>(*t, n);
+    }
+
+    template <class... Indices>
+    const IndefinitIndexBase& MultiIndex<Indices...>::getIndex(size_t n) const
+    {
+	if(n >= sMult){
+	    // throw !!
+	}
+	MultiIndex<Indices...>* t = this;
+	return getIndex<sizeof...(Indices)>(*t, n);
+    }
+
+    template <class... Indices>
+    bool MultiIndex<Indices...>::linkLower(IndefinitIndexBase* toLink)
+    {
+	bool res = false;
+	for(size_t i = 0; i != sMult; ++i){
+	    res |= getIndex(i).link(toLink);
+	}
+	return res;
+    }
+
+    template <class... Indices>
+    void MultiIndex<Indices...>::linkTo(IndefinitIndexBase* target)
+    {
+	target->link(this);
+	for(size_t i = 0; i != sMult; ++i){
+	    getIndex(i).linkTo(target);
+	}
+    }
+
+    /******************
+     *   MultiRange   *
+     ******************/
+    
+    template <size_t N>
+    auto MultiRange<Ranges...>::get() -> decltype( std::get<N>(mSpace) )
+    {
+	return std::get<N>(mSpace);
+    }
+    
+    
+}
diff --git a/src/multi_range.h b/src/multi_range.h
index 5871a0a..3bbd1e7 100644
--- a/src/multi_range.h
+++ b/src/multi_range.h
@@ -37,8 +37,8 @@ namespace MultiArrayTools
 	IndefinitIndexBase& getIndex(size_t n);
 	const IndefinitIndexBase& getIndex(size_t n) const;
 	
-	// dimension of MultiRange
-	virtual size_t dim() const override; // implement !!!
+	// dimension of MultiRange; includes ALL degrees of freedom
+	virtual size_t dim() const override;
 
 	virtual bool link(IndefinitIndexBase* toLink) override;
 	virtual void linkTo(IndefinitIndexBase* target) override;
diff --git a/src/range_base.cc b/src/range_base.cc
new file mode 100644
index 0000000..9bbecc0
--- /dev/null
+++ b/src/range_base.cc
@@ -0,0 +1,93 @@
+
+#include "range_base.h"
+
+namespace MultiArrayTools
+{
+    /*********************
+     *  MultiRangeType   *
+     *********************/
+
+    MultiRangeType& MultiRangeType::operator=(RangeType& type)
+    {
+	setType(type);
+	return *this;
+    }
+    
+    MultiRangeType& MultiRangeType::operator=(const std::vector<MultiRangeType>& multiType)
+    {
+	setMultiType(multiType);
+	return *this;
+    }
+
+    MultiRangeType& MultiRangeType::operator[](size_t num)
+    {
+	return mMultiType->at(num);
+    }
+    
+    const MultiRangeType& MultiRangeType::operator[](size_t num) const
+    {
+	return mMultiType->at(num);
+    }
+    
+    bool MultiRangeType::multi() const
+    {
+	return mType != nullptr;
+    }
+
+    bool MultiRangeType::operator==(const MultiRangeType& in) const
+    {
+	if(multi()){
+	    return *mMultiType == *in.mMultiType;
+	}
+	else {
+	    return mType == in.mType;
+	}
+    }
+    
+    bool MultiRangeType::operator!=(const MultiRangeType& in) const
+    {
+	if(multi()){
+	    return *mMultiType != *in.mMultiType;
+	}
+	else {
+	    return mType != in.mType;
+	}
+    }
+    
+    void MultiRangeType::setType(RangeType type)
+    {
+	mType = type;
+	if(mMultiType != nullptr){
+	    delete mMultiType;
+	}
+	mMultiType = nullptr;
+    }
+    
+    void MultiRangeType::setMultiType(const std::vector<MultiRangeType>& multiType)
+    {
+	mMultiType = new std::vector<MultiRangeType>( multiType );
+	mType = RangeType::NIL;
+    }
+    
+    /******************
+     *   RangeBase    *
+     ******************/
+
+    template <class Index>
+    bool RangeBase<Index>::isSubRange() const
+    {
+	return false;
+    }
+
+    /*********************
+     *   SubRangeBase    *
+     *********************/
+
+    template <class Index>
+    bool SubRangeBase<Index>::isSubRange() const
+    {
+	return true;
+    }
+
+
+}
diff --git a/src/single_range.cc b/src/single_range.cc
new file mode 100644
index 0000000..7013592
--- /dev/null
+++ b/src/single_range.cc
@@ -0,0 +1,59 @@
+
+#include "single_range.h"
+
+namespace MultiArrayTools
+{
+    /********************
+     *   SingleRange    *
+     ********************/
+
+    template <typename U, RangeType TYPE>
+    const U& SingleRange<U,TYPE>::get(size_t pos) const
+    {
+	return mSpace[pos];
+    }
+
+    template <typename U, RangeType TYPE>
+    size_t SingleRange<U,TYPE>::get(const U& metaPos) const
+    {
+	size_t cnt = 0;
+	for(auto& x: mSpace){
+	    if(x == metaPos){
+		return cnt;
+	    }
+	    ++cnt;
+	}
+	return cnt;
+    }
+
+
+    
+    /******************
+     *  SingleIndex   *	     
+     ******************/
+    
+    template <typename U, IndexType TYPE>
+    const U& SingleIndexBase<U,TYPE>::getMetaPos() const
+    {
+	return dynamic_cast<SingleRange*>( mRange )->get(mPos);
+    }
+
+    template <typename U, IndexType TYPE>
+    size_t dim() const
+    {
+	return 1;
+    }
+    
+    template <typename U, IndexType TYPE>
+    size_t SingleIndexBase<TYPE>::evaluate(const Index& in)
+    {
+	return in.mPos;
+    }
+
+    template <typename U, IndexType TYPE>
+    void linkTo(IndefinitIndexBase* target)
+    {
+	target->link(this);
+    }    
+
+}
diff --git a/src/tuple_helper.cc b/src/tuple_helper.cc
new file mode 100644
index 0000000..0055226
--- /dev/null
+++ b/src/tuple_helper.cc
@@ -0,0 +1,46 @@
+
+#include "tuple_helper.h"
+
+namespace MultiArrayTools
+{
+
+    template <class Tuple, size_t N>
+    auto make_left_x(const Tuple& tp) -> decltype(std::tuple_cat(make_left<Tuple,N-1>(tp),
+							       std::make_tuple(get<N>(tp))))
+    {
+	return std::tuple_cat(make_left<Tuple,N-1>(tp), std::make_tuple(get<N>(tp)));
+    }
+
+    template <class Tuple>
+    auto make_left_x<Tuple, 0>(const Tuple& tp) -> decltype(std::make_tuple(get<N>(tp)))
+    {
+	return std::make_tuple(get<N>(tp));
+    }
+
+    template <class Tuple, size_t N>
+    auto make_right_x(const Tuple& tp) -> decltype(std::tuple_cat(std::make_tuple(get<std::tuple_size(tp)-N>(tp)),
+								make_left<Tuple,std::tuple_size(tp)-N+1>(tp)))
+    {
+	const size_t M = std::tuple_size(tp) - N;
+	return std::tuple_cat(std::make_tuple(get<M>(tp)), make_left<Tuple,M+1>(tp));
+    }
+
+    template <class Tuple>
+    auto make_right_x<Tuple, 0>(const Tuple& tp) -> decltype(std::make_tuple(get<std::tuple_size(tp)>(tp)))
+    {
+	const size_t M = std::tuple_size(tp);
+	return std::make_tuple(get<M>(tp));
+    }
+
+    template <class Tuple, size_t N>
+    auto make_left(const Tuple& tp) -> decltype(make_left_x<Tuple, N>(tp))
+    {
+	return make_left_x<Tuple, N>(tp);
+    }
+
+    template <class Tuple, size_t N>
+    auto make_right(const Tuple& tp) -> decltype(make_right_x<Tuple, std::tuple_size(Tuple)-N>(tp))
+    {
+	return make_right_x<Tuple, std::tuple_size(Tuple)-N>(tp);
+    }
+}
diff --git a/src/tuple_helper.h b/src/tuple_helper.h
index d3f99b0..dde29ce 100644
--- a/src/tuple_helper.h
+++ b/src/tuple_helper.h
@@ -14,44 +14,23 @@ namespace MultiArrayTools
 
     template <class Tuple, size_t N>
     auto make_left_x(const Tuple& tp) -> decltype(std::tuple_cat(make_left<Tuple,N-1>(tp),
-							       std::make_tuple(get<N>(tp))))
-    {
-	return std::tuple_cat(make_left<Tuple,N-1>(tp), std::make_tuple(get<N>(tp)));
-    }
+								 std::make_tuple(get<N>(tp))));
 
     template <class Tuple>
-    auto make_left_x<Tuple, 0>(const Tuple& tp) -> decltype(std::make_tuple(get<N>(tp)))
-    {
-	return std::make_tuple(get<N>(tp));
-    }
-
+    auto make_left_x<Tuple, 0>(const Tuple& tp) -> decltype(std::make_tuple(get<N>(tp)));
+    
     template <class Tuple, size_t N>
     auto make_right_x(const Tuple& tp) -> decltype(std::tuple_cat(std::make_tuple(get<std::tuple_size(tp)-N>(tp)),
-								make_left<Tuple,std::tuple_size(tp)-N+1>(tp)))
-    {
-	const size_t M = std::tuple_size(tp) - N;
-	return std::tuple_cat(std::make_tuple(get<M>(tp)), make_left<Tuple,M+1>(tp));
-    }
-
+								  make_left<Tuple,std::tuple_size(tp)-N+1>(tp)));
+    
     template <class Tuple>
-    auto make_right_x<Tuple, 0>(const Tuple& tp) -> decltype(std::make_tuple(get<std::tuple_size(tp)>(tp)))
-    {
-	const size_t M = std::tuple_size(tp);
-	return std::make_tuple(get<M>(tp));
-    }
+    auto make_right_x<Tuple, 0>(const Tuple& tp) -> decltype(std::make_tuple(get<std::tuple_size(tp)>(tp)));
 
     template <class Tuple, size_t N>
-    auto make_left(const Tuple& tp) -> decltype(make_left_x<Tuple, N>(tp))
-    {
-	return make_left_x<Tuple, N>(tp);
-    }
+    auto make_left(const Tuple& tp) -> decltype(make_left_x<Tuple, N>(tp));
 
     template <class Tuple, size_t N>
-    auto make_right(const Tuple& tp) -> decltype(make_right_x<Tuple, std::tuple_size(Tuple)-N>(tp))
-    {
-	return make_right_x<Tuple, std::tuple_size(Tuple)-N>(tp);
-    }
-
+    auto make_right(const Tuple& tp) -> decltype(make_right_x<Tuple, std::tuple_size(Tuple)-N>(tp));
 
 }