/* SIMPINPUT.C */
/*-
routines for input of data and control values for simplex minimization:
  
the routine is (essentially) independent of the function and data to be fit
	(coded in XXXXFIT), and it generally need not be altered when 
	XXXXFIT is modified.
  
The code is particularly clumsy, and may reflect porting from Fortran to
CP/M Basic, to CP/M C, to UNIX -- in its travels with me over the last
15+ years.
  
J.A. Rupley, Tucson, Arizona
rupley!local@megaron.arizona.edu
*/

#define SIMPINPUT

#include "simpdefs.h"

#define MANYITER	10000

/*-
READ_DATA
	ENTRY OF TITLE, CONTROL VARIABLES, STARTING SIMPLEX, AND DATA
		FROM DISK FILE
	MANIPULATION OF DATA PRIOR TO FITTING SHOULD BE DONE HERE (OR IN
		MAIN())
	THE DISK DATA FILE IS FREE-FORM (IE, WITHOUT FIELD WIDTHS), 
		BUT THE SEQUENCE OF ENTRIES MUST BE EXACTLY AS BELOW
	THE MNEMONIC IDENTIFIERS MUST BE IN THE DATA FILE (THEY ARE
		DISCARDED IN THE READ, BUT ARE ASSUMED TO BE PRESENT)
	THE IDENTIFIERS CANNOT CONTAIN WHITE SPACE
	THE ONE-LINE & < 80 CHAR TITLE CANNOT CONTAIN CONTROL CHARACTERS
*/

int
read_data(fp_out, fptr)
FILE           *fp_out;
FILE           *fptr;
{
	register int    i, j;
	char            dummy[200];

	extern char    *str_in();
	extern char    *num_in();
	extern void     fdatprint();
	extern void     fpprint();
	extern void     fsprint();
	extern void     use_mess();
	extern          func();

	extern double   atof();
	extern void     enditall();

	/*
	 * read and print title 
	 */
	for (i = 0; i < 79; i++) {
		if (iscntrl(title[i] = getc(fptr)))
			break;
	}
	title[i] = '\0';
	fprintf(fp_out, "\n%-s\n\n", title);

	/*
	 * read and print nvert, nparm, ndata, ndatval 
	 */
	if (str_in(fptr, dummy) != NULL)
		enditall();
	fprintf(fp_out, "nvert = %d\n",
		nvert = atoi(num_in(fptr, dummy)));
	if ((nvert <= 0) || (nvert > (NPARM + 1)))
		enditall();
	if (str_in(fptr, dummy) != NULL)
		enditall();
	fprintf(fp_out, "nparm = %d\n",
		nparm = atoi(num_in(fptr, dummy)));
	if ((nparm <= 0) || (nparm > NPARM))
		enditall();
	if (str_in(fptr, dummy) != NULL)
		enditall();
	fprintf(fp_out, "ndata = %d\n",
		ndata = atoi(num_in(fptr, dummy)));
	if ((ndata <= 0) || (ndata > NDATA))
		enditall();
	if (str_in(fptr, dummy) != NULL)
		enditall();
	fprintf(fp_out, "ndatval = %d\n",
		ndatval = atoi(num_in(fptr, dummy)));
	if ((ndatval <= 0) || (ndatval > NDATVAL))
		enditall();
	nfree = nvert - 1;

	/*
	 * read and print iter, maxiter, exit_test, prt_cycle, quad_test 
	 */
	if (str_in(fptr, dummy) != NULL)
		enditall();
	fprintf(fp_out, "iter = %d\n",
		iter = atoi(num_in(fptr, dummy)));
	if ((iter < 0) || (iter > MANYITER))
		enditall();
	if (str_in(fptr, dummy) != NULL)
		enditall();
	fprintf(fp_out, "maxquad_skip = %d\n",
		maxquad_skip = atoi(num_in(fptr, dummy)));
	if ((maxquad_skip < 0) || (maxquad_skip > MANYITER))
		enditall();
	if (str_in(fptr, dummy) != NULL)
		enditall();
	fprintf(fp_out, "exit_test = %20.14e\n",
		exit_test = atof(num_in(fptr, dummy)));
	if ((exit_test <= 0))
		enditall();
	if (str_in(fptr, dummy) != NULL)
		enditall();
	fprintf(fp_out, "prt_cycle = %d\n",
		prt_cycle = atoi(num_in(fptr, dummy)));
	if ((prt_cycle < 0) || (prt_cycle > MANYITER))
		enditall();
	if (str_in(fptr, dummy) != NULL)
		enditall();
	fprintf(fp_out, "quad_test = %20.14e\n",
		quad_test = atof(num_in(fptr, dummy)));
	if ((quad_test < 0))
		enditall();

	/*
	 * read and print simplex 
	 */
	if (str_in(fptr, dummy) != NULL)
		enditall();
	fprintf(fp_out, "\n\n%-79s\n", dummy);
	for (j = 0; j < nvert; j++) {
		for (i = 0; i < nparm; i++) {
			p[j].parm[i] = atof(num_in(fptr, dummy));
			fprintf(fp_out, "vert[%d].parm[%d] = %20.14e\n",
				j, i, p[j].parm[i]);
		}
	}

	/*
	 * read and print bounds, if present 
	 */
	if (str_in(fptr, dummy) != NULL)
		enditall();
	if (strncmp(dummy, "parm-bounds", 11) == 0) {
		fprintf(fp_out, "\n\n%-79s\n", dummy);
		for (j = 0; j < 2; j++) {
			for (i = 0; i < nparm; i++) {
				bounds[j][i] = atof(num_in(fptr, dummy));
				fprintf(fp_out, "bounds[%d][%d] = %20.14e\n",
					j, i, bounds[j][i]);
			}
		}
		if (str_in(fptr, dummy) != NULL)
			enditall();
	}

	/*
	 * read and print data array 
	 */
	fprintf(fp_out, "\n\n%-79s\n", dummy);
	for (j = 0; j < ndata; j++) {
		for (i = 0; i < ndatval; i++) {
			char dummyxxx[200];
			strcpy(dummyxxx, num_in(fptr, dummy));
			data[j].datval[i] = atof(dummyxxx);
		}
	}
	maxiter = 0;
	fdatprint(fp_out);

	/*
	 * calculate function values and print simplex 
	 */
	fprintf(fp_out, "\n\ncalculating function values: ");
	for (j = 0; j < nvert; j++) {
		func(&p[j]);
		fprintf(fp_out, "%d ", j);
	}
	fsprint(fp_out, "\n\nsimplex:\n");
	return (OK);
}				/* END OF READ_DATA			 */

void
use_mess()
{
	puts("\nUsage:");
	puts("xxxxfit   [-s a,c,l,n] [-d a,c,l,n] [[-i] inputfile [[-o] diskfile]");
	puts("   -s and -d control output to terminal and diskfile;");
	puts("           a = ALL possible output;              c = ouput each CYCLE");
	puts("           l = output on LAST cycle only;        n = NO output;");
	puts("   output to terminal defaults to ALL possible output to stdout;");
	puts("   inputfile and diskfile default to stdin and /dev/null;");
	puts("   the input file has the following structure:");
	puts("     one-line title, with no tabs or ctrl characters;");
	puts("     lines following give control variables, the starting simplex,");
	puts("              and the data array;");
	puts("     the order of entry is fixed by the order in <read_data()>;");
	puts("              see template file for structure;");
	puts("     the one-word descriptors must be present in the data file;");
	puts("     the data format is free-form (no set field widths);");
	puts("     comments at the end of the file are not read by the program");
}				/* END OF USE_MESS			 */

char           *
str_in(fptr, dummy)
	char           *dummy;
	FILE           *fptr;
{
	register int    i;

	while (isspace(dummy[0] = getc(fptr)));
	for (i = 1; !isspace(dummy[i] = getc(fptr)); i++);
	dummy[i] = '\0';
	if (isalpha(dummy[0]))
		return (NULL);
	else
		return (&dummy[0]);
}				/* END OF *STR_IN */

char           *
num_in(fptr, dummy)
	char           *dummy;
	FILE           *fptr;
{
	int             i;

	while (isspace(dummy[0] = getc(fptr)));
	for (i = 1; !isspace(dummy[i] = getc(fptr)); i++);
	dummy[i] = '\0';
	return (&dummy[0]);
}				/* END OF *NUM_IN */
