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