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.exception.util.LocalizedFormats;
027    import org.apache.commons.math.util.MathUtils;
028    import org.apache.commons.math.util.FastMath;
029    
030    /**
031     * Representation of a Complex number - a number which has both a
032     * real and imaginary part.
033     * <p>
034     * Implementations of arithmetic operations handle <code>NaN</code> and
035     * infinite values according to the rules for {@link java.lang.Double}
036     * arithmetic, applying definitional formulas and returning <code>NaN</code> or
037     * infinite values in real or imaginary parts as these arise in computation.
038     * See individual method javadocs for details.</p>
039     * <p>
040     * {@link #equals} identifies all values with <code>NaN</code> in either real
041     * or imaginary part - e.g., <pre>
042     * <code>1 + NaNi  == NaN + i == NaN + NaNi.</code></pre></p>
043     *
044     * implements Serializable since 2.0
045     *
046     * @version $Revision: 990655 $ $Date: 2010-08-29 23:49:40 +0200 (dim. 29 ao??t 2010) $
047     */
048    public class Complex implements FieldElement<Complex>, Serializable  {
049    
050        /** The square root of -1. A number representing "0.0 + 1.0i" */
051        public static final Complex I = new Complex(0.0, 1.0);
052    
053        // CHECKSTYLE: stop ConstantName
054        /** A complex number representing "NaN + NaNi" */
055        public static final Complex NaN = new Complex(Double.NaN, Double.NaN);
056        // CHECKSTYLE: resume ConstantName
057    
058        /** A complex number representing "+INF + INFi" */
059        public static final Complex INF = new Complex(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
060    
061        /** A complex number representing "1.0 + 0.0i" */
062        public static final Complex ONE = new Complex(1.0, 0.0);
063    
064        /** A complex number representing "0.0 + 0.0i" */
065        public static final Complex ZERO = new Complex(0.0, 0.0);
066    
067        /** Serializable version identifier */
068        private static final long serialVersionUID = -6195664516687396620L;
069    
070        /** The imaginary part. */
071        private final double imaginary;
072    
073        /** The real part. */
074        private final double real;
075    
076        /** Record whether this complex number is equal to NaN. */
077        private final transient boolean isNaN;
078    
079        /** Record whether this complex number is infinite. */
080        private final transient boolean isInfinite;
081    
082        /**
083         * Create a complex number given the real and imaginary parts.
084         *
085         * @param real the real part
086         * @param imaginary the imaginary part
087         */
088        public Complex(double real, double imaginary) {
089            super();
090            this.real = real;
091            this.imaginary = imaginary;
092    
093            isNaN = Double.isNaN(real) || Double.isNaN(imaginary);
094            isInfinite = !isNaN &&
095            (Double.isInfinite(real) || Double.isInfinite(imaginary));
096        }
097    
098        /**
099         * 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    }