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.util.MathUtils;
27
28 /**
29 * Representation of a Complex number - a number which has both a
30 * real and imaginary part.
31 * <p>
32 * Implementations of arithmetic operations handle <code>NaN</code> and
33 * infinite values according to the rules for {@link java.lang.Double}
34 * arithmetic, applying definitional formulas and returning <code>NaN</code> or
35 * infinite values in real or imaginary parts as these arise in computation.
36 * See individual method javadocs for details.</p>
37 * <p>
38 * {@link #equals} identifies all values with <code>NaN</code> in either real
39 * or imaginary part - e.g., <pre>
40 * <code>1 + NaNi == NaN + i == NaN + NaNi.</code></pre></p>
41 *
42 * implements Serializable since 2.0
43 *
44 * @version $Revision: 791237 $ $Date: 2009-07-05 08:53:13 -0400 (Sun, 05 Jul 2009) $
45 */
46 public class Complex implements FieldElement<Complex>, Serializable {
47
48 /** Serializable version identifier */
49 private static final long serialVersionUID = -6195664516687396620L;
50
51 /** The square root of -1. A number representing "0.0 + 1.0i" */
52 public static final Complex I = new Complex(0.0, 1.0);
53
54 /** A complex number representing "NaN + NaNi" */
55 public static final Complex NaN = new Complex(Double.NaN, Double.NaN);
56
57 /** A complex number representing "+INF + INFi" */
58 public static final Complex INF = new Complex(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
59
60 /** A complex number representing "1.0 + 0.0i" */
61 public static final Complex ONE = new Complex(1.0, 0.0);
62
63 /** A complex number representing "0.0 + 0.0i" */
64 public static final Complex ZERO = new Complex(0.0, 0.0);
65
66 /**
67 * The imaginary part
68 */
69 private final double imaginary;
70
71 /**
72 * The real part
73 */
74 private final double real;
75
76 /**
77 * Record whether this complex number is equal to NaN
78 */
79 private final transient boolean isNaN;
80
81 /**
82 * Record whether this complex number is infinite
83 */
84 private final transient boolean isInfinite;
85
86 /**
87 * Create a complex number given the real and imaginary parts.
88 *
89 * @param real the real part
90 * @param imaginary the imaginary part
91 */
92 public Complex(double real, double imaginary) {
93 super();
94 this.real = real;
95 this.imaginary = imaginary;
96
97 isNaN = Double.isNaN(real) || Double.isNaN(imaginary);
98 isInfinite = !isNaN &&
99 (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 ± INFINITY i) = 1 ∓ INFINITY i
559 * cos(±INFINITY + i) = NaN + NaN i
560 * cos(±INFINITY ± 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 ± INFINITY i) = NaN + NaN i
593 * cosh(±INFINITY + i) = INFINITY ± INFINITY i
594 * cosh(±INFINITY ± 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 ± INFINITY i) = NaN + NaN i
627 * exp(INFINITY + i) = INFINITY + INFINITY i
628 * exp(-INFINITY + i) = 0 + 0i
629 * exp(±INFINITY ± 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 ± INFINITY i) = INFINITY ± (π/2)i
662 * log(INFINITY + i) = INFINITY + 0i
663 * log(-INFINITY + i) = INFINITY + πi
664 * log(INFINITY ± INFINITY i) = INFINITY ± (π/4)i
665 * log(-INFINITY ± INFINITY i) = INFINITY ± (3π/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·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 ± INFINITY i) = 1 ± INFINITY i
725 * sin(±INFINITY + i) = NaN + NaN i
726 * sin(±INFINITY ± 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 ± INFINITY i) = NaN + NaN i
759 * sinh(±INFINITY + i) = ± INFINITY + INFINITY i
760 * sinh(±INFINITY ± 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 ≥ 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 ± INFINITY i) = INFINITY + NaN i
798 * sqrt(INFINITY + i) = INFINITY + 0i
799 * sqrt(-INFINITY + i) = 0 + INFINITY i
800 * sqrt(INFINITY ± INFINITY i) = INFINITY + NaN i
801 * sqrt(-INFINITY ± INFINITY i) = NaN ± 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 ± INFINITY i) = 0 + NaN i
866 * tan(±INFINITY + i) = NaN + NaN i
867 * tan(±INFINITY ± INFINITY i) = NaN + NaN i
868 * tan(±π/2 + 0 i) = ±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 ± INFINITY i) = NaN + NaN i
904 * tanh(±INFINITY + i) = NaN + 0 i
905 * tanh(±INFINITY ± INFINITY i) = NaN + NaN i
906 * tanh(0 + (π/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πk/n) + i (sin(phi + 2π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 }