/* Programa    raizes_bin_p.c  -  versão final
   Assunto:		Estudo das raizes de uma funcao definida no programa.
   
	Condicionantes:
	Programa sem erros
	Os resultados deste programa foram bons em vários testes.
	
	compilar com
		gcc -Wall -oprog -lm raizes.c
         
	Descricao:	Varre um intervalo com uma malha dada 
		procurando quando f troca 	de sinal, ao encontrar uma
		troca de sinal desencadeia os três métodos
      busca binária com 10 iteradas, método da secante 
      e método da tangente.
      
      Quando a raiz for tipo tangente usa a troca de sinal da derivada
      e verifica o módulo máximo
      
		    
	Palavras-chave:	troca de sinal, raiz, varredura, métodos clássicos             
	por Tarcisio Praciano Pereira - 10 licões para aprender C
	Sobral, Agosto de 2003   - UVA
*/
                  

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


real	f(real	x); //  A função cujas raízes serão procuradas
real	df(real	x); //  podia ser uma macro, mas não gosto delas...
real	busca_binaria(real a, real b, inteiro n);


inteira	principal()
{
	real	a=-10,b=10,delta=0.05; // valores predefinidos
	real	epsilon;
	//  *******   entrada de dados  ************************
	inteira contador = 0; // (10) se nao houver raizes 
	imprima("Raizes aproximadas - metodo binário  \n");
	imprima("Forneca-me o intervalo [a,b] para busca de raizes: \n");
	a = entrada_float("a = ", a); // (20) definida em ambiente.h
	b = entrada_float("b = ", b); // (20) definida em ambiente.h
	imprima("Forneca-me o passo da malha para a  busca:\n");
	imprima("Sugestao  0.01 <  delta   <  0.5  \n");
	delta = entrada_float("delta  = " , delta);  // (20) 	
	imprima("busca de raizes no intervalo [%f, %f] \n ",a,b);	
	imprima("Precisao da malha %f \n ", delta);
	//  *******   entrada de dados  ************************	
	se (delta > 1) { epsilon = 0.01;}
		senao { epsilon = 0.01*delta;}	
	apeteco2();  // (20) 	
	enquanto ( a <= b)  // malha grossa 
	{
		se ( ( f(a)*f(a+delta) <=0) )
			{
				real   raiz; // (40) variável local
				inteira	N=10; // (40) variável local
				contador++; // se houver raiz  contador conta quantas	há
				imprima("============= Três métodos ===========\n");
 				imprima("Raiz provável da função no intervalo ");
				imprima("[%lf, %lf] \n ", a, a+delta);				
				imprima("========1o método: por busca binária ======= \n");
			   raiz =  busca_binaria(a, a+delta,  N);								
				imprima("f(%lf) =  %lf  \n",raiz,f(raiz));				
				imprima("========  fim do caso troca de sinal  ======== \n\n\n");
				a = a + delta; // pula um subintervalo				
			}
	a = a + delta;
	}
	se (!contador)
	// se contador for zero, nao encontrou raizes
	{
	imprima("Nao encontrei raízes...mas isto não significa que \n");
	imprima("nao as haja!  apenas eu não consegui encontrá-las !\n");
	imprima("Rode, novamente, o programa, com passo mais fino...\n");
	imprima("ou em  intervalo  diferente. \n");
	}
	senao
	{
	se (contador == 1)
		imprima("Encontrei 1 intervalo onde h\'a raizes \n");
	senao
	  imprima("Encontrei %d intervalos onde h\'a raizes \n", contador);
	}
 	voltar(0);
}

                        
// (60) selecione uma função
real	f(real	x)
{
      voltar( (x + 5)*(x-3) );
}


real	df(real	x)
{
    //real	delta = 0.00001; //  variável local
    //voltar( (f(x+delta)-f(x))/delta ) ;
    //voltar( 1000*pow(1+x,24) + 24000*pow(1+x,23)*x);
    voltar( x - 3 + x + 5 );
}


// função recursiva -  parâmetro da recursividade é n
real	busca_binaria(real a, real b, inteiro n)
{
  real	x = (a+b)/2;  // ponto médio
  se (n == 0) voltar(x); 
  senao
  {   
      se (f(x)*f(a) == 0) voltar(x);// ponto médio
      senao
      { 
        se (f(a)*f(x) <= 0)  voltar(busca_binaria(a, x, n-1)); // [a,x]
          senao voltar(busca_binaria(x,b,n-1)); // [x,b]   
      }
  } 
}





/*

	(10) Alterei a lógica do  contador  -  agora  contador é também um
	contador de raízes - antes ela era 1  se não houvesse raiz.

	(40)	Variável local.  Em C, quando abrimos uma chave, estamos 
		criando um bloco lógico. No início de cada bloco lógico podemos
		definir novas variáveis. Toda variável fica restrita ao bloco
		lógico em que for definida. É local.  Terminada vigência do
		bloco lógico, a variável será destruida.

   (41) é o teto de operações, vai fazer a busca  binária até o 
     limite de N divisões do intervalo.

	(60) O símbolo //  transforma a linha em que ele se encontra, em um
		comentário, a partir do ponto em que ele estiver. Desta forma eu
      posso definir diversas equações para uma função, e 
      ligar uma em que eu esteja interessado  e 
      desligar as outras. 
               
  (70) Teste simultâneo (and) da troca de sinal da derivada e módulo 
  máximo da derivada. O módulo é desnecessário porque f tem sinal constante.
  Observe que estou usando f(a)*f(a+delta) que é positivo e se f for menor
  do que 1 então  f(a)*f(a+delta) < |f(a)| < delta 
                  

*/

