/* Programa    raizes_secante.c
   Assunto:		Estudo das raizes de uma função definida no programa.
   
	Condicionantes:
	Programa sem erros, ver raizes012.c com mudança de variável
	Para compilar
			gcc -Wall -oprog raizes_secante.c
	cria o executável  prog  que você pode rodar na linha de comandos
	em Linux.		
         
	Descrição:	Varre um intervalo com uma malha dada 
		procurando quando f troca 	de sinal.
		Lendo os comentários você pode alterar o programa com segurança
		
	Altere (0) logo abaixo para refletir a posição das bibliotecas
		na sua árvore de diretórios.	

	Palavras-chave:	troca de sinal, raiz, varredura, método da secnte
	             
	por Tarcisio Praciano Pereira - 10 lições para aprender C
	Sobral, Agosto de 2007   - UVA
*/
                  

#include <stdio.h>
#include <math.h>
#include "ambiente.h" // (0) Altere aqui

typedef	struct	{float a; 	float b; 
		 float delta; 	float epsilon;
		 int  teto; } dados;

// funções -  main() ao final

// há várias equações, para escolher uma, apague o comentário //
float	f(float	x)
{
	//return(-(x+3)*(x+3)*(x-2)*(x+2) ); // (50)
	// return( x*x*x*x*x + x*x*x*x + x*x*x + x*x + x + 1);  // (50)
	// return(x*x);    // (50) escolha somente um return()
	// return(x); // (50) 
	// return( (x+5)*(x+5)*(x+3)*(x+2)*x*(x-1)*(x-2)*(x-3)*(x-3) );
	return( (x+6)*(x+5)*(x+3)*(x+2)*x*(x-1)*(x-2)*(x-3)*(x-5) );
	// return( x*x*x*x*x - 4*x*x*x + x*x + 0.2*sin(19*x) - 0.10782); // função com vários gogosmat_dad.
	// return( x*x*x*x*x - 4*x*x*x + x*x + 0.2*sin(19*x) ); // função com vários gogosmat_dad.
};

// reta secante y = f(a) + df(a)(x - a) 
// zero da reta secante  x0 =  a - f(a)/df(a)  
float raiz_secante(float a, float b, float epsilon, int n)
{
	float m = (f(b)- f(a))/(b-a); 
	float c = a - f(a)/m;
	// se n==0, para! , se |f(x)| < epsilon,  para!
	while( ( n*( fabsf(f(c)) > epsilon ) ) ) 
	{ //  n=iterações  epsilon é a precisão 
		if (f(a)*f(c) < 0) b = c;
		  else a = c; // descobre intervalo de troca de sinal
		m = (f(b)- f(a))/(b-a);		  
		c = a - f(a)/m;
		n--; // desconta o número de iterações
	}
return(c);
};

dados	entrada_dados(dados	mat_dad)
{
	//  *** traduz para linguagem mais simples a,b,delta....
	float a=mat_dad.a,b=mat_dad.b, delta=mat_dad.delta, epsilon=mat_dad.epsilon;
	int	teto=mat_dad.teto;
	printf("Intervalo [a,b] para busca de raizes: \n");
	a = entrada_float("a = ", a); // definida em ambiente.h
	b = entrada_float("b = ", b); // definida em ambiente.h
	printf("O passo  delta da malha para a  busca:\n");
	printf("Sugestão  0.01 <  delta   <  0.5  \n");
	delta = entrada_float("delta  = ", delta);
	printf("Forneça-me o erro epsilon (módulo máximo) :\n");
	printf("Sugestão  0.01 <  epsilon    <  0.5  \n");	
	epsilon = entrada_float("epsilon   = ", epsilon);	
	teto = entrada_inteira("Teto para iterações ", teto);
	printf("Sua busca de raízes no intervalo [%f , %f] \n ",a,b);	
	printf("Precisão da malha: %f \n ", delta);		
	printf("Erro  (módulo máximo): %f \n ", epsilon);
	printf("Com %d máximo de iterações permitidas \n", teto);
	// ***************   fim da entrada de dados
	//  *** volta à complicação do struct 
	mat_dad.a=a;mat_dad.b=b; mat_dad.delta=delta; mat_dad.epsilon=epsilon;
	mat_dad.teto=teto;
	return(mat_dad); // devolve um struct
};

void	executa(float a, float b, float delta, float epsilon, int n)
{
	int	teste=0; // caso nao encontre raizes, teste=1
	float raiz;
	while( a <= b)
	{
		// (30) procura troca de sinal e tamanho
		if (  f(a)*f(a+delta)<=0  ) 		{
		if ( f(a) == 0 )
		{
		   printf("Uma raíz exata %f \n", a);
		   a = a + delta; // salto extra
		   teste = teste + 1; // conta raízes
		}
		else if ( f(a+delta) == 0 )
		     {
			printf("Uma raíz exata %f \n", a+delta);
			a = a + delta; // salto extra
			teste = teste + 1; // conta raízes
		     }  
		     else
		     {
			printf("Troca de sinal da função no intervalo ");
			printf("[ %f , %f] \n", a, a+delta);
			raiz =  raiz_secante(a,a+delta, epsilon, n);
			printf("Raiz p/ método da secante x =  %f \n", raiz);
			printf("Valor de f na raíz aprox f(%f)=%f\n",raiz,f(raiz));
			a = a + delta;  // salto extra
			teste = teste + 1; // conta raízes
		     }

		} 	
		a = a + delta;
	}
	if (!teste)
		{
		printf("Nenhuma raíz foi encontrada no intervalo dado !\n");
		printf("Rode, novamente, o programa, com passo mais finomat_dad.\n");
		}
	if (teste == 1)
		printf("Achei uma raíz \n");
	else   	printf("Achei %d intervalos onde há raíz \n", teste);
};



//  a função principal 

int	main()
{
	dados   entrada = {-5.0,5.0,0.1,0.1,10}; // inicializa sruct
	float a,b,delta,epsilon; int teto,n;

	entrada = entrada_dados(entrada);
	apeteco2();  // definida em ambiente.h
	// simlifica as variaveis
	a = entrada.a; b=entrada.b; delta = entrada.delta;
	epsilon=entrada.epsilon; 	teto = entrada.teto;
	n = teto;
	executa(a,b,delta, epsilon, n);
	return(0);
}



/*
	Comentários:  

(10) Os dados do programa podem ser aceitos apenas dando enter quando
	for feita pergunta sobre valores a fornecer. Rode o programa
	apenas dando enter na primeira vez.

(30) Há dois testes - troca de sinal  e módulo máximo 
		experimente apagar o módulo máximo, deixando 
		apenas
		se ( (f(a)*f(a+delta)<=0)  )
		copie o texto acima e coloque em lugar de se() em (30),
		mas não apague porque você vai precisar deste programa
		ainda. Torne um comentário aquilo que você apagaria
		usando o símbolo  //  
	
(40)  teste = 0  evita que seja escrita a mensagem informando
	que nenhuma raiz foi encontrada.
	
(50)	em uma função somente um return()  deve ser
	executado. em f() há vários, todos desligados, menos um que
	é o que está em vigor. Troque pela equação desejada ou
	escolha outra equação.


(60)    No módulo raiz_secante 
(61)	M é o coeficiente angular da reta secante em (a,f(a)) (b,f(b))
	para memorizar o crescimento global de f no intervalo de troca
	de sinal
(62)    A função pode ter muitos gogos no intervalo [a,b], oscilando
	antes de chegar no zero procurado.  Se m*M for negativo ou zero
	pego o próximo ponto na malha fina e volto a testar até
	que  m*M  seja positvo - m tem o mesmo sinal de M


*/

