#ifndef __NEOCOG_PROTO_H__
#define __NEOCOG_PROTO_H__

#ifdef NEOCOG_MATLAB

double ***getp(			// memory for 1-D pointer array **u[L]
	int		L
	);
double *get1D(			// get memory for 1-D array m[N]
	int		N
	);
int *get1Di(			// get memory for 1-D int array m[N]
	int		N
	);
double **get2D(			// get memory for 2-D array u[N1][N2]
	int		N1,
	int		N2
	);
int **get2Di(			// get memory for 2-D int array m[N1][N2]
	int		N1,
	int		N2
	);
unsigned char **get2Dc(	// get memory for 2-D unsigned char array ch[N1][N2]
	int		N1,
	int		N2
	);
double ***geta3D(		// get addable memory for 3-D array u[K][N1][N2]
	int		K,			// initial array size
	int		N1,
	int		N2,
	int		Kmax		// maximum possible array size: u[Kmax][N1][N2]
	);
void add3D(				// add memory to 3-D array u[K][N1][N2]
	double	***u,		// (in) u = (double ***)malloc(sizeof(double **) * Kmax)
	int		Knew,		// new array size
	int		N1,
	int		N2,
	int		Kmax		// maximum possiboe array size
	);
double ****geta4D1(		// get addable memory for 1-D pointer array ***a[]
	int		Kmax		// maximum possible pointer array size: ***a[Kmax]
	);
void add4D2(			// add memory to 2-D pointer array **a[K][Kc]
	double	****a,		// (in) a = (double ****)malloc(sizeof(double *) * Kmax)
	int		Knew,		// new pointer array size: **a[Knew][Kc]
	int		Kc,
	int		Kmax		// maximum possible array size: **a[Kmax][Kc]
	);
void Sres(				// response of S-layer
	double	***us,		// (out) response of S-cells: us[Ks][Ns][Ns]
	double	***uc,		// (in) response of C-cells: uc[Kc][Nc][Nc]
	double	****as,		// (in) exc. connections to S-cells: as[Ks][Kc][Na][Na]
	double	**cs,		// (in) exc. connections to V-cells: cs[Na][Na]
	double	*bs,		// (in) inh. connections to S-cells: bs[Ks]
	int		Nc,			// size of the C-layer: (nc*2) or (nc*2+1)
	int		Kc,			// number of cell-planes in C-layer
	int		Ns,			// size of the S-layer: (ns*2) or (ns*2+1)
	int		Ks,			// numberof cell-planes in S-layer
	int		Na,			// size of the connections (as & cs): (na*2) or (na*2+1)
	int		NcMAX,		// max of Nc (and Ng) among all stages
	int		NsMAX,		// max of Ns among all stages
	double	theta		// threshold of an S-cell
	);
void Cres(				// response of C-layer
	double	***uc,		// (out) response of C-cells: uc[K][Nc][Nc]
	double	***us,		// (in) response of S-cells: us[K][Ns][Ns]
	double	**ac,		// (in) exc. connections to C-cells: ac[Nd][Nd]
	int		Ns,			// size of the S-layer: (ns*2) or (ns*2+1)
	int		Nc,			// size of the C-layer: (nc*2) or (nc*2+1)
	int		mc,			// ratio of thinning-out
	int		K,			// number of cell-planes in S- and C-layers (K=Ks=Kc)
	int		Nd,			// size of the connections (ac): (nd*2) or (nd*2+1)
	int		NsMAX		// max of Ns among all stages
	);
int CresL(				// response of C-layer without lateral inhibition
	double	***uc,		// (out) response of C-cells: uc[Kc][1][1]
	double	***us,		// (in) response of S-cells: us[K][Ns][Ns]
	int		*cat,		// (in) category of the S-plane: cat[Ks]
	int		Ns,			// size of the S-layer: (ns*2) or (ns*2+1)
	int		Ks,			// number of cell-planes in S-layers (Ks)
	int		Kc			// number of cell-planes in C-layers (Kc)
	);
void onoff(				// response of on- & off-center cell layers
	double	***uc,		// (out) response of on- & off-center cells: uc[2][Nc][Nc]
	double	**us,		// (in) response of receptor cells: us[Ns][Ns]
	double	**cg,		// (in) connections for on-center: cg[Ng][Ng]
	int		Ns,			// size of the receptor layer: (ns*2) or (ns*2+1)
	int		Nc,			// size of the on- & off-center cell layer: (nc*2) or (nc*2+1)
	int		Ng			// size of the connections (ag): (ng*2) or (ng*2+1)
	);
void make_cg(			// make connections for on-center
	double	**cg,		// (out) Connections: cg[Ng][Ng]
	int		Ng,			// size of connection cg: (ng*2) or (ng*2+1)
	double	Ag,			// radius of the off-periphery (connect. area)
	double	Ago,		// radius of the on-center component
	double	gamcg		// spatial decay at x=Ag
	);
void make_ac(			// make center surround connections ac
	double	**ac,		// (out) Connections: ac[Na][Na]
	int		Na,			// size of the connection ac: (na*2) or (na*2+1)
	double	A,			// radius of the off-periphery (connect. area)
	double	Ao,			// radius of the on-center component
	double	gamma,		// spatial decay of exc. connect. at x=Ao
	double	gammao,		// spatial decay of inh. connect. at x=Ao
	double	gammap,		// spatial decay of inh. connect. at x=A
	double	co,			// value of ac[][] at the center
	double	pn			// ratio of negative to positibe components
	);
void make_c(			// make connections (spatial weight)
	double	**c,		// (out) Connections: c[Na][Na]
	int		Na,			// size of the connection A: (na*2) or (na*2+1)
	double	A,			// radius of the connectable area
	double	gamma,		// spatial decay at x=A
	double  co			// value of c[][] at the center
	);
void angle(				// draw an angle of ang degree
	double	**u,		// (out) generated pattern: u[N][N]
	int		N,			// size of the layer
	int		K,			// number of different orientations
	int		k,			// sequence number of the orientation of the edge
	double	ang,		// angle (in degree) of the bend
	double	x0,			// x offset of the center of the pattern
	double	y0			// y offset of the center of the pattern
	);
void edge(
	double	**u,		// (i/o) generated pattern: u[N][N]
	int		N,			// size of the layer
	double	xs,
	double	ys,			// edge from (xs,ys) to (xe,ye)
	double	xe,
	double	ye
	);
int Sorg(				// self-organization of S-layer
	double	****as,		// (out) exc. connections to S-cells: as[Ks][Kc][Na][Na]
	double	*bs,		// (out) inh. connections to S-cells: bs[Ks], new Ks
	double	***uc,		// (in) response of C-cells: uc[Kc][Nc][Nc]
	double	**cs,		// (in) spatial weight: cs[Na][Na]
	double	**asini,	// (in) exc. initial connections to S-cells: as[Na][Na]
	double	**cl,		// (in) connect. for lat.inh. from us to usini: cl[Nl][Nl]
	double	***us,		// (work) response of S-cells: us[Ks][Ns][Ns], old Ks
	int		Nc,			// size of the C-layer:  (nc*2) or (nc*2+1)
	int		Kc,			// number of cell-planes in C-layer
	int		Ns,			// size of the S-layer:  (ns*2) or (ns*2+1)
	int		Ks,			// number of cell-planes in S-layer, old value
	int		Na,			// size of connections (as & cs):  (na*2) or (na*2+1)
	int		Nasini,		// size of connect. asini:  (nasini*2) or (nasini*2+1)
	int		Nl,			// size of connection cl (lat. inh. from us to usini):  Nl=nl*2+1
	double	D,			// radius of competition area
	double	qs,			// parameter determining the speed of learning
	double	theta,		// threshold of an S-cell
	int		Ksmax,		// maximum possible Ks
	int		KsMAX,		// max of KsMAX among all stages
	int		NcMAX,		// max of Nc (and Ng) among all stages
	int		NsMAX,		// max of Ns among all stages
	double	thrini		// threshold for cutting usini
	);
void delta(				// strengthen connections
	double	****as,		// (out) exc. connections to S-cells: as[Ks][Kc][Na][Na]
	double	*bs,		// (out) inh. connections to S-cells: bs[Ks]
	double	***uc,		// (in) response of C-cells: uc[Kc][Nc][Nc]
	double	**cs,		// (in) spatial weight: cs[Na][Na]
	int		Na,			// size of the connections (as & cs): (na*2) or (na*2+1)
	int		Nc,			// size of the C-layer: (nc*2) or (nc*2+1)
	int		Kc,			// numberof cell-planes in C-layer
	int		Ns,			// size of the S-layer: (ns*2) or (ns*2+1)
	int		kseed,		// cell-plane of the seed cell
	int		iseed,		// x-coordinate of the seed cell
	int		jseed,		// y-coordinate of the seed cell
	int		KsMAX,		// max of KsMAX among all stages, because KcMAX <= KsMAX
	double	qs			// parameter determining the speed of learning
	);
void seed(				// select seed cells
	int		*iseed,		// (out) x-coordinate of the k-th cell-plane: iseed[Ks]
	int		*jseed,		// (out) y-coordinate of the k-th cell-plane: jseed[Ks]
	double	***us,		// (in) response of S-cells: us[Ks][Ns][Ns]
	double	**wmax,		// (work) working area: wmax[Ns][Ns]
	int		**kwmax,	// (work) working area: kwmax[Ns][Ns]
	int		Ns,			// size of the S-layer
	int		Ks,			// number of cell-planes in S-layer
	int		NsMAX,		// max of Ns among all stages
	double	D			// radius of competition area
	);
void Sresini(			// response of seed-selecting plane
	double	**usini,	// (out) response of seed-selecting plane: usini[Ns][Ns]
	double	***uc,		// (in) response of C-cells: uc[Kc][Nc][Nc]
	double	**asini,	// (in) exc. initial connections to S-cells: as[Na][Na]
	int		Nc,			// size of the C-layer: (nc*2) or (nc*2+1)
	int		Kc,			// number of cell-planes in C-layer
	int		Ns,			// size of the S-layer: (ns*2) or (ns*2+1)
	int		Na,			// size of the connections (asini, as & cs): (na*2) or (na*2+1)
	int		NcMAX,		// max of Nc (and Ng) among all stages
	double	thrini		// threshold for cutting usini
	);
void seedini(			// select seed cells
	int		*iseed0,	// (out) x-coordinate of the k-th cell-plane: iseed0[1]
	int		*jseed0,	// (out) y-coordinate of the k-th cell-plane: jseed0[1]
	double	**usini,	// (in) response of S-cells: usini[Ns][Ns]
	int		Ns			// size of the S-layer
	);
void lat(				// lateral inhibition from uin to uout
	double	**ut,		// (i/o) cell-plane to be inhibited: ut[N][N]
	double	**uf,		// (in) inhibiting cell-plane: uf[N][N]
	double	**cl,		// (in) connections for lateral inhibition: cl[Nl][Nl]
	int		N,			// size of the layer
	int		Nl			// size of connection cl:  Nl=nl*2+1
	);
int SorgL(				// self-organization of S-layer (new cell-plane if winner is not from correct category)
	double	****as,		// (out) exc. connections to S-cells: as[Ks][Kc][Na][Na]
	double	*bs,		// (out) inh. connections to S-cells: bs[Ks], new Ks
	int		*cat,		// (out) category of the S-plane: cat[Ks]
	int		Cat,		// (in) category of the training pattern
	double	***uc,		// (in) response of C-cells: uc[Kc][Nc][Nc]
	double	**cs,		// (in) spatial weight: cs[Na][Na]
	double	**asini,	// (in) exc. initial connections to S-cells: as[Na][Na]
	double	***us,		// (work) response of S-cells: us[Ks][Ns][Ns], old Ks
	int		Nc,			// size of the C-layer:  (nc*2) or (nc*2+1)
	int		Kc,			// number of cell-planes in C-layer
	int		Ns,			// size of the S-layer:  (ns*2) or (ns*2+1)
	int		Ks,			// number of cell-planes in S-layer, old value
	int		Na,			// size of the connections (as & cs): (na*2) or (na*2+1)
	int		Nasini,		// size of the connect. asini:  (nasini*2) or (nasini*2+1)
	double	qs,			// parameter determining the speed of learning
	double	theta,		// threshold of an S-cell
	int		Ksmax,		// maximum possible Ks
	int		KsMAX,		// max of KsMAX among all stages, because KcMAX <= KsMAX
	int		NcMAX,		// max of Nc (and Ng) among all stages
	int		NsMAX,		// max of Ns among all stages
	FILE	*fpT		// (in) file pointer for debugging.  If ==NULL, no debugging
	);
void rwcon(				// read/write connections.  Also get memores as and bs, in the read mode
	FILE	*fpC,		// (in) file pointer
	char	*fnameC,	// (in) file name
	double	*****as,	// (i/o) exc. connect. to S-cells: as[L][Ks][Kc][Na][Na]
	double	**bs,		// (i/o) inh. connect. to S-cells: bs[L][Ks]
	int		**cat0,		// (i/o) category of the cell-plane UsL: cat0[1][KsL]=cat[Ks]
	int		*Na,		// (in) size of connect. as
	int		*Kc,		// (i/o) no. of C-cell-planes: Kc[L+1]
	int		*Ks,		// (i/o) no. of S-cell-planes: Ks[L]
	int		*Mas,		// (i/o) no. of active as[L][Ks][Kc]: Mas[L]
	int		L,			// number of stages
	int		learn		// switch:  if (learn>0) write, else read.  If (learn<0) up to (-learn-1)
	);
void printu(
	FILE	*fp,		// (in) file pointer
	double	***u,		// (in) layer to be printed: u[K][N][N]
	int		N,			// size of a cell-plane: (n*2+1) or (n*2)
	int		K,			// number of cell-planes
	char	title[],	// title to be printed
	int		l,			// stage number to be printed in the title. if (l<0) no print
	int		KMAX		// >0: maximum possible K, Initialize only, No printing.  ==0: print response
	);
void outH(				// hexadecinmal output of the response of a layer
	FILE	*fp,		// (in) file pointer
	double	***u,		// (in) layer to be printed: u[K][N][N]
	int		N,			// size of a cell-plane: (n*2) or (n*2+1)
	int		K,			// number of cell-planes
	char	title[],	// title to be printed
	int		l,			// stage number in the title. if (l==-1) no number; if (l==-2) no title
	int		KMAX		// >0: maximum possible K, Initialize only, No output.  ==0: write output
	);
void outHhead(			// write header of hexadecinmal output file fpN
	FILE	*fpN,		// (in) file pointer
	char	fnameNh[],	// header of fnameN (fpNh)
	int		Npages		// no. of pages. >0: all data in one ps file.  =0: separate eps files.
	);
void printuadd(			// print sum of k1-th to k2-th cell-planes
	FILE	*fp,		// (in) file pointer
	double	***u,		// (in) layer to be printed: u[K][N][N]
	int		N,			// size of a cell-plane: (n*2) or (n*2+1)
	char	title[],	// title to be printed
	int		l,			// stage number to be printed in the title. if (l<0) no print
	int		k1,			// added cell-planes from k1
	int		k2			// added cell-planes to k2
	);
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)
	);
void score(				// make confusion matrix
	int		**mat,		// (i/o) confusion matrix: mat[KcL][KcL+1]
	int		recCat,		// result of recognition
	int		Cat,		// category of the input pattern
	int		KcL			// number of categories
	);
void printsc(			// print confusion matrix
	FILE	*fp,		// (in) file pointer
	int		**mat,		// (in) confusion matrix: mat[KcL][KcL+1]
	int		KcL			// number of categories
	);
void ErrOut(			// hexadecinal output of erroneously recognized patterns
	double	***u,		// (in) layer to be printed: u[1][N][N]
	int		N,			// size of a cell-plane: (n*2) or (n*2+1)
	char	fnameE[],	// file name (fpE), erroneously recognized patterns
	char	fnameEh[],	// header of fnameE (fpEh)
	int		iend		// if (iend==1), no more output (close file)
	);
#endif /* NEOCOG_MATLAB */

#endif /* __NEOCOG_PROTO_H__ */
