/* 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	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=-10,b=10,delta=0.5;
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");
// **********   entrada de dados   ************************************
printf("Forneca-me o intervalo [a,b] para busca de raizes: \n");
a 	= entrada_float("a = ", a);
b 	= entrada_float("\n b = ",b);
printf("Forneca-me o passo  delta da malha para a  busca:\n");
printf("Sugestao  0.01 <  delta   <  0.5  \n");
delta  	= entrada_float("delta  = ", delta);
// *************************  entrada de dados  fim   ******************
printf("Sua busca de raizes no intervalo %s %f %s %f %s \n ","[",a,",",b,"]");
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; // re-iniciada ! (100)
                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 ) && ( fabs(f(a)*delta) < delta)  )
                {
                printf("Procurando raizes do tipo tangente \n");
                contador = 0;  // re-iniciada ! (100)
                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 && ( fabs(f(a)*delta) < delta)  )	
                     {
                      printf("Procurando raizes do tipo inflexao \n");
                      contador = 0;  // re-iniciada ! (100)
                      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	raiz_binaria_secante(double a, double b, int p)
{
	if (p)  // é o limite permitido de iterações
	{
	contador++;   // incrementando variável global - perigo!
	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);
	}
	printf("%d %f %f \n",1, a,b);apeteco2();
	//return (a+b)/2;
	return(a);
}                        

double raiz_binaria_tangente(double a, double b, int p)
{
	if (p) // é o limite permitido de iterações
	{
	double delta = (b-a)/4, 
		deltaf1=f(a+delta)-f(a), 
		deltaf2=f(a+2*delta)-f(a+delta);
	contador++; // incrementando variável global - perigo!
	if ( deltaf1*deltaf2  <= 0 ) 
		raiz_binaria_tangente(a,(a+b)/2 , --p);
	else raiz_binaria_tangente((a+b)/2,b , --p);
	}
	printf("%d %f %f \n",2, a,b);apeteco2();
	//return (a+b)/2;
	return(a);
}


double raiz_binaria_inflexao(double a, double b, int p)
{
	if (p)  // é o limite permitido de iterações
	{
	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++;   // incrementando variável global - perigo!	
	if ( (deltaf2-deltaf1)*(deltaf3-deltaf2)  <= 0 ) 
		raiz_binaria_inflexao(a,(a+b)/2 , --p);
	else raiz_binaria_inflexao((a+b)/2,b , --p);
	}
	printf("%d %f %f \n",3, a,b);apeteco2();
	//return (a+b)/2;
	return(a);
}


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

/*
(100)  A variável  contador  é incrementa dentro de cada rotina
       de cálculo de raízes para contar o número de iteraçoes
       executada na naquela rotina. Ela é re-iniciada antes de
       que a rotina seja chamada. Tudo sob controle!




*/

