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: 922713 $ $Date: 2010-03-13 20:26:13 -0500 (Sat, 13 Mar 2010) $
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            if (this == other) {
257                return true;
258            }
259            if (other instanceof Complex){
260                Complex rhs = (Complex)other;
261                if (rhs.isNaN()) {
262                    return this.isNaN();
263                } else {
264                    return (real == rhs.real) && (imaginary == rhs.imaginary);
265                }
266            }
267            return false;
268        }
269    
270        /**
271         * Get a hashCode for the complex number.
272         * <p>
273         * All NaN values have the same hash code.</p>
274         *
275         * @return a hash code value for this object
276         */
277        @Override
278        public int hashCode() {
279            if (isNaN()) {
280                return 7;
281            }
282            return 37 * (17 * MathUtils.hash(imaginary) +
283                MathUtils.hash(real));
284        }
285    
286        /**
287         * Access the imaginary part.
288         *
289         * @return the imaginary part
290         */
291        public double getImaginary() {
292            return imaginary;
293        }
294    
295        /**
296         * Access the real part.
297         *
298         * @return the real part
299         */
300        public double getReal() {
301            return real;
302        }
303    
304        /**
305         * Returns true if either or both parts of this complex number is NaN;
306         * false otherwise
307         *
308         * @return  true if either or both parts of this complex number is NaN;
309         * false otherwise
310         */
311        public boolean isNaN() {
312            return isNaN;
313        }
314    
315        /**
316         * Returns true if either the real or imaginary part of this complex number
317         * takes an infinite value (either <code>Double.POSITIVE_INFINITY</code> or
318         * <code>Double.NEGATIVE_INFINITY</code>) and neither part
319         * is <code>NaN</code>.
320         *
321         * @return true if one or both parts of this complex number are infinite
322         * and neither part is <code>NaN</code>
323         */
324        public boolean isInfinite() {
325            return isInfinite;
326        }
327    
328        /**
329         * Return the product of this complex number and the given complex number.
330         * <p>
331         * Implements preliminary checks for NaN and infinity followed by
332         * the definitional formula:
333         * <pre><code>
334         * (a + bi)(c + di) = (ac - bd) + (ad + bc)i
335         * </code></pre>
336         * </p>
337         * <p>
338         * Returns {@link #NaN} if either this or <code>rhs</code> has one or more
339         * NaN parts.
340         * </p>
341         * Returns {@link #INF} if neither this nor <code>rhs</code> has one or more
342         * NaN parts and if either this or <code>rhs</code> has one or more
343         * infinite parts (same result is returned regardless of the sign of the
344         * components).
345         * </p>
346         * <p>
347         * Returns finite values in components of the result per the
348         * definitional formula in all remaining cases.
349         *  </p>
350         *
351         * @param rhs the other complex number
352         * @return the complex number product
353         * @throws NullPointerException if <code>rhs</code> is null
354         */
355        public Complex multiply(Complex rhs) {
356            if (isNaN() || rhs.isNaN()) {
357                return NaN;
358            }
359            if (Double.isInfinite(real) || Double.isInfinite(imaginary) ||
360                Double.isInfinite(rhs.real)|| Double.isInfinite(rhs.imaginary)) {
361                // we don't use Complex.isInfinite() to avoid testing for NaN again
362                return INF;
363            }
364            return createComplex(real * rhs.real - imaginary * rhs.imaginary,
365                    real * rhs.imaginary + imaginary * rhs.real);
366        }
367    
368        /**
369         * Return the product of this complex number and the given scalar number.
370         * <p>
371         * Implements preliminary checks for NaN and infinity followed by
372         * the definitional formula:
373         * <pre><code>
374         * c(a + bi) = (ca) + (cb)i
375         * </code></pre>
376         * </p>
377         * <p>
378         * Returns {@link #NaN} if either this or <code>rhs</code> has one or more
379         * NaN parts.
380         * </p>
381         * Returns {@link #INF} if neither this nor <code>rhs</code> has one or more
382         * NaN parts and if either this or <code>rhs</code> has one or more
383         * infinite parts (same result is returned regardless of the sign of the
384         * components).
385         * </p>
386         * <p>
387         * Returns finite values in components of the result per the
388         * definitional formula in all remaining cases.
389         *  </p>
390         *
391         * @param rhs the scalar number
392         * @return the complex number product
393         */
394        public Complex multiply(double rhs) {
395            if (isNaN() || Double.isNaN(rhs)) {
396                return NaN;
397            }
398            if (Double.isInfinite(real) || Double.isInfinite(imaginary) ||
399                Double.isInfinite(rhs)) {
400                // we don't use Complex.isInfinite() to avoid testing for NaN again
401                return INF;
402            }
403            return createComplex(real * rhs, imaginary * rhs);
404        }
405    
406        /**
407         * Return the additive inverse of this complex number.
408         * <p>
409         * Returns <code>Complex.NaN</code> if either real or imaginary
410         * part of this Complex number equals <code>Double.NaN</code>.</p>
411         *
412         * @return the negation of this complex number
413         */
414        public Complex negate() {
415            if (isNaN()) {
416                return NaN;
417            }
418    
419            return createComplex(-real, -imaginary);
420        }
421    
422        /**
423         * Return the difference between this complex number and the given complex
424         * number.
425          * <p>
426         * Uses the definitional formula
427         * <pre>
428         * (a + bi) - (c + di) = (a-c) + (b-d)i
429         * </pre></p>
430         * <p>
431         * If either this or <code>rhs</code> has a NaN value in either part,
432         * {@link #NaN} is returned; otherwise inifinite and NaN values are
433         * returned in the parts of the result according to the rules for
434         * {@link java.lang.Double} arithmetic. </p>
435         *
436         * @param rhs the other complex number
437         * @return the complex number difference
438         * @throws NullPointerException if <code>rhs</code> is null
439         */
440        public Complex subtract(Complex rhs) {
441            if (isNaN() || rhs.isNaN()) {
442                return NaN;
443            }
444    
445            return createComplex(real - rhs.getReal(),
446                imaginary - rhs.getImaginary());
447        }
448    
449        /**
450         * Compute the
451         * <a href="http://mathworld.wolfram.com/InverseCosine.html" TARGET="_top">
452         * inverse cosine</a> of this complex number.
453         * <p>
454         * Implements the formula: <pre>
455         * <code> acos(z) = -i (log(z + i (sqrt(1 - z<sup>2</sup>))))</code></pre></p>
456         * <p>
457         * Returns {@link Complex#NaN} if either real or imaginary part of the
458         * input argument is <code>NaN</code> or infinite.</p>
459         *
460         * @return the inverse cosine of this complex number
461         * @since 1.2
462         */
463        public Complex acos() {
464            if (isNaN()) {
465                return Complex.NaN;
466            }
467    
468            return this.add(this.sqrt1z().multiply(Complex.I)).log()
469                  .multiply(Complex.I.negate());
470        }
471    
472        /**
473         * Compute the
474         * <a href="http://mathworld.wolfram.com/InverseSine.html" TARGET="_top">
475         * inverse sine</a> of this complex number.
476         * <p>
477         * Implements the formula: <pre>
478         * <code> asin(z) = -i (log(sqrt(1 - z<sup>2</sup>) + iz)) </code></pre></p>
479         * <p>
480         * Returns {@link Complex#NaN} if either real or imaginary part of the
481         * input argument is <code>NaN</code> or infinite.</p>
482         *
483         * @return the inverse sine of this complex number.
484         * @since 1.2
485         */
486        public Complex asin() {
487            if (isNaN()) {
488                return Complex.NaN;
489            }
490    
491            return sqrt1z().add(this.multiply(Complex.I)).log()
492                  .multiply(Complex.I.negate());
493        }
494    
495        /**
496         * Compute the
497         * <a href="http://mathworld.wolfram.com/InverseTangent.html" TARGET="_top">
498         * inverse tangent</a> of this complex number.
499         * <p>
500         * Implements the formula: <pre>
501         * <code> atan(z) = (i/2) log((i + z)/(i - z)) </code></pre></p>
502         * <p>
503         * Returns {@link Complex#NaN} if either real or imaginary part of the
504         * input argument is <code>NaN</code> or infinite.</p>
505         *
506         * @return the inverse tangent of this complex number
507         * @since 1.2
508         */
509        public Complex atan() {
510            if (isNaN()) {
511                return Complex.NaN;
512            }
513    
514            return this.add(Complex.I).divide(Complex.I.subtract(this)).log()
515                .multiply(Complex.I.divide(createComplex(2.0, 0.0)));
516        }
517    
518        /**
519         * Compute the
520         * <a href="http://mathworld.wolfram.com/Cosine.html" TARGET="_top">
521         * cosine</a>
522         * of this complex number.
523         * <p>
524         * Implements the formula: <pre>
525         * <code> cos(a + bi) = cos(a)cosh(b) - sin(a)sinh(b)i</code></pre>
526         * where the (real) functions on the right-hand side are
527         * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
528         * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
529         * <p>
530         * Returns {@link Complex#NaN} if either real or imaginary part of the
531         * input argument is <code>NaN</code>.</p>
532         * <p>
533         * Infinite values in real or imaginary parts of the input may result in
534         * infinite or NaN values returned in parts of the result.<pre>
535         * Examples:
536         * <code>
537         * cos(1 &plusmn; INFINITY i) = 1 &#x2213; INFINITY i
538         * cos(&plusmn;INFINITY + i) = NaN + NaN i
539         * cos(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre></p>
540         *
541         * @return the cosine of this complex number
542         * @since 1.2
543         */
544        public Complex cos() {
545            if (isNaN()) {
546                return Complex.NaN;
547            }
548    
549            return createComplex(Math.cos(real) * MathUtils.cosh(imaginary),
550                -Math.sin(real) * MathUtils.sinh(imaginary));
551        }
552    
553        /**
554         * Compute the
555         * <a href="http://mathworld.wolfram.com/HyperbolicCosine.html" TARGET="_top">
556         * hyperbolic cosine</a> of this complex number.
557         * <p>
558         * Implements the formula: <pre>
559         * <code> cosh(a + bi) = cosh(a)cos(b) + sinh(a)sin(b)i</code></pre>
560         * where the (real) functions on the right-hand side are
561         * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
562         * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
563         * <p>
564         * Returns {@link Complex#NaN} if either real or imaginary part of the
565         * input argument is <code>NaN</code>.</p>
566         * <p>
567         * Infinite values in real or imaginary parts of the input may result in
568         * infinite or NaN values returned in parts of the result.<pre>
569         * Examples:
570         * <code>
571         * cosh(1 &plusmn; INFINITY i) = NaN + NaN i
572         * cosh(&plusmn;INFINITY + i) = INFINITY &plusmn; INFINITY i
573         * cosh(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre></p>
574         *
575         * @return the hyperbolic cosine of this complex number.
576         * @since 1.2
577         */
578        public Complex cosh() {
579            if (isNaN()) {
580                return Complex.NaN;
581            }
582    
583            return createComplex(MathUtils.cosh(real) * Math.cos(imaginary),
584                MathUtils.sinh(real) * Math.sin(imaginary));
585        }
586    
587        /**
588         * Compute the
589         * <a href="http://mathworld.wolfram.com/ExponentialFunction.html" TARGET="_top">
590         * exponential function</a> of this complex number.
591         * <p>
592         * Implements the formula: <pre>
593         * <code> exp(a + bi) = exp(a)cos(b) + exp(a)sin(b)i</code></pre>
594         * where the (real) functions on the right-hand side are
595         * {@link java.lang.Math#exp}, {@link java.lang.Math#cos}, and
596         * {@link java.lang.Math#sin}.</p>
597         * <p>
598         * Returns {@link Complex#NaN} if either real or imaginary part of the
599         * input argument is <code>NaN</code>.</p>
600         * <p>
601         * Infinite values in real or imaginary parts of the input may result in
602         * infinite or NaN values returned in parts of the result.<pre>
603         * Examples:
604         * <code>
605         * exp(1 &plusmn; INFINITY i) = NaN + NaN i
606         * exp(INFINITY + i) = INFINITY + INFINITY i
607         * exp(-INFINITY + i) = 0 + 0i
608         * exp(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre></p>
609         *
610         * @return <i>e</i><sup><code>this</code></sup>
611         * @since 1.2
612         */
613        public Complex exp() {
614            if (isNaN()) {
615                return Complex.NaN;
616            }
617    
618            double expReal = Math.exp(real);
619            return createComplex(expReal *  Math.cos(imaginary), expReal * Math.sin(imaginary));
620        }
621    
622        /**
623         * Compute the
624         * <a href="http://mathworld.wolfram.com/NaturalLogarithm.html" TARGET="_top">
625         * natural logarithm</a> of this complex number.
626         * <p>
627         * Implements the formula: <pre>
628         * <code> log(a + bi) = ln(|a + bi|) + arg(a + bi)i</code></pre>
629         * where ln on the right hand side is {@link java.lang.Math#log},
630         * <code>|a + bi|</code> is the modulus, {@link Complex#abs},  and
631         * <code>arg(a + bi) = {@link java.lang.Math#atan2}(b, a)</code></p>
632         * <p>
633         * Returns {@link Complex#NaN} if either real or imaginary part of the
634         * input argument is <code>NaN</code>.</p>
635         * <p>
636         * Infinite (or critical) values in real or imaginary parts of the input may
637         * result in infinite or NaN values returned in parts of the result.<pre>
638         * Examples:
639         * <code>
640         * log(1 &plusmn; INFINITY i) = INFINITY &plusmn; (&pi;/2)i
641         * log(INFINITY + i) = INFINITY + 0i
642         * log(-INFINITY + i) = INFINITY + &pi;i
643         * log(INFINITY &plusmn; INFINITY i) = INFINITY &plusmn; (&pi;/4)i
644         * log(-INFINITY &plusmn; INFINITY i) = INFINITY &plusmn; (3&pi;/4)i
645         * log(0 + 0i) = -INFINITY + 0i
646         * </code></pre></p>
647         *
648         * @return ln of this complex number.
649         * @since 1.2
650         */
651        public Complex log() {
652            if (isNaN()) {
653                return Complex.NaN;
654            }
655    
656            return createComplex(Math.log(abs()),
657                Math.atan2(imaginary, real));
658        }
659    
660        /**
661         * Returns of value of this complex number raised to the power of <code>x</code>.
662         * <p>
663         * Implements the formula: <pre>
664         * <code> y<sup>x</sup> = exp(x&middot;log(y))</code></pre>
665         * where <code>exp</code> and <code>log</code> are {@link #exp} and
666         * {@link #log}, respectively.</p>
667         * <p>
668         * Returns {@link Complex#NaN} if either real or imaginary part of the
669         * input argument is <code>NaN</code> or infinite, or if <code>y</code>
670         * equals {@link Complex#ZERO}.</p>
671         *
672         * @param x the exponent.
673         * @return <code>this</code><sup><code>x</code></sup>
674         * @throws NullPointerException if x is null
675         * @since 1.2
676         */
677        public Complex pow(Complex x) {
678            if (x == null) {
679                throw new NullPointerException();
680            }
681            return this.log().multiply(x).exp();
682        }
683    
684        /**
685         * Compute the
686         * <a href="http://mathworld.wolfram.com/Sine.html" TARGET="_top">
687         * sine</a>
688         * of this complex number.
689         * <p>
690         * Implements the formula: <pre>
691         * <code> sin(a + bi) = sin(a)cosh(b) - cos(a)sinh(b)i</code></pre>
692         * where the (real) functions on the right-hand side are
693         * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
694         * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
695         * <p>
696         * Returns {@link Complex#NaN} if either real or imaginary part of the
697         * input argument is <code>NaN</code>.</p>
698         * <p>
699         * Infinite values in real or imaginary parts of the input may result in
700         * infinite or NaN values returned in parts of the result.<pre>
701         * Examples:
702         * <code>
703         * sin(1 &plusmn; INFINITY i) = 1 &plusmn; INFINITY i
704         * sin(&plusmn;INFINITY + i) = NaN + NaN i
705         * sin(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre></p>
706         *
707         * @return the sine of this complex number.
708         * @since 1.2
709         */
710        public Complex sin() {
711            if (isNaN()) {
712                return Complex.NaN;
713            }
714    
715            return createComplex(Math.sin(real) * MathUtils.cosh(imaginary),
716                Math.cos(real) * MathUtils.sinh(imaginary));
717        }
718    
719        /**
720         * Compute the
721         * <a href="http://mathworld.wolfram.com/HyperbolicSine.html" TARGET="_top">
722         * hyperbolic sine</a> of this complex number.
723         * <p>
724         * Implements the formula: <pre>
725         * <code> sinh(a + bi) = sinh(a)cos(b)) + cosh(a)sin(b)i</code></pre>
726         * where the (real) functions on the right-hand side are
727         * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
728         * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
729         * <p>
730         * Returns {@link Complex#NaN} if either real or imaginary part of the
731         * input argument is <code>NaN</code>.</p>
732         * <p>
733         * Infinite values in real or imaginary parts of the input may result in
734         * infinite or NaN values returned in parts of the result.<pre>
735         * Examples:
736         * <code>
737         * sinh(1 &plusmn; INFINITY i) = NaN + NaN i
738         * sinh(&plusmn;INFINITY + i) = &plusmn; INFINITY + INFINITY i
739         * sinh(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre></p>
740         *
741         * @return the hyperbolic sine of this complex number
742         * @since 1.2
743         */
744        public Complex sinh() {
745            if (isNaN()) {
746                return Complex.NaN;
747            }
748    
749            return createComplex(MathUtils.sinh(real) * Math.cos(imaginary),
750                MathUtils.cosh(real) * Math.sin(imaginary));
751        }
752    
753        /**
754         * Compute the
755         * <a href="http://mathworld.wolfram.com/SquareRoot.html" TARGET="_top">
756         * square root</a> of this complex number.
757         * <p>
758         * Implements the following algorithm to compute <code>sqrt(a + bi)</code>:
759         * <ol><li>Let <code>t = sqrt((|a| + |a + bi|) / 2)</code></li>
760         * <li><pre>if <code> a &#8805; 0</code> return <code>t + (b/2t)i</code>
761         *  else return <code>|b|/2t + sign(b)t i </code></pre></li>
762         * </ol>
763         * where <ul>
764         * <li><code>|a| = {@link Math#abs}(a)</code></li>
765         * <li><code>|a + bi| = {@link Complex#abs}(a + bi) </code></li>
766         * <li><code>sign(b) =  {@link MathUtils#indicator}(b) </code>
767         * </ul></p>
768         * <p>
769         * Returns {@link Complex#NaN} if either real or imaginary part of the
770         * input argument is <code>NaN</code>.</p>
771         * <p>
772         * Infinite values in real or imaginary parts of the input may result in
773         * infinite or NaN values returned in parts of the result.<pre>
774         * Examples:
775         * <code>
776         * sqrt(1 &plusmn; INFINITY i) = INFINITY + NaN i
777         * sqrt(INFINITY + i) = INFINITY + 0i
778         * sqrt(-INFINITY + i) = 0 + INFINITY i
779         * sqrt(INFINITY &plusmn; INFINITY i) = INFINITY + NaN i
780         * sqrt(-INFINITY &plusmn; INFINITY i) = NaN &plusmn; INFINITY i
781         * </code></pre></p>
782         *
783         * @return the square root of this complex number
784         * @since 1.2
785         */
786        public Complex sqrt() {
787            if (isNaN()) {
788                return Complex.NaN;
789            }
790    
791            if (real == 0.0 && imaginary == 0.0) {
792                return createComplex(0.0, 0.0);
793            }
794    
795            double t = Math.sqrt((Math.abs(real) + abs()) / 2.0);
796            if (real >= 0.0) {
797                return createComplex(t, imaginary / (2.0 * t));
798            } else {
799                return createComplex(Math.abs(imaginary) / (2.0 * t),
800                    MathUtils.indicator(imaginary) * t);
801            }
802        }
803    
804        /**
805         * Compute the
806         * <a href="http://mathworld.wolfram.com/SquareRoot.html" TARGET="_top">
807         * square root</a> of 1 - <code>this</code><sup>2</sup> for this complex
808         * number.
809         * <p>
810         * Computes the result directly as
811         * <code>sqrt(Complex.ONE.subtract(z.multiply(z)))</code>.</p>
812         * <p>
813         * Returns {@link Complex#NaN} if either real or imaginary part of the
814         * input argument is <code>NaN</code>.</p>
815         * <p>
816         * Infinite values in real or imaginary parts of the input may result in
817         * infinite or NaN values returned in parts of the result.</p>
818         *
819         * @return the square root of 1 - <code>this</code><sup>2</sup>
820         * @since 1.2
821         */
822        public Complex sqrt1z() {
823            return createComplex(1.0, 0.0).subtract(this.multiply(this)).sqrt();
824        }
825    
826        /**
827         * Compute the
828         * <a href="http://mathworld.wolfram.com/Tangent.html" TARGET="_top">
829         * tangent</a> of this complex number.
830         * <p>
831         * Implements the formula: <pre>
832         * <code>tan(a + bi) = sin(2a)/(cos(2a)+cosh(2b)) + [sinh(2b)/(cos(2a)+cosh(2b))]i</code></pre>
833         * where the (real) functions on the right-hand side are
834         * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
835         * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
836         * <p>
837         * Returns {@link Complex#NaN} if either real or imaginary part of the
838         * input argument is <code>NaN</code>.</p>
839         * <p>
840         * Infinite (or critical) values in real or imaginary parts of the input may
841         * result in infinite or NaN values returned in parts of the result.<pre>
842         * Examples:
843         * <code>
844         * tan(1 &plusmn; INFINITY i) = 0 + NaN i
845         * tan(&plusmn;INFINITY + i) = NaN + NaN i
846         * tan(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i
847         * tan(&plusmn;&pi;/2 + 0 i) = &plusmn;INFINITY + NaN i</code></pre></p>
848         *
849         * @return the tangent of this complex number
850         * @since 1.2
851         */
852        public Complex tan() {
853            if (isNaN()) {
854                return Complex.NaN;
855            }
856    
857            double real2 = 2.0 * real;
858            double imaginary2 = 2.0 * imaginary;
859            double d = Math.cos(real2) + MathUtils.cosh(imaginary2);
860    
861            return createComplex(Math.sin(real2) / d, MathUtils.sinh(imaginary2) / d);
862        }
863    
864        /**
865         * Compute the
866         * <a href="http://mathworld.wolfram.com/HyperbolicTangent.html" TARGET="_top">
867         * hyperbolic tangent</a> of this complex number.
868         * <p>
869         * Implements the formula: <pre>
870         * <code>tan(a + bi) = sinh(2a)/(cosh(2a)+cos(2b)) + [sin(2b)/(cosh(2a)+cos(2b))]i</code></pre>
871         * where the (real) functions on the right-hand side are
872         * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
873         * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
874         * <p>
875         * Returns {@link Complex#NaN} if either real or imaginary part of the
876         * input argument is <code>NaN</code>.</p>
877         * <p>
878         * Infinite values in real or imaginary parts of the input may result in
879         * infinite or NaN values returned in parts of the result.<pre>
880         * Examples:
881         * <code>
882         * tanh(1 &plusmn; INFINITY i) = NaN + NaN i
883         * tanh(&plusmn;INFINITY + i) = NaN + 0 i
884         * tanh(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i
885         * tanh(0 + (&pi;/2)i) = NaN + INFINITY i</code></pre></p>
886         *
887         * @return the hyperbolic tangent of this complex number
888         * @since 1.2
889         */
890        public Complex tanh() {
891            if (isNaN()) {
892                return Complex.NaN;
893            }
894    
895            double real2 = 2.0 * real;
896            double imaginary2 = 2.0 * imaginary;
897            double d = MathUtils.cosh(real2) + Math.cos(imaginary2);
898    
899            return createComplex(MathUtils.sinh(real2) / d, Math.sin(imaginary2) / d);
900        }
901    
902    
903    
904        /**
905         * <p>Compute the argument of this complex number.
906         * </p>
907         * <p>The argument is the angle phi between the positive real axis and the point
908         * representing this number in the complex plane. The value returned is between -PI (not inclusive)
909         * and PI (inclusive), with negative values returned for numbers with negative imaginary parts.
910         * </p>
911         * <p>If either real or imaginary part (or both) is NaN, NaN is returned.  Infinite parts are handled
912         * as java.Math.atan2 handles them, essentially treating finite parts as zero in the presence of
913         * an infinite coordinate and returning a multiple of pi/4 depending on the signs of the infinite
914         * parts.  See the javadoc for java.Math.atan2 for full details.</p>
915         *
916         * @return the argument of this complex number
917         */
918        public double getArgument() {
919            return Math.atan2(getImaginary(), getReal());
920        }
921    
922        /**
923         * <p>Computes the n-th roots of this complex number.
924         * </p>
925         * <p>The nth roots are defined by the formula: <pre>
926         * <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>
927         * for <i><code>k=0, 1, ..., n-1</code></i>, where <code>abs</code> and <code>phi</code> are
928         * respectively the {@link #abs() modulus} and {@link #getArgument() argument} of this complex number.
929         * </p>
930         * <p>If one or both parts of this complex number is NaN, a list with just one element,
931         *  {@link #NaN} is returned.</p>
932         * <p>if neither part is NaN, but at least one part is infinite, the result is a one-element
933         * list containing {@link #INF}.</p>
934         *
935         * @param n degree of root
936         * @return List<Complex> all nth roots of this complex number
937         * @throws IllegalArgumentException if parameter n is less than or equal to 0
938         * @since 2.0
939         */
940        public List<Complex> nthRoot(int n) throws IllegalArgumentException {
941    
942            if (n <= 0) {
943                throw MathRuntimeException.createIllegalArgumentException(
944                        "cannot compute nth root for null or negative n: {0}",
945                        n);
946            }
947    
948            List<Complex> result = new ArrayList<Complex>();
949    
950            if (isNaN()) {
951                result.add(Complex.NaN);
952                return result;
953            }
954    
955            if (isInfinite()) {
956                result.add(Complex.INF);
957                return result;
958            }
959    
960            // nth root of abs -- faster / more accurate to use a solver here?
961            final double nthRootOfAbs = Math.pow(abs(), 1.0 / n);
962    
963            // Compute nth roots of complex number with k = 0, 1, ... n-1
964            final double nthPhi = getArgument()/n;
965            final double slice = 2 * Math.PI / n;
966            double innerPart = nthPhi;
967            for (int k = 0; k < n ; k++) {
968                // inner part
969                final double realPart      = nthRootOfAbs *  Math.cos(innerPart);
970                final double imaginaryPart = nthRootOfAbs *  Math.sin(innerPart);
971                result.add(createComplex(realPart, imaginaryPart));
972                innerPart += slice;
973            }
974    
975            return result;
976        }
977    
978        /**
979         * Create a complex number given the real and imaginary parts.
980         *
981         * @param realPart the real part
982         * @param imaginaryPart the imaginary part
983         * @return a new complex number instance
984         * @since 1.2
985         */
986        protected Complex createComplex(double realPart, double imaginaryPart) {
987            return new Complex(realPart, imaginaryPart);
988        }
989    
990        /**
991         * <p>Resolve the transient fields in a deserialized Complex Object.</p>
992         * <p>Subclasses will need to override {@link #createComplex} to deserialize properly</p>
993         * @return A Complex instance with all fields resolved.
994         * @since 2.0
995         */
996        protected final Object readResolve() {
997            return createComplex(real, imaginary);
998        }
999    
1000        /** {@inheritDoc} */
1001        public ComplexField getField() {
1002            return ComplexField.getInstance();
1003        }
1004    
1005    }