/* io.c:	Input/Output functions.
 *
 * Written by Daniel Barrett.  100% PUBLIC DOMAIN. */

#include "decl.h"


PrintComplex(comp)
/* Print a complex number. */
complex comp;
{
	double fabs();

	if (comp.n[REAL] >= 0)
		printf(" ");
	printf("%f%c%fi",	comp.n[REAL], 
				(comp.n[IMAG] < 0.0) ? '-' : '+',
				fabs(comp.n[IMAG]));
}

	
PrintPoly(poly, n)
/* Print the polynomial in a nice format. */
complex poly[];
int n;
{
	int i;

	printf("\nYour polynomial is:\n");
	printf("--------------------\n");
	for (i=0; i<n-1; i++) {
		PrintComplex(poly[i]);
		printf("	* X^%d	+\n", n-i);
	}
	PrintComplex(poly[n-1]);
	printf("	* X	+\n");
	PrintComplex(poly[n]);
	printf("\n\n");
}

	
ReadPoly(poly, degree, epsilon)
/* Read all data from the user:  the degree of the polynomial, the
 * accuracy desired, and the polynomial coefficients. */
complex poly[];
int *degree;
double *epsilon;
{
	ReadDegree(degree);
	ReadEpsilon(epsilon);
	TellUserWhatToDo();
	ReadCoefficients(poly, *degree);
}

	
ReadDegree(degree)
/* Prompt user for the degree of the polynomial.  Read it. */
int *degree;
{
	char buf[BUFSIZ];

	*degree = 0;
	do {
		printf("Degree of polynomial? (1..%d): ", MAX_DEGREE);
		gets(buf);
		*degree = atoi(buf);
	}while (*degree <= 0 || *degree > MAX_DEGREE);
}

	
ReadEpsilon(epsilon)
/* Prompt user for epsilon, the desired accuracy.  Read it.  If no
 * data, set epsilon to the default value. */
double *epsilon;
{
	char buf[BUFSIZ];
	double atof();

	do {
		*epsilon = EPSILON_DEFAULT;
		printf("Accuracy desired? [<RETURN> = %1.7f]: ", *epsilon);
		gets(buf);
 		if (strlen(buf))
			*epsilon = atof(buf);
	}while (*epsilon <= 0.0);
}

	
ReadCoefficients(poly, degree)
/* Read in the coefficients of the polynomial "poly".  NOTE that
 *  the array "poly" is backwards... poly[0] is the coefficient
 *  of X^degree, and so on. 
 * I use "strtok()", my version of the UNIX function, to get the input. */
complex poly[];
int degree;
{
	char buf[BUFSIZ], *tokeReal=NULL, *tokeImag=NULL, *strtok();
	static char separators[] = " \t\n\r";
	register int i;
	double atof();

	for (i=0; i <= degree; i++) {
Again:		printf("X^%d coefficient: ", degree-i);
		gets(buf);
		tokeReal = strtok(buf, separators);
		if (!tokeReal)
			goto Again;
		else if (NeedsHelp(tokeReal)) {
			Help();
			goto Again;
		}
		tokeImag = strtok((char *)NULL, separators);
		AssignComplex(&poly[i],	atof(tokeReal),
					tokeImag ? atof(tokeImag) : 0.0);
	}
}


PrintRoot(root, i)
/* Print the value of root "i" of the polynomial. */
complex root;
int i;
{
	printf("Root %d:  ", i);
	if (i<10)
		printf(" ");
	PrintComplex(root);
	printf("\n");
}

	
TellUserWhatToDo()
{
	printf("Enter the coefficients of your polynomial.  ");
	printf("Type \"H\" for help.\n");
}

	
static char *helpMessage[] = {
"",
"Enter the coefficients of your polynomial, one coefficient per line.",
"Note that \"X^n\" means \"X to the nth power\".",
"If the coefficient is REAL, simply enter it and press <RETURN>.",
"If the coefficient is COMPLEX, enter its real and imaginary terms,",
" separated by a space.  (Do not use the letter \"i\".)",
"",
NULL
};

	
Help()
/* Print the above help message. */
{
	char **s = helpMessage;
	do
		puts(*s);
	while (*(s++));
}


NeedsHelp(s)
/* Does the user need help? */
char *s;
{
	return(EQUAL(s, "H") | EQUAL(s, "h") | EQUAL(s, "?"));
}

	
Version()
{
	printf("[33mNewton V1.0[0m");
	printf(" by Daniel Barrett.  100%% PUBLIC DOMAIN.\n");
	printf("Estimate the roots of a polynomial numerically.\n");
	printf("Type ^C <RETURN> to abort this program.\n\n");
}
