#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <fstream.h>
#include <stdio.h>
#include <iomanip.h>
#include <conio.h>

//============================================================================
//|					Steven Fontenot Project 1								 |
//|					   Language Used: C++									 |
//============================================================================


/*************************************Global Variables************************/
double ERROR = 0.00000001;
double ROOT = 0.0;

int newton_n = 0; // counter for newton recursion
int secant_n = 0; //counter for secant recursion
int bisection_n = 0; //counter for bisection iteration

double newton_temp = 0; //newton_temp is next guess in series
double secant_temp = 0; //secant_temp is next guess in series


//below are user entered data -- subject to error
double User_Bi_Left;
double User_Bi_Right;
double User_Newton;
double User_Secant1;
double User_Secant2;



/*************************************Function Approx*************************/
double fun(double x) { //A first degree taylor approx of
	                   //   2e^x - sin x + x^3 + 5x^2 -20
	double y;

	y = 28.146715943 * x - 39.738384093;
	//y = pow(x,6) - x - 1; //test from book 

	return y;
}

/*************************************First Derivative************************/
double der(double x) { //The first der of above taylor approx

	double y;

	y = 28.146715943;
	//y = 6 * pow(x,5) - 1; //test from book 

	return y;
}

/**************************************Bisection******************************/
void Bisection (double left, double right, double error){	
	
	double c; //center

	bool again = true; //keeps loop going

	while (again) {

		c = (left+right)/2.0; //calc center

		if ((right - c) <= error || bisection_n > 100 ) { //if in error tolerance
			again = false;						// or max loops met		
		}
		
		if (bisection_n < 10 && fun(c) >=0){
			cout<<" "<<bisection_n<<" "<<left<<" "<<right<<" "<<c<<" "<<setw(16)<<right-c<<"     "<<fun(c)<<endl;
		}
		else if (bisection_n<10){
			cout<<" "<<bisection_n<<" "<<left<<" "<<right<<" "<<c<<" "<<setw(16)<<right-c<<"    "<<fun(c)<<endl;
		}
		else
			cout<<bisection_n<<" "<<left<<" "<<right<<" "<<c<<" "<<setw(16)<<right-c<<"  "<<setw(17)<<fun(c)<<endl;

		if (fun(c) * fun(right) < 0){ //root is right of c			
			
			left=c;		
		}		
		else
			right = c; //root is left of c		
		bisection_n++;	
	}//while loop
}
/***************************************Newton's******************************/
void Newton(double guess, double error ){	

	if (newton_temp == 0){
		cout<<" "<<newton_n<<" "<<setw(18)<<guess<<"  "<<setw(18)<<fun(guess)<<"  "<<setw(18)<<endl;
	}


	newton_temp = guess - ((fun(guess))/(der(guess))); //calculates next guess

	newton_n++;	//increments n before recursion


	if ((fabs(newton_temp - guess)) <= error ){  //checks if error tolerance is met
		if (newton_n < 10){
			cout<<" "<<newton_n<<" "<<setw(18)<<newton_temp<<"  "<<setw(18)<<fun(newton_temp)<<"  "<<setw(18)<<newton_temp - guess<<endl;
		}	
		else
			cout<<newton_n<<" "<<setw(18)<<newton_temp<<"  "<<setw(18)<<fun(newton_temp)<<"  "<<setw(18)<<newton_temp - guess<<endl;
		ROOT = newton_temp;
		return;
	} // last recursion	


	if (newton_n < 10){
		cout<<" "<<newton_n<<" "<<setw(18)<<newton_temp<<"  "<<setw(18)<<fun(newton_temp)<<"  "<<setw(18)<<newton_temp - guess<<endl;
	}	
	else
		cout<<newton_n<<" "<<setw(18)<<newton_temp<<"  "<<setw(18)<<fun(newton_temp)<<"  "<<setw(18)<<newton_temp - guess<<endl;


	if (newton_n>100){ //max loop reached		
		return;
	}


	Newton(newton_temp, error); //recursivly calles newton with new guess
}


/***************************************Secant********************************/
void Secant(double guess,double prev_guess, double error ){	

	if (secant_temp == 0.0){
		cout<<" "<<secant_n<<" "<<setw(18)<<guess<<"  "<<setw(18)<<fun(guess)<<"  "<<setw(18)<<endl;
	}


	secant_temp = guess - fun(guess) * (guess - prev_guess)/(fun(guess) - fun(prev_guess)); //calculates next guess

	secant_n++;	//increments n before recursion


	if ((fabs(secant_temp - guess)) <= error ){  //checks if error tolerance is met
		if (secant_n < 10){
			cout<<" "<<secant_n<<" "<<setw(18)<<secant_temp<<"  "<<setw(18)<<fun(secant_temp)<<"  "<<setw(18)<<secant_temp - guess<<endl;
		}	
		else
			cout<<secant_n<<" "<<setw(18)<<secant_temp<<"  "<<setw(18)<<fun(secant_temp)<<"  "<<setw(18)<<secant_temp - guess<<endl;
		return;
	} // last recursion	


	if (secant_n < 10){
		cout<<" "<<secant_n<<" "<<setw(18)<<secant_temp<<"  "<<setw(18)<<fun(secant_temp)<<"  "<<setw(18)<<secant_temp - guess<<endl;
	}	
	else
		cout<<secant_n<<" "<<setw(18)<<secant_temp<<"  "<<setw(18)<<fun(secant_temp)<<"  "<<setw(18)<<secant_temp - guess<<endl;


	if (secant_n>100){ //max loop reached		
		return;
	}


	Secant(secant_temp, guess, error); //recursivly calles secant with new guesses
}



/***********************************Header************************************/
void Header(int header_num){ //just header stuff
	
	if (header_num == 1){
		cout<<" BISECTION METHOD OF ROOT FINDING"<<endl;
		cout<<" #  Left        Right        Center        Approx Error      Function At Center"<<endl;
		cout<<" -  ----        -----        ------        ------------      ------------------"<<endl;
	}	
	else if (header_num == 2){		
		cout<<" NEWTON'S METHOD OF ROOT FINDING"<<endl;
		cout<<" #      Current Guess   Function At Guess    Approx Error"<<endl;
		cout<<" -      -------------   -----------------    ------------"<<endl;	
	}
	else if (header_num == 3){
		cout<<" SECANT METHOD OF ROOT FINDING"<<endl;
		cout<<" #      Current Guess   Function At Guess    Approx Error"<<endl;
		cout<<" -      -------------   -----------------    ------------"<<endl;
	}
	else if (header_num == 4){
		cout<<" The Root is "<<ROOT<<endl;
		cout<<" The bisection method took "<<(bisection_n - 1)<<" iterations to reach the root."<<endl;
		cout<<" Newton's method took "<<newton_n<<" recursions to reach the root."<<endl;
		cout<<" The secant method took "<<secant_n<<" recursions to reach the root."<<endl;
	}
}

/***********************************Pause & clear screen**********************/
void pause(){

	cout<<"You may have to scroll up to view all output."<<endl;
	cout<<"Press Any key to continue."<<endl;
	//above lines to seperate different methods

	getch(); //pauses screen untill any key pressed

	system("cls"); //clears screen on Win 9X, NT, and 2K	
}

/***********************************User input *******************************/
void User_io(){
	cout<<"Enter Left Guess At Root For Bisection Method--> ";
	cin>>User_Bi_Left;
	cout<<"Enter Right Guess At Root For Bisection Method--> ";
	cin>>User_Bi_Right;
	cout<<"Enter Guess At Root For Newton's Method--> ";
	cin>>User_Newton;
	cout<<"Enter Left Guess At Root For Secant Method--> ";
	cin>>User_Secant1;
	cout<<"Enter Right Guess At Root For Secant Method--> ";
	cin>>User_Secant2;
}


/***********************************Main**************************************/
void main(){	
	cout.setf(ios::showpoint);	
	cout.precision(11);	

	User_io();

	pause();
	
	Header(1);
	Bisection(User_Bi_Left, User_Bi_Right, ERROR);

	pause();
	
	Header(2);
	Newton(User_Newton, ERROR);

	pause();
	
	Header(3);
	Secant(User_Secant1,User_Secant2,ERROR);

	pause();

	Header(4);


}