#ifndef GRID_MATH_TRACE_H #define GRID_MATH_TRACE_H namespace Grid { ////////////////////////////////////////////////////////////////// // Traces: both all indices and a specific index ///////////////////////////////////////////////////////////////// inline ComplexF trace( const ComplexF &arg){ return arg;} inline ComplexD trace( const ComplexD &arg){ return arg;} inline RealF trace( const RealF &arg){ return arg;} inline RealD trace( const RealD &arg){ return arg;} template inline ComplexF traceIndex(const ComplexF arg) { return arg;} template inline ComplexD traceIndex(const ComplexD arg) { return arg;} template inline RealF traceIndex(const RealF arg) { return arg;} template inline RealD traceIndex(const RealD arg) { return arg;} template inline auto trace(const iMatrix &arg) -> iScalar { iScalar ret; zeroit(ret._internal); for(int i=0;i inline auto trace(const iScalar &arg) -> iScalar { iScalar ret; ret._internal=trace(arg._internal); return ret; } ///////////////////////////////////// // Alternate implementation .. count // indices from left. Annoying but // I'm working around compiler bugs in gcc and earlier icpc ///////////////////////////////////// // Allow to recurse if vector, but never terminate on a vector // ltrace of a different index can distribute across the vector index in a replicated way // but we do not ltrace a vector index. template class TensorIndexRecursion { public: //////////////////////////////////////////// // Recursion for tracing a specific index //////////////////////////////////////////// template static auto traceIndex(const iScalar arg) -> iScalar::traceIndex(arg._internal))> { iScalar::traceIndex(arg._internal))> ret; ret._internal = TensorIndexRecursion::traceIndex(arg._internal); return ret; } template static auto traceIndex(const iVector arg) -> iVector::traceIndex(arg._internal[0])),N> { iVector::traceIndex(arg._internal[0])),N> ret; for(int i=0;i::traceIndex(arg._internal[i]); } return ret; } template static auto traceIndex(const iMatrix arg) -> iMatrix::traceIndex(arg._internal[0][0])),N> { iMatrix::traceIndex(arg._internal[0][0])),N> ret; for(int i=0;i::traceIndex(arg._internal[i][j]); }} return ret; } //////////////////////////////////////////// // Recursion for peeking a specific index //////////////////////////////////////////// template static auto peekIndex(const iScalar arg,int i) -> iScalar::peekIndex(arg._internal,0))> { iScalar::peekIndex(arg._internal,0))> ret; ret._internal = TensorIndexRecursion::peekIndex(arg._internal,i); return ret; } template static auto peekIndex(const iScalar arg,int i,int j) -> iScalar::peekIndex(arg._internal,0,0))> { iScalar::peekIndex(arg._internal,0,0))> ret; ret._internal = TensorIndexRecursion::peekIndex(arg._internal,i,j); return ret; } template static auto peekIndex(const iVector arg,int ii) -> iVector::peekIndex(arg._internal[0],0)),N> { iVector::peekIndex(arg._internal[0],0)),N> ret; for(int i=0;i::peekIndex(arg._internal[i],ii); } return ret; } template static auto peekIndex(const iVector arg,int ii,int jj) -> iVector::peekIndex(arg._internal[0],0,0)),N> { iVector::peekIndex(arg._internal[0],0,0)),N> ret; for(int i=0;i::peekIndex(arg._internal[i],ii,jj); } return ret; } template static auto peekIndex(const iMatrix arg,int ii) -> iMatrix::peekIndex(arg._internal[0][0],0)),N> { iMatrix::peekIndex(arg._internal[0][0],0)),N> ret; for(int i=0;i::peekIndex(arg._internal[i][j],ii); }} return ret; } template static auto peekIndex(const iMatrix arg,int ii,int jj) -> iMatrix::peekIndex(arg._internal[0][0],0,0)),N> { iMatrix::peekIndex(arg._internal[0][0],0,0)),N> ret; for(int i=0;i::peekIndex(arg._internal[i][j],ii,jj); }} return ret; } //////////////////////////////////////////// // Recursion for poking a specific index //////////////////////////////////////////// template inline static void pokeIndex(iScalar &ret, const iScalar::peekIndex(ret._internal,0))> &arg, int i) { TensorIndexRecursion::pokeIndex(ret._internal,arg._internal,i); } template inline static void pokeIndex(iScalar &ret, const iScalar::peekIndex(ret._internal,0,0))> &arg, int i,int j) { TensorIndexRecursion::pokeIndex(ret._internal,arg._internal,i,j); } template inline static void pokeIndex(iVector &ret, const iVector::peekIndex(ret._internal,0)),N> &arg, int i) { for(int ii=0;ii::pokeIndex(ret._internal[ii],arg._internal[ii],i); } } template inline static void pokeIndex(iVector &ret, const iVector::peekIndex(ret._internal,0)),N> &arg, int i,int j) { for(int ii=0;ii::pokeIndex(ret._internal[ii],arg._internal[ii],i,j); } } template inline static void pokeIndex(iMatrix &ret, const iMatrix::peekIndex(ret._internal,0)),N> &arg, int i) { for(int ii=0;ii::pokeIndex(ret._internal[ii][jj],arg._internal[ii][jj],i); }} } template inline static void pokeIndex(iMatrix &ret, const iMatrix::peekIndex(ret._internal,0)),N> &arg, int i,int j) { for(int ii=0;ii::pokeIndex(ret._internal[ii][jj],arg._internal[ii][jj],i,j); }} } //////////////////////////////////////////// // Recursion for transposing a specific index //////////////////////////////////////////// template static auto transposeIndex(const iScalar arg) -> iScalar { iScalar ret; ret._internal = TensorIndexRecursion::transposeIndex(arg._internal); return ret; } template static auto transposeIndex(const iVector arg) -> iVector { iVector ret; for(int i=0;i::transposeIndex(arg._internal[i]); } return ret; } template static auto transposeIndex(const iMatrix arg) -> iMatrix { iMatrix ret; for(int i=0;i::transposeIndex(arg._internal[i][j]); }} return ret; } }; //////////////////////////// // strip const & ref quali's //////////////////////////// #define RemoveCRV(a) typename std::remove_const::type>::type template<> class TensorIndexRecursion<0> { public: ///////////////////////////////////////// // Ends recursion for trace (scalar/vector/matrix) ///////////////////////////////////////// template static auto traceIndex(const iScalar arg) -> iScalar { iScalar ret; ret._internal = arg._internal; return ret; } template static auto traceIndex(const iVector arg) -> iScalar { iScalar ret; ret._internal=zero; for(int i=0;i static auto traceIndex(const iMatrix arg) -> iScalar { iScalar ret; ret=zero; for(int i=0;i static auto transposeIndex(const iScalar arg) -> iScalar { iScalar ret; ret._internal = arg._internal; return ret; } template static auto transposeIndex(const iVector arg) -> iVector { iScalar ret; ret._internal=zero; for(int i=0;i static auto transposeIndex(const iMatrix arg) -> iMatrix { iScalar ret; ret=zero; for(int i=0;i static auto peekIndex(const iVector arg,int ii) -> iScalar { iScalar ret; ret._internal = arg._internal[ii]; return ret; } template static auto peekIndex(const iMatrix arg,int ii,int jj) -> iScalar { iScalar ret; ret._internal = arg._internal[ii][jj]; return ret; } // Vector poke, one index template inline static void pokeIndex(iVector &ret, const iScalar &arg,int i) { ret._internal[i] = arg._internal; } // Matrix poke two indices template inline static void pokeIndex(iMatrix &ret, const iScalar &arg,int i,int j) { ret._internal[i][j] = arg._internal; } }; //////////////////////////////////////////////////////////////////////////////////////////////////////// // External wrappers //////////////////////////////////////////////////////////////////////////////////////////////////////// template inline auto traceIndex (const vtype &arg) -> RemoveCRV(TensorIndexRecursion::traceIndex(arg)) { RemoveCRV(TensorIndexRecursion::traceIndex(arg)) ret; ret=TensorIndexRecursion::traceIndex(arg); return ret; } template inline auto transposeIndex (const vtype &arg) -> RemoveCRV(TensorIndexRecursion::transposeIndex(arg)) { RemoveCRV(TensorIndexRecursion::transposeIndex(arg)) ret; ret=TensorIndexRecursion::transposeIndex(arg); return ret; } template inline auto peekIndex (const vtype &arg,int i) -> RemoveCRV(TensorIndexRecursion::peekIndex(arg,0)) { RemoveCRV(TensorIndexRecursion::peekIndex(arg,0)) ret; ret=TensorIndexRecursion::peekIndex(arg,i); return ret; } template inline auto peekIndex (const vtype &arg,int i,int j) -> RemoveCRV(TensorIndexRecursion::peekIndex(arg,0,0)) { RemoveCRV(TensorIndexRecursion::peekIndex(arg,0,0)) ret; ret=TensorIndexRecursion::peekIndex(arg,i,j); return ret; } template inline void pokeIndex (vtype &ret,const decltype(TensorIndexRecursion::peekIndex(ret,0)) &arg,int i) { TensorIndexRecursion::pokeIndex(ret,arg,i); } template inline void pokeIndex (vtype &ret,const decltype(TensorIndexRecursion::peekIndex(ret,0,0)) &arg,int i,int j) { TensorIndexRecursion::pokeIndex(ret,arg,i,j); } #undef RemoveCRV } #endif