#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; } //////////////////////////////////////////////////////////////////////////////////////////////////////// // Trace Specific indices. //////////////////////////////////////////////////////////////////////////////////////////////////////// template::TensorLevel != Level >::type * =nullptr> inline auto traceIndex (const iScalar &arg) -> iScalar(arg._internal))> { iScalar(arg._internal))> ret; ret._internal=traceIndex(arg._internal); return ret; } template::TensorLevel == Level >::type * =nullptr> inline auto traceIndex (const iScalar &arg) -> iScalar { return arg; } // If we hit the right index, return scalar and trace it with no further recursion template::TensorLevel == Level >::type * =nullptr> inline auto traceIndex(const iMatrix &arg) -> iScalar { iScalar ret; zeroit(ret._internal); for(int i=0;i::TensorLevel != Level >::type * =nullptr> inline auto traceIndex(const iMatrix &arg) -> iMatrix(arg._internal[0][0])),N> { iMatrix(arg._internal[0][0])),N> ret; for(int i=0;i(arg._internal[i][j]); }} return ret; } } #endif