/**
  * Cette classe represente un complexe. Un nombre complexe s'ecrit sous la forme
  * z = a +ib, ou a est la partie reelle et b la partie imaginaire. i etant le 
  * nombre dont le carre vaut -1.
 */
public class Complexe
{
	/** Partie reelle du complexe */
	protected double a;
	/** Partie imaginaire du complexe */
	protected double b;
	
	/** Un premier constructeur ne prenant pas de parametres et creant 
	  * par defaut le complexe 0.
	 */
	public Complexe()
	{
		a = 0.0; b = 0.0;
	}
	
	/** Un deuxieme constructeur permettant de construire un complexe ne
	  * possedant pas de partie imaginaire.
	  * @param r la partie reelle
	 */
	public Complexe(double r)
	{
		a = r; b = 0;
	}
	
	/** Le dernier constructeur (le plus general) permettant de construire 
	  * n'importe quel complexe.
	  * @param r la partie reelle
	  * @param i la partie imaginaire
	 */
	public Complexe(double r, double i)
	{
		a = r; b = i;
	}
	
	/** Affichage d'un complexe sous la forme "a + i b" 
	  * @return la chaine de caracteres representant un complexe 
	 */
	public String toString()
	{
		if (a==0.0 || b==0.0) {
			if (a == 0.0) 
				return b+" i";
			else 
				return ""+a;
		}
		return a+" + "+b+" i";
	}
	
	/** Accesseur permettant de recuperer la partie reelle du complexe 
	  * @return la partie reelle du complexe
	 */
	public double partieReelle()
	{
		return a;
	}
	
	/** Accesseur permettant de recuperer la partie imaginaire du complexe 
	  * @return la partie imaginaire du complexe
	 */
	public double partieImaginaire()
	{
		return b;
	}
	
	/** Test d'egalite entre deux complexes
	  * @param z le complexe a comparer
	  * @return <em>true</em> si les complexes sont egaux, <em>false</em> sinon
	 */
	public boolean equals(Complexe z)
	{
		return (a == z.a) && (b == z.b);
	}
	
	/** Calcul la somme des carres de la partie reelle et de la partie imaginaire
	  * @return la somme des carres de la partie reelle et de la partie imaginaire
	 */
	private double sommeDesCarres()
	{
		return (a * a + b * b);
	}
	
	/** Calcul le module du complexe
	  * @return la valeur du module du complexe
	 */
	public double module()
	{
		return Math.sqrt(sommeDesCarres());
	}
	
	/** Calcul le conjugue du complexe
	  * @return la valeur du conjugue du complexe
	 */
	public void conjugue()
	{
		b = -b;
	}
	
	/** Ajoute au complexe courant le complexe z. Cette methode ne retourne 
	  * pas de resultat car elle modifie le complexe courant (c'est ce que 
	  * l'on appelle un <em>effet de bord</em>, car on modifie l'etat de l'objet).
	  * @param z le complexe a ajouter
	 */
	public void ajouter(Complexe z)
	{
		a = a + z.a;
		b = b + z.b;
	}
	
	/** Ajoute au complexe courant un reel. Cette methode ne retourne 
	  * pas de resultat car elle modifie le complexe courant (c'est ce que 
	  * l'on appelle un <em>effet de bord</em>, car on modifie l'etat de l'objet).
	  * @param r le reel a ajouter
	 */
	public void ajouter(double r)
	{
		a = a + r;
	}
	
	/** Retourne un nouveau complexe representant l'addition du complexe courant 
	  * au complexe passe en parametre. Contrairement aux methodes <em>ajouter</em>,
	  * cette methode ne provoque pas d'effets de bord et retourne un nouvel objet ! 
	  * @param z le complexe a ajouter
	  * @return la somme du complexe courant et de z
	 */
	public Complexe addition(Complexe z)
	{
		return new Complexe(a + z.a, b + z.b);
	}
	
	/** Retourne un nouveau complexe representant l'addition du complexe courant 
	  * au reel passe en parametre. Contrairement aux methodes <em>ajouter</em>,
	  * cette methode ne provoque pas d'effets de bord et retourne un nouvel objet ! 
	  * @param r le reel a ajouter
	  * @return la somme du complexe courant et de r
	 */
	public Complexe addition(double r)
	{
		return new Complexe(a + r, b);
	}
	
	/** Retourne un nouveau complexe representant la multiplication du complexe 
	  * courant au complexe passe en parametre.
	  * @param z le complexe a multiplier
	  * @return le resultat de la multiplication du complexe courant et de z
	 */
	public Complexe multiplication(Complexe z)
	{
		return new Complexe(a * z.a - b * z.b, a * z.b + z.a * b);
	}
	
	/** Retourne un nouveau complexe representant la multiplication du complexe 
	  * courant au reel passe en parametre.
	  * @param r le reel a multiplier
	  * @return le resultat de la multiplication du complexe courant et de r
	 */
	public Complexe multiplication(double r)
	{
		return new Complexe(a * r, b * r);
	}
	
	/** Retourne un nouveau complexe representant la division du complexe 
	  * courant par le complexe passe en parametre.
	  * @param z le diviseur
	  * @return le resultat de la division du complexe courant par z
	 */
	public Complexe division(Complexe z)
	{
		return new Complexe( (a * z.a + b * z.b) / z.sommeDesCarres(), 
		                     (-a * z.b + z.a * b) / z.sommeDesCarres());
	}
	
}
