#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 // #define TENSOR_IS_POD 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 >; #ifndef TENSOR_IS_POD iScalar(){;}; iScalar(scalar_type s) : _internal(s) {};// recurse down and hit the constructor for vector_type iScalar(const Zero &z){ *this = zero; }; #endif iScalar & operator= (const Zero &hero){ zeroit(*this); return *this; } iScalar & operator= (const scalar_type s){ _internal=s; return *this; } friend void zeroit(iScalar &that){ zeroit(that._internal); } friend void permute(iScalar &out,const iScalar &in,int permutetype){ permute(out._internal,in._internal,permutetype); } friend void extract(const iScalar &in,std::vector &out){ extract(in._internal,out); // extract advances the pointers in out } friend void merge(iScalar &in,std::vector &out){ merge(in._internal,out); // extract advances the pointers in out } // 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; } // inline vtype && operator ()(void) { // return _internal; // } operator ComplexD () const { return(TensorRemove(_internal)); }; operator RealD () const { return(real(TensorRemove(_internal))); } template::notvalue, T>::type* = nullptr > inline auto operator = (T arg) -> iScalar { _internal = arg; return *this; } }; /////////////////////////////////////////////////////////// // Allows to turn scalar>>> back to double. /////////////////////////////////////////////////////////// template inline typename std::enable_if::notvalue, 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}; #ifndef TENSOR_IS_POD iVector(const Zero &z){ *this = zero; }; iVector() {};// Empty constructure #endif iVector & operator= (const Zero &hero){ zeroit(*this); return *this; } friend void zeroit(iVector &that){ for(int i=0;i &out,const iVector &in,int permutetype){ for(int i=0;i &in,std::vector &out){ for(int i=0;i &in,std::vector &out){ 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}; #ifndef TENSOR_IS_POD iMatrix(const Zero &z){ *this = zero; }; iMatrix() {}; #endif iMatrix & operator= (const Zero &hero){ zeroit(*this); return *this; } template::notvalue, T>::type* = nullptr > inline auto operator = (T arg) -> iMatrix { zeroit(*this); for(int i=0;i &that){ for(int i=0;i &out,const iMatrix &in,int permutetype){ for(int i=0;i &in,std::vector &out){ for(int i=0;i &in,std::vector &out){ 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 inline void extract(const vobj &vec,std::vector &extracted) { typedef typename vobj::scalar_type scalar_type ; typedef typename vobj::vector_type vector_type ; int Nsimd=vobj::vector_type::Nsimd(); extracted.resize(Nsimd); std::vector pointers(Nsimd); for(int i=0;i inline void merge(vobj &vec,std::vector &extracted) { typedef typename vobj::scalar_type scalar_type ; typedef typename vobj::vector_type vector_type ; int Nsimd=vobj::vector_type::Nsimd(); assert(extracted.size()==Nsimd); std::vector pointers(Nsimd); for(int i=0;i