#ifndef DEFINITIONS_H
#define DEFINITIONS_H

//#define USE_ARMA
#define USE_POLYMATH

//#define ARMA_NO_DEBUG

#include <complex>

#ifndef REPLACEMENTS
#define REPLACEMENTS

#define REALTYPE_DOUBLE
//#define REALTYPE_LONGDOUBLE


#ifdef REALTYPE_DOUBLE
    typedef double _Real;
#endif
#ifdef REALTYPE_LONGDOUBLE
    typedef long double _Real;
#endif

#ifdef USE_ARMA
#define VEC    arma::vec
#define CX_VEC arma::cx_vec
#define MAT    arma::Mat<_Real>
#define CX_MAT arma::Mat<std::complex<_Real>>
#define G_MAT arma::Mat
#define ZEROS zeros()
#define AT(iIndex,jIndex) at(iIndex,jIndex)
#define EXPMAT_H(in,out) out = expmat(in)
#define EXPMAT_AH(in,out) out = expmat(in)
#define MATINVERSE(in,out) out = in.i()
#define ELEMENTWISEPRODUCT(in1,in2,out) out = in1 % in2
#define EIGSYM(vals,vecs,mat) eig_sym(vals, vecs, mat, "std");
#define MATTRACE(in,out) out = trace(in)
#define CONJTRANSPOSE(in,out) out = in.t()
#define TRANSPOSE(in,out) out = in.st()
#define HALFVECTORIZE(in,out) out = _vectorizeMatrix_upperTriangular_columnMajor(in)
#define KRONPROD(in1,in2,out) out = kron(in1,in2)
#define ROWS(mat) mat.n_rows
#define COLS(mat) mat.n_cols
#endif

#ifdef USE_POLYMATH
#define VEC    Poly::Matrix<_Real>
#define CX_VEC Poly::Matrix<std::complex<_Real>>
#define MAT    Poly::Matrix<_Real>
#define CX_MAT Poly::Matrix<std::complex<_Real>>
#define G_MAT  Poly::Matrix
#define ZEROS zeros()
#define AT(iIndex,jIndex) at(iIndex,jIndex)
#define EXPMAT_H(in,out) out = MatrixExp(in,Poly::MATRIX_HERMITIAN)
#define EXPMAT_AH(in,out) out = MatrixExp(in,Poly::MATRIX_ANTIHERMITIAN)
#define MATINVERSE(in,out) out = in.inverse()
#define EIGSYM(vals,vecs,mat) EigenVecsVals(vals, vecs, mat, Poly::MATRIX_HERMITIAN, Poly::MATRIX_HERMITIAN);
#define ELEMENTWISEPRODUCT(in1,in2,out) out = in1.elementWiseProduct(in2)
#define MATTRACE(in,out) out = Trace(in)
#define CONJTRANSPOSE(in,out) out = Poly::ConjugateTranspose(in)
#define TRANSPOSE(in,out) out = Poly::Transpose(in)
#define HALFVECTORIZE(in,out) out = in.vectorize(Poly::VECMODE_UPPER_TRIANGULAR_NO_DIAGONAL)
#define KRONPROD(in1,in2,out) out = KroneckerProduct(in1,in2)
#define ROWS(mat) mat.rows()
#define COLS(mat) mat.columns()
#endif

#endif
#endif // DEFINITIONS_H

