/* \file MatlabMatrixToDoubleMatrix.cpp
 * \brief: convert a sparse or dense matlab matrix to a double* pointer
 */

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

/*Matlab includes: */
#include "mex.h"
#include "../../shared/shared.h"

int MatlabMatrixToDoubleMatrix(double** pmatrix,int* pmatrix_rows,int* pmatrix_cols,const mxArray* mxmatrix){

	int        i,j,count,rows,cols;

	/*output: */
	double* matrix=NULL;

	/*matlab indices: */
	mwIndex*    ir=NULL;
	mwIndex*    jc=NULL;

	/*Ok, first check if we are dealing with a sparse or full matrix: */
	if (mxIsSparse(mxmatrix)){

		/*Dealing with sparse matrix: recover size first: */
		double* pmxmatrix=(double*)mxGetPr(mxmatrix);
		rows=mxGetM(mxmatrix);
		cols=mxGetN(mxmatrix);
		
		if(rows*cols){
			matrix=xNewZeroInit<double>(rows*cols);

			/*Now, get ir,jc and pr: */
			ir=mxGetIr(mxmatrix);
			jc=mxGetJc(mxmatrix);

			/*Now, start inserting data into double* matrix: */
			count=0;
			for(i=0;i<cols;i++){
				for(j=0;j<(jc[i+1]-jc[i]);j++){
					matrix[rows*ir[count]+i]=pmxmatrix[count];
					count++;
				}
			}
		}

	}
	else if(mxIsClass(mxmatrix,"double")){
		/*Dealing with dense matrix: recover pointer and size: */
		double* pmxmatrix=(double*)mxGetPr(mxmatrix);
		rows=mxGetM(mxmatrix);
		cols=mxGetN(mxmatrix);
		
		/*Create serial matrix: */
		if(rows*cols){
			matrix=xNewZeroInit<double>(rows*cols);

			for(i=0;i<rows;i++){
				for(j=0;j<cols;j++){
					matrix[cols*i+j]=(double)pmxmatrix[rows*j+i];
				}
			}
		}
	}
	else if(mxIsClass(mxmatrix,"single")){
		/*Dealing with dense matrix: recover pointer and size: */
		float *pmxmatrix=(float*)mxGetPr(mxmatrix);
		rows=mxGetM(mxmatrix);
		cols=mxGetN(mxmatrix);

		/*Create serial matrix: */
		if(rows*cols){
			matrix=xNewZeroInit<double>(rows*cols);

			for(i=0;i<rows;i++){
				for(j=0;j<cols;j++){
					matrix[cols*i+j]=(double)pmxmatrix[rows*j+i];
				}
			}
		}
	}
	else if(mxIsClass(mxmatrix,"int16")){
		/*Dealing with dense matrix: recover pointer and size: */
		short int *pmxmatrix=(short*)mxGetPr(mxmatrix);
		rows=mxGetM(mxmatrix);
		cols=mxGetN(mxmatrix);

		/*Create serial matrix: */
		if(rows*cols){
			matrix=xNewZeroInit<double>(rows*cols);

			for(i=0;i<rows;i++){
				for(j=0;j<cols;j++){
					matrix[cols*i+j]=(double)pmxmatrix[rows*j+i];
				}
			}
		}
	}
	else if(mxIsClass(mxmatrix,"uint8")){
		/*Dealing with dense matrix: recover pointer and size: */
		char *pmxmatrix=(char*)mxGetPr(mxmatrix);
		rows=mxGetM(mxmatrix);
		cols=mxGetN(mxmatrix);

		/*Create serial matrix: */
		if(rows*cols){
			matrix=xNewZeroInit<double>(rows*cols);

			for(i=0;i<rows;i++){
				for(j=0;j<cols;j++){
					matrix[cols*i+j]=(double)pmxmatrix[rows*j+i];
				}
			}
		}
	}
	else{
		_error2_("Matlab matrix type Not implemented yet");
	}

	/*Assign output pointer: */
	*pmatrix=matrix;
	*pmatrix_rows=rows;
	*pmatrix_cols=cols;

	return 1;
}
