//#####################################################################
// Copyright 2006-2009, Geoffrey Irving, Craig Schroeder, Jonathan Su.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
// Class SCALAR_POLICY
//#####################################################################
#ifndef __SCALAR_POLICY__
#define __SCALAR_POLICY__

#include <Core/Arrays/ARRAYS_FORWARD.h>
#include <Core/Matrices/MATRIX_FORWARD.h>
#include <Core/Utilities/TYPE_UTILITIES.h>
#include <Core/Vectors/VECTOR_FORWARD.h>
#include <complex>
namespace PhysBAM{

template<class T,int m> struct FIXED_NUMBER;
class SYMBOLIC;
template<class T> struct IS_SCALAR{static const bool value=false;};
template<> struct IS_SCALAR<float>{static const bool value=true;};
template<> struct IS_SCALAR<double>{static const bool value=true;};
template<class T,int m> struct IS_SCALAR<FIXED_NUMBER<T,m> >{static const bool value=true;};
template<> struct IS_SCALAR<SYMBOLIC>{static const bool value=true;};

template<class T> struct IS_NUMBER{static const bool value=IS_SCALAR<T>::value;};
template<> struct IS_NUMBER<int>{static const bool value=true;};

template<class T> struct IS_SCALAR_BLOCK {static const bool value=is_scalar<T>::value;}; // true if memory layout is contiguous array of scalars

template<class T,class ENABLER=void> struct SCALAR_POLICY{typedef struct UNUSABLE{} TYPE;};
template<class T> using SCALAR_TYPE = typename SCALAR_POLICY<T>::TYPE;

template<class T> struct SCALAR_POLICY<T,enable_if_t<is_scalar<T>::value> >{typedef T TYPE;};
template<class T> struct SCALAR_POLICY<std::complex<T> >{typedef std::complex<T> TYPE;};

template<class T,int d> struct SCALAR_POLICY<VECTOR<T,d> > : public SCALAR_POLICY<T> {};
template<class T,int d> struct SCALAR_POLICY<ZERO_VECTOR<T,d> > : public SCALAR_POLICY<T> {};

template<class T,class ID> struct SCALAR_POLICY<ARRAY<T,ID> > : public SCALAR_POLICY<T> {};
template<class T,class ID> struct SCALAR_POLICY<ARRAY_VIEW<T,ID> > : public SCALAR_POLICY<T> {};
template<class A,class B> struct SCALAR_POLICY<INDIRECT_ARRAY<A,B> > : public SCALAR_POLICY<A> {};

template<class T> struct SCALAR_POLICY<INTERVAL<T> > : public SCALAR_POLICY<T> {};
template<class T> struct SCALAR_POLICY<QUATERNION<T> > : public SCALAR_POLICY<T> {};
template<class T> struct SCALAR_POLICY<TETRAHEDRAL_GROUP<T> > : public SCALAR_POLICY<T> {};
template<class TV> struct SCALAR_POLICY<ROTATION<TV> > : public SCALAR_POLICY<TV> {};
template<class TV> struct SCALAR_POLICY<FRAME<TV> > : public SCALAR_POLICY<TV> {};
template<class TV> struct SCALAR_POLICY<TWIST<TV> > : public SCALAR_POLICY<TV> {};

template<class T,int m,int n> class SCALAR_POLICY<MATRIX<T,m,n> > : public SCALAR_POLICY<T> {};
template<class T,int d> class SCALAR_POLICY<DIAGONAL_MATRIX<T,d> > : public SCALAR_POLICY<T> {};
template<class T,int d> class SCALAR_POLICY<SYMMETRIC_MATRIX<T,d> > : public SCALAR_POLICY<T> {};
template<class T> class SCALAR_POLICY<MATRIX_MXN<T> > : public SCALAR_POLICY<T> {};
template<class T> class SCALAR_POLICY<MATRIX_VIEW<T> > : public SCALAR_POLICY<T> {};
template<class T> class SCALAR_POLICY<SPARSE_MATRIX_FLAT_MXN<T> > : public SCALAR_POLICY<T> {};
template<class T,int m,int n> class SCALAR_POLICY<ZERO_MATRIX<T,m,n> > : public SCALAR_POLICY<T> {};
template<class T,int d> class SCALAR_POLICY<IDENTITY_MATRIX<T,d> > : public SCALAR_POLICY<T> {};
template<class T,int d> class SCALAR_POLICY<SCALE_MATRIX<T,d> > : public SCALAR_POLICY<T> {};




}
#endif
