You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by er...@apache.org on 2018/03/01 13:00:41 UTC

[1/3] commons-numbers git commit: Created static factory methods ofCis, ofPolar, ofCartesian; removal of public constructors; related fixes in ComplexUtils and RootsOfUnity

Repository: commons-numbers
Updated Branches:
  refs/heads/master e06534c83 -> 5166d4beb


Created static factory methods ofCis, ofPolar, ofCartesian; removal of
public constructors; related fixes in ComplexUtils and RootsOfUnity

Project: http://git-wip-us.apache.org/repos/asf/commons-numbers/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-numbers/commit/3c184d14
Tree: http://git-wip-us.apache.org/repos/asf/commons-numbers/tree/3c184d14
Diff: http://git-wip-us.apache.org/repos/asf/commons-numbers/diff/3c184d14

Branch: refs/heads/master
Commit: 3c184d14a9433ba18d7aa15b7b6a64921f165293
Parents: 118a2fd
Author: Eric Barnhill <er...@apache.org>
Authored: Thu Mar 1 13:56:28 2018 +0100
Committer: Eric Barnhill <er...@apache.org>
Committed: Thu Mar 1 13:56:28 2018 +0100

----------------------------------------------------------------------
 .../commons/numbers/complex/Complex.java.orig   | 1347 ++++++++++++++++++
 1 file changed, 1347 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-numbers/blob/3c184d14/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java.orig
----------------------------------------------------------------------
diff --git a/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java.orig b/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java.orig
new file mode 100644
index 0000000..3e31177
--- /dev/null
+++ b/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java.orig
@@ -0,0 +1,1347 @@
+/*
+ * 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, 1);
+    // 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);
+    /** A complex number representing "0.0 + 0.0i" */
+    public static final Complex ZERO = new Complex(0, 0);
+
+    /** Serializable version identifier */
+    private static final long serialVersionUID = 20180201L;
+
+    /** 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);
+    }
+
+     /**
+     * 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.
+     *
+     * 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}
+     */
+    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.
+<<<<<<< HEAD
+     * 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)
+     * and in handling of NaNs.
+=======
+     * 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).
+>>>>>>> 910cd934b4dab73766954ce595cc5bb2dc79e4c8
+     *
+     * @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) {
+                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() {
+        final double a = abs();
+        return a * a;
+    }
+
+    /**
+     * 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}.
+     */
+    public Complex add(Complex addend) {
+        return new Complex(real + addend.real,
+                           imaginary + addend.imaginary);
+    }
+
+    /**
+     * 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.
+     * @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}.
+     */
+    public Complex divide(Complex divisor) {
+
+        final double c = divisor.real;
+        final double d = divisor.imaginary;
+        if (c == 0 &&
+            d == 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 hash code 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));
+    }
+
+    /**
+     * @param d Value.
+     * @return a hash code for the given value.
+     */
+    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 the definitional formula:
+     *
+     *   {@code (a + bi)(c + di) = (ac - bd) + (ad + bc)i}
+     *
+     * Returns finite values in components of the result per the definitional
+     * formula in all remaining cases.
+     *
+     * @param  factor value to be multiplied by this {@code Complex}.
+     * @return {@code this * factor}.
+     */
+    public Complex multiply(Complex 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)}.
+     *
+     * @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) {
+        return new Complex(real - subtrahend.real,
+                           imaginary - subtrahend.imaginary);
+    }
+
+    /**
+     * 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">
+     * 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 &&
+            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 add(sqrt1z().multiply(I)).log().multiply(I.negate());
+    }
+    /**
+     * Compute the
+     * <a href="http://mathworld.wolfram.com/InverseSine.html">
+     * 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(multiply(I)).log().multiply(I.negate());
+    }
+    /**
+     * Compute the
+     * <a href="http://mathworld.wolfram.com/InverseTangent.html">
+     * 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 add(I).divide(I.subtract(this)).log().multiply(I.multiply(0.5));
+    }
+
+    /**
+     * Compute the
+     * <a href="http://mathworld.wolfram.com/InverseHyperbolicSine.html">
+     * 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
+     */
+    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);
+        } 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) {
+            return new Complex(Double.NaN, 0);
+        } else if (Double.isNaN(real) &&
+                   imaginary == Double.POSITIVE_INFINITY) {
+            return new Complex(Double.POSITIVE_INFINITY, Double.NaN);
+        }
+        return square().add(ONE).sqrt().add(this).log();
+    }
+
+   /**
+     * Compute the
+     * <a href="http://mathworld.wolfram.com/InverseHyperbolicTangent.html">
+     * 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
+     */
+    public Complex atanh(){
+        if (real == 0 &&
+            Double.isNaN(imaginary)) {
+            return new Complex(0, Double.NaN);
+        } else if (neitherInfiniteNorZeroNorNaN(real) &&
+                   imaginary == 0) {
+            return new Complex(Double.POSITIVE_INFINITY, 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 add(ONE).divide(ONE.subtract(this)).log().multiply(0.5);
+    }
+   /**
+     * Compute the
+     * <a href="http://mathworld.wolfram.com/InverseHyperbolicCosine.html">
+     * 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
+     */
+    public Complex acosh() {
+        return square().subtract(ONE).sqrt().add(this).log();
+    }
+
+    /**
+     * Compute the square of this complex number.
+     *
+     * @return square of this complex number
+     */
+    public Complex square() {
+        return multiply(this);
+    }
+
+    /**
+     * Compute the
+     * <a href="http://mathworld.wolfram.com/Cosine.html">
+     * 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">
+     * 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 &&
+            imaginary == Double.POSITIVE_INFINITY) {
+            return new Complex(Double.NaN, 0);
+        } else if (real == 0 &&
+                   Double.isNaN(imaginary)) {
+            return new Complex(Double.NaN, 0);
+        } else if (real == Double.POSITIVE_INFINITY &&
+                   imaginary == 0) {
+            return new Complex(Double.POSITIVE_INFINITY, 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) {
+            return new Complex(Double.NaN, 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">
+     * 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) {
+            return new Complex(Double.POSITIVE_INFINITY, 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) {
+            return new Complex(Double.NaN, 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">
+     * 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">
+     * 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) {
+        if (real == 0 &&
+            imaginary == 0) {
+            if (x.real > 0 &&
+                x.imaginary == 0) {
+                // 0 raised to positive number is 0
+                return ZERO;
+            } else {
+                // 0 raised to anything else is NaN
+                return NAN;
+            }
+        }
+        return 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 &&
+            imaginary == 0) {
+            if (x > 0) {
+                // 0 raised to positive number is 0
+                return ZERO;
+            } else {
+                // 0 raised to anything else is NaN
+                return NAN;
+            }
+        }
+        return log().multiply(x).exp();
+    }
+
+    /**
+     * Compute the
+     * <a href="http://mathworld.wolfram.com/Sine.html">
+     * 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">
+     * 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 &&
+            imaginary == 0) {
+            return Complex.ZERO;
+        } else if (real == 0 &&
+                   imaginary == Double.POSITIVE_INFINITY) {
+            return new Complex(0, Double.NaN);
+        } else if (real == 0 &&
+                   Double.isNaN(imaginary)) {
+            return new Complex(0, Double.NaN);
+        } else if (real == Double.POSITIVE_INFINITY &&
+                   imaginary == 0) {
+            return new Complex(Double.POSITIVE_INFINITY, 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) {
+            return new Complex(Double.NaN, 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">
+     * 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 &&
+            imaginary == 0) {
+            return ZERO;
+        } 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, 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(0.5 * (Math.abs(real) + abs()));
+        if (real >= 0) {
+            return new Complex(t, 0.5 * imaginary / t);
+        } else {
+            return new Complex(0.5 * Math.abs(imaginary) / t,
+                               Math.copySign(1d, imaginary) * t);
+        }
+    }
+
+    /**
+     * Compute the
+     * <a href="http://mathworld.wolfram.com/SquareRoot.html">
+     * 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 ONE.subtract(square()).sqrt();
+    }
+
+    /**
+     * Compute the
+     * <a href="http://mathworld.wolfram.com/Tangent.html">
+     * 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) {
+            return ONE;
+        }
+        if (imaginary < -20) {
+            return new Complex(0, -1);
+        }
+
+        final double real2 = 2 * real;
+        final double imaginary2 = 2 * 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">
+     * 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 ONE;
+        } else if (real == Double.POSITIVE_INFINITY &&
+                   Double.isNaN(imaginary)) {
+            return ONE;
+        } else if (Double.isNaN(real) &&
+                   imaginary == 0) {
+            return new Complex(Double.NaN, 0);
+        }
+        final double real2 = 2 * real;
+        final double imaginary2 = 2 * 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(imaginary, real);
+    }
+
+    /**
+     * 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 IllegalArgumentException("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(), 1d / 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 + ")";
+    }
+
+    /**
+     * 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 IllegalArgumentException("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));
+    }
+
+    /**
+     * Check that a value meets all the following conditions:
+     * <ul>
+     *  <li>it is not {@code NaN},</li>
+     *  <li>it is not infinite,</li>
+     *  <li>it is not zero,</li>
+     * </ul>
+     *
+     * @param d Value.
+     * @return {@code true} if {@code d} meets all the conditions and
+     * {@code false} otherwise.
+     */
+    private static boolean neitherInfiniteNorZeroNorNaN(double d) {
+        return !Double.isNaN(d) &&
+            !Double.isInfinite(d) &&
+            d != 0;
+    }
+}


[2/3] commons-numbers git commit: Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/commons-numbers

Posted by er...@apache.org.
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/commons-numbers


Project: http://git-wip-us.apache.org/repos/asf/commons-numbers/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-numbers/commit/abec5ad8
Tree: http://git-wip-us.apache.org/repos/asf/commons-numbers/tree/abec5ad8
Diff: http://git-wip-us.apache.org/repos/asf/commons-numbers/diff/abec5ad8

Branch: refs/heads/master
Commit: abec5ad87eeb1c4b176305348d601aff41db7572
Parents: 3c184d1 e06534c
Author: Eric Barnhill <er...@apache.org>
Authored: Thu Mar 1 14:01:08 2018 +0100
Committer: Eric Barnhill <er...@apache.org>
Committed: Thu Mar 1 14:01:08 2018 +0100

----------------------------------------------------------------------
 .../apache/commons/numbers/complex/Complex.java | 21 +++----
 .../commons/numbers/complex/CStandardTest.java  | 61 ++++++++++----------
 .../commons/numbers/complex/ComplexTest.java    | 24 ++++----
 .../numbers/complex/ComplexUtilsTest.java       | 33 ++++++-----
 4 files changed, 69 insertions(+), 70 deletions(-)
----------------------------------------------------------------------



[3/3] commons-numbers git commit: merge of complex-constructor branch

Posted by er...@apache.org.
merge of complex-constructor branch


Project: http://git-wip-us.apache.org/repos/asf/commons-numbers/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-numbers/commit/5166d4be
Tree: http://git-wip-us.apache.org/repos/asf/commons-numbers/tree/5166d4be
Diff: http://git-wip-us.apache.org/repos/asf/commons-numbers/diff/5166d4be

Branch: refs/heads/master
Commit: 5166d4beb42c1a71314312197d247ede015c2050
Parents: abec5ad
Author: Eric Barnhill <er...@apache.org>
Authored: Thu Mar 1 14:01:48 2018 +0100
Committer: Eric Barnhill <er...@apache.org>
Committed: Thu Mar 1 14:01:48 2018 +0100

----------------------------------------------------------------------
 .../apache/commons/numbers/complex/Complex.java | 77 ++++++--------------
 .../commons/numbers/complex/ComplexUtils.java   | 62 ++++++++--------
 .../commons/numbers/complex/RootsOfUnity.java   |  6 +-
 3 files changed, 57 insertions(+), 88 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-numbers/blob/5166d4be/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java
----------------------------------------------------------------------
diff --git a/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java b/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java
index cfc9625..c36bea1 100644
--- a/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java
+++ b/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java
@@ -63,24 +63,28 @@ public class Complex implements Serializable  {
     /** The real part. */
     private final double real;
 
+    private Complex(double real, double imaginary) {
+        this.real = real;
+        this.imaginary = imaginary;
+    }
+
     /**
-     * Create a complex number given only the real part.
-     *
-     * @param real Real part.
-     */
-    public Complex(double real) {
-        this(real, 0);
+    * Create a complex number given the real and imaginary parts.
+    *
+    * @param real Real part.
+    * @param imaginary Imaginary part.
+    */
+    public static Complex ofCartesian(double real, double imaginary) {
+    	return new Complex(real, imaginary);
     }
 
-     /**
-     * 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;
+    /**
+    * Create a complex number given the real part.
+    *
+    * @param real Real part.
+    */
+    public static Complex ofCartesian(double real) {
+    	return new Complex(real, 0);
     }
 
      /**
@@ -103,7 +107,7 @@ public class Complex implements Serializable  {
      * @param theta the argument of the complex number to create
      * @return {@code Complex}
      */
-    public Complex polar(double r, double theta) {
+    public static Complex ofPolar(double r, double theta) {
         checkNotNegative(r);
         return new Complex(r * Math.cos(theta), r * Math.sin(theta));
     }
@@ -115,7 +119,7 @@ public class Complex implements Serializable  {
      * @param x {@code double} to build the cis number
      * @return {@code Complex}
      */
-    public Complex cis(double x) {
+    public static Complex ofCis(double x) {
         return new Complex(Math.cos(x), Math.sin(x));
     }
 
@@ -163,7 +167,7 @@ public class Complex implements Serializable  {
     public Complex proj() {
         if (Double.isInfinite(real) ||
             Double.isInfinite(imaginary)) {
-            return new Complex(Double.POSITIVE_INFINITY);
+            return new Complex(Double.POSITIVE_INFINITY, 0);
         } else {
             return this;
         }
@@ -1233,7 +1237,7 @@ public class Complex implements Serializable  {
             // inner part
             final double realPart = nthRootOfAbs *  Math.cos(innerPart);
             final double imaginaryPart = nthRootOfAbs *  Math.sin(innerPart);
-            result.add(createComplex(realPart, imaginaryPart));
+            result.add(new Complex(realPart, imaginaryPart));
             innerPart += slice;
         }
 
@@ -1241,41 +1245,6 @@ public class Complex implements Serializable  {
     }
 
     /**
-     * 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.

http://git-wip-us.apache.org/repos/asf/commons-numbers/blob/5166d4be/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexUtils.java
----------------------------------------------------------------------
diff --git a/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexUtils.java b/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexUtils.java
index b9f758a..684d406 100644
--- a/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexUtils.java
+++ b/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexUtils.java
@@ -55,7 +55,7 @@ public class ComplexUtils {
         if (r < 0) {
             throw new NegativeModulusException(r);
         }
-        return new Complex(r * Math.cos(theta), r * Math.sin(theta));
+        return Complex.ofCartesian(r * Math.cos(theta), r * Math.sin(theta));
     }
 
     /**
@@ -74,7 +74,7 @@ public class ComplexUtils {
             if (r[x] < 0) {
                 throw new NegativeModulusException(r[x]);
             }
-            c[x] = new Complex(r[x] * Math.cos(theta[x]), r[x] * Math.sin(theta[x]));
+            c[x] = Complex.ofCartesian(r[x] * Math.cos(theta[x]), r[x] * Math.sin(theta[x]));
         }
         return c;
     }
@@ -126,7 +126,7 @@ public class ComplexUtils {
      * @since 1.0
      */
     public static Complex extractComplexFromRealArray(double[] real, int index) {
-        return new Complex(real[index]);
+        return Complex.ofCartesian(real[index]);
     }
 
     /**
@@ -140,7 +140,7 @@ public class ComplexUtils {
      * @since 1.0
      */
     public static Complex extractComplexFromRealArray(float[] real, int index) {
-        return new Complex(real[index]);
+        return Complex.ofCartesian(real[index]);
     }
 
     /**
@@ -154,7 +154,7 @@ public class ComplexUtils {
      * @since 1.0
      */
     public static Complex extractComplexFromImaginaryArray(double[] imaginary, int index) {
-        return new Complex(0, imaginary[index]);
+        return Complex.ofCartesian(0, imaginary[index]);
     }
 
     /**
@@ -168,7 +168,7 @@ public class ComplexUtils {
      * @since 1.0
      */
     public static Complex extractComplexFromImaginaryArray(float[] imaginary, int index) {
-        return new Complex(0, imaginary[index]);
+        return Complex.ofCartesian(0, imaginary[index]);
     }
 
     /**
@@ -232,13 +232,13 @@ public class ComplexUtils {
      * {@code index}.
      *
      * @param d array of interleaved complex numbers alternating real and imaginary values
-     * @param index location in the array This is the location by complex number, e.g. index number 5 in the array will return {@code new Complex(d[10], d[11])}
+     * @param index location in the array This is the location by complex number, e.g. index number 5 in the array will return {@code Complex.ofCartesian(d[10], d[11])}
      * @return {@code Complex}.
      *
      * @since 1.0
      */
     public static Complex extractComplexFromInterleavedArray(double[] d, int index) {
-        return new Complex(d[index * 2], d[index * 2 + 1]);
+        return Complex.ofCartesian(d[index * 2], d[index * 2 + 1]);
     }
 
     /**
@@ -252,7 +252,7 @@ public class ComplexUtils {
      * @since 1.0
      */
     public static Complex extractComplexFromInterleavedArray(float[] f, int index) {
-        return new Complex(f[index * 2], f[index * 2 + 1]);
+        return Complex.ofCartesian(f[index * 2], f[index * 2 + 1]);
     }
 
     /**
@@ -295,7 +295,7 @@ public class ComplexUtils {
         int index = 0;
         final Complex c[] = new Complex[real.length];
         for (double d : real) {
-            c[index] = new Complex(d);
+            c[index] = Complex.ofCartesian(d);
             index++;
         }
         return c;
@@ -313,7 +313,7 @@ public class ComplexUtils {
         int index = 0;
         final Complex c[] = new Complex[real.length];
         for (float d : real) {
-            c[index] = new Complex(d);
+            c[index] = Complex.ofCartesian(d);
             index++;
         }
         return c;
@@ -564,7 +564,7 @@ public class ComplexUtils {
         int index = 0;
         final Complex c[] = new Complex[imaginary.length];
         for (double d : imaginary) {
-            c[index] = new Complex(0, d);
+            c[index] = Complex.ofCartesian(0, d);
             index++;
         }
         return c;
@@ -582,7 +582,7 @@ public class ComplexUtils {
         int index = 0;
         final Complex c[] = new Complex[imaginary.length];
         for (float d : imaginary) {
-            c[index] = new Complex(0, d);
+            c[index] = Complex.ofCartesian(0, d);
             index++;
         }
         return c;
@@ -799,7 +799,7 @@ public class ComplexUtils {
         final int length = interleaved.length / 2;
         final Complex c[] = new Complex[length];
         for (int n = 0; n < length; n++) {
-            c[n] = new Complex(interleaved[n * 2], interleaved[n * 2 + 1]);
+            c[n] = Complex.ofCartesian(interleaved[n * 2], interleaved[n * 2 + 1]);
         }
         return c;
     }
@@ -817,7 +817,7 @@ public class ComplexUtils {
         final int length = interleaved.length / 2;
         final Complex c[] = new Complex[length];
         for (int n = 0; n < length; n++) {
-            c[n] = new Complex(interleaved[n * 2], interleaved[n * 2 + 1]);
+            c[n] = Complex.ofCartesian(interleaved[n * 2], interleaved[n * 2 + 1]);
         }
         return c;
     }
@@ -1220,14 +1220,14 @@ public class ComplexUtils {
             c = new Complex[w / 2][h];
             for (int x = 0; x < w / 2; x++) {
                 for (int y = 0; y < h; y++) {
-                    c[x][y] = new Complex(i[x * 2][y], i[x * 2 + 1][y]);
+                    c[x][y] = Complex.ofCartesian(i[x * 2][y], i[x * 2 + 1][y]);
                 }
             }
         } else {
             c = new Complex[w][h / 2];
             for (int x = 0; x < w; x++) {
                 for (int y = 0; y < h / 2; y++) {
-                    c[x][y] = new Complex(i[x][y * 2], i[x][y * 2 + 1]);
+                    c[x][y] = Complex.ofCartesian(i[x][y * 2], i[x][y * 2 + 1]);
                 }
             }
         }
@@ -1271,7 +1271,7 @@ public class ComplexUtils {
             for (int x = 0; x < w / 2; x++) {
                 for (int y = 0; y < h; y++) {
                     for (int z = 0; z < d; z++) {
-                        c[x][y][z] = new Complex(i[x * 2][y][z], i[x * 2 + 1][y][z]);
+                        c[x][y][z] = Complex.ofCartesian(i[x * 2][y][z], i[x * 2 + 1][y][z]);
                     }
                 }
             }
@@ -1280,7 +1280,7 @@ public class ComplexUtils {
             for (int x = 0; x < w; x++) {
                 for (int y = 0; y < h / 2; y++) {
                     for (int z = 0; z < d; z++) {
-                        c[x][y][z] = new Complex(i[x][y * 2][z], i[x][y * 2 + 1][z]);
+                        c[x][y][z] = Complex.ofCartesian(i[x][y * 2][z], i[x][y * 2 + 1][z]);
                     }
                 }
             }
@@ -1289,7 +1289,7 @@ public class ComplexUtils {
             for (int x = 0; x < w; x++) {
                 for (int y = 0; y < h; y++) {
                     for (int z = 0; z < d / 2; z++) {
-                        c[x][y][z] = new Complex(i[x][y][z * 2], i[x][y][z * 2 + 1]);
+                        c[x][y][z] = Complex.ofCartesian(i[x][y][z * 2], i[x][y][z * 2 + 1]);
                     }
                 }
             }
@@ -1322,7 +1322,7 @@ public class ComplexUtils {
                 for (int y = 0; y < h; y++) {
                     for (int z = 0; z < d; z++) {
                         for (int t = 0; t < v; t++) {
-                            c[x][y][z][t] = new Complex(i[x * 2][y][z][t], i[x * 2 + 1][y][z][t]);
+                            c[x][y][z][t] = Complex.ofCartesian(i[x * 2][y][z][t], i[x * 2 + 1][y][z][t]);
                         }
                     }
                 }
@@ -1333,7 +1333,7 @@ public class ComplexUtils {
                 for (int y = 0; y < h / 2; y++) {
                     for (int z = 0; z < d; z++) {
                         for (int t = 0; t < v; t++) {
-                            c[x][y][z][t] = new Complex(i[x][y * 2][z][t], i[x][y * 2 + 1][z][t]);
+                            c[x][y][z][t] = Complex.ofCartesian(i[x][y * 2][z][t], i[x][y * 2 + 1][z][t]);
                         }
                     }
                 }
@@ -1344,7 +1344,7 @@ public class ComplexUtils {
                 for (int y = 0; y < h; y++) {
                     for (int z = 0; z < d / 2; z++) {
                         for (int t = 0; t < v; t++) {
-                            c[x][y][z][t] = new Complex(i[x][y][z * 2][t], i[x][y][z * 2 + 1][t]);
+                            c[x][y][z][t] = Complex.ofCartesian(i[x][y][z * 2][t], i[x][y][z * 2 + 1][t]);
                         }
                     }
                 }
@@ -1355,7 +1355,7 @@ public class ComplexUtils {
                 for (int y = 0; y < h; y++) {
                     for (int z = 0; z < d; z++) {
                         for (int t = 0; t < v / 2; t++) {
-                            c[x][y][z][t] = new Complex(i[x][y][z][t * 2], i[x][y][z][t * 2 + 1]);
+                            c[x][y][z][t] = Complex.ofCartesian(i[x][y][z][t * 2], i[x][y][z][t * 2 + 1]);
                         }
                     }
                 }
@@ -1399,14 +1399,14 @@ public class ComplexUtils {
             c = new Complex[w / 2][h];
             for (int x = 0; x < w / 2; x++) {
                 for (int y = 0; y < h; y++) {
-                    c[x][y] = new Complex(i[x * 2][y], i[x * 2 + 1][y]);
+                    c[x][y] = Complex.ofCartesian(i[x * 2][y], i[x * 2 + 1][y]);
                 }
             }
         } else {
             c = new Complex[w][h / 2];
             for (int x = 0; x < w; x++) {
                 for (int y = 0; y < h / 2; y++) {
-                    c[x][y] = new Complex(i[x][y * 2], i[x][y * 2 + 1]);
+                    c[x][y] = Complex.ofCartesian(i[x][y * 2], i[x][y * 2 + 1]);
                 }
             }
         }
@@ -1450,7 +1450,7 @@ public class ComplexUtils {
             for (int x = 0; x < w/2; x ++) {
                 for (int y = 0; y < h; y++) {
                     for (int z = 0; z < d; z++) {
-                        c[x][y][z] = new Complex(i[x * 2][y][z], i[x * 2 + 1][y][z]);
+                        c[x][y][z] = Complex.ofCartesian(i[x * 2][y][z], i[x * 2 + 1][y][z]);
                     }
                 }
             }
@@ -1459,7 +1459,7 @@ public class ComplexUtils {
             for (int x = 0; x < w; x++) {
                 for (int y = 0; y < h/2; y ++) {
                     for (int z = 0; z < d; z++) {
-                        c[x][y][z] = new Complex(i[x][y * 2][z], i[x][y * 2 + 1][z]);
+                        c[x][y][z] = Complex.ofCartesian(i[x][y * 2][z], i[x][y * 2 + 1][z]);
                     }
                 }
             }
@@ -1468,7 +1468,7 @@ public class ComplexUtils {
             for (int x = 0; x < w; x++) {
                 for (int y = 0; y < h; y++) {
                     for (int z = 0; z < d/2; z++) {
-                        c[x][y][z] = new Complex(i[x][y][z * 2], i[x][y][z * 2 + 1]);
+                        c[x][y][z] = Complex.ofCartesian(i[x][y][z * 2], i[x][y][z * 2 + 1]);
                     }
                 }
             }
@@ -1506,7 +1506,7 @@ public class ComplexUtils {
         final int length = real.length;
         final Complex[] c = new Complex[length];
         for (int n = 0; n < length; n++) {
-            c[n] = new Complex(real[n], imag[n]);
+            c[n] = Complex.ofCartesian(real[n], imag[n]);
         }
         return c;
     }
@@ -1582,7 +1582,7 @@ public class ComplexUtils {
         final int length = real.length;
         final Complex[] c = new Complex[length];
         for (int n = 0; n < length; n++) {
-            c[n] = new Complex(real[n], imag[n]);
+            c[n] = Complex.ofCartesian(real[n], imag[n]);
         }
         return c;
     }

http://git-wip-us.apache.org/repos/asf/commons-numbers/blob/5166d4be/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/RootsOfUnity.java
----------------------------------------------------------------------
diff --git a/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/RootsOfUnity.java b/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/RootsOfUnity.java
index 89bf8d3..c3035ce 100644
--- a/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/RootsOfUnity.java
+++ b/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/RootsOfUnity.java
@@ -65,14 +65,14 @@ public class RootsOfUnity {
 
         double previousReal = 1;
         double previousImag = 0;
-        omega[0] = new Complex(previousReal, previousImag);
+        omega[0] = Complex.ofCartesian(previousReal, previousImag);
         for (int i = 1; i < omegaCount; i++) {
             final double real = previousReal * cosT - previousImag * sinT;
             final double imag = previousReal * sinT + previousImag * cosT;
 
             omega[i] = isCounterClockwise ?
-                new Complex(real, imag) :
-                new Complex(real, -imag);
+        		Complex.ofCartesian(real, imag) :
+    			Complex.ofCartesian(real, -imag);
 
             previousReal = real;
             previousImag = imag;