#ifndef vDEC_TYPES_H
#define vDEC_TYPES_H

#include <vDEC/include/vdec_config.h>
#include <vector>
#include <map>

typedef unsigned int vertex_index;
typedef unsigned int edge_index;
typedef unsigned int face_index;
typedef unsigned int tet_index;
typedef unsigned int he_index;
typedef unsigned int simplex_index;
const vertex_index INVALID_VERTEX = (vertex_index)(-1);
//const unsigned int mod4[7] = {0, 1, 2, 3, 0, 1, 2, 3}; // use bit mask against 3
const unsigned int mod3[5] = {0, 1, 2, 0, 1};
//const unsigned int mod2[3] = {0, 1, 0}; // use bit mask against 1

#define VDEC_USE_FLOAT

#ifdef VDEC_USE_FLOAT
# include <float.h>
  typedef float real;
# define REAL_MAX FLT_MAX
# define REAL_EPSILON FLT_EPSILON
# define TAUCS_REAL TAUCS_SINGLE
# define TAUCS_MATRIX_COMPONENT s

# define VDEC_SQR(A) ((A)*(A))
# define VDEC_CUBE(A) ((A)*(A)*(A))
# define VDEC_FABS(A) fabsf(A)
# define VDEC_SQRT(A) sqrtf(A)
# define VDEC_MAX(A,B) (((A)>(B))?(A):(B))
# define VDEC_MIN(A,B) (((A)<(B))?(A):(B))
# define VDEC_SIN(A) sinf(A)
# define VDEC_COS(A) cosf(A)
# define VDEC_TAN(A) tanf(A)
# define VDEC_ACOS(A) acosf(A)
# define VDEC_FRAND() ((real)rand()/(real)RAND_MAX)
#elif defined(VDEC_USE_DOUBLE)
# include <float.h>
  typedef double real;
# define REAL_MAX DBL_MAX
# define REAL_EPSILON DBL_EPSILON
# define TAUCS_REAL TAUCS_DOUBLE
# define TAUCS_MATRIX_COMPONENT d

# define VDEC_SQR(A) ((A)*(A))
# define VDEC_CUBE(A) ((A)*(A)*(A))
# define VDEC_FABS(A) fabs(A)
# define VDEC_SQRT(A) sqrt(A)
# define VDEC_MAX(A,B) (((A)>(B))?(A):(B))
# define VDEC_MIN(A,B) (((A)<(B))?(A):(B))
# define VDEC_SIN(A) sin(A)
# define VDEC_COS(A) cos(A)
# define VDEC_TAN(A) tan(A)
# define VDEC_ACOS(A) acos(A)
# define VDEC_FRAND() ((real)rand()/(real)RAND_MAX)
#endif

// Our custom matrix types
// We prefer column major storage so that we can convert to TAUCS format
// easily.

#include <mtl/mtl.h>
#include <mtl/matrix.h>

typedef mtl::dense1D<real> vDEC_vector_real;

typedef mtl::matrix<int,
	mtl::rectangle<>,
	mtl::array<mtl::compressed<> >,
	mtl::column_major>::type vDEC_sparse_matrix_int;

typedef mtl::matrix<real,
	mtl::rectangle<>,
	mtl::array<mtl::compressed<> >,
	mtl::column_major>::type vDEC_sparse_matrix_real;

typedef mtl::matrix<real,
	mtl::symmetric<mtl::lower>,
	mtl::array<mtl::compressed<> >,
	mtl::column_major>::type vDEC_lower_symmetric_sparse_matrix_real;

typedef mtl::matrix<real,
	mtl::rectangle<>,
	mtl::dense<>,
	mtl::column_major>::type vDEC_dense_matrix_real;

typedef mtl::matrix<real,
	mtl::diagonal<>,
	mtl::banded<>,
	mtl::column_major>::type vDEC_diagonal_matrix_real;
/*
typedef boost::tuples::tuple<vertex_index, vertex_index> edge;
struct ltedge{
	bool operator()(const edge &e0, const edge &e1) const{
		return e0 < e1;
	}
};

typedef boost::tuples::tuple<vertex_index, vertex_index, vertex_index> face;
struct ltface{
	bool operator()(const face &f0, const face &f1) const{
		return f0 < f1;
	}
};

typedef boost::tuples::tuple<vertex_index, vertex_index, vertex_index, vertex_index> tet;
struct lttet{
	bool operator()(const tet &t0, const tet &t1) const{
		return t0 < t1;
	}
};
*/
/*
// Taken from http://www.unknownroad.com/rtfm/VisualStudio/warningC4251.html
#define EXPORT_STL_VECTOR( dllmacro, vectype ) \
  template class dllmacro std::allocator< vectype >; \
  template class dllmacro std::vector<vectype, \
    std::allocator< vectype > >;

#define EXPORT_STL_MAP( dllmacro, mapkey, mapvalue ) \
  template struct dllmacro std::pair< mapkey,mapvalue >; \
  template class dllmacro std::allocator< \
    std::pair<const mapkey,mapvalue> >; \
  template struct dllmacro std::less< mapkey >; \
  template class dllmacro std::allocator< \
    std::_Tree_ptr<std::_Tmap_traits<mapkey,mapvalue,std::less<mapkey>, \
    std::allocator<std::pair<const mapkey,mapvalue> >,false> > >; \
  template class dllmacro std::allocator< \
    std::_Tree_nod<std::_Tmap_traits<mapkey,mapvalue,std::less<mapkey>, \
    std::allocator<std::pair<const mapkey,mapvalue> >,false> > >; \
  template class dllmacro std::_Tree_nod< \
    std::_Tmap_traits<mapkey,mapvalue,std::less<mapkey>, \
    std::allocator<std::pair<const mapkey,mapvalue> >,false> >; \
  template class dllmacro std::_Tree_ptr< \
    std::_Tmap_traits<mapkey,mapvalue,std::less<mapkey>, \
    std::allocator<std::pair<const mapkey,mapvalue> >,false> >; \
  template class dllmacro std::_Tree_val< \
    std::_Tmap_traits<mapkey,mapvalue,std::less<mapkey>, \
	std::allocator<std::pair<const mapkey,mapvalue> >,false> >; \
  template class dllmacro std::map< \
    mapkey, mapvalue, std::less< mapkey >, \
    std::allocator<std::pair<const mapkey,mapvalue> > >;
*/
	
#endif
