/************************************************************************************* 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_BEGIN(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; // get double precision version typedef iScalar::DoublePrecision> DoublePrecision; enum { TensorLevel = GridTypeMapper::TensorLevel + 1 }; // Scalar no action accelerator iScalar() = default; friend accelerator_inline void zeroit(iScalar &that){ zeroit(that._internal); } accelerator_inline iScalar(scalar_type s) : _internal(s){}; // recurse down and hit the constructor for vector_type accelerator_inline iScalar(const Zero &z) { zeroit(*this); }; accelerator_inline iScalar &operator=(const Zero &hero) { zeroit(*this); return *this; } friend accelerator_inline void vstream(iScalar &out, const iScalar &in) { vstream(out._internal, in._internal); } friend accelerator_inline void vbroadcast(iScalar &out,const iScalar &in,int lane){ vbroadcast(out._internal,in._internal,lane); } friend accelerator_inline void prefetch(iScalar &that) { prefetch(that._internal); } friend accelerator_inline void permute(iScalar &out, const iScalar &in, int permutetype) { permute(out._internal, in._internal, permutetype); } friend accelerator_inline void rotate(iScalar &out,const iScalar &in,int rot){ rotate(out._internal,in._internal,rot); } friend accelerator_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 accelerator_inline iScalar operator-(const iScalar &r) { iScalar ret; ret._internal = -r._internal; return ret; } // *=,+=,-= operators inherit from corresponding "*,-,+" behaviour accelerator_inline iScalar &operator*=(const iScalar &r) { *this = (*this) * r; return *this; } accelerator_inline iScalar &operator-=(const iScalar &r) { *this = (*this) - r; return *this; } accelerator_inline iScalar &operator+=(const iScalar &r) { *this = (*this) + r; return *this; } accelerator_inline vtype &operator()(void) { return _internal; } accelerator_inline const vtype &operator()(void) const { return _internal; } // Type casts meta programmed, must be pure scalar to match TensorRemove template = 0, IfNotSimd = 0> accelerator_inline operator ComplexF() const { return (TensorRemove(_internal)); } template = 0, IfNotSimd = 0> accelerator_inline operator ComplexD() const { return (TensorRemove(_internal)); } template = 0,IfNotSimd = 0> accelerator_inline operator RealD() const { return TensorRemove(_internal); } template = 0, IfNotSimd = 0> accelerator_inline operator Integer() const { return Integer(TensorRemove(_internal)); } // convert from a something to a scalar via constructor of something arg template ::value, T>::type * = nullptr> accelerator_inline iScalar operator=(T arg) { _internal = arg; return *this; } // Convert elements template accelerator_inline iScalar operator=(iScalar &&arg) { _internal = arg._internal; return *this; } // Host only friend std::ostream &operator<<(std::ostream &stream,const iScalar &o) { stream << "S {" << o._internal << "}"; return stream; }; }; /////////////////////////////////////////////////////////// // Allows to turn scalar>>> back to double. /////////////////////////////////////////////////////////// template accelerator_inline typename std::enable_if::value, T>::type TensorRemove(T arg) { return arg; } template accelerator_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; // get double precision version typedef iVector::DoublePrecision, N> DoublePrecision; template ::value, T>::type * = nullptr> accelerator_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 }; accelerator_inline iVector(const Zero &z) { zeroit(*this); }; accelerator iVector() = default; accelerator_inline iVector &operator=(const Zero &hero) { zeroit(*this); return *this; } friend accelerator_inline void zeroit(iVector &that) { for (int i = 0; i < N; i++) { zeroit(that._internal[i]); } } friend accelerator_inline void prefetch(iVector &that) { for (int i = 0; i < N; i++) prefetch(that._internal[i]); } friend accelerator_inline void vstream(iVector &out, const iVector &in) { for (int i = 0; i < N; i++) { vstream(out._internal[i], in._internal[i]); } } friend accelerator_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 accelerator_inline iVector &operator*=(const iScalar &r) { *this = (*this) * r; return *this; } accelerator_inline iVector &operator-=(const iVector &r) { *this = (*this) - r; return *this; } accelerator_inline iVector &operator+=(const iVector &r) { *this = (*this) + r; return *this; } accelerator_inline vtype &operator()(int i) { return _internal[i]; } accelerator_inline const vtype &operator()(int i) const { return _internal[i]; } // Host 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; }; }; 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; // get double precision version typedef iMatrix::DoublePrecision, N> DoublePrecision; // Tensor removal typedef iScalar tensor_reduced; typedef iMatrix scalar_object; enum { TensorLevel = GridTypeMapper::TensorLevel + 1 }; accelerator_inline iMatrix(const Zero &z) { zeroit(*this); }; accelerator iMatrix() = default; accelerator_inline 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; }; accelerator_inline iMatrix(scalar_type s) { (*this) = s; }; // recurse down and hit the constructor for vector_type accelerator_inline iMatrix &operator=(const Zero &hero) { zeroit(*this); return *this; } template ::value, T>::type * = nullptr> accelerator_inline auto operator=(T arg) -> iMatrix { zeroit(*this); for (int i = 0; i < N; i++) _internal[i][i] = arg; return *this; } friend accelerator_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 accelerator_inline iMatrix &operator*=(const T &r) { *this = (*this) * r; return *this; } template accelerator_inline iMatrix &operator-=(const T &r) { *this = (*this) - r; return *this; } template accelerator_inline iMatrix &operator+=(const T &r) { *this = (*this) + r; return *this; } // returns an lvalue reference accelerator_inline vtype &operator()(int i, int j) { return _internal[i][j]; } accelerator_inline const vtype &operator()(int i, int j) const { return _internal[i][j]; } // Host function only 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; }; }; template accelerator_inline void vprefetch(const iScalar &vv) { vprefetch(vv._internal); } template accelerator_inline void vprefetch(const iVector &vv) { for (int i = 0; i < N; i++) { vprefetch(vv._internal[i]); } } template accelerator_inline void vprefetch(const iMatrix &vv) { for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { vprefetch(vv._internal[i][j]); } } } NAMESPACE_END(Grid); #endif