/*\file FetchData.cpp:
 * \brief: general I/O interface to fetch data in matlab
 */

#ifdef HAVE_CONFIG_H
	#include <config.h>
#else
#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
#endif

#include <mex.h>
#include "../../shared/shared.h"
#include "../../include/include.h"
#include "./matlabio.h"

/*Primitive data types*/
/*FUNCTION FetchData(double** pmatrix,int* pM,int *pN,const mxArray* dataref){{{*/
void FetchData(double** pmatrix,int* pM,int *pN,const mxArray* dataref){

	double*  outmatrix=NULL;
	int      outmatrix_rows,outmatrix_cols;

	if(mxIsEmpty(dataref) ){
		/*Nothing to pick up. Just initialize matrix pointer to NULL: */
		outmatrix_rows=0;
		outmatrix_cols=0;
		outmatrix=NULL;
	}
	else if( mxIsClass(dataref,"double") || 
				mxIsClass(dataref,"single") || 
				mxIsClass(dataref,"int16") || 
				mxIsClass(dataref,"int8") || 
				mxIsClass(dataref,"uint8")){
		/*Check dataref is not pointing to NaN: */
		if ( mxIsNaN(*(mxGetPr(dataref))) && (mxGetM(dataref)==1) && (mxGetN(dataref)==1) ){
			outmatrix_rows=0;
			outmatrix_cols=0;
			outmatrix=NULL;
		}
		else{
			if(!mxIsClass(dataref,"double") && !mxIsClass(dataref,"single")){
				_printLine_("Warning: converting matlab data from '" << mxGetClassName(dataref) << "' to 'double'");
			}
			/*Convert matlab matrix to double* matrix: */
			MatlabMatrixToDoubleMatrix(&outmatrix,&outmatrix_rows,&outmatrix_cols,dataref);
		}
	}
	else{
		/*This is an error: we don't have the correct input!: */
		_error2_("Input parameter of class " << mxGetClassName(dataref) << " not supported yet");
	}
			
	/*Assign output pointers:*/
	*pmatrix=outmatrix;
	if (pM)*pM=outmatrix_rows;
	if (pN)*pN=outmatrix_cols;

}
/*}}}*/
/*FUNCTION FetchData(double** pmatrix,int* pnumel,int* pndims,int** psize,const mxArray* dataref){{{*/
void FetchData(double** pmatrix,int* pnumel,int* pndims,int** psize,const mxArray* dataref){

	double*  outmatrix=NULL;
	int      outmatrix_numel,outmatrix_ndims;
	int*     outmatrix_size=NULL;

	if(mxIsEmpty(dataref) ){
		/*Nothing to pick up. Just initialize matrix pointer to NULL: */
		outmatrix_numel=0;
		outmatrix_ndims=0;
		outmatrix_size =NULL;
		outmatrix=NULL;
	}
	else if (mxIsClass(dataref,"double") ){

		/*Check dataref is not pointing to NaN: */
		if ( mxIsNaN(*(mxGetPr(dataref))) && (mxGetNumberOfElements(dataref)==1) ){
			outmatrix_numel=0;
			outmatrix_ndims=0;
			outmatrix_size =NULL;
			outmatrix=NULL;
		}
		else{

			/*Convert matlab n-dim array to double* matrix: */
			MatlabNArrayToNArray(&outmatrix,&outmatrix_numel,&outmatrix_ndims,&outmatrix_size,dataref);
		}
	}
	else{
		/*This is an error: we don't have the correct input!: */
		_error2_("Input parameter of class " << mxGetClassName(dataref) << " not supported yet");
	}
			
	/*Assign output pointers:*/
	*pmatrix=outmatrix;
	if (pnumel)*pnumel=outmatrix_numel;
	if (pndims)*pndims=outmatrix_ndims;
	if (psize )*psize =outmatrix_size;
	else xDelete<int>(outmatrix_size);

}
/*}}}*/
/*FUNCTION FetchData(int** pmatrix,int* pM,int *pN,const mxArray* dataref){{{*/
void FetchData(int** pmatrix,int* pM,int *pN,const mxArray* dataref){

	int     i,outmatrix_rows,outmatrix_cols;
	double *doublematrix=NULL;
	int    *outmatrix=NULL;

	if(mxIsEmpty(dataref) ){
		/*Nothing to pick up. Just initialize matrix pointer to NULL: */
		outmatrix_rows=0;
		outmatrix_cols=0;
		outmatrix=NULL;
	}
	else if (mxIsClass(dataref,"double") ){

		/*Check dataref is not pointing to NaN: */
		if ( mxIsNaN(*(mxGetPr(dataref))) && (mxGetM(dataref)==1) && (mxGetN(dataref)==1) ){
			outmatrix_rows=0;
			outmatrix_cols=0;
			outmatrix=NULL;
		}
		else{

			/*Convert matlab matrix to double* matrix: */
			MatlabMatrixToDoubleMatrix(&doublematrix,&outmatrix_rows,&outmatrix_cols,dataref);

			/*Convert double matrix into integer matrix: */
			outmatrix=xNew<int>(outmatrix_rows*outmatrix_cols);
			for(i=0;i<outmatrix_rows*outmatrix_cols;i++)outmatrix[i]=(int)doublematrix[i];
		}
	}
	else{
		/*This is an error: we don't have the correct input!: */
		_error2_("Input parameter of class " << mxGetClassName(dataref) << " not supported yet");
	}

	/*Assign output pointers:*/
	*pmatrix=outmatrix;
	if (pM)*pM=outmatrix_rows;
	if (pN)*pN=outmatrix_cols;
}
/*}}}*/
/*FUNCTION FetchData(bool** pmatrix,int* pM,int *pN,const mxArray* dataref){{{*/
void FetchData(bool** pmatrix,int* pM,int *pN,const mxArray* dataref){

	int     i,outmatrix_rows,outmatrix_cols;
	double *doublematrix=NULL;
	bool   *outmatrix=NULL;

	if(mxIsEmpty(dataref) ){
		/*Nothing to pick up. Just initialize matrix pointer to NULL: */
		outmatrix_rows=0;
		outmatrix_cols=0;
		outmatrix=NULL;
	}
	else if (mxIsClass(dataref,"double") ){

		/*Check dataref is not pointing to NaN: */
		if ( mxIsNaN(*(mxGetPr(dataref))) && (mxGetM(dataref)==1) && (mxGetN(dataref)==1) ){
			outmatrix_rows=0;
			outmatrix_cols=0;
			outmatrix=NULL;
		}
		else{

			/*Convert matlab matrix to double* matrix: */
			MatlabMatrixToDoubleMatrix(&doublematrix,&outmatrix_rows,&outmatrix_cols,dataref);

			/*Convert double matrix into integer matrix: */
			outmatrix=xNew<bool>(outmatrix_rows*outmatrix_cols);
			for(i=0;i<outmatrix_rows;i++)outmatrix[i]=(bool)doublematrix[i];
		}
	}
	else{
		/*This is an error: we don't have the correct input!: */
		_error2_("Input parameter of class " << mxGetClassName(dataref) << " not supported yet");
	}

	/*Assign output pointers:*/
	*pmatrix=outmatrix;
	if (pM)*pM=outmatrix_rows;
	if (pN)*pN=outmatrix_cols;
}
/*}}}*/
/*FUNCTION FetchData(bool** pmatrix,int* pnumel,int* pndims,int** psize,const mxArray* dataref){{{*/
void FetchData(bool** pmatrix,int* pnumel,int* pndims,int** psize,const mxArray* dataref){

	int      i;
	int      outmatrix_numel,outmatrix_ndims;
	int*     outmatrix_size=NULL;
	double*  doublematrix=NULL;
	bool*    outmatrix=NULL;

	if(mxIsEmpty(dataref) ){
		/*Nothing to pick up. Just initialize matrix pointer to NULL: */
		outmatrix_numel=0;
		outmatrix_ndims=0;
		outmatrix_size =NULL;
		outmatrix=NULL;
	}
	else if (mxIsClass(dataref,"logical") ){

		/*Check dataref is not pointing to NaN: */
		if ( mxIsNaN(*((bool*)mxGetData(dataref))) && (mxGetNumberOfElements(dataref)==1) ){
			outmatrix_numel=0;
			outmatrix_ndims=0;
			outmatrix_size =NULL;
			outmatrix=NULL;
		}
		else{

			/*Convert matlab n-dim array to bool* matrix: */
			MatlabNArrayToNArray(&outmatrix,&outmatrix_numel,&outmatrix_ndims,&outmatrix_size,dataref);
		}
	}
	else if (mxIsClass(dataref,"double") ){

		/*Check dataref is not pointing to NaN: */
		if ( mxIsNaN(*(mxGetPr(dataref))) && (mxGetNumberOfElements(dataref)==1) ){
			outmatrix_numel=0;
			outmatrix_ndims=0;
			outmatrix_size =NULL;
			outmatrix=NULL;
		}
		else{

			/*Convert matlab n-dim array to double* matrix: */
			MatlabNArrayToNArray(&doublematrix,&outmatrix_numel,&outmatrix_ndims,&outmatrix_size,dataref);

			/*Convert double matrix into bool matrix: */
			outmatrix=xNew<bool>(outmatrix_numel);
			for(i=0;i<outmatrix_numel;i++)outmatrix[i]=(bool)doublematrix[i];
			xDelete<double>(doublematrix);
		}
	}
	else{
		/*This is an error: we don't have the correct input!: */
		_error2_("Input parameter of class " << mxGetClassName(dataref) << " not supported yet");
	}
			
	/*Assign output pointers:*/
	*pmatrix=outmatrix;
	if (pnumel)*pnumel=outmatrix_numel;
	if (pndims)*pndims=outmatrix_ndims;
	if (psize )*psize =outmatrix_size;
	else xDelete<int>(outmatrix_size);

}
/*}}}*/
/*FUNCTION FetchData(double** pvector,int* pM,const mxArray* dataref){{{*/
void FetchData(double** pvector,int* pM,const mxArray* dataref){

	double* outvector=NULL;
	int outvector_rows;

	if(mxIsEmpty(dataref)){
		/*Nothing to pick up. Just initialize matrix pointer to NULL: */
		outvector_rows=0;
		outvector=NULL;
	}
	else if (mxIsClass(dataref,"double") ){

		/*Convert matlab vector to double*  vector: */
		MatlabVectorToDoubleVector(&outvector,&outvector_rows,dataref);

	}
	else{
		/*This is an error: we don't have the correct input!: */
		_error2_("Input parameter of class " << mxGetClassName(dataref) << " not supported yet");
	}

	/*Assign output pointers:*/
	*pvector=outvector;
	if (pM)*pM=outvector_rows;
}
/*}}}*/
/*FUNCTION FetchData(int** pvector,int* pM,const mxArray* dataref){{{*/
void FetchData(int** pvector,int* pM,const mxArray* dataref){

	int    i;
	double *doublevector   = NULL;
	int    *outvector      = NULL;
	int     outvector_rows;

	if(mxIsEmpty(dataref)){
		/*Nothing to pick up. Just initialize matrix pointer to NULL: */
		outvector_rows=0;
		outvector=NULL;
	}
	else if (mxIsClass(dataref,"double") ){

		/*Convert matlab vector to double*  vector: */
		MatlabVectorToDoubleVector(&doublevector,&outvector_rows,dataref);

		/*Convert double vector into integer vector: */
		outvector=xNew<int>(outvector_rows);
		for(i=0;i<outvector_rows;i++)outvector[i]=(int)doublevector[i];
	}
	else{
		/*This is an error: we don't have the correct input!: */
		_error2_("Input parameter of class " << mxGetClassName(dataref) << " not supported yet");
	}

	/*Assign output pointers:*/
	*pvector=outvector;
	if (pM)*pM=outvector_rows;
}
/*}}}*/
/*FUNCTION FetchData(bool** pvector,int* pM,const mxArray* dataref){{{*/
void FetchData(bool** pvector,int* pM,const mxArray* dataref){

	int    i;
	double *doublevector   = NULL;
	bool   *outvector      = NULL;
	int     outvector_rows;

	if(mxIsEmpty(dataref)){
		/*Nothing to pick up. Just initialize matrix pointer to NULL: */
		outvector_rows=0;
		outvector=NULL;
	}
	else if (mxIsClass(dataref,"double") ){

		/*Convert matlab vector to double*  vector: */
		MatlabVectorToDoubleVector(&doublevector,&outvector_rows,dataref);

		/*Convert double vector into integer vector: */
		outvector=xNew<bool>(outvector_rows);
		for(i=0;i<outvector_rows;i++)outvector[i]=(bool)doublevector[i];
	}
	else{
		/*This is an error: we don't have the correct input!: */
		_error2_("Input parameter of class " << mxGetClassName(dataref) << " not supported yet");
	}

	/*Assign output pointers:*/
	*pvector=outvector;
	if (pM)*pM=outvector_rows;
}
/*}}}*/
/*FUNCTION FetchData(float** pvector,int* pM,const mxArray* dataref){{{*/
void FetchData(float** pvector,int* pM,const mxArray* dataref){

	int    i;
	double *doublevector   = NULL;
	float  *outvector      = NULL;
	int     outvector_rows;

	if(mxIsEmpty(dataref)){
		/*Nothing to pick up. Just initialize matrix pointer to NULL: */
		outvector_rows=0;
		outvector=NULL;
	}
	else if (mxIsClass(dataref,"double") ){

		/*Convert matlab vector to double*  vector: */
		MatlabVectorToDoubleVector(&doublevector,&outvector_rows,dataref);

		/*Convert double vector into float vector: */
		outvector=xNew<float>(outvector_rows);
		for(i=0;i<outvector_rows;i++)outvector[i]=(float)doublevector[i];
	}
	else{
		/*This is an error: we don't have the correct input!: */
		_error2_("Input parameter of class " << mxGetClassName(dataref) << " not supported yet");
	}

	/*Assign output pointers:*/
	*pvector=outvector;
	if (pM)*pM=outvector_rows;
}
/*}}}*/
/*FUNCTION FetchData(char** pstring,const mxArray* dataref){{{*/
void FetchData(char** pstring,const mxArray* dataref){

	char* outstring=NULL;


	/*Ok, the string should be coming directly from the matlab workspace: */
	if (!mxIsClass(dataref,"char")){
		_error2_("input data_type is not a string!");
	}
	else{
		/*Recover the string:*/
		int stringlen;
		
		stringlen = mxGetM(dataref)*mxGetN(dataref)+1;
		outstring =xNew<char>(stringlen);
		mxGetString(dataref,outstring,stringlen);
	}

	/*Assign output pointers:*/
	*pstring=outstring;
}/*}}}*/
/*FUNCTION FetchData(char** pmatrix,int* pnumel,int* pndims,int** psize,const mxArray* dataref){{{*/
void FetchData(char** pmatrix,int* pnumel,int* pndims,int** psize,const mxArray* dataref){

	int      outmatrix_numel,outmatrix_ndims;
	int*     outmatrix_size=NULL;
	char*    outmatrix=NULL;

	if(mxIsEmpty(dataref) ){
		/*Nothing to pick up. Just initialize matrix pointer to NULL: */
		outmatrix_numel=0;
		outmatrix_ndims=0;
		outmatrix_size =NULL;
		outmatrix=NULL;
	}
	else if (mxIsClass(dataref,"char") ){

		/*Convert matlab n-dim array to char* matrix: */
		MatlabNArrayToNArray(&outmatrix,&outmatrix_numel,&outmatrix_ndims,&outmatrix_size,dataref);
	}
	else{
		/*This is an error: we don't have the correct input!: */
		_error2_("Input parameter of class " << mxGetClassName(dataref) << " not supported yet");
	}
			
	/*Assign output pointers:*/
	*pmatrix=outmatrix;
	if (pnumel)*pnumel=outmatrix_numel;
	if (pndims)*pndims=outmatrix_ndims;
	if (psize )*psize =outmatrix_size;
	else xDelete<int>(outmatrix_size);

}
/*}}}*/
/*FUNCTION FetchData(double* pscalar,const mxArray* dataref){{{*/
void FetchData(double* pscalar,const mxArray* dataref){

	double scalar;

	if (!mxIsClass(dataref,"double")){
		_error2_("input data_type is not a double!");
	}
	else{
		/*Recover the double: */
		scalar=mxGetScalar(dataref);
	}

	/*Assign output pointers:*/
	*pscalar=scalar;
}
/*}}}*/
/*FUNCTION FetchData(int* pinteger,const mxArray* dataref){{{*/
void FetchData(int* pinteger,const mxArray* dataref){

	int integer;

	if (!mxIsClass(dataref,"double")){
		_error2_("input data_type is not a scalar!");
	}
	else{
		/*Recover the double: */
		integer=(int)mxGetScalar(dataref);
	}

	/*Assign output pointers:*/
	*pinteger=integer;
}
/*}}}*/
/*FUNCTION FetchData(bool* pboolean,const mxArray* dataref){{{*/
void FetchData(bool* pboolean,const mxArray* dataref){

	bool* mxbool_ptr=NULL;

	if (mxIsClass(dataref,"logical")){
		if(mxGetM(dataref)!=1) _error2_("input data is not of size 1x1");
		if(mxGetN(dataref)!=1) _error2_("input data is not of size 1x1");
		mxbool_ptr=mxGetLogicals(dataref);
	}
	else{
		_error2_("input data_type is not a bool!");
	}

	*pboolean=*mxbool_ptr;
}
/*}}}*/

/*ISSM objects*/
/*FUNCTION FetchData(Matrix** pmatrix,const mxArray* dataref){{{*/
void FetchData(Matrix** pmatrix,const mxArray* dataref){

	Matrix* outmatrix=NULL;
	int dummy=0;

	if (mxIsClass(dataref,"double") ){

		/*Convert matlab matrix to matrix: */
		outmatrix=MatlabMatrixToMatrix(dataref);

	}
	else{
		/*This is an error: we don't have the correct input!: */
		_error2_("Input parameter of class " << mxGetClassName(dataref) << " not supported yet");
	}

	/*Assign output pointers:*/
	*pmatrix=outmatrix;
}
/*}}}*/
/*FUNCTION FetchData(Vector** pvector,const mxArray* dataref){{{*/
void FetchData(Vector** pvector,const mxArray* dataref){

	Vector* vector=NULL;
	int dummy;

	if(mxIsEmpty(dataref)){
		/*Nothing to pick up. Just initialize matrix pointer to NULL: */
		vector=new Vector(0);
	}
	else if (mxIsClass(dataref,"double") ){

		/*Convert matlab vector to petsc vector: */
		vector=MatlabVectorToVector(dataref);
	}
	else{
		/*This is an error: we don't have the correct input!: */
		_error2_("Input parameter of class " << mxGetClassName(dataref) << " not supported yet");
	}

	/*Assign output pointers:*/
	*pvector=vector;
}
/*}}}*/
/*FUNCTION FetchData(BamgGeom** pbamggeom,const mxArray* dataref){{{*/
void FetchData(BamgGeom** pbamggeom,const mxArray* dataref){

	/*Initialize output*/
	BamgGeom* bamggeom=new BamgGeom();

	/*Fetch all fields*/
	FetchData(&bamggeom->Vertices,&bamggeom->VerticesSize[0],&bamggeom->VerticesSize[1],mxGetAssignedField(dataref,0,"Vertices"));
	FetchData(&bamggeom->Edges, &bamggeom->EdgesSize[0], &bamggeom->EdgesSize[1], mxGetAssignedField(dataref,0,"Edges"));
	FetchData(&bamggeom->Corners, &bamggeom->CornersSize[0], &bamggeom->CornersSize[1], mxGetAssignedField(dataref,0,"Corners"));
	FetchData(&bamggeom->RequiredVertices,&bamggeom->RequiredVerticesSize[0],&bamggeom->RequiredVerticesSize[1],mxGetAssignedField(dataref,0,"RequiredVertices"));
	FetchData(&bamggeom->RequiredEdges, &bamggeom->RequiredEdgesSize[0], &bamggeom->RequiredEdgesSize[1], mxGetAssignedField(dataref,0,"RequiredEdges"));
	FetchData(&bamggeom->CrackedEdges,&bamggeom->CrackedEdgesSize[0],&bamggeom->CrackedEdgesSize[1],mxGetAssignedField(dataref,0,"CrackedEdges"));
	FetchData(&bamggeom->SubDomains,&bamggeom->SubDomainsSize[0],&bamggeom->SubDomainsSize[1],mxGetAssignedField(dataref,0,"SubDomains"));

	/*Assign output pointers:*/
	*pbamggeom=bamggeom;
}
/*}}}*/
/*FUNCTION FetchData(BamgMesh** pbamgmesh,const mxArray* dataref){{{*/
void FetchData(BamgMesh** pbamgmesh,const mxArray* dataref){

	/*Initialize output*/
	BamgMesh* bamgmesh=new BamgMesh();

	/*Fetch all fields*/
	FetchData(&bamgmesh->Vertices,&bamgmesh->VerticesSize[0],&bamgmesh->VerticesSize[1],mxGetAssignedField(dataref,0,"Vertices"));
	FetchData(&bamgmesh->Edges, &bamgmesh->EdgesSize[0], &bamgmesh->EdgesSize[1], mxGetAssignedField(dataref,0,"Edges"));
	FetchData(&bamgmesh->Triangles, &bamgmesh->TrianglesSize[0], &bamgmesh->TrianglesSize[1], mxGetAssignedField(dataref,0,"Triangles"));
	FetchData(&bamgmesh->CrackedEdges,&bamgmesh->CrackedEdgesSize[0],&bamgmesh->CrackedEdgesSize[1],mxGetAssignedField(dataref,0,"CrackedEdges"));
	FetchData(&bamgmesh->VerticesOnGeomEdge,&bamgmesh->VerticesOnGeomEdgeSize[0],&bamgmesh->VerticesOnGeomEdgeSize[1],mxGetAssignedField(dataref,0,"VerticesOnGeomEdge"));
	FetchData(&bamgmesh->VerticesOnGeomVertex,&bamgmesh->VerticesOnGeomVertexSize[0],&bamgmesh->VerticesOnGeomVertexSize[1],mxGetAssignedField(dataref,0,"VerticesOnGeomVertex"));
	FetchData(&bamgmesh->EdgesOnGeomEdge, &bamgmesh->EdgesOnGeomEdgeSize[0], &bamgmesh->EdgesOnGeomEdgeSize[1], mxGetAssignedField(dataref,0,"EdgesOnGeomEdge"));
	FetchData(&bamgmesh->IssmSegments,&bamgmesh->IssmSegmentsSize[0],&bamgmesh->IssmSegmentsSize[1],mxGetAssignedField(dataref,0,"IssmSegments"));

	/*Assign output pointers:*/
	*pbamgmesh=bamgmesh;
}
/*}}}*/
/*FUNCTION FetchData(BamgOpts** pbamgopts,const mxArray* dataref){{{*/
void FetchData(BamgOpts** pbamgopts,const mxArray* dataref){

	/*Initialize output*/
	BamgOpts* bamgopts=new BamgOpts();

	/*Fetch all fields*/
	FetchData(&bamgopts->anisomax,mxGetField(dataref,0,"anisomax"));
	FetchData(&bamgopts->cutoff,mxGetField(dataref,0,"cutoff"));
	FetchData(&bamgopts->coeff,mxGetField(dataref,0,"coeff"));
	FetchData(&bamgopts->errg,mxGetField(dataref,0,"errg"));
	FetchData(&bamgopts->gradation,mxGetField(dataref,0,"gradation"));
	FetchData(&bamgopts->Hessiantype,mxGetField(dataref,0,"Hessiantype"));
	FetchData(&bamgopts->MaxCornerAngle,mxGetField(dataref,0,"MaxCornerAngle"));
	FetchData(&bamgopts->maxnbv,mxGetField(dataref,0,"maxnbv"));
	FetchData(&bamgopts->maxsubdiv,mxGetField(dataref,0,"maxsubdiv"));
	FetchData(&bamgopts->Metrictype,mxGetField(dataref,0,"Metrictype"));
	FetchData(&bamgopts->nbjacobi,mxGetField(dataref,0,"nbjacobi"));
	FetchData(&bamgopts->nbsmooth,mxGetField(dataref,0,"nbsmooth"));
	FetchData(&bamgopts->omega,mxGetField(dataref,0,"omega"));
	FetchData(&bamgopts->power,mxGetField(dataref,0,"power"));
	FetchData(&bamgopts->verbose,mxGetField(dataref,0,"verbose"));

	FetchData(&bamgopts->Crack,mxGetField(dataref,0,"Crack"));
	FetchData(&bamgopts->geometricalmetric,mxGetField(dataref,0,"geometricalmetric"));
	FetchData(&bamgopts->KeepVertices,mxGetField(dataref,0,"KeepVertices"));
	FetchData(&bamgopts->splitcorners,mxGetField(dataref,0,"splitcorners"));

	FetchData(&bamgopts->hmin,mxGetField(dataref,0,"hmin"));
	FetchData(&bamgopts->hmax,mxGetField(dataref,0,"hmax"));
	FetchData(&bamgopts->hminVertices,&bamgopts->hminVerticesSize[0],&bamgopts->hminVerticesSize[1],mxGetField(dataref,0,"hminVertices"));
	FetchData(&bamgopts->hmaxVertices,&bamgopts->hmaxVerticesSize[0],&bamgopts->hmaxVerticesSize[1],mxGetField(dataref,0,"hmaxVertices"));
	FetchData(&bamgopts->hVertices,&bamgopts->hVerticesSize[0],&bamgopts->hVerticesSize[1],mxGetField(dataref,0,"hVertices"));
	FetchData(&bamgopts->metric,&bamgopts->metricSize[0],&bamgopts->metricSize[1],mxGetField(dataref,0,"metric"));
	FetchData(&bamgopts->field,&bamgopts->fieldSize[0],&bamgopts->fieldSize[1],mxGetField(dataref,0,"field"));
	FetchData(&bamgopts->err,&bamgopts->errSize[0],&bamgopts->errSize[1],mxGetField(dataref,0,"err"));

	/*Additional checks*/
	bamgopts->Check();

	/*Assign output pointers:*/
	*pbamgopts=bamgopts;
}
/*}}}*/
/*FUNCTION FetchData(Options** poptions,const mxArray* dataref){{{*/
void FetchData(Options** poptions,int istart, int nrhs,const mxArray** pdataref){

	char   *name   = NULL;
	Option *option = NULL;

	/*Initialize output*/
	Options* options=new Options();

	/*Fetch all options*/
	for (int i=istart; i<nrhs; i=i+2){
		if (!mxIsClass(pdataref[i],"char")) _error2_("Argument " << i+1 << " must be name of option");

		FetchData(&name,pdataref[i]);
		if(i+1 == nrhs) _error2_("Argument " << i+2 << " must exist and be value of option \"" << name << "\".");

		option=(Option*)OptionParse(name,&pdataref[i+1]);
		options->AddOption(option);
		option=NULL;
	}

	/*Assign output pointers:*/
	*poptions=options;
}
/*}}}*/
