/************************************************************************************* Grid physics library, www.github.com/paboyle/Grid Source file: ./lib/tensors/Tensor_class.h Copyright (C) 2015 Author: Azusa Yamaguchi Author: Peter Boyle This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. See the full license in the file "LICENSE" in the top level distribution directory *************************************************************************************/ /* END LEGAL */ #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 vtype element; typedef typename GridTypeMapper::scalar_type scalar_type; typedef typename GridTypeMapper::vector_type vector_type; typedef typename GridTypeMapper::vector_typeD vector_typeD; typedef typename GridTypeMapper::tensor_reduced tensor_reduced_v; typedef typename GridTypeMapper::scalar_object recurse_scalar_object; typedef iScalar tensor_reduced; typedef iScalar scalar_object; // substitutes a real or complex version with same tensor structure typedef iScalar::Complexified> Complexified; typedef iScalar::Realified> Realified; enum { TensorLevel = GridTypeMapper::TensorLevel + 1 }; // Scalar no action // template using tensor_reduce_level = typename // iScalar::tensor_reduce_level >; iScalar() = default; /* iScalar(const iScalar ©me)=default; iScalar(iScalar &©me)=default; iScalar & operator= (const iScalar ©me) = default; iScalar & operator= (iScalar &©me) = default; */ // template // iScalar(EnableIf, vector_type> s) : _internal(s){}; // recurse down and hit the constructor for vector_type 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 strong_inline void vstream(iScalar &out, const iScalar &in) { vstream(out._internal, in._internal); } friend strong_inline void vbroadcast(iScalar &out,const iScalar &in,int lane){ vbroadcast(out._internal,in._internal,lane); } friend strong_inline void zeroit(iScalar &that){ zeroit(that._internal); } friend strong_inline void prefetch(iScalar &that) { prefetch(that._internal); } friend strong_inline void permute(iScalar &out, const iScalar &in, int permutetype) { permute(out._internal, in._internal, permutetype); } friend strong_inline void rotate(iScalar &out,const iScalar &in,int rot){ rotate(out._internal,in._internal,rot); } friend strong_inline void exchange(iScalar &out1,iScalar &out2, const iScalar &in1,const iScalar &in2,int type){ exchange(out1._internal,out2._internal, in1._internal, in2._internal,type); } // Unary negation friend strong_inline iScalar operator-(const iScalar &r) { iScalar ret; ret._internal = -r._internal; return ret; } // *=,+=,-= operators inherit from corresponding "*,-,+" behaviour strong_inline iScalar &operator*=(const iScalar &r) { *this = (*this) * r; return *this; } strong_inline iScalar &operator-=(const iScalar &r) { *this = (*this) - r; return *this; } strong_inline iScalar &operator+=(const iScalar &r) { *this = (*this) + r; return *this; } strong_inline vtype &operator()(void) { return _internal; } strong_inline const vtype &operator()(void) const { return _internal; } // Type casts meta programmed, must be pure scalar to match TensorRemove template = 0, IfNotSimd = 0> operator ComplexF() const { return (TensorRemove(_internal)); }; template = 0, IfNotSimd = 0> operator ComplexD() const { return (TensorRemove(_internal)); }; // template = 0,IfNotSimd = // 0> operator RealD () const { return(real(TensorRemove(_internal))); } template = 0,IfNotSimd = 0> operator RealD() const { return TensorRemove(_internal); } template = 0, IfNotSimd = 0> operator Integer() const { return Integer(TensorRemove(_internal)); } // convert from a something to a scalar via constructor of something arg template ::value, T>::type * = nullptr> strong_inline iScalar operator=(T arg) { _internal = arg; return *this; } friend std::ostream &operator<<(std::ostream &stream,const iScalar &o) { stream << "S {" << o._internal << "}"; return stream; }; }; /////////////////////////////////////////////////////////// // Allows to turn scalar>>> back to double. /////////////////////////////////////////////////////////// template strong_inline typename std::enable_if::value, T>::type TensorRemove(T arg) { return arg; } template strong_inline auto TensorRemove(iScalar arg) -> decltype(TensorRemove(arg._internal)) { return TensorRemove(arg._internal); } template class iVector { public: vtype _internal[N]; typedef vtype element; typedef typename GridTypeMapper::scalar_type scalar_type; typedef typename GridTypeMapper::vector_type vector_type; typedef typename GridTypeMapper::vector_typeD vector_typeD; typedef typename GridTypeMapper::tensor_reduced tensor_reduced_v; typedef typename GridTypeMapper::scalar_object recurse_scalar_object; typedef iScalar tensor_reduced; typedef iVector scalar_object; // substitutes a real or complex version with same tensor structure typedef iVector::Complexified, N> Complexified; typedef iVector::Realified, N> Realified; template ::value, T>::type * = nullptr> strong_inline auto operator=(T arg) -> iVector { zeroit(*this); for (int i = 0; i < N; i++) _internal[i] = arg; return *this; } enum { TensorLevel = GridTypeMapper::TensorLevel + 1 }; iVector(const Zero &z) { *this = zero; }; iVector() = default; /* iVector(const iVector ©me)=default; iVector(iVector &©me)=default; iVector & operator= (const iVector ©me) = default; iVector & operator= (iVector &©me) = default; */ iVector &operator=(const Zero &hero) { zeroit(*this); return *this; } friend strong_inline void zeroit(iVector &that) { for (int i = 0; i < N; i++) { zeroit(that._internal[i]); } } friend strong_inline void prefetch(iVector &that) { for (int i = 0; i < N; i++) prefetch(that._internal[i]); } friend strong_inline void vstream(iVector &out, const iVector &in) { for (int i = 0; i < N; i++) { vstream(out._internal[i], in._internal[i]); } } friend strong_inline void vbroadcast(iVector &out,const iVector &in,int lane){ for(int i=0;i &out,const iVector &in,int permutetype){ for(int i=0;i &out,const iVector &in,int rot){ for(int i=0;i &out1,iVector &out2, const iVector &in1,const iVector &in2,int type){ for(int i=0;i operator-(const iVector &r) { iVector ret; for (int i = 0; i < N; i++) ret._internal[i] = -r._internal[i]; return ret; } // *=,+=,-= operators inherit from corresponding "*,-,+" behaviour strong_inline iVector &operator*=(const iScalar &r) { *this = (*this) * r; return *this; } strong_inline iVector &operator-=(const iVector &r) { *this = (*this) - r; return *this; } strong_inline iVector &operator+=(const iVector &r) { *this = (*this) + r; return *this; } strong_inline vtype &operator()(int i) { return _internal[i]; } strong_inline const vtype &operator()(int i) const { return _internal[i]; } friend std::ostream &operator<<(std::ostream &stream, const iVector &o) { stream << "V<" << N << ">{"; for (int i = 0; i < N; i++) { stream << o._internal[i]; if (i < N - 1) stream << ","; } stream << "}"; return stream; }; // strong_inline vtype && operator ()(int i) { // return _internal[i]; // } }; template class iMatrix { public: vtype _internal[N][N]; typedef vtype element; typedef typename GridTypeMapper::scalar_type scalar_type; typedef typename GridTypeMapper::vector_type vector_type; typedef typename GridTypeMapper::vector_typeD vector_typeD; typedef typename GridTypeMapper::tensor_reduced tensor_reduced_v; typedef typename GridTypeMapper::scalar_object recurse_scalar_object; // substitutes a real or complex version with same tensor structure typedef iMatrix::Complexified, N> Complexified; typedef iMatrix::Realified, N> Realified; // Tensure removal typedef iScalar tensor_reduced; typedef iMatrix scalar_object; enum { TensorLevel = GridTypeMapper::TensorLevel + 1 }; iMatrix(const Zero &z) { *this = zero; }; iMatrix() = default; iMatrix &operator=(const iMatrix &rhs) { for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) vstream(_internal[i][j], rhs._internal[i][j]); return *this; }; iMatrix(scalar_type s) { (*this) = s; }; // recurse down and hit the constructor for vector_type /* iMatrix(const iMatrix ©me)=default; iMatrix(iMatrix &©me)=default; iMatrix & operator= (const iMatrix ©me) = default; iMatrix & operator= (iMatrix &©me) = default; */ iMatrix &operator=(const Zero &hero) { zeroit(*this); return *this; } template ::value, T>::type * = nullptr> strong_inline auto operator=(T arg) -> iMatrix { zeroit(*this); for (int i = 0; i < N; i++) _internal[i][i] = arg; return *this; } friend strong_inline void zeroit(iMatrix &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 lane){ for(int i=0;i &out,const iMatrix &in,int permutetype){ for(int i=0;i &out,const iMatrix &in,int rot){ for(int i=0;i &out1,iMatrix &out2, const iMatrix &in1,const iMatrix &in2,int type){ for(int i=0;i operator-(const iMatrix &r) { iMatrix ret; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { ret._internal[i][j] = -r._internal[i][j]; } } return ret; } // *=,+=,-= operators inherit from corresponding "*,-,+" behaviour template strong_inline iMatrix &operator*=(const T &r) { *this = (*this) * r; return *this; } template strong_inline iMatrix &operator-=(const T &r) { *this = (*this) - r; return *this; } template strong_inline iMatrix &operator+=(const T &r) { *this = (*this) + r; return *this; } // returns an lvalue reference strong_inline vtype &operator()(int i, int j) { return _internal[i][j]; } strong_inline const vtype &operator()(int i, int j) const { return _internal[i][j]; } friend std::ostream &operator<<(std::ostream &stream, const iMatrix &o) { stream << "M<" << N << ">{"; for (int i = 0; i < N; i++) { stream << "{"; for (int j = 0; j < N; j++) { stream << o._internal[i][j]; if (i < N - 1) stream << ","; } stream << "}"; if (i != N - 1) stream << "\n\t\t"; } stream << "}"; return stream; }; // strong_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 < N; i++) { vprefetch(vv._internal[i]); } } template void vprefetch(const iMatrix &vv) { for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { vprefetch(vv._internal[i][j]); } } } } #endif