package nxm.ucl.lib;

/**
 Implements various operations on complex numbers.
 In this case, the real and imaginary coefficients of the numbers
 are passed into static functions, to make the utilities independent of
 implementation.

 @author Hoyt J. Heaton
*/
public class Complex {

  /** Real part of the Complex Number */
  public float real;

  /** Imaginary part Complex Number */
  public float imag;

// Constructors
  /** Complex default constructor */
  public Complex () {
    this(0, 0);
  }

  /** Constructor
   *  @param r real part of a Complex number.
   *  @param i imaginary part of a Complex number.
   */
  public Complex (float r, float i) {
    this.real = r;
    this.imag = i;
  }

  /** input values will be down cast to floats.
      @param r real part of a Complex number.
      @param i imaginary part of a Complex number.
   */
  public Complex (double r, double i) {
    this.real = (float)r;
    this.imag = (float)i;
  }

  /** Constructor
   *  @param c complex number to set this too */
  public Complex (Complex c) {
    this(c.real(), c.imag());
  }

  /** Get the real part of a Complex number.
      @return the real part of of this complex number
   */
  public float real () {
    return real;
  }

  /** Get the imaginary part of a Complex number.
      @return the imaginary part of of this complex number
   */
  public float imag () {
    return imag;
  }

  /** Perform a complex add on this Complex number.
      @param c complex number to add to this
   */
  public void add (Complex c) {
    add(this.real, this.imag, c.real(), c.imag(), this);
  }

  /** Perform a complex multiply on this Complex number.
      @param c complex number to multiply with this
   */
  public void mult (Complex c) {
    float tempReal = (this.real * c.real()) - (this.imag * c.imag());
    this.imag = (this.real * c.imag()) + (this.imag * c.real());
    this.real = tempReal;
  }

  /** Perform a scalar divide on this Complex number.
      @param b    divisor
   */
  public void div (float b) {
    div(this.real, this.imag, b, this);
  }

  /** Compute the absolute value of this complex number.
      @param b not used at this time
   */
  public void abs (float b) {
    abs(this.real, this.imag);
  }

// STATIC METHODS
  /** Multiply a complex number by a float. Result is stored in the cnum object parameter.
     @param real   Real part
     @param imag   Imaginary part
     @param b      Scalar multiplier
     @param result Complex output
  */
  public static void mult(float real, float imag, float b, Complex result) {
    result.real = real * b;
    result.imag = imag * b;
  }

  /** Multiply two complex numbers.
      @param real1  Real part of first Complex number
      @param imag1  Imaginary part of first Complex number
      @param real2  Real part of second Complex number
      @param imag2  Imaginary part of second Complex number
      @param result Complex output
  */
  public static void mult(float real1, float imag1, float real2, float imag2, Complex result) {
    result.real = (real1 * real2) - (imag1 * imag2);
    result.imag = (real1 * imag2) + (imag1 * real2);
  }

  /** Add two complex numbers. Result is stored in the result object parameter.
      @param real1  Real part of first Complex number
      @param imag1  Imaginary part of first Complex number
      @param real2  Real part of second Complex number
      @param imag2  Imaginary part of second Complex number
      @param result Complex output stored in here (cannot be null)
  */
  public static void add(float real1, float imag1, float real2, float imag2, Complex result) {
    result.real = real1 + real2;
    result.imag = imag1 + imag2;
  }

  /** Divide a complex number by a float. Result is store in the result object parameter.
      @param real Real part of complex number
      @param imag Imaginary part of complex number
      @param b    divisor
      @param result Complex output stored in here (cannot be null)
   */
  public static void div(float real, float imag, float b, Complex result) {
    result.real = real / b;
    result.imag = imag / b;
  }

  /** same as calling {@link #div(float, float, float, Complex)}.
      @param real Real part of complex number
      @param imag Imaginary part of complex number
      @param b    divisor
      @param result Complex output stored in here (cannot be null)
   */
  public static void divide(float real, float imag, float b, Complex result) {
    div(real, imag, b, result);
  }

  /** Find absolute value of complex number and return the result.
      @param real Real part of complex number
      @param imag Imaginary part of complex number
      @return absolute value of complex number (i.e. sqrt(real*real + imag*imag))
  */
  public static float abs(float real, float imag) {
     return (float) Math.sqrt( (real*real) + (imag*imag) );
  }

  /** same as calling {@link #abs(float, float)}
      @param real Real part of complex number
      @param imag Imaginary part of complex number
      @return absolute value of complex number
   */
  public static float cabs(float real, float imag) {
    return abs(real, imag);
  }

}