/*****************************************************
*  Class to store and manipulate complex numbers     *
*                                                    *
*  Methods:  add, subtract, mult, div, conjugate,    *
*	mag, toString                                  *					
*                                                    *
*  Author:  Jay Henniger                             *
*  Date:    July 5, 2001                             *
*  email:   jlh75@cornell.edu                        *
*                                                    *
*****************************************************/
		
public class Complex{

   //An instance of the Complex class, a complex number,
   //consists of a real and imaginary part.

   public double real, imag;

   //Constructor takes real and imaginary parts as 
   //arguments and sets them to real and imag.

   public Complex(double r, double i)
   {
      real = r;
      imag = i;
   }

   //Input:  Complex number c
   //Output:  String representation of c (i.e. a + bi)

   public static String toString(Complex c)
   {
      return "" + c.real + " + " + c.imag + "i";
   }

   //Input:  Complex number c
   //Output:  Magnitude of c

   public static double mag(Complex c)
   {
      return Math.sqrt(c.real * c.real + c.imag * c.imag);
   }

   //Input:  A complex number
   //Output:  true if calling Complex and passed Complex
   //are almost (< 10^-14 difference) or exactly equal.
	
   public boolean equals(Complex d){
      double tol = Math.pow(10.0,-14);
	double realDiff, imagDiff;
	realDiff = Math.abs(this.real - d.real);
	imagDiff = Math.abs(this.imag - d.imag);
	if(realDiff < tol && imagDiff < tol)
      {
	   return true;
	}
      else{
	   return false;
	}
   }//end equals(Complex d)

   //Input:  A complex number and an error tolerance
   //Output:  true if calling Complex and passed Complex
   //are almost (difference < error tolerance) or exactly equal.
	
   public boolean equals(Complex d, double tol){
     	double realDiff, imagDiff;
	realDiff = Math.abs(this.real - d.real);
	imagDiff = Math.abs(this.imag - d.imag);
	if(realDiff < tol && imagDiff < tol)
      {
	   return true;
	}
      else{
	   return false;
	}
   }//end equals(Complex d)   //Input:  A complex number
   //Output:  It's complex conjugate

   public static Complex conjugate(Complex c)
   {
      return new Complex(c.real, -c.imag);
   }
   
   //Input:  Two complex numbers
   //Output:  The product of the two numbers

   public static Complex mult(Complex c, Complex d)
   {
      double r, i;  //the real and imag parts of the new Complex
      r = c.real * d.real - c.imag * d.imag;
      i = c.imag * d.real + c.real * d.imag;
      return new Complex(r,i);
   }

   public static Complex div(Complex c, Complex d)
   {
      double r, i;
	if(mag(d) != 0)   //don't want to divide by zero
	{
         r = mult(c, conjugate(d)).real/mag(d);
         i = mult(c, conjugate(d)).imag/mag(d);
	}
	else
	{
	   //return some ridiculous number if user 
	   //tries to divide by zero (bad user!)
	
	   r = -Math.pow(9.99999999,20);
	   i = -Math.pow(9.99999999,20);
	}
      return new Complex(r,i);
   }

   //Input:  Two complex numbers
   //Output:  The sum of the two numbers

   public static Complex add(Complex c, Complex d)
   {
      return new Complex(c.real + d.real, c.imag + d.imag);
   }

   //Input:  Two complex numbers (c,c)
   //Output:  The difference c - d

   public static Complex subtract(Complex c, Complex d)
   {
      return new Complex(c.real - d.real, c.imag - d.imag);
   }

   


   public static void main(String args[]){
	Complex c = new Complex(1.0,1.0);
      Complex d = new Complex(0.2,1.0);
	Complex e = new Complex(1.000000000000001,2);
	Complex f = new Complex(1,2.000000000000001);
	System.out.println("e = " + toString(e) + " , f = " + toString(f));
	System.out.println("e.equals(f) is " + e.equals(f));
      System.out.println("c.equals(d) is " + c.equals(d));
	System.out.println("The mag of c is " + mag(c));
	System.out.println("c * d = " + toString(mult(c,d)));
      System.out.println("c/d = " + toString(div(c,d)));

	//Demonstration of round-off error
	double myPI = Math.PI;
	for(int i = 1; i <= 3; i++)
      {
         myPI = Math.sqrt(myPI);
	}
	for(int i = 1; i <= 3; i++)
      {
         myPI = myPI * myPI;
	}
	System.out.println("\nPi = " + Math.PI+ " myPI = " + myPI);
   }

}