• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 package org.apache.commons.math.complex;
19 
20 import java.io.Serializable;
21 import java.util.ArrayList;
22 import java.util.List;
23 
24 import org.apache.commons.math.FieldElement;
25 import org.apache.commons.math.MathRuntimeException;
26 import org.apache.commons.math.exception.util.LocalizedFormats;
27 import org.apache.commons.math.util.MathUtils;
28 import org.apache.commons.math.util.FastMath;
29 
30 /**
31  * Representation of a Complex number - a number which has both a
32  * real and imaginary part.
33  * <p>
34  * Implementations of arithmetic operations handle <code>NaN</code> and
35  * infinite values according to the rules for {@link java.lang.Double}
36  * arithmetic, applying definitional formulas and returning <code>NaN</code> or
37  * infinite values in real or imaginary parts as these arise in computation.
38  * See individual method javadocs for details.</p>
39  * <p>
40  * {@link #equals} identifies all values with <code>NaN</code> in either real
41  * or imaginary part - e.g., <pre>
42  * <code>1 + NaNi  == NaN + i == NaN + NaNi.</code></pre></p>
43  *
44  * implements Serializable since 2.0
45  *
46  * @version $Revision: 990655 $ $Date: 2010-08-29 23:49:40 +0200 (dim. 29 août 2010) $
47  */
48 public class Complex implements FieldElement<Complex>, Serializable  {
49 
50     /** The square root of -1. A number representing "0.0 + 1.0i" */
51     public static final Complex I = new Complex(0.0, 1.0);
52 
53     // CHECKSTYLE: stop ConstantName
54     /** A complex number representing "NaN + NaNi" */
55     public static final Complex NaN = new Complex(Double.NaN, Double.NaN);
56     // CHECKSTYLE: resume ConstantName
57 
58     /** A complex number representing "+INF + INFi" */
59     public static final Complex INF = new Complex(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
60 
61     /** A complex number representing "1.0 + 0.0i" */
62     public static final Complex ONE = new Complex(1.0, 0.0);
63 
64     /** A complex number representing "0.0 + 0.0i" */
65     public static final Complex ZERO = new Complex(0.0, 0.0);
66 
67     /** Serializable version identifier */
68     private static final long serialVersionUID = -6195664516687396620L;
69 
70     /** The imaginary part. */
71     private final double imaginary;
72 
73     /** The real part. */
74     private final double real;
75 
76     /** Record whether this complex number is equal to NaN. */
77     private final transient boolean isNaN;
78 
79     /** Record whether this complex number is infinite. */
80     private final transient boolean isInfinite;
81 
82     /**
83      * Create a complex number given the real and imaginary parts.
84      *
85      * @param real the real part
86      * @param imaginary the imaginary part
87      */
Complex(double real, double imaginary)88     public Complex(double real, double imaginary) {
89         super();
90         this.real = real;
91         this.imaginary = imaginary;
92 
93         isNaN = Double.isNaN(real) || Double.isNaN(imaginary);
94         isInfinite = !isNaN &&
95         (Double.isInfinite(real) || Double.isInfinite(imaginary));
96     }
97 
98     /**
99      * Return the absolute value of this complex number.
100      * <p>
101      * Returns <code>NaN</code> if either real or imaginary part is
102      * <code>NaN</code> and <code>Double.POSITIVE_INFINITY</code> if
103      * neither part is <code>NaN</code>, but at least one part takes an infinite
104      * value.</p>
105      *
106      * @return the absolute value
107      */
abs()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      */
add(Complex rhs)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      */
conjugate()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      */
divide(Complex rhs)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
equals(Object other)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
hashCode()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      */
getImaginary()293     public double getImaginary() {
294         return imaginary;
295     }
296 
297     /**
298      * Access the real part.
299      *
300      * @return the real part
301      */
getReal()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      */
isNaN()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      */
isInfinite()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      */
multiply(Complex rhs)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      */
multiply(double rhs)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      */
negate()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      */
subtract(Complex rhs)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      */
acos()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      */
asin()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      */
atan()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      */
cos()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      */
cosh()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      */
exp()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      */
log()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      */
pow(Complex x)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      */
sin()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      */
sinh()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      */
sqrt()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      */
sqrt1z()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      */
tan()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      */
tanh()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      */
getArgument()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      */
nthRoot(int n)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      */
createComplex(double realPart, double imaginaryPart)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      */
readResolve()998     protected final Object readResolve() {
999         return createComplex(real, imaginary);
1000     }
1001 
1002     /** {@inheritDoc} */
getField()1003     public ComplexField getField() {
1004         return ComplexField.getInstance();
1005     }
1006 
1007 }
1008