#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime>

class Complexe {
    private:
        double re;
        double im;
    public:
	    
        Complexe(double x = 0, double y = 0) : re(x), im(y)  { }
        
        void setgetRe(double reel) { re = reel; }
        void setgetIm(double imaginaire) { im = imaginaire; }
        double getRe() const { return re; }
        double getIm() const { return im; }
        double Norme() const { return sqrt(getRe()*getRe() + getIm()*getIm()); }
        Complexe Addition(const Complexe& c1, const Complexe& c2) {
	        Complexe temp;
	        temp.re = c1.getRe() + c2.getRe();
	        temp.im = c1.getIm() + c2.getIm();
	        return temp;
		}
		Complexe Multiplication(const Complexe &c1, const Complexe& c2) {
	        Complexe temp;
	        temp.re = c1.getRe()*c2.getRe() - c1.getIm()*c2.getIm();
	        temp.im = c1.getRe()*c2.getIm() + c1.getIm()*c2.getRe();
	        return temp;
		}
		Complexe Soustraction(const Complexe& c1, const Complexe& c2) {
	        Complexe temp;
	        temp.re = c1.getRe() - c2.getRe();
	        temp.im = c1.getIm() - c2.getIm();
	        return temp;
		}
		Complexe MulPargetReel(const Complexe &c1, double reel) {
	        Complexe temp;
	        temp.re = c1.getRe() * reel;
	        temp.im = c1.getIm() * reel;
	        return temp;
		}
		Complexe Racine(const Complexe &c1) {
	        Complexe temp;
			double a = 0, b = 0;
	        a = sqrt((c1.Norme() + c1.getRe())/2.);
	        if(c1.getIm() >= 0.) 
                b = sqrt((c1.Norme() - c1.getRe())/2.);
			else b = -sqrt((c1.Norme() - c1.getRe())/2.);
			temp.re = a;
			temp.im = b;
			return temp;
		}
};

int aleatoire(int min, int max) {
    return (int) (min + ((float) rand() / RAND_MAX * (max - min + 1)));
}

Complexe dynamique[1500];

Complexe f(Complexe z, Complexe c) {
    Complexe temp;
    return (temp.Addition(temp.Multiplication(z,z),c));
}

Complexe Julia(int n, Complexe z0, Complexe c) {
    if(dynamique[n].getRe() != -100000 && dynamique[n].getIm() != -100000) {
		//printf("\tdyn %lf %lf\n", dynamique[n].getRe(), dynamique[n].getIm()); 
        return dynamique[n];
    }
    Complexe temp;
    if(n == 0)
        return z0;
    else {
		dynamique[n] = (temp.Addition(temp.Multiplication(Julia(n-1, z0, c),Julia(n-1, z0, c)), c));
        return dynamique[n];
		return (temp.Addition(temp.Multiplication(Julia(n-1, z0, c),Julia(n-1, z0, c)), c));
	}
}


int main()
{
 	srand(time(NULL));
 	
 	Complexe t;
 	
 	for(int i = 0; i < 1500; i++) {
		dynamique[i].setgetRe(-100000);
		dynamique[i].setgetIm(-100000);
	}
 	
 	//test pour vérifier si les fonctions sont cohérentes, ou non ^^
/* 	
 	Complexe comp1(2.0, 1.0);
 	Complexe comp2(1.0, 2.0);
 	printf("%lf %lf\n", comp1.getRe(), comp1.getIm());
    printf("norme : %lf\n", comp1.Norme());
    Complexe res(0.,0.);
    res = comp1.Addition(comp1, comp2);
    printf("addition : %lf %lf\n", res.getRe(), res.getIm());
    res = comp1.Multiplication(comp1, comp2);
    printf("multiplication : %lf %lf\n", res.getRe(), res.getIm());
 	res = comp1.Soustraction(comp1, comp2);
 	printf("soustraction : %lf %lf\n", res.getRe(), res.getIm());
 	res = comp1.MulPargetReel(comp1, 5.5);
 	printf("mult par reel : %lf %lf\n", res.getRe(), res.getIm());
 	res = comp1.Multiplication(comp1, comp1);
 	printf("carre : %lf %lf\n", res.getRe(), res.getIm());
 	res = comp1.Racine(comp1);
 	printf("racine : %lf %lf\n", res.getRe(), res.getIm());
 	
 	for(int i = 0; i < 10; i++) {
        printf("%d ", aleatoire(-1, 1));
	}
	printf("\n");
*/ 	
 	
 	/************************ Julia ***********************/
 	
 	//test Julia :
    Complexe zInit;
    Complexe cInit(-0.5,0.3);
    
    Complexe resultat;
    resultat = Julia(30, zInit, cInit);
    
    printf("resultat : %lf %lf\n", resultat.getRe(), resultat.getIm());
/* 	
 	Complexe res_f;
 	res_f = f(resultat, cInit);
 	printf("f : %lf %lf\n", res_f.getRe(), res_f.getIm());
*/	

 	system("pause");
 	return 0;
}
