/* Programa    raizes015.c
   Assunto:	Estudo das raizes de uma funcao definida no programa.
   
	Condicionantes:
	Programa sem erros
         
	Descricao:	Varre um intervalo com uma malha dada 
		procurando quando f troca 	de sinal.
		procura raiz secante, tangente, inflexao
		Usa mudanca de variavel para fazer procura fina.
		Recursiva
		
	Palavras-chave:	recursiva, busca binaria             
	por Tarcisio Praciano Pereira - 10 licões para aprender C
	Sobral, Agosto de 2003   - UVA
*/
                  

#include <stdio.h>
#include <math.h>
#include "ambiente.h"


double    absol(double x);
double	raiz_binaria_secante(double a, double b, int p);
double	raiz_binaria_tangente(double a, double b, int p);
double 	raiz_binaria_inflexao(double a, double b, int p);
double	f(double	x);
int	contador; // contar as iteracoes;

int	main()
{
	double	a,b,delta;
	int teste = 0; // se nao houver raizes 
	int	p=13; // limite de iteracoes
	printf("Raizes aproximadas - metodos: da secante, da tangente e da inflexao \n");
	printf("Forneca-me o intervalo [a,b] para busca de raizes: \n");
	printf("a = "); scanf("%lf",&a);
	printf("\n b = "); scanf("%lf",&b);
	printf("Sua busca de raizes no intervalo %s %f %s %f %s \n ","[",a,",",b,"]");
	printf("Forneca-me o passo  delta da malha para a  busca:\n");
	printf("Sugestao  0.01 <  delta   <  0.5  \n");
	printf("delta  = ");
	scanf("%lf",&delta);
	printf("Precisao da malha %f \n ", delta);	
	apeteco2();
	while ( a <= b)
	{
		double raiz;
		double deltaf1=(f(a+delta)-f(a));
		double deltaf2=(f(a+2*delta)-f(a+delta));
                double deltaf3=(f(a+3*delta)-f(a+2*delta));  // Var Loc
		if ( (f(a)*f(a+delta)<=0) )
			{
			printf("Procurando raizes do tipo secante\n");
			contador = 0;
			raiz = raiz_binaria_secante(a, a+delta,p);
			teste++; // conta uma raiz 
			printf("Raiz, por secancia, provavel, da funcao no intervalo \n");
			printf("%s%lf%s%lf%s \n","[", a, ",", a+delta,"]");
			printf("valor de f no ponto %lf  com %d iteracoes  --> %lf  \n",raiz,contador,f(raiz));
			// a = a + delta; // pula um subintervalo
			}
		else if  ( ( deltaf1*deltaf2 <= 0 ) && ( absol(f(a)*delta) < delta)  )
			{
			printf("Procurando raizes do tipo tangente \n");
			contador = 0;
			raiz = raiz_binaria_tangente(a,a+delta,p);
			teste++; // conta uma raiz 
			printf("Raiz, por tangencia, provavel, da funcao no intervalo \n");
			printf("%s%lf%s%lf%s \n","[", a, ",", a+delta,"]");
			printf("valor de f no ponto %lf com %d iteracoes  --> %lf  \n",raiz,contador,f(raiz));
			a = a + delta; // pula um subintervalo
			}	
                        else if ( (deltaf3-deltaf2)*(deltaf2-deltaf1) <=0 && ( absol(f(a)*delta) < delta)  )	
                             {
                              printf("Procurando raizes do tipo inflexao \n");
                              contador = 0;
                              raiz = raiz_binaria_inflexao(a,a+delta,p);
                              teste++; // conta uma raiz 
                              printf("Raiz, por inflexao, provavel, da funcao no intervalo \n");
                              printf("%s%lf%s%lf%s \n","[", a, ",", a+delta,"]");
                              printf("valor de f no ponto %lf com %d iteracoes  --> %lf  \n",raiz,contador,f(raiz));
                              a = a + delta; // pula um subintervalo
                             }
	a = a + delta;
	}
	if (!teste)
	// se teste for zero, nao encontrou raizes
	{
	printf("Nao encontrei raizes...mas isto nao significa que \n");
	printf("nao as haja!  apenas eu nao consegui encontra-las !\n");
	printf("Rode, novamente, o programa, com passo mais fino...\n");
	}
	else
	{
	if (teste == 1)
		printf("Encontrei 1 intervalo onde h\'a raizes \n");
	else
	  printf("Encontrei %d intervalos onde h\'a raizes \n", teste);
	}
 	return 0;
}

double    absol(double x)
{
	if (x >=0) return x;
	else return -x;
}
                        

double	raiz_binaria_secante(double a, double b, int p)
{
	if (p)
	{
	contador++;
	if (f(a)*f((a+b)/2) <= 0) raiz_binaria_secante(a, (a+b)/2,--p);
	else raiz_binaria_secante((a+b)/2, b,--p);
	}
	return (a+b)/2;
}                        

double raiz_binaria_tangente(double a, double b, int p)
{
	if (p)
	{
	double delta = (b-a)/4, deltaf1=f(a+delta)-f(a), deltaf2=f(a+2*delta)-f(a+delta);
	contador++;	
	if ( deltaf1*deltaf2  <= 0 ) 
		raiz_binaria_tangente(a,(a+b)/2 , --p);
	else raiz_binaria_tangente((a+b)/2,b , --p);
	}
	return (a+b)/2;
}


double raiz_binaria_inflexao(double a, double b, int p)
{
	if (p)
	{
	double delta = (b-a)/6;
        double  deltaf1=f(a+delta)-f(a), deltaf2=f(a+2*delta)-f(a+delta);
        double  deltaf3=f(a+3*delta)-f(a+2*delta);
	contador++;	
	if ( (deltaf2-deltaf1)*(deltaf3-deltaf2)  <= 0 ) 
		raiz_binaria_inflexao(a,(a+b)/2 , --p);
	else raiz_binaria_inflexao((a+b)/2,b , --p);
	}
	return (a+b)/2;
}


double	f(double	x)
{
		//x = x/100;// mudanca de variavel
		return (x-1)*(x+2)*(x+2)*(x-2)*(x-2)*(x+1)*(x+1)*(x+1);
		// return  	x*x*x - x*x - 3*x -10; 
		// uma funcao do quinto grau
		// return x*x;
}

/*





*/
