/*
 * given a fileroot, open up basic files and set up network
 */
#include  <stdio.h>
#include  <sys/file.h>
#include  <sys/types.h>
#include  <math.h>
#include  "defs.h"

extern FILE	*datafp;
extern FILE	*teachfp;
extern FILE	*ifp;
extern FILE	*tfp;
extern FILE	*errfp;
extern FILE	*cmdfp;
extern int	ndtokens;
extern float	rate ;
extern int	insize;
extern float	tsize;
extern float	**d_tokenp;
extern float	**t_tokenp;
extern float	**tp;
extern float	*dp;
extern float	**lp;
extern float	*type_index;
extern float	*tip;
extern float	*extract_end;
extern float	momentum ;
extern float	olderr ;
extern float	noise ;
extern int	width ;
extern int	height ;
extern int	debug;	
extern int	decayflag; 
extern int	nobias; 
extern int	sequential; 
extern long	sweeps;
extern int	array;
extern int	errsig;
extern int	pat_err;
extern int	continuous;
extern int	linflag;
extern int	dispout;
extern long	check;
extern int	printout;
extern int	printhid;
extern int	test;
extern int	extract;
extern int	cur_token;
extern int	types;
extern int	autoen;
extern int	advance;
extern int	nolearn;
extern int	interactive;
extern char	**type_list;
extern char	fileroot[];
extern char	datafile[];
extern char	teachfile[];
extern char	indexfile[];
extern char	typefile[];
extern char    errfile[128];
extern char    cmdfile[128];
extern char    title[80];
extern	float global_error;
extern	float **layerp;
extern	float *nodep;
extern	int buildin();
extern	int ransi();
extern	int *layer_descp;
extern	int roll();
extern	int optind;
extern	int numin;
extern	int numout;
extern 	int num_hidden;	
extern	int nh;
extern	int nlayers;
extern	char *malloc();
extern	char *optarg;
extern	int numtotal;
extern	int rbp;

setup(fileroot)
	char	*fileroot;
{
	extern	char *calloc();
	extern	int context;
	extern	FILE *rootfile();
	FILE	*fopen();
	int	i;
	int	j;
	int	tim;
	int	freq;
	int	*ldp;
	char	buf[80];
	float	f;
	int	nread;

	/*
	 * Read in the config file and configure the network
	 * before anything else, since we need to know the dimensions
	 * of the input/output arrays; then read in data
	 */
	if (config(fileroot) < 0) {
		return -1;
	}
	datafp = rootfile(datafile, "data", "r");
	teachfp = rootfile(teachfile, "teach", "r");
	if (errsig || pat_err) {
		errfp = rootfile(errfile, "err", "w+");
 	}
	/*
	 * if recurrent back prop, we need the data and teacher
	 * files in different format
	 */
	if (rbp == 0) {
		/*
		 * get basic information about format of datafile
		 */
		nread = 0;
		nread += fscanf(datafp,"%d",&ndtokens);
		nread += fscanf(datafp,"%d",&tim);
		nread += fscanf(datafp,"%d",&freq);
		if (nread != 3)
			inputerr(datafile, "ndtokens, tim, or freq");
		if (ndtokens < 1 || tim < 1 || freq < 1) {
			fprintf(stderr, "%s: data file header error\n",
				datafile);
			exit(0);
		}
		insize = tim * freq;
		/*
		 * allocate space for ndtokens number of data token pointers
		 */
		d_tokenp = (float **)
			malloc((u_int)ndtokens * sizeof(float *));
		/*
		 * now allocate a block of space for each of our ndtokens;
		 * we need tim*freq number of float for each of our ndtokens,
		 * so allocate that space and store the address of the space
		 * reserved for each pointer in the right d_tokenp.
		 */
		if (continuous == 0) {
			for (i=0, tp=d_tokenp ; i<ndtokens; i++, tp++) {
				*tp =(float *)malloc((u_int)*layer_descp * sizeof(float));
				if (*tp == NULL) {
					fprintf(stderr, "malloc err on data token space\n");
					exit(1);
				}
			}
		} else if ((extract == 1) || (continuous == 1)) {
			*d_tokenp = (float *)
				malloc((u_int)insize * sizeof(float));
		}
		/*
		 * allocate space for nttokens number of teacher token pointers
		 * (same number of teacher tokens as data tokens)
		 * If we are autoencoding, then we just copy the d_tokenp and
		 * always use the same data as the teacher.
		 */
		if (autoen == 0) {
			t_tokenp = (float **)
				malloc((u_int)ndtokens * sizeof(float *));
		} else if (autoen == 1) {
			t_tokenp = d_tokenp;
		}
		/*
		 * now allocate a block of space for each of our teacher tokens
		 * the size of a given teacher token can be retrieved from the
		 * layer_descp stuff we read in from config()
		 * If we are in test mode, then only need space for one token.
		 * If we are autoencoding, then we skip this, since the 
		 * teacher pointers have already been set equal to the data
		 * token pointers.
		 */
		tsize = *(layer_descp+nlayers-1);
		if (autoen == 0) {
			if (continuous == 0) {
				for (i=0, tp=t_tokenp ; i<ndtokens; i++, tp++) {
					*tp = (float *) malloc((u_int)(int)tsize * sizeof(float));
					if (*tp == NULL) {
						fprintf(stderr,"malloc err on teacher token space\n");
						exit(1);
					}
				}
			} else if ((extract == 1) || (continuous == 1)) {
				*t_tokenp = (float *)
					malloc((u_int)insize * sizeof(float));
			}
			if (*t_tokenp == NULL) {
				fprintf(stderr,
					"malloc err on teacher tokenp space\n");
				exit(1);
			}
		}
		/*
		 * read in the index of types for each token; if a typefile
		 * is specified with type labels, retrieve those
		 */
		ifp = rootfile(indexfile, "index", "r");
		tfp = rootfile(typefile, "types", "r");
		/*
		 * first line number of different types
		 */
		fscanf(tfp, "%d\n", &types);
		type_list = (char **) calloc(sizeof(char *), types);
		for (i=0; i<types; i++)  {
			if (fscanf(tfp, "%s\n", buf) != 1) {
				fprintf(stderr, "%s: ran out of types\n",
					typefile);
				break;
			}
			type_list[i] = (char *) malloc((u_int)strlen(buf)+1);
			strcpy(type_list[i], buf);
		}
		/*
		 * calculate info for activation display;
		 * need to know total number of units in hidden layers, i.e.,
		 * sum of units in all but first and last layers
		 */
		num_hidden = 0;
		if (array == 0) {
			for (i=1, ldp=(layer_descp+1); i<(nlayers-1); i++, ldp++) {
				    num_hidden += *ldp;
				    nh = num_hidden;
			}
			if (dispout == 1)
				nh = *(layer_descp+nlayers-1);
		} else if (array == 1) {
			num_hidden = numtotal - (numin + numout);
			if (dispout == 1)
				nh = numout;
			else 
				nh = num_hidden;
		}
		type_index = (float *)malloc((u_int)ndtokens * sizeof(float));
		if (type_index == NULL) {
			fprintf(stderr,"malloc err on type_index space\n");
			exit(1);
		}
		/*
		 * the first number is number of tokens, throw away
		 */
		if (fscanf(ifp, "%f", &f) == 1) {
			for (i=0, tip = type_index; i<ndtokens; i++, tip++) {
				if (fscanf(ifp, "%f", &f) != 1)
					break;
				if (f < 0 || f >= types) {
					fprintf(stderr,
						"%s: invalid index %f\n",
						indexfile, f);
					exit(0);
				}
				*tip = f;
			}
		} else
			fprintf(stderr, "warning: empty file %s\n", indexfile);
		/*
 		 * read in the tim*freq floating point numbers for data tokens;
		 * convert from ascii to binary floats; if we are in test
		 * mode, only need to read in designated token;
		 * If have context, layer_descp is too big.
		 */
		if (continuous != 1) {
			for (i=0, tp=d_tokenp ; i<ndtokens; i++, tp++) {
				int max;
				if (context == 1)
					max = *layer_descp - num_hidden;
				else
					max = *layer_descp;
				nread = 0;
				for (j=0, dp = *tp; j < max; j++, dp++)
					nread += fscanf(datafp, "%f", dp);
				if (nread != max)
					inputerr(datafile, "data tokens");
			}
		} else if (continuous == 1) {
			/* 
			 * we need insize rather than *layer_descp here
			 */
			nread = 0;
			for (j=0, dp = *d_tokenp; j<insize; j++, dp++)
				nread += fscanf(datafp, "%f", dp);
			if (nread != insize)
				inputerr(datafile, "data tokens");
#define FMSIZE 20
			extract_end = dp - FMSIZE;
		}
		/*
		 * read in the floating point numbers for teacher tokens;
		 * convert from ascii to binary floats
		 * If we are in test mode, only need to read in
		 * designated token.
		 * (Throw away some initial garbage first.)
		 */
		fscanf(teachfp,"%*f");
		fscanf(teachfp,"%*f");
		fscanf(teachfp,"%*f");
		if (continuous == 1)
			tsize = insize;
		nread = 0;
		for (i=0, tp=t_tokenp ; i<ndtokens; i++, tp++) {
			for (j=0, dp = *tp; j<tsize; j++, dp++) {
				nread += fscanf(teachfp, "%s", buf);
				/*
				 * if teacher pattern is *, then
				 * mark this as a don't care spot;
				 * delta[12].c will set error to 0
				 * when tp < -999999999.0
				 */
				if (buf[0] == '*')
					*dp = -999999999.0;
				else
					*dp = (float) atof(buf);
			}
		}
		if (nread != ndtokens * tsize)
			inputerr(teachfile, "input pattern");
	} else if (rbp == 1) {
		/*
		 * get basic information about format of datafile;
		 * for RBP we will only use ndtokens, however.
		 */
		fscanf(datafp,"%d",&ndtokens);
		fscanf(datafp,"%*d");
		fscanf(datafp,"%*d");
		if (ndtokens < 1) {
			fprintf(stderr, "%s: data file header error\n",
				datafile);
			exit(0);
		}
		/*
		 * allocate space for ndtokens number of data token pointers
		 */
		d_tokenp = (float **)
			malloc((u_int)ndtokens * sizeof(float *));
		/*
		 * now allocate a block of space for each of our ndtokens;
		 * we need numtotal number of float for each of our ndtokens,
		 * so allocate that space and store the address of the space
		 * reserved for each pointer in the right d_tokenp.
		 */
		for (i=0, tp=d_tokenp ; i<ndtokens; i++, tp++) {
			*tp =(float *)malloc((u_int)numtotal * sizeof(float));
			if (*tp == NULL) {
				fprintf(stderr,"malloc err on data token\n");
				exit(1);
			}
		}
		/*
		 * allocate space for nttokens number of teacher token pointers
		 * (same number of teacher tokens as data tokens)
		 * If we are autoencoding, then we just copy the d_tokenp and
		 * always use the same data as the teacher.
		 */
		t_tokenp = (float **) malloc((u_int)ndtokens * sizeof(float *));
		if (t_tokenp == NULL) {
			fprintf(stderr,"malloc err on teacher tokenp space\n");
			exit(1);
		}
		/*
		 * now allocate a block of space for each of our teacher tokens
		 */
		for (i=0, tp=t_tokenp ; i<ndtokens; i++, tp++) {
			*tp = (float *) malloc((u_int)numtotal * sizeof(float));
			if (*tp == NULL) {
				fprintf(stderr,"malloc err on teacher token\n");
				exit(1);
			}
		}
		/*
		 * read in the index of types for each token; if a typefile
		 * is specified with type labels, retrieve those
		 */
		ifp = rootfile(indexfile, "index", "r");
		tfp = rootfile(typefile, "types", "r");
		/*
		 * first line number of different types
		 */
		if (fscanf(tfp, "%d\n", &types) != 1)
			inputerr(typefile, "number of types");
		type_list = (char **) calloc(sizeof(char *), types);
		nread = 0;
		for (i=0; i<types; i++)  {
			nread += fgets(buf, sizeof(buf), tfp) != 0;
			type_list[i] = (char *) malloc((u_int)strlen(buf)+1);
			strcpy(type_list[i], buf);
		}
		if (nread != types)
			inputerr(typefile, "not enough types");
		/*
		 * calculate info for activation display;
		 * since rbp has no notion of I/H/O units, we will
		 * treat all units as hidden
		 */
		num_hidden = numtotal;
		nh = num_hidden;
		type_index = (float *)malloc((u_int)ndtokens * sizeof(float));
		if (type_index == NULL) {
			fprintf(stderr,"malloc err on type_index space\n");
			exit(1);
		}
		/*
		 * the first number is number of tokens, throw away
		 */
		fgets(buf, 80, ifp);
		nread = 0;
		for (i=0, tip = type_index; i<ndtokens; i++, tip++) {
			nread += fscanf(ifp, "%d", tip);
			if (*tip < 0 || *tip >= types) {
				fprintf(stderr, "%s: invalid index %f\n",
					indexfile, f);
				exit(0);
			}
		}
		if (nread != ndtokens)
			inputerr(typefile, "not enough types");
		/*
		 * read in the data tokens; convert from ascii to binary floats;
		 * the non-input nodes are marked with "*'" which we convert
		 * to some distinctive value (and then ignore during activate2()
		 */
		nread = 0;
		for (i=0, tp=d_tokenp ; i<ndtokens; i++, tp++) {
			for (j=0, dp = *tp; j < numtotal; j++, dp++) {
				nread += fscanf(datafp, "%s", buf);
				if (buf[0] == '*')
					*dp = -999999999.0;
				else
					*dp = (float) atof(buf);
			}
		}
		if (nread != ndtokens * numtotal)
			inputerr(datafile, "not enough input tokens");
		/*
		 * read in the floating point numbers for teacher tokens;
		 * convert from ascii to binary floats
		 * (Throw away some initial garbage first.)
		 */
		fscanf(teachfp,"%*f");
		fscanf(teachfp,"%*f");
		fscanf(teachfp,"%*f");
		nread = 0;
		for (i=0, tp=t_tokenp ; i<ndtokens; i++, tp++) {
			for (j=0, dp = *tp; j<numtotal; j++, dp++) {
				nread += fscanf(teachfp, "%s", buf);
				/*
				 * if teacher pattern is *, then
				 * mark this as a don't care spot;
				 * delta[12].c will set error to 0
				 * when tp < -999999999.0
				 */
				if (buf[0] == '*')
					*dp = -999999999.0;
				else
					*dp = (float) atof(buf);
			}
		}
		if (nread != ndtokens * numtotal)
			inputerr(teachfile, "input patterns");
	}
	return 0;
}
