1
0
mirror of https://github.com/paboyle/Grid.git synced 2025-04-09 21:50:45 +01:00

Recommendations for Traits classes

This commit is contained in:
Michael Marshall 2019-02-28 20:06:59 +00:00
parent 9b6ddb6e54
commit b7db99967a
3 changed files with 201 additions and 113 deletions

View File

@ -89,17 +89,25 @@ template <typename Condition, typename ReturnType> using NotEnableIf = Invoke<st
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
// Check for complexity with type traits // Check for complexity with type traits
template <typename T> struct is_complex : public std::false_type {}; template <typename T> struct is_complex : public std::false_type {};
template <> struct is_complex<std::complex<double> > : public std::true_type {}; template <> struct is_complex<ComplexD> : public std::true_type {};
template <> struct is_complex<std::complex<float> > : public std::true_type {}; template <> struct is_complex<ComplexF> : public std::true_type {};
template <typename T> using IfReal = Invoke<std::enable_if<std::is_floating_point<T>::value, int> >; template<typename T, typename V=void> struct is_real : public std::false_type {};
template<typename T> struct is_real<T, typename std::enable_if<std::is_floating_point<T>::value,
void>::type> : public std::true_type {};
template<typename T, typename V=void> struct is_integer : public std::false_type {};
template<typename T> struct is_integer<T, typename std::enable_if<std::is_integral<T>::value,
void>::type> : public std::true_type {};
template <typename T> using IfReal = Invoke<std::enable_if<is_real<T>::value, int> >;
template <typename T> using IfComplex = Invoke<std::enable_if<is_complex<T>::value, int> >; template <typename T> using IfComplex = Invoke<std::enable_if<is_complex<T>::value, int> >;
template <typename T> using IfInteger = Invoke<std::enable_if<std::is_integral<T>::value, int> >; template <typename T> using IfInteger = Invoke<std::enable_if<is_integer<T>::value, int> >;
template <typename T1,typename T2> using IfSame = Invoke<std::enable_if<std::is_same<T1,T2>::value, int> >; template <typename T1,typename T2> using IfSame = Invoke<std::enable_if<std::is_same<T1,T2>::value, int> >;
template <typename T> using IfNotReal = Invoke<std::enable_if<!std::is_floating_point<T>::value, int> >; template <typename T> using IfNotReal = Invoke<std::enable_if<!is_real<T>::value, int> >;
template <typename T> using IfNotComplex = Invoke<std::enable_if<!is_complex<T>::value, int> >; template <typename T> using IfNotComplex = Invoke<std::enable_if<!is_complex<T>::value, int> >;
template <typename T> using IfNotInteger = Invoke<std::enable_if<!std::is_integral<T>::value, int> >; template <typename T> using IfNotInteger = Invoke<std::enable_if<!is_integer<T>::value, int> >;
template <typename T1,typename T2> using IfNotSame = Invoke<std::enable_if<!std::is_same<T1,T2>::value, int> >; template <typename T1,typename T2> using IfNotSame = Invoke<std::enable_if<!std::is_same<T1,T2>::value, int> >;
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////

View File

@ -62,7 +62,7 @@ class iScalar {
// get double precision version // get double precision version
typedef iScalar<typename GridTypeMapper<vtype>::DoublePrecision> DoublePrecision; typedef iScalar<typename GridTypeMapper<vtype>::DoublePrecision> DoublePrecision;
enum { TensorLevel = GridTypeMapper<vtype>::TensorLevel + 1 }; static constexpr int TensorLevel = GridTypeMapper<vtype>::TensorLevel + 1;
// Scalar no action // Scalar no action
// template<int Level> using tensor_reduce_level = typename // template<int Level> using tensor_reduce_level = typename
@ -173,7 +173,37 @@ class iScalar {
return stream; return stream;
}; };
template <typename T = vtype>
typename std::enable_if<!isGridTensor<T>::value, const scalar_type *>::type
strong_inline begin() const { return &_internal; }
template <typename T = vtype>
typename std::enable_if<isGridTensor<T>::value, const scalar_type *>::type
strong_inline begin() const { return _internal.begin(); }
template <typename T = vtype>
typename std::enable_if<!isGridTensor<T>::value, const scalar_type *>::type
strong_inline end() const { return (&_internal) + 1; }
template <typename T = vtype>
typename std::enable_if<isGridTensor<T>::value, const scalar_type *>::type
strong_inline end() const { return _internal.begin() + sizeof(_internal)/sizeof(scalar_type); }
template <typename T = vtype>
typename std::enable_if<!isGridTensor<T>::value, scalar_type *>::type
strong_inline begin() { return &_internal; }
template <typename T = vtype>
typename std::enable_if<isGridTensor<T>::value, scalar_type *>::type
strong_inline begin() { return _internal.begin(); }
template <typename T = vtype>
typename std::enable_if<!isGridTensor<T>::value, scalar_type *>::type
strong_inline end() { return (&_internal) + 1; }
template <typename T = vtype>
typename std::enable_if<isGridTensor<T>::value, scalar_type *>::type
strong_inline end() { return _internal.begin() + sizeof(_internal)/sizeof(scalar_type); }
}; };
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
// Allows to turn scalar<scalar<scalar<double>>>> back to double. // Allows to turn scalar<scalar<scalar<double>>>> back to double.
@ -218,7 +248,7 @@ class iVector {
return *this; return *this;
} }
enum { TensorLevel = GridTypeMapper<vtype>::TensorLevel + 1 }; static constexpr int TensorLevel = GridTypeMapper<vtype>::TensorLevel + 1;
iVector(const Zero &z) { *this = zero; }; iVector(const Zero &z) { *this = zero; };
iVector() = default; iVector() = default;
/* /*
@ -303,6 +333,38 @@ class iVector {
// strong_inline vtype && operator ()(int i) { // strong_inline vtype && operator ()(int i) {
// return _internal[i]; // return _internal[i];
// } // }
template <typename T = vtype>
typename std::enable_if<!isGridTensor<T>::value, const scalar_type *>::type
strong_inline begin() const { return _internal; }
template <typename T = vtype>
typename std::enable_if<isGridTensor<T>::value, const scalar_type *>::type
strong_inline begin() const { return _internal[0].begin(); }
template <typename T = vtype>
typename std::enable_if<!isGridTensor<T>::value, const scalar_type *>::type
strong_inline end() const { return _internal + N; }
template <typename T = vtype>
typename std::enable_if<isGridTensor<T>::value, const scalar_type *>::type
strong_inline end() const { return _internal[0].begin() + sizeof(_internal)/sizeof(scalar_type); }
template <typename T = vtype>
typename std::enable_if<!isGridTensor<T>::value, scalar_type *>::type
strong_inline begin() { return _internal; }
template <typename T = vtype>
typename std::enable_if<isGridTensor<T>::value, scalar_type *>::type
strong_inline begin() { return _internal[0].begin(); }
template <typename T = vtype>
typename std::enable_if<!isGridTensor<T>::value, scalar_type *>::type
strong_inline end() { return _internal + N; }
template <typename T = vtype>
typename std::enable_if<isGridTensor<T>::value, scalar_type *>::type
strong_inline end() { return _internal[0].begin() + sizeof(_internal)/sizeof(scalar_type); }
}; };
template <class vtype, int N> template <class vtype, int N>
@ -328,7 +390,7 @@ class iMatrix {
typedef iScalar<tensor_reduced_v> tensor_reduced; typedef iScalar<tensor_reduced_v> tensor_reduced;
typedef iMatrix<recurse_scalar_object, N> scalar_object; typedef iMatrix<recurse_scalar_object, N> scalar_object;
enum { TensorLevel = GridTypeMapper<vtype>::TensorLevel + 1 }; static constexpr int TensorLevel = GridTypeMapper<vtype>::TensorLevel + 1;
iMatrix(const Zero &z) { *this = zero; }; iMatrix(const Zero &z) { *this = zero; };
iMatrix() = default; iMatrix() = default;
@ -458,6 +520,38 @@ class iMatrix {
// strong_inline vtype && operator ()(int i,int j) { // strong_inline vtype && operator ()(int i,int j) {
// return _internal[i][j]; // return _internal[i][j];
// } // }
template <typename T = vtype>
typename std::enable_if<!isGridTensor<T>::value, const scalar_type *>::type
strong_inline begin() const { return _internal[0]; }
template <typename T = vtype>
typename std::enable_if<isGridTensor<T>::value, const scalar_type *>::type
strong_inline begin() const { return _internal[0][0].begin(); }
template <typename T = vtype>
typename std::enable_if<!isGridTensor<T>::value, const scalar_type *>::type
strong_inline end() const { return _internal[0] + N * N; }
template <typename T = vtype>
typename std::enable_if<isGridTensor<T>::value, const scalar_type *>::type
strong_inline end() const { return _internal[0][0].begin() + sizeof(_internal)/sizeof(scalar_type); }
template <typename T = vtype>
typename std::enable_if<!isGridTensor<T>::value, scalar_type *>::type
strong_inline begin() { return _internal[0]; }
template <typename T = vtype>
typename std::enable_if<isGridTensor<T>::value, scalar_type *>::type
strong_inline begin() { return _internal[0][0].begin(); }
template <typename T = vtype>
typename std::enable_if<!isGridTensor<T>::value, scalar_type *>::type
strong_inline end() { return _internal[0] + N * N; }
template <typename T = vtype>
typename std::enable_if<isGridTensor<T>::value, scalar_type *>::type
strong_inline end() { return _internal[0][0].begin() + sizeof(_internal)/sizeof(scalar_type); }
}; };
template <class v> template <class v>

View File

@ -26,6 +26,21 @@ Author: Christopher Kelly <ckelly@phys.columbia.edu>
namespace Grid { namespace Grid {
// Forward declarations
template<class T> class iScalar;
template<class T, int N> class iVector;
template<class T, int N> class iMatrix;
// These are the Grid tensors
template<typename T> struct isGridTensor
: public std::false_type { static constexpr bool notvalue = true; };
template<class T> struct isGridTensor<iScalar<T>>
: public std::true_type { static constexpr bool notvalue = false; };
template<class T, int N> struct isGridTensor<iVector<T, N>>
: public std::true_type { static constexpr bool notvalue = false; };
template<class T, int N> struct isGridTensor<iMatrix<T, N>>
: public std::true_type { static constexpr bool notvalue = false; };
////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////
// Want to recurse: GridTypeMapper<Matrix<vComplexD> >::scalar_type == ComplexD. // Want to recurse: GridTypeMapper<Matrix<vComplexD> >::scalar_type == ComplexD.
// Use of a helper class like this allows us to template specialise and "dress" // Use of a helper class like this allows us to template specialise and "dress"
@ -40,25 +55,31 @@ namespace Grid {
// to study C++11's type_traits.h file. (std::enable_if<isGridTensorType<vtype> >) // to study C++11's type_traits.h file. (std::enable_if<isGridTensorType<vtype> >)
// //
////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////
template <class T> class GridTypeMapper { // This saves repeating common properties for supported Grid Scalar types
public: template<typename T, typename V=void> struct GridTypeMapper_Base {};
typedef typename T::scalar_type scalar_type; // TensorLevel How many nested grid tensors
typedef typename T::vector_type vector_type; // Rank Rank of the grid tensor
typedef typename T::vector_typeD vector_typeD; // count Total number of elements, i.e. product of dimensions
typedef typename T::tensor_reduced tensor_reduced; // scalar_size Size of the underlying fundamental object (tensor_reduced) in bytes
typedef typename T::scalar_object scalar_object; // size Total size of all elements in bytes
typedef typename T::Complexified Complexified; // Dimension(dim) Size of dimension dim
typedef typename T::Realified Realified; template<typename T> struct GridTypeMapper_Base<T> {
typedef typename T::DoublePrecision DoublePrecision; static constexpr int TensorLevel = 0;
enum { TensorLevel = T::TensorLevel }; static constexpr int Rank = 0;
static constexpr std::size_t count = 1;
static constexpr std::size_t scalar_size = sizeof(T);
static constexpr std::size_t size = scalar_size * count;
static constexpr int Dimension(unsigned int dim) { return 0; }
}; };
////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////
// Recursion stops with these template specialisations // Recursion stops with these template specialisations
////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////
template<> class GridTypeMapper<RealF> {
public: template<typename T> struct GridTypeMapper {};
template<> struct GridTypeMapper<RealF> : public GridTypeMapper_Base<RealF> {
typedef RealF scalar_type; typedef RealF scalar_type;
typedef RealF vector_type; typedef RealF vector_type;
typedef RealD vector_typeD; typedef RealD vector_typeD;
@ -67,10 +88,8 @@ namespace Grid {
typedef ComplexF Complexified; typedef ComplexF Complexified;
typedef RealF Realified; typedef RealF Realified;
typedef RealD DoublePrecision; typedef RealD DoublePrecision;
enum { TensorLevel = 0 };
}; };
template<> class GridTypeMapper<RealD> { template<> struct GridTypeMapper<RealD> : public GridTypeMapper_Base<RealD> {
public:
typedef RealD scalar_type; typedef RealD scalar_type;
typedef RealD vector_type; typedef RealD vector_type;
typedef RealD vector_typeD; typedef RealD vector_typeD;
@ -79,10 +98,8 @@ namespace Grid {
typedef ComplexD Complexified; typedef ComplexD Complexified;
typedef RealD Realified; typedef RealD Realified;
typedef RealD DoublePrecision; typedef RealD DoublePrecision;
enum { TensorLevel = 0 };
}; };
template<> class GridTypeMapper<ComplexF> { template<> struct GridTypeMapper<ComplexF> : public GridTypeMapper_Base<ComplexF> {
public:
typedef ComplexF scalar_type; typedef ComplexF scalar_type;
typedef ComplexF vector_type; typedef ComplexF vector_type;
typedef ComplexD vector_typeD; typedef ComplexD vector_typeD;
@ -91,10 +108,8 @@ namespace Grid {
typedef ComplexF Complexified; typedef ComplexF Complexified;
typedef RealF Realified; typedef RealF Realified;
typedef ComplexD DoublePrecision; typedef ComplexD DoublePrecision;
enum { TensorLevel = 0 };
}; };
template<> class GridTypeMapper<ComplexD> { template<> struct GridTypeMapper<ComplexD> : public GridTypeMapper_Base<ComplexD> {
public:
typedef ComplexD scalar_type; typedef ComplexD scalar_type;
typedef ComplexD vector_type; typedef ComplexD vector_type;
typedef ComplexD vector_typeD; typedef ComplexD vector_typeD;
@ -103,10 +118,8 @@ namespace Grid {
typedef ComplexD Complexified; typedef ComplexD Complexified;
typedef RealD Realified; typedef RealD Realified;
typedef ComplexD DoublePrecision; typedef ComplexD DoublePrecision;
enum { TensorLevel = 0 };
}; };
template<> class GridTypeMapper<Integer> { template<> struct GridTypeMapper<Integer> : public GridTypeMapper_Base<Integer> {
public:
typedef Integer scalar_type; typedef Integer scalar_type;
typedef Integer vector_type; typedef Integer vector_type;
typedef Integer vector_typeD; typedef Integer vector_typeD;
@ -115,11 +128,9 @@ namespace Grid {
typedef void Complexified; typedef void Complexified;
typedef void Realified; typedef void Realified;
typedef void DoublePrecision; typedef void DoublePrecision;
enum { TensorLevel = 0 };
}; };
template<> class GridTypeMapper<vRealF> { template<> struct GridTypeMapper<vRealF> : public GridTypeMapper_Base<vRealF> {
public:
typedef RealF scalar_type; typedef RealF scalar_type;
typedef vRealF vector_type; typedef vRealF vector_type;
typedef vRealD vector_typeD; typedef vRealD vector_typeD;
@ -128,10 +139,8 @@ namespace Grid {
typedef vComplexF Complexified; typedef vComplexF Complexified;
typedef vRealF Realified; typedef vRealF Realified;
typedef vRealD DoublePrecision; typedef vRealD DoublePrecision;
enum { TensorLevel = 0 };
}; };
template<> class GridTypeMapper<vRealD> { template<> struct GridTypeMapper<vRealD> : public GridTypeMapper_Base<vRealD> {
public:
typedef RealD scalar_type; typedef RealD scalar_type;
typedef vRealD vector_type; typedef vRealD vector_type;
typedef vRealD vector_typeD; typedef vRealD vector_typeD;
@ -140,10 +149,8 @@ namespace Grid {
typedef vComplexD Complexified; typedef vComplexD Complexified;
typedef vRealD Realified; typedef vRealD Realified;
typedef vRealD DoublePrecision; typedef vRealD DoublePrecision;
enum { TensorLevel = 0 };
}; };
template<> class GridTypeMapper<vComplexH> { template<> struct GridTypeMapper<vComplexH> : public GridTypeMapper_Base<vComplexH> {
public:
typedef ComplexF scalar_type; typedef ComplexF scalar_type;
typedef vComplexH vector_type; typedef vComplexH vector_type;
typedef vComplexD vector_typeD; typedef vComplexD vector_typeD;
@ -152,10 +159,8 @@ namespace Grid {
typedef vComplexH Complexified; typedef vComplexH Complexified;
typedef vRealH Realified; typedef vRealH Realified;
typedef vComplexD DoublePrecision; typedef vComplexD DoublePrecision;
enum { TensorLevel = 0 };
}; };
template<> class GridTypeMapper<vComplexF> { template<> struct GridTypeMapper<vComplexF> : public GridTypeMapper_Base<vComplexF> {
public:
typedef ComplexF scalar_type; typedef ComplexF scalar_type;
typedef vComplexF vector_type; typedef vComplexF vector_type;
typedef vComplexD vector_typeD; typedef vComplexD vector_typeD;
@ -164,10 +169,8 @@ namespace Grid {
typedef vComplexF Complexified; typedef vComplexF Complexified;
typedef vRealF Realified; typedef vRealF Realified;
typedef vComplexD DoublePrecision; typedef vComplexD DoublePrecision;
enum { TensorLevel = 0 };
}; };
template<> class GridTypeMapper<vComplexD> { template<> struct GridTypeMapper<vComplexD> : public GridTypeMapper_Base<vComplexD> {
public:
typedef ComplexD scalar_type; typedef ComplexD scalar_type;
typedef vComplexD vector_type; typedef vComplexD vector_type;
typedef vComplexD vector_typeD; typedef vComplexD vector_typeD;
@ -176,10 +179,8 @@ namespace Grid {
typedef vComplexD Complexified; typedef vComplexD Complexified;
typedef vRealD Realified; typedef vRealD Realified;
typedef vComplexD DoublePrecision; typedef vComplexD DoublePrecision;
enum { TensorLevel = 0 };
}; };
template<> class GridTypeMapper<vInteger> { template<> struct GridTypeMapper<vInteger> : public GridTypeMapper_Base<vInteger> {
public:
typedef Integer scalar_type; typedef Integer scalar_type;
typedef vInteger vector_type; typedef vInteger vector_type;
typedef vInteger vector_typeD; typedef vInteger vector_typeD;
@ -188,57 +189,49 @@ namespace Grid {
typedef void Complexified; typedef void Complexified;
typedef void Realified; typedef void Realified;
typedef void DoublePrecision; typedef void DoublePrecision;
enum { TensorLevel = 0 };
}; };
// First some of my own traits #define GridTypeMapper_RepeatedTypes \
template<typename T> struct isGridTensor { typedef typename ObjectTraits::scalar_type scalar_type; \
static const bool value = true; typedef typename ObjectTraits::vector_type vector_type; \
static const bool notvalue = false; typedef typename ObjectTraits::vector_typeD vector_typeD; \
typedef typename ObjectTraits::tensor_reduced tensor_reduced; \
typedef typename ObjectTraits::scalar_object scalar_object; \
typedef typename ObjectTraits::Complexified Complexified; \
typedef typename ObjectTraits::Realified Realified; \
typedef typename ObjectTraits::DoublePrecision DoublePrecision; \
static constexpr int TensorLevel = BaseTraits::TensorLevel + 1; \
static constexpr std::size_t scalar_size = BaseTraits::scalar_size; \
static constexpr std::size_t size = scalar_size * count
template<typename T> struct GridTypeMapper<iScalar<T>> {
using ObjectTraits = iScalar<T>;
using BaseTraits = GridTypeMapper<T>;
static constexpr int Rank = 1 + BaseTraits::Rank;
static constexpr std::size_t count = 1 * BaseTraits::count;
static constexpr int Dimension(unsigned int dim) {
return ( dim == 0 ) ? 1 : BaseTraits::Dimension(dim - 1); }
GridTypeMapper_RepeatedTypes;
}; };
template<> struct isGridTensor<int > {
static const bool value = false; template<typename T, int N> struct GridTypeMapper<iVector<T, N>> {
static const bool notvalue = true; using ObjectTraits = iVector<T, N>;
using BaseTraits = GridTypeMapper<T>;
static constexpr int Rank = 1 + BaseTraits::Rank;
static constexpr std::size_t count = N * BaseTraits::count;
static constexpr int Dimension(unsigned int dim) {
return ( dim == 0 ) ? N : BaseTraits::Dimension(dim - 1); }
GridTypeMapper_RepeatedTypes;
}; };
template<> struct isGridTensor<RealD > {
static const bool value = false; template<typename T, int N> struct GridTypeMapper<iMatrix<T, N>> {
static const bool notvalue = true; using ObjectTraits = iMatrix<T, N>;
}; using BaseTraits = GridTypeMapper<T>;
template<> struct isGridTensor<RealF > { static constexpr int Rank = 2 + BaseTraits::Rank;
static const bool value = false; static constexpr std::size_t count = N * N * BaseTraits::count;
static const bool notvalue = true; static constexpr int Dimension(unsigned int dim) {
}; return ( dim == 0 || dim == 1 ) ? N : BaseTraits::Dimension(dim - 2); }
template<> struct isGridTensor<ComplexD > { GridTypeMapper_RepeatedTypes;
static const bool value = false;
static const bool notvalue = true;
};
template<> struct isGridTensor<ComplexF > {
static const bool value = false;
static const bool notvalue = true;
};
template<> struct isGridTensor<Integer > {
static const bool value = false;
static const bool notvalue = true;
};
template<> struct isGridTensor<vRealD > {
static const bool value = false;
static const bool notvalue = true;
};
template<> struct isGridTensor<vRealF > {
static const bool value = false;
static const bool notvalue = true;
};
template<> struct isGridTensor<vComplexD > {
static const bool value = false;
static const bool notvalue = true;
};
template<> struct isGridTensor<vComplexF > {
static const bool value = false;
static const bool notvalue = true;
};
template<> struct isGridTensor<vInteger > {
static const bool value = false;
static const bool notvalue = true;
}; };
// Match the index // Match the index
@ -263,20 +256,13 @@ namespace Grid {
typedef T type; typedef T type;
}; };
//Query if a tensor or Lattice<Tensor> is SIMD vector or scalar //Query whether a tensor or Lattice<Tensor> is SIMD vector or scalar
template<typename T> template<typename T, typename V=void> struct isSIMDvectorized : public std::false_type {};
class isSIMDvectorized{ template<typename U> struct isSIMDvectorized<U, typename std::enable_if< !std::is_same<
template<typename U> typename GridTypeMapper<typename getVectorType<U>::type>::scalar_type,
static typename std::enable_if< !std::is_same< typename GridTypeMapper<typename getVectorType<U>::type>::scalar_type, typename GridTypeMapper<typename getVectorType<U>::type>::vector_type>::value, void>::type>
typename GridTypeMapper<typename getVectorType<U>::type>::vector_type>::value, char>::type test(void *); : public std::true_type {};
template<typename U>
static double test(...);
public:
enum {value = sizeof(test<T>(0)) == sizeof(char) };
};
//Get the precision of a Lattice, tensor or scalar type in units of sizeof(float) //Get the precision of a Lattice, tensor or scalar type in units of sizeof(float)
template<typename T> template<typename T>
class getPrecision{ class getPrecision{