/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.commons.numbers.complex;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.numbers.core.Precision;
/**
 * Representation of a Complex number, i.e. a number which has both a
 * real and imaginary part.
 * <p>
 * Implementations of arithmetic operations handle {@code NaN} and
 * infinite values according to the rules for {@link java.lang.Double}, i.e.
 * {@link #equals} is an equivalence relation for all instances that have
 * a {@code NaN} in either real or imaginary part, e.g. the following are
 * considered equal:
 * <ul>
 *  <li>{@code 1 + NaNi}</li>
 *  <li>{@code NaN + i}</li>
 *  <li>{@code NaN + NaNi}</li>
 * </ul><p>
 * Note that this contradicts the IEEE-754 standard for floating
 * point numbers (according to which the test {@code x == x} must fail if
 * {@code x} is {@code NaN}). The method
 * {@link org.apache.commons.numbers.core.Precision#equals(double,double,int)
 * equals for primitive double} in class {@code Precision} conforms with
 * IEEE-754 while this class conforms with the standard behavior for Java
 * object types.</p>
 *
 */
public class Complex implements Serializable  {
    /** The square root of -1. A number representing "0.0 + 1.0i" */
    public static final Complex I = new Complex(0.0, 1.0);
    // CHECKSTYLE: stop ConstantName
    /** A complex number representing "NaN + NaNi" */
    public static final Complex NaN = new Complex(Double.NaN, Double.NaN);
    // CHECKSTYLE: resume ConstantName
    /** A complex number representing "+INF + INFi" */
    public static final Complex INF = new Complex(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
    /** A complex number representing "1.0 + 0.0i" */
    public static final Complex ONE = new Complex(1.0, 0.0);
    /** A complex number representing "0.0 + 0.0i" */
    public static final Complex ZERO = new Complex(0.0, 0.0);

    /** Serializable version identifier */
    private static final long serialVersionUID = -6195664516687396620L;

    /** The imaginary part. */
    private final double imaginary;
    /** The real part. */
    private final double real;

    /**
     * Create a complex number given only the real part.
     *
     * @param real Real part.
     */
    public Complex(double real) {
        this(real, 0.0);
    }

     /**
     * Create a complex number given the real and imaginary parts.
     *
     * @param real Real part.
     * @param imaginary Imaginary part.
     */
    public Complex(double real, double imaginary) {
        this.real = real;
        this.imaginary = imaginary;
    }

     /**
     * Creates a Complex from its polar representation.
     * <p>
     * If either {@code r} or {@code theta} is NaN, or {@code theta} is
     * infinite, {@link Complex#NaN} is returned.
     * <p>
     * If {@code r} is infinite and {@code theta} is finite, infinite or NaN
     * values may be returned in parts of the result, following the rules for
     * double arithmetic.
     *
     * <pre>
     * Examples:
     * {@code
     * polar2Complex(INFINITY, \(\pi\)) = INFINITY + INFINITY i
     * polar2Complex(INFINITY, 0) = INFINITY + NaN i
     * polar2Complex(INFINITY, \(-\frac{\pi}{4}\)) = INFINITY - INFINITY i
     * polar2Complex(INFINITY, \(5\frac{\pi}{4}\)) = -INFINITY - INFINITY i }
     * </pre>
     *
     * @param r the modulus of the complex number to create
     * @param theta the argument of the complex number to create
     * @return {@code Complex}
     * @since 1.1
     */
    public Complex polar(double r, double theta) {
        checkNotNegative(r);
        return new Complex(r * Math.cos(theta), r * Math.sin(theta));
    }

    /**
     * For a real constructor argument x, returns a new Complex object c
     * where {@code c = cos(x) + i sin (x)}
     *
     * @param x {@code double} to build the cis number
     * @return {@code Complex}
     */
    public Complex cis(double x) {
        return new Complex(Math.cos(x), Math.sin(x));
    }

    /**
     * Returns true if either real or imaginary component of the Complex
     * is NaN
     * 
     * @return {@code boolean}
     */
    public boolean isNaN() {
        if (Double.isNaN(real) || Double.isNaN(imaginary)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Returns true if either real or imaginary component of the Complex
     * is Infinite 
     * 
     * @return {@code boolean}
     */
    public boolean isInfinite() {
        if (Double.isInfinite(real) || Double.isInfinite(imaginary)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Returns projection of this complex number onto the Riemann sphere,
     * i.e. all infinities (including those with an NaN component)
     * project onto real infinity, as described in the
     * <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/cproj.html">
     * IEEE and ISO C standards</a>.
     * <p>
     *
     *
     * @return {@code Complex} projected onto the Riemann sphere.
     */
    public Complex proj() {
        if (Double.isInfinite(real) || Double.isInfinite(imaginary)) {
            return new Complex(Double.POSITIVE_INFINITY);
        } else {
            return this;
        }
    }

     /**
     * Return the absolute value of this complex number.
     * Returns {@code NaN} if either real or imaginary part is {@code NaN}
     * and {@code Double.POSITIVE_INFINITY} if neither part is {@code NaN},
     * but at least one part is infinite.
     * This code follows the <a href="http://www.iso-9899.info/wiki/The_Standard">ISO C Standard</a>, Annex G, in calculating the returned value (i.e. the hypot(x,y) method)
     *
     * @return the absolute value.
     */
    public double abs() {
        if (Math.abs(real) < Math.abs(imaginary)) {
            final double q = real / imaginary;
            return Math.abs(imaginary) * Math.sqrt(1 + q * q);
        } else {
            if (real == 0.0) {
                return Math.abs(imaginary);
            }
            final double q = imaginary / real;
            return Math.abs(real) * Math.sqrt(1 + q * q);
        }
    }

     /**
     * Return the norm of this complex number, defined as the square of the magnitude
in the
     * <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/cproj.html">
     * IEEE and ISO C standards</a>.
     *
     * @return the norm.
     */
    public double norm() {
        return abs()*abs();
    }

    /**
     * Returns a {@code Complex} whose value is
     * {@code (this + addend)}.
     * Uses the definitional formula
     * <p>
     *   {@code (a + bi) + (c + di) = (a+c) + (b+d)i}
     * </p>
     *
     * @param  addend Value to be added to this {@code Complex}.
     * @return {@code this + addend}.
     * @if {@code addend} is {@code null}.
     */
    public Complex add(Complex addend) {
        checkNotNull(addend);
        return new Complex(real + addend.getReal(),
                             imaginary + addend.getImaginary());
    }

    /**
     * Returns a {@code Complex} whose value is {@code (this + addend)},
     * with {@code addend} interpreted as a real number.
     *
     * @param addend Value to be added to this {@code Complex}.
     * @return {@code this + addend}.
     * @see #add(Complex)
     */
    public Complex add(double addend) {
        return new Complex(real + addend, imaginary);
    }

     /**
     * Returns the conjugate of this complex number.
     * The conjugate of {@code a + bi} is {@code a - bi}.
     *
     * @return the conjugate of this complex object.
     */
    public Complex conjugate() {
        return new Complex(real, -imaginary);
    }

     /**
     * Returns the conjugate of this complex number.
     * C++11 grammar.
     * </p>
     * @return the conjugate of this complex object.
     */
    public Complex conj() {
        return conjugate();
    }


    /**
     * Returns a {@code Complex} whose value is
     * {@code (this / divisor)}.
     * Implements the definitional formula
     * <pre>
     *  <code>
     *    a + bi          ac + bd + (bc - ad)i
     *    ----------- = -------------------------
     *    c + di         c<sup>2</sup> + d<sup>2</sup>
     *  </code>
     * </pre>
     * but uses
     * <a href="http://doi.acm.org/10.1145/1039813.1039814">
     * prescaling of operands</a> to limit the effects of overflows and
     * underflows in the computation.
     * <p>
     * {@code Infinite} and {@code NaN} values are handled according to the
     * following rules, applied in the order presented:
     * <ul>
     *  <li>If {@code divisor} equals {@link #ZERO}, {@link #NaN} is returned.
     *  </li>
     *  <li>If {@code this} and {@code divisor} are both infinite,
     *   {@link #NaN} is returned.
     *  </li>
     *  <li>If {@code this} is finite (i.e., has no {@code Infinite} or
     *   {@code NaN} parts) and {@code divisor} is infinite (one or both parts
     *   infinite), {@link #ZERO} is returned.
     *  </li>
     *  <li>If {@code this} is infinite and {@code divisor} is finite,
     *   {@code NaN} values are returned in the parts of the result if the
     *   {@link java.lang.Double} rules applied to the definitional formula
     *   force {@code NaN} results.
     *  </li>
     * </ul>
     *
     * @param divisor Value by which this {@code Complex} is to be divided.
     * @return {@code this / divisor}.
     * @if {@code divisor} is {@code null}.
     */
    public Complex divide(Complex divisor) {
        checkNotNull(divisor);

        final double c = divisor.getReal();
        final double d = divisor.getImaginary();
        if (c == 0.0 && d == 0.0) {
            return NaN;
        }

        if ( (Double.isInfinite(c) || Double.isInfinite(d))&& (Double.isInfinite(real) || Double.isInfinite(imaginary))) {
            return ZERO;
        }

        if (Math.abs(c) < Math.abs(d)) {
            final double q = c / d;
            final double denominator = c * q + d;
            return new Complex((real * q + imaginary) / denominator,
                (imaginary * q - real) / denominator);
        } else {
            final double q = d / c;
            final double denominator = d * q + c;
            return new Complex((imaginary * q + real) / denominator,
                (imaginary - real * q) / denominator);
        }
    }

    /**
     * Returns a {@code Complex} whose value is {@code (this / divisor)},
     * with {@code divisor} interpreted as a real number.
     *
     * @param  divisor Value by which this {@code Complex} is to be divided.
     * @return {@code this / divisor}.
     * @see #divide(Complex)
     */
    public Complex divide(double divisor) {
        if (divisor == 0d) {
            return NaN;
        }
        if (Double.isInfinite(divisor)) {
            return !(Double.isInfinite(real) || Double.isInfinite(imaginary)) ? ZERO : NaN;
        }
        return new Complex(real / divisor,
                             imaginary  / divisor);
    }

    /**
     * Returns the multiplicative inverse of this instance.
     *
     * @return {@code 1 / this}.
     * @see #divide(Complex)
     */
    public Complex reciprocal() {
        if (Math.abs(real) < Math.abs(imaginary)) {
            final double q = real / imaginary;
            final double scale = 1. / (real * q + imaginary);
            double scaleQ = 0;
            if (q != 0 && scale != 0) {
                scaleQ = scale * q;
            }
            return new Complex(scaleQ, -scale);
        } else {
            final double q = imaginary / real;
            final double scale = 1. / (imaginary * q + real);
            double scaleQ = 0;
            if (q != 0 && scale != 0) {
                scaleQ = scale * q;
            }
            return new Complex(scale, -scaleQ);
        }
    }

    /**
     * Test for equality with another object.
     * If both the real and imaginary parts of two complex numbers
     * are exactly the same, and neither is {@code Double.NaN}, the two
     * Complex objects are considered to be equal.
     * The behavior is the same as for JDK's {@link Double#equals(Object)
     * Double}:
     * <ul>
     *  <li>All {@code NaN} values are considered to be equal,
     *   i.e, if either (or both) real and imaginary parts of the complex
     *   number are equal to {@code Double.NaN}, the complex number is equal
     *   to {@code NaN}.
     *  </li>
     *  <li>
     *   Instances constructed with different representations of zero (i.e.
     *   either "0" or "-0") are <em>not</em> considered to be equal.
     *  </li>
     * </ul>
     *
     * @param other Object to test for equality with this instance.
     * @return {@code true} if the objects are equal, {@code false} if object
     * is {@code null}, not an instance of {@code Complex}, or not equal to
     * this instance.
     */
    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }
        if (other instanceof Complex){
            Complex c = (Complex) other;
            return equals(real, c.real) &&
            equals(imaginary, c.imaginary);
        }
        return false;
    }

    /**
     * Test for the floating-point equality between Complex objects.
     * It returns {@code true} if both arguments are equal or within the
     * range of allowed error (inclusive).
     *
     * @param x First value (cannot be {@code null}).
     * @param y Second value (cannot be {@code null}).
     * @param maxUlps {@code (maxUlps - 1)} is the number of floating point
     * values between the real (resp. imaginary) parts of {@code x} and
     * {@code y}.
     * @return {@code true} if there are fewer than {@code maxUlps} floating
     * point values between the real (resp. imaginary) parts of {@code x}
     * and {@code y}.
     *
     * @see Precision#equals(double,double,int)
     */
    public static boolean equals(Complex x, Complex y, int maxUlps) {
        return Precision.equals(x.real, y.real, maxUlps) &&
            Precision.equals(x.imaginary, y.imaginary, maxUlps);
    }

    /**
     * Returns {@code true} iff the values are equal as defined by
     * {@link #equals(Complex,Complex,int) equals(x, y, 1)}.
     *
     * @param x First value (cannot be {@code null}).
     * @param y Second value (cannot be {@code null}).
     * @return {@code true} if the values are equal.
     */
    public static boolean equals(Complex x, Complex y) {
        return equals(x, y, 1);
    }

    /**
     * Returns {@code true} if, both for the real part and for the imaginary
     * part, there is no double value strictly between the arguments or the
     * difference between them is within the range of allowed error
     * (inclusive).  Returns {@code false} if either of the arguments is NaN.
     *
     * @param x First value (cannot be {@code null}).
     * @param y Second value (cannot be {@code null}).
     * @param eps Amount of allowed absolute error.
     * @return {@code true} if the values are two adjacent floating point
     * numbers or they are within range of each other.
     *
     * @see Precision#equals(double,double,double)
     */
    public static boolean equals(Complex x, Complex y, double eps) {
        return Precision.equals(x.real, y.real, eps) &&
            Precision.equals(x.imaginary, y.imaginary, eps);
    }

    /**
     * Returns {@code true} if, both for the real part and for the imaginary
     * part, there is no double value strictly between the arguments or the
     * relative difference between them is smaller or equal to the given
     * tolerance. Returns {@code false} if either of the arguments is NaN.
     *
     * @param x First value (cannot be {@code null}).
     * @param y Second value (cannot be {@code null}).
     * @param eps Amount of allowed relative error.
     * @return {@code true} if the values are two adjacent floating point
     * numbers or they are within range of each other.
     *
     * @see Precision#equalsWithRelativeTolerance(double,double,double)
     */
    public static boolean equalsWithRelativeTolerance(Complex x, Complex y,
                                                      double eps) {
        return Precision.equalsWithRelativeTolerance(x.real, y.real, eps) &&
            Precision.equalsWithRelativeTolerance(x.imaginary, y.imaginary, eps);
    }

    /**
     * Get a hashCode for the complex number.
     * Any {@code Double.NaN} value in real or imaginary part produces
     * the same hash code {@code 7}.
     *
     * @return a hash code value for this object.
     */
    @Override
    public int hashCode() {
        if (Double.isNaN(real) || Double.isNaN(imaginary)) {
            return 7;
        }
        return 37 * 17 * (hash(imaginary) +
            hash(real));
    }

    private int hash(double d) {
        final long v = Double.doubleToLongBits(d);
        return (int)(v^(v>>>32));
        //return new Double(d).hashCode();
    }

    /**
     * Access the imaginary part.
     *
     * @return the imaginary part.
     */
    public double getImaginary() {
        return imaginary;
    }
    /**
     * Access the imaginary part (C++ grammar)
     *
     * @return the imaginary part.
     */
    public double imag() {
        return imaginary;
    }

    /**
     * Access the real part.
     *
     * @return the real part.
     */
    public double getReal() {
        return real;
    }

     /**
     * Access the real part (C++ grammar)
     *
     * @return the real part.
     */
    public double real() {
        return real;
    }

    /**
     * Returns a {@code Complex} whose value is {@code this * factor}.
     * Implements preliminary checks for {@code NaN} and infinity followed by
     * the definitional formula:
     * <p>
     *   {@code (a + bi)(c + di) = (ac - bd) + (ad + bc)i}
     * </p>
     * Returns {@link #NaN} if either {@code this} or {@code factor} has one or
     * more {@code NaN} parts.
     * <p>
     * Returns {@link #INF} if neither {@code this} nor {@code factor} has one
     * or more {@code NaN} parts and if either {@code this} or {@code factor}
     * has one or more infinite parts (same result is returned regardless of
     * the sign of the components).
     * </p><p>
     * Returns finite values in components of the result per the definitional
     * formula in all remaining cases.</p>
     *
     * @param  factor value to be multiplied by this {@code Complex}.
     * @return {@code this * factor}.
     * @if {@code factor} is {@code null}.
     */
    public Complex multiply(Complex factor) {
        checkNotNull(factor);
        return new Complex(real * factor.real - imaginary * factor.imaginary,
                             real * factor.imaginary + imaginary * factor.real);
    }

    /**
     * Returns a {@code Complex} whose value is {@code this * factor}, with {@code factor}
     * interpreted as a integer number.
     *
     * @param  factor value to be multiplied by this {@code Complex}.
     * @return {@code this * factor}.
     * @see #multiply(Complex)
     */
    public Complex multiply(final int factor) {
        return new Complex(real * factor, imaginary * factor);
    }

    /**
     * Returns a {@code Complex} whose value is {@code this * factor}, with {@code factor}
     * interpreted as a real number.
     *
     * @param  factor value to be multiplied by this {@code Complex}.
     * @return {@code this * factor}.
     * @see #multiply(Complex)
     */
    public Complex multiply(double factor) {
        return new Complex(real * factor, imaginary * factor);
    }

    /**
     * Returns a {@code Complex} whose value is {@code (-this)}.
     * Returns {@code NaN} if either real or imaginary
     * part of this complex number is {@code Double.NaN}.
     *
     * @return {@code -this}.
     */
    public Complex negate() {
        return new Complex(-real, -imaginary);
    }

    /**
     * Returns a {@code Complex} whose value is
     * {@code (this - subtrahend)}.
     * Uses the definitional formula
     * <p>
     *  {@code (a + bi) - (c + di) = (a-c) + (b-d)i}
     * </p>
     *
     * @param  subtrahend value to be subtracted from this {@code Complex}.
     * @return {@code this - subtrahend}.
     */
    public Complex subtract(Complex subtrahend) {
        checkNotNull(subtrahend);
        return new Complex(real - subtrahend.getReal(),
                             imaginary - subtrahend.getImaginary());
    }

    /**
     * Returns a {@code Complex} whose value is
     * {@code (this - subtrahend)}.
     *
     * @param  subtrahend value to be subtracted from this {@code Complex}.
     * @return {@code this - subtrahend}.
     * @see #subtract(Complex)
     */
    public Complex subtract(double subtrahend) {
        return new Complex(real - subtrahend, imaginary);
    }

    /**
     * Compute the
     * <a href="http://mathworld.wolfram.com/InverseCosine.html" TARGET="_top">
     * inverse cosine</a> of this complex number.
     * Implements the formula:
     * <p>
     *  {@code acos(z) = -i (log(z + i (sqrt(1 - z<sup>2</sup>))))}
     * </p>
     *
     * @return the inverse cosine of this complex number.
     */
    public Complex acos() {
        if (real == 0.0&& Double.isNaN(imaginary)) {
            return new Complex(Math.PI * 0.5, Double.NaN);
        } else if (neitherInfiniteNorZeroNorNaN(real) && imaginary == Double.POSITIVE_INFINITY) {
            return new Complex(Math.PI * 0.5, Double.NEGATIVE_INFINITY);
        } else if (real == Double.NEGATIVE_INFINITY && imaginary == 1) {
            return new Complex(Math.PI, Double.NEGATIVE_INFINITY);
        } else if (real == Double.POSITIVE_INFINITY && imaginary == 1) {
            return new Complex(0, Double.NEGATIVE_INFINITY);
        } else if (real == Double.NEGATIVE_INFINITY && imaginary == Double.POSITIVE_INFINITY) {
            return new Complex(Math.PI * 0.75, Double.NEGATIVE_INFINITY);
        } else if (real == Double.POSITIVE_INFINITY && imaginary == Double.POSITIVE_INFINITY) {
            return new Complex(Math.PI * 0.25, Double.NEGATIVE_INFINITY); 
        } else if (real == Double.POSITIVE_INFINITY && Double.isNaN(imaginary)) {
            return new Complex(Double.NaN , Double.POSITIVE_INFINITY);
        } else if (real == Double.NEGATIVE_INFINITY && Double.isNaN(imaginary)) {
            return new Complex(Double.NaN, Double.NEGATIVE_INFINITY);
        } else if (Double.isNaN(real) && imaginary == Double.POSITIVE_INFINITY) {
            return new Complex(Double.NaN, Double.NEGATIVE_INFINITY);
        } 
        return this.add(this.sqrt1z().multiply(I)).log().multiply(I.negate());
    }
    /**
     * Compute the
     * <a href="http://mathworld.wolfram.com/InverseSine.html" TARGET="_top">
     * inverse sine</a> of this complex number.
     * <p>
     *  {@code asin(z) = -i (log(sqrt(1 - z<sup>2</sup>) + iz))}
     * </p><p>
     * @return the inverse sine of this complex number
     */
    public Complex asin() {
        return sqrt1z().add(this.multiply(I)).log().multiply(I.negate());
    }
    /**
     * Compute the
     * <a href="http://mathworld.wolfram.com/InverseTangent.html" TARGET="_top">
     * inverse tangent</a> of this complex number.
     * Implements the formula:
     * <p>
     * {@code atan(z) = (i/2) log((i + z)/(i - z))}
     * </p><p>
     * @return the inverse tangent of this complex number
     */
    public Complex atan() {
        return this.add(I).divide(I.subtract(this)).log()
                .multiply(I.divide(createComplex(2.0, 0.0)));
    }

    /**
     * Compute the
     * <a href="http://mathworld.wolfram.com/InverseHyperbolicSine.html" TARGET="_top">
     * inverse hyperbolic sine</a> of this complex number.
     * Implements the formula:
     * <p>
     * {@code asinh(z) = log(z+sqrt(z^2+1))}
     * </p><p>
     * @return the inverse hyperbolic cosine of this complex number
     * @since 1.2
     */
    public Complex asinh(){
        if (neitherInfiniteNorZeroNorNaN(real) && imaginary == Double.POSITIVE_INFINITY) {
            return new Complex(Double.POSITIVE_INFINITY, Math.PI * 0.5);
        } else if (real == Double.POSITIVE_INFINITY && !Double.isInfinite(imaginary) && !Double.isNaN(imaginary)) {
            return new Complex(Double.POSITIVE_INFINITY, 0.0);
        } else if (real == Double.POSITIVE_INFINITY && imaginary == Double.POSITIVE_INFINITY) {
            return new Complex(Double.POSITIVE_INFINITY, Math.PI * 0.25);
        } else if (real == Double.POSITIVE_INFINITY && Double.isNaN(imaginary)) {
            return new Complex(Double.POSITIVE_INFINITY,  Double.NaN);
        } else if (Double.isNaN(real) && imaginary == 0.0) {
            return new Complex(Double.NaN, 0.0);
        } else if (Double.isNaN(real) && imaginary == Double.POSITIVE_INFINITY) {
            return new Complex(Double.POSITIVE_INFINITY, Double.NaN);
        }
        return square().add(Complex.ONE).sqrt().add(this).log();
    }

   /**
     * Compute the
     * <a href="http://mathworld.wolfram.com/InverseHyperbolicTangent.html" TARGET="_top">
     * inverse hyperbolic tangent</a> of this complex number.
     * Implements the formula:
     * <p>
     * {@code atanh(z) = log((1+z)/(1-z))/2}
     * </p><p>
     * @return the inverse hyperbolic cosine of this complex number
     * @since 1.2
     */
    public Complex atanh(){
        if (real == 0.0 && Double.isNaN(imaginary)) {
            return new Complex(0, Double.NaN);
        } else if (neitherInfiniteNorZeroNorNaN(real) && imaginary == 0.0) {
            return new Complex(Double.POSITIVE_INFINITY, 0.0);
        } else if (neitherInfiniteNorZeroNorNaN(real) && imaginary == Double.POSITIVE_INFINITY) {
            return new Complex(0, Math.PI*0.5);
        } else if (real == Double.POSITIVE_INFINITY && neitherInfiniteNorZeroNorNaN(imaginary)) {
            return new Complex(0, Math.PI*0.5);
        } else if (real == Double.POSITIVE_INFINITY && imaginary == Double.POSITIVE_INFINITY) {
            return new Complex(0, Math.PI*0.5);
        } else if (real == Double.POSITIVE_INFINITY && Double.isNaN(imaginary)) {
            return new Complex(0, Double.NaN);
        } else if (Double.isNaN(real) && imaginary == Double.POSITIVE_INFINITY) {
            return new Complex(0, Math.PI*0.5);
        }
        return this.add(Complex.ONE).divide(Complex.ONE.subtract(this)).log().divide(new Complex(2));
    }
   /**
     * Compute the
     * <a href="http://mathworld.wolfram.com/InverseHyperbolicCosine.html" TARGET="_top">
     * inverse hyperbolic cosine</a> of this complex number.
     * Implements the formula:
     * <p>
     * {@code acosh(z) = log(z+sqrt(z^2-1))}
     * </p><p>
     * @return the inverse hyperbolic cosine of this complex number
     * @since 1.2
     */
    public Complex acosh() {
        return square().subtract(Complex.ONE).sqrt().add(this).log();
    }

    /**
     * Compute the square of this complex number.
     *
     * @return square of this complex number
     */
    public Complex square(){
        return this.multiply(this);
    }

    /**
     * Compute the
     * <a href="http://mathworld.wolfram.com/Cosine.html" TARGET="_top">
     * cosine</a> of this complex number.
     * Implements the formula:
     * <p>
     *  {@code cos(a + bi) = cos(a)cosh(b) - sin(a)sinh(b)i}
     * </p><p>
     * where the (real) functions on the right-hand side are
     * {@link Math#sin}, {@link Math#cos},
     * {@link Math#cosh} and {@link Math#sinh}.
     * </p><p>
     *
     * @return the cosine of this complex number.
     */
    public Complex cos() {
        return new Complex(Math.cos(real) * Math.cosh(imaginary),
                             -Math.sin(real) * Math.sinh(imaginary));
    }

    /**
     * Compute the
     * <a href="http://mathworld.wolfram.com/HyperbolicCosine.html" TARGET="_top">
     * hyperbolic cosine</a> of this complex number.
     * Implements the formula:
     * <pre>
     *  <code>
     *   cosh(a + bi) = cosh(a)cos(b) + sinh(a)sin(b)i
     *  </code>
     * </pre>
     * where the (real) functions on the right-hand side are
     * {@link Math#sin}, {@link Math#cos},
     * {@link Math#cosh} and {@link Math#sinh}.
     * <p>
     *
     * @return the hyperbolic cosine of this complex number.
     */
    public Complex cosh() {
        if (real == 0.0&& imaginary == Double.POSITIVE_INFINITY) {
            return new Complex(Double.NaN, 0.0);
        } else if (real == 0.0&& Double.isNaN(imaginary)) {
            return new Complex(Double.NaN, 0.0);
        } else if (real == Double.POSITIVE_INFINITY && imaginary == 0.0) {
            return new Complex(Double.POSITIVE_INFINITY, 0.0);
        } else if (real == Double.POSITIVE_INFINITY && imaginary == Double.POSITIVE_INFINITY) {
            return new Complex(Double.POSITIVE_INFINITY, Double.NaN); 
        } else if (real == Double.POSITIVE_INFINITY && Double.isNaN(imaginary)) {
            return new Complex(Double.POSITIVE_INFINITY, Double.NaN);
        } else if (Double.isNaN(real) && imaginary == 0.0) {
            return new Complex(Double.NaN, 0.0);
        }

        return new Complex(Math.cosh(real) * Math.cos(imaginary),
                             Math.sinh(real) * Math.sin(imaginary));
    }

    /**
     * Compute the
     * <a href="http://mathworld.wolfram.com/ExponentialFunction.html" TARGET="_top">
     * exponential function</a> of this complex number.
     * Implements the formula:
     * <pre>
     *  <code>
     *   exp(a + bi) = exp(a)cos(b) + exp(a)sin(b)i
     *  </code>
     * </pre>
     * where the (real) functions on the right-hand side are
     * {@link Math#exp}, {@link Math#cos}, and
     * {@link Math#sin}.
     *
     * @return <code><i>e</i><sup>this</sup></code>.
     */
    public Complex exp() {
        if (real == Double.POSITIVE_INFINITY && imaginary == 0.0) {
            return new Complex(Double.POSITIVE_INFINITY, 0.0);
        } else if (real == Double.NEGATIVE_INFINITY && imaginary == Double.POSITIVE_INFINITY) {
            return Complex.ZERO;
        } else if (real == Double.POSITIVE_INFINITY && imaginary == Double.POSITIVE_INFINITY) {
            return new Complex(Double.POSITIVE_INFINITY, Double.NaN);
        } else if (real == Double.NEGATIVE_INFINITY && Double.isNaN(imaginary)) {
            return Complex.ZERO;
        } else if (real == Double.POSITIVE_INFINITY && Double.isNaN(imaginary)) {
            return new Complex(Double.POSITIVE_INFINITY, Double.NaN);
        } else if (Double.isNaN(real) && imaginary == 0.0) {
            return new Complex(Double.NaN, 0.0);
        }
        double expReal = Math.exp(real);
        return new Complex(expReal *  Math.cos(imaginary),
                             expReal * Math.sin(imaginary));
    }

    /**
     * Compute the
     * <a href="http://mathworld.wolfram.com/NaturalLogarithm.html" TARGET="_top">
     * natural logarithm</a> of this complex number.
     * Implements the formula:
     * <pre>
     *  <code>
     *   log(a + bi) = ln(|a + bi|) + arg(a + bi)i
     *  </code>
     * </pre>
     * where ln on the right hand side is {@link Math#log},
     * {@code |a + bi|} is the modulus, {@link Complex#abs},  and
     * {@code arg(a + bi) = }{@link Math#atan2}(b, a).
     *
     * @return the value <code>ln &nbsp; this</code>, the natural logarithm
     * of {@code this}.
     */
    public Complex log() {
        if (real == Double.POSITIVE_INFINITY && imaginary == Double.POSITIVE_INFINITY) {
            return new Complex(Double.POSITIVE_INFINITY, Math.PI * 0.25);
        } else if (real == Double.POSITIVE_INFINITY && Double.isNaN(imaginary)) {
            return new Complex(Double.POSITIVE_INFINITY, Double.NaN);
        } else if (Double.isNaN(real) && imaginary == Double.POSITIVE_INFINITY) {
            return new Complex(Double.POSITIVE_INFINITY, Double.NaN);
        }
        return new Complex(Math.log(abs()),
                             Math.atan2(imaginary, real));
    }

    /**
     * Compute the base 10 or
     * <a href="http://mathworld.wolfram.com/CommonLogarithm.html" TARGET="_top">
     * common logarithm</a> of this complex number.
     *
     *  @return the base 10 logarithm of <code>this</code>.
    */
    public Complex log10() {
        return new Complex(Math.log(abs())/Math.log(10),
                             Math.atan2(imaginary, real));
    }

    /**
     * Returns of value of this complex number raised to the power of {@code x}.
     * Implements the formula:
     * <pre>
     *  <code>
     *   y<sup>x</sup> = exp(x&middot;log(y))
     *  </code>
     * </pre>
     * where {@code exp} and {@code log} are {@link #exp} and
     * {@link #log}, respectively.
     *
     * @param  x exponent to which this {@code Complex} is to be raised.
     * @return <code> this<sup>x</sup></code>.
     */
    public Complex pow(Complex x) {
        checkNotNull(x);
        if (real == 0.0&& imaginary == 0.0) {
            if (x.real > 0 && x.imaginary == 0.0) {
                // 0 raised to positive number is 0
                return ZERO;
            } else {
                // 0 raised to anything else is NaN
                return NaN;
            }
        }
        return this.log().multiply(x).exp();
    }

    /**
     * Returns of value of this complex number raised to the power of {@code x}.
     *
     * @param  x exponent to which this {@code Complex} is to be raised.
     * @return <code>this<sup>x</sup></code>.
     * @see #pow(Complex)
     */
     public Complex pow(double x) {
        if (real == 0.0&& imaginary == 0.0) {
            if (x > 0) {
                // 0 raised to positive number is 0
                return ZERO;
            } else {
                // 0 raised to anything else is NaN
                return NaN;
            }
        }
        return this.log().multiply(x).exp();
    }

    /**
     * Compute the
     * <a href="http://mathworld.wolfram.com/Sine.html" TARGET="_top">
     * sine</a>
     * of this complex number.
     * Implements the formula:
     * <pre>
     *  <code>
     *   sin(a + bi) = sin(a)cosh(b) - cos(a)sinh(b)i
     *  </code>
     * </pre>
     * where the (real) functions on the right-hand side are
     * {@link Math#sin}, {@link Math#cos},
     * {@link Math#cosh} and {@link Math#sinh}.
     *
     * @return the sine of this complex number.
     */
    public Complex sin() {
        return new Complex(Math.sin(real) * Math.cosh(imaginary),
                             Math.cos(real) * Math.sinh(imaginary));
    }

    /**
     * Compute the
     * <a href="http://mathworld.wolfram.com/HyperbolicSine.html" TARGET="_top">
     * hyperbolic sine</a> of this complex number.
     * Implements the formula:
     * <pre>
     *  <code>
     *   sinh(a + bi) = sinh(a)cos(b)) + cosh(a)sin(b)i
     *  </code>
     * </pre>
     * where the (real) functions on the right-hand side are
     * {@link Math#sin}, {@link Math#cos},
     * {@link Math#cosh} and {@link Math#sinh}.
     *
     * @return the hyperbolic sine of {@code this}.
     */
    public Complex sinh() {
        if (real == 0.0&& imaginary == 0.0) {
            return Complex.ZERO;
        } else if (real == 0.0&& imaginary == Double.POSITIVE_INFINITY) {
            return new Complex(0, Double.NaN);
        } else if (real == 0.0&& Double.isNaN(imaginary)) {
            return new Complex(0, Double.NaN);
        } else if (real == Double.POSITIVE_INFINITY && imaginary == 0.0) {
            return new Complex(Double.POSITIVE_INFINITY, 0.0);
        } else if (real == Double.POSITIVE_INFINITY && imaginary == Double.POSITIVE_INFINITY) {
            return new Complex(Double.POSITIVE_INFINITY, Double.NaN);
        } else if (real == Double.POSITIVE_INFINITY && Double.isNaN(imaginary)) {
            return new Complex(Double.POSITIVE_INFINITY, Double.NaN);
        } else if (Double.isNaN(real) && imaginary == 0.0) {
            return new Complex(Double.NaN, 0.0);
        }
        return new Complex(Math.sinh(real) * Math.cos(imaginary),
            Math.cosh(real) * Math.sin(imaginary));
    }

    /**
     * Compute the
     * <a href="http://mathworld.wolfram.com/SquareRoot.html" TARGET="_top">
     * square root</a> of this complex number.
     * Implements the following algorithm to compute {@code sqrt(a + bi)}:
     * <ol><li>Let {@code t = sqrt((|a| + |a + bi|) / 2)}</li>
     * <li><pre>if {@code  a &#8805; 0} return {@code t + (b/2t)i}
     *  else return {@code |b|/2t + sign(b)t i }</pre></li>
     * </ol>
     * where <ul>
     * <li>{@code |a| = }{@link Math#abs}(a)</li>
     * <li>{@code |a + bi| = }{@link Complex#abs}(a + bi)</li>
     * <li>{@code sign(b) =  }{@link Math#copySign(double,double) copySign(1d, b)}
     * </ul>
     *
     * @return the square root of {@code this}.
     */
    public Complex sqrt() {
        if (real == 0.0 && imaginary == 0.0) {
            return new Complex(0.0, 0.0);
        } else if (neitherInfiniteNorZeroNorNaN(real) && imaginary == Double.POSITIVE_INFINITY) {
            return new Complex(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
        } else if (real == Double.NEGATIVE_INFINITY && neitherInfiniteNorZeroNorNaN(imaginary)) {
            return new Complex(0.0, Double.NaN);
        } else if (real == Double.NEGATIVE_INFINITY && Double.isNaN(imaginary)) {
            return new Complex(Double.NaN, Double.POSITIVE_INFINITY);
        } else if (real == Double.POSITIVE_INFINITY && Double.isNaN(imaginary)) {
            return new Complex(Double.POSITIVE_INFINITY, Double.NaN);
        }

        final double t = Math.sqrt((Math.abs(real) + abs()) / 2.0);
        if (real >= 0.0) {
            return new Complex(t, imaginary / (2.0 * t));
        } else {
            return new Complex(Math.abs(imaginary) / (2.0 * t),
                                 Math.copySign(1d, imaginary) * t);
        }
    }

    /**
     * Compute the
     * <a href="http://mathworld.wolfram.com/SquareRoot.html" TARGET="_top">
     * square root</a> of <code>1 - this<sup>2</sup></code> for this complex
     * number.
     * Computes the result directly as
     * {@code sqrt(ONE.subtract(z.multiply(z)))}.
     *
     * @return the square root of <code>1 - this<sup>2</sup></code>.
     */
    public Complex sqrt1z() {
        return new Complex(1.0, 0.0).subtract(this.multiply(this)).sqrt();
    }

    /**
     * Compute the
     * <a href="http://mathworld.wolfram.com/Tangent.html" TARGET="_top">
     * tangent</a> of this complex number.
     * Implements the formula:
     * <pre>
     *  <code>
     *   tan(a + bi) = sin(2a)/(cos(2a)+cosh(2b)) + [sinh(2b)/(cos(2a)+cosh(2b))]i
     *  </code>
     * </pre>
     * where the (real) functions on the right-hand side are
     * {@link Math#sin}, {@link Math#cos}, {@link Math#cosh} and
     * {@link Math#sinh}.
     *
     * @return the tangent of {@code this}.
     */
    public Complex tan() {
        if (imaginary > 20.0) {
            return new Complex(0.0, 1.0);
        }
        if (imaginary < -20.0) {
            return new Complex(0.0, -1.0);
        }

        final double real2 = 2.0 * real;
        final double imaginary2 = 2.0 * imaginary;
        final double d = Math.cos(real2) + Math.cosh(imaginary2);

        return new Complex(Math.sin(real2) / d,
                             Math.sinh(imaginary2) / d);
    }

    /**
     * Compute the
     * <a href="http://mathworld.wolfram.com/HyperbolicTangent.html" TARGET="_top">
     * hyperbolic tangent</a> of this complex number.
     * Implements the formula:
     * <pre>
     *  <code>
     *   tan(a + bi) = sinh(2a)/(cosh(2a)+cos(2b)) + [sin(2b)/(cosh(2a)+cos(2b))]i
     *  </code>
     * </pre>
     * where the (real) functions on the right-hand side are
     * {@link Math#sin}, {@link Math#cos}, {@link Math#cosh} and
     * {@link Math#sinh}.
     *
     * @return the hyperbolic tangent of {@code this}.
     */
    public Complex tanh() {
        if (real == Double.POSITIVE_INFINITY && imaginary == Double.POSITIVE_INFINITY) {
            return new Complex(1.0, 0.0);
        } else if (real == Double.POSITIVE_INFINITY && Double.isNaN(imaginary)) {
            return new Complex(1.0, 0.0);
        } else if (Double.isNaN(real) && imaginary == 0) {
            return new Complex(Double.NaN, 0); 
        }
        final double real2 = 2.0 * real;
        final double imaginary2 = 2.0 * imaginary;
        final double d = Math.cosh(real2) + Math.cos(imaginary2);

        return new Complex(Math.sinh(real2) / d,
                             Math.sin(imaginary2) / d);
    }

   /**
     * Compute the argument of this complex number.
     * The argument is the angle phi between the positive real axis and
     * the point representing this number in the complex plane.
     * The value returned is between -PI (not inclusive)
     * and PI (inclusive), with negative values returned for numbers with
     * negative imaginary parts.
     * <p>
     * If either real or imaginary part (or both) is NaN, NaN is returned.
     * Infinite parts are handled as {@code Math.atan2} handles them,
     * essentially treating finite parts as zero in the presence of an
     * infinite coordinate and returning a multiple of pi/4 depending on
     * the signs of the infinite parts.
     * See the javadoc for {@code Math.atan2} for full details.
     *
     * @return the argument of {@code this}.
     */
    public double getArgument() {
        return Math.atan2(getImaginary(), getReal());
    }

    /**
     * Compute the argument of this complex number.
     * C++11 syntax
     *
     * @return the argument of {@code this}.
     */
    public double arg() {
        return getArgument();
    }

    /**
     * Computes the n-th roots of this complex number.
     * The nth roots are defined by the formula:
     * <pre>
     *  <code>
     *   z<sub>k</sub> = abs<sup>1/n</sup> (cos(phi + 2&pi;k/n) + i (sin(phi + 2&pi;k/n))
     *  </code>
     * </pre>
     * for <i>{@code k=0, 1, ..., n-1}</i>, where {@code abs} and {@code phi}
     * are respectively the {@link #abs() modulus} and
     * {@link #getArgument() argument} of this complex number.
     * <p>
     * If one or both parts of this complex number is NaN, a list with just
     * one element, {@link #NaN} is returned.
     * if neither part is NaN, but at least one part is infinite, the result
     * is a one-element list containing {@link #INF}.
     *
     * @param n Degree of root.
     * @return a List of all {@code n}-th roots of {@code this}.
     */
    public List<Complex> nthRoot(int n) {

        if (n <= 0) {
            throw new RuntimeException("cannot compute nth root for null or negative n: {0}");
        }

        final List<Complex> result = new ArrayList<Complex>();

        // nth root of abs -- faster / more accurate to use a solver here?
        final double nthRootOfAbs = Math.pow(abs(), 1.0 / n);

        // Compute nth roots of complex number with k = 0, 1, ... n-1
        final double nthPhi = getArgument() / n;
        final double slice = 2 * Math.PI / n;
        double innerPart = nthPhi;
        for (int k = 0; k < n ; k++) {
            // inner part
            final double realPart = nthRootOfAbs *  Math.cos(innerPart);
            final double imaginaryPart = nthRootOfAbs *  Math.sin(innerPart);
            result.add(createComplex(realPart, imaginaryPart));
            innerPart += slice;
        }

        return result;
    }

    /**
     * Create a complex number given the real and imaginary parts.
     *
     * @param realPart Real part.
     * @param imaginaryPart Imaginary part.
     * @return a new complex number instance.
     * @see #valueOf(double, double)
     */
    protected Complex createComplex(double realPart,
                                    double imaginaryPart) {
        return new Complex(realPart, imaginaryPart);
    }

    /**
     * Create a complex number given the real and imaginary parts.
     *
     * @param realPart Real part.
     * @param imaginaryPart Imaginary part.
     * @return a Complex instance.
     */
    public static Complex valueOf(double realPart,
                                  double imaginaryPart) {
        return new Complex(realPart, imaginaryPart);
    }

    /**
     * Create a complex number given only the real part.
     *
     * @param realPart Real part.
     * @return a Complex instance.
     */
    public static Complex valueOf(double realPart) {
        return new Complex(realPart);
    }

    /**
     * Resolve the transient fields in a deserialized Complex Object.
     * Subclasses will need to override {@link #createComplex} to
     * deserialize properly.
     *
     * @return A Complex instance with all fields resolved.
     */
    protected final Object readResolve() {
        return new Complex(real, imaginary);
    }

    /** {@inheritDoc} */
    @Override
    public String toString() {
        return "(" + real + ", " + imaginary + ")";
    }

    /**
     * Checks that an object is not null.
     *
     * @param o Object to be checked.
     */
    private static void checkNotNull(Object o) {
        if (o == null) {
            throw new RuntimeException("Null Argument to Complex Method");
        }
    }

     /**
     * Check that the argument is positive and throw a RuntimeException
     * if it is not.
     * @param arg {@code int} to check
     */
    private static void checkNotNegative(int arg) {
        if (arg <= 0) {
            throw new RuntimeException("Complex: Non-positive argument");
        }
    }

     /**
     * Check that the argument is positive and throw a RuntimeException
     * if it is not.
     * @param arg {@code double} to check
     */
    private static void checkNotNegative(double arg) {
        if (arg <= 0) {
            throw new RuntimeException("Complex: Non-positive argument");
        }
    }
    
    /**
     * Returns {@code true} if the values are equal according to semantics of
     * {@link Double#equals(Object)}.
     *
     * @param x Value
     * @param y Value
     * @return {@code new Double(x).equals(new Double(y))}
     */
    private static boolean equals(double x, double y) {
        return new Double(x).equals(new Double(y));
    }

    private static boolean neitherInfiniteNorZeroNorNaN(double d) {
        if (!Double.isNaN(d) && !Double.isInfinite(d) && d != 0) {
            return true;
        } else return false;
    }
}
