/* Programa    complex03.c  
	Assunto:  	Imagem de uma curva por um polinômnio complexo.
	Programa 	sem erros
	
	Condição: compile com
		gcc -Wall -oprog -lm complex03.c
		
		inclua a biblioteca ambiente.h no mesmo diretório e altere
			linha de inclusão desta biblioteca

   Descrição: Determina a imagem da fronteira do quadrado 
       [-3,3]x[-3,3]  pela função exponencial.
   	Procure comentário "enfase"
         

   por Tarcisio Praciano Pereira - 10 lições para aprender C
   Sobral, Fevereiro de 2008 - 	- UVA

	Palavras-chave: imagem de curvas por polinômios complexos
	palavras chave: struct, estrutura
	palavras chave: fronteira de uma superficie de Riemann 	
   por Tarcisio Praciano Pereira - 10 lições para aprender C
   Sobral,  de 2008	- UeVA    	      		
*/

# include <stdio.h>  	// (1) leitura da biblioteca padrão
# include <stdlib.h>
# include <math.h>
# include "/home/tarcisio/tex/c/ufg/ambiente.h"

			//	(2)	O tipo, número complexo
typedef	struct {
			float a; float b;
			} Complexo;

float		Re(Complexo z);
float		Im(Complexo z);
void		escreve(Complexo z);
Complexo	mais(Complexo z, Complexo w);
Complexo	vezes(Complexo z, Complexo w);
Complexo	P(Complexo z);
Complexo	Q(Complexo z);
Complexo Exp(Complexo z);
Complexo	recebe(Complexo z, Complexo w);
Complexo	faz_complexo(float a, float b);
int	curva_imagem(); // sem parâmetros para produzir imagens de retânmgulos
void		prepara_gnuplot();



int main(void)
{
	//Complexo	z=faz_complexo(2, 2);
	printf("	=====   Sistema algébrico dos números complexos \n");
	printf("		Imagem de uma curva por um polinômio   \n");	
	curva_imagem(); 
	//escreve(z); printf("\n");
	//z = faz_complexo(3.14, 4.45);  // problema
	//escreve(faz_complexo(3.14, 4.45));
	//escreve(z);
	prepara_gnuplot();
	system("gnuplot transfere");
	return 0;
}

// percorre um retângulo com ênfase nas paralelas ao eixo OX (quer dizer
// o salto no eixo OY é grande)
int	curva_imagem()
{
  float x,y;
  float delta = 0.001;
  Complexo z;
  FILE	*dados;
  dados	= fopen("dados", "w");
  // primeiro lado do quadrado - fronteira de [0,1]x[-3.1415,3.1415]
  x = 0;
  y = 0;//-3.1415;
  while(y <= 2*3.1415)
  {
			 z = faz_complexo(x, y);
			 z = Exp(z); // exp(x+iy)
			 fprintf(dados, "%f  %f\n", Re(z), Im(z));
			 y+=delta; //  y+= delta; ou delta2  // (10)  troque aqui para alterar a ênfase...
  }
  // terceiro  lado do quadrado - fronteira de [-3,3]x[-3,3]  
  x = 0;
  y = 2*3.1415;
  while(x <= 1)
  {
			 z = faz_complexo(x, y);
			 z = Exp(z); // exp(x+iy)
			 fprintf(dados, "%f  %f\n", Re(z), Im(z));
			 x+=delta; //  y+= delta; ou delta2  // (10)  troque aqui para alterar a ênfase...
  }  
  // segundo  lado do quadrado - fronteira de [-3,3]x[-3,3]  
  x = 1;
  y = 2*3.1415;
  while(y >= 0)
  {
			 z = faz_complexo(x, y);
			 z = Exp(z); // exp(x+iy)
			 fprintf(dados, "%f  %f\n", Re(z), Im(z));
			 y-=delta; //  y+= delta; ou delta2  // (10)  troque aqui para alterar a ênfase...
  }    
  // quarto  lado do quadrado - fronteira de [-3,3]x[-3,3]  
  x = 1;
  y = 0;// 3.1415;
  while(x >=0)
  {
			 z = faz_complexo(x, y);
			 z = Exp(z); // exp(x+iy)
			 fprintf(dados, "%f  %f\n", Re(z), Im(z));
			 x-=delta; //  y+= delta; ou delta2  // (10)  troque aqui para alterar a ênfase...
  }    
  fclose(dados);
  return(0);
}


void	prepara_gnuplot()
{
  FILE  *transfere;
  transfere =  fopen("transfere", "w");
  fprintf(transfere, "set title 'Sup. de Riemann: Imagem Fr( [0,1]x[0,6.283] ) pela exponencial'  \n");  
  fprintf(transfere, "set pointsize 0.1 \n");
  fprintf(transfere, "set grid  \n");  
  fprintf(transfere, "plot \"dados\" with points \n");
  fprintf(transfere, "pause -2\n");
  fclose(transfere);
}



Complexo	recebe(Complexo z, Complexo w)
{
	z.a = w.a;
	z.b = w.b;
	return(z);
}

float		Re(Complexo z)
	{
		return z.a;
	}

float		Im(Complexo z)
	{
		return z.b;
	}

Complexo	mais(Complexo z, Complexo w)
{
	Complexo temp;
	temp.a = z.a + w.a;
	temp.b = z.b + w.b;
	return(temp);
}

Complexo vezes(Complexo z, Complexo w)
{
	Complexo temp;
	temp.a = z.a*w.a - z.b*w.b;
	temp.b = z.b*w.a + z.a*w.b;
	return(temp);
}

Complexo	faz_complexo(float a, float b)
{
	Complexo temp;
	temp.a= a; temp.b = b;
	return(temp);
}

void	escreve(Complexo z)
{
	printf(" %2.2f + %2.2f i\n", Re(z),Im(z));
}

//      a0 + z*(a1 + z*( a2 + z*a3))) 
//     mais(a0, vezes(z, mais(a1, vezes(z, mais(a2, vezes(a3,z))))))
Complexo	P(Complexo z)
{
	Complexo a0, a1, a2, a3;
	Complexo temp;
	
	recebe(temp, mais(a0, vezes(z, mais(a1, vezes(z, mais(a2, vezes(a3,z)))))));
	return(temp);
}

Complexo	Q(Complexo z)
{
	Complexo v={1,0};
	recebe(v, faz_complexo(1,0));
	Complexo temp = vezes(z,z);
	temp = vezes(v,temp);
	return(temp);
}

//  exp(z) = exp(x+iy) = exp(x)*exp(iy) = exp(x)( cos(y) + i sin(y) )
Complexo	Exp(Complexo z)
{
	Complexo temp;
	temp.a = exp(z.a)*cos(z.b); // exp(x)cos(y)
	temp.b = exp(z.a)*sin(z.b); // exp(x)sin(y)
	return(temp);
}

/* Comentários:  A numeração dos comentários não
		  é continuada, pode dar saltos...para
		  facilitar a reutilização de programas.

	(2)	O tipo, número complexo. Com "typedef" podemos criar novos tipos 
	de dados. Aqui foi criado o tipo "Complexo" com auxílio de "struct".
	Um número complexo tem dois campos indicados por "a" e por "b".

(10) na função curva_imagem()  a escolha de uma malha mais fina em
    um dos eixos determina a ênfase - quer dizer, se quero a imagem
    de segmentos de reta paralelo ao eixo OX  ou  ao eixo OY 
*/


