1
0
mirror of https://github.com/paboyle/Grid.git synced 2024-11-09 23:45:36 +00:00

Changed EigenIO to use GridTypeMapper type traits

This commit is contained in:
Michael Marshall 2019-03-06 12:55:05 +00:00
parent 1880e6d12d
commit aa24f04911
3 changed files with 72 additions and 57 deletions

View File

@ -37,16 +37,16 @@ Author: Guido Cossu <guido.cossu@ed.ac.uk>
namespace Grid {
// TODO Support Grid::complex from GPU port
template<typename T> using Grid_complex = std::complex<T>;
//template<typename T> using Grid_complex = std::complex<T>;
// Returns original type, except for Grid_complex, where it returns the underlying type
template<typename T> struct RealType { using type = T; };
template<typename T> struct RealType<Grid_complex<T>> { using type = T; };
//template<typename T> struct RealType { using type = T; };
//template<typename T> struct RealType<Grid_complex<T>> { using type = T; };
namespace EigenIO {
template<typename T> struct is_complex : public std::false_type {};
template<typename T> struct is_complex<Grid_complex<T>>
: std::integral_constant<bool, std::is_arithmetic<T>::value> {};
//template<typename T> struct is_complex : public std::false_type {};
//template<typename T> struct is_complex<Grid_complex<T>>
//: std::integral_constant<bool, std::is_arithmetic<T>::value> {};
// Eigen tensors can be composed of arithmetic scalar and complex types
template<typename T> struct is_scalar : std::integral_constant<bool,
@ -54,11 +54,11 @@ namespace Grid {
// Eigen tensors can also be composed of a limited number of containers
// NB: grid tensors (iScalar, iVector, iMatrix) have stricter limits on complex types
template <typename T> struct is_container : public std::false_type {};
template <typename T> struct is_container<iScalar<T>> : public std::true_type {};
template <typename T, int N> struct is_container<iVector<T, N>> : public std::true_type {};
template <typename T, int N> struct is_container<iMatrix<T, N>> : public std::true_type {};
template <typename T, std::size_t N> struct is_container<std::array<T, N>> : public std::true_type {};
//template <typename T> struct is_container : public std::false_type {};
//template <typename T> struct is_container<iScalar<T>> : public std::true_type {};
//template <typename T, int N> struct is_container<iVector<T, N>> : public std::true_type {};
//template <typename T, int N> struct is_container<iMatrix<T, N>> : public std::true_type {};
//template <typename T, std::size_t N> struct is_container<std::array<T, N>> : public std::true_type {};
// Is this an Eigen tensor
template<typename T> struct is_tensor : std::integral_constant<bool,
@ -70,7 +70,7 @@ namespace Grid {
// Is this an Eigen tensor of a supported container
template<typename T, typename C = void> struct is_tensor_of_container : public std::false_type {};
template<typename T> struct is_tensor_of_container<T, typename std::enable_if<is_tensor<T>::value && is_container<typename T::Scalar>::value, void>::type> : public std::true_type {};
template<typename T> struct is_tensor_of_container<T, typename std::enable_if<is_tensor<T>::value && isGridTensor<typename T::Scalar>::value, void>::type> : public std::true_type {};
// Is this a fixed-size Eigen tensor
template<typename T> struct is_tensor_fixed : public std::false_type {};
@ -94,11 +94,11 @@ namespace Grid {
// EigenIO::Traits are not defined for Eigen tensors, but rather their top-level scalar
// This is because Eigen tensors have a dynamic size flavour, but the scalars are all fixed size
// This allows the traits to all be defined as constexpr
template <typename T, typename C = void> struct Traits {}; // C needed for specialisation
/*template <typename T, typename C = void> struct Traits {}; // C needed for specialisation
// This defines the bottom level - i.e. it's a description of the underlying scalar
template <typename T> struct Traits<T, typename std::enable_if<is_scalar<T>::value, void>::type> {
using scalar_type = T; // Type of the underlying scalar
using scalar_real = typename RealType<scalar_type>::type; // real type underlying scalar_type
using scalar_real = typename RealPart<scalar_type>::type; // real type underlying scalar_type
static constexpr unsigned int rank = 0; // The rank of the grid tensor (i.e. how many indices used)
//static constexpr unsigned int rank_non_trivial = 0; // As per rank, but excludes those of dimension 1
static constexpr unsigned int count = 1; // total number of elements (i.e. product of dimensions)
@ -121,7 +121,7 @@ namespace Grid {
};
template <typename T> struct Traits<iScalar<T>> {
using scalar_type = typename Traits<T>::scalar_type;
using scalar_real = typename RealType<scalar_type>::type;
using scalar_real = typename RealPart<scalar_type>::type;
static constexpr unsigned int rank = 1 + Traits<T>::rank;
//static constexpr unsigned int rank_non_trivial = 0 + Traits<T>::rank_non_trivial;
static constexpr unsigned int count = 1 * Traits<T>::count;
@ -134,7 +134,7 @@ namespace Grid {
};
template <typename T, int N> struct Traits<iVector<T, N>> {
using scalar_type = typename Traits<T>::scalar_type;
using scalar_real = typename RealType<scalar_type>::type;
using scalar_real = typename RealPart<scalar_type>::type;
static constexpr unsigned int rank = 1 + Traits<T>::rank;
//static constexpr unsigned int rank_non_trivial = (N>1 ? 1 : 0) + Traits<T>::rank_non_trivial;
static constexpr unsigned int count = N * Traits<T>::count;
@ -148,7 +148,7 @@ namespace Grid {
};
template <typename T, int N> struct Traits<iMatrix<T, N>> {
using scalar_type = typename Traits<T>::scalar_type;
using scalar_real = typename RealType<scalar_type>::type;
using scalar_real = typename RealPart<scalar_type>::type;
static constexpr unsigned int rank = 2 + Traits<T>::rank;
//static constexpr unsigned int rank_non_trivial = (N>1 ? 2 : 0) + Traits<T>::rank_non_trivial;
static constexpr unsigned int count = N * N * Traits<T>::count;
@ -160,7 +160,7 @@ namespace Grid {
//return ( N == 1 ) ? Traits<T>::DimensionNT(dim) : ( dim == 0 || dim == 1 ) ? N : Traits<T>::DimensionNT(dim - 2);
//}
};
template <typename T, int N> struct Traits<std::array<T, N>> : Traits<iVector<T, N>> {};
template <typename T, int N> struct Traits<std::array<T, N>> : Traits<iVector<T, N>> {};*/
}
// Abstract writer/reader classes ////////////////////////////////////////////
@ -195,14 +195,14 @@ namespace Grid {
// Helper functions for Scalar vs Container specialisations
template <typename ETensor>
inline typename std::enable_if<EigenIO::is_tensor_of_scalar<ETensor>::value, const typename EigenIO::Traits<typename ETensor::Scalar>::scalar_type *>::type
inline typename std::enable_if<EigenIO::is_tensor_of_scalar<ETensor>::value, const typename GridTypeMapper<typename ETensor::Scalar>::scalar_type *>::type
getFirstScalar(const ETensor &output)
{
return output.data();
}
template <typename ETensor>
inline typename std::enable_if<EigenIO::is_tensor_of_container<ETensor>::value, const typename EigenIO::Traits<typename ETensor::Scalar>::scalar_type *>::type
inline typename std::enable_if<EigenIO::is_tensor_of_container<ETensor>::value, const typename GridTypeMapper<typename ETensor::Scalar>::scalar_type *>::type
getFirstScalar(const ETensor &output)
{
return output.data()->begin();
@ -210,16 +210,16 @@ namespace Grid {
template <typename S>
inline typename std::enable_if<EigenIO::is_scalar<S>::value, void>::type
copyScalars(typename EigenIO::Traits<S>::scalar_type * &pCopy, const S &Source)
copyScalars(typename GridTypeMapper<S>::scalar_type * &pCopy, const S &Source)
{
* pCopy ++ = Source;
}
template <typename S>
inline typename std::enable_if<EigenIO::is_container<S>::value, void>::type
copyScalars(typename EigenIO::Traits<S>::scalar_type * &pCopy, const S &Source)
inline typename std::enable_if<isGridTensor<S>::value, void>::type
copyScalars(typename GridTypeMapper<S>::scalar_type * &pCopy, const S &Source)
{
for( const typename EigenIO::Traits<S>::scalar_type &item : Source )
for( const typename GridTypeMapper<S>::scalar_type &item : Source )
* pCopy ++ = item;
}
@ -268,16 +268,16 @@ namespace Grid {
// Helper functions for Scalar vs Container specialisations
template <typename S>
inline typename std::enable_if<EigenIO::is_scalar<S>::value, void>::type
copyScalars(S &Dest, const typename EigenIO::Traits<S>::scalar_type * &pSource)
copyScalars(S &Dest, const typename GridTypeMapper<S>::scalar_type * &pSource)
{
Dest = * pSource ++;
}
template <typename S>
inline typename std::enable_if<EigenIO::is_container<S>::value, void>::type
copyScalars(S &Dest, const typename EigenIO::Traits<S>::scalar_type * &pSource)
inline typename std::enable_if<isGridTensor<S>::value, void>::type
copyScalars(S &Dest, const typename GridTypeMapper<S>::scalar_type * &pSource)
{
for( typename EigenIO::Traits<S>::scalar_type &item : Dest )
for( typename GridTypeMapper<S>::scalar_type &item : Dest )
item = * pSource ++;
}
@ -362,10 +362,10 @@ namespace Grid {
{
using Index = typename ETensor::Index;
using Container = typename ETensor::Scalar; // NB: could be same as scalar
using Traits = EigenIO::Traits<Container>;
using Traits = GridTypeMapper<Container>;
using Scalar = typename Traits::scalar_type; // type of the underlying scalar
constexpr unsigned int TensorRank{ETensor::NumIndices};
constexpr unsigned int ContainerRank{Traits::rank}; // Only non-zero for containers
constexpr unsigned int ContainerRank{Traits::Rank}; // Only non-zero for containers
constexpr unsigned int TotalRank{TensorRank + ContainerRank};
const Index NumElements{output.size()};
assert( NumElements > 0 );
@ -513,10 +513,10 @@ namespace Grid {
{
using Index = typename ETensor::Index;
using Container = typename ETensor::Scalar; // NB: could be same as scalar
using Traits = EigenIO::Traits<Container>;
using Traits = GridTypeMapper<Container>;
using Scalar = typename Traits::scalar_type; // type of the underlying scalar
constexpr unsigned int TensorRank{ETensor::NumIndices};
constexpr unsigned int ContainerRank{Traits::rank}; // Only non-zero for containers
constexpr unsigned int ContainerRank{Traits::Rank}; // Only non-zero for containers
constexpr unsigned int TotalRank{TensorRank + ContainerRank};
using ETDims = std::array<Index, TensorRank>; // Dimensions of the tensor

View File

@ -27,6 +27,7 @@
/* END LEGAL */
#ifndef GRID_UTIL_EIGEN_H
#define GRID_UTIL_EIGEN_H
#include <Grid/tensors/Tensor_traits.h>
#include <Grid/Eigen/unsupported/CXX11/Tensor>
namespace Grid {
@ -34,7 +35,7 @@ namespace Grid {
template <typename ETensor, typename Lambda>
typename std::enable_if<EigenIO::is_tensor_of_scalar<ETensor>::value, void>::type
for_all_do_lambda( Lambda lambda, typename ETensor::Scalar &scalar, typename ETensor::Index &Seq,
std::array<std::size_t, ETensor::NumIndices + EigenIO::Traits<typename ETensor::Scalar>::rank> &MyIndex)
std::array<std::size_t, ETensor::NumIndices + GridTypeMapper<typename ETensor::Scalar>::Rank> &MyIndex)
{
lambda( scalar, Seq++, MyIndex );
}
@ -43,11 +44,11 @@ namespace Grid {
template <typename ETensor, typename Lambda>
typename std::enable_if<EigenIO::is_tensor_of_container<ETensor>::value, void>::type
for_all_do_lambda( Lambda lambda, typename ETensor::Scalar &container, typename ETensor::Index &Seq,
std::array<std::size_t, ETensor::NumIndices + EigenIO::Traits<typename ETensor::Scalar>::rank> &MyIndex)
std::array<std::size_t, ETensor::NumIndices + GridTypeMapper<typename ETensor::Scalar>::Rank> &MyIndex)
{
using Traits = EigenIO::Traits<typename ETensor::Scalar>;
using Traits = GridTypeMapper<typename ETensor::Scalar>;
const auto rank{ETensor::NumIndices};
const auto InnerRank = Traits::rank;
const auto InnerRank = Traits::Rank;
for( typename Traits::scalar_type &Source : container ) {
lambda(Source, Seq++, MyIndex );
// Now increment SubIndex
@ -68,7 +69,7 @@ namespace Grid {
assert( NumScalars > 0 );
using Index = typename ETensor::Index;
Index ScalarElementCount{1};
const auto InnerRank = EigenIO::Traits<Scalar>::rank;
const auto InnerRank = GridTypeMapper<Scalar>::Rank;
const auto rank{ETensor::NumIndices};
std::array<std::size_t, rank + InnerRank> Dims;
for(auto i = 0; i < rank; i++ ) {
@ -83,14 +84,14 @@ namespace Grid {
// If the Scalar is actually a container, add the inner Scalar's dimensions
size_t InnerScalarCount{1};
for(auto i = 0; i < InnerRank; i++ ) {
auto dim = EigenIO::Traits<Scalar>::Dimension(i);
auto dim = GridTypeMapper<Scalar>::Dimension(i);
assert( dim > 0 );
Dims[rank + i] = static_cast<std::size_t>(dim);
assert( Dims[rank + i] == dim ); // check we didn't lose anything in the conversion
InnerScalarCount *= dim;
}
assert(EigenIO::Traits<Scalar>::count == InnerScalarCount);
assert(EigenIO::Traits<Scalar>::size == sizeof( Scalar ));
assert(GridTypeMapper<Scalar>::count == InnerScalarCount);
assert(GridTypeMapper<Scalar>::size == sizeof( Scalar ));
std::array<std::size_t, rank + InnerRank> MyIndex;
for( auto &idx : MyIndex ) idx = 0;
Index Seq = 0;
@ -118,13 +119,13 @@ namespace Grid {
// Sequential initialisation of tensors
// Would have preferred to define template variables for this, but that's c++ 17
template <typename ETensor>
typename std::enable_if<EigenIO::is_tensor<ETensor>::value && !EigenIO::is_complex<typename EigenIO::Traits<typename ETensor::Scalar>::scalar_type>::value, void>::type
SequentialInit( ETensor &ET, typename EigenIO::Traits<typename ETensor::Scalar>::scalar_type Inc = 1,
typename std::enable_if<EigenIO::is_tensor<ETensor>::value && !is_complex<typename GridTypeMapper<typename ETensor::Scalar>::scalar_type>::value, void>::type
SequentialInit( ETensor &ET, typename GridTypeMapper<typename ETensor::Scalar>::scalar_type Inc = 1,
unsigned short Precision = 0 )
{
using Traits = EigenIO::Traits<typename ETensor::Scalar>;
using Traits = GridTypeMapper<typename ETensor::Scalar>;
using scalar_type = typename Traits::scalar_type;
for_all( ET, [&](scalar_type &c, typename ETensor::Index n, const std::array<size_t, ETensor::NumIndices + Traits::rank> &Dims ) {
for_all( ET, [&](scalar_type &c, typename ETensor::Index n, const std::array<size_t, ETensor::NumIndices + Traits::Rank> &Dims ) {
scalar_type x = Inc * static_cast<scalar_type>(n);
if( Precision ) {
std::stringstream s;
@ -136,13 +137,13 @@ namespace Grid {
}
template <typename ETensor>
typename std::enable_if<EigenIO::is_tensor<ETensor>::value && EigenIO::is_complex<typename EigenIO::Traits<typename ETensor::Scalar>::scalar_type>::value, void>::type
SequentialInit( ETensor &ET, typename EigenIO::Traits<typename ETensor::Scalar>::scalar_type Inc={1,-1},
typename std::enable_if<EigenIO::is_tensor<ETensor>::value && is_complex<typename GridTypeMapper<typename ETensor::Scalar>::scalar_type>::value, void>::type
SequentialInit( ETensor &ET, typename GridTypeMapper<typename ETensor::Scalar>::scalar_type Inc={1,-1},
unsigned short Precision = 0 )
{
using Traits = EigenIO::Traits<typename ETensor::Scalar>;
using Traits = GridTypeMapper<typename ETensor::Scalar>;
using scalar_type = typename Traits::scalar_type;
for_all( ET, [&](scalar_type &c, typename ETensor::Index n, const std::array<size_t, ETensor::NumIndices + Traits::rank> &Dims ) {
for_all( ET, [&](scalar_type &c, typename ETensor::Index n, const std::array<size_t, ETensor::NumIndices + Traits::Rank> &Dims ) {
auto re = Inc.real();
auto im = Inc.imag();
re *= n;
@ -166,7 +167,7 @@ namespace Grid {
typename std::enable_if<EigenIO::is_tensor<T>::value, void>::type
dump_tensor_func(T &t, const char * pName = nullptr)
{
using Traits = typename EigenIO::Traits<typename T::Scalar>;
using Traits = GridTypeMapper<typename T::Scalar>;
const auto rank{T::NumIndices};
const auto &dims = t.dimensions();
std::cout << "Dumping rank " << rank << ((T::Options & Eigen::RowMajor) ? ", row" : ", column") << "-major tensor ";
@ -174,7 +175,7 @@ namespace Grid {
std::cout << pName;
for( auto i = 0 ; i < rank; i++ ) std::cout << "[" << dims[i] << "]";
std::cout << " in memory order:" << std::endl;
for_all( t, [&](typename Traits::scalar_type &c, typename T::Index index, const std::array<size_t, T::NumIndices + Traits::rank> &Dims ){
for_all( t, [&](typename Traits::scalar_type &c, typename T::Index index, const std::array<size_t, T::NumIndices + Traits::Rank> &Dims ){
std::cout << " ";
for( auto dim : Dims )
std::cout << "[" << dim << "]";

View File

@ -109,16 +109,16 @@ void ioTest(const std::string &filename, const O &object, const std::string &nam
std::cout << " done." << std::endl;
}
typedef std::complex<double> TestScalar;
typedef Eigen::TensorFixedSize<unsigned short, Eigen::Sizes<5,4,3,2,1>> TensorRank5UShort;
typedef Eigen::TensorFixedSize<unsigned short, Eigen::Sizes<5,4,3,2,1>, Eigen::StorageOptions::RowMajor> TensorRank5UShortAlt;
typedef ComplexD TestScalar;
typedef Eigen::TensorFixedSize<Integer, Eigen::Sizes<5,4,3,2,1>> TensorRank5UShort;
typedef Eigen::TensorFixedSize<Integer, Eigen::Sizes<5,4,3,2,1>, Eigen::StorageOptions::RowMajor> TensorRank5UShortAlt;
typedef Eigen::Tensor<TestScalar, 3, Eigen::StorageOptions::RowMajor> TensorRank3;
typedef Eigen::TensorFixedSize<TestScalar, Eigen::Sizes<9,4,2>, Eigen::StorageOptions::RowMajor> Tensor_9_4_2;
typedef std::vector<Tensor_9_4_2> aTensor_9_4_2;
typedef Eigen::TensorFixedSize<SpinColourVector, Eigen::Sizes<6,5>> LSCTensor;
class PerambIOTestClass: Serializable {
Grid_complex<double> Flag;
ComplexD Flag;
public:
using PerambTensor = Eigen::Tensor<SpinColourVector, 6, Eigen::StorageOptions::RowMajor>;
GRID_SERIALIZABLE_CLASS_MEMBERS(PerambIOTestClass
@ -157,11 +157,11 @@ public:
#define TEST_PARAMS( T ) #T, Flag, Precision, filename, pszExtension, TestNum
template <typename WTR_, typename RDR_, typename T, typename... IndexTypes>
void EigenTensorTestSingle(const char * MyTypeName, typename EigenIO::Traits<typename T::Scalar>::scalar_type Flag,
void EigenTensorTestSingle(const char * MyTypeName, typename GridTypeMapper<typename T::Scalar>::scalar_type Flag,
unsigned short Precision, std::string &filename, const char * pszExtension, unsigned int &TestNum,
IndexTypes... otherDims)
{
using Traits = EigenIO::Traits<typename T::Scalar>;
using Traits = GridTypeMapper<typename T::Scalar>;
using scalar_type = typename Traits::scalar_type;
std::unique_ptr<T> pTensor{new T(otherDims...)};
SequentialInit( * pTensor, Flag, Precision );
@ -176,7 +176,7 @@ void EigenTensorTest(const char * pszExtension, unsigned short Precision = 0)
std::string filename;
{
int Flag = 7;
using TensorSingle = Eigen::TensorFixedSize<int, Eigen::Sizes<1>>;
using TensorSingle = Eigen::TensorFixedSize<Integer, Eigen::Sizes<1>>;
EigenTensorTestSingle<WTR_, RDR_, TensorSingle>(TEST_PARAMS( TensorSingle ));
}
TestScalar Flag{1,-3.1415927};
@ -240,6 +240,20 @@ void tensorConvTestFn(GridSerialRNG &rng, const std::string label)
int main(int argc,char **argv)
{
{
LSCTensor Bingo;
constexpr Complex Flag{1,-3.1415927};
Complex z{0};
SpinColourVector * pV = Bingo.data();
for( std::size_t i = Bingo.size(); i--; ) {
for( typename GridTypeMapper<SpinColourVector>::scalar_type &s : *pV++ ) {
s = z;
z += Flag;
}
}
dump_tensor( Bingo );
}
Grid_init(&argc,&argv);
std::cout << std::boolalpha << "==== basic IO" << std::endl; // display true / false for boolean