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