/* Programa    raizes023.c
   Assunto:	Estudo das raizes de uma funcao bivariadad definida no programa.
   
	Condicionantes:
	Programa sem erros
	Os resultados deste programa foram bons em vários testes.
	
	compilar com
		gcc -Wall -oprog -lm raizes023.c
         
	Descricao:	Varre um intervalo com uma malha dada 
		procurando quando f troca 	de sinal, 
		    quando df troca de sinal e é pequena
		    
	Palavras-chave:	troca de sinal, raiz, varredura             
	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...

inteira	principal()
{
	real	a1=-10,b1=10,delta=0.05; // valores predefinidos
	real 	a2=-10,b2=10;
	real	epsilon;
	inteira teste = 0; // (10) se nao houver raizes 
	imprima("Raizes aproximadas - metodos da secante e tangente \n");
	imprima("Forneca-me o intervalo [a,b] para busca de raizes: \n");
	a1 = entrada_float("No eixo OX a = ", a1); // (20) definida em ambiente.h
	b1 = entrada_float("No eixo OX b = ", b1); // (20) definida em ambiente.h
	a2 = entrada_float("No eixo OY a = ", a2); // (20) definida em ambiente.h
	b2 = entrada_float("No eixo OY b = ", b2); // (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 retângulo  [%f, %f] x  [%f, %f]  \n ",
	            a1,b1,a2,b2);	
	imprima("Precisao da malha %f \n ", delta);
	se (delta > 1) { epsilon = 0.1;}
		senao { epsilon = 0.1*delta;}	
	apeteco2();  // (20) 	
	enquanto ( a1 <= b1)
	{
	      
		se ( ( f(a)*f(a+delta) <=0) )
			{
			  // y - f(a) = m(x - a)
				real  m, raiz; // (40) variáveis locais
				m = (f(a+delta)-f(a))/delta; // coef. ang. reta secante
				raiz = a - f(a)/m;
				teste++; // se houver raiz  teste conta quantas
				imprima("Raiz, por secância, provável, da função no intervalo \n");
				imprima("[%f, %f] \n ", a,a+delta);
				imprima("valor de f no ponto %f  --> %f  \n",raiz,f(raiz));
				a = a + delta; // pula um subintervalo
			}
		senao se  ( ( df(a)*df(a+delta) < 0 ) && ( f(a)*f(a+delta)  < epsilon)  )
			{
				// (70) testa troca de sinal da derivada e  f(a) pequena
				real raiz=(a + a+delta)/2; // Var local - ponto médio do intervalo
				teste++; // conta as raizes 
				imprima("Raiz, por tangência, provável, da função no intervalo \n");
				imprima("[%f, %f] \n", a, a+delta);
				imprima("valor de f no ponto %f  --> %f  \n",raiz,f(raiz));
				a = a + 2*delta; // pula dois subintervalos
			}		
	a = a + delta;
	}
	se (!teste)
	// se teste 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 (teste == 1)
		imprima("Encontrei 1 intervalo onde h\'a raizes \n");
	senao
	  imprima("Encontrei %d intervalos onde h\'a raizes \n", teste);
	}
 	voltar(0);
}

                        
// (60) selecione uma função
real	f(real	x)
{
		//voltar(0.001*(x-1)*(x+2)*(x+2)*(x-2)*(x-2)*(x*x*x*x*x + x*x*x*x + x*x*x + x*x + x + 1));
		//voltar((x+3)*(x+3)*(x+1)*(x-2)*(x-2)); 
		// voltar(x*x);
		voltar((1+x*x)*sin(x/3.0 + 1));
}


real	df(real	x)
{
    real	delta = 0.00001; //  variável local
    return( (f(x+delta)-f(x))/delta ) ;
}

/*

	(10) Alterei a lógica do  teste  -  agora  teste é 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.


	(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 
                  

*/

