/* inputPoly.cp */

#include "myTypedef.h"
#include "inputPoly.h"
#include "ExtComplex.h"
#include <string.h>
#include <stdlib.h>
#include "fpMath.h"
#include "fpConv.h"
#include <stdio.h>

/*
	This analyzes the string number in dataString and puts it in theNumber & returns true or false
*/
static bool getNumber(ExtComplex& theNumber, char* dataString, char* doubleString, char* singleString)
{
	int					i, j, length, index;
	char				ch;
	bool				hasLeftParen, hasRightParen, isNegative, hasComma;
	static ExtComplex	one;
	static bool			arrayGood=false;
	
	if(!arrayGood)
	{
		one.Re.i.n = one.Re.i.nn = 1;
		one.Re.e = 0;
		one.Re.i.b = (UINT32*)malloc(one.Re.i.nn*sizeof(UINT32));
		one.Re.i.b[0] = 1;
		one.Im.i.n = 0;
		arrayGood = true;
	}
	
	length = strlen(dataString);
	if(length==0)
	{
		EquateC_C(theNumber, one);
		return true;
	}
	
	// do we have Parentheses? In the right order?
	hasLeftParen = false;
	hasRightParen = false;
	for(i=0;i<length;i++)
	{
		ch = dataString[i];
		if(ch=='(')
		{
			index = i;
			hasLeftParen = true;
			break;
		}
		if(ch==')')
			return false;
	}
	
	if(hasLeftParen==true)
	{
		// check that we have a right paren
		for(i=index+1;i<length;i++)
			if(dataString[i]==')')
				hasRightParen = true;
			
		if(!hasRightParen)
			return false;
		
		// might have real or complex number
		// is there a sign
		isNegative = false;
		i = 0;
		ch = dataString[i];
		if(ch=='+' || ch=='-')
		{
			if(ch=='-')
				isNegative = true;
			i++;
		}
		// check that we have a left paren now
		if(dataString[i++]!='(')
			return false;
			
		// copy what's inside the parens to doubleString
		ch = dataString[i++];
		j = 0;
		while(ch!=')')
		{
			doubleString[j++] = ch;
			ch = dataString[i++];
		}
		doubleString[j] = 0;
		
		// get first or only single string
		length = strlen(doubleString);
		j = 0;
		i = 0;
		ch = doubleString[i];
		while(i<length && ch!=',')
		{
			singleString[j++] = ch;
			ch = doubleString[++i]; // now i points to current value of ch
		}
		singleString[j] = 0;
		
		
		if(!equate(theNumber.Re, singleString))
			return false;
		if(isNegative)
			theNumber.Re.i.n = -theNumber.Re.i.n;
		
		if(i>=(length-1))
		{
			theNumber.Im.i.n = 0;
			return true;
		}
		
		// now, since ch=',' we get the Im part
		j = 0;
		ch = doubleString[++i];
		while(i<length)
		{
			singleString[j++] = ch;
			ch = doubleString[++i];
		}
		singleString[j] = 0;
		if(!equate(theNumber.Im, singleString))
			return false;
		
		if(isNegative)
			theNumber.Im.i.n = -theNumber.Im.i.n;
		
		return true;
	}
	else
	{
		// have a real number
		
		// we should not have a comma
		hasComma = false;
		for(i=0;i<length;i++)
		{
			ch = dataString[i];
			if(ch==',')
			{
				hasComma = true;
				break;
			}
		}
		if(hasComma)
			return false;
		
		// is there a sign
		isNegative = false;
		i = 0;
		ch = dataString[i];
		if(ch=='+' || ch=='-')
		{
			if(ch=='-')
				isNegative = true;
			i++;
			// if there's only a sign we have a +/- 1
			if(i>=length)
			{
				
				equate(theNumber.Re, 1.);
				theNumber.Im.i.n = 0;
				if(isNegative)
					theNumber.Re.i.n = -theNumber.Re.i.n;
				return true;
			}
		}
		// get the rest of the number
		j = 0;
		ch = dataString[i];
		while(i<length)
		{
			singleString[j++] = ch;
			ch = dataString[++i];
		}
		singleString[j] = 0;
		if(!equate(theNumber.Re, singleString))
			return false;
		
		if(isNegative)
			theNumber.Re.i.n = -theNumber.Re.i.n;
		
		theNumber.Im.i.n = 0;
		
		return true;
	}
	
}/* getNumber */


/*
	Allows input of polynomial in forms:
	x^2-4x+4
	4-4x+x^2
	-4x+x^2+4
	x^2-(2,3)x+(4,-5)
	x^5+1
	etc.
	We presume that white spaces have been removed, and that the order n of the polynomial
	has been determined. coeffArray has already been created, but not yet initialized to zero.
	This sub fills this array and returns true or false.
*/
bool inputPoly(ExtComplex *coeffArray, int n, char *inputStr)
{
	int					i, j, length, thePower;
	char				ch;
	char				*dataString, *doubleString, *singleString;
	static ExtComplex	theNumber;
	static bool			arrayGood=false;
	
	if(!arrayGood)
	{
		init(theNumber);
		arrayGood = true;
	}
	
	length = strlen(inputStr);
	
	if(n==0 || length==0)
		return false;
	
	dataString = (char *)malloc((length+1)*sizeof(char));
	doubleString = (char *)malloc((length+1)*sizeof(char));
	singleString = (char *)malloc((length+1)*sizeof(char));
	
	for(i=0;i<n;i++)
	{
		//coeffArray[i].Re.i.n = 0;
		//coeffArray[i].Im.i.n = 0;
		equate(coeffArray[i].Re, 0.);
		equate(coeffArray[i].Im, 0.);
	}
	
	i = 0;
	getNext:
	j = 0;
	ch = inputStr[i];
	if(ch=='+' || ch=='-')
	{
		dataString[j++] = ch;
		ch = inputStr[++i];
	}
	if(ch=='(')
	{
		while(ch!=')' && i<length)
		{
			dataString[j++] = ch;
			ch = inputStr[++i];
		}
		if(i>=length)
			goto exitFalse;
		dataString[j++] = ch;
		ch = inputStr[++i];
		
	}
	else
	{
		while(ch!='x' && i<length && ch!='+' && ch!='-')
		{
			dataString[j++] = ch;
			ch = inputStr[++i]; // i points to current value of ch
		}
	}
	dataString[j] = 0;
	
	// get theNumber
	if(!getNumber(theNumber, dataString, doubleString, singleString))
		goto exitFalse;
	
	// get thePower
	
	if(ch!='x' &&(i>=(length-1) || ch=='+' || ch=='-'))
	{
		thePower = 0;
		add(coeffArray[thePower].Re, coeffArray[thePower].Re, theNumber.Re);
		add(coeffArray[thePower].Im, coeffArray[thePower].Im, theNumber.Im);
	}
	
	if(ch!='x' && i>=(length-1))
		goto exitTrue;
	
	if(ch=='+' || ch=='-')
		goto getNext;
	
	// ch should be an x
	if(ch!='x')
		goto exitFalse;
	
	// is next a ^ ?
	
	ch = inputStr[++i];
	if(ch!='^')
	{
		thePower = 1;
		
		add(coeffArray[thePower].Re, coeffArray[thePower].Re, theNumber.Re);
		add(coeffArray[thePower].Im, coeffArray[thePower].Im, theNumber.Im);
		if(i>=(length-1))
			goto exitTrue;
		goto getNext;
	}
	
	// now we must have a power
	if(i>=(length-1))
		goto exitFalse;
	
	// ch is now ^ and i points to it
	
	// get the power
	j = 0;
	ch = inputStr[++i];
	if(ch=='+' || ch=='-')
	{
		singleString[j++] = ch;
		ch = inputStr[++i];
	}
	while(i<length && ch!='+' && ch!='-')
	{
		singleString[j++] = ch;
		ch = inputStr[++i]; // i points to current value of ch
	}
	singleString[j] = 0;
	
	if(sscanf(singleString, "%d", &thePower)!=1)
		goto exitFalse;
	
	if(thePower<0)
		goto exitFalse;
	
	add(coeffArray[thePower].Re, coeffArray[thePower].Re, theNumber.Re);
	add(coeffArray[thePower].Im, coeffArray[thePower].Im, theNumber.Im);
	
	if(i>=(length-1))
		goto exitTrue;
	
	goto getNext;
	
	exitTrue:
	free(dataString);
	free(doubleString);
	free(singleString);
	return true;
	
	exitFalse:
	free(dataString);
	free(doubleString);
	free(singleString);
	return false;
	
}/* inputPoly */
