cnorxz/src/multi_array_operation.h

513 lines
14 KiB
C
Raw Normal View History

2017-02-16 11:20:40 +01:00
// -*- C++ -*-
#ifndef __multi_array_operation_h__
#define __multi_array_operation_h__
#include <cstdlib>
#include <tuple>
2017-03-22 21:51:54 +01:00
#include <cmath>
2017-08-30 17:56:38 +02:00
#include <map>
#include <utility>
2017-02-16 11:20:40 +01:00
#include "base_def.h"
2017-12-18 11:19:04 +01:00
#include "mbase_def.h"
#include "block/block.h"
#include "operation_utils.h"
2017-02-16 11:20:40 +01:00
namespace MultiArrayTools
{
namespace
{
using namespace MultiArrayHelper;
}
2017-08-10 15:12:26 +02:00
/*
* OperationBase
* MutableOperationBase
*
* OperationMaster : MutableOperationBase
*
* OperationTemplate<...>
* ConstOperationRoot : OperationBase, OperationTemplate<...>
* OperationRoot : MutableOperationBase,
* OperationTemplate<...>
*
*/
2017-08-30 17:56:38 +02:00
template <typename T>
2017-12-16 20:38:57 +01:00
Block<T> makeBlock(const T* vec, size_t stepSize, size_t blockSize);
2017-08-30 17:56:38 +02:00
template <typename T>
2017-12-16 20:38:57 +01:00
MBlock<T> makeBlock(T* vec, size_t stepSize, size_t blockSize);
2017-08-30 17:56:38 +02:00
template <class OpClass>
std::shared_ptr<VIWB> seekBlockIndex(std::shared_ptr<VIWB> ownIdx,
const OpClass& second);
template <typename T, class OperationClass>
2017-08-11 11:30:27 +02:00
class OperationTemplate
{
public:
2017-08-27 17:52:50 +02:00
2017-08-11 15:26:10 +02:00
OperationTemplate(OperationClass* oc);
2017-08-11 11:30:27 +02:00
template <class Second>
2017-08-26 17:18:42 +02:00
auto operator+(const Second& in) const
-> Operation<T,std::plus<T>,OperationClass,Second>;
2017-08-26 17:18:42 +02:00
template <class Second>
auto operator-(const Second& in) const
-> Operation<T,std::minus<T>,OperationClass,Second>;
2017-08-26 17:18:42 +02:00
template <class Second>
auto operator*(const Second& in) const
-> Operation<T,std::multiplies<T>,OperationClass,Second>;
2017-08-26 17:18:42 +02:00
template <class Second>
auto operator/(const Second& in) const
-> Operation<T,std::divides<T>,OperationClass,Second>;
2017-11-05 18:46:38 +01:00
2017-11-02 21:20:31 +01:00
template <class IndexType>
auto c(std::shared_ptr<IndexType>& ind) const
-> Contraction<T,OperationClass,IndexType>;
2017-11-05 18:46:38 +01:00
2017-08-11 15:26:10 +02:00
private:
OperationClass* mOc;
2017-08-11 11:30:27 +02:00
};
template <typename T, class OpClass, class... Ranges>
class OperationMaster/* : public MutableOperationBase<T>*/
{
public:
2017-08-27 17:52:50 +02:00
typedef T value_type;
2017-08-10 15:12:26 +02:00
typedef OperationBase<T> OB;
2017-08-11 15:26:10 +02:00
typedef ContainerRange<Ranges...> CRange;
2017-08-10 15:12:26 +02:00
typedef typename MultiRange<Ranges...>::IndexType IndexType;
2017-03-08 22:53:18 +01:00
OperationMaster(MutableMultiArrayBase<T,Ranges...>& ma, const OpClass& second,
2017-08-11 15:26:10 +02:00
std::shared_ptr<typename CRange::IndexType>& index);
MBlock<T>& get();
const Block<T>& get() const;
2017-02-27 17:00:51 +01:00
std::vector<BTSS> block(const std::shared_ptr<VIWB> blockIndex) const;
const OperationMaster& block() const;
2017-02-16 11:20:40 +01:00
protected:
2017-02-27 17:00:51 +01:00
2017-08-11 11:30:27 +02:00
//void performAssignment(const OperationBase<T>& in);
OpClass const& mSecond;
MutableMultiArrayBase<T,Ranges...>& mArrayRef;
2017-08-11 11:30:27 +02:00
std::shared_ptr<IndexType> mIndex;
2017-12-16 20:38:57 +01:00
mutable MBlock<T> mBlock;
2017-02-16 11:20:40 +01:00
};
2017-08-10 15:12:26 +02:00
2017-08-10 15:12:26 +02:00
template <typename T, class... Ranges>
class ConstOperationRoot : /*public OperationBase<T>,*/
public OperationTemplate<T,ConstOperationRoot<T,Ranges...> >
{
public:
2017-08-27 17:52:50 +02:00
typedef T value_type;
2017-08-10 15:12:26 +02:00
typedef OperationBase<T> OB;
typedef OperationTemplate<T,ConstOperationRoot<T,Ranges...> > OT;
2017-08-10 15:12:26 +02:00
typedef ContainerRange<Ranges...> CRange;
typedef typename CRange::IndexType IndexType;
ConstOperationRoot(const MultiArrayBase<T,Ranges...>& ma,
2017-08-10 15:12:26 +02:00
const std::shared_ptr<typename Ranges::IndexType>&... indices);
const Block<T>& get() const;
std::vector<BTSS> block(const std::shared_ptr<VIWB> blockIndex) const;
const ConstOperationRoot& block() const;
protected:
2017-08-10 15:12:26 +02:00
MultiArrayBase<T,Ranges...> const& mArrayRef;
2017-08-10 15:12:26 +02:00
std::shared_ptr<IndexType> mIndex;
2017-12-16 20:38:57 +01:00
mutable Block<T> mBlock;
};
2017-09-11 12:54:24 +02:00
2017-08-10 15:12:26 +02:00
template <typename T, class... Ranges>
class OperationRoot : /*public MutableOperationBase<T>,*/
public OperationTemplate<T,OperationRoot<T,Ranges...> >
{
public:
2017-08-27 17:52:50 +02:00
typedef T value_type;
2017-08-10 15:12:26 +02:00
typedef OperationBase<T> OB;
typedef OperationTemplate<T,OperationRoot<T,Ranges...> > OT;
2017-08-10 15:12:26 +02:00
typedef ContainerRange<Ranges...> CRange;
typedef typename CRange::IndexType IndexType;
OperationRoot(MutableMultiArrayBase<T,Ranges...>& ma,
2017-08-10 15:12:26 +02:00
const std::shared_ptr<typename Ranges::IndexType>&... indices);
2017-08-11 11:30:27 +02:00
template <class OpClass>
OperationMaster<T,OpClass,Ranges...> operator=(const OpClass& in);
2017-08-11 11:30:27 +02:00
const MBlock<T>& get() const;
MBlock<T>& get();
std::vector<BTSS> block(const std::shared_ptr<VIWB> blockIndex) const;
const OperationRoot& block() const;
2017-05-24 19:01:02 +02:00
protected:
MutableMultiArrayBase<T,Ranges...>& mArrayRef;
2017-08-10 15:12:26 +02:00
std::shared_ptr<IndexType> mIndex;
2017-12-16 20:38:57 +01:00
mutable MBlock<T> mBlock;
2017-02-16 11:20:40 +01:00
};
2017-09-11 12:54:24 +02:00
2017-08-10 15:12:26 +02:00
template <typename T, class OpFunction, class... Ops>
class Operation : /*public OperationBase<T>,*/
public OperationTemplate<T,Operation<T,OpFunction,Ops...> >
2017-03-22 11:44:33 +01:00
{
public:
2017-08-27 17:52:50 +02:00
typedef T value_type;
2017-08-10 15:12:26 +02:00
typedef OperationBase<T> OB;
typedef OperationTemplate<T,Operation<T,OpFunction,Ops...> > OT;
2017-08-10 15:12:26 +02:00
typedef OpFunction F;
2017-03-22 11:44:33 +01:00
2017-08-11 15:26:10 +02:00
Operation(const Ops&... ops);
2017-03-22 11:44:33 +01:00
const BlockResult<T>& get() const;
std::vector<BTSS> block(const std::shared_ptr<VIWB> blockIndex) const;
const Operation& block() const;
2017-03-22 11:44:33 +01:00
protected:
2017-08-10 15:12:26 +02:00
std::tuple<Ops...> mOps;
mutable BlockResult<T> mRes;
2017-03-22 11:44:33 +01:00
};
2017-11-04 22:49:55 +01:00
2017-11-02 21:20:31 +01:00
template <typename T, class Op, class IndexType>
2017-11-04 22:49:55 +01:00
class Contraction : public OperationTemplate<T,Contraction<T,Op,IndexType> >
{
public:
typedef T value_type;
2017-11-02 21:20:31 +01:00
typedef OperationTemplate<T,Contraction<T,Op,IndexType> > OT;
Contraction(const Op& op, std::shared_ptr<IndexType> ind);
const BlockResult<T>& get() const;
std::vector<BTSS> block(const std::shared_ptr<VIWB> blockIndex) const;
const Contraction& block() const;
protected:
2017-11-05 18:46:38 +01:00
Op mOp;
2017-11-02 21:20:31 +01:00
std::shared_ptr<IndexType> mInd;
mutable BlockResult<T> mRes;
};
2017-08-11 15:26:10 +02:00
}
2017-02-16 11:20:40 +01:00
/* ========================= *
* --- TEMPLATE CODE --- *
* ========================= */
namespace MultiArrayTools
{
namespace
{
using namespace MultiArrayHelper;
}
template <typename T>
2017-12-16 20:38:57 +01:00
Block<T> makeBlock(const T* vec, size_t stepSize, size_t blockSize)
{
2017-12-16 20:38:57 +01:00
return Block<T>(vec, 0, blockSize, stepSize);
}
template <typename T>
2017-12-16 20:38:57 +01:00
MBlock<T> makeBlock(T* vec, size_t stepSize, size_t blockSize)
{
2017-12-16 20:38:57 +01:00
return MBlock<T>(vec, 0, blockSize, stepSize);
}
template <class OpClass>
std::shared_ptr<VIWB> seekBlockIndex(std::shared_ptr<VIWB> ownIdx,
const OpClass& second)
{
std::vector<std::shared_ptr<VIWB> > ivec;
seekIndexInst(ownIdx, ivec);
std::map<std::shared_ptr<VIWB>, std::vector<BTSS> > mp;
for(auto& xx: ivec){
mp[xx] = second.block(xx);
}
// seek minimal number of VALUEs => guarantees absence of conflicting blocks
minimizeAppearanceOfType(mp, BlockType::VALUE);
// seek mininmal number of SPLITs => maximal vectorization possible
minimizeAppearanceOfType(mp, BlockType::SPLIT);
return mp.begin()->first;
}
/***************************
* OperationTemplate *
***************************/
template <typename T, class OperationClass>
OperationTemplate<T,OperationClass>::OperationTemplate(OperationClass* oc) : mOc(oc) {}
template <typename T, class OperationClass>
template <class Second>
auto OperationTemplate<T,OperationClass>::operator+(const Second& in) const
-> Operation<T,std::plus<T>,OperationClass,Second>
{
return Operation<T,std::plus<T>,OperationClass,Second>(*mOc, in);
}
template <typename T, class OperationClass>
template <class Second>
auto OperationTemplate<T,OperationClass>::operator-(const Second& in) const
-> Operation<T,std::minus<T>,OperationClass,Second>
{
return Operation<T,std::minus<T>,OperationClass,Second>(*mOc, in);
}
template <typename T, class OperationClass>
template <class Second>
auto OperationTemplate<T,OperationClass>::operator*(const Second& in) const
-> Operation<T,std::multiplies<T>,OperationClass,Second>
{
return Operation<T,std::multiplies<T>,OperationClass,Second>(*mOc, in);
}
template <typename T, class OperationClass>
template <class Second>
auto OperationTemplate<T,OperationClass>::operator/(const Second& in) const
-> Operation<T,std::divides<T>,OperationClass,Second>
{
return Operation<T,std::divides<T>,OperationClass,Second>(*mOc, in);
}
template <typename T, class OperationClass>
template <class IndexType>
auto OperationTemplate<T,OperationClass>::c(std::shared_ptr<IndexType>& ind) const
-> Contraction<T,OperationClass,IndexType>
{
return Contraction<T,OperationClass,IndexType>(*mOc, ind);
}
/*************************
* OperationMaster *
*************************/
template <typename T, class OpClass, class... Ranges>
OperationMaster<T,OpClass,Ranges...>::
OperationMaster(MutableMultiArrayBase<T,Ranges...>& ma, const OpClass& second,
std::shared_ptr<typename CRange::IndexType>& index) :
mSecond(second), mArrayRef(ma), mIndex()
{
MultiRangeFactory<Ranges...> mrf( index->range() );
std::shared_ptr<MultiRange<Ranges...> > mr =
std::dynamic_pointer_cast<MultiRange<Ranges...> >( mrf.create() );
mIndex = std::make_shared<IndexType>( mr->begin() );
(*mIndex) = *index;
auto blockIndex = seekBlockIndex( make_viwb( mIndex ), second);
std::intptr_t blockIndexNum = blockIndex->getPtrNum();
block(blockIndex);
second.block(blockIndex);
for(*mIndex = 0; mIndex->pos() != mIndex->max(); mIndex->pp(blockIndexNum) ){
get() = mSecond.get();
}
}
template <typename T, class OpClass, class... Ranges>
MBlock<T>& OperationMaster<T,OpClass,Ranges...>::get()
{
block();
2017-12-16 20:38:57 +01:00
return mBlock;
}
template <typename T, class OpClass, class... Ranges>
const Block<T>& OperationMaster<T,OpClass,Ranges...>::get() const
{
block();
2017-12-16 20:38:57 +01:00
return mBlock;
}
template <typename T, class OpClass, class... Ranges>
std::vector<BTSS> OperationMaster<T,OpClass,Ranges...>::block(const std::shared_ptr<VIWB> blockIndex) const
{
std::vector<BTSS> btv(1, getBlockType( make_viwb( mIndex ), blockIndex, true) );
2017-12-16 20:38:57 +01:00
mBlock = makeBlock(mArrayRef.data(), btv[0].second, blockIndex->max());
return btv;
}
template <typename T, class OpClass, class... Ranges>
const OperationMaster<T,OpClass,Ranges...>& OperationMaster<T,OpClass,Ranges...>::block() const
{
2017-12-16 20:38:57 +01:00
mBlock.set( mIndex->pos() );
return *this;
}
/****************************
* ConstOperationRoot *
****************************/
template <typename T, class... Ranges>
ConstOperationRoot<T,Ranges...>::
ConstOperationRoot(const MultiArrayBase<T,Ranges...>& ma,
const std::shared_ptr<typename Ranges::IndexType>&... indices) :
OperationTemplate<T,ConstOperationRoot<T,Ranges...> >(this),
mArrayRef(ma), mIndex( std::make_shared<IndexType>( mArrayRef.range() ) )
{
(*mIndex)(indices...);
}
template <typename T, class... Ranges>
const Block<T>& ConstOperationRoot<T,Ranges...>::get() const
{
block();
2017-12-16 20:38:57 +01:00
return mBlock;
}
template <typename T, class... Ranges>
std::vector<BTSS> ConstOperationRoot<T,Ranges...>::block(const std::shared_ptr<VIWB> blockIndex) const
{
std::vector<BTSS> btv(1, getBlockType( make_viwb( mIndex ), blockIndex, true) );
2017-12-16 20:38:57 +01:00
mBlock = makeBlock(mArrayRef.data(), btv[0].second, blockIndex->max());
return btv;
}
template <typename T, class... Ranges>
const ConstOperationRoot<T,Ranges...>& ConstOperationRoot<T,Ranges...>::block() const
{
2017-12-16 20:38:57 +01:00
mBlock.set( (*mIndex)().pos() );
return *this;
}
/***********************
* OperationRoot *
***********************/
template <typename T, class... Ranges>
OperationRoot<T,Ranges...>::
OperationRoot(MutableMultiArrayBase<T,Ranges...>& ma,
const std::shared_ptr<typename Ranges::IndexType>&... indices) :
OperationTemplate<T,OperationRoot<T,Ranges...> >(this),
mArrayRef(ma), mIndex( std::make_shared<IndexType>( mArrayRef.range() ) )
{
(*mIndex)(indices...);
}
template <typename T, class... Ranges>
template <class OpClass>
OperationMaster<T,OpClass,Ranges...> OperationRoot<T,Ranges...>::operator=(const OpClass& in)
{
return OperationMaster<T,OpClass,Ranges...>(mArrayRef, in, mIndex);
}
template <typename T, class... Ranges>
const MBlock<T>& OperationRoot<T,Ranges...>::get() const
{
block();
2017-12-16 20:38:57 +01:00
return mBlock;
}
template <typename T, class... Ranges>
MBlock<T>& OperationRoot<T,Ranges...>::get()
{
block();
2017-12-16 20:38:57 +01:00
return mBlock;
}
template <typename T, class... Ranges>
std::vector<BTSS> OperationRoot<T,Ranges...>::block(const std::shared_ptr<VIWB> blockIndex) const
{
std::vector<BTSS> btv(1, getBlockType( make_viwb( mIndex ), blockIndex, true) );
2017-12-16 20:38:57 +01:00
mBlock = makeBlock(mArrayRef.data(), btv[0].second, blockIndex->max());
return btv;
}
template <typename T, class... Ranges>
const OperationRoot<T,Ranges...>& OperationRoot<T,Ranges...>::block() const
{
2017-12-16 20:38:57 +01:00
mBlock.set( (*mIndex)().pos() );
return *this;
}
/*******************
* Operation *
*******************/
template <typename T, class OpFunction, class... Ops>
Operation<T,OpFunction,Ops...>::Operation(const Ops&... ops) :
OperationTemplate<T,Operation<T,OpFunction,Ops...> >(this),
mOps(ops...) {}
template <typename T, class OpFunction, class... Ops>
const BlockResult<T>& Operation<T,OpFunction,Ops...>::get() const
{
mRes = std::move( PackNum<sizeof...(Ops)-1>::template unpackArgs<T,OpFunction>(mOps) );
return mRes;
}
template <typename T, class OpFunction, class... Ops>
std::vector<BTSS> Operation<T,OpFunction,Ops...>::block(const std::shared_ptr<VIWB> blockIndex) const
{
std::vector<BTSS> btv;
PackNum<sizeof...(Ops)-1>::makeBlockTypeVec(btv, mOps, blockIndex);
return btv;
}
template <typename T, class OpFunction, class... Ops>
const Operation<T,OpFunction,Ops...>& Operation<T,OpFunction,Ops...>::block() const
{
2017-12-16 20:38:57 +01:00
//mBlock.set( mIndex->pos() );
return *this;
}
/*********************
* Contraction *
*********************/
template <typename T, class Op, class IndexType>
Contraction<T,Op,IndexType>::Contraction(const Op& op, std::shared_ptr<IndexType> ind) :
OperationTemplate<T,Contraction<T,Op,IndexType> >(this),
mOp(op),
mInd(ind) {}
template <typename T, class Op, class IndexType>
const BlockResult<T>& Contraction<T,Op,IndexType>::get() const
{
BlockBinaryOpSelf<T,std::plus<T>,decltype(mOp.get())> f(mRes);
for(*mInd = 0; mInd->pos() != mInd->max(); ++(*mInd)){
f(mOp.get());
}
return mRes;
}
template <typename T, class Op, class IndexType>
std::vector<BTSS> Contraction<T,Op,IndexType>::block(const std::shared_ptr<VIWB> blockIndex) const
{
return mOp.block(blockIndex);
}
template <typename T, class Op, class IndexType>
const Contraction<T,Op,IndexType>& Contraction<T,Op,IndexType>::block() const
{
return *this;
}
}
2017-02-16 11:20:40 +01:00
#endif