mirror of
https://github.com/paboyle/Grid.git
synced 2024-11-10 07:55:35 +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_tensors.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
|
||||
|
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