# -*- coding: utf-8 -*-

__nom_fichier__ = "complexe"
__author__ = "Anne-Julie Tinet - Christine Fay-Varnier"
__date__ = "mars 2020"

#  Description:    programme de modélisation de la classe complexe

from math import sqrt

class Complexe:
    """ Cette classe définit les nombres complexes, et permet l'utilisation
    d'opérations simples."""

    def __init__(self, partie_reelle=0, partie_imaginaire=0):
        """

        @param partie_reelle:       partie réelle
        @param partie_imaginaire:   partie imaginaire
        """

        self.reel_ = partie_reelle
        self.imag_ = partie_imaginaire

    def get_pr(self):
        """

        :return:    retourne la partie réelle
        """
        return self.reel_

    def get_pim(self):
        """

        :return:    retourne la partie imaginaire
        """
        return self.imag_

    def set_pr(self, newpr):
        """
        :newpr      nouvelle valeurde la partie réelle
        :return:     modifie la partie réelle
        """
        self.reel_ = newpr

    def set_pim(self, newpim):
        """

        @param newpim:  nouvelle valeur de la partie imaginaire
        :return:        modifie la partie imaginaire
        """
        self.imag_ = newpim

    def __add__(self, other):
        """

        @param other:   second complexe
        :return:        un complexe (surcharge de +), somme de deux complexes
        """

        return Complexe(self.reel_ + other.reel_, self.imag_ + other.imag_)

    def __mul__(self, other):
        """

        @param other:   second complexe
        :return:        un complexe (surcharge de *), produit de deux complexes
        """

        return Complexe(self.reel_ * other.reel_ - self.imag_ * other.imag_, \
                        self.reel_ * other.imag_ + self.imag_ * other.reel_)

    def __pow__(self, p):
        """

        @param p:   exposant (entier)
        :return:    le complexe à la puissance p (surcharge de **)
        """

        cpx = Complexe(1, 0)
        for i in range(p):
            cpx = cpx * self

        return cpx

    def __str__(self):
        """

        :return:    Affichage (surcharge de print) sur l'écran du nombre
        complexe sous la forme x+yi
        """

        if self.imag_ >= 0.:
            return str(self.reel_) + ' + ' + str(self.imag_) + ' i'
        else:
            return str(self.reel_) + ' - ' + str(-self.imag_) + ' i'

    def multiplie(self, scalaire):
        """

        @param scalaire:    coefficient entier
        :return:            Multiplie le nombre complexe par un scalaire
        """

        self.reel_ *= scalaire
        self.imag_ *= scalaire

    def conjugue(self):
        """

        :return:    le conjugué d'un nombre complexe
        """

        return Complexe(self.reel_, -self.imag_)

    def norme(self):
        """

        :return:    la norme (scalaire) d'un nombre complexe
        """

        return sqrt(self.reel_ ** 2 + self.imag_ ** 2)

    def inverse(self):
        """

        :return:    l'inverse d'un nombre complexe
        """

        cpx = self.conjugue()
        cpx.multiplie((self.norme()) ** 2)
        return cpx

if __name__ == '__main__':
    cpx1 = Complexe(-5, 10)
    cpx2 = Complexe(4, 8)
    cpxmul = cpx1 * cpx2
    print(cpxmul)

    print(cpx1**4)

    cpx = Complexe(2,0)
    print(cpx**5)

    print(cpx1**4)