#include <iostream>
#include <iomanip>
#include <math.h>

using namespace std;

// Deklarationen
float testfunktion1(int funktion, float x);
void bisek(double x0, double x1, int genauig_x, int genauig_f, int funktion);
void sekant(double x0, double x1, int genauig_x, int genauig_f, int funktion);

// Implementation

float testfunktion(int funktion, float x)
{
	switch(funktion)
	{
		case 1:
			return(cos(x) - x);
			break;
		case 2:
			return(exp(x) - pow(x,5));
			break;	
	}
	
}


void bisek(double x0, double x1, int genauig_x, int genauig_f, int funktion)
{
	double x_test =(x0 + x1)/2;
	int i=1;
	// cout << x0 << "-"<<x1<< "-"<<genauig_x<< "-"<<genauig_f<< "-"<<funktion << endl;
	while((fabs(x1-x0) > pow(10,- genauig_x)) && fabs(testfunktion(funktion,x_test)) > pow(10,- genauig_f))
	{
		cout << "Schrittzahl: " << i << " Interval: [" << x0 << "," << x1 << "] f(x_test)=" << testfunktion(funktion,x_test) << endl;
		if(testfunktion(funktion,x_test) * testfunktion(funktion,x0) < 0)
		{
			x1 = x_test;
		}
		else if (testfunktion(funktion,x_test) * testfunktion(funktion,x1) < 0)
		{
			x0 = x_test;
		}else
		{
			cerr << "Keine Nullstelle im gegebenen Intervall!" << endl;
			exit(1);
		}
		x_test =(x0 + x1)/2;
		i++;
		
	}
	cout << "Ergebnis: Nullstelle bei x=" << x_test << endl;
}

void sekant(double x0,double x1, int genauig_x, int genauig_f, int funktion)
{
	double x_test =((x0 *testfunktion(funktion,x1)) - (x1 *testfunktion(funktion,x0)))/(testfunktion(funktion,x1)-testfunktion(funktion,x0));
	
	int i=1;
	//cout << "x_test:" << x_test << " f(x_test):" << testfunktion(funktion,x_test) << endl;
	// cout << x0 << "-"<<x1<< "-"<<genauig_x<< "-"<<genauig_f<< "-"<<funktion << endl;
	while((fabs(x1-x0) > pow(10,- genauig_x)) && fabs(testfunktion(funktion,x_test)) > pow(10,- genauig_f))
	{
		cout << "Schrittzahl: " << i << " Interval: [" << x0 << "," << x1 << "] f(x_test)=" << testfunktion(funktion,x_test) << endl;
		if(testfunktion(funktion,x_test) * testfunktion(funktion,x0) < 0)
		{
			x1 = x_test;
		}
		else if (testfunktion(funktion,x_test) * testfunktion(funktion,x1) < 0)
		{
			x0 = x_test;
		}else
		{
			cerr << "Keine Nullstelle im gegebenen Intervall!" << endl;
			exit(1);
		}
		x_test =((x0 *testfunktion(funktion,x1)) - (x1 *testfunktion(funktion,x0)))/(testfunktion(funktion,x1)-testfunktion(funktion,x0));
		i++;
		
	}
	cout << "Ergebnis: Nullstelle bei x=" << x_test << endl;
}


int main()
{
	float x0_start=0, x1_start=0;
	int testf=0, verfahren=0;
	cout << "Aufgabe 18: Nullstellenbestimmung\n";
	do
	{
	    cout << "Bitte die Testfunktion waehlen:\n(1) f(x) = cos(x)-x \n(2) f(x) = exp(x) - x^5\nIhre Wahl:";
	    cin >> testf;
	}while(!(testf == 1 || testf == 2));
	
	do
	{
	    cout << "Bitte das Verfahren waehlen:\n(1) Bisektionsverfahren \n(2) Sekantenverfahren\nIhre Wahl:";
	    cin >> verfahren;
	}while(!(verfahren == 1 || verfahren == 2));
	
	cout << "Bitte Anfangsinterval [x0,x1] angeben:\n";
	cout << "x0:";
	cin >> x0_start;
	cout << "x1:";
	cin >> x1_start;
	
	switch(verfahren)
	{
	    case 1: 	bisek(x0_start,x1_start,6,4,testf);
			break;
	    case 2:	sekant(x0_start,x1_start,6,4,testf);
			break;
	}
	
	return(0);
}
