mirror of
https://github.com/paboyle/Grid.git
synced 2024-11-13 01:05:36 +00:00
splitting into smaller, multiple files for readability and easy find.
This commit is contained in:
parent
af72ade26a
commit
2eb5ab26bf
647
lib/Grid_math.h
647
lib/Grid_math.h
@ -4,646 +4,13 @@
|
|||||||
#include <Grid_math_traits.h>
|
#include <Grid_math_traits.h>
|
||||||
#include <Grid_math_tensors.h>
|
#include <Grid_math_tensors.h>
|
||||||
#include <Grid_math_arith.h>
|
#include <Grid_math_arith.h>
|
||||||
|
#include <Grid_math_inner.h>
|
||||||
|
#include <Grid_math_outer.h>
|
||||||
|
#include <Grid_math_transpose.h>
|
||||||
|
#include <Grid_math_trace.h>
|
||||||
|
#include <Grid_math_peek.h>
|
||||||
|
#include <Grid_math_poke.h>
|
||||||
|
#include <Grid_math_reality.h>
|
||||||
|
|
||||||
//
|
|
||||||
// Indexing; want to be able to dereference and
|
|
||||||
// obtain either an lvalue or an rvalue.
|
|
||||||
//
|
|
||||||
namespace Grid {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// innerProduct Scalar x Scalar -> Scalar
|
|
||||||
// innerProduct Vector x Vector -> Scalar
|
|
||||||
// innerProduct Matrix x Matrix -> Scalar
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
template<class l,class r,int N> inline
|
|
||||||
auto innerProduct (const iVector<l,N>& lhs,const iVector<r,N>& rhs) -> iScalar<decltype(innerProduct(lhs._internal[0],rhs._internal[0]))>
|
|
||||||
{
|
|
||||||
typedef decltype(innerProduct(lhs._internal[0],rhs._internal[0])) ret_t;
|
|
||||||
iScalar<ret_t> ret=zero;
|
|
||||||
for(int c1=0;c1<N;c1++){
|
|
||||||
ret._internal += innerProduct(lhs._internal[c1],rhs._internal[c1]);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
template<class l,class r,int N> inline
|
|
||||||
auto innerProduct (const iMatrix<l,N>& lhs,const iMatrix<r,N>& rhs) -> iScalar<decltype(innerProduct(lhs._internal[0][0],rhs._internal[0][0]))>
|
|
||||||
{
|
|
||||||
typedef decltype(innerProduct(lhs._internal[0][0],rhs._internal[0][0])) ret_t;
|
|
||||||
iScalar<ret_t> ret=zero;
|
|
||||||
iScalar<ret_t> tmp;
|
|
||||||
for(int c1=0;c1<N;c1++){
|
|
||||||
for(int c2=0;c2<N;c2++){
|
|
||||||
ret._internal+=innerProduct(lhs._internal[c1][c2],rhs._internal[c1][c2]);
|
|
||||||
}}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
template<class l,class r> inline
|
|
||||||
auto innerProduct (const iScalar<l>& lhs,const iScalar<r>& rhs) -> iScalar<decltype(innerProduct(lhs._internal,rhs._internal))>
|
|
||||||
{
|
|
||||||
typedef decltype(innerProduct(lhs._internal,rhs._internal)) ret_t;
|
|
||||||
iScalar<ret_t> ret;
|
|
||||||
ret._internal = innerProduct(lhs._internal,rhs._internal);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// outerProduct Scalar x Scalar -> Scalar
|
|
||||||
// Vector x Vector -> Matrix
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
template<class l,class r,int N> inline
|
|
||||||
auto outerProduct (const iVector<l,N>& lhs,const iVector<r,N>& rhs) -> iMatrix<decltype(outerProduct(lhs._internal[0],rhs._internal[0])),N>
|
|
||||||
{
|
|
||||||
typedef decltype(outerProduct(lhs._internal[0],rhs._internal[0])) ret_t;
|
|
||||||
iMatrix<ret_t,N> ret;
|
|
||||||
for(int c1=0;c1<N;c1++){
|
|
||||||
for(int c2=0;c2<N;c2++){
|
|
||||||
ret._internal[c1][c2] = outerProduct(lhs._internal[c1],rhs._internal[c2]);
|
|
||||||
}}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
template<class l,class r> inline
|
|
||||||
auto outerProduct (const iScalar<l>& lhs,const iScalar<r>& rhs) -> iScalar<decltype(outerProduct(lhs._internal,rhs._internal))>
|
|
||||||
{
|
|
||||||
typedef decltype(outerProduct(lhs._internal,rhs._internal)) ret_t;
|
|
||||||
iScalar<ret_t> ret;
|
|
||||||
ret._internal = outerProduct(lhs._internal,rhs._internal);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ComplexF outerProduct(const ComplexF &l, const ComplexF& r)
|
|
||||||
{
|
|
||||||
return l*r;
|
|
||||||
}
|
|
||||||
inline ComplexD outerProduct(const ComplexD &l, const ComplexD& r)
|
|
||||||
{
|
|
||||||
return l*r;
|
|
||||||
}
|
|
||||||
inline RealF outerProduct(const RealF &l, const RealF& r)
|
|
||||||
{
|
|
||||||
return l*r;
|
|
||||||
}
|
|
||||||
inline RealD outerProduct(const RealD &l, const RealD& r)
|
|
||||||
{
|
|
||||||
return l*r;
|
|
||||||
}
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/////////////////////////////////////////// CONJ ///////////////////////////////////////////
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Conj function for scalar, vector, matrix
|
|
||||||
template<class vtype> inline iScalar<vtype> conj(const iScalar<vtype>&r)
|
|
||||||
{
|
|
||||||
iScalar<vtype> ret;
|
|
||||||
ret._internal = conj(r._internal);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
template<class vtype,int N> inline iVector<vtype,N> conj(const iVector<vtype,N>&r)
|
|
||||||
{
|
|
||||||
iVector<vtype,N> ret;
|
|
||||||
for(int i=0;i<N;i++){
|
|
||||||
ret._internal[i] = conj(r._internal[i]);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
template<class vtype,int N> inline iMatrix<vtype,N> conj(const iMatrix<vtype,N>&r)
|
|
||||||
{
|
|
||||||
iMatrix<vtype,N> ret;
|
|
||||||
for(int i=0;i<N;i++){
|
|
||||||
for(int j=0;j<N;j++){
|
|
||||||
ret._internal[i][j] = conj(r._internal[i][j]);
|
|
||||||
}}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adj function for scalar, vector, matrix
|
|
||||||
template<class vtype> inline iScalar<vtype> adj(const iScalar<vtype>&r)
|
|
||||||
{
|
|
||||||
iScalar<vtype> ret;
|
|
||||||
ret._internal = adj(r._internal);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
template<class vtype,int N> inline iVector<vtype,N> adj(const iVector<vtype,N>&r)
|
|
||||||
{
|
|
||||||
iVector<vtype,N> ret;
|
|
||||||
for(int i=0;i<N;i++){
|
|
||||||
ret._internal[i] = adj(r._internal[i]);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
template<class vtype,int N> inline iMatrix<vtype,N> adj(const iMatrix<vtype,N> &arg)
|
|
||||||
{
|
|
||||||
iMatrix<vtype,N> ret;
|
|
||||||
for(int c1=0;c1<N;c1++){
|
|
||||||
for(int c2=0;c2<N;c2++){
|
|
||||||
ret._internal[c1][c2]=adj(arg._internal[c2][c1]);
|
|
||||||
}}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////
|
|
||||||
// Transpose all indices
|
|
||||||
/////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
inline ComplexD transpose(ComplexD &rhs){ return rhs;}
|
|
||||||
inline ComplexF transpose(ComplexF &rhs){ return rhs;}
|
|
||||||
inline RealD transpose(RealD &rhs){ return rhs;}
|
|
||||||
inline RealF transpose(RealF &rhs){ return rhs;}
|
|
||||||
|
|
||||||
template<class vtype,int N>
|
|
||||||
inline typename std::enable_if<isGridTensor<vtype>::value, iMatrix<vtype,N> >::type
|
|
||||||
transpose(iMatrix<vtype,N> arg)
|
|
||||||
{
|
|
||||||
iMatrix<vtype,N> ret;
|
|
||||||
for(int i=0;i<N;i++){
|
|
||||||
for(int j=0;j<N;j++){
|
|
||||||
ret._internal[i][j] = transpose(arg._internal[j][i]); // NB recurses
|
|
||||||
}}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
template<class vtype,int N>
|
|
||||||
inline typename std::enable_if<isGridTensor<vtype>::notvalue, iMatrix<vtype,N> >::type
|
|
||||||
transpose(iMatrix<vtype,N> arg)
|
|
||||||
{
|
|
||||||
iMatrix<vtype,N> ret;
|
|
||||||
for(int i=0;i<N;i++){
|
|
||||||
for(int j=0;j<N;j++){
|
|
||||||
ret._internal[i][j] = arg._internal[j][i]; // Stop recursion if not a tensor type
|
|
||||||
}}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class vtype>
|
|
||||||
inline typename std::enable_if<isGridTensor<vtype>::value, iScalar<vtype> >::type
|
|
||||||
transpose(iScalar<vtype> arg)
|
|
||||||
{
|
|
||||||
iScalar<vtype> ret;
|
|
||||||
ret._internal = transpose(arg._internal); // NB recurses
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class vtype>
|
|
||||||
inline typename std::enable_if<isGridTensor<vtype>::notvalue, iScalar<vtype> >::type
|
|
||||||
transpose(iScalar<vtype> arg)
|
|
||||||
{
|
|
||||||
iScalar<vtype> ret;
|
|
||||||
ret._internal = arg._internal; // NB recursion stops
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Transpose a specific index; instructive to compare this style of recursion termination
|
|
||||||
// to that of adj; which is easiers?
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
template<int Level,class vtype,int N> inline
|
|
||||||
typename std::enable_if<matchGridTensorIndex<iMatrix<vtype,N>,Level>::value, iMatrix<vtype,N> >::type
|
|
||||||
transposeIndex (const iMatrix<vtype,N> &arg)
|
|
||||||
{
|
|
||||||
iMatrix<vtype,N> ret;
|
|
||||||
for(int i=0;i<N;i++){
|
|
||||||
for(int j=0;j<N;j++){
|
|
||||||
ret._internal[i][j] = arg._internal[j][i];
|
|
||||||
}}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
// or not
|
|
||||||
template<int Level,class vtype,int N> inline
|
|
||||||
typename std::enable_if<matchGridTensorIndex<iMatrix<vtype,N>,Level>::notvalue, iMatrix<vtype,N> >::type
|
|
||||||
transposeIndex (const iMatrix<vtype,N> &arg)
|
|
||||||
{
|
|
||||||
iMatrix<vtype,N> ret;
|
|
||||||
for(int i=0;i<N;i++){
|
|
||||||
for(int j=0;j<N;j++){
|
|
||||||
ret._internal[i][j] = transposeIndex<Level>(arg._internal[i][j]);
|
|
||||||
}}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
template<int Level,class vtype> inline
|
|
||||||
typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::notvalue, iScalar<vtype> >::type
|
|
||||||
transposeIndex (const iScalar<vtype> &arg)
|
|
||||||
{
|
|
||||||
iScalar<vtype> ret;
|
|
||||||
ret._internal=transposeIndex<Level>(arg._internal);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
template<int Level,class vtype> inline
|
|
||||||
typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::value, iScalar<vtype> >::type
|
|
||||||
transposeIndex (const iScalar<vtype> &arg)
|
|
||||||
{
|
|
||||||
return arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////
|
|
||||||
// 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<int Level> inline ComplexF traceIndex(const ComplexF arg) { return arg;}
|
|
||||||
template<int Level> inline ComplexD traceIndex(const ComplexD arg) { return arg;}
|
|
||||||
template<int Level> inline RealF traceIndex(const RealF arg) { return arg;}
|
|
||||||
template<int Level> inline RealD traceIndex(const RealD arg) { return arg;}
|
|
||||||
|
|
||||||
template<class vtype,int N>
|
|
||||||
inline auto trace(const iMatrix<vtype,N> &arg) -> iScalar<decltype(trace(arg._internal[0][0]))>
|
|
||||||
{
|
|
||||||
iScalar<decltype( trace(arg._internal[0][0] )) > ret;
|
|
||||||
zeroit(ret._internal);
|
|
||||||
for(int i=0;i<N;i++){
|
|
||||||
ret._internal=ret._internal+trace(arg._internal[i][i]);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
template<class vtype>
|
|
||||||
inline auto trace(const iScalar<vtype> &arg) -> iScalar<decltype(trace(arg._internal))>
|
|
||||||
{
|
|
||||||
iScalar<decltype(trace(arg._internal))> ret;
|
|
||||||
ret._internal=trace(arg._internal);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Trace Specific indices.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/*
|
|
||||||
template<int Level,class vtype> inline
|
|
||||||
auto traceIndex(const iScalar<vtype> &arg) -> iScalar<decltype(traceIndex<Level>(arg._internal)) >
|
|
||||||
{
|
|
||||||
iScalar<decltype(traceIndex<Level>(arg._internal))> ret;
|
|
||||||
ret._internal = traceIndex<Level>(arg._internal);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
template<int Level,class vtype> inline auto
|
|
||||||
traceIndex (const iScalar<vtype> &arg) ->
|
|
||||||
typename
|
|
||||||
std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::notvalue,
|
|
||||||
iScalar<decltype(traceIndex<Level>(arg._internal))> >::type
|
|
||||||
|
|
||||||
{
|
|
||||||
iScalar<decltype(traceIndex<Level>(arg._internal))> ret;
|
|
||||||
ret._internal=traceIndex<Level>(arg._internal);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
template<int Level,class vtype> inline auto
|
|
||||||
traceIndex (const iScalar<vtype> &arg) ->
|
|
||||||
typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::value,
|
|
||||||
iScalar<vtype> >::type
|
|
||||||
{
|
|
||||||
return arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we hit the right index, return scalar and trace it with no further recursion
|
|
||||||
template<int Level,class vtype,int N> inline
|
|
||||||
auto traceIndex(const iMatrix<vtype,N> &arg) ->
|
|
||||||
typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::value, // Index matches
|
|
||||||
iScalar<vtype> >::type // return scalar
|
|
||||||
{
|
|
||||||
iScalar<vtype> ret;
|
|
||||||
zeroit(ret._internal);
|
|
||||||
for(int i=0;i<N;i++){
|
|
||||||
ret._internal = ret._internal + arg._internal[i][i];
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// not this level, so recurse
|
|
||||||
template<int Level,class vtype,int N> inline
|
|
||||||
auto traceIndex(const iMatrix<vtype,N> &arg) ->
|
|
||||||
typename std::enable_if<matchGridTensorIndex<iMatrix<vtype,N>,Level>::notvalue,// No index match
|
|
||||||
iMatrix<decltype(traceIndex<Level>(arg._internal[0][0])),N> >::type // return matrix
|
|
||||||
{
|
|
||||||
iMatrix<decltype(traceIndex<Level>(arg._internal[0][0])),N> ret;
|
|
||||||
for(int i=0;i<N;i++){
|
|
||||||
for(int j=0;j<N;j++){
|
|
||||||
ret._internal[i][j] = traceIndex<Level>(arg._internal[i][j]);
|
|
||||||
}}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Peek on a specific index; returns a scalar in that index, tensor inherits rest
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
// If we hit the right index, return scalar with no further recursion
|
|
||||||
|
|
||||||
//template<int Level> inline ComplexF peekIndex(const ComplexF arg) { return arg;}
|
|
||||||
//template<int Level> inline ComplexD peekIndex(const ComplexD arg) { return arg;}
|
|
||||||
//template<int Level> inline RealF peekIndex(const RealF arg) { return arg;}
|
|
||||||
//template<int Level> inline RealD peekIndex(const RealD arg) { return arg;}
|
|
||||||
|
|
||||||
// Scalar peek, no indices
|
|
||||||
template<int Level,class vtype> inline
|
|
||||||
auto peekIndex(const iScalar<vtype> &arg) ->
|
|
||||||
typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::value, // Index matches
|
|
||||||
iScalar<vtype> >::type // return scalar
|
|
||||||
{
|
|
||||||
return arg;
|
|
||||||
}
|
|
||||||
// Vector peek, one index
|
|
||||||
template<int Level,class vtype,int N> inline
|
|
||||||
auto peekIndex(const iVector<vtype,N> &arg,int i) ->
|
|
||||||
typename std::enable_if<matchGridTensorIndex<iVector<vtype,N>,Level>::value, // Index matches
|
|
||||||
iScalar<vtype> >::type // return scalar
|
|
||||||
{
|
|
||||||
iScalar<vtype> ret; // return scalar
|
|
||||||
ret._internal = arg._internal[i];
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
// Matrix peek, two indices
|
|
||||||
template<int Level,class vtype,int N> inline
|
|
||||||
auto peekIndex(const iMatrix<vtype,N> &arg,int i,int j) ->
|
|
||||||
typename std::enable_if<matchGridTensorIndex<iMatrix<vtype,N>,Level>::value, // Index matches
|
|
||||||
iScalar<vtype> >::type // return scalar
|
|
||||||
{
|
|
||||||
iScalar<vtype> ret; // return scalar
|
|
||||||
ret._internal = arg._internal[i][j];
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////
|
|
||||||
// No match peek for scalar,vector,matrix must forward on either 0,1,2 args. Must have 9 routines with notvalue
|
|
||||||
/////////////
|
|
||||||
// scalar
|
|
||||||
template<int Level,class vtype> inline
|
|
||||||
auto peekIndex(const iScalar<vtype> &arg) -> // Scalar 0 index
|
|
||||||
typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::notvalue, // Index does NOT match
|
|
||||||
iScalar<decltype(peekIndex<Level>(arg._internal))> >::type
|
|
||||||
{
|
|
||||||
iScalar<decltype(peekIndex<Level>(arg._internal))> ret;
|
|
||||||
ret._internal= peekIndex<Level>(arg._internal);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
template<int Level,class vtype> inline
|
|
||||||
auto peekIndex(const iScalar<vtype> &arg,int i) -> // Scalar 1 index
|
|
||||||
typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::notvalue, // Index does NOT match
|
|
||||||
iScalar<decltype(peekIndex<Level>(arg._internal,i))> >::type
|
|
||||||
{
|
|
||||||
iScalar<decltype(peekIndex<Level>(arg._internal,i))> ret;
|
|
||||||
ret._internal=peekIndex<Level>(arg._internal,i);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
template<int Level,class vtype> inline
|
|
||||||
auto peekIndex(const iScalar<vtype> &arg,int i,int j) -> // Scalar, 2 index
|
|
||||||
typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::notvalue, // Index does NOT match
|
|
||||||
iScalar<decltype(peekIndex<Level>(arg._internal,i,j))> >::type
|
|
||||||
{
|
|
||||||
iScalar<decltype(peekIndex<Level>(arg._internal,i,j))> ret;
|
|
||||||
ret._internal=peekIndex<Level>(arg._internal,i,j);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
// vector
|
|
||||||
template<int Level,class vtype,int N> inline
|
|
||||||
auto peekIndex(const iVector<vtype,N> &arg) ->
|
|
||||||
typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::notvalue, // Index does not match
|
|
||||||
iVector<decltype(peekIndex<Level>(arg._internal[0])),N> >::type
|
|
||||||
{
|
|
||||||
iVector<decltype(peekIndex<Level>(arg._internal[0])),N> ret;
|
|
||||||
for(int ii=0;ii<N;ii++){
|
|
||||||
ret._internal[ii]=peekIndex<Level>(arg._internal[ii]);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
template<int Level,class vtype,int N> inline
|
|
||||||
auto peekIndex(const iVector<vtype,N> &arg,int i) ->
|
|
||||||
typename std::enable_if<matchGridTensorIndex<iVector<vtype,N>,Level>::notvalue, // Index does not match
|
|
||||||
iVector<decltype(peekIndex<Level>(arg._internal[0],i)),N> >::type
|
|
||||||
{
|
|
||||||
iVector<decltype(peekIndex<Level>(arg._internal[0],i)),N> ret;
|
|
||||||
for(int ii=0;ii<N;ii++){
|
|
||||||
ret._internal[ii]=peekIndex<Level>(arg._internal[ii],i);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
template<int Level,class vtype,int N> inline
|
|
||||||
auto peekIndex(const iVector<vtype,N> &arg,int i,int j) ->
|
|
||||||
typename std::enable_if<matchGridTensorIndex<iVector<vtype,N>,Level>::notvalue, // Index does not match
|
|
||||||
iVector<decltype(peekIndex<Level>(arg._internal[0],i,j)),N> >::type
|
|
||||||
{
|
|
||||||
iVector<decltype(peekIndex<Level>(arg._internal[0],i,j)),N> ret;
|
|
||||||
for(int ii=0;ii<N;ii++){
|
|
||||||
ret._internal[ii]=peekIndex<Level>(arg._internal[ii],i,j);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
// matrix
|
|
||||||
template<int Level,class vtype,int N> inline
|
|
||||||
auto peekIndex(const iMatrix<vtype,N> &arg) ->
|
|
||||||
typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::notvalue, // Index does not match
|
|
||||||
iMatrix<decltype(peekIndex<Level>(arg._internal[0][0])),N> >::type
|
|
||||||
{
|
|
||||||
iMatrix<decltype(peekIndex<Level>(arg._internal[0][0])),N> ret;
|
|
||||||
for(int ii=0;ii<N;ii++){
|
|
||||||
for(int jj=0;jj<N;jj++){
|
|
||||||
ret._internal[ii][jj]=peekIndex<Level>(arg._internal[ii][jj]);// Could avoid this because peeking a scalar is dumb
|
|
||||||
}}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
template<int Level,class vtype,int N> inline
|
|
||||||
auto peekIndex(const iMatrix<vtype,N> &arg,int i) ->
|
|
||||||
typename std::enable_if<matchGridTensorIndex<iMatrix<vtype,N>,Level>::notvalue, // Index does not match
|
|
||||||
iMatrix<decltype(peekIndex<Level>(arg._internal[0],i)),N> >::type
|
|
||||||
{
|
|
||||||
iMatrix<decltype(peekIndex<Level>(arg._internal[0],i)),N> ret;
|
|
||||||
for(int ii=0;ii<N;ii++){
|
|
||||||
for(int jj=0;jj<N;jj++){
|
|
||||||
ret._internal[ii][jj]=peekIndex<Level>(arg._internal[ii][jj],i);
|
|
||||||
}}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
template<int Level,class vtype,int N> inline
|
|
||||||
auto peekIndex(const iMatrix<vtype,N> &arg,int i,int j) ->
|
|
||||||
typename std::enable_if<matchGridTensorIndex<iMatrix<vtype,N>,Level>::notvalue, // Index does not match
|
|
||||||
iMatrix<decltype(peekIndex<Level>(arg._internal[0][0],i,j)),N> >::type
|
|
||||||
{
|
|
||||||
iMatrix<decltype(peekIndex<Level>(arg._internal[0][0],i,j)),N> ret;
|
|
||||||
for(int ii=0;ii<N;ii++){
|
|
||||||
for(int jj=0;jj<N;jj++){
|
|
||||||
ret._internal[ii][jj]=peekIndex<Level>(arg._internal[ii][jj],i,j);
|
|
||||||
}}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Poke a specific index;
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Scalar poke
|
|
||||||
template<int Level,class vtype> inline
|
|
||||||
void pokeIndex(iScalar<vtype> &ret,
|
|
||||||
const typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::value,iScalar<vtype> >::type &arg)
|
|
||||||
{
|
|
||||||
ret._internal = arg._internal;
|
|
||||||
}
|
|
||||||
// Vector poke, one index
|
|
||||||
template<int Level,class vtype,int N> inline
|
|
||||||
void pokeIndex(iVector<vtype,N> &ret,
|
|
||||||
const typename std::enable_if<matchGridTensorIndex<iVector<vtype,N>,Level>::value,iScalar<vtype> >::type &arg,int i)
|
|
||||||
{
|
|
||||||
ret._internal[i] = arg._internal;
|
|
||||||
}
|
|
||||||
// Vector poke, two indices
|
|
||||||
template<int Level,class vtype,int N> inline
|
|
||||||
void pokeIndex(iMatrix<vtype,N> &ret,
|
|
||||||
const typename std::enable_if<matchGridTensorIndex<iMatrix<vtype,N>,Level>::value,iScalar<vtype> >::type &arg,int i,int j)
|
|
||||||
{
|
|
||||||
ret._internal[i][j] = arg._internal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////
|
|
||||||
// No match poke for scalar,vector,matrix must forward on either 0,1,2 args. Must have 9 routines with notvalue
|
|
||||||
/////////////
|
|
||||||
// scalar
|
|
||||||
template<int Level,class vtype> inline
|
|
||||||
void pokeIndex(iScalar<vtype> &ret,
|
|
||||||
const typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::notvalue,iScalar<decltype(peekIndex<Level>(ret._internal))> >::type &arg)
|
|
||||||
|
|
||||||
{
|
|
||||||
pokeIndex<Level>(ret._internal,arg._internal);
|
|
||||||
}
|
|
||||||
template<int Level,class vtype> inline
|
|
||||||
void pokeIndex(iScalar<vtype> &ret,
|
|
||||||
const typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::notvalue,iScalar<decltype(peekIndex<Level>(ret._internal,0))> >::type &arg,
|
|
||||||
int i)
|
|
||||||
|
|
||||||
{
|
|
||||||
pokeIndex<Level>(ret._internal,arg._internal,i);
|
|
||||||
}
|
|
||||||
template<int Level,class vtype> inline
|
|
||||||
void pokeIndex(iScalar<vtype> &ret,
|
|
||||||
const typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::notvalue,iScalar<decltype(peekIndex<Level>(ret._internal,0,0))> >::type &arg,
|
|
||||||
int i,int j)
|
|
||||||
|
|
||||||
{
|
|
||||||
pokeIndex<Level>(ret._internal,arg._internal,i,j);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vector
|
|
||||||
template<int Level,class vtype,int N> inline
|
|
||||||
void pokeIndex(iVector<vtype,N> &ret,
|
|
||||||
const typename std::enable_if<matchGridTensorIndex<iVector<vtype,N>,Level>::notvalue,iVector<decltype(peekIndex<Level>(ret._internal)),N> >::type &arg)
|
|
||||||
|
|
||||||
{
|
|
||||||
for(int ii=0;ii<N;ii++){
|
|
||||||
pokeIndex<Level>(ret._internal[ii],arg._internal[ii]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
template<int Level,class vtype,int N> inline
|
|
||||||
void pokeIndex(iVector<vtype,N> &ret,
|
|
||||||
const typename std::enable_if<matchGridTensorIndex<iVector<vtype,N>,Level>::notvalue,iVector<decltype(peekIndex<Level>(ret._internal,0)),N> >::type &arg,
|
|
||||||
int i)
|
|
||||||
|
|
||||||
{
|
|
||||||
for(int ii=0;ii<N;ii++){
|
|
||||||
pokeIndex<Level>(ret._internal[ii],arg._internal[ii],i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
template<int Level,class vtype,int N> inline
|
|
||||||
void pokeIndex(iVector<vtype,N> &ret,
|
|
||||||
const typename std::enable_if<matchGridTensorIndex<iVector<vtype,N>,Level>::notvalue,iVector<decltype(peekIndex<Level>(ret._internal,0,0)),N> >::type &arg,
|
|
||||||
int i,int j)
|
|
||||||
|
|
||||||
{
|
|
||||||
for(int ii=0;ii<N;ii++){
|
|
||||||
pokeIndex<Level>(ret._internal[ii],arg._internal[ii],i,j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Matrix
|
|
||||||
template<int Level,class vtype,int N> inline
|
|
||||||
void pokeIndex(iMatrix<vtype,N> &ret,
|
|
||||||
const typename std::enable_if<matchGridTensorIndex<iMatrix<vtype,N>,Level>::notvalue,iMatrix<decltype(peekIndex<Level>(ret._internal)),N> >::type &arg)
|
|
||||||
|
|
||||||
{
|
|
||||||
for(int ii=0;ii<N;ii++){
|
|
||||||
for(int jj=0;jj<N;jj++){
|
|
||||||
pokeIndex<Level>(ret._internal[ii][jj],arg._internal[ii][jj]);
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
template<int Level,class vtype,int N> inline
|
|
||||||
void pokeIndex(iMatrix<vtype,N> &ret,
|
|
||||||
const typename std::enable_if<matchGridTensorIndex<iMatrix<vtype,N>,Level>::notvalue,iMatrix<decltype(peekIndex<Level>(ret._internal,0)),N> >::type &arg,
|
|
||||||
int i)
|
|
||||||
|
|
||||||
{
|
|
||||||
for(int ii=0;ii<N;ii++){
|
|
||||||
for(int jj=0;jj<N;jj++){
|
|
||||||
pokeIndex<Level>(ret._internal[ii][jj],arg._internal[ii][jj],i);
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
template<int Level,class vtype,int N> inline
|
|
||||||
void pokeIndex(iMatrix<vtype,N> &ret,
|
|
||||||
const typename std::enable_if<matchGridTensorIndex<iMatrix<vtype,N>,Level>::notvalue,iMatrix<decltype(peekIndex<Level>(ret._internal,0,0)),N> >::type &arg,
|
|
||||||
int i,int j)
|
|
||||||
|
|
||||||
{
|
|
||||||
for(int ii=0;ii<N;ii++){
|
|
||||||
for(int jj=0;jj<N;jj++){
|
|
||||||
pokeIndex<Level>(ret._internal[ii][jj],arg._internal[ii][jj],i,j);
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////
|
|
||||||
// Can only take the real/imag part of scalar objects, since
|
|
||||||
// lattice objects of different complex nature are non-conformable.
|
|
||||||
/////////////////////////////////////////////////////////////////
|
|
||||||
template<class itype> inline auto real(const iScalar<itype> &z) -> iScalar<decltype(real(z._internal))>
|
|
||||||
{
|
|
||||||
iScalar<decltype(real(z._internal))> ret;
|
|
||||||
ret._internal = real(z._internal);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
template<class itype,int N> inline auto real(const iMatrix<itype,N> &z) -> iMatrix<decltype(real(z._internal[0][0])),N>
|
|
||||||
{
|
|
||||||
iMatrix<decltype(real(z._internal[0][0])),N> ret;
|
|
||||||
for(int c1=0;c1<N;c1++){
|
|
||||||
for(int c2=0;c2<N;c2++){
|
|
||||||
ret._internal[c1][c2] = real(z._internal[c1][c2]);
|
|
||||||
}}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
template<class itype,int N> inline auto real(const iVector<itype,N> &z) -> iVector<decltype(real(z._internal[0])),N>
|
|
||||||
{
|
|
||||||
iVector<decltype(real(z._internal[0])),N> ret;
|
|
||||||
for(int c1=0;c1<N;c1++){
|
|
||||||
ret._internal[c1] = real(z._internal[c1]);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class itype> inline auto imag(const iScalar<itype> &z) -> iScalar<decltype(imag(z._internal))>
|
|
||||||
{
|
|
||||||
iScalar<decltype(imag(z._internal))> ret;
|
|
||||||
ret._internal = imag(z._internal);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
template<class itype,int N> inline auto imag(const iMatrix<itype,N> &z) -> iMatrix<decltype(imag(z._internal[0][0])),N>
|
|
||||||
{
|
|
||||||
iMatrix<decltype(imag(z._internal[0][0])),N> ret;
|
|
||||||
for(int c1=0;c1<N;c1++){
|
|
||||||
for(int c2=0;c2<N;c2++){
|
|
||||||
ret._internal[c1][c2] = imag(z._internal[c1][c2]);
|
|
||||||
}}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
template<class itype,int N> inline auto imag(const iVector<itype,N> &z) -> iVector<decltype(imag(z._internal[0])),N>
|
|
||||||
{
|
|
||||||
iVector<decltype(imag(z._internal[0])),N> ret;
|
|
||||||
for(int c1=0;c1<N;c1++){
|
|
||||||
ret._internal[c1] = imag(z._internal[c1]);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
41
lib/Grid_math_inner.h
Normal file
41
lib/Grid_math_inner.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#ifndef GRID_MATH_INNER_H
|
||||||
|
#define GRID_MATH_INNER_H
|
||||||
|
namespace Grid {
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// innerProduct Scalar x Scalar -> Scalar
|
||||||
|
// innerProduct Vector x Vector -> Scalar
|
||||||
|
// innerProduct Matrix x Matrix -> Scalar
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
template<class l,class r,int N> inline
|
||||||
|
auto innerProduct (const iVector<l,N>& lhs,const iVector<r,N>& rhs) -> iScalar<decltype(innerProduct(lhs._internal[0],rhs._internal[0]))>
|
||||||
|
{
|
||||||
|
typedef decltype(innerProduct(lhs._internal[0],rhs._internal[0])) ret_t;
|
||||||
|
iScalar<ret_t> ret=zero;
|
||||||
|
for(int c1=0;c1<N;c1++){
|
||||||
|
ret._internal += innerProduct(lhs._internal[c1],rhs._internal[c1]);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
template<class l,class r,int N> inline
|
||||||
|
auto innerProduct (const iMatrix<l,N>& lhs,const iMatrix<r,N>& rhs) -> iScalar<decltype(innerProduct(lhs._internal[0][0],rhs._internal[0][0]))>
|
||||||
|
{
|
||||||
|
typedef decltype(innerProduct(lhs._internal[0][0],rhs._internal[0][0])) ret_t;
|
||||||
|
iScalar<ret_t> ret=zero;
|
||||||
|
iScalar<ret_t> tmp;
|
||||||
|
for(int c1=0;c1<N;c1++){
|
||||||
|
for(int c2=0;c2<N;c2++){
|
||||||
|
ret._internal+=innerProduct(lhs._internal[c1][c2],rhs._internal[c1][c2]);
|
||||||
|
}}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
template<class l,class r> inline
|
||||||
|
auto innerProduct (const iScalar<l>& lhs,const iScalar<r>& rhs) -> iScalar<decltype(innerProduct(lhs._internal,rhs._internal))>
|
||||||
|
{
|
||||||
|
typedef decltype(innerProduct(lhs._internal,rhs._internal)) ret_t;
|
||||||
|
iScalar<ret_t> ret;
|
||||||
|
ret._internal = innerProduct(lhs._internal,rhs._internal);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
47
lib/Grid_math_outer.h
Normal file
47
lib/Grid_math_outer.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#ifndef GRID_MATH_OUTER_H
|
||||||
|
#define GRID_MATH_OUTER_H
|
||||||
|
namespace Grid {
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// outerProduct Scalar x Scalar -> Scalar
|
||||||
|
// Vector x Vector -> Matrix
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template<class l,class r,int N> inline
|
||||||
|
auto outerProduct (const iVector<l,N>& lhs,const iVector<r,N>& rhs) -> iMatrix<decltype(outerProduct(lhs._internal[0],rhs._internal[0])),N>
|
||||||
|
{
|
||||||
|
typedef decltype(outerProduct(lhs._internal[0],rhs._internal[0])) ret_t;
|
||||||
|
iMatrix<ret_t,N> ret;
|
||||||
|
for(int c1=0;c1<N;c1++){
|
||||||
|
for(int c2=0;c2<N;c2++){
|
||||||
|
ret._internal[c1][c2] = outerProduct(lhs._internal[c1],rhs._internal[c2]);
|
||||||
|
}}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
template<class l,class r> inline
|
||||||
|
auto outerProduct (const iScalar<l>& lhs,const iScalar<r>& rhs) -> iScalar<decltype(outerProduct(lhs._internal,rhs._internal))>
|
||||||
|
{
|
||||||
|
typedef decltype(outerProduct(lhs._internal,rhs._internal)) ret_t;
|
||||||
|
iScalar<ret_t> ret;
|
||||||
|
ret._internal = outerProduct(lhs._internal,rhs._internal);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ComplexF outerProduct(const ComplexF &l, const ComplexF& r)
|
||||||
|
{
|
||||||
|
return l*r;
|
||||||
|
}
|
||||||
|
inline ComplexD outerProduct(const ComplexD &l, const ComplexD& r)
|
||||||
|
{
|
||||||
|
return l*r;
|
||||||
|
}
|
||||||
|
inline RealF outerProduct(const RealF &l, const RealF& r)
|
||||||
|
{
|
||||||
|
return l*r;
|
||||||
|
}
|
||||||
|
inline RealD outerProduct(const RealD &l, const RealD& r)
|
||||||
|
{
|
||||||
|
return l*r;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
149
lib/Grid_math_peek.h
Normal file
149
lib/Grid_math_peek.h
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
#ifndef GRID_MATH_PEEK_H
|
||||||
|
#define GRID_MATH_PEEK_H
|
||||||
|
namespace Grid {
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Peek on a specific index; returns a scalar in that index, tensor inherits rest
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// If we hit the right index, return scalar with no further recursion
|
||||||
|
|
||||||
|
//template<int Level> inline ComplexF peekIndex(const ComplexF arg) { return arg;}
|
||||||
|
//template<int Level> inline ComplexD peekIndex(const ComplexD arg) { return arg;}
|
||||||
|
//template<int Level> inline RealF peekIndex(const RealF arg) { return arg;}
|
||||||
|
//template<int Level> inline RealD peekIndex(const RealD arg) { return arg;}
|
||||||
|
|
||||||
|
// Scalar peek, no indices
|
||||||
|
template<int Level,class vtype> inline
|
||||||
|
auto peekIndex(const iScalar<vtype> &arg) ->
|
||||||
|
typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::value, // Index matches
|
||||||
|
iScalar<vtype> >::type // return scalar
|
||||||
|
{
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
// Vector peek, one index
|
||||||
|
template<int Level,class vtype,int N> inline
|
||||||
|
auto peekIndex(const iVector<vtype,N> &arg,int i) ->
|
||||||
|
typename std::enable_if<matchGridTensorIndex<iVector<vtype,N>,Level>::value, // Index matches
|
||||||
|
iScalar<vtype> >::type // return scalar
|
||||||
|
{
|
||||||
|
iScalar<vtype> ret; // return scalar
|
||||||
|
ret._internal = arg._internal[i];
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
// Matrix peek, two indices
|
||||||
|
template<int Level,class vtype,int N> inline
|
||||||
|
auto peekIndex(const iMatrix<vtype,N> &arg,int i,int j) ->
|
||||||
|
typename std::enable_if<matchGridTensorIndex<iMatrix<vtype,N>,Level>::value, // Index matches
|
||||||
|
iScalar<vtype> >::type // return scalar
|
||||||
|
{
|
||||||
|
iScalar<vtype> ret; // return scalar
|
||||||
|
ret._internal = arg._internal[i][j];
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////
|
||||||
|
// No match peek for scalar,vector,matrix must forward on either 0,1,2 args. Must have 9 routines with notvalue
|
||||||
|
/////////////
|
||||||
|
// scalar
|
||||||
|
template<int Level,class vtype> inline
|
||||||
|
auto peekIndex(const iScalar<vtype> &arg) -> // Scalar 0 index
|
||||||
|
typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::notvalue, // Index does NOT match
|
||||||
|
iScalar<decltype(peekIndex<Level>(arg._internal))> >::type
|
||||||
|
{
|
||||||
|
iScalar<decltype(peekIndex<Level>(arg._internal))> ret;
|
||||||
|
ret._internal= peekIndex<Level>(arg._internal);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
template<int Level,class vtype> inline
|
||||||
|
auto peekIndex(const iScalar<vtype> &arg,int i) -> // Scalar 1 index
|
||||||
|
typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::notvalue, // Index does NOT match
|
||||||
|
iScalar<decltype(peekIndex<Level>(arg._internal,i))> >::type
|
||||||
|
{
|
||||||
|
iScalar<decltype(peekIndex<Level>(arg._internal,i))> ret;
|
||||||
|
ret._internal=peekIndex<Level>(arg._internal,i);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
template<int Level,class vtype> inline
|
||||||
|
auto peekIndex(const iScalar<vtype> &arg,int i,int j) -> // Scalar, 2 index
|
||||||
|
typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::notvalue, // Index does NOT match
|
||||||
|
iScalar<decltype(peekIndex<Level>(arg._internal,i,j))> >::type
|
||||||
|
{
|
||||||
|
iScalar<decltype(peekIndex<Level>(arg._internal,i,j))> ret;
|
||||||
|
ret._internal=peekIndex<Level>(arg._internal,i,j);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
// vector
|
||||||
|
template<int Level,class vtype,int N> inline
|
||||||
|
auto peekIndex(const iVector<vtype,N> &arg) ->
|
||||||
|
typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::notvalue, // Index does not match
|
||||||
|
iVector<decltype(peekIndex<Level>(arg._internal[0])),N> >::type
|
||||||
|
{
|
||||||
|
iVector<decltype(peekIndex<Level>(arg._internal[0])),N> ret;
|
||||||
|
for(int ii=0;ii<N;ii++){
|
||||||
|
ret._internal[ii]=peekIndex<Level>(arg._internal[ii]);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
template<int Level,class vtype,int N> inline
|
||||||
|
auto peekIndex(const iVector<vtype,N> &arg,int i) ->
|
||||||
|
typename std::enable_if<matchGridTensorIndex<iVector<vtype,N>,Level>::notvalue, // Index does not match
|
||||||
|
iVector<decltype(peekIndex<Level>(arg._internal[0],i)),N> >::type
|
||||||
|
{
|
||||||
|
iVector<decltype(peekIndex<Level>(arg._internal[0],i)),N> ret;
|
||||||
|
for(int ii=0;ii<N;ii++){
|
||||||
|
ret._internal[ii]=peekIndex<Level>(arg._internal[ii],i);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
template<int Level,class vtype,int N> inline
|
||||||
|
auto peekIndex(const iVector<vtype,N> &arg,int i,int j) ->
|
||||||
|
typename std::enable_if<matchGridTensorIndex<iVector<vtype,N>,Level>::notvalue, // Index does not match
|
||||||
|
iVector<decltype(peekIndex<Level>(arg._internal[0],i,j)),N> >::type
|
||||||
|
{
|
||||||
|
iVector<decltype(peekIndex<Level>(arg._internal[0],i,j)),N> ret;
|
||||||
|
for(int ii=0;ii<N;ii++){
|
||||||
|
ret._internal[ii]=peekIndex<Level>(arg._internal[ii],i,j);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
// matrix
|
||||||
|
template<int Level,class vtype,int N> inline
|
||||||
|
auto peekIndex(const iMatrix<vtype,N> &arg) ->
|
||||||
|
typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::notvalue, // Index does not match
|
||||||
|
iMatrix<decltype(peekIndex<Level>(arg._internal[0][0])),N> >::type
|
||||||
|
{
|
||||||
|
iMatrix<decltype(peekIndex<Level>(arg._internal[0][0])),N> ret;
|
||||||
|
for(int ii=0;ii<N;ii++){
|
||||||
|
for(int jj=0;jj<N;jj++){
|
||||||
|
ret._internal[ii][jj]=peekIndex<Level>(arg._internal[ii][jj]);// Could avoid this because peeking a scalar is dumb
|
||||||
|
}}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
template<int Level,class vtype,int N> inline
|
||||||
|
auto peekIndex(const iMatrix<vtype,N> &arg,int i) ->
|
||||||
|
typename std::enable_if<matchGridTensorIndex<iMatrix<vtype,N>,Level>::notvalue, // Index does not match
|
||||||
|
iMatrix<decltype(peekIndex<Level>(arg._internal[0],i)),N> >::type
|
||||||
|
{
|
||||||
|
iMatrix<decltype(peekIndex<Level>(arg._internal[0],i)),N> ret;
|
||||||
|
for(int ii=0;ii<N;ii++){
|
||||||
|
for(int jj=0;jj<N;jj++){
|
||||||
|
ret._internal[ii][jj]=peekIndex<Level>(arg._internal[ii][jj],i);
|
||||||
|
}}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
template<int Level,class vtype,int N> inline
|
||||||
|
auto peekIndex(const iMatrix<vtype,N> &arg,int i,int j) ->
|
||||||
|
typename std::enable_if<matchGridTensorIndex<iMatrix<vtype,N>,Level>::notvalue, // Index does not match
|
||||||
|
iMatrix<decltype(peekIndex<Level>(arg._internal[0][0],i,j)),N> >::type
|
||||||
|
{
|
||||||
|
iMatrix<decltype(peekIndex<Level>(arg._internal[0][0],i,j)),N> ret;
|
||||||
|
for(int ii=0;ii<N;ii++){
|
||||||
|
for(int jj=0;jj<N;jj++){
|
||||||
|
ret._internal[ii][jj]=peekIndex<Level>(arg._internal[ii][jj],i,j);
|
||||||
|
}}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
126
lib/Grid_math_poke.h
Normal file
126
lib/Grid_math_poke.h
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
#ifndef GRID_MATH_POKE_H
|
||||||
|
#define GRID_MATH_POKE_H
|
||||||
|
namespace Grid {
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Poke a specific index;
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Scalar poke
|
||||||
|
template<int Level,class vtype> inline
|
||||||
|
void pokeIndex(iScalar<vtype> &ret,
|
||||||
|
const typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::value,iScalar<vtype> >::type &arg)
|
||||||
|
{
|
||||||
|
ret._internal = arg._internal;
|
||||||
|
}
|
||||||
|
// Vector poke, one index
|
||||||
|
template<int Level,class vtype,int N> inline
|
||||||
|
void pokeIndex(iVector<vtype,N> &ret,
|
||||||
|
const typename std::enable_if<matchGridTensorIndex<iVector<vtype,N>,Level>::value,iScalar<vtype> >::type &arg,int i)
|
||||||
|
{
|
||||||
|
ret._internal[i] = arg._internal;
|
||||||
|
}
|
||||||
|
// Vector poke, two indices
|
||||||
|
template<int Level,class vtype,int N> inline
|
||||||
|
void pokeIndex(iMatrix<vtype,N> &ret,
|
||||||
|
const typename std::enable_if<matchGridTensorIndex<iMatrix<vtype,N>,Level>::value,iScalar<vtype> >::type &arg,int i,int j)
|
||||||
|
{
|
||||||
|
ret._internal[i][j] = arg._internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////
|
||||||
|
// No match poke for scalar,vector,matrix must forward on either 0,1,2 args. Must have 9 routines with notvalue
|
||||||
|
/////////////
|
||||||
|
// scalar
|
||||||
|
template<int Level,class vtype> inline
|
||||||
|
void pokeIndex(iScalar<vtype> &ret,
|
||||||
|
const typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::notvalue,iScalar<decltype(peekIndex<Level>(ret._internal))> >::type &arg)
|
||||||
|
|
||||||
|
{
|
||||||
|
pokeIndex<Level>(ret._internal,arg._internal);
|
||||||
|
}
|
||||||
|
template<int Level,class vtype> inline
|
||||||
|
void pokeIndex(iScalar<vtype> &ret,
|
||||||
|
const typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::notvalue,iScalar<decltype(peekIndex<Level>(ret._internal,0))> >::type &arg,
|
||||||
|
int i)
|
||||||
|
|
||||||
|
{
|
||||||
|
pokeIndex<Level>(ret._internal,arg._internal,i);
|
||||||
|
}
|
||||||
|
template<int Level,class vtype> inline
|
||||||
|
void pokeIndex(iScalar<vtype> &ret,
|
||||||
|
const typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::notvalue,iScalar<decltype(peekIndex<Level>(ret._internal,0,0))> >::type &arg,
|
||||||
|
int i,int j)
|
||||||
|
|
||||||
|
{
|
||||||
|
pokeIndex<Level>(ret._internal,arg._internal,i,j);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vector
|
||||||
|
template<int Level,class vtype,int N> inline
|
||||||
|
void pokeIndex(iVector<vtype,N> &ret,
|
||||||
|
const typename std::enable_if<matchGridTensorIndex<iVector<vtype,N>,Level>::notvalue,iVector<decltype(peekIndex<Level>(ret._internal)),N> >::type &arg)
|
||||||
|
|
||||||
|
{
|
||||||
|
for(int ii=0;ii<N;ii++){
|
||||||
|
pokeIndex<Level>(ret._internal[ii],arg._internal[ii]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template<int Level,class vtype,int N> inline
|
||||||
|
void pokeIndex(iVector<vtype,N> &ret,
|
||||||
|
const typename std::enable_if<matchGridTensorIndex<iVector<vtype,N>,Level>::notvalue,iVector<decltype(peekIndex<Level>(ret._internal,0)),N> >::type &arg,
|
||||||
|
int i)
|
||||||
|
|
||||||
|
{
|
||||||
|
for(int ii=0;ii<N;ii++){
|
||||||
|
pokeIndex<Level>(ret._internal[ii],arg._internal[ii],i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template<int Level,class vtype,int N> inline
|
||||||
|
void pokeIndex(iVector<vtype,N> &ret,
|
||||||
|
const typename std::enable_if<matchGridTensorIndex<iVector<vtype,N>,Level>::notvalue,iVector<decltype(peekIndex<Level>(ret._internal,0,0)),N> >::type &arg,
|
||||||
|
int i,int j)
|
||||||
|
|
||||||
|
{
|
||||||
|
for(int ii=0;ii<N;ii++){
|
||||||
|
pokeIndex<Level>(ret._internal[ii],arg._internal[ii],i,j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Matrix
|
||||||
|
template<int Level,class vtype,int N> inline
|
||||||
|
void pokeIndex(iMatrix<vtype,N> &ret,
|
||||||
|
const typename std::enable_if<matchGridTensorIndex<iMatrix<vtype,N>,Level>::notvalue,iMatrix<decltype(peekIndex<Level>(ret._internal)),N> >::type &arg)
|
||||||
|
|
||||||
|
{
|
||||||
|
for(int ii=0;ii<N;ii++){
|
||||||
|
for(int jj=0;jj<N;jj++){
|
||||||
|
pokeIndex<Level>(ret._internal[ii][jj],arg._internal[ii][jj]);
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
template<int Level,class vtype,int N> inline
|
||||||
|
void pokeIndex(iMatrix<vtype,N> &ret,
|
||||||
|
const typename std::enable_if<matchGridTensorIndex<iMatrix<vtype,N>,Level>::notvalue,iMatrix<decltype(peekIndex<Level>(ret._internal,0)),N> >::type &arg,
|
||||||
|
int i)
|
||||||
|
|
||||||
|
{
|
||||||
|
for(int ii=0;ii<N;ii++){
|
||||||
|
for(int jj=0;jj<N;jj++){
|
||||||
|
pokeIndex<Level>(ret._internal[ii][jj],arg._internal[ii][jj],i);
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
template<int Level,class vtype,int N> inline
|
||||||
|
void pokeIndex(iMatrix<vtype,N> &ret,
|
||||||
|
const typename std::enable_if<matchGridTensorIndex<iMatrix<vtype,N>,Level>::notvalue,iMatrix<decltype(peekIndex<Level>(ret._internal,0,0)),N> >::type &arg,
|
||||||
|
int i,int j)
|
||||||
|
|
||||||
|
{
|
||||||
|
for(int ii=0;ii<N;ii++){
|
||||||
|
for(int jj=0;jj<N;jj++){
|
||||||
|
pokeIndex<Level>(ret._internal[ii][jj],arg._internal[ii][jj],i,j);
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
115
lib/Grid_math_reality.h
Normal file
115
lib/Grid_math_reality.h
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
#ifndef GRID_MATH_REALITY_H
|
||||||
|
#define GRID_MATH_REALITY_H
|
||||||
|
namespace Grid {
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/////////////////////////////////////////// CONJ ///////////////////////////////////////////
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Conj function for scalar, vector, matrix
|
||||||
|
template<class vtype> inline iScalar<vtype> conj(const iScalar<vtype>&r)
|
||||||
|
{
|
||||||
|
iScalar<vtype> ret;
|
||||||
|
ret._internal = conj(r._internal);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
template<class vtype,int N> inline iVector<vtype,N> conj(const iVector<vtype,N>&r)
|
||||||
|
{
|
||||||
|
iVector<vtype,N> ret;
|
||||||
|
for(int i=0;i<N;i++){
|
||||||
|
ret._internal[i] = conj(r._internal[i]);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
template<class vtype,int N> inline iMatrix<vtype,N> conj(const iMatrix<vtype,N>&r)
|
||||||
|
{
|
||||||
|
iMatrix<vtype,N> ret;
|
||||||
|
for(int i=0;i<N;i++){
|
||||||
|
for(int j=0;j<N;j++){
|
||||||
|
ret._internal[i][j] = conj(r._internal[i][j]);
|
||||||
|
}}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adj function for scalar, vector, matrix
|
||||||
|
template<class vtype> inline iScalar<vtype> adj(const iScalar<vtype>&r)
|
||||||
|
{
|
||||||
|
iScalar<vtype> ret;
|
||||||
|
ret._internal = adj(r._internal);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
template<class vtype,int N> inline iVector<vtype,N> adj(const iVector<vtype,N>&r)
|
||||||
|
{
|
||||||
|
iVector<vtype,N> ret;
|
||||||
|
for(int i=0;i<N;i++){
|
||||||
|
ret._internal[i] = adj(r._internal[i]);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
template<class vtype,int N> inline iMatrix<vtype,N> adj(const iMatrix<vtype,N> &arg)
|
||||||
|
{
|
||||||
|
iMatrix<vtype,N> ret;
|
||||||
|
for(int c1=0;c1<N;c1++){
|
||||||
|
for(int c2=0;c2<N;c2++){
|
||||||
|
ret._internal[c1][c2]=adj(arg._internal[c2][c1]);
|
||||||
|
}}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// Can only take the real/imag part of scalar objects, since
|
||||||
|
// lattice objects of different complex nature are non-conformable.
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
template<class itype> inline auto real(const iScalar<itype> &z) -> iScalar<decltype(real(z._internal))>
|
||||||
|
{
|
||||||
|
iScalar<decltype(real(z._internal))> ret;
|
||||||
|
ret._internal = real(z._internal);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
template<class itype,int N> inline auto real(const iMatrix<itype,N> &z) -> iMatrix<decltype(real(z._internal[0][0])),N>
|
||||||
|
{
|
||||||
|
iMatrix<decltype(real(z._internal[0][0])),N> ret;
|
||||||
|
for(int c1=0;c1<N;c1++){
|
||||||
|
for(int c2=0;c2<N;c2++){
|
||||||
|
ret._internal[c1][c2] = real(z._internal[c1][c2]);
|
||||||
|
}}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
template<class itype,int N> inline auto real(const iVector<itype,N> &z) -> iVector<decltype(real(z._internal[0])),N>
|
||||||
|
{
|
||||||
|
iVector<decltype(real(z._internal[0])),N> ret;
|
||||||
|
for(int c1=0;c1<N;c1++){
|
||||||
|
ret._internal[c1] = real(z._internal[c1]);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class itype> inline auto imag(const iScalar<itype> &z) -> iScalar<decltype(imag(z._internal))>
|
||||||
|
{
|
||||||
|
iScalar<decltype(imag(z._internal))> ret;
|
||||||
|
ret._internal = imag(z._internal);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
template<class itype,int N> inline auto imag(const iMatrix<itype,N> &z) -> iMatrix<decltype(imag(z._internal[0][0])),N>
|
||||||
|
{
|
||||||
|
iMatrix<decltype(imag(z._internal[0][0])),N> ret;
|
||||||
|
for(int c1=0;c1<N;c1++){
|
||||||
|
for(int c2=0;c2<N;c2++){
|
||||||
|
ret._internal[c1][c2] = imag(z._internal[c1][c2]);
|
||||||
|
}}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
template<class itype,int N> inline auto imag(const iVector<itype,N> &z) -> iVector<decltype(imag(z._internal[0])),N>
|
||||||
|
{
|
||||||
|
iVector<decltype(imag(z._internal[0])),N> ret;
|
||||||
|
for(int c1=0;c1<N;c1++){
|
||||||
|
ret._internal[c1] = imag(z._internal[c1]);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
95
lib/Grid_math_trace.h
Normal file
95
lib/Grid_math_trace.h
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
#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<int Level> inline ComplexF traceIndex(const ComplexF arg) { return arg;}
|
||||||
|
template<int Level> inline ComplexD traceIndex(const ComplexD arg) { return arg;}
|
||||||
|
template<int Level> inline RealF traceIndex(const RealF arg) { return arg;}
|
||||||
|
template<int Level> inline RealD traceIndex(const RealD arg) { return arg;}
|
||||||
|
|
||||||
|
template<class vtype,int N>
|
||||||
|
inline auto trace(const iMatrix<vtype,N> &arg) -> iScalar<decltype(trace(arg._internal[0][0]))>
|
||||||
|
{
|
||||||
|
iScalar<decltype( trace(arg._internal[0][0] )) > ret;
|
||||||
|
zeroit(ret._internal);
|
||||||
|
for(int i=0;i<N;i++){
|
||||||
|
ret._internal=ret._internal+trace(arg._internal[i][i]);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
template<class vtype>
|
||||||
|
inline auto trace(const iScalar<vtype> &arg) -> iScalar<decltype(trace(arg._internal))>
|
||||||
|
{
|
||||||
|
iScalar<decltype(trace(arg._internal))> ret;
|
||||||
|
ret._internal=trace(arg._internal);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Trace Specific indices.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/*
|
||||||
|
template<int Level,class vtype> inline
|
||||||
|
auto traceIndex(const iScalar<vtype> &arg) -> iScalar<decltype(traceIndex<Level>(arg._internal)) >
|
||||||
|
{
|
||||||
|
iScalar<decltype(traceIndex<Level>(arg._internal))> ret;
|
||||||
|
ret._internal = traceIndex<Level>(arg._internal);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
template<int Level,class vtype> inline auto
|
||||||
|
traceIndex (const iScalar<vtype> &arg) ->
|
||||||
|
typename
|
||||||
|
std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::notvalue,
|
||||||
|
iScalar<decltype(traceIndex<Level>(arg._internal))> >::type
|
||||||
|
|
||||||
|
{
|
||||||
|
iScalar<decltype(traceIndex<Level>(arg._internal))> ret;
|
||||||
|
ret._internal=traceIndex<Level>(arg._internal);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
template<int Level,class vtype> inline auto
|
||||||
|
traceIndex (const iScalar<vtype> &arg) ->
|
||||||
|
typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::value,
|
||||||
|
iScalar<vtype> >::type
|
||||||
|
{
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we hit the right index, return scalar and trace it with no further recursion
|
||||||
|
template<int Level,class vtype,int N> inline
|
||||||
|
auto traceIndex(const iMatrix<vtype,N> &arg) ->
|
||||||
|
typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::value, // Index matches
|
||||||
|
iScalar<vtype> >::type // return scalar
|
||||||
|
{
|
||||||
|
iScalar<vtype> ret;
|
||||||
|
zeroit(ret._internal);
|
||||||
|
for(int i=0;i<N;i++){
|
||||||
|
ret._internal = ret._internal + arg._internal[i][i];
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not this level, so recurse
|
||||||
|
template<int Level,class vtype,int N> inline
|
||||||
|
auto traceIndex(const iMatrix<vtype,N> &arg) ->
|
||||||
|
typename std::enable_if<matchGridTensorIndex<iMatrix<vtype,N>,Level>::notvalue,// No index match
|
||||||
|
iMatrix<decltype(traceIndex<Level>(arg._internal[0][0])),N> >::type // return matrix
|
||||||
|
{
|
||||||
|
iMatrix<decltype(traceIndex<Level>(arg._internal[0][0])),N> ret;
|
||||||
|
for(int i=0;i<N;i++){
|
||||||
|
for(int j=0;j<N;j++){
|
||||||
|
ret._internal[i][j] = traceIndex<Level>(arg._internal[i][j]);
|
||||||
|
}}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
101
lib/Grid_math_transpose.h
Normal file
101
lib/Grid_math_transpose.h
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
#ifndef GRID_MATH_TRANSPOSE_H
|
||||||
|
#define GRID_MATH_TRANSPOSE_H
|
||||||
|
namespace Grid {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// Transpose all indices
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline ComplexD transpose(ComplexD &rhs){ return rhs;}
|
||||||
|
inline ComplexF transpose(ComplexF &rhs){ return rhs;}
|
||||||
|
inline RealD transpose(RealD &rhs){ return rhs;}
|
||||||
|
inline RealF transpose(RealF &rhs){ return rhs;}
|
||||||
|
|
||||||
|
template<class vtype,int N>
|
||||||
|
inline typename std::enable_if<isGridTensor<vtype>::value, iMatrix<vtype,N> >::type
|
||||||
|
transpose(iMatrix<vtype,N> arg)
|
||||||
|
{
|
||||||
|
iMatrix<vtype,N> ret;
|
||||||
|
for(int i=0;i<N;i++){
|
||||||
|
for(int j=0;j<N;j++){
|
||||||
|
ret._internal[i][j] = transpose(arg._internal[j][i]); // NB recurses
|
||||||
|
}}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
template<class vtype,int N>
|
||||||
|
inline typename std::enable_if<isGridTensor<vtype>::notvalue, iMatrix<vtype,N> >::type
|
||||||
|
transpose(iMatrix<vtype,N> arg)
|
||||||
|
{
|
||||||
|
iMatrix<vtype,N> ret;
|
||||||
|
for(int i=0;i<N;i++){
|
||||||
|
for(int j=0;j<N;j++){
|
||||||
|
ret._internal[i][j] = arg._internal[j][i]; // Stop recursion if not a tensor type
|
||||||
|
}}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class vtype>
|
||||||
|
inline typename std::enable_if<isGridTensor<vtype>::value, iScalar<vtype> >::type
|
||||||
|
transpose(iScalar<vtype> arg)
|
||||||
|
{
|
||||||
|
iScalar<vtype> ret;
|
||||||
|
ret._internal = transpose(arg._internal); // NB recurses
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class vtype>
|
||||||
|
inline typename std::enable_if<isGridTensor<vtype>::notvalue, iScalar<vtype> >::type
|
||||||
|
transpose(iScalar<vtype> arg)
|
||||||
|
{
|
||||||
|
iScalar<vtype> ret;
|
||||||
|
ret._internal = arg._internal; // NB recursion stops
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Transpose a specific index; instructive to compare this style of recursion termination
|
||||||
|
// to that of adj; which is easiers?
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
template<int Level,class vtype,int N> inline
|
||||||
|
typename std::enable_if<matchGridTensorIndex<iMatrix<vtype,N>,Level>::value, iMatrix<vtype,N> >::type
|
||||||
|
transposeIndex (const iMatrix<vtype,N> &arg)
|
||||||
|
{
|
||||||
|
iMatrix<vtype,N> ret;
|
||||||
|
for(int i=0;i<N;i++){
|
||||||
|
for(int j=0;j<N;j++){
|
||||||
|
ret._internal[i][j] = arg._internal[j][i];
|
||||||
|
}}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
// or not
|
||||||
|
template<int Level,class vtype,int N> inline
|
||||||
|
typename std::enable_if<matchGridTensorIndex<iMatrix<vtype,N>,Level>::notvalue, iMatrix<vtype,N> >::type
|
||||||
|
transposeIndex (const iMatrix<vtype,N> &arg)
|
||||||
|
{
|
||||||
|
iMatrix<vtype,N> ret;
|
||||||
|
for(int i=0;i<N;i++){
|
||||||
|
for(int j=0;j<N;j++){
|
||||||
|
ret._internal[i][j] = transposeIndex<Level>(arg._internal[i][j]);
|
||||||
|
}}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
template<int Level,class vtype> inline
|
||||||
|
typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::notvalue, iScalar<vtype> >::type
|
||||||
|
transposeIndex (const iScalar<vtype> &arg)
|
||||||
|
{
|
||||||
|
iScalar<vtype> ret;
|
||||||
|
ret._internal=transposeIndex<Level>(arg._internal);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
template<int Level,class vtype> inline
|
||||||
|
typename std::enable_if<matchGridTensorIndex<iScalar<vtype>,Level>::value, iScalar<vtype> >::type
|
||||||
|
transposeIndex (const iScalar<vtype> &arg)
|
||||||
|
{
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user