blocking: OpTest_1Dim.ExecOp works

This commit is contained in:
Christian Zimmermann 2017-09-09 19:59:09 +02:00
parent cfe93b60f8
commit 9aac8afcd9
10 changed files with 149 additions and 80 deletions

View file

@ -188,6 +188,10 @@ namespace MultiArrayTools
namespace MultiArrayHelper
{
// block.h
template <typename T, class OpFunc>
class BlockBinaryOp;
// block.h
enum class BlockType;

View file

@ -5,6 +5,23 @@
namespace MultiArrayHelper
{
/*********************
* BlockBinaryOp *
*********************/
template <typename T, class OpFunc>
BlockResult<T> BlockBinaryOp<T,OpFunc>::operator()(const BlockBase<T>& arg1,
const BlockBase<T>& arg2)
{
static OpFunc f;
BlockResult<T> res(arg1.size());
assert(arg1.size() == arg2.size());
for(size_t i = 0; i != arg1.size(); ++i){
res[i] = f(arg1[i], arg2[i]);
}
return res;
}
/*****************
* BlockBase *
*****************/
@ -80,6 +97,7 @@ namespace MultiArrayHelper
Block<T>::Block(const std::vector<T>& data,
size_t begPos, size_t size) :
BlockBase<T>(size),
mData(&data),
mBegPtr(data.data() + begPos) {}
template <typename T>
@ -91,13 +109,14 @@ namespace MultiArrayHelper
template <typename T>
const T& Block<T>::operator[](size_t i) const
{
return *(mBegPtr + i);
}
template <typename T>
Block<T>& Block<T>::set(const T* nbeg)
Block<T>& Block<T>::set(size_t npos)
{
mBegPtr = nbeg;
mBegPtr = &(*mData)[npos];
return *this;
}
@ -109,6 +128,7 @@ namespace MultiArrayHelper
MBlock<T>::MBlock(std::vector<T>& data,
size_t begPos, size_t size) :
MutableBlockBase<T>(size),
mData(&data),
mBegPtr(data.data() + begPos) {}
template <typename T>
@ -120,19 +140,21 @@ namespace MultiArrayHelper
template <typename T>
const T& MBlock<T>::operator[](size_t i) const
{
return *(mBegPtr + i);
}
template <typename T>
T& MBlock<T>::operator[](size_t i)
{
return *(mBegPtr + i);
}
template <typename T>
MBlock<T>& MBlock<T>::set(const T* nbeg)
MBlock<T>& MBlock<T>::set(size_t npos)
{
mBegPtr = nbeg;
mBegPtr = &(*mData)[npos];
return *this;
}
@ -141,9 +163,11 @@ namespace MultiArrayHelper
******************/
template <typename T>
BlockValue<T>::BlockValue(const T& val, size_t size) :
BlockValue<T>::BlockValue(const std::vector<T>& data,
size_t pos, size_t size) :
BlockBase<T>(size),
mVal(val) {}
mData(&data),
mVal(data[pos]) {}
template <typename T>
BlockType BlockValue<T>::type() const
@ -154,13 +178,14 @@ namespace MultiArrayHelper
template <typename T>
const T& BlockValue<T>::operator[](size_t i) const
{
return mVal;
}
template <typename T>
BlockValue<T>& BlockValue<T>::set(const T* nbeg)
BlockValue<T>& BlockValue<T>::set(size_t npos)
{
mVal = *nbeg;
mVal = (*mData)[npos];
return *this;
}
@ -169,9 +194,11 @@ namespace MultiArrayHelper
*******************/
template <typename T>
MBlockValue<T>::MBlockValue(T& val, size_t size) :
BlockBase<T>(size),
mVal(val) {}
MBlockValue<T>::MBlockValue(std::vector<T>& data,
size_t pos, size_t size) :
MutableBlockBase<T>(size),
mData(&data),
mVal(data[pos]) {}
template <typename T>
BlockType MBlockValue<T>::type() const
@ -182,19 +209,21 @@ namespace MultiArrayHelper
template <typename T>
const T& MBlockValue<T>::operator[](size_t i) const
{
return mVal;
}
template <typename T>
T& MBlockValue<T>::operator[](size_t i)
{
return mVal;
}
template <typename T>
MBlockValue<T>& MBlockValue<T>::set(const T* nbeg)
MBlockValue<T>& MBlockValue<T>::set(size_t npos)
{
mVal = *nbeg;
mVal = (*mData)[npos];
return *this;
}
@ -206,6 +235,7 @@ namespace MultiArrayHelper
SplitBlock<T>::SplitBlock(const std::vector<T>& data, size_t begPos,
size_t stepSize, size_t size) :
BlockBase<T>(size),
mData(data),
mStepSize(stepSize),
mBegPtr(data.data() + begPos) {}
@ -218,13 +248,14 @@ namespace MultiArrayHelper
template <typename T>
const T& SplitBlock<T>::operator[](size_t pos) const
{
return *(mBegPtr + pos*mStepSize);
}
template <typename T>
SplitBlock<T>& SplitBlock<T>::set(const T* nbeg)
SplitBlock<T>& SplitBlock<T>::set(size_t npos)
{
mBegPtr = nbeg;
mBegPtr = &(*mData)[npos];
return *this;
}
@ -235,7 +266,7 @@ namespace MultiArrayHelper
template <typename T>
MSplitBlock<T>::MSplitBlock(std::vector<T>& data, size_t begPos,
size_t stepSize, size_t size) :
BlockBase<T>(size),
MutableBlockBase<T>(size),
mStepSize(stepSize),
mBegPtr(data.data() + begPos) {}
@ -248,19 +279,21 @@ namespace MultiArrayHelper
template <typename T>
const T& MSplitBlock<T>::operator[](size_t pos) const
{
return *(mBegPtr + pos*mStepSize);
}
template <typename T>
T& MSplitBlock<T>::operator[](size_t pos)
{
return *(mBegPtr + pos*mStepSize);
}
template <typename T>
MSplitBlock<T>& MSplitBlock<T>::set(const T* nbeg)
MSplitBlock<T>& MSplitBlock<T>::set(size_t npos)
{
mBegPtr = nbeg;
mBegPtr = &(*mData)[npos];
return *this;
}
@ -270,7 +303,7 @@ namespace MultiArrayHelper
template <typename T>
BlockResult<T>::BlockResult(size_t size) :
BlockBase<T>(size),
MutableBlockBase<T>(size),
mRes(size) {}
template <typename T>
@ -282,17 +315,19 @@ namespace MultiArrayHelper
template <typename T>
const T& BlockResult<T>::operator[](size_t i) const
{
return mRes[i];
}
template <typename T>
T& BlockResult<T>::operator[](size_t i)
{
return mRes[i];
}
template <typename T>
BlockResult<T>& BlockResult<T>::set(const T* nbeg)
BlockResult<T>& BlockResult<T>::set(size_t npos)
{
return *this;
}

View file

@ -21,6 +21,14 @@ namespace MultiArrayHelper
// manage vectorization in the future !!
template <typename T, class OpFunc>
class BlockBinaryOp
{
public:
BlockBinaryOp() = default;
BlockResult<T> operator()(const BlockBase<T>& arg1, const BlockBase<T>& arg2);
};
template <typename T>
class BlockBase
{
@ -36,7 +44,7 @@ namespace MultiArrayHelper
virtual size_t size() const;
virtual const T& operator[](size_t pos) const = 0;
virtual BlockBase& set(const T* nbeg) = 0;
virtual BlockBase& set(size_t npos) = 0;
template <class OpFunction>
BlockResult<T> operate(const BlockBase& in);
@ -76,9 +84,10 @@ namespace MultiArrayHelper
virtual BlockType type() const override;
virtual const T& operator[](size_t pos) const override;
virtual Block& set(const T* nbeg) override;
virtual Block& set(size_t npos) override;
protected:
const std::vector<T>* mData;
const T* mBegPtr;
};
@ -92,9 +101,10 @@ namespace MultiArrayHelper
virtual BlockType type() const override;
virtual const T& operator[](size_t pos) const override;
virtual T& operator[](size_t pos) override;
virtual MBlock& set(const T* nbeg) override;
virtual MBlock& set(size_t npos) override;
protected:
std::vector<T>* mData;
T* mBegPtr;
};
@ -103,14 +113,16 @@ namespace MultiArrayHelper
{
public:
BlockValue() = default;
BlockValue(const T& val, size_t size);
BlockValue(const std::vector<T>& data,
size_t pos, size_t size);
virtual BlockType type() const override;
virtual const T& operator[](size_t pos) const override;
virtual BlockValue& set(const T* nbeg) override;
virtual BlockValue& set(size_t npos) override;
protected:
T mVal;
const std::vector<T>* mData;
T& mVal;
};
template <typename T>
@ -118,14 +130,16 @@ namespace MultiArrayHelper
{
public:
MBlockValue() = default;
MBlockValue(T& val, size_t size);
MBlockValue(std::vector<T>& data,
size_t pos, size_t size);
virtual BlockType type() const override;
virtual const T& operator[](size_t pos) const override;
virtual T& operator[](size_t pos) override;
virtual MBlockValue& set(const T* nbeg) override;
virtual MBlockValue& set(size_t npos) override;
protected:
std::vector<T>* mData;
T& mVal;
};
@ -140,9 +154,10 @@ namespace MultiArrayHelper
virtual BlockType type() const override;
virtual const T& operator[](size_t pos) const override;
virtual SplitBlock& set(const T* nbeg) override;
virtual SplitBlock& set(size_t npos) override;
protected:
const std::vector<T>* mData;
size_t mStepSize;
const T* mBegPtr;
};
@ -159,9 +174,10 @@ namespace MultiArrayHelper
virtual BlockType type() const override;
virtual const T& operator[](size_t pos) const override;
virtual T& operator[](size_t pos) override;
virtual MSplitBlock& set(const T* nbeg) override;
virtual MSplitBlock& set(size_t npos) override;
protected:
std::vector<T>* mData;
size_t mStepSize;
T* mBegPtr;
};
@ -180,7 +196,7 @@ namespace MultiArrayHelper
virtual BlockType type() const override;
virtual const T& operator[](size_t pos) const override;
virtual T& operator[](size_t i) override;
virtual BlockResult& set(const T* nbeg) override;
virtual BlockResult& set(size_t npos) override;
protected:
std::vector<T> mRes;

View file

@ -526,6 +526,19 @@ namespace MultiArrayTools
return mCont.data();
}
template <typename T, class... SRanges>
const std::vector<T>& MultiArray<T,SRanges...>::datav() const
{
return mCont;
}
template <typename T, class... SRanges>
std::vector<T>& MultiArray<T,SRanges...>::datav()
{
return mCont;
}
/*
template <typename T, class... SRanges>
void MultiArray<T,SRanges...>::manipulate(ManipulatorBase<T>& mb,

View file

@ -81,6 +81,7 @@ namespace MultiArrayTools
virtual const T& at(const typename CRange::IndexType::MetaType& meta) const = 0;
virtual const T* data() const = 0;
virtual const std::vector<T>& datav() const = 0;
virtual size_t size() const;
virtual bool isSlice() const = 0;
@ -171,6 +172,7 @@ namespace MultiArrayTools
virtual T& at(const typename CRange::IndexType::MetaType& meta) = 0;
virtual T* data() = 0;
virtual std::vector<T>& datav() = 0;
virtual iterator begin();
virtual iterator end();
@ -216,8 +218,11 @@ namespace MultiArrayTools
MultiArray<T,SRanges2...> format(const std::shared_ptr<SRanges2>&... nrs); // reformat array using 'nr' which in
// total must have the same size as mRange
const T* data() const override;
T* data() override;
virtual const T* data() const override;
virtual T* data() override;
virtual const std::vector<T>& datav() const override;
virtual std::vector<T>& datav() override;
// virtual void manipulate(ManipulatorBase<T>& mb,
// const typename CRange::IndexType& manBegin,

View file

@ -55,7 +55,7 @@ namespace MultiArrayTools
std::shared_ptr<BlockBase<T> > makeBlock(const std::vector<T>& vec, size_t stepSize, size_t blockSize)
{
if(stepSize == 0){
return std::make_shared<BlockValue<T> >(vec[0], blockSize);
return std::make_shared<BlockValue<T> >(vec, 0, blockSize);
}
else if(stepSize == 1){
return std::make_shared<Block<T> >(vec, 0, blockSize);
@ -69,7 +69,7 @@ namespace MultiArrayTools
std::shared_ptr<MutableBlockBase<T> > makeBlock(std::vector<T>& vec, size_t stepSize, size_t blockSize)
{
if(stepSize == 0){
return std::make_shared<MBlockValue<T> >(vec[0], blockSize);
return std::make_shared<MBlockValue<T> >(vec, 0, blockSize);
}
else if(stepSize == 1){
return std::make_shared<MBlock<T> >(vec, 0, blockSize);
@ -223,14 +223,14 @@ namespace MultiArrayTools
std::vector<BTSS> OperationMaster<T,Ranges...>::block(const std::shared_ptr<IndexBase> blockIndex) const
{
std::vector<BTSS> btv(1, getBlockType(mIndex, blockIndex, true) );
mBlockPtr = makeBlock(mArrayRef.data(), btv[0].second, blockIndex->max());
mBlockPtr = makeBlock(mArrayRef.datav(), btv[0].second, blockIndex->max());
return btv;
}
template <typename T, class... Ranges>
OperationMaster<T,Ranges...>& OperationMaster<T,Ranges...>::block() const
const OperationMaster<T,Ranges...>& OperationMaster<T,Ranges...>::block() const
{
mBlockPtr->set( &mArrayRef[ (*mIndex) ] );
mBlockPtr->set( mIndex->pos() ); // containerRange <-> multiRange !!!
return *this;
}
@ -259,14 +259,14 @@ namespace MultiArrayTools
std::vector<BTSS> ConstOperationRoot<T,Ranges...>::block(const std::shared_ptr<IndexBase> blockIndex) const
{
std::vector<BTSS> btv(1, getBlockType(mIndex, blockIndex, true) );
mBlockPtr = makeBlock(mArrayRef.data(), btv[0].second, blockIndex->max());
mBlockPtr = makeBlock(mArrayRef.datav(), btv[0].second, blockIndex->max());
return btv;
}
template <typename T, class... Ranges>
ConstOperationRoot<T,Ranges...>& ConstOperationRoot<T,Ranges...>::block() const
const ConstOperationRoot<T,Ranges...>& ConstOperationRoot<T,Ranges...>::block() const
{
mBlockPtr->set( &mArrayRef[ (*mIndex)() ] );
mBlockPtr->set( mIndex->pos() );
return *this;
}
@ -308,14 +308,14 @@ namespace MultiArrayTools
std::vector<BTSS> OperationRoot<T,Ranges...>::block(const std::shared_ptr<IndexBase> blockIndex) const
{
std::vector<BTSS> btv(1, getBlockType(mIndex, blockIndex, true) );
mBlockPtr = makeBlock(mArrayRef.data(), btv[0].second, blockIndex->max());
mBlockPtr = makeBlock(mArrayRef.datav(), btv[0].second, blockIndex->max());
return btv;
}
template <typename T, class... Ranges>
OperationRoot<T,Ranges...>& OperationRoot<T,Ranges...>::block() const
const OperationRoot<T,Ranges...>& OperationRoot<T,Ranges...>::block() const
{
mBlockPtr->set( &mArrayRef[ (*mIndex)() ] );
mBlockPtr->set( mIndex->pos() );
return *this;
}
@ -331,7 +331,7 @@ namespace MultiArrayTools
template <typename T, class OpFunction, class... Ops>
const BlockBase<T>& Operation<T,OpFunction,Ops...>::get() const
{
mRes = PackNum<sizeof...(Ops)-1>::template unpackArgs<T,OpFunction>(mOps);
mRes = std::move( PackNum<sizeof...(Ops)-1>::template unpackArgs<T,OpFunction>(mOps) );
return mRes;
}
@ -344,9 +344,9 @@ namespace MultiArrayTools
}
template <typename T, class OpFunction, class... Ops>
Operation<T,OpFunction,Ops...>& Operation<T,OpFunction,Ops...>::block() const
const Operation<T,OpFunction,Ops...>& Operation<T,OpFunction,Ops...>::block() const
{
//mBlockPtr->set( &mArrayRef[ (*mIndex)() ] );
//mBlockPtr->set( mIndex->pos() );
return *this;
}

View file

@ -67,7 +67,7 @@ namespace MultiArrayTools
// init block, return resulting type (BLOCK, VALUE, SPLIT)
virtual std::vector<BTSS> block(const std::shared_ptr<IndexBase> blockIndex) const = 0;
virtual OperationBase& block() const = 0; // update block
virtual const OperationBase& block() const = 0; // update block
//virtual size_t argNum() const = 0;
virtual const BlockBase<T>& get() const = 0;
@ -129,7 +129,7 @@ namespace MultiArrayTools
virtual const BlockBase<T>& get() const override;
virtual std::vector<BTSS> block(const std::shared_ptr<IndexBase> blockIndex) const override;
virtual OperationMaster& block() const override;
virtual const OperationMaster& block() const override;
protected:
@ -159,7 +159,7 @@ namespace MultiArrayTools
virtual const BlockBase<T>& get() const override;
virtual std::vector<BTSS> block(const std::shared_ptr<IndexBase> blockIndex) const override;
virtual ConstOperationRoot& block() const override;
virtual const ConstOperationRoot& block() const override;
protected:
@ -189,7 +189,7 @@ namespace MultiArrayTools
virtual MutableBlockBase<T>& get() override;
virtual std::vector<BTSS> block(const std::shared_ptr<IndexBase> blockIndex) const override;
virtual OperationRoot& block() const override;
virtual const OperationRoot& block() const override;
protected:
@ -214,7 +214,7 @@ namespace MultiArrayTools
virtual const BlockBase<T>& get() const override;
virtual std::vector<BTSS> block(const std::shared_ptr<IndexBase> blockIndex) const override;
virtual Operation& block() const override;
virtual const Operation& block() const override;
protected:
std::tuple<Ops...> mOps;

View file

@ -47,7 +47,8 @@ namespace MultiArrayTools
{
PackNum<sizeof...(Indices)-1>::construct(mIPack, *range);
IB::mPos = PackNum<sizeof...(Indices)-1>::makePos(mIPack);
PackNum<sizeof...(Indices)>::initBlockSizes(mBlockSizes, mIPack); // has one more element!
std::get<sizeof...(Indices)>(mBlockSizes) = 1;
PackNum<sizeof...(Indices)-1>::initBlockSizes(mBlockSizes, mIPack); // has one more element!
}
template <class... Indices>
@ -102,7 +103,7 @@ namespace MultiArrayTools
{
static_assert(DIR < sizeof...(Indices), "DIR exceeds number of sub-indices");
IB::mPos += PackNum<sizeof...(Indices)-DIR-1>::blockSize( mIPack );
PackNum<DIR+1>::pp( mIPack );
PackNum<DIR>::pp( mIPack );
return *this;
}
@ -112,7 +113,7 @@ namespace MultiArrayTools
{
static_assert(DIR < sizeof...(Indices), "DIR exceeds number of sub-indices");
IB::mPos -= PackNum<sizeof...(Indices)-DIR-1>::blockSize( mIPack );
PackNum<DIR+1>::mm( mIPack );
PackNum<DIR>::mm( mIPack );
return *this;
}

View file

@ -110,7 +110,7 @@ namespace {
EXPECT_EQ( fabs( res.at('f') - (0.373+8.215) ) < 0.0001, true );
EXPECT_EQ( fabs( res.at('g') - (7.192+5.063) ) < 0.0001, true );
}
/*
TEST_F(OpTest_MDim, ExecOp1)
{
MultiArray<double,SRange,SRange> res(sr2ptr,sr4ptr);
@ -191,7 +191,7 @@ namespace {
EXPECT_EQ( fabs( res.at(mkt(mkt('3','b'),'A')) - (2.911 + 0.373 + 1.470) ) < 0.0001, true );
EXPECT_EQ( fabs( res.at(mkt(mkt('3','b'),'B')) - (2.911 + 0.373 + 2.210) ) < 0.0001, true );
}
*/
} // anonymous namspace
int main(int argc, char** argv)

View file

@ -40,7 +40,7 @@ namespace MultiArrayHelper
}
template <class IndexType>
static std::shared_ptr<const IndexBase> getIndexPtr(const IndexType& in, size_t n)
static std::shared_ptr<IndexBase> getIndexPtr(const IndexType& in, size_t n)
{
if(n == N){
return in.template getPtr<N>();
@ -62,14 +62,9 @@ namespace MultiArrayHelper
static void initBlockSizes(std::array<size_t,sizeof...(Indices)+1>& bs,
std::tuple<std::shared_ptr<Indices>...>& ip)
{
if(N == sizeof...(Indices)+1){
std::get<N>(bs) = 1;
}
else {
std::get<N>(bs) = PackNum<sizeof...(Indices)-N-1>::blockSize(ip);
PackNum<N-1>::initBlockSizes(bs, ip);
}
}
template <class... Indices>
static inline void pp(std::tuple<std::shared_ptr<Indices>...>& ip)
@ -86,17 +81,17 @@ namespace MultiArrayHelper
template <class... Indices>
static inline size_t pp(std::tuple<std::shared_ptr<Indices>...>& ip,
std::array<size_t,sizeof...(Indices)>& bs,
std::array<size_t,sizeof...(Indices)+1>& bs,
std::shared_ptr<IndexBase> idxPtr)
{
auto siPtr = std::get<N>(ip);
if(siPtr.get() == idxPtr.get()){
return std::get<N>(bs) + PackNum<N-1>::pp(ip);
return std::get<N>(bs) + PackNum<N-1>::pp(ip, bs, idxPtr);
}
else {
if(siPtr->last()){
(*siPtr) = 0;
return PackNum<N-1>::pp(ip, bs) - siPtr->max() + 1;
return PackNum<N-1>::pp(ip, bs, idxPtr) - siPtr->max() + 1;
}
else {
return siPtr->pp(idxPtr);
@ -119,17 +114,17 @@ namespace MultiArrayHelper
template <class... Indices>
static inline size_t mm(std::tuple<std::shared_ptr<Indices>...>& ip,
std::array<size_t,sizeof...(Indices)>& bs,
std::array<size_t,sizeof...(Indices)+1>& bs,
std::shared_ptr<IndexBase> idxPtr)
{
auto siPtr = std::get<N>(ip);
if(siPtr.get() == idxPtr.get()){
return std::get<N>(bs) + PackNum<N-1>::mm(ip);
return std::get<N>(bs) + PackNum<N-1>::mm(ip, bs, idxPtr);
}
else {
if(siPtr->first()){
(*siPtr) = siPtr->max() - 1;
return PackNum<N-1>::mm(ip, bs) - siPtr->max() + 1;
return PackNum<N-1>::mm(ip, bs, idxPtr) - siPtr->max() + 1;
}
else {
return siPtr->mm(idxPtr);
@ -222,7 +217,7 @@ namespace MultiArrayHelper
}
template <typename T, class Func, class ArgTuple, class... Args>
static T unpackArgs(const ArgTuple& tp, const Args&... args)
static BlockResult<T> unpackArgs(const ArgTuple& tp, const Args&... args)
{
return PackNum<N-1>::template unpackArgs<T,Func>(tp, std::get<N>(tp).get(), args...);
}
@ -232,7 +227,7 @@ namespace MultiArrayHelper
const std::tuple<Ops...>& ops,
std::shared_ptr<IndexBase> idxPtr)
{
auto& subvec = std::get<N>(ops).block(idxPtr);
auto subvec = std::move( std::get<N>(ops).block(idxPtr) );
btv.insert(btv.end(), subvec.begin(), subvec.end() );
PackNum<N-1>::makeBlockTypeVec(btv, ops, idxPtr);
}
@ -255,7 +250,7 @@ namespace MultiArrayHelper
}
template <class IndexType>
static std::shared_ptr<const IndexBase> getIndexPtr(const IndexType& in, size_t n)
static std::shared_ptr<IndexBase> getIndexPtr(const IndexType& in, size_t n)
{
return in.template getPtr<0>();
}
@ -283,7 +278,7 @@ namespace MultiArrayHelper
template <class... Indices>
static inline size_t pp(std::tuple<std::shared_ptr<Indices>...>& ip,
std::array<size_t,sizeof...(Indices)>& bs,
std::array<size_t,sizeof...(Indices)+1>& bs,
std::shared_ptr<IndexBase> idxPtr)
{
auto siPtr = std::get<0>(ip);
@ -304,7 +299,7 @@ namespace MultiArrayHelper
template <class... Indices>
static inline size_t mm(std::tuple<std::shared_ptr<Indices>...>& ip,
std::array<size_t,sizeof...(Indices)>& bs,
std::array<size_t,sizeof...(Indices)+1>& bs,
std::shared_ptr<IndexBase> idxPtr)
{
auto siPtr = std::get<0>(ip);
@ -392,11 +387,11 @@ namespace MultiArrayHelper
}
template <typename T, class Func, class ArgTuple, class... Args>
static T unpackArgs(const ArgTuple& tp, const Args&... args)
static BlockResult<T> unpackArgs(const ArgTuple& tp, const Args&... args)
{
static_assert(sizeof...(Args) == std::tuple_size<ArgTuple>::value-1,
"inconsistent number of arguments");
static Func f;
static BlockBinaryOp<T,Func> f;
return f(std::get<0>(tp).get(), args...);
}
@ -405,7 +400,7 @@ namespace MultiArrayHelper
const std::tuple<Ops...>& ops,
std::shared_ptr<IndexBase> idxPtr)
{
auto& subvec = std::get<0>(ops).block(idxPtr);
auto subvec = std::move( std::get<0>(ops).block(idxPtr) );
btv.insert(btv.end(), subvec.begin(), subvec.end() );
}