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