2016-01-02 14:51:32 +00:00
/*************************************************************************************
Grid physics library , www . github . com / paboyle / Grid
Source file : . / lib / tensors / Tensor_traits . h
Copyright ( C ) 2015
Author : Azusa Yamaguchi < ayamaguc @ staffmail . ed . ac . uk >
Author : Peter Boyle < paboyle @ ph . ed . ac . uk >
2016-07-06 20:57:04 +01:00
Author : Christopher Kelly < ckelly @ phys . columbia . edu >
2016-01-02 14:51:32 +00:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License along
with this program ; if not , write to the Free Software Foundation , Inc . ,
51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
See the full license in the file " LICENSE " in the top level distribution directory
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* END LEGAL */
2015-04-18 18:36:48 +01:00
# ifndef GRID_MATH_TRAITS_H
# define GRID_MATH_TRAITS_H
# include <type_traits>
namespace Grid {
//////////////////////////////////////////////////////////////////////////////////
// Want to recurse: GridTypeMapper<Matrix<vComplexD> >::scalar_type == ComplexD.
// Use of a helper class like this allows us to template specialise and "dress"
// other classes such as RealD == double, ComplexD == std::complex<double> with these
// traits.
//
// It is possible that we could do this more elegantly if I introduced a
// queryable trait in iScalar, iMatrix and iVector and used the query on vtype in
// place of the type mapper?
//
// Not sure how to do this, but probably could be done with a research effort
// to study C++11's type_traits.h file. (std::enable_if<isGridTensorType<vtype> >)
//
//////////////////////////////////////////////////////////////////////////////////
template < class T > class GridTypeMapper {
public :
typedef typename T : : scalar_type scalar_type ;
typedef typename T : : vector_type vector_type ;
2017-04-15 10:57:21 +01:00
typedef typename T : : vector_typeD vector_typeD ;
2015-04-18 18:36:48 +01:00
typedef typename T : : tensor_reduced tensor_reduced ;
2015-04-22 22:46:48 +01:00
typedef typename T : : scalar_object scalar_object ;
2015-06-14 00:53:52 +01:00
typedef typename T : : Complexified Complexified ;
typedef typename T : : Realified Realified ;
2015-04-18 18:36:48 +01:00
enum { TensorLevel = T : : TensorLevel } ;
} ;
//////////////////////////////////////////////////////////////////////////////////
// Recursion stops with these template specialisations
//////////////////////////////////////////////////////////////////////////////////
template < > class GridTypeMapper < RealF > {
public :
typedef RealF scalar_type ;
typedef RealF vector_type ;
2017-04-15 10:57:21 +01:00
typedef RealD vector_typeD ;
2015-04-18 18:36:48 +01:00
typedef RealF tensor_reduced ;
2015-04-22 22:46:48 +01:00
typedef RealF scalar_object ;
2015-06-14 00:53:52 +01:00
typedef ComplexF Complexified ;
typedef RealF Realified ;
2015-04-18 18:36:48 +01:00
enum { TensorLevel = 0 } ;
} ;
template < > class GridTypeMapper < RealD > {
public :
typedef RealD scalar_type ;
typedef RealD vector_type ;
2017-04-15 10:57:21 +01:00
typedef RealD vector_typeD ;
2015-04-18 18:36:48 +01:00
typedef RealD tensor_reduced ;
2015-04-22 22:46:48 +01:00
typedef RealD scalar_object ;
2015-06-14 00:53:52 +01:00
typedef ComplexD Complexified ;
typedef RealD Realified ;
2015-04-18 18:36:48 +01:00
enum { TensorLevel = 0 } ;
} ;
template < > class GridTypeMapper < ComplexF > {
public :
typedef ComplexF scalar_type ;
typedef ComplexF vector_type ;
2017-04-15 10:57:21 +01:00
typedef ComplexD vector_typeD ;
2015-04-18 18:36:48 +01:00
typedef ComplexF tensor_reduced ;
2015-04-22 22:46:48 +01:00
typedef ComplexF scalar_object ;
2015-06-14 00:53:52 +01:00
typedef ComplexF Complexified ;
typedef RealF Realified ;
2015-04-18 18:36:48 +01:00
enum { TensorLevel = 0 } ;
} ;
template < > class GridTypeMapper < ComplexD > {
public :
typedef ComplexD scalar_type ;
typedef ComplexD vector_type ;
2017-04-15 10:57:21 +01:00
typedef ComplexD vector_typeD ;
2015-04-18 18:36:48 +01:00
typedef ComplexD tensor_reduced ;
2015-04-22 22:46:48 +01:00
typedef ComplexD scalar_object ;
2015-06-14 00:53:52 +01:00
typedef ComplexD Complexified ;
typedef RealD Realified ;
2015-04-18 18:36:48 +01:00
enum { TensorLevel = 0 } ;
} ;
2015-04-28 08:11:59 +01:00
template < > class GridTypeMapper < Integer > {
public :
typedef Integer scalar_type ;
typedef Integer vector_type ;
2017-04-16 23:40:00 +01:00
typedef Integer vector_typeD ;
2015-04-28 08:11:59 +01:00
typedef Integer tensor_reduced ;
typedef Integer scalar_object ;
2015-06-14 00:53:52 +01:00
typedef void Complexified ;
typedef void Realified ;
2015-04-28 08:11:59 +01:00
enum { TensorLevel = 0 } ;
} ;
2015-04-18 18:36:48 +01:00
template < > class GridTypeMapper < vRealF > {
public :
typedef RealF scalar_type ;
typedef vRealF vector_type ;
2017-04-15 10:57:21 +01:00
typedef vRealD vector_typeD ;
2015-04-18 18:36:48 +01:00
typedef vRealF tensor_reduced ;
2015-04-22 22:46:48 +01:00
typedef RealF scalar_object ;
2015-06-14 00:53:52 +01:00
typedef vComplexF Complexified ;
typedef vRealF Realified ;
2015-04-18 18:36:48 +01:00
enum { TensorLevel = 0 } ;
} ;
template < > class GridTypeMapper < vRealD > {
public :
typedef RealD scalar_type ;
typedef vRealD vector_type ;
2017-04-15 10:57:21 +01:00
typedef vRealD vector_typeD ;
2015-04-18 18:36:48 +01:00
typedef vRealD tensor_reduced ;
2015-04-22 22:46:48 +01:00
typedef RealD scalar_object ;
2015-06-14 00:53:52 +01:00
typedef vComplexD Complexified ;
typedef vRealD Realified ;
2015-04-18 18:36:48 +01:00
enum { TensorLevel = 0 } ;
} ;
template < > class GridTypeMapper < vComplexF > {
public :
typedef ComplexF scalar_type ;
typedef vComplexF vector_type ;
2017-04-15 10:57:21 +01:00
typedef vComplexD vector_typeD ;
2015-04-18 18:36:48 +01:00
typedef vComplexF tensor_reduced ;
2015-04-22 22:46:48 +01:00
typedef ComplexF scalar_object ;
2015-06-14 00:53:52 +01:00
typedef vComplexF Complexified ;
typedef vRealF Realified ;
2015-04-18 18:36:48 +01:00
enum { TensorLevel = 0 } ;
} ;
template < > class GridTypeMapper < vComplexD > {
public :
typedef ComplexD scalar_type ;
typedef vComplexD vector_type ;
2017-04-15 10:57:21 +01:00
typedef vComplexD vector_typeD ;
2015-04-18 18:36:48 +01:00
typedef vComplexD tensor_reduced ;
2015-04-22 22:46:48 +01:00
typedef ComplexD scalar_object ;
2015-06-14 00:53:52 +01:00
typedef vComplexD Complexified ;
typedef vRealD Realified ;
2015-04-18 18:36:48 +01:00
enum { TensorLevel = 0 } ;
} ;
template < > class GridTypeMapper < vInteger > {
public :
2015-04-28 08:11:59 +01:00
typedef Integer scalar_type ;
2015-04-18 18:36:48 +01:00
typedef vInteger vector_type ;
2017-04-15 10:57:21 +01:00
typedef vInteger vector_typeD ;
2015-04-18 18:36:48 +01:00
typedef vInteger tensor_reduced ;
2015-04-28 08:11:59 +01:00
typedef Integer scalar_object ;
2015-06-14 00:53:52 +01:00
typedef void Complexified ;
typedef void Realified ;
2015-04-18 18:36:48 +01:00
enum { TensorLevel = 0 } ;
} ;
// First some of my own traits
template < typename T > struct isGridTensor {
static const bool value = true ;
static const bool notvalue = false ;
} ;
2015-04-22 22:46:48 +01:00
template < > struct isGridTensor < int > {
static const bool value = false ;
static const bool notvalue = true ;
} ;
2015-04-18 18:36:48 +01:00
template < > struct isGridTensor < RealD > {
static const bool value = false ;
static const bool notvalue = true ;
} ;
template < > struct isGridTensor < RealF > {
static const bool value = false ;
static const bool notvalue = true ;
} ;
template < > struct isGridTensor < ComplexD > {
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
template < typename T , int Level > struct matchGridTensorIndex {
static const bool value = ( Level = = T : : TensorLevel ) ;
static const bool notvalue = ( Level ! = T : : TensorLevel ) ;
} ;
// What is the vtype
template < typename T > struct isComplex {
static const bool value = false ;
} ;
template < > struct isComplex < ComplexF > {
static const bool value = true ;
} ;
template < > struct isComplex < ComplexD > {
static const bool value = true ;
} ;
2016-07-06 20:57:04 +01:00
//Get the SIMD vector type from a Grid tensor or Lattice<Tensor>
template < typename T >
struct getVectorType {
typedef T type ;
} ;
//Query if a tensor or Lattice<Tensor> is SIMD vector or scalar
template < typename T >
class isSIMDvectorized {
template < typename U >
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 , char > : : type test ( void * ) ;
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)
template < typename T >
class getPrecision {
typedef typename getVectorType < T > : : type vector_obj ; //get the vector_obj (i.e. a grid Tensor) if its a Lattice<vobj>, do nothing otherwise (i.e. if fundamental or grid Tensor)
typedef typename GridTypeMapper < vector_obj > : : scalar_type scalar_type ; //get the associated scalar type. Works on fundamental and tensor types
typedef typename GridTypeMapper < scalar_type > : : Realified real_scalar_type ; //remove any std::complex wrapper, should get us to the fundamental type
public :
enum { value = sizeof ( real_scalar_type ) / sizeof ( float ) } ;
} ;
2015-04-18 18:36:48 +01:00
}
# endif