/*
 * PatTest.c
 *
 *  Created on: 2009/03/03
 *      Author: shouno
 */

#include <stdio.h>
#include <sys/stat.h>
#include "mex.h"
#include "matrix.h"

void mexFunction( int nlhs, mxArray *lhs[], int nrhs, const mxArray *rhs[] );

/*
 * Input & Output Arguments
 */

#define U_OUT		lhs[0] // output matrix
#define FNAME_IN	rhs[0] // file name
#define USIZE_IN	rhs[1] // Pattern size 64 or 65
#define TSTART_IN	rhs[2] // start of read out
#define TEND_IN		rhs[3] // end of read out
#define SAT_IN		rhs[4] // satruation factor


void pat(				// get a pattern (from ETL1 file or memory)
	double	**u,		// (out) generated pattern: u[N][N]
	int		N,			// size of the layer:  N*N = 64*64 or 65*65
	double	sat,		// saturation factor
	int		t,			// sequence number of the pattern to be generated
	int		T0,			// starting no. of patterns to be read from file
	int		TT,			// total no. of patterns to be read from file
	int		TTmax,		// maximum possible TT
	char	fnameETL[]	// name of ETL1 file (fpETL)
);


#define MAXSTRING 65536
#define UDEFAULT 65

// Gateway function
void mexFunction( int nlhs, mxArray *lhs[], int nrhs, const mxArray *rhs[] )
{
	int i, size, start, end, t;
	int T_max = 400;
	const int Lpat = 2052; // unit record length for ETL1
	double sat;
	char fname[MAXSTRING];
	static double udat[UDEFAULT*UDEFAULT], *umat[UDEFAULT];
	static int IsFirstCall = 1;
	struct stat st;

	if( IsFirstCall == 1 ){
		int i;
		umat[0] = &udat[0];
		for( i = 1 ; i < UDEFAULT ; i++ ){
			umat[i] = umat[i-1] + UDEFAULT;
		}
		IsFirstCall = 0;
	}

	if( nrhs < 1 ){
		mexErrMsgTxt( "PatTest requires 4 input arguments: filename, [pattern size], [start number], and [end number]" );
	}
	if( nlhs != 1 ){
		mexErrMsgTxt( "PatTest requires 1 output argument: pattern matrix" );
	}

	if( mxIsChar(FNAME_IN) != 1 ){
		mexErrMsgTxt( "File name must be a string." );
	}
	mxGetString( FNAME_IN, fname, MAXSTRING-1);
	if( stat( fname, &st ) != 0 ){
		mexPrintf( "File '%s' does not exist. ", fname );
		mexErrMsgTxt( "stat() was failed." );
	}
	T_max = st.st_size / Lpat; // max pattern numbers for ETL1 data
	mexPrintf( "%s contains %d patterns\n", fname, T_max );

	if( nrhs < 2 )		size = UDEFAULT;
	else				size = (int)mxGetScalar( USIZE_IN );
	if( size != 64 && size != 65 ){
		mxErrMsgTxt( "Pattern size should be 64 or 65. This is specification of Fukushima's Neocognitron." );
	}

	if( nrhs < 3 )		start = 0;
	else				start = (int)mxGetScalar( TSTART_IN ); // How can I validate the argument?
	if( nrhs < 4 )		end = T_max;
	else				end = (int)mxGetScalar( TEND_IN );  // How can I validate the argument?

	if( nrhs < 5 )		sat = 0.5;
	else				sat = mxGetScalar( SAT_IN );

	t = 10;
	pat( umat, size, sat, t, start, end, T_max, fname );

	U_OUT = mxCreateDoubleMatrix( size, size, mxREAL );
	mxSetPr( U_OUT, udat );

	return;
}
