/**
 * Represents a complex number of the form a + bi.
 *
 * @author Jonas L. Jensen
 */

import java.util.StringTokenizer;

public class ComplexNumber {
    private double a, b;
    public static final ComplexNumber ZERO = new ComplexNumber(0,0);
    public static final ComplexNumber i = new ComplexNumber(0,1);
    public static final ComplexNumber ONE = new ComplexNumber(1,0);

    /**
     * Initializes a new complex number, with the value zero.
     */
    public ComplexNumber() { a = 0; b = 0; }
    
    /**
     * Initializes a complex number with the value a + bi.
     *
     * @param a real part of the number
     *        b imaginary part of the number
     */
    public ComplexNumber(double a, double b) { this.a = a; this.b = b; }


    /**
     * Initializes a complex number with the specified value. The string parameter must
     * be of the form 'a + bi', 'a' or 'bi'.
     *
     * @param num A String-representation of a complex number (a+bi)
     */
    public ComplexNumber(String num) throws NumberFormatException {
	StringTokenizer t = new StringTokenizer(num, " ", false);
	String[] tokens = new String[3];
	int n;

	for(n = 0; t.hasMoreTokens(); n++)
	    tokens[n] = t.nextToken();

	if (n==1) {
	    if (tokens[0].equals("i")) {
		setValue(0, 1);
		return;
	    }
			 
	    if (tokens[0].endsWith("i")) {
	        setValue(0, Double.parseDouble(tokens[0].substring(0, tokens[0].length() - 1)));
	    } else {
		setValue(Double.parseDouble(tokens[0]), 0);
	    }
	}

	if (n==3) {
	    double a,b;
	    a = Double.parseDouble(tokens[0]);
	    b = Double.parseDouble(tokens[2].substring(0, tokens[2].length()-1));

	    if (tokens[1].equals("+")) {
		setValue(a,b);
		return;
	    } if (tokens[1].equals("-")) {
		setValue(a,-b);
		return;
	    } else throw new NumberFormatException("Invalid complex number. Must be of form a + bi");
	}
    }
	    
		

    /**
     * Sets the value of the number to a + bi.
     *
     * @param a real part of the new value
     *        b imaginary part of the new value
     */
    public void setValue(double a, double b) {
	this.a = a; this.b = b;
    }
    
    /**
     * Returns an array with the real par, and the imaginary part
     * of the number.
     *
     * @return <code>{ a, b }</code> where <code>this = a + bi</code>
     */
    public double[] getValue() {
	double w[] = { a, b };
	return w;
    }

    /**
     * Returns a complex number with the value <code>this * z</code>
     *
     * @param z the number to multiplicate with
     * @return this * z
     */
    public ComplexNumber multiplicate(ComplexNumber z) {
	double[] w = z.getValue();
	return new ComplexNumber(a*w[0] - b*w[1], b*w[0] + a*w[1]);
    }

    /**
     * Returns the reciprocial of the number (1/<code>this</code>)
     *
     * @return 1/this
     */
    public ComplexNumber inverse() {
	return new ComplexNumber(a / (a*a + b*b), -b / (a*a + b*b));
    }

    /**
     * Returns <code>this</code> divided by <code>z</code>
     *
     * @param z the number to divide with
     * @return <code>this / z</code>
     */
    public ComplexNumber divide(ComplexNumber z) {
	return this.multiplicate(z.inverse());
    }

    /**
     * Returns <code>this</code> plus <code>z</code>
     *
     * @param z the number to add to this
     * @return <code>this + z</code>
     */
    public ComplexNumber add(ComplexNumber z) {
	double[] w = z.getValue();
	return new ComplexNumber(a + w[0], b + w[1]);
    }

    /**
     * Returns <code>this</code> minus <code>z</code>
     *
     * @param z the number to subtract from this
     * @return <code>this - z</code>
     */
    public ComplexNumber subtract(ComplexNumber z) {
	double[] w = z.getValue();
	return new ComplexNumber(a - w[0], b - w[1]);
    }


    public boolean equals(ComplexNumber z) {
	if (z == null) return false;

	double[] x = z.getValue();

	if ( (x[0]==a) && (x[1]==b) ) return true;
	else return false;
    }


    /**
     * Returns the norm of the complexnumber, sqrt(a^2 + b^2)
     *
     * @return ||this||
     */
    public double norm() { return Math.sqrt(a*a + b*b); }


    /**
     * Returns argument of number
     *
     * @return arg(this)
     */
    public double arg() { return Math.atan2(a,b); }


    /**
     * Returns a string representating the complex number as a+bi. Eg:
     * <p> 1+2i will be returnned as <code> 1.0 + 2.0i </code>
     *
     * @return String representation of the number
     */
    public String toString() { 
	if (b==0) return "" + a;
	if (a==0) return b + "i"; 
	else return "" + a + " + " + b + "i";
    }
}	

