---
jupytext:
  text_representation:
    extension: .md
    format_name: myst
    format_version: 0.13
kernelspec:
  display_name: C++17
  language: C++17
  name: xcpp17
---

+++ {"tags": ["solution"]}

# Exercice : Fractale de Mandelbrot

La fractale de Mandelbrot est un ensemble de points du plan complexe définie comme suit:
soit $c$ un nombre complexe, on lui associe la suite $(z_n)$ donnée par $z_0 = 0$ et
$z_{n+1} = z_n^2 + c$; alors $c$ est dans la fractale ssi la suite $(z_n)$ est bornée.

Le type `Complexe`, la fonction `initComplexe`, la fonction `egaleComplexe`, la fonction
`ajouterComplexe` et la fonction `moduleComplexe` vous sont données ci-dessous. Lisez
leur code pour bien les comprendre.

```cpp
struct Complexe {
    float re, im;
};

void initComplexe(Complexe *c, float reel, float imaginaire) {
    c->re = reel;
    c->im = imaginaire;
}

bool egaleComplexe(Complexe a, Complexe b) {
    return (a.re == b.re) && (a.im == b.im);
}

void ajouterComplexe(Complexe *a, Complexe b) {
    a->re = a->re + b.re;
    a->im = a->im + b.im;
}

float moduleComplexe(Complexe c) {
    return sqrt(pow(c.re, 2) + pow(c.im, 2));
}
```

1. Définissez la fonction `void multiplierComplexe` sur le modèle de la fonction
   `ajouterComplexe` qui prend en entrée deux nombres complexes dont le premier est sous
   la forme d'un pointeur et qui renvoie leur produit en modifiant le premier paramètre.
   La formule de multiplication de deux nombres complexe vous est fournie:

   $$(a_1+i\,b_1) * (a_2+i\,b_2) = a_1 *a_2 - b_1 * b_2 + i\,(a_1*b_2 + a_2 * b_1)$$

   Transcrivez cette formule avec beaucoup de soin. En effet, comme en programmation
   modulaire, la moindre erreur risque de vous faire perdre beaucoup de temps. De plus
   pensez à bien tester votre fonction.

   BEGIN SOLUTION

   Attention ici, il ne faut pas modifier le contenu de {\\tt a} immédiatement lors du
   calcul de la partie réelle car on en a besoin pour le calcul de la partie imaginaire.

   ```cpp
   void multiplierComplexe(Complexe *a, Complexe b) {
       float re, im;
       re = a->re * b.re - a->im * b.im;
       im = a->im * b.re + a->re * b.im;
       a->re = re;
       a->im = im;
   }
   ```

   END SOLUTION

2. Définissez une fonction booléenne `znResteBorne` qui prend un complexe $c$, et renvoie
   vrai si la suite $z_n$ associée ne tend pas vers l'infini, faux sinon. On calculera la
   suite des termes $z_n$, jusqu'à ce que le module de $z_n$ devienne plus grand que $2$
   (auquel cas on supposera que la suite tend vers l'infini), ou $1000$ itérations ont
   été faites (auquel cas on supposera que la suite reste bornée).

   BEGIN SOLUTION

   ```cpp
   bool znResteBorne(Complexe c) {
       Complexe z;
       initComplexe(&z, 0, 0);
       for(int i = 0; i < 1000; i++){
           if (moduleComplexe(z) > 2){
               return false;
           }
           multiplierComplexe(&z, z);
           ajouterComplexe(&z, c);
       }
       return true;
   }
   ```

   END SOLUTION

3. La procédure `mandelbrot` qui vous est donnée ci-dessous utilise la fonction
   `znResteBorne` que vous venez d'écrire pour afficher l'ensemble de Mandelbrot. Elle
   fait varier $x$ entre $-2$ et $0.5$ et $y$ entre $-1.1$ et $+1.1$, et fait un
   affichage ASCII sur $80\times40$ caractères.

   ```cpp
   void mandelbrot() {
       const float xmin = -2;
       const float xmax = 0.5;
       const float ymin = -1.1;
       const float ymax = 1.1;
       const int xresol = 79;
       const int yresol = 39;
       for (int i = 0; i <= yresol; i++) {
           for (int j = 0; j <= xresol; j++) {
               Complexe z;
               initComplexe(&z, (xresol - j) * xmin / xresol
                                  + j * xmax / xresol,
                                (yresol - i) * ymax / yresol
                                  + i * ymin / yresol);
               if (znResteBorne(z)) {
                   cout << '#';
               } else {
                   cout << ' ';
               }
           }
           cout << endl;
       }
   }
   ```

   Exécutez `mandelbrot`, puis modifiez cette procédure pour zoomer sur la figure, en
   faisant varier *x* et *y* sur de plus petits intervalles, autour de points pas trop
   loin de la frontière.
