Home | History | Annotate | Download | only in complex
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one or more
      3  * contributor license agreements.  See the NOTICE file distributed with
      4  * this work for additional information regarding copyright ownership.
      5  * The ASF licenses this file to You under the Apache License, Version 2.0
      6  * (the "License"); you may not use this file except in compliance with
      7  * the License.  You may obtain a copy of the License at
      8  *
      9  *      http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 package org.apache.commons.math.complex;
     19 
     20 import java.io.Serializable;
     21 import java.util.ArrayList;
     22 import java.util.List;
     23 
     24 import org.apache.commons.math.FieldElement;
     25 import org.apache.commons.math.MathRuntimeException;
     26 import org.apache.commons.math.exception.util.LocalizedFormats;
     27 import org.apache.commons.math.util.MathUtils;
     28 import org.apache.commons.math.util.FastMath;
     29 
     30 /**
     31  * Representation of a Complex number - a number which has both a
     32  * real and imaginary part.
     33  * <p>
     34  * Implementations of arithmetic operations handle <code>NaN</code> and
     35  * infinite values according to the rules for {@link java.lang.Double}
     36  * arithmetic, applying definitional formulas and returning <code>NaN</code> or
     37  * infinite values in real or imaginary parts as these arise in computation.
     38  * See individual method javadocs for details.</p>
     39  * <p>
     40  * {@link #equals} identifies all values with <code>NaN</code> in either real
     41  * or imaginary part - e.g., <pre>
     42  * <code>1 + NaNi  == NaN + i == NaN + NaNi.</code></pre></p>
     43  *
     44  * implements Serializable since 2.0
     45  *
     46  * @version $Revision: 990655 $ $Date: 2010-08-29 23:49:40 +0200 (dim. 29 aot 2010) $
     47  */
     48 public class Complex implements FieldElement<Complex>, Serializable  {
     49 
     50     /** The square root of -1. A number representing "0.0 + 1.0i" */
     51     public static final Complex I = new Complex(0.0, 1.0);
     52 
     53     // CHECKSTYLE: stop ConstantName
     54     /** A complex number representing "NaN + NaNi" */
     55     public static final Complex NaN = new Complex(Double.NaN, Double.NaN);
     56     // CHECKSTYLE: resume ConstantName
     57 
     58     /** A complex number representing "+INF + INFi" */
     59     public static final Complex INF = new Complex(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
     60 
     61     /** A complex number representing "1.0 + 0.0i" */
     62     public static final Complex ONE = new Complex(1.0, 0.0);
     63 
     64     /** A complex number representing "0.0 + 0.0i" */
     65     public static final Complex ZERO = new Complex(0.0, 0.0);
     66 
     67     /** Serializable version identifier */
     68     private static final long serialVersionUID = -6195664516687396620L;
     69 
     70     /** The imaginary part. */
     71     private final double imaginary;
     72 
     73     /** The real part. */
     74     private final double real;
     75 
     76     /** Record whether this complex number is equal to NaN. */
     77     private final transient boolean isNaN;
     78 
     79     /** Record whether this complex number is infinite. */
     80     private final transient boolean isInfinite;
     81 
     82     /**
     83      * Create a complex number given the real and imaginary parts.
     84      *
     85      * @param real the real part
     86      * @param imaginary the imaginary part
     87      */
     88     public Complex(double real, double imaginary) {
     89         super();
     90         this.real = real;
     91         this.imaginary = imaginary;
     92 
     93         isNaN = Double.isNaN(real) || Double.isNaN(imaginary);
     94         isInfinite = !isNaN &&
     95         (Double.isInfinite(real) || Double.isInfinite(imaginary));
     96     }
     97 
     98     /**
     99      * Return the absolute value of this complex number.
    100      * <p>
    101      * Returns <code>NaN</code> if either real or imaginary part is
    102      * <code>NaN</code> and <code>Double.POSITIVE_INFINITY</code> if
    103      * neither part is <code>NaN</code>, but at least one part takes an infinite
    104      * value.</p>
    105      *
    106      * @return the absolute value
    107      */
    108     public double abs() {
    109         if (isNaN()) {
    110             return Double.NaN;
    111         }
    112 
    113         if (isInfinite()) {
    114             return Double.POSITIVE_INFINITY;
    115         }
    116 
    117         if (FastMath.abs(real) < FastMath.abs(imaginary)) {
    118             if (imaginary == 0.0) {
    119                 return FastMath.abs(real);
    120             }
    121             double q = real / imaginary;
    122             return FastMath.abs(imaginary) * FastMath.sqrt(1 + q * q);
    123         } else {
    124             if (real == 0.0) {
    125                 return FastMath.abs(imaginary);
    126             }
    127             double q = imaginary / real;
    128             return FastMath.abs(real) * FastMath.sqrt(1 + q * q);
    129         }
    130     }
    131 
    132     /**
    133      * Return the sum of this complex number and the given complex number.
    134      * <p>
    135      * Uses the definitional formula
    136      * <pre>
    137      * (a + bi) + (c + di) = (a+c) + (b+d)i
    138      * </pre></p>
    139      * <p>
    140      * If either this or <code>rhs</code> has a NaN value in either part,
    141      * {@link #NaN} is returned; otherwise Inifinite and NaN values are
    142      * returned in the parts of the result according to the rules for
    143      * {@link java.lang.Double} arithmetic.</p>
    144      *
    145      * @param rhs the other complex number
    146      * @return the complex number sum
    147      * @throws NullPointerException if <code>rhs</code> is null
    148      */
    149     public Complex add(Complex rhs) {
    150         return createComplex(real + rhs.getReal(),
    151             imaginary + rhs.getImaginary());
    152     }
    153 
    154     /**
    155      * Return the conjugate of this complex number. The conjugate of
    156      * "A + Bi" is "A - Bi".
    157      * <p>
    158      * {@link #NaN} is returned if either the real or imaginary
    159      * part of this Complex number equals <code>Double.NaN</code>.</p>
    160      * <p>
    161      * If the imaginary part is infinite, and the real part is not NaN,
    162      * the returned value has infinite imaginary part of the opposite
    163      * sign - e.g. the conjugate of <code>1 + POSITIVE_INFINITY i</code>
    164      * is <code>1 - NEGATIVE_INFINITY i</code></p>
    165      *
    166      * @return the conjugate of this Complex object
    167      */
    168     public Complex conjugate() {
    169         if (isNaN()) {
    170             return NaN;
    171         }
    172         return createComplex(real, -imaginary);
    173     }
    174 
    175     /**
    176      * Return the quotient of this complex number and the given complex number.
    177      * <p>
    178      * Implements the definitional formula
    179      * <pre><code>
    180      *    a + bi          ac + bd + (bc - ad)i
    181      *    ----------- = -------------------------
    182      *    c + di         c<sup>2</sup> + d<sup>2</sup>
    183      * </code></pre>
    184      * but uses
    185      * <a href="http://doi.acm.org/10.1145/1039813.1039814">
    186      * prescaling of operands</a> to limit the effects of overflows and
    187      * underflows in the computation.</p>
    188      * <p>
    189      * Infinite and NaN values are handled / returned according to the
    190      * following rules, applied in the order presented:
    191      * <ul>
    192      * <li>If either this or <code>rhs</code> has a NaN value in either part,
    193      *  {@link #NaN} is returned.</li>
    194      * <li>If <code>rhs</code> equals {@link #ZERO}, {@link #NaN} is returned.
    195      * </li>
    196      * <li>If this and <code>rhs</code> are both infinite,
    197      * {@link #NaN} is returned.</li>
    198      * <li>If this is finite (i.e., has no infinite or NaN parts) and
    199      *  <code>rhs</code> is infinite (one or both parts infinite),
    200      * {@link #ZERO} is returned.</li>
    201      * <li>If this is infinite and <code>rhs</code> is finite, NaN values are
    202      * returned in the parts of the result if the {@link java.lang.Double}
    203      * rules applied to the definitional formula force NaN results.</li>
    204      * </ul></p>
    205      *
    206      * @param rhs the other complex number
    207      * @return the complex number quotient
    208      * @throws NullPointerException if <code>rhs</code> is null
    209      */
    210     public Complex divide(Complex rhs) {
    211         if (isNaN() || rhs.isNaN()) {
    212             return NaN;
    213         }
    214 
    215         double c = rhs.getReal();
    216         double d = rhs.getImaginary();
    217         if (c == 0.0 && d == 0.0) {
    218             return NaN;
    219         }
    220 
    221         if (rhs.isInfinite() && !isInfinite()) {
    222             return ZERO;
    223         }
    224 
    225         if (FastMath.abs(c) < FastMath.abs(d)) {
    226             double q = c / d;
    227             double denominator = c * q + d;
    228             return createComplex((real * q + imaginary) / denominator,
    229                 (imaginary * q - real) / denominator);
    230         } else {
    231             double q = d / c;
    232             double denominator = d * q + c;
    233             return createComplex((imaginary * q + real) / denominator,
    234                 (imaginary - real * q) / denominator);
    235         }
    236     }
    237 
    238     /**
    239      * Test for the equality of two Complex objects.
    240      * <p>
    241      * If both the real and imaginary parts of two Complex numbers
    242      * are exactly the same, and neither is <code>Double.NaN</code>, the two
    243      * Complex objects are considered to be equal.</p>
    244      * <p>
    245      * All <code>NaN</code> values are considered to be equal - i.e, if either
    246      * (or both) real and imaginary parts of the complex number are equal
    247      * to <code>Double.NaN</code>, the complex number is equal to
    248      * <code>Complex.NaN</code>.</p>
    249      *
    250      * @param other Object to test for equality to this
    251      * @return true if two Complex objects are equal, false if
    252      *         object is null, not an instance of Complex, or
    253      *         not equal to this Complex instance
    254      *
    255      */
    256     @Override
    257     public boolean equals(Object other) {
    258         if (this == other) {
    259             return true;
    260         }
    261         if (other instanceof Complex){
    262             Complex rhs = (Complex)other;
    263             if (rhs.isNaN()) {
    264                 return this.isNaN();
    265             } else {
    266                 return (real == rhs.real) && (imaginary == rhs.imaginary);
    267             }
    268         }
    269         return false;
    270     }
    271 
    272     /**
    273      * Get a hashCode for the complex number.
    274      * <p>
    275      * All NaN values have the same hash code.</p>
    276      *
    277      * @return a hash code value for this object
    278      */
    279     @Override
    280     public int hashCode() {
    281         if (isNaN()) {
    282             return 7;
    283         }
    284         return 37 * (17 * MathUtils.hash(imaginary) +
    285             MathUtils.hash(real));
    286     }
    287 
    288     /**
    289      * Access the imaginary part.
    290      *
    291      * @return the imaginary part
    292      */
    293     public double getImaginary() {
    294         return imaginary;
    295     }
    296 
    297     /**
    298      * Access the real part.
    299      *
    300      * @return the real part
    301      */
    302     public double getReal() {
    303         return real;
    304     }
    305 
    306     /**
    307      * Returns true if either or both parts of this complex number is NaN;
    308      * false otherwise
    309      *
    310      * @return  true if either or both parts of this complex number is NaN;
    311      * false otherwise
    312      */
    313     public boolean isNaN() {
    314         return isNaN;
    315     }
    316 
    317     /**
    318      * Returns true if either the real or imaginary part of this complex number
    319      * takes an infinite value (either <code>Double.POSITIVE_INFINITY</code> or
    320      * <code>Double.NEGATIVE_INFINITY</code>) and neither part
    321      * is <code>NaN</code>.
    322      *
    323      * @return true if one or both parts of this complex number are infinite
    324      * and neither part is <code>NaN</code>
    325      */
    326     public boolean isInfinite() {
    327         return isInfinite;
    328     }
    329 
    330     /**
    331      * Return the product of this complex number and the given complex number.
    332      * <p>
    333      * Implements preliminary checks for NaN and infinity followed by
    334      * the definitional formula:
    335      * <pre><code>
    336      * (a + bi)(c + di) = (ac - bd) + (ad + bc)i
    337      * </code></pre>
    338      * </p>
    339      * <p>
    340      * Returns {@link #NaN} if either this or <code>rhs</code> has one or more
    341      * NaN parts.
    342      * </p>
    343      * Returns {@link #INF} if neither this nor <code>rhs</code> has one or more
    344      * NaN parts and if either this or <code>rhs</code> has one or more
    345      * infinite parts (same result is returned regardless of the sign of the
    346      * components).
    347      * </p>
    348      * <p>
    349      * Returns finite values in components of the result per the
    350      * definitional formula in all remaining cases.
    351      *  </p>
    352      *
    353      * @param rhs the other complex number
    354      * @return the complex number product
    355      * @throws NullPointerException if <code>rhs</code> is null
    356      */
    357     public Complex multiply(Complex rhs) {
    358         if (isNaN() || rhs.isNaN()) {
    359             return NaN;
    360         }
    361         if (Double.isInfinite(real) || Double.isInfinite(imaginary) ||
    362             Double.isInfinite(rhs.real)|| Double.isInfinite(rhs.imaginary)) {
    363             // we don't use Complex.isInfinite() to avoid testing for NaN again
    364             return INF;
    365         }
    366         return createComplex(real * rhs.real - imaginary * rhs.imaginary,
    367                 real * rhs.imaginary + imaginary * rhs.real);
    368     }
    369 
    370     /**
    371      * Return the product of this complex number and the given scalar number.
    372      * <p>
    373      * Implements preliminary checks for NaN and infinity followed by
    374      * the definitional formula:
    375      * <pre><code>
    376      * c(a + bi) = (ca) + (cb)i
    377      * </code></pre>
    378      * </p>
    379      * <p>
    380      * Returns {@link #NaN} if either this or <code>rhs</code> has one or more
    381      * NaN parts.
    382      * </p>
    383      * Returns {@link #INF} if neither this nor <code>rhs</code> has one or more
    384      * NaN parts and if either this or <code>rhs</code> has one or more
    385      * infinite parts (same result is returned regardless of the sign of the
    386      * components).
    387      * </p>
    388      * <p>
    389      * Returns finite values in components of the result per the
    390      * definitional formula in all remaining cases.
    391      *  </p>
    392      *
    393      * @param rhs the scalar number
    394      * @return the complex number product
    395      */
    396     public Complex multiply(double rhs) {
    397         if (isNaN() || Double.isNaN(rhs)) {
    398             return NaN;
    399         }
    400         if (Double.isInfinite(real) || Double.isInfinite(imaginary) ||
    401             Double.isInfinite(rhs)) {
    402             // we don't use Complex.isInfinite() to avoid testing for NaN again
    403             return INF;
    404         }
    405         return createComplex(real * rhs, imaginary * rhs);
    406     }
    407 
    408     /**
    409      * Return the additive inverse of this complex number.
    410      * <p>
    411      * Returns <code>Complex.NaN</code> if either real or imaginary
    412      * part of this Complex number equals <code>Double.NaN</code>.</p>
    413      *
    414      * @return the negation of this complex number
    415      */
    416     public Complex negate() {
    417         if (isNaN()) {
    418             return NaN;
    419         }
    420 
    421         return createComplex(-real, -imaginary);
    422     }
    423 
    424     /**
    425      * Return the difference between this complex number and the given complex
    426      * number.
    427       * <p>
    428      * Uses the definitional formula
    429      * <pre>
    430      * (a + bi) - (c + di) = (a-c) + (b-d)i
    431      * </pre></p>
    432      * <p>
    433      * If either this or <code>rhs</code> has a NaN value in either part,
    434      * {@link #NaN} is returned; otherwise inifinite and NaN values are
    435      * returned in the parts of the result according to the rules for
    436      * {@link java.lang.Double} arithmetic. </p>
    437      *
    438      * @param rhs the other complex number
    439      * @return the complex number difference
    440      * @throws NullPointerException if <code>rhs</code> is null
    441      */
    442     public Complex subtract(Complex rhs) {
    443         if (isNaN() || rhs.isNaN()) {
    444             return NaN;
    445         }
    446 
    447         return createComplex(real - rhs.getReal(),
    448             imaginary - rhs.getImaginary());
    449     }
    450 
    451     /**
    452      * Compute the
    453      * <a href="http://mathworld.wolfram.com/InverseCosine.html" TARGET="_top">
    454      * inverse cosine</a> of this complex number.
    455      * <p>
    456      * Implements the formula: <pre>
    457      * <code> acos(z) = -i (log(z + i (sqrt(1 - z<sup>2</sup>))))</code></pre></p>
    458      * <p>
    459      * Returns {@link Complex#NaN} if either real or imaginary part of the
    460      * input argument is <code>NaN</code> or infinite.</p>
    461      *
    462      * @return the inverse cosine of this complex number
    463      * @since 1.2
    464      */
    465     public Complex acos() {
    466         if (isNaN()) {
    467             return Complex.NaN;
    468         }
    469 
    470         return this.add(this.sqrt1z().multiply(Complex.I)).log()
    471               .multiply(Complex.I.negate());
    472     }
    473 
    474     /**
    475      * Compute the
    476      * <a href="http://mathworld.wolfram.com/InverseSine.html" TARGET="_top">
    477      * inverse sine</a> of this complex number.
    478      * <p>
    479      * Implements the formula: <pre>
    480      * <code> asin(z) = -i (log(sqrt(1 - z<sup>2</sup>) + iz)) </code></pre></p>
    481      * <p>
    482      * Returns {@link Complex#NaN} if either real or imaginary part of the
    483      * input argument is <code>NaN</code> or infinite.</p>
    484      *
    485      * @return the inverse sine of this complex number.
    486      * @since 1.2
    487      */
    488     public Complex asin() {
    489         if (isNaN()) {
    490             return Complex.NaN;
    491         }
    492 
    493         return sqrt1z().add(this.multiply(Complex.I)).log()
    494               .multiply(Complex.I.negate());
    495     }
    496 
    497     /**
    498      * Compute the
    499      * <a href="http://mathworld.wolfram.com/InverseTangent.html" TARGET="_top">
    500      * inverse tangent</a> of this complex number.
    501      * <p>
    502      * Implements the formula: <pre>
    503      * <code> atan(z) = (i/2) log((i + z)/(i - z)) </code></pre></p>
    504      * <p>
    505      * Returns {@link Complex#NaN} if either real or imaginary part of the
    506      * input argument is <code>NaN</code> or infinite.</p>
    507      *
    508      * @return the inverse tangent of this complex number
    509      * @since 1.2
    510      */
    511     public Complex atan() {
    512         if (isNaN()) {
    513             return Complex.NaN;
    514         }
    515 
    516         return this.add(Complex.I).divide(Complex.I.subtract(this)).log()
    517             .multiply(Complex.I.divide(createComplex(2.0, 0.0)));
    518     }
    519 
    520     /**
    521      * Compute the
    522      * <a href="http://mathworld.wolfram.com/Cosine.html" TARGET="_top">
    523      * cosine</a>
    524      * of this complex number.
    525      * <p>
    526      * Implements the formula: <pre>
    527      * <code> cos(a + bi) = cos(a)cosh(b) - sin(a)sinh(b)i</code></pre>
    528      * where the (real) functions on the right-hand side are
    529      * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
    530      * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
    531      * <p>
    532      * Returns {@link Complex#NaN} if either real or imaginary part of the
    533      * input argument is <code>NaN</code>.</p>
    534      * <p>
    535      * Infinite values in real or imaginary parts of the input may result in
    536      * infinite or NaN values returned in parts of the result.<pre>
    537      * Examples:
    538      * <code>
    539      * cos(1 &plusmn; INFINITY i) = 1 &#x2213; INFINITY i
    540      * cos(&plusmn;INFINITY + i) = NaN + NaN i
    541      * cos(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre></p>
    542      *
    543      * @return the cosine of this complex number
    544      * @since 1.2
    545      */
    546     public Complex cos() {
    547         if (isNaN()) {
    548             return Complex.NaN;
    549         }
    550 
    551         return createComplex(FastMath.cos(real) * MathUtils.cosh(imaginary),
    552             -FastMath.sin(real) * MathUtils.sinh(imaginary));
    553     }
    554 
    555     /**
    556      * Compute the
    557      * <a href="http://mathworld.wolfram.com/HyperbolicCosine.html" TARGET="_top">
    558      * hyperbolic cosine</a> of this complex number.
    559      * <p>
    560      * Implements the formula: <pre>
    561      * <code> cosh(a + bi) = cosh(a)cos(b) + sinh(a)sin(b)i</code></pre>
    562      * where the (real) functions on the right-hand side are
    563      * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
    564      * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
    565      * <p>
    566      * Returns {@link Complex#NaN} if either real or imaginary part of the
    567      * input argument is <code>NaN</code>.</p>
    568      * <p>
    569      * Infinite values in real or imaginary parts of the input may result in
    570      * infinite or NaN values returned in parts of the result.<pre>
    571      * Examples:
    572      * <code>
    573      * cosh(1 &plusmn; INFINITY i) = NaN + NaN i
    574      * cosh(&plusmn;INFINITY + i) = INFINITY &plusmn; INFINITY i
    575      * cosh(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre></p>
    576      *
    577      * @return the hyperbolic cosine of this complex number.
    578      * @since 1.2
    579      */
    580     public Complex cosh() {
    581         if (isNaN()) {
    582             return Complex.NaN;
    583         }
    584 
    585         return createComplex(MathUtils.cosh(real) * FastMath.cos(imaginary),
    586             MathUtils.sinh(real) * FastMath.sin(imaginary));
    587     }
    588 
    589     /**
    590      * Compute the
    591      * <a href="http://mathworld.wolfram.com/ExponentialFunction.html" TARGET="_top">
    592      * exponential function</a> of this complex number.
    593      * <p>
    594      * Implements the formula: <pre>
    595      * <code> exp(a + bi) = exp(a)cos(b) + exp(a)sin(b)i</code></pre>
    596      * where the (real) functions on the right-hand side are
    597      * {@link java.lang.Math#exp}, {@link java.lang.Math#cos}, and
    598      * {@link java.lang.Math#sin}.</p>
    599      * <p>
    600      * Returns {@link Complex#NaN} if either real or imaginary part of the
    601      * input argument is <code>NaN</code>.</p>
    602      * <p>
    603      * Infinite values in real or imaginary parts of the input may result in
    604      * infinite or NaN values returned in parts of the result.<pre>
    605      * Examples:
    606      * <code>
    607      * exp(1 &plusmn; INFINITY i) = NaN + NaN i
    608      * exp(INFINITY + i) = INFINITY + INFINITY i
    609      * exp(-INFINITY + i) = 0 + 0i
    610      * exp(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre></p>
    611      *
    612      * @return <i>e</i><sup><code>this</code></sup>
    613      * @since 1.2
    614      */
    615     public Complex exp() {
    616         if (isNaN()) {
    617             return Complex.NaN;
    618         }
    619 
    620         double expReal = FastMath.exp(real);
    621         return createComplex(expReal *  FastMath.cos(imaginary), expReal * FastMath.sin(imaginary));
    622     }
    623 
    624     /**
    625      * Compute the
    626      * <a href="http://mathworld.wolfram.com/NaturalLogarithm.html" TARGET="_top">
    627      * natural logarithm</a> of this complex number.
    628      * <p>
    629      * Implements the formula: <pre>
    630      * <code> log(a + bi) = ln(|a + bi|) + arg(a + bi)i</code></pre>
    631      * where ln on the right hand side is {@link java.lang.Math#log},
    632      * <code>|a + bi|</code> is the modulus, {@link Complex#abs},  and
    633      * <code>arg(a + bi) = {@link java.lang.Math#atan2}(b, a)</code></p>
    634      * <p>
    635      * Returns {@link Complex#NaN} if either real or imaginary part of the
    636      * input argument is <code>NaN</code>.</p>
    637      * <p>
    638      * Infinite (or critical) values in real or imaginary parts of the input may
    639      * result in infinite or NaN values returned in parts of the result.<pre>
    640      * Examples:
    641      * <code>
    642      * log(1 &plusmn; INFINITY i) = INFINITY &plusmn; (&pi;/2)i
    643      * log(INFINITY + i) = INFINITY + 0i
    644      * log(-INFINITY + i) = INFINITY + &pi;i
    645      * log(INFINITY &plusmn; INFINITY i) = INFINITY &plusmn; (&pi;/4)i
    646      * log(-INFINITY &plusmn; INFINITY i) = INFINITY &plusmn; (3&pi;/4)i
    647      * log(0 + 0i) = -INFINITY + 0i
    648      * </code></pre></p>
    649      *
    650      * @return ln of this complex number.
    651      * @since 1.2
    652      */
    653     public Complex log() {
    654         if (isNaN()) {
    655             return Complex.NaN;
    656         }
    657 
    658         return createComplex(FastMath.log(abs()),
    659             FastMath.atan2(imaginary, real));
    660     }
    661 
    662     /**
    663      * Returns of value of this complex number raised to the power of <code>x</code>.
    664      * <p>
    665      * Implements the formula: <pre>
    666      * <code> y<sup>x</sup> = exp(x&middot;log(y))</code></pre>
    667      * where <code>exp</code> and <code>log</code> are {@link #exp} and
    668      * {@link #log}, respectively.</p>
    669      * <p>
    670      * Returns {@link Complex#NaN} if either real or imaginary part of the
    671      * input argument is <code>NaN</code> or infinite, or if <code>y</code>
    672      * equals {@link Complex#ZERO}.</p>
    673      *
    674      * @param x the exponent.
    675      * @return <code>this</code><sup><code>x</code></sup>
    676      * @throws NullPointerException if x is null
    677      * @since 1.2
    678      */
    679     public Complex pow(Complex x) {
    680         if (x == null) {
    681             throw new NullPointerException();
    682         }
    683         return this.log().multiply(x).exp();
    684     }
    685 
    686     /**
    687      * Compute the
    688      * <a href="http://mathworld.wolfram.com/Sine.html" TARGET="_top">
    689      * sine</a>
    690      * of this complex number.
    691      * <p>
    692      * Implements the formula: <pre>
    693      * <code> sin(a + bi) = sin(a)cosh(b) - cos(a)sinh(b)i</code></pre>
    694      * where the (real) functions on the right-hand side are
    695      * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
    696      * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
    697      * <p>
    698      * Returns {@link Complex#NaN} if either real or imaginary part of the
    699      * input argument is <code>NaN</code>.</p>
    700      * <p>
    701      * Infinite values in real or imaginary parts of the input may result in
    702      * infinite or NaN values returned in parts of the result.<pre>
    703      * Examples:
    704      * <code>
    705      * sin(1 &plusmn; INFINITY i) = 1 &plusmn; INFINITY i
    706      * sin(&plusmn;INFINITY + i) = NaN + NaN i
    707      * sin(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre></p>
    708      *
    709      * @return the sine of this complex number.
    710      * @since 1.2
    711      */
    712     public Complex sin() {
    713         if (isNaN()) {
    714             return Complex.NaN;
    715         }
    716 
    717         return createComplex(FastMath.sin(real) * MathUtils.cosh(imaginary),
    718             FastMath.cos(real) * MathUtils.sinh(imaginary));
    719     }
    720 
    721     /**
    722      * Compute the
    723      * <a href="http://mathworld.wolfram.com/HyperbolicSine.html" TARGET="_top">
    724      * hyperbolic sine</a> of this complex number.
    725      * <p>
    726      * Implements the formula: <pre>
    727      * <code> sinh(a + bi) = sinh(a)cos(b)) + cosh(a)sin(b)i</code></pre>
    728      * where the (real) functions on the right-hand side are
    729      * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
    730      * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
    731      * <p>
    732      * Returns {@link Complex#NaN} if either real or imaginary part of the
    733      * input argument is <code>NaN</code>.</p>
    734      * <p>
    735      * Infinite values in real or imaginary parts of the input may result in
    736      * infinite or NaN values returned in parts of the result.<pre>
    737      * Examples:
    738      * <code>
    739      * sinh(1 &plusmn; INFINITY i) = NaN + NaN i
    740      * sinh(&plusmn;INFINITY + i) = &plusmn; INFINITY + INFINITY i
    741      * sinh(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre></p>
    742      *
    743      * @return the hyperbolic sine of this complex number
    744      * @since 1.2
    745      */
    746     public Complex sinh() {
    747         if (isNaN()) {
    748             return Complex.NaN;
    749         }
    750 
    751         return createComplex(MathUtils.sinh(real) * FastMath.cos(imaginary),
    752             MathUtils.cosh(real) * FastMath.sin(imaginary));
    753     }
    754 
    755     /**
    756      * Compute the
    757      * <a href="http://mathworld.wolfram.com/SquareRoot.html" TARGET="_top">
    758      * square root</a> of this complex number.
    759      * <p>
    760      * Implements the following algorithm to compute <code>sqrt(a + bi)</code>:
    761      * <ol><li>Let <code>t = sqrt((|a| + |a + bi|) / 2)</code></li>
    762      * <li><pre>if <code> a &#8805; 0</code> return <code>t + (b/2t)i</code>
    763      *  else return <code>|b|/2t + sign(b)t i </code></pre></li>
    764      * </ol>
    765      * where <ul>
    766      * <li><code>|a| = {@link Math#abs}(a)</code></li>
    767      * <li><code>|a + bi| = {@link Complex#abs}(a + bi) </code></li>
    768      * <li><code>sign(b) =  {@link MathUtils#indicator}(b) </code>
    769      * </ul></p>
    770      * <p>
    771      * Returns {@link Complex#NaN} if either real or imaginary part of the
    772      * input argument is <code>NaN</code>.</p>
    773      * <p>
    774      * Infinite values in real or imaginary parts of the input may result in
    775      * infinite or NaN values returned in parts of the result.<pre>
    776      * Examples:
    777      * <code>
    778      * sqrt(1 &plusmn; INFINITY i) = INFINITY + NaN i
    779      * sqrt(INFINITY + i) = INFINITY + 0i
    780      * sqrt(-INFINITY + i) = 0 + INFINITY i
    781      * sqrt(INFINITY &plusmn; INFINITY i) = INFINITY + NaN i
    782      * sqrt(-INFINITY &plusmn; INFINITY i) = NaN &plusmn; INFINITY i
    783      * </code></pre></p>
    784      *
    785      * @return the square root of this complex number
    786      * @since 1.2
    787      */
    788     public Complex sqrt() {
    789         if (isNaN()) {
    790             return Complex.NaN;
    791         }
    792 
    793         if (real == 0.0 && imaginary == 0.0) {
    794             return createComplex(0.0, 0.0);
    795         }
    796 
    797         double t = FastMath.sqrt((FastMath.abs(real) + abs()) / 2.0);
    798         if (real >= 0.0) {
    799             return createComplex(t, imaginary / (2.0 * t));
    800         } else {
    801             return createComplex(FastMath.abs(imaginary) / (2.0 * t),
    802                 MathUtils.indicator(imaginary) * t);
    803         }
    804     }
    805 
    806     /**
    807      * Compute the
    808      * <a href="http://mathworld.wolfram.com/SquareRoot.html" TARGET="_top">
    809      * square root</a> of 1 - <code>this</code><sup>2</sup> for this complex
    810      * number.
    811      * <p>
    812      * Computes the result directly as
    813      * <code>sqrt(Complex.ONE.subtract(z.multiply(z)))</code>.</p>
    814      * <p>
    815      * Returns {@link Complex#NaN} if either real or imaginary part of the
    816      * input argument is <code>NaN</code>.</p>
    817      * <p>
    818      * Infinite values in real or imaginary parts of the input may result in
    819      * infinite or NaN values returned in parts of the result.</p>
    820      *
    821      * @return the square root of 1 - <code>this</code><sup>2</sup>
    822      * @since 1.2
    823      */
    824     public Complex sqrt1z() {
    825         return createComplex(1.0, 0.0).subtract(this.multiply(this)).sqrt();
    826     }
    827 
    828     /**
    829      * Compute the
    830      * <a href="http://mathworld.wolfram.com/Tangent.html" TARGET="_top">
    831      * tangent</a> of this complex number.
    832      * <p>
    833      * Implements the formula: <pre>
    834      * <code>tan(a + bi) = sin(2a)/(cos(2a)+cosh(2b)) + [sinh(2b)/(cos(2a)+cosh(2b))]i</code></pre>
    835      * where the (real) functions on the right-hand side are
    836      * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
    837      * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
    838      * <p>
    839      * Returns {@link Complex#NaN} if either real or imaginary part of the
    840      * input argument is <code>NaN</code>.</p>
    841      * <p>
    842      * Infinite (or critical) values in real or imaginary parts of the input may
    843      * result in infinite or NaN values returned in parts of the result.<pre>
    844      * Examples:
    845      * <code>
    846      * tan(1 &plusmn; INFINITY i) = 0 + NaN i
    847      * tan(&plusmn;INFINITY + i) = NaN + NaN i
    848      * tan(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i
    849      * tan(&plusmn;&pi;/2 + 0 i) = &plusmn;INFINITY + NaN i</code></pre></p>
    850      *
    851      * @return the tangent of this complex number
    852      * @since 1.2
    853      */
    854     public Complex tan() {
    855         if (isNaN()) {
    856             return Complex.NaN;
    857         }
    858 
    859         double real2 = 2.0 * real;
    860         double imaginary2 = 2.0 * imaginary;
    861         double d = FastMath.cos(real2) + MathUtils.cosh(imaginary2);
    862 
    863         return createComplex(FastMath.sin(real2) / d, MathUtils.sinh(imaginary2) / d);
    864     }
    865 
    866     /**
    867      * Compute the
    868      * <a href="http://mathworld.wolfram.com/HyperbolicTangent.html" TARGET="_top">
    869      * hyperbolic tangent</a> of this complex number.
    870      * <p>
    871      * Implements the formula: <pre>
    872      * <code>tan(a + bi) = sinh(2a)/(cosh(2a)+cos(2b)) + [sin(2b)/(cosh(2a)+cos(2b))]i</code></pre>
    873      * where the (real) functions on the right-hand side are
    874      * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
    875      * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
    876      * <p>
    877      * Returns {@link Complex#NaN} if either real or imaginary part of the
    878      * input argument is <code>NaN</code>.</p>
    879      * <p>
    880      * Infinite values in real or imaginary parts of the input may result in
    881      * infinite or NaN values returned in parts of the result.<pre>
    882      * Examples:
    883      * <code>
    884      * tanh(1 &plusmn; INFINITY i) = NaN + NaN i
    885      * tanh(&plusmn;INFINITY + i) = NaN + 0 i
    886      * tanh(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i
    887      * tanh(0 + (&pi;/2)i) = NaN + INFINITY i</code></pre></p>
    888      *
    889      * @return the hyperbolic tangent of this complex number
    890      * @since 1.2
    891      */
    892     public Complex tanh() {
    893         if (isNaN()) {
    894             return Complex.NaN;
    895         }
    896 
    897         double real2 = 2.0 * real;
    898         double imaginary2 = 2.0 * imaginary;
    899         double d = MathUtils.cosh(real2) + FastMath.cos(imaginary2);
    900 
    901         return createComplex(MathUtils.sinh(real2) / d, FastMath.sin(imaginary2) / d);
    902     }
    903 
    904 
    905 
    906     /**
    907      * <p>Compute the argument of this complex number.
    908      * </p>
    909      * <p>The argument is the angle phi between the positive real axis and the point
    910      * representing this number in the complex plane. The value returned is between -PI (not inclusive)
    911      * and PI (inclusive), with negative values returned for numbers with negative imaginary parts.
    912      * </p>
    913      * <p>If either real or imaginary part (or both) is NaN, NaN is returned.  Infinite parts are handled
    914      * as java.Math.atan2 handles them, essentially treating finite parts as zero in the presence of
    915      * an infinite coordinate and returning a multiple of pi/4 depending on the signs of the infinite
    916      * parts.  See the javadoc for java.Math.atan2 for full details.</p>
    917      *
    918      * @return the argument of this complex number
    919      */
    920     public double getArgument() {
    921         return FastMath.atan2(getImaginary(), getReal());
    922     }
    923 
    924     /**
    925      * <p>Computes the n-th roots of this complex number.
    926      * </p>
    927      * <p>The nth roots are defined by the formula: <pre>
    928      * <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>
    929      * for <i><code>k=0, 1, ..., n-1</code></i>, where <code>abs</code> and <code>phi</code> are
    930      * respectively the {@link #abs() modulus} and {@link #getArgument() argument} of this complex number.
    931      * </p>
    932      * <p>If one or both parts of this complex number is NaN, a list with just one element,
    933      *  {@link #NaN} is returned.</p>
    934      * <p>if neither part is NaN, but at least one part is infinite, the result is a one-element
    935      * list containing {@link #INF}.</p>
    936      *
    937      * @param n degree of root
    938      * @return List<Complex> all nth roots of this complex number
    939      * @throws IllegalArgumentException if parameter n is less than or equal to 0
    940      * @since 2.0
    941      */
    942     public List<Complex> nthRoot(int n) throws IllegalArgumentException {
    943 
    944         if (n <= 0) {
    945             throw MathRuntimeException.createIllegalArgumentException(
    946                     LocalizedFormats.CANNOT_COMPUTE_NTH_ROOT_FOR_NEGATIVE_N,
    947                     n);
    948         }
    949 
    950         List<Complex> result = new ArrayList<Complex>();
    951 
    952         if (isNaN()) {
    953             result.add(Complex.NaN);
    954             return result;
    955         }
    956 
    957         if (isInfinite()) {
    958             result.add(Complex.INF);
    959             return result;
    960         }
    961 
    962         // nth root of abs -- faster / more accurate to use a solver here?
    963         final double nthRootOfAbs = FastMath.pow(abs(), 1.0 / n);
    964 
    965         // Compute nth roots of complex number with k = 0, 1, ... n-1
    966         final double nthPhi = getArgument()/n;
    967         final double slice = 2 * FastMath.PI / n;
    968         double innerPart = nthPhi;
    969         for (int k = 0; k < n ; k++) {
    970             // inner part
    971             final double realPart      = nthRootOfAbs *  FastMath.cos(innerPart);
    972             final double imaginaryPart = nthRootOfAbs *  FastMath.sin(innerPart);
    973             result.add(createComplex(realPart, imaginaryPart));
    974             innerPart += slice;
    975         }
    976 
    977         return result;
    978     }
    979 
    980     /**
    981      * Create a complex number given the real and imaginary parts.
    982      *
    983      * @param realPart the real part
    984      * @param imaginaryPart the imaginary part
    985      * @return a new complex number instance
    986      * @since 1.2
    987      */
    988     protected Complex createComplex(double realPart, double imaginaryPart) {
    989         return new Complex(realPart, imaginaryPart);
    990     }
    991 
    992     /**
    993      * <p>Resolve the transient fields in a deserialized Complex Object.</p>
    994      * <p>Subclasses will need to override {@link #createComplex} to deserialize properly</p>
    995      * @return A Complex instance with all fields resolved.
    996      * @since 2.0
    997      */
    998     protected final Object readResolve() {
    999         return createComplex(real, imaginary);
   1000     }
   1001 
   1002     /** {@inheritDoc} */
   1003     public ComplexField getField() {
   1004         return ComplexField.getInstance();
   1005     }
   1006 
   1007 }
   1008