/*!\file DoubleMatArrayParam.c
 * \brief: implementation of the DoubleMatArrayParam object
 */

/*header files: */
/*{{{1*/
#ifdef HAVE_CONFIG_H
	#include <config.h>
#else
#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
#endif

#include <stdio.h>
#include <string.h>
#include "../objects.h"
#include "../../EnumDefinitions/EnumDefinitions.h"
#include "../../shared/shared.h"
#include "../../Container/Container.h"
#include "../../include/include.h"
/*}}}*/

/*DoubleMatArrayParam constructors and destructor*/
/*FUNCTION DoubleMatArrayParam::DoubleMatArrayParam(){{{1*/
DoubleMatArrayParam::DoubleMatArrayParam(){
	return;
}
/*}}}*/
/*FUNCTION DoubleMatArrayParam::DoubleMatArrayParam(int enum_type,double** array, int M, int* mdim_array, int* ndim_array){{{1*/
DoubleMatArrayParam::DoubleMatArrayParam(int in_enum_type,double** in_array, int in_M, int* in_mdim_array, int* in_ndim_array){

	int i;
	double* matrix=NULL;
	int     m,n;

	enum_type=in_enum_type;
	M=in_M;
	if(M){
		array=(double**)xmalloc(M*sizeof(double*));
		mdim_array=(int*)xmalloc(M*sizeof(int));
		ndim_array=(int*)xmalloc(M*sizeof(int));

		for(i=0;i<M;i++){
			m=in_mdim_array[i]; 
			n=in_ndim_array[i];

			mdim_array[i]=m;
			ndim_array[i]=n;

			if(m*n){
				matrix=(double*)xmalloc(m*n*sizeof(double));
				memcpy(matrix,in_array[i],m*n*sizeof(double));
			}
			else{
				matrix=NULL;
			}
			array[i]=matrix;
		}
	}
	else{
		array=NULL;
		mdim_array=NULL;
		ndim_array=NULL;
	}
}
/*}}}*/
/*FUNCTION DoubleMatArrayParam::~DoubleMatArrayParam(){{{1*/
DoubleMatArrayParam::~DoubleMatArrayParam(){

	int i;
	double* matrix=NULL;

	xfree((void**)&mdim_array);
	xfree((void**)&ndim_array);

	for(i=0;i<M;i++){
		matrix=array[i];
		xfree((void**)&matrix);
	}
	
	xfree((void**)&array);
	return;
}
/*}}}*/

/*Object virtual functions definitions:*/
/*FUNCTION DoubleMatArrayParam::Echo {{{1*/
void DoubleMatArrayParam::Echo(void){

	printf("DoubleMatArrayParam:\n");
	printf("   enum: %i (%s)\n",this->enum_type,EnumToStringx(this->enum_type));
	printf("   array size: %i\n",this->M);
	printf("   array pointer: %p\n",this->array);

}
/*}}}*/
/*FUNCTION DoubleMatArrayParam::DeepEcho{{{1*/
void DoubleMatArrayParam::DeepEcho(void){

	int i,j,k;
	int m,n;
	double* matrix=NULL;
	
	printf("DoubleMatArrayParam:\n");
	printf("   enum: %i (%s)\n",this->enum_type,EnumToStringx(this->enum_type));
	printf("   array size: %i\n",this->M);
	for(i=0;i<M;i++){
		printf("   array %i (%ix%i):\n",i,mdim_array[i],ndim_array[i]);
		matrix=array[i];
		m=mdim_array[i];
		n=ndim_array[i];

		for(j=0;j<m;j++){
			printf("   ");
			for(k=0;k<n;k++)printf("%g ",*(matrix+n*j+k));
			printf("\n");
		}
	}
}
/*}}}*/
/*FUNCTION DoubleMatArrayParam::Id{{{1*/
int    DoubleMatArrayParam::Id(void){ return -1; }
/*}}}*/
/*FUNCTION DoubleMatArrayParam::MyRank{{{1*/
int    DoubleMatArrayParam::MyRank(void){ 
	extern int my_rank;
	return my_rank; 
}
/*}}}*/
/*FUNCTION DoubleMatArrayParam::ObjectEnum{{{1*/
int DoubleMatArrayParam::ObjectEnum(void){

	return DoubleMatArrayParamEnum;

}
/*}}}*/
/*FUNCTION DoubleMatArrayParam::copy{{{1*/
Object* DoubleMatArrayParam::copy() {
	
	return new DoubleMatArrayParam(this->enum_type,this->array, this->M, this->mdim_array,this->ndim_array);

}
/*}}}*/

/*DoubleMatArrayParam virtual functions definitions: */
/*FUNCTION DoubleMatArrayParam::GetParameterValue(double*** parray, int* pM,int** pmdims, int** pndims){{{1*/
void  DoubleMatArrayParam::GetParameterValue(double*** pout_array, int* pout_M,int** pout_mdim_array, int** pout_ndim_array){

	int i,m,n;
	double* matrix=NULL;
	double* out_matrix=NULL;

	/*output: */
	double** out_array=NULL;
	int      out_M;
	int*     out_mdim_array=NULL;
	int*     out_ndim_array=NULL;


	out_M=this->M;
	if(out_M){
		out_array=(double**)xmalloc(M*sizeof(double*));
		out_mdim_array=(int*)xmalloc(M*sizeof(int));
		out_ndim_array=(int*)xmalloc(M*sizeof(int));

		memcpy(out_mdim_array,this->mdim_array,M*sizeof(int));
		memcpy(out_ndim_array,this->ndim_array,M*sizeof(int));

		for(i=0;i<this->M;i++){
			matrix=this->array[i];
			m=this->mdim_array[i];
			n=this->ndim_array[i];

			if(m*n){
				out_matrix=(double*)xmalloc(m*n*sizeof(double));
				memcpy(out_matrix,matrix,m*n*sizeof(double));
			}
			else{
				out_matrix=NULL;
			}
			out_array[i]=out_matrix;
		}
	}
	else{
		out_array=NULL;
		out_matrix=NULL;
		out_ndim_array=NULL;
	}


	/*Assign output pointers:*/
	if(pout_M) *pout_M=out_M;
	if(pout_mdim_array) *pout_mdim_array=out_mdim_array;
	if(pout_ndim_array) *pout_ndim_array=out_ndim_array;
	*pout_array=out_array;

}
/*}}}*/
/*FUNCTION DoubleMatArrayParam::GetParameterName{{{1*/
void DoubleMatArrayParam::GetParameterName(char**pname){
	EnumToStringx(pname,this->enum_type);
}
/*}}}*/
/*FUNCTION DoubleMatArrayParam::SetValue(double** array, int M, int* mdim_array, int* ndim_array){{{1*/
void  DoubleMatArrayParam::SetValue(double** in_array, int in_M, int* in_mdim_array, int* in_ndim_array){

	int i,m,n;
	double* in_matrix=NULL;
	double* matrix=NULL;

	/*avoid leak: */
	xfree((void**)&mdim_array);
	xfree((void**)&ndim_array);
	for(i=0;i<M;i++){
		matrix=array[i];
		xfree((void**)&matrix);
	}
	xfree((void**)&array);

	/*copy data: */
	this->M=in_M;
	this->array=(double**)xmalloc(M*sizeof(double*));
	this->mdim_array=(int*)xmalloc(M*sizeof(int));
	this->ndim_array=(int*)xmalloc(M*sizeof(int));
	
	memcpy(this->mdim_array,in_mdim_array,M*sizeof(double));
	memcpy(this->ndim_array,in_ndim_array,M*sizeof(double));

	for(i=0;i<M;i++){
		in_matrix=in_array[i];
		m=in_mdim_array[i];
		n=in_ndim_array[i];

		matrix=(double*)xmalloc(m*n*sizeof(double));
		memcpy(matrix,in_matrix,m*n*sizeof(double));

		this->array[i]=matrix;
	}

}
/*}}}*/
/*FUNCTION DoubleMatArrayParam::UnitConversion{{{1*/
void  DoubleMatArrayParam::UnitConversion(int direction_enum){
	/*go through all matrices and convert: */
	for (int i=0;i<this->M;i++){
		double* matrix=this->array[i];
		int     m=this->mdim_array[i];
		int     n=this->ndim_array[i];
		::UnitConversion(matrix,m*n,direction_enum,this->enum_type);
	}

}
/*}}}*/
