# -*- coding:utf-8 -*-

__nom_fichier__ = "suiteComplexe"
__author__ = "Anne-Julie Tinet - Christine Fay-Varnier"
__date__ = "mars 2020"

from complexe import Complexe
from copy import copy

# **************************************************************************

class SuiteComplexe:
    """La classe suite complexe considère la suite:
        u0 = z
        un+1 = un^p + c
    """

    def __init__(self, p, c, niter=128, u0=None):
        """ Définit une suite complexe : un+1 = un^p + c avec u0 = z
        @param: p
        @param: c
        @param: niter nombre d'itération maximal
        @param: z valeur initiale de la suite
        """

        self.p_ = p
        self.c_ = c
        self.niter_ = niter

        if u0 is None:
            self.u0_ = Complexe()
        else:
            self.u0_ = u0

    def set_u0(self, z):
        """

        @param z:  nouvelle valeur initiale
        :return:    mutateur de la valeur initiale
        """
        self.u0_ = z

    def set_cste(self, c):
        """

        @param c:   nouvelle constante de la suite
        :return:    mutateur de la constante c
        """
        self.c_ = c

    def get_nbiter(self):
        """

        :return:     accesseur du nombre d'itérations
        """
        return self.niter_

    def suivant(self, zn):
        """

        @param zn:  valeur courante de la suite
        :return:    calcule  un+1 à partir de un
        """
        return zn ** self.p_ + self.c_

    def diverge(self):
        """

        :return:    Renvoie le nombre d'itération correspondant au dépassement du critère de
                    convergence pour la norme.
                    S'il n'y a pas convergence, renvoie niter
        """
        # pour éviter que u0 soit modifié, on en fait une copie
        zn = copy(self.u0_)
        # on regarde si la suite diverge
        # pour ne pas faire trop d'itérations, on arrête l'itérations quand on atteint niter itération max
        for i in range(self.niter_):
            if zn.norme() > 2:
                # la suite diverge on retourne le range à partir duquel elle diverge
                return i

            zn = self.suivant(zn)
        # la suite ne diverge pas on retourne le nombre max d'itérations atteint

        return self.niter_

if __name__ == '__main__':
    c = Complexe(0.285, 0.01)
    z = Complexe(-0.98, - 1.0)
    suite = SuiteComplexe(2, c, 256, z)
    # print(suite.suivant(z))
    # print("c : ", c)
    # print("z : ", z)
    # print("pour SuiteComplexe(2, c, 256, z)")
    # print("la suite diverge à partir de : ", suite.diverge())
    #
    # suite.set_u0(Complexe(0.8, 0.42))
    # print("\nModification de u0 : ", suite.u0_)
    # print(suite.diverge())

    u0 = Complexe(-0.09, -0.44)
    suite = SuiteComplexe(3, c, 128, u0)
    print(suite.diverge())