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