source: src/main/java/agents/org/apache/commons/math/complex/Complex.java

Last change on this file was 1, checked in by Wouter Pasman, 7 years ago

Initial import : Genius 9.0.0

File size: 35.2 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package agents.org.apache.commons.math.complex;
19
20import java.io.Serializable;
21import java.util.ArrayList;
22import java.util.List;
23
24import agents.org.apache.commons.math.FieldElement;
25import agents.org.apache.commons.math.MathRuntimeException;
26import agents.org.apache.commons.math.exception.util.LocalizedFormats;
27import agents.org.apache.commons.math.util.FastMath;
28import agents.org.apache.commons.math.util.MathUtils;
29
30/**
31 * Representation of a Complex number - a number which has both a
32 * real and imaginary part.
33 * <p>
34 * Implementations of arithmetic operations handle <code>NaN</code> and
35 * infinite values according to the rules for {@link java.lang.Double}
36 * arithmetic, applying definitional formulas and returning <code>NaN</code> or
37 * infinite values in real or imaginary parts as these arise in computation.
38 * See individual method javadocs for details.</p>
39 * <p>
40 * {@link #equals} identifies all values with <code>NaN</code> in either real
41 * or imaginary part - e.g., <pre>
42 * <code>1 + NaNi == NaN + i == NaN + NaNi.</code></pre></p>
43 *
44 * implements Serializable since 2.0
45 *
46 * @version $Revision: 990655 $ $Date: 2010-08-29 23:49:40 +0200 (dim. 29 août 2010) $
47 */
48public class Complex implements FieldElement<Complex>, Serializable {
49
50 /** The square root of -1. A number representing "0.0 + 1.0i" */
51 public static final Complex I = new Complex(0.0, 1.0);
52
53 // CHECKSTYLE: stop ConstantName
54 /** A complex number representing "NaN + NaNi" */
55 public static final Complex NaN = new Complex(Double.NaN, Double.NaN);
56 // CHECKSTYLE: resume ConstantName
57
58 /** A complex number representing "+INF + INFi" */
59 public static final Complex INF = new Complex(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
60
61 /** A complex number representing "1.0 + 0.0i" */
62 public static final Complex ONE = new Complex(1.0, 0.0);
63
64 /** A complex number representing "0.0 + 0.0i" */
65 public static final Complex ZERO = new Complex(0.0, 0.0);
66
67 /** Serializable version identifier */
68 private static final long serialVersionUID = -6195664516687396620L;
69
70 /** The imaginary part. */
71 private final double imaginary;
72
73 /** The real part. */
74 private final double real;
75
76 /** Record whether this complex number is equal to NaN. */
77 private final transient boolean isNaN;
78
79 /** Record whether this complex number is infinite. */
80 private final transient boolean isInfinite;
81
82 /**
83 * Create a complex number given the real and imaginary parts.
84 *
85 * @param real the real part
86 * @param imaginary the imaginary part
87 */
88 public Complex(double real, double imaginary) {
89 super();
90 this.real = real;
91 this.imaginary = imaginary;
92
93 isNaN = Double.isNaN(real) || Double.isNaN(imaginary);
94 isInfinite = !isNaN &&
95 (Double.isInfinite(real) || Double.isInfinite(imaginary));
96 }
97
98 /**
99 * Return the absolute value of this complex number.
100 * <p>
101 * Returns <code>NaN</code> if either real or imaginary part is
102 * <code>NaN</code> and <code>Double.POSITIVE_INFINITY</code> if
103 * neither part is <code>NaN</code>, but at least one part takes an infinite
104 * value.</p>
105 *
106 * @return the absolute value
107 */
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 &plusmn; INFINITY i) = 1 &#x2213; INFINITY i
540 * cos(&plusmn;INFINITY + i) = NaN + NaN i
541 * cos(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre></p>
542 *
543 * @return the cosine of this complex number
544 * @since 1.2
545 */
546 public Complex cos() {
547 if (isNaN()) {
548 return Complex.NaN;
549 }
550
551 return createComplex(FastMath.cos(real) * MathUtils.cosh(imaginary),
552 -FastMath.sin(real) * MathUtils.sinh(imaginary));
553 }
554
555 /**
556 * Compute the
557 * <a href="http://mathworld.wolfram.com/HyperbolicCosine.html" TARGET="_top">
558 * hyperbolic cosine</a> of this complex number.
559 * <p>
560 * Implements the formula: <pre>
561 * <code> cosh(a + bi) = cosh(a)cos(b) + sinh(a)sin(b)i</code></pre>
562 * where the (real) functions on the right-hand side are
563 * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
564 * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
565 * <p>
566 * Returns {@link Complex#NaN} if either real or imaginary part of the
567 * input argument is <code>NaN</code>.</p>
568 * <p>
569 * Infinite values in real or imaginary parts of the input may result in
570 * infinite or NaN values returned in parts of the result.<pre>
571 * Examples:
572 * <code>
573 * cosh(1 &plusmn; INFINITY i) = NaN + NaN i
574 * cosh(&plusmn;INFINITY + i) = INFINITY &plusmn; INFINITY i
575 * cosh(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre></p>
576 *
577 * @return the hyperbolic cosine of this complex number.
578 * @since 1.2
579 */
580 public Complex cosh() {
581 if (isNaN()) {
582 return Complex.NaN;
583 }
584
585 return createComplex(MathUtils.cosh(real) * FastMath.cos(imaginary),
586 MathUtils.sinh(real) * FastMath.sin(imaginary));
587 }
588
589 /**
590 * Compute the
591 * <a href="http://mathworld.wolfram.com/ExponentialFunction.html" TARGET="_top">
592 * exponential function</a> of this complex number.
593 * <p>
594 * Implements the formula: <pre>
595 * <code> exp(a + bi) = exp(a)cos(b) + exp(a)sin(b)i</code></pre>
596 * where the (real) functions on the right-hand side are
597 * {@link java.lang.Math#exp}, {@link java.lang.Math#cos}, and
598 * {@link java.lang.Math#sin}.</p>
599 * <p>
600 * Returns {@link Complex#NaN} if either real or imaginary part of the
601 * input argument is <code>NaN</code>.</p>
602 * <p>
603 * Infinite values in real or imaginary parts of the input may result in
604 * infinite or NaN values returned in parts of the result.<pre>
605 * Examples:
606 * <code>
607 * exp(1 &plusmn; INFINITY i) = NaN + NaN i
608 * exp(INFINITY + i) = INFINITY + INFINITY i
609 * exp(-INFINITY + i) = 0 + 0i
610 * exp(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre></p>
611 *
612 * @return <i>e</i><sup><code>this</code></sup>
613 * @since 1.2
614 */
615 public Complex exp() {
616 if (isNaN()) {
617 return Complex.NaN;
618 }
619
620 double expReal = FastMath.exp(real);
621 return createComplex(expReal * FastMath.cos(imaginary), expReal * FastMath.sin(imaginary));
622 }
623
624 /**
625 * Compute the
626 * <a href="http://mathworld.wolfram.com/NaturalLogarithm.html" TARGET="_top">
627 * natural logarithm</a> of this complex number.
628 * <p>
629 * Implements the formula: <pre>
630 * <code> log(a + bi) = ln(|a + bi|) + arg(a + bi)i</code></pre>
631 * where ln on the right hand side is {@link java.lang.Math#log},
632 * <code>|a + bi|</code> is the modulus, {@link Complex#abs}, and
633 * <code>arg(a + bi) = {@link java.lang.Math#atan2}(b, a)</code></p>
634 * <p>
635 * Returns {@link Complex#NaN} if either real or imaginary part of the
636 * input argument is <code>NaN</code>.</p>
637 * <p>
638 * Infinite (or critical) values in real or imaginary parts of the input may
639 * result in infinite or NaN values returned in parts of the result.<pre>
640 * Examples:
641 * <code>
642 * log(1 &plusmn; INFINITY i) = INFINITY &plusmn; (&pi;/2)i
643 * log(INFINITY + i) = INFINITY + 0i
644 * log(-INFINITY + i) = INFINITY + &pi;i
645 * log(INFINITY &plusmn; INFINITY i) = INFINITY &plusmn; (&pi;/4)i
646 * log(-INFINITY &plusmn; INFINITY i) = INFINITY &plusmn; (3&pi;/4)i
647 * log(0 + 0i) = -INFINITY + 0i
648 * </code></pre></p>
649 *
650 * @return ln of this complex number.
651 * @since 1.2
652 */
653 public Complex log() {
654 if (isNaN()) {
655 return Complex.NaN;
656 }
657
658 return createComplex(FastMath.log(abs()),
659 FastMath.atan2(imaginary, real));
660 }
661
662 /**
663 * Returns of value of this complex number raised to the power of <code>x</code>.
664 * <p>
665 * Implements the formula: <pre>
666 * <code> y<sup>x</sup> = exp(x&middot;log(y))</code></pre>
667 * where <code>exp</code> and <code>log</code> are {@link #exp} and
668 * {@link #log}, respectively.</p>
669 * <p>
670 * Returns {@link Complex#NaN} if either real or imaginary part of the
671 * input argument is <code>NaN</code> or infinite, or if <code>y</code>
672 * equals {@link Complex#ZERO}.</p>
673 *
674 * @param x the exponent.
675 * @return <code>this</code><sup><code>x</code></sup>
676 * @throws NullPointerException if x is null
677 * @since 1.2
678 */
679 public Complex pow(Complex x) {
680 if (x == null) {
681 throw new NullPointerException();
682 }
683 return this.log().multiply(x).exp();
684 }
685
686 /**
687 * Compute the
688 * <a href="http://mathworld.wolfram.com/Sine.html" TARGET="_top">
689 * sine</a>
690 * of this complex number.
691 * <p>
692 * Implements the formula: <pre>
693 * <code> sin(a + bi) = sin(a)cosh(b) - cos(a)sinh(b)i</code></pre>
694 * where the (real) functions on the right-hand side are
695 * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
696 * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
697 * <p>
698 * Returns {@link Complex#NaN} if either real or imaginary part of the
699 * input argument is <code>NaN</code>.</p>
700 * <p>
701 * Infinite values in real or imaginary parts of the input may result in
702 * infinite or NaN values returned in parts of the result.<pre>
703 * Examples:
704 * <code>
705 * sin(1 &plusmn; INFINITY i) = 1 &plusmn; INFINITY i
706 * sin(&plusmn;INFINITY + i) = NaN + NaN i
707 * sin(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre></p>
708 *
709 * @return the sine of this complex number.
710 * @since 1.2
711 */
712 public Complex sin() {
713 if (isNaN()) {
714 return Complex.NaN;
715 }
716
717 return createComplex(FastMath.sin(real) * MathUtils.cosh(imaginary),
718 FastMath.cos(real) * MathUtils.sinh(imaginary));
719 }
720
721 /**
722 * Compute the
723 * <a href="http://mathworld.wolfram.com/HyperbolicSine.html" TARGET="_top">
724 * hyperbolic sine</a> of this complex number.
725 * <p>
726 * Implements the formula: <pre>
727 * <code> sinh(a + bi) = sinh(a)cos(b)) + cosh(a)sin(b)i</code></pre>
728 * where the (real) functions on the right-hand side are
729 * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
730 * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
731 * <p>
732 * Returns {@link Complex#NaN} if either real or imaginary part of the
733 * input argument is <code>NaN</code>.</p>
734 * <p>
735 * Infinite values in real or imaginary parts of the input may result in
736 * infinite or NaN values returned in parts of the result.<pre>
737 * Examples:
738 * <code>
739 * sinh(1 &plusmn; INFINITY i) = NaN + NaN i
740 * sinh(&plusmn;INFINITY + i) = &plusmn; INFINITY + INFINITY i
741 * sinh(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i</code></pre></p>
742 *
743 * @return the hyperbolic sine of this complex number
744 * @since 1.2
745 */
746 public Complex sinh() {
747 if (isNaN()) {
748 return Complex.NaN;
749 }
750
751 return createComplex(MathUtils.sinh(real) * FastMath.cos(imaginary),
752 MathUtils.cosh(real) * FastMath.sin(imaginary));
753 }
754
755 /**
756 * Compute the
757 * <a href="http://mathworld.wolfram.com/SquareRoot.html" TARGET="_top">
758 * square root</a> of this complex number.
759 * <p>
760 * Implements the following algorithm to compute <code>sqrt(a + bi)</code>:
761 * <ol><li>Let <code>t = sqrt((|a| + |a + bi|) / 2)</code></li>
762 * <li><pre>if <code> a &#8805; 0</code> return <code>t + (b/2t)i</code>
763 * else return <code>|b|/2t + sign(b)t i </code></pre></li>
764 * </ol>
765 * where <ul>
766 * <li><code>|a| = {@link Math#abs}(a)</code></li>
767 * <li><code>|a + bi| = {@link Complex#abs}(a + bi) </code></li>
768 * <li><code>sign(b) = {@link MathUtils#indicator}(b) </code>
769 * </ul></p>
770 * <p>
771 * Returns {@link Complex#NaN} if either real or imaginary part of the
772 * input argument is <code>NaN</code>.</p>
773 * <p>
774 * Infinite values in real or imaginary parts of the input may result in
775 * infinite or NaN values returned in parts of the result.<pre>
776 * Examples:
777 * <code>
778 * sqrt(1 &plusmn; INFINITY i) = INFINITY + NaN i
779 * sqrt(INFINITY + i) = INFINITY + 0i
780 * sqrt(-INFINITY + i) = 0 + INFINITY i
781 * sqrt(INFINITY &plusmn; INFINITY i) = INFINITY + NaN i
782 * sqrt(-INFINITY &plusmn; INFINITY i) = NaN &plusmn; INFINITY i
783 * </code></pre></p>
784 *
785 * @return the square root of this complex number
786 * @since 1.2
787 */
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 &plusmn; INFINITY i) = 0 + NaN i
847 * tan(&plusmn;INFINITY + i) = NaN + NaN i
848 * tan(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i
849 * tan(&plusmn;&pi;/2 + 0 i) = &plusmn;INFINITY + NaN i</code></pre></p>
850 *
851 * @return the tangent of this complex number
852 * @since 1.2
853 */
854 public Complex tan() {
855 if (isNaN()) {
856 return Complex.NaN;
857 }
858
859 double real2 = 2.0 * real;
860 double imaginary2 = 2.0 * imaginary;
861 double d = FastMath.cos(real2) + MathUtils.cosh(imaginary2);
862
863 return createComplex(FastMath.sin(real2) / d, MathUtils.sinh(imaginary2) / d);
864 }
865
866 /**
867 * Compute the
868 * <a href="http://mathworld.wolfram.com/HyperbolicTangent.html" TARGET="_top">
869 * hyperbolic tangent</a> of this complex number.
870 * <p>
871 * Implements the formula: <pre>
872 * <code>tan(a + bi) = sinh(2a)/(cosh(2a)+cos(2b)) + [sin(2b)/(cosh(2a)+cos(2b))]i</code></pre>
873 * where the (real) functions on the right-hand side are
874 * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
875 * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
876 * <p>
877 * Returns {@link Complex#NaN} if either real or imaginary part of the
878 * input argument is <code>NaN</code>.</p>
879 * <p>
880 * Infinite values in real or imaginary parts of the input may result in
881 * infinite or NaN values returned in parts of the result.<pre>
882 * Examples:
883 * <code>
884 * tanh(1 &plusmn; INFINITY i) = NaN + NaN i
885 * tanh(&plusmn;INFINITY + i) = NaN + 0 i
886 * tanh(&plusmn;INFINITY &plusmn; INFINITY i) = NaN + NaN i
887 * tanh(0 + (&pi;/2)i) = NaN + INFINITY i</code></pre></p>
888 *
889 * @return the hyperbolic tangent of this complex number
890 * @since 1.2
891 */
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&pi;k/n) + i (sin(phi + 2&pi;k/n))</code></pre>
929 * for <i><code>k=0, 1, ..., n-1</code></i>, where <code>abs</code> and <code>phi</code> are
930 * respectively the {@link #abs() modulus} and {@link #getArgument() argument} of this complex number.
931 * </p>
932 * <p>If one or both parts of this complex number is NaN, a list with just one element,
933 * {@link #NaN} is returned.</p>
934 * <p>if neither part is NaN, but at least one part is infinite, the result is a one-element
935 * list containing {@link #INF}.</p>
936 *
937 * @param n degree of root
938 * @return List<Complex> all nth roots of this complex number
939 * @throws IllegalArgumentException if parameter n is less than or equal to 0
940 * @since 2.0
941 */
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}
Note: See TracBrowser for help on using the repository browser.