#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