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