#ifndef GRID_MATH_TENSORS_H #define GRID_MATH_TENSORS_H namespace Grid { /////////////////////////////////////////////////// // Scalar, Vector, Matrix objects. // These can be composed to form tensor products of internal indices. /////////////////////////////////////////////////// // It is useful to NOT have any constructors // so that these classes assert "is_pod == true" // because then the standard C++ valarray container eliminates fill overhead on new allocation and // non-move copying. // // However note that doing this eliminates some syntactical sugar such as // calling the constructor explicitly or implicitly // class GridTensorBase {}; template class iScalar { public: vtype _internal; typedef typename GridTypeMapper::scalar_type scalar_type; typedef typename GridTypeMapper::vector_type vector_type; typedef typename GridTypeMapper::tensor_reduced tensor_reduced_v; typedef iScalar tensor_reduced; typedef typename GridTypeMapper::scalar_object recurse_scalar_object; typedef iScalar scalar_object; enum { TensorLevel = GridTypeMapper::TensorLevel + 1}; // Scalar no action // template using tensor_reduce_level = typename iScalar::tensor_reduce_level >; iScalar()=default; iScalar(scalar_type s) : _internal(s) {};// recurse down and hit the constructor for vector_type iScalar(const Zero &z){ *this = zero; }; iScalar & operator= (const Zero &hero){ zeroit(*this); return *this; } friend void vstream(iScalar &out,const iScalar &in){ vstream(out._internal,in._internal); } friend void zeroit(iScalar &that){ zeroit(that._internal); } friend void prefetch(iScalar &that){ prefetch(that._internal); } friend void permute(iScalar &out,const iScalar &in,int permutetype){ permute(out._internal,in._internal,permutetype); } // Unary negation friend inline iScalar operator -(const iScalar &r) { iScalar ret; ret._internal= -r._internal; return ret; } // *=,+=,-= operators inherit from corresponding "*,-,+" behaviour inline iScalar &operator *=(const iScalar &r) { *this = (*this)*r; return *this; } inline iScalar &operator -=(const iScalar &r) { *this = (*this)-r; return *this; } inline iScalar &operator +=(const iScalar &r) { *this = (*this)+r; return *this; } inline vtype & operator ()(void) { return _internal; } inline const vtype & operator ()(void) const { return _internal; } operator ComplexD () const { return(TensorRemove(_internal)); }; operator RealD () const { return(real(TensorRemove(_internal))); } // convert from a something to a scalar template::value, T>::type* = nullptr > inline auto operator = (T arg) -> iScalar { _internal = vtype(arg); return *this; } }; /////////////////////////////////////////////////////////// // Allows to turn scalar>>> back to double. /////////////////////////////////////////////////////////// template inline typename std::enable_if::value, T>::type TensorRemove(T arg) { return arg;} template inline auto TensorRemove(iScalar arg) -> decltype(TensorRemove(arg._internal)) { return TensorRemove(arg._internal); } template class iVector { public: vtype _internal[N]; typedef typename GridTypeMapper::scalar_type scalar_type; typedef typename GridTypeMapper::vector_type vector_type; typedef typename GridTypeMapper::tensor_reduced tensor_reduced_v; typedef typename GridTypeMapper::scalar_object recurse_scalar_object; typedef iScalar tensor_reduced; typedef iVector scalar_object; enum { TensorLevel = GridTypeMapper::TensorLevel + 1}; iVector(const Zero &z){ *this = zero; }; iVector() =default; iVector & operator= (const Zero &hero){ zeroit(*this); return *this; } friend void zeroit(iVector &that){ for(int i=0;i &that){ for(int i=0;i &out,const iVector &in){ for(int i=0;i &out,const iVector &in,int permutetype){ for(int i=0;i operator -(const iVector &r) { iVector ret; for(int i=0;i &operator *=(const iScalar &r) { *this = (*this)*r; return *this; } inline iVector &operator -=(const iVector &r) { *this = (*this)-r; return *this; } inline iVector &operator +=(const iVector &r) { *this = (*this)+r; return *this; } inline vtype & operator ()(int i) { return _internal[i]; } inline const vtype & operator ()(int i) const { return _internal[i]; } // inline vtype && operator ()(int i) { // return _internal[i]; // } }; template class iMatrix { public: vtype _internal[N][N]; typedef typename GridTypeMapper::scalar_type scalar_type; typedef typename GridTypeMapper::vector_type vector_type; typedef typename GridTypeMapper::tensor_reduced tensor_reduced_v; typedef typename GridTypeMapper::scalar_object recurse_scalar_object; typedef iScalar tensor_reduced; typedef iMatrix scalar_object; enum { TensorLevel = GridTypeMapper::TensorLevel + 1}; iMatrix(const Zero &z){ *this = zero; }; iMatrix() =default; iMatrix & operator= (const Zero &hero){ zeroit(*this); return *this; } template::value, T>::type* = nullptr > inline auto operator = (T arg) -> iMatrix { zeroit(*this); for(int i=0;i &that){ for(int i=0;i &that){ for(int i=0;i &out,const iMatrix &in){ for(int i=0;i &out,const iMatrix &in,int permutetype){ for(int i=0;i operator -(const iMatrix &r) { iMatrix ret; for(int i=0;i inline iMatrix &operator *=(const T &r) { *this = (*this)*r; return *this; } template inline iMatrix &operator -=(const T &r) { *this = (*this)-r; return *this; } template inline iMatrix &operator +=(const T &r) { *this = (*this)+r; return *this; } // returns an lvalue reference inline vtype & operator ()(int i,int j) { return _internal[i][j]; } inline const vtype & operator ()(int i,int j) const { return _internal[i][j]; } // inline vtype && operator ()(int i,int j) { // return _internal[i][j]; // } }; template void vprefetch(const iScalar &vv) { vprefetch(vv._internal); } template void vprefetch(const iVector &vv) { for(int i=0;i void vprefetch(const iMatrix &vv) { for(int i=0;i