cnorxz/src/include/multi_array_operation.h

640 lines
17 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"
2017-12-18 13:13:13 +01:00
#include "ranges/rheader.h"
#include "pack_num.h"
2017-02-16 11:20:40 +01:00
#include "arith.h"
2017-12-25 13:44:55 +01:00
2017-02-16 11:20:40 +01:00
namespace MultiArrayTools
{
namespace
{
using namespace MultiArrayHelper;
}
2018-05-15 21:18:21 +02:00
template <typename T, class OperationClass>
class OperationBase
2017-08-11 11:30:27 +02:00
{
public:
2017-08-27 17:52:50 +02:00
2017-12-25 13:44:55 +01:00
OperationClass& THIS() { return static_cast<OperationClass&>(*this); }
const OperationClass& THIS() const { return static_cast<OperationClass const&>(*this); }
template <typename U, class Second>
auto operator+(const OperationBase<U,Second>& in) const;
2017-08-26 17:18:42 +02:00
template <typename U, class Second>
auto operator-(const OperationBase<U,Second>& in) const;
2017-08-26 17:18:42 +02:00
template <typename U, class Second>
auto operator*(const OperationBase<U,Second>& in) const;
2017-08-26 17:18:42 +02:00
template <typename U, class Second>
auto operator/(const OperationBase<U,Second>& in) const;
2017-11-05 18:46:38 +01:00
2017-11-02 21:20:31 +01:00
template <class IndexType>
2018-09-11 18:38:30 +02:00
auto c(const std::shared_ptr<IndexType>& ind) const
2017-11-02 21:20:31 +01:00
-> Contraction<T,OperationClass,IndexType>;
2018-09-11 18:38:30 +02:00
template <class... Indices>
auto sl(const std::shared_ptr<Indices>&... inds) const
-> ConstSlice<T,typename Indices::RangeType...>;
2018-09-14 17:50:19 +02:00
template <class... Indices>
2018-09-15 16:33:49 +02:00
auto slc(const std::shared_ptr<Indices>&... inds) const
2018-09-15 01:58:17 +02:00
-> SliceContraction<T,OperationClass,Indices...>;
template <class... Indices>
auto p(const std::shared_ptr<Indices>&... inds) const
-> ConstOperationRoot<T,typename Indices::RangeType...>;
template <class... Indices>
auto to(const std::shared_ptr<Indices>&... inds) const
-> MultiArray<T,typename Indices::RangeType...>;
2019-02-19 16:35:01 +01:00
template <class... Indices>
auto addto(const std::shared_ptr<Indices>&... inds) const
2019-02-19 16:20:38 +01:00
-> MultiArray<T,typename Indices::RangeType...>;
template <class... Indices>
auto pto(const std::shared_ptr<Indices>&... inds) const
-> MultiArray<T,typename Indices::RangeType...>;
template <class... Indices>
auto paddto(const std::shared_ptr<Indices>&... inds) const
-> MultiArray<T,typename Indices::RangeType...>;
template <typename R, class... Args> // Args = Operation Classes
auto a(const std::shared_ptr<function<R,T,typename Args::value_type...>>& ll, const Args&... args) const
-> Operation<R,function<R,T,typename Args::value_type...>,OperationClass, Args...>;
private:
2017-12-25 13:44:55 +01:00
friend OperationClass;
friend OperationTemplate<T,OperationClass>;
OperationBase() = default;
2017-08-11 11:30:27 +02:00
};
template <typename T, class OperationClass>
class OperationTemplate : public OperationBase<T,OperationClass>
{
/* empty per default; specialize if needed */
private:
OperationTemplate() = default;
friend OperationClass;
};
template <typename T>
struct SelfIdentity
{
2019-02-26 18:56:57 +01:00
static inline T& sapply(T& a, T b)
{
2019-02-14 14:39:59 +01:00
return a = b;
}
};
2019-01-15 17:41:43 +01:00
template <typename T, class OpClass>
class AssignmentExpr
{
private:
AssignmentExpr() = default;
OpClass mSec;
T* mDataPtr;
2019-02-26 18:56:57 +01:00
public:
2018-01-07 23:08:16 +01:00
static constexpr size_t LAYER = 0;
static constexpr size_t SIZE = OpClass::SIZE;
typedef decltype(mSec.rootSteps()) ExtType;
2018-01-07 23:08:16 +01:00
AssignmentExpr(T* dataPtr, const OpClass& sec);
AssignmentExpr(const AssignmentExpr& in) = default;
AssignmentExpr(AssignmentExpr&& in) = default;
2018-01-07 23:08:16 +01:00
inline void operator()(size_t start = 0);
inline void operator()(size_t start, ExtType last);
auto rootSteps(std::intptr_t iPtrNum = 0) const -> ExtType;
};
2019-02-26 18:56:57 +01:00
template <typename T, class Target, class OpClass>
class AssignmentExpr2
{
private:
AssignmentExpr2() = default;
Target mTar;
OpClass mSec;
T* mDataPtr;
public:
static constexpr size_t LAYER = 0;
static constexpr size_t SIZE = Target::SIZE + OpClass::SIZE;
typedef decltype(mTar.rootSteps(0).extend( mSec.rootSteps(0) )) ExtType;
AssignmentExpr2(T* dataPtr, const Target& tar, const OpClass& sec);
AssignmentExpr2(const AssignmentExpr2& in) = default;
AssignmentExpr2(AssignmentExpr2&& in) = default;
inline void operator()(size_t start = 0);
inline void operator()(size_t start, ExtType last);
auto rootSteps(std::intptr_t iPtrNum = 0) const -> ExtType;
};
template <typename T, class OpClass>
class AddExpr
{
private:
AddExpr() = default;
2019-02-26 18:56:57 +01:00
OpClass mSec;
T* mDataPtr;
2019-02-26 18:56:57 +01:00
public:
2019-02-26 18:56:57 +01:00
static constexpr size_t LAYER = 0;
static constexpr size_t SIZE = OpClass::SIZE;
typedef decltype(mSec.rootSteps()) ExtType;
2019-02-26 18:56:57 +01:00
AddExpr(T* dataPtr, const OpClass& sec);
AddExpr(const AddExpr& in) = default;
AddExpr(AddExpr&& in) = default;
2019-02-26 18:56:57 +01:00
inline void operator()(size_t start = 0);
inline void operator()(size_t start, ExtType last);
auto rootSteps(std::intptr_t iPtrNum = 0) const -> ExtType;
2017-02-16 11:20:40 +01:00
};
2017-08-10 15:12:26 +02:00
template <typename T, class... Ranges>
class ConstOperationRoot : public OperationTemplate<T,ConstOperationRoot<T,Ranges...> >
{
public:
2017-08-27 17:52:50 +02:00
typedef T value_type;
typedef OperationBase<T,ConstOperationRoot<T,Ranges...> > OT;
typedef ContainerRange<T,Ranges...> CRange;
typedef ContainerIndex<T,typename Ranges::IndexType...> IndexType;
static constexpr size_t SIZE = 1;
2019-02-27 13:37:53 +01:00
static constexpr bool CONT = true;
ConstOperationRoot(const MultiArrayBase<T,Ranges...>& ma,
2017-08-10 15:12:26 +02:00
const std::shared_ptr<typename Ranges::IndexType>&... indices);
ConstOperationRoot(std::shared_ptr<MultiArrayBase<T,Ranges...> > maptr,
const std::shared_ptr<typename Ranges::IndexType>&... indices);
ConstOperationRoot(const T* data, const IndexType& ind);
2018-02-12 18:26:56 +01:00
template <class ET>
2019-02-27 13:37:53 +01:00
inline const T& get(ET pos) const;
2018-09-15 01:58:17 +02:00
template <class ET>
2019-02-26 18:56:57 +01:00
inline ConstOperationRoot& set(ET pos);
2018-09-15 01:58:17 +02:00
2018-02-13 15:38:03 +01:00
MExt<void> rootSteps(std::intptr_t iPtrNum = 0) const; // nullptr for simple usage with decltype
template <class Expr>
Expr loop(Expr exp) const;
2018-09-11 18:38:30 +02:00
const T* data() const;
private:
2017-12-25 13:44:55 +01:00
2018-02-13 15:38:03 +01:00
const T* mDataPtr;
2019-02-26 18:56:57 +01:00
const T* mOrigDataPtr;
IndexType mIndex;
2018-09-16 15:53:56 +02:00
std::shared_ptr<MultiArrayBase<T,Ranges...> > mMaPtr; // never remove this ptr, otherwise we lose temporary container instances!
};
template <typename T, class Op>
class StaticCast : public OperationTemplate<T,StaticCast<T,Op> >
{
private:
2019-02-26 18:56:57 +01:00
Op mOp;
public:
typedef T value_type;
typedef OperationBase<T,StaticCast<T,Op> > OT;
typedef typename Op::CRange CRange;
typedef typename Op::IndexType IndexType;
static constexpr size_t SIZE = Op::SIZE;
2019-02-27 13:37:53 +01:00
static constexpr bool CONT = false;
StaticCast(const Op& op);
template <class ET>
inline T get(ET pos) const;
2018-09-15 01:58:17 +02:00
template <class ET>
2019-02-26 18:56:57 +01:00
inline StaticCast& set(ET pos);
2018-09-15 01:58:17 +02:00
auto rootSteps(std::intptr_t iPtrNum = 0) const
-> decltype(mOp.rootSteps(iPtrNum));
template <class Expr>
Expr loop(Expr exp) const;
};
template <typename T, class Op>
StaticCast<T,Op> staticcast(const Op& op)
{
return StaticCast<T,Op>(op);
}
template <class Range>
class MetaOperationRoot : public OperationTemplate<typename Range::MetaType,
MetaOperationRoot<Range> >
{
public:
typedef typename Range::IndexType IndexType;
typedef typename IndexType::MetaType value_type;
typedef OperationBase<value_type,MetaOperationRoot<Range> > OT;
static constexpr size_t SIZE = 1;
2019-02-27 13:37:53 +01:00
static constexpr bool CONT = false;
MetaOperationRoot(const std::shared_ptr<IndexType>& ind);
template <class ET>
inline value_type get(ET pos) const;
2018-09-15 01:58:17 +02:00
template <class ET>
2019-02-26 18:56:57 +01:00
inline MetaOperationRoot& set(ET pos);
2018-09-15 01:58:17 +02:00
MExt<void> rootSteps(std::intptr_t iPtrNum = 0) const; // nullptr for simple usage with decltype
template <class Expr>
Expr loop(Expr exp) const;
private:
2018-11-26 18:23:38 +01:00
mutable IndexType mWorkIndex;
std::shared_ptr<IndexType> mIndex;
};
2017-08-10 15:12:26 +02:00
template <typename T, class... Ranges>
2018-01-05 13:56:16 +01:00
class OperationRoot : public OperationTemplate<T,OperationRoot<T,Ranges...> >
{
public:
2017-08-27 17:52:50 +02:00
typedef T value_type;
typedef OperationBase<T,OperationRoot<T,Ranges...> > OT;
typedef ContainerRange<T,Ranges...> CRange;
typedef ContainerIndex<T,typename Ranges::IndexType...> IndexType;
static constexpr size_t SIZE = 1;
2019-02-27 13:37:53 +01:00
static constexpr bool CONT = true;
private:
T* mDataPtr;
T* mOrigDataPtr;
IndexType mIndex;
public:
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
OperationRoot(T* data, const IndexType& ind);
template <class OpClass>
2019-05-07 16:40:40 +02:00
auto assign(const OpClass& in) const
-> decltype(mIndex.ifor(1,in.loop(AssignmentExpr<T,OpClass>(mOrigDataPtr,in))));
2019-01-15 17:41:43 +01:00
2019-05-10 18:14:13 +02:00
template <class OpClass>
auto assignExpr(const OpClass& in) const
-> decltype(in.loop(AssignmentExpr<T,OpClass>(mOrigDataPtr,in)));
template <class OpClass, class Index>
2019-05-07 16:40:40 +02:00
auto assign(const OpClass& in, const std::shared_ptr<Index>& i) const
-> decltype(i->ifor(1,in.loop(AssignmentExpr2<T,OperationRoot<T,Ranges...>,OpClass>
(mOrigDataPtr,*this,in))));
template <class OpClass>
2019-05-07 16:40:40 +02:00
auto plus(const OpClass& in) const
-> decltype(mIndex.ifor(1,in.loop(AddExpr<T,OpClass>(mOrigDataPtr,in))));
2019-02-26 18:56:57 +01:00
template <class OpClass>
OperationRoot& operator=(const OpClass& in);
template <class OpClass>
OperationRoot& operator+=(const OpClass& in);
OperationRoot& operator=(const OperationRoot& in);
ParallelOperationRoot<T,Ranges...> par();
2019-01-15 17:41:43 +01:00
2018-02-12 18:26:56 +01:00
template <class ET>
2019-02-27 13:37:53 +01:00
inline T& get(ET pos) const;
2018-09-15 01:58:17 +02:00
template <class ET>
2019-02-26 18:56:57 +01:00
inline OperationRoot& set(ET pos);
2018-09-15 01:58:17 +02:00
2018-02-13 15:38:03 +01:00
MExt<void> rootSteps(std::intptr_t iPtrNum = 0) const; // nullptr for simple usage with decltype
template <class Expr>
Expr loop(Expr exp) const;
T* data() const;
2017-05-24 19:01:02 +02:00
2018-09-11 18:38:30 +02:00
template <class... Indices>
auto sl(const std::shared_ptr<Indices>&... inds)
-> Slice<T,typename Indices::RangeType...>;
};
template <typename T, class... Ranges>
class ParallelOperationRoot : public OperationTemplate<T,ParallelOperationRoot<T,Ranges...> >
{
public:
typedef T value_type;
typedef OperationBase<T,ParallelOperationRoot<T,Ranges...> > OT;
typedef ContainerRange<T,Ranges...> CRange;
typedef ContainerIndex<T,typename Ranges::IndexType...> IndexType;
static constexpr size_t SIZE = 1;
static constexpr bool CONT = true;
private:
2017-12-25 13:44:55 +01:00
2018-02-13 15:38:03 +01:00
T* mDataPtr;
2019-02-26 18:56:57 +01:00
T* mOrigDataPtr;
IndexType mIndex;
public:
ParallelOperationRoot(MutableMultiArrayBase<T,Ranges...>& ma,
const std::shared_ptr<typename Ranges::IndexType>&... indices);
ParallelOperationRoot(T* data, const IndexType& ind);
template <class OpClass>
auto assign(const OpClass& in)
-> decltype(mIndex.pifor(1,in.loop(AssignmentExpr<T,OpClass>(mOrigDataPtr,in))));
template <class OpClass>
auto plus(const OpClass& in)
-> decltype(mIndex.pifor(1,in.loop(AddExpr<T,OpClass>(mOrigDataPtr,in))));
template <class OpClass>
ParallelOperationRoot& operator=(const OpClass& in);
template <class OpClass>
ParallelOperationRoot& operator+=(const OpClass& in);
ParallelOperationRoot& operator=(const ParallelOperationRoot& in);
template <class ET>
inline T& get(ET pos) const;
template <class ET>
inline ParallelOperationRoot& set(ET pos);
MExt<void> rootSteps(std::intptr_t iPtrNum = 0) const; // nullptr for simple usage with decltype
template <class Expr>
Expr loop(Expr exp) const;
T* data() const;
2017-02-16 11:20:40 +01:00
};
template <typename T>
class OperationValue : public OperationTemplate<T,OperationValue<T> >
{
public:
typedef T value_type;
typedef OperationBase<T,OperationValue<T> > OT;
typedef ContainerRange<T,NullRange> CRange;
typedef ContainerIndex<T,NullIndex> IndexType;
static constexpr size_t SIZE = 0;
2019-02-27 13:37:53 +01:00
static constexpr bool CONT = true;
OperationValue(const T& val);
template <class ET>
2019-02-27 13:37:53 +01:00
inline const T& get(ET pos) const;
2018-09-15 01:58:17 +02:00
template <class ET>
2019-02-26 18:56:57 +01:00
inline OperationValue& set(ET pos);
2018-09-15 01:58:17 +02:00
None rootSteps(std::intptr_t iPtrNum = 0) const; // nullptr for simple usage with decltype
template <class Expr>
Expr loop(Expr exp) const;
private:
T mVal;
};
template <class Op>
size_t sumRootNum()
{
return typename Op::rootNum();
}
template <class Op1, class Op2, class... Ops>
size_t sumRootNum()
{
return typename Op1::rootNum() + sumRootNum<Op2,Ops...>();
}
template <size_t N>
struct RootSumN
{
template <class Op1, class... Ops>
struct rs
{
2018-02-13 15:38:03 +01:00
static constexpr size_t SIZE = Op1::SIZE + RootSumN<N-1>::template rs<Ops...>::SIZE;
};
};
template <>
struct RootSumN<0>
{
template <class Op1>
struct rs
{
2018-02-13 15:38:03 +01:00
static constexpr size_t SIZE = Op1::SIZE;
};
};
template <class... Ops>
struct RootSum
{
2018-02-13 15:38:03 +01:00
static constexpr size_t SIZE = RootSumN<sizeof...(Ops)-1>::template rs<Ops...>::SIZE;
};
2017-09-11 12:54:24 +02:00
2017-08-10 15:12:26 +02:00
template <typename T, class OpFunction, class... Ops>
2018-01-05 13:56:16 +01:00
class Operation : 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;
typedef OperationBase<T,Operation<T,OpFunction,Ops...> > OT;
2017-08-10 15:12:26 +02:00
typedef OpFunction F;
2018-02-13 15:38:03 +01:00
static constexpr size_t SIZE = RootSum<Ops...>::SIZE;
static constexpr bool FISSTATIC = OpFunction::FISSTATIC;
2019-02-27 13:37:53 +01:00
static constexpr bool CONT = false;
private:
2018-02-13 15:38:03 +01:00
std::tuple<Ops...> mOps;
std::shared_ptr<OpFunction> mF; // only if non-static
public:
2018-02-13 21:36:41 +01:00
typedef decltype(PackNum<sizeof...(Ops)-1>::template mkSteps<Ops...>(0, mOps)) ETuple;
2017-08-11 15:26:10 +02:00
Operation(const Ops&... ops);
Operation(std::shared_ptr<OpFunction> ff, const Ops&... ops);
2017-03-22 11:44:33 +01:00
2018-02-13 15:38:03 +01:00
template <class ET>
2019-05-20 18:32:19 +02:00
inline auto get(ET pos) const;
2018-09-15 01:58:17 +02:00
template <class ET>
2019-02-26 18:56:57 +01:00
inline Operation& set(ET pos);
2018-09-15 01:58:17 +02:00
auto rootSteps(std::intptr_t iPtrNum = 0) const // nullptr for simple usage with decltype
2018-02-13 15:38:03 +01:00
-> decltype(PackNum<sizeof...(Ops)-1>::mkSteps(iPtrNum, mOps));
template <class Expr>
auto loop(Expr exp) const
-> decltype(PackNum<sizeof...(Ops)-1>::mkLoop( mOps, exp));
2017-03-22 11:44:33 +01:00
};
2018-03-19 18:38:53 +01:00
2018-09-12 20:56:55 +02:00
namespace
{
template <bool FISSTATIC>
struct OpMaker
{
template <class OpFunction, class... Ops>
static inline auto mkOperation(const std::shared_ptr<OpFunction>& f, const Ops&... ops)
-> Operation<typename OpFunction::value_type,OpFunction,Ops...>
{
return Operation<typename OpFunction::value_type,OpFunction,Ops...>(f,ops...);
}
};
template <>
struct OpMaker<true>
{
template <class OpFunction, class... Ops>
static inline auto mkOperation(const std::shared_ptr<OpFunction>& f, const Ops&... ops)
-> Operation<typename OpFunction::value_type,OpFunction,Ops...>
{
return Operation<typename OpFunction::value_type,OpFunction,Ops...>(ops...);
}
};
}
template <class OpFunction, class... Ops>
2018-09-12 20:56:55 +02:00
auto mkOperation(const std::shared_ptr<OpFunction>& f, const Ops&... ops)
-> Operation<typename OpFunction::value_type,OpFunction,Ops...>
{
2018-09-12 20:56:55 +02:00
return OpMaker<OpFunction::FISSTATIC>::mkOperation(f, ops...);
}
2018-07-19 13:00:34 +02: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;
typedef OperationBase<T,Contraction<T,Op,IndexType> > OT;
static constexpr size_t SIZE = Op::SIZE;
2019-02-27 13:37:53 +01:00
static constexpr bool CONT = Op::CONT;
private:
2019-02-26 18:56:57 +01:00
Op mOp;
std::shared_ptr<IndexType> mInd;
public:
typedef decltype(mOp.rootSteps(0)) ETuple;
2017-11-02 21:20:31 +01:00
Contraction(const Op& op, std::shared_ptr<IndexType> ind);
2018-02-13 15:38:03 +01:00
template <class ET>
2019-02-27 13:37:53 +01:00
inline auto get(ET pos) const
-> decltype(mOp.template get<ET>(pos));
2018-09-15 01:58:17 +02:00
template <class ET>
2019-02-26 18:56:57 +01:00
inline Contraction& set(ET pos);
2018-09-15 01:58:17 +02:00
auto rootSteps(std::intptr_t iPtrNum = 0) const // nullptr for simple usage with decltype
-> decltype(mOp.rootSteps(iPtrNum));
template <class Expr>
auto loop(Expr exp) const
-> decltype(mInd->iforh(1,mOp.loop(exp)));
};
2018-05-15 21:18:21 +02:00
2018-09-14 17:50:19 +02:00
template <typename T, class Op, class... Indices>
2018-09-15 01:58:17 +02:00
// class SliceContraction : public OperationTemplate
//<MultiArray<T,typename Indices::RangeType...>,
//SliceContraction<MultiArray<T,typename Indices::RangeType...>,Op,Indices...> >
class SliceContraction : public OperationTemplate<T,SliceContraction<T,Op,Indices...> >
2018-09-14 17:50:19 +02:00
{
public:
2018-09-15 01:58:17 +02:00
typedef MultiArray<T,typename Indices::RangeType...> value_type;
typedef OperationTemplate<T,SliceContraction<T,Op,Indices...> > OT;
2018-09-14 17:50:19 +02:00
static constexpr size_t SIZE = Op::SIZE;
2019-02-27 13:37:53 +01:00
static constexpr bool CONT = false;
2018-09-14 17:50:19 +02:00
private:
2019-02-26 18:56:57 +01:00
mutable Op mOp;
mutable std::shared_ptr<MultiArray<T,typename Indices::RangeType...> > mCont;
2018-09-15 01:58:17 +02:00
mutable OperationRoot<T,typename Indices::RangeType...> mTarOp;
2018-09-14 17:50:19 +02:00
public:
typedef decltype(mOp.rootSteps(0)) ETuple;
2018-09-15 16:33:49 +02:00
SliceContraction(const Op& op, std::shared_ptr<Indices>... ind);
2018-09-14 17:50:19 +02:00
template <class ET>
inline const value_type& get(ET pos) const;
2018-09-15 01:58:17 +02:00
template <class ET>
2019-02-26 18:56:57 +01:00
inline SliceContraction& set(ET pos);
2018-09-15 01:58:17 +02:00
2018-09-14 17:50:19 +02:00
auto rootSteps(std::intptr_t iPtrNum = 0) const // nullptr for simple usage with decltype
-> decltype(mOp.rootSteps(iPtrNum));
template <class Expr>
auto loop(Expr exp) const -> decltype(mOp.loop(exp)); // no loop
};
2017-08-11 15:26:10 +02:00
}
2017-02-16 11:20:40 +01:00
#include "type_operations.h"
2017-02-16 11:20:40 +01:00
#endif