finish parts of auto-vectorization
This commit is contained in:
parent
db92197048
commit
64d10867dd
5 changed files with 180 additions and 46 deletions
|
@ -48,6 +48,7 @@ namespace MultiArrayTools
|
||||||
{
|
{
|
||||||
static constexpr bool FISSTATIC = true;
|
static constexpr bool FISSTATIC = true;
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
|
typedef F function;
|
||||||
|
|
||||||
template <class... Ops>
|
template <class... Ops>
|
||||||
static auto mk(const Ops&... ops)
|
static auto mk(const Ops&... ops)
|
||||||
|
@ -74,6 +75,11 @@ namespace MultiArrayTools
|
||||||
{
|
{
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline T selfApply(T& a1, const T& a2)
|
||||||
|
{
|
||||||
|
return a1 = a2;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
|
|
|
@ -17,6 +17,7 @@ namespace MultiArrayTools
|
||||||
|
|
||||||
static constexpr size_t SIZE = 1;
|
static constexpr size_t SIZE = 1;
|
||||||
static constexpr bool CONT = true;
|
static constexpr bool CONT = true;
|
||||||
|
static constexpr bool VABLE = false;
|
||||||
|
|
||||||
DynamicOperationBase() = default;
|
DynamicOperationBase() = default;
|
||||||
DynamicOperationBase(const DynamicOperationBase& in) = default;
|
DynamicOperationBase(const DynamicOperationBase& in) = default;
|
||||||
|
@ -125,6 +126,7 @@ namespace MultiArrayTools
|
||||||
|
|
||||||
static constexpr size_t SIZE = 1;
|
static constexpr size_t SIZE = 1;
|
||||||
static constexpr bool CONT = true;
|
static constexpr bool CONT = true;
|
||||||
|
static constexpr bool VABLE = false;
|
||||||
|
|
||||||
DynamicO() = default;
|
DynamicO() = default;
|
||||||
DynamicO(const DynamicO& in) : mOp(in.mOp ? in.mOp->deepCopy() : nullptr) {}
|
DynamicO(const DynamicO& in) : mOp(in.mOp ? in.mOp->deepCopy() : nullptr) {}
|
||||||
|
@ -144,6 +146,11 @@ namespace MultiArrayTools
|
||||||
|
|
||||||
template <class X>
|
template <class X>
|
||||||
inline T get(const DExtTX<X>& pos) const { return mOp->get(pos.reduce()); }
|
inline T get(const DExtTX<X>& pos) const { return mOp->get(pos.reduce()); }
|
||||||
|
|
||||||
|
template <typename V,class X>
|
||||||
|
inline auto vget(const DExtTX<X>& pos) const
|
||||||
|
{ return mOp->template vget<V>(pos.reduce()); }
|
||||||
|
|
||||||
template <class X>
|
template <class X>
|
||||||
inline DynamicO& set(const DExtTX<X>& pos) { mOp->set(pos.reduce()); return *this; }
|
inline DynamicO& set(const DExtTX<X>& pos) { mOp->set(pos.reduce()); return *this; }
|
||||||
inline DExtT rootSteps(std::intptr_t iPtrNum = 0) const { return mOp->rootSteps(iPtrNum); }
|
inline DExtT rootSteps(std::intptr_t iPtrNum = 0) const { return mOp->rootSteps(iPtrNum); }
|
||||||
|
|
|
@ -555,55 +555,78 @@ namespace MultiArrayTools
|
||||||
template <typename T, class... Ranges>
|
template <typename T, class... Ranges>
|
||||||
template <class OpClass>
|
template <class OpClass>
|
||||||
auto OperationRoot<T,Ranges...>::assign(const OpClass& in) const
|
auto OperationRoot<T,Ranges...>::assign(const OpClass& in) const
|
||||||
-> decltype(this->template asx<IAssign>(in))
|
-> decltype(this->template asx<IAssign<T>>(in))
|
||||||
{
|
{
|
||||||
return this->template asx<IAssign>(in);
|
return this->template asx<IAssign<T>>(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, class... Ranges>
|
template <typename T, class... Ranges>
|
||||||
template <class OpClass>
|
template <class OpClass>
|
||||||
auto OperationRoot<T,Ranges...>::assignExpr(const OpClass& in) const
|
auto OperationRoot<T,Ranges...>::assignExpr(const OpClass& in) const
|
||||||
-> decltype(this->template asxExpr<IAssign>(in))
|
-> decltype(this->template asxExpr<IAssign<T>>(in))
|
||||||
{
|
{
|
||||||
return this->template asxExpr<IAssign>(in);
|
return this->template asxExpr<IAssign<T>>(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, class... Ranges>
|
template <typename T, class... Ranges>
|
||||||
template <class OpClass, class Index>
|
template <class OpClass, class Index>
|
||||||
auto OperationRoot<T,Ranges...>::assign(const OpClass& in, const std::shared_ptr<Index>& i) const
|
auto OperationRoot<T,Ranges...>::assign(const OpClass& in, const std::shared_ptr<Index>& i) const
|
||||||
-> decltype(this->template asx<IAssign>(in,i))
|
-> decltype(this->template asx<IAssign<T>>(in,i))
|
||||||
{
|
{
|
||||||
return this->template asx<IAssign>(in,i);
|
return this->template asx<IAssign<T>>(in,i);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, class... Ranges>
|
template <typename T, class... Ranges>
|
||||||
template <class OpClass>
|
template <class OpClass>
|
||||||
auto OperationRoot<T,Ranges...>::plus(const OpClass& in) const
|
auto OperationRoot<T,Ranges...>::plus(const OpClass& in) const
|
||||||
-> decltype(this->template asx<IPlus>(in))
|
-> decltype(this->template asx<IPlus<T>>(in))
|
||||||
{
|
{
|
||||||
return this->template asx<IPlus>(in);
|
return this->template asx<IPlus<T>>(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, class... Ranges>
|
template <typename T, class... Ranges>
|
||||||
template <class OpClass, class Index>
|
template <class OpClass, class Index>
|
||||||
auto OperationRoot<T,Ranges...>::plus(const OpClass& in, const std::shared_ptr<Index>& i) const
|
auto OperationRoot<T,Ranges...>::plus(const OpClass& in, const std::shared_ptr<Index>& i) const
|
||||||
-> decltype(this->template asx<IPlus>(in,i))
|
-> decltype(this->template asx<IPlus<T>>(in,i))
|
||||||
{
|
{
|
||||||
return this->template asx<IPlus>(in,i);
|
return this->template asx<IPlus<T>>(in,i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <bool VABLE = false>
|
||||||
|
struct VExec
|
||||||
|
{
|
||||||
|
template <typename TarOp, class OpClass>
|
||||||
|
static inline void exec(TarOp& th, const OpClass& in)
|
||||||
|
{
|
||||||
|
th.assign(in)();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct VExec<true>
|
||||||
|
{
|
||||||
|
template <typename TarOp, class OpClass>
|
||||||
|
static inline void exec(TarOp& th, const OpClass& in)
|
||||||
|
{
|
||||||
|
CHECK;
|
||||||
|
typedef typename TarOp::value_type T;
|
||||||
|
auto x = th.template asx<IVAssign<typename VType<T>::type,T>>(in);
|
||||||
|
const size_t inum = x.vec(VType<T>::MULT);
|
||||||
|
if(x.rootSteps(inum) == 1){
|
||||||
|
CHECK;
|
||||||
|
x();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
th.assign(in)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T, class... Ranges>
|
template <typename T, class... Ranges>
|
||||||
template <class OpClass>
|
template <class OpClass>
|
||||||
OperationRoot<T,Ranges...>& OperationRoot<T,Ranges...>::operator=(const OpClass& in)
|
OperationRoot<T,Ranges...>& OperationRoot<T,Ranges...>::operator=(const OpClass& in)
|
||||||
{
|
{
|
||||||
auto x = this->template asx<IVAssign<typename VType<T>::type>>(in);
|
VExec<OpClass::VABLE>::exec(*this,in);
|
||||||
const size_t inum = x.vec(VType<T>::MULT);
|
|
||||||
if(x.rootSteps(inum) == 1){
|
|
||||||
x();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
assign(in)();
|
|
||||||
}
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -896,7 +919,7 @@ namespace MultiArrayTools
|
||||||
{
|
{
|
||||||
typedef std::tuple<Ops...> OpTuple;
|
typedef std::tuple<Ops...> OpTuple;
|
||||||
return PackNum<sizeof...(Ops)-1>::
|
return PackNum<sizeof...(Ops)-1>::
|
||||||
template mkVOpExpr<SIZE,V,ET,OpTuple,OpFunction>(mF, pos, mOps); // implement!!!
|
template mkVOpExpr<SIZE,V,ET,OpTuple,VFunc<OpFunction>>(mkVFuncPtr(mF), pos, mOps); // implement!!!
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, class OpFunction, class... Ops>
|
template <typename T, class OpFunction, class... Ops>
|
||||||
|
|
|
@ -204,12 +204,74 @@ namespace MultiArrayTools
|
||||||
TARGET = 1
|
TARGET = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct VType
|
||||||
|
{
|
||||||
|
typedef T type;
|
||||||
|
static constexpr size_t MULT = sizeof(type)/sizeof(T);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct VType<double>
|
||||||
|
{
|
||||||
|
typedef v256 type;
|
||||||
|
static constexpr size_t MULT = sizeof(type)/sizeof(double);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <template <typename...> class F,typename... Ts>
|
||||||
|
inline auto mkVFuncPtr(const std::shared_ptr<F<Ts...>>& f)
|
||||||
|
{
|
||||||
|
return std::shared_ptr<F<typename VType<Ts>::type...>>();
|
||||||
|
// empty, implement corresponding constructors...!!!
|
||||||
|
}
|
||||||
|
|
||||||
|
template <template <typename...> class F,typename... Ts>
|
||||||
|
inline auto mkVFunc(const F<Ts...>& f)
|
||||||
|
{
|
||||||
|
return F<typename VType<Ts>::type...>();
|
||||||
|
// empty, implement corresponding constructors...!!!
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class F>
|
||||||
|
using VFunc = decltype(mkVFunc(std::declval<F>()));
|
||||||
|
|
||||||
|
template <class F>
|
||||||
|
struct IAccess
|
||||||
|
{
|
||||||
|
template <typename T, typename Op, class ExtType>
|
||||||
|
static inline void f(T*& t, size_t pos, const Op& op, ExtType e)
|
||||||
|
{
|
||||||
|
F::selfApply(t[pos],op.get(e));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename V, class F>
|
||||||
|
struct IVAccess
|
||||||
|
{
|
||||||
|
template <typename T, typename Op, class ExtType>
|
||||||
|
static inline void f(T*& t, size_t pos, const Op& op, ExtType e)
|
||||||
|
{
|
||||||
|
VFunc<F>::selfApply(reinterpret_cast<V*>(t)[pos],op.template vget<V>(e));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using IAssign = IAccess<identity<T>>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using IPlus = IAccess<plus<T>>;
|
||||||
|
|
||||||
|
template <typename V, typename T>
|
||||||
|
using IVAssign = IVAccess<V,identity<T>>;
|
||||||
|
|
||||||
|
template <typename V, typename T>
|
||||||
|
using IVPlus = IVAccess<V,plus<T>>;
|
||||||
|
/*
|
||||||
struct IAssign
|
struct IAssign
|
||||||
{
|
{
|
||||||
template <typename T, typename Op, class ExtType>
|
template <typename T, typename Op, class ExtType>
|
||||||
static inline void f(T*& t, size_t pos, const Op& op, ExtType e)
|
static inline void f(T*& t, size_t pos, const Op& op, ExtType e)
|
||||||
{
|
{
|
||||||
//a = b;
|
|
||||||
t[pos] = op.get(e);
|
t[pos] = op.get(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -242,20 +304,8 @@ namespace MultiArrayTools
|
||||||
reinterpret_cast<V*>(t)[pos] += op.template vget<V>(e);
|
reinterpret_cast<V*>(t)[pos] += op.template vget<V>(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
template <class T>
|
|
||||||
struct VType
|
|
||||||
{
|
|
||||||
typedef T type;
|
|
||||||
static constexpr size_t MULT = sizeof(type)/sizeof(T);
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct VType<double>
|
|
||||||
{
|
|
||||||
typedef v256 type;
|
|
||||||
static constexpr size_t MULT = sizeof(type)/sizeof(double);
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, class IOp, class Target, class OpClass, OpIndexAff OIA=OpIndexAff::EXTERN>
|
template <typename T, class IOp, class Target, class OpClass, OpIndexAff OIA=OpIndexAff::EXTERN>
|
||||||
class AssignmentExpr : public ExpressionBase
|
class AssignmentExpr : public ExpressionBase
|
||||||
|
@ -295,10 +345,10 @@ namespace MultiArrayTools
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, class Target, class OpClass, OpIndexAff OIA=OpIndexAff::EXTERN>
|
template <typename T, class Target, class OpClass, OpIndexAff OIA=OpIndexAff::EXTERN>
|
||||||
using AssignmentExpr2 = AssignmentExpr<T,IAssign,Target,OpClass,OIA>;
|
using AssignmentExpr2 = AssignmentExpr<T,IAssign<T>,Target,OpClass,OIA>;
|
||||||
|
|
||||||
template <typename T, class Target, class OpClass, OpIndexAff OIA=OpIndexAff::EXTERN>
|
template <typename T, class Target, class OpClass, OpIndexAff OIA=OpIndexAff::EXTERN>
|
||||||
using AddExpr = AssignmentExpr<T,IPlus,Target,OpClass,OIA>;
|
using AddExpr = AssignmentExpr<T,IPlus<T>,Target,OpClass,OIA>;
|
||||||
|
|
||||||
template <typename T, class... Ops>
|
template <typename T, class... Ops>
|
||||||
class MOp
|
class MOp
|
||||||
|
@ -401,6 +451,7 @@ namespace MultiArrayTools
|
||||||
|
|
||||||
static constexpr size_t SIZE = 1;
|
static constexpr size_t SIZE = 1;
|
||||||
static constexpr bool CONT = true;
|
static constexpr bool CONT = true;
|
||||||
|
static constexpr bool VABLE = true;
|
||||||
|
|
||||||
ConstOperationRoot(const MultiArrayBase<T,Ranges...>& ma,
|
ConstOperationRoot(const MultiArrayBase<T,Ranges...>& ma,
|
||||||
const std::shared_ptr<typename Ranges::IndexType>&... indices);
|
const std::shared_ptr<typename Ranges::IndexType>&... indices);
|
||||||
|
@ -449,6 +500,7 @@ namespace MultiArrayTools
|
||||||
|
|
||||||
static constexpr size_t SIZE = Op::SIZE;
|
static constexpr size_t SIZE = Op::SIZE;
|
||||||
static constexpr bool CONT = false;
|
static constexpr bool CONT = false;
|
||||||
|
static constexpr bool VABLE = false;
|
||||||
|
|
||||||
StaticCast(const Op& op);
|
StaticCast(const Op& op);
|
||||||
|
|
||||||
|
@ -487,6 +539,7 @@ namespace MultiArrayTools
|
||||||
|
|
||||||
static constexpr size_t SIZE = 1;
|
static constexpr size_t SIZE = 1;
|
||||||
static constexpr bool CONT = false;
|
static constexpr bool CONT = false;
|
||||||
|
static constexpr bool VABLE = false;
|
||||||
|
|
||||||
MetaOperationRoot(const std::shared_ptr<IndexType>& ind);
|
MetaOperationRoot(const std::shared_ptr<IndexType>& ind);
|
||||||
|
|
||||||
|
@ -522,6 +575,7 @@ namespace MultiArrayTools
|
||||||
|
|
||||||
static constexpr size_t SIZE = 1;
|
static constexpr size_t SIZE = 1;
|
||||||
static constexpr bool CONT = true;
|
static constexpr bool CONT = true;
|
||||||
|
static constexpr bool VABLE = true;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -554,23 +608,23 @@ namespace MultiArrayTools
|
||||||
|
|
||||||
template <class OpClass>
|
template <class OpClass>
|
||||||
auto assign(const OpClass& in) const
|
auto assign(const OpClass& in) const
|
||||||
-> decltype(this->template asx<IAssign>(in));
|
-> decltype(this->template asx<IAssign<T>>(in));
|
||||||
|
|
||||||
template <class OpClass>
|
template <class OpClass>
|
||||||
auto assignExpr(const OpClass& in) const
|
auto assignExpr(const OpClass& in) const
|
||||||
-> decltype(this->template asxExpr<IAssign>(in));
|
-> decltype(this->template asxExpr<IAssign<T>>(in));
|
||||||
|
|
||||||
template <class OpClass, class Index>
|
template <class OpClass, class Index>
|
||||||
auto assign(const OpClass& in, const std::shared_ptr<Index>& i) const
|
auto assign(const OpClass& in, const std::shared_ptr<Index>& i) const
|
||||||
-> decltype(this->template asx<IAssign>(in,i));
|
-> decltype(this->template asx<IAssign<T>>(in,i));
|
||||||
|
|
||||||
template <class OpClass>
|
template <class OpClass>
|
||||||
auto plus(const OpClass& in) const
|
auto plus(const OpClass& in) const
|
||||||
-> decltype(this->template asx<IPlus>(in));
|
-> decltype(this->template asx<IPlus<T>>(in));
|
||||||
|
|
||||||
template <class OpClass, class Index>
|
template <class OpClass, class Index>
|
||||||
auto plus(const OpClass& in, const std::shared_ptr<Index>& i) const
|
auto plus(const OpClass& in, const std::shared_ptr<Index>& i) const
|
||||||
-> decltype(this->template asx<IPlus>(in,i));
|
-> decltype(this->template asx<IPlus<T>>(in,i));
|
||||||
|
|
||||||
template <class OpClass>
|
template <class OpClass>
|
||||||
OperationRoot& operator=(const OpClass& in);
|
OperationRoot& operator=(const OpClass& in);
|
||||||
|
@ -616,6 +670,7 @@ namespace MultiArrayTools
|
||||||
|
|
||||||
static constexpr size_t SIZE = 1;
|
static constexpr size_t SIZE = 1;
|
||||||
static constexpr bool CONT = true;
|
static constexpr bool CONT = true;
|
||||||
|
static constexpr bool VABLE = true;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -686,6 +741,7 @@ namespace MultiArrayTools
|
||||||
|
|
||||||
static constexpr size_t SIZE = 0;
|
static constexpr size_t SIZE = 0;
|
||||||
static constexpr bool CONT = true;
|
static constexpr bool CONT = true;
|
||||||
|
static constexpr bool VABLE = false;
|
||||||
|
|
||||||
OperationValue(const T& val);
|
OperationValue(const T& val);
|
||||||
|
|
||||||
|
@ -707,7 +763,17 @@ namespace MultiArrayTools
|
||||||
T mVal;
|
T mVal;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class Op>
|
||||||
|
inline constexpr bool isVAble()
|
||||||
|
{
|
||||||
|
return Op::VABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Op1, class Op2, class... Ops>
|
||||||
|
inline constexpr bool isVAble()
|
||||||
|
{
|
||||||
|
return Op1::VABLE and isVAble<Op2,Ops...>();
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T, class OpFunction, class... Ops>
|
template <typename T, class OpFunction, class... Ops>
|
||||||
class Operation : public OperationTemplate<T,Operation<T,OpFunction,Ops...> >
|
class Operation : public OperationTemplate<T,Operation<T,OpFunction,Ops...> >
|
||||||
|
@ -721,6 +787,7 @@ namespace MultiArrayTools
|
||||||
static constexpr size_t SIZE = RootSum<Ops...>::SIZE;
|
static constexpr size_t SIZE = RootSum<Ops...>::SIZE;
|
||||||
static constexpr bool FISSTATIC = OpFunction::FISSTATIC;
|
static constexpr bool FISSTATIC = OpFunction::FISSTATIC;
|
||||||
static constexpr bool CONT = false;
|
static constexpr bool CONT = false;
|
||||||
|
static constexpr bool VABLE = isVAble<Ops...>();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::tuple<Ops...> mOps;
|
std::tuple<Ops...> mOps;
|
||||||
|
@ -795,6 +862,7 @@ namespace MultiArrayTools
|
||||||
|
|
||||||
static constexpr size_t SIZE = Op::SIZE;
|
static constexpr size_t SIZE = Op::SIZE;
|
||||||
static constexpr bool CONT = Op::CONT;
|
static constexpr bool CONT = Op::CONT;
|
||||||
|
static constexpr bool VABLE = Op::VABLE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -839,6 +907,7 @@ namespace MultiArrayTools
|
||||||
|
|
||||||
static constexpr size_t SIZE = Op::SIZE;
|
static constexpr size_t SIZE = Op::SIZE;
|
||||||
static constexpr bool CONT = false;
|
static constexpr bool CONT = false;
|
||||||
|
static constexpr bool VABLE = false;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "mbase_def.h"
|
#include "mbase_def.h"
|
||||||
|
|
||||||
#include "pack_num.h"
|
#include "pack_num.h"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
namespace MultiArrayTools
|
namespace MultiArrayTools
|
||||||
{
|
{
|
||||||
|
@ -471,6 +472,34 @@ namespace MultiArrayTools
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline double xpow(const double& b, const double& e)
|
||||||
|
{
|
||||||
|
return pow(b,e);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline v256 pow(const v256& b, const v256& e)
|
||||||
|
{
|
||||||
|
v256 out;
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
out._x[i] = xpow(b._x[i],e._x[i]);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double xexp(const double& a)
|
||||||
|
{
|
||||||
|
return exp(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline v256 exp(const v256& a)
|
||||||
|
{
|
||||||
|
v256 out;
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
out._x[i] = xexp(a._x[i]);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace MultiArrayTools
|
} // namespace MultiArrayTools
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue