From 015fbee7724637da6dbef4f8545f14ff07f471ee Mon Sep 17 00:00:00 2001 From: Peter Boyle Date: Sun, 10 May 2015 15:34:20 +0100 Subject: [PATCH] Expression template engin --- lib/lattice/Grid_lattice_ET.h | 227 ++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 lib/lattice/Grid_lattice_ET.h diff --git a/lib/lattice/Grid_lattice_ET.h b/lib/lattice/Grid_lattice_ET.h new file mode 100644 index 00000000..d4fd7d05 --- /dev/null +++ b/lib/lattice/Grid_lattice_ET.h @@ -0,0 +1,227 @@ + +#ifndef GRID_LATTICE_ET_H +#define GRID_LATTICE_ET_H + +#include +#include +#include +#include + +namespace Grid { + +//////////////////////////////////////////// +// recursive evaluation of expressions; Could +// switch to generic approach with variadics, a la +// Antonin's Lat Sim but the repack to variadic with popped +// from tuple is hideous; C++14 introduces std::make_index_sequence for this +//////////////////////////////////////////// + + +//leaf eval of lattice ; should enable if protect using traits + +template using is_lattice = std::is_base_of; + +template using is_lattice_expr = std::is_base_of; + +template +inline sobj eval(const unsigned int ss, const sobj &arg) +{ + return arg; +} +template +inline const lobj &eval(const unsigned int ss, const Lattice &arg) +{ + return arg._odata[ss]; +} + +// handle nodes in syntax tree +template +auto inline eval(const unsigned int ss, const LatticeUnaryExpression &expr) // eval one operand + -> decltype(expr.first.func(eval(ss,std::get<0>(expr.second)))) +{ + return expr.first.func(eval(ss,std::get<0>(expr.second))); +} + +template +auto inline eval(const unsigned int ss, const LatticeBinaryExpression &expr) // eval two operands + -> decltype(expr.first.func(eval(ss,std::get<0>(expr.second)),eval(ss,std::get<1>(expr.second)))) +{ + return expr.first.func(eval(ss,std::get<0>(expr.second)),eval(ss,std::get<1>(expr.second))); +} + +template +auto inline eval(const unsigned int ss, const LatticeTrinaryExpression &expr) // eval three operands + -> decltype(expr.first.func(eval(ss,std::get<0>(expr.second)),eval(ss,std::get<1>(expr.second)),eval(ss,std::get<2>(expr.second)))) +{ + return expr.first.func(eval(ss,std::get<0>(expr.second)),eval(ss,std::get<1>(expr.second)),eval(ss,std::get<2>(expr.second)) ); +} + +////////////////////////////////////////////////////////////////////////// +// Obtain the grid from an expression, ensuring conformable. This must follow a tree recursion +////////////////////////////////////////////////////////////////////////// +template::value, T1>::type * =nullptr > +inline void GridFromExpression(GridBase * &grid,const T1& lat) // Lattice leaf +{ + if ( grid ) { + conformable(grid,lat._grid); + } + grid=lat._grid; +} +template +inline void GridFromExpression(GridBase * &grid,const LatticeUnaryExpression &expr) +{ + GridFromExpression(grid,std::get<0>(expr.second));// recurse +} + +template +inline void GridFromExpression(GridBase * &grid,const LatticeBinaryExpression &expr) +{ + GridFromExpression(grid,std::get<0>(expr.second));// recurse + GridFromExpression(grid,std::get<1>(expr.second)); +} +template +inline void GridFromExpression( GridBase * &grid,const LatticeTrinaryExpression &expr) +{ + GridFromExpression(grid,std::get<0>(expr.second));// recurse + GridFromExpression(grid,std::get<1>(expr.second)); + GridFromExpression(grid,std::get<2>(expr.second)); +} +template::value, T1>::type * = nullptr > +inline void GridFromExpression(GridBase * &grid,const T1& notlat) // non-lattice leaf +{ +} + +//////////////////////////////////////////// +// Unary operators and funcs +//////////////////////////////////////////// +#define GridUnopClass(name,ret)\ +template struct name\ +{\ + static auto inline func(const arg a)-> decltype(ret) { return ret; } \ +}; + +GridUnopClass(UnarySub,-a); +GridUnopClass(UnaryAdj,adj(a)); +GridUnopClass(UnaryConj,conj(a)); +GridUnopClass(UnaryTrace,trace(a)); +GridUnopClass(UnaryTranspose,transpose(a)); + +//////////////////////////////////////////// +// Binary operators +//////////////////////////////////////////// +#define GridBinOpClass(name,combination)\ +template \ +struct name\ +{\ + static auto inline func(const left &lhs,const right &rhs)-> decltype(combination) const \ + {\ + return combination;\ + }\ +} +GridBinOpClass(BinaryAdd,lhs+rhs); +GridBinOpClass(BinarySub,lhs-rhs); +GridBinOpClass(BinaryMul,lhs*rhs); + +//////////////////////////////////////////// +// Operator syntactical glue +//////////////////////////////////////////// + +#define GRID_UNOP(name) name +#define GRID_BINOP(name) name +#define GRID_TRINOP(name) name + +#define GRID_DEF_UNOP(op, name)\ +template ::value||is_lattice_expr::value, T1>::type* = nullptr> inline auto op(const T1 &arg) \ + -> decltype(LatticeUnaryExpression(std::make_pair(GRID_UNOP(name)(),std::forward_as_tuple(arg)))) \ +{ return LatticeUnaryExpression(std::make_pair(GRID_UNOP(name)(),std::forward_as_tuple(arg))); } + +#define GRID_BINOP_LEFT(op, name)\ +template ::value||is_lattice_expr::value, T1>::type* = nullptr>\ +inline auto op(const T1 &lhs,const T2&rhs) \ + -> decltype(LatticeBinaryExpression(std::make_pair(GRID_BINOP(name)(),\ + std::forward_as_tuple(lhs, rhs)))) \ +{\ + return LatticeBinaryExpression(std::make_pair(GRID_BINOP(name)(),\ + std::forward_as_tuple(lhs, rhs))); \ +} + +#define GRID_BINOP_RIGHT(op, name)\ + template ::value && !is_lattice_expr::value, T1>::type* = nullptr,\ + typename std::enable_if< is_lattice::value || is_lattice_expr::value, T2>::type* = nullptr> \ +inline auto op(const T1 &lhs,const T2&rhs) \ + -> decltype(LatticeBinaryExpression(std::make_pair(GRID_BINOP(name)(),\ + std::forward_as_tuple(lhs, rhs)))) \ +{\ + return LatticeBinaryExpression(std::make_pair(GRID_BINOP(name)(),\ + std::forward_as_tuple(lhs, rhs))); \ +} + +#define GRID_DEF_BINOP(op, name)\ + GRID_BINOP_LEFT(op,name);\ + GRID_BINOP_RIGHT(op,name); + + +#define GRID_DEF_TRINOP(op, name)\ +template inline auto op(const T1 &pred,const T2&lhs,const T3 &rhs) \ + -> decltype(LatticeTrinaryExpression(std::make_pair(GRID_TRINOP(name)(),\ + std::forward_as_tuple(pred,lhs,rhs)))) \ +{\ + return LatticeTrinaryExpression(std::make_pair(GRID_TRINOP(name)(), \ + std::forward_as_tuple(pred,lhs, rhs))); \ +} +//////////////////////// +//Operator definitions +//////////////////////// + +GRID_DEF_UNOP(operator -,UnarySub); +GRID_DEF_UNOP(adj,UnaryAdj); +GRID_DEF_UNOP(conj,UnaryConj); +GRID_DEF_UNOP(trace,UnaryTrace); +GRID_DEF_UNOP(transpose,UnaryTranspose); + +GRID_DEF_BINOP(operator+,BinaryAdd); +GRID_DEF_BINOP(operator-,BinarySub); +GRID_DEF_BINOP(operator*,BinaryMul); + +#undef GRID_UNOP +#undef GRID_BINOP +#undef GRID_TRINOP + +#undef GRID_DEF_UNOP +#undef GRID_DEF_BINOP +#undef GRID_DEF_TRINOP + +} + +#if 0 +using namespace Grid; + + int main(int argc,char **argv){ + + Lattice v1(16); + Lattice v2(16); + Lattice v3(16); + + BinaryAdd tmp; + LatticeBinaryExpression,Lattice &,Lattice &> + expr(std::make_pair(tmp, + std::forward_as_tuple(v1,v2))); + tmp.func(eval(0,v1),eval(0,v2)); + + auto var = v1+v2; + std::cout< &v1,Lattice &v2,Lattice &v3) +{ + v3=v1+v2+v1*v2; +} +#endif + +#endif