1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.commons.math.complex;
19
20 import java.io.Serializable;
21 import org.apache.commons.math.util.MathUtils;
22
23 /**
24 * Representation of a Complex number - a number which has both a
25 * real and imaginary part.
26 * <p>
27 * Implementations of arithmetic operations handle <code>NaN</code> and
28 * infinite values according to the rules for {@link java.lang.Double}
29 * arithmetic, applying definitional formulas and returning <code>NaN</code> or
30 * infinite values in real or imaginary parts as these arise in computation.
31 * See individual method javadocs for details.</p>
32 * <p>
33 * {@link #equals} identifies all values with <code>NaN</code> in either real
34 * or imaginary part - e.g., <pre>
35 * <code>1 + NaNi == NaN + i == NaN + NaNi.</code></pre></p>
36 *
37 * @version $Revision: 670469 $ $Date: 2008-06-23 10:01:38 +0200 (lun, 23 jun 2008) $
38 */
39 public class Complex implements Serializable {
40
41 /** Serializable version identifier */
42 private static final long serialVersionUID = -6530173849413811929L;
43
44 /** The square root of -1. A number representing "0.0 + 1.0i" */
45 public static final Complex I = new Complex(0.0, 1.0);
46
47 /** A complex number representing "NaN + NaNi" */
48 public static final Complex NaN = new Complex(Double.NaN, Double.NaN);
49
50 /** A complex number representing "+INF + INFi" */
51 public static final Complex INF = new Complex(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
52
53 /** A complex number representing "1.0 + 0.0i" */
54 public static final Complex ONE = new Complex(1.0, 0.0);
55
56 /** A complex number representing "0.0 + 0.0i" */
57 public static final Complex ZERO = new Complex(0.0, 0.0);
58
59 /**
60 * The imaginary part
61 */
62 private final double imaginary;
63
64 /**
65 * The real part
66 */
67 private final double real;
68
69 /**
70 * Create a complex number given the real and imaginary parts.
71 *
72 * @param real the real part
73 * @param imaginary the imaginary part
74 */
75 public Complex(double real, double imaginary) {
76 super();
77 this.real = real;
78 this.imaginary = imaginary;
79 }
80
81 /**
82 * Return the absolute value of this complex number.
83 * <p>
84 * Returns <code>NaN</code> if either real or imaginary part is
85 * <code>NaN</code> and <code>Double.POSITIVE_INFINITY</code> if
86 * neither part is <code>NaN</code>, but at least one part takes an infinite
87 * value.</p>
88 *
89 * @return the absolute value
90 */
91 public double abs() {
92 if (isNaN()) {
93 return Double.NaN;
94 }
95
96 if (isInfinite()) {
97 return Double.POSITIVE_INFINITY;
98 }
99
100 if (Math.abs(real) < Math.abs(imaginary)) {
101 if (imaginary == 0.0) {
102 return Math.abs(real);
103 }
104 double q = real / imaginary;
105 return (Math.abs(imaginary) * Math.sqrt(1 + q*q));
106 } else {
107 if (real == 0.0) {
108 return Math.abs(imaginary);
109 }
110 double q = imaginary / real;
111 return (Math.abs(real) * Math.sqrt(1 + q*q));
112 }
113 }
114
115 /**
116 * Return the sum of this complex number and the given complex number.
117 * <p>
118 * Uses the definitional formula
119 * <pre>
120 * (a + bi) + (c + di) = (a+c) + (b+d)i
121 * </pre></p>
122 * <p>
123 * If either this or <code>rhs</code> has a NaN value in either part,
124 * {@link #NaN} is returned; otherwise Inifinite and NaN values are
125 * returned in the parts of the result according to the rules for
126 * {@link java.lang.Double} arithmetic.</p>
127 *
128 * @param rhs the other complex number
129 * @return the complex number sum
130 * @throws NullPointerException if <code>rhs</code> is null
131 */
132 public Complex add(Complex rhs) {
133 return createComplex(real + rhs.getReal(),
134 imaginary + rhs.getImaginary());
135 }
136
137 /**
138 * Return the conjugate of this complex number. The conjugate of
139 * "A + Bi" is "A - Bi".
140 * <p>
141 * {@link #NaN} is returned if either the real or imaginary
142 * part of this Complex number equals <code>Double.NaN</code>.</p>
143 * <p>
144 * If the imaginary part is infinite, and the real part is not NaN,
145 * the returned value has infinite imaginary part of the opposite
146 * sign - e.g. the conjugate of <code>1 + POSITIVE_INFINITY i</code>
147 * is <code>1 - NEGATIVE_INFINITY i</code></p>
148 *
149 * @return the conjugate of this Complex object
150 */
151 public Complex conjugate() {
152 if (isNaN()) {
153 return NaN;
154 }
155 return createComplex(real, -imaginary);
156 }
157
158 /**
159 * Return the quotient of this complex number and the given complex number.
160 * <p>
161 * Implements the definitional formula
162 * <pre><code>
163 * a + bi ac + bd + (bc - ad)i
164 * ----------- = -------------------------
165 * c + di c<sup>2</sup> + d<sup>2</sup>
166 * </code></pre>
167 * but uses
168 * <a href="http://doi.acm.org/10.1145/1039813.1039814">
169 * prescaling of operands</a> to limit the effects of overflows and
170 * underflows in the computation.</p>
171 * <p>
172 * Infinite and NaN values are handled / returned according to the
173 * following rules, applied in the order presented:
174 * <ul>
175 * <li>If either this or <code>rhs</code> has a NaN value in either part,
176 * {@link #NaN} is returned.</li>
177 * <li>If <code>rhs</code> equals {@link #ZERO}, {@link #NaN} is returned.
178 * </li>
179 * <li>If this and <code>rhs</code> are both infinite,
180 * {@link #NaN} is returned.</li>
181 * <li>If this is finite (i.e., has no infinite or NaN parts) and
182 * <code>rhs</code> is infinite (one or both parts infinite),
183 * {@link #ZERO} is returned.</li>
184 * <li>If this is infinite and <code>rhs</code> is finite, NaN values are
185 * returned in the parts of the result if the {@link java.lang.Double}
186 * rules applied to the definitional formula force NaN results.</li>
187 * </ul></p>
188 *
189 * @param rhs the other complex number
190 * @return the complex number quotient
191 * @throws NullPointerException if <code>rhs</code> is null
192 */
193 public Complex divide(Complex rhs) {
194 if (isNaN() || rhs.isNaN()) {
195 return NaN;
196 }
197
198 double c = rhs.getReal();
199 double d = rhs.getImaginary();
200 if (c == 0.0 && d == 0.0) {
201 return NaN;
202 }
203
204 if (rhs.isInfinite() && !isInfinite()) {
205 return ZERO;
206 }
207
208 if (Math.abs(c) < Math.abs(d)) {
209 if (d == 0.0) {
210 return createComplex(real/c, imaginary/c);
211 }
212 double q = c / d;
213 double denominator = c * q + d;
214 return createComplex((real * q + imaginary) / denominator,
215 (imaginary * q - real) / denominator);
216 } else {
217 if (c == 0.0) {
218 return createComplex(imaginary/d, -real/c);
219 }
220 double q = d / c;
221 double denominator = d * q + c;
222 return createComplex((imaginary * q + real) / denominator,
223 (imaginary - real * q) / denominator);
224 }
225 }
226
227 /**
228 * Test for the equality of two Complex objects.
229 * <p>
230 * If both the real and imaginary parts of two Complex numbers
231 * are exactly the same, and neither is <code>Double.NaN</code>, the two
232 * Complex objects are considered to be equal.</p>
233 * <p>
234 * All <code>NaN</code> values are considered to be equal - i.e, if either
235 * (or both) real and imaginary parts of the complex number are equal
236 * to <code>Double.NaN</code>, the complex number is equal to
237 * <code>Complex.NaN</code>.</p>
238 *
239 * @param other Object to test for equality to this
240 * @return true if two Complex objects are equal, false if
241 * object is null, not an instance of Complex, or
242 * not equal to this Complex instance
243 *
244 */
245 public boolean equals(Object other) {
246 boolean ret;
247
248 if (this == other) {
249 ret = true;
250 } else if (other == null) {
251 ret = false;
252 } else {
253 try {
254 Complex rhs = (Complex)other;
255 if (rhs.isNaN()) {
256 ret = this.isNaN();
257 } else {
258 ret = (Double.doubleToRawLongBits(real) ==
259 Double.doubleToRawLongBits(rhs.getReal())) &&
260 (Double.doubleToRawLongBits(imaginary) ==
261 Double.doubleToRawLongBits(rhs.getImaginary()));
262 }
263 } catch (ClassCastException ex) {
264 // ignore exception
265 ret = false;
266 }
267 }
268
269 return ret;
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 public int hashCode() {
280 if (isNaN()) {
281 return 7;
282 }
283 return 37 * (17 * MathUtils.hash(imaginary) +
284 MathUtils.hash(real));
285 }
286
287 /**
288 * Access the imaginary part.
289 *
290 * @return the imaginary part
291 */
292 public double getImaginary() {
293 return imaginary;
294 }
295
296 /**
297 * Access the real part.
298 *
299 * @return the real part
300 */
301 public double getReal() {
302 return real;
303 }
304
305 /**
306 * Returns true if either or both parts of this complex number is NaN;
307 * false otherwise
308 *
309 * @return true if either or both parts of this complex number is NaN;
310 * false otherwise
311 */
312 public boolean isNaN() {
313 return Double.isNaN(real) || Double.isNaN(imaginary);
314 }
315
316 /**
317 * Returns true if either the real or imaginary part of this complex number
318 * takes an infinite value (either <code>Double.POSITIVE_INFINITY</code> or
319 * <code>Double.NEGATIVE_INFINITY</code>) and neither part
320 * is <code>NaN</code>.
321 *
322 * @return true if one or both parts of this complex number are infinite
323 * and neither part is <code>NaN</code>
324 */
325 public boolean isInfinite() {
326 return !isNaN() &&
327 (Double.isInfinite(real) || Double.isInfinite(imaginary));
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 additive inverse of this complex number.
372 * <p>
373 * Returns <code>Complex.NaN</code> if either real or imaginary
374 * part of this Complex number equals <code>Double.NaN</code>.</p>
375 *
376 * @return the negation of this complex number
377 */
378 public Complex negate() {
379 if (isNaN()) {
380 return NaN;
381 }
382
383 return createComplex(-real, -imaginary);
384 }
385
386 /**
387 * Return the difference between this complex number and the given complex
388 * number.
389 * <p>
390 * Uses the definitional formula
391 * <pre>
392 * (a + bi) - (c + di) = (a-c) + (b-d)i
393 * </pre></p>
394 * <p>
395 * If either this or <code>rhs</code> has a NaN value in either part,
396 * {@link #NaN} is returned; otherwise inifinite and NaN values are
397 * returned in the parts of the result according to the rules for
398 * {@link java.lang.Double} arithmetic. </p>
399 *
400 * @param rhs the other complex number
401 * @return the complex number difference
402 * @throws NullPointerException if <code>rhs</code> is null
403 */
404 public Complex subtract(Complex rhs) {
405 if (isNaN() || rhs.isNaN()) {
406 return NaN;
407 }
408
409 return createComplex(real - rhs.getReal(),
410 imaginary - rhs.getImaginary());
411 }
412
413 /**
414 * Compute the
415 * <a href="http://mathworld.wolfram.com/InverseCosine.html" TARGET="_top">
416 * inverse cosine</a> of this complex number.
417 * <p>
418 * Implements the formula: <pre>
419 * <code> acos(z) = -i (log(z + i (sqrt(1 - z<sup>2</sup>))))</code></pre></p>
420 * <p>
421 * Returns {@link Complex#NaN} if either real or imaginary part of the
422 * input argument is <code>NaN</code> or infinite.</p>
423 *
424 * @return the inverse cosine of this complex number
425 * @since 1.2
426 */
427 public Complex acos() {
428 if (isNaN()) {
429 return Complex.NaN;
430 }
431
432 return this.add(this.sqrt1z().multiply(Complex.I)).log()
433 .multiply(Complex.I.negate());
434 }
435
436 /**
437 * Compute the
438 * <a href="http://mathworld.wolfram.com/InverseSine.html" TARGET="_top">
439 * inverse sine</a> of this complex number.
440 * <p>
441 * Implements the formula: <pre>
442 * <code> asin(z) = -i (log(sqrt(1 - z<sup>2</sup>) + iz)) </code></pre></p>
443 * <p>
444 * Returns {@link Complex#NaN} if either real or imaginary part of the
445 * input argument is <code>NaN</code> or infinite.</p>
446 *
447 * @return the inverse sine of this complex number.
448 * @since 1.2
449 */
450 public Complex asin() {
451 if (isNaN()) {
452 return Complex.NaN;
453 }
454
455 return sqrt1z().add(this.multiply(Complex.I)).log()
456 .multiply(Complex.I.negate());
457 }
458
459 /**
460 * Compute the
461 * <a href="http://mathworld.wolfram.com/InverseTangent.html" TARGET="_top">
462 * inverse tangent</a> of this complex number.
463 * <p>
464 * Implements the formula: <pre>
465 * <code> atan(z) = (i/2) log((i + z)/(i - z)) </code></pre></p>
466 * <p>
467 * Returns {@link Complex#NaN} if either real or imaginary part of the
468 * input argument is <code>NaN</code> or infinite.</p>
469 *
470 * @return the inverse tangent of this complex number
471 * @since 1.2
472 */
473 public Complex atan() {
474 if (isNaN()) {
475 return Complex.NaN;
476 }
477
478 return this.add(Complex.I).divide(Complex.I.subtract(this)).log()
479 .multiply(Complex.I.divide(createComplex(2.0, 0.0)));
480 }
481
482 /**
483 * Compute the
484 * <a href="http://mathworld.wolfram.com/Cosine.html" TARGET="_top">
485 * cosine</a>
486 * of this complex number.
487 * <p>
488 * Implements the formula: <pre>
489 * <code> cos(a + bi) = cos(a)cosh(b) - sin(a)sinh(b)i</code></pre>
490 * where the (real) functions on the right-hand side are
491 * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
492 * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
493 * <p>
494 * Returns {@link Complex#NaN} if either real or imaginary part of the
495 * input argument is <code>NaN</code>.</p>
496 * <p>
497 * Infinite values in real or imaginary parts of the input may result in
498 * infinite or NaN values returned in parts of the result.<pre>
499 * Examples:
500 * <code>
501 * cos(1 ± INFINITY i) = 1 ∓ INFINITY i
502 * cos(±INFINITY + i) = NaN + NaN i
503 * cos(±INFINITY ± INFINITY i) = NaN + NaN i</code></pre></p>
504 *
505 * @return the cosine of this complex number
506 * @since 1.2
507 */
508 public Complex cos() {
509 if (isNaN()) {
510 return Complex.NaN;
511 }
512
513 return createComplex(Math.cos(real) * MathUtils.cosh(imaginary),
514 -Math.sin(real) * MathUtils.sinh(imaginary));
515 }
516
517 /**
518 * Compute the
519 * <a href="http://mathworld.wolfram.com/HyperbolicCosine.html" TARGET="_top">
520 * hyperbolic cosine</a> of this complex number.
521 * <p>
522 * Implements the formula: <pre>
523 * <code> cosh(a + bi) = cosh(a)cos(b) + sinh(a)sin(b)i</code></pre>
524 * where the (real) functions on the right-hand side are
525 * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
526 * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
527 * <p>
528 * Returns {@link Complex#NaN} if either real or imaginary part of the
529 * input argument is <code>NaN</code>.</p>
530 * <p>
531 * Infinite values in real or imaginary parts of the input may result in
532 * infinite or NaN values returned in parts of the result.<pre>
533 * Examples:
534 * <code>
535 * cosh(1 ± INFINITY i) = NaN + NaN i
536 * cosh(±INFINITY + i) = INFINITY ± INFINITY i
537 * cosh(±INFINITY ± INFINITY i) = NaN + NaN i</code></pre></p>
538 *
539 * @return the hyperbolic cosine of this complex number.
540 * @since 1.2
541 */
542 public Complex cosh() {
543 if (isNaN()) {
544 return Complex.NaN;
545 }
546
547 return createComplex(MathUtils.cosh(real) * Math.cos(imaginary),
548 MathUtils.sinh(real) * Math.sin(imaginary));
549 }
550
551 /**
552 * Compute the
553 * <a href="http://mathworld.wolfram.com/ExponentialFunction.html" TARGET="_top">
554 * exponential function</a> of this complex number.
555 * <p>
556 * Implements the formula: <pre>
557 * <code> exp(a + bi) = exp(a)cos(b) + exp(a)sin(b)i</code></pre>
558 * where the (real) functions on the right-hand side are
559 * {@link java.lang.Math#exp}, {@link java.lang.Math#cos}, and
560 * {@link java.lang.Math#sin}.</p>
561 * <p>
562 * Returns {@link Complex#NaN} if either real or imaginary part of the
563 * input argument is <code>NaN</code>.</p>
564 * <p>
565 * Infinite values in real or imaginary parts of the input may result in
566 * infinite or NaN values returned in parts of the result.<pre>
567 * Examples:
568 * <code>
569 * exp(1 ± INFINITY i) = NaN + NaN i
570 * exp(INFINITY + i) = INFINITY + INFINITY i
571 * exp(-INFINITY + i) = 0 + 0i
572 * exp(±INFINITY ± INFINITY i) = NaN + NaN i</code></pre></p>
573 *
574 * @return <i>e</i><sup><code>this</code></sup>
575 * @since 1.2
576 */
577 public Complex exp() {
578 if (isNaN()) {
579 return Complex.NaN;
580 }
581
582 double expReal = Math.exp(real);
583 return createComplex(expReal * Math.cos(imaginary), expReal * Math.sin(imaginary));
584 }
585
586 /**
587 * Compute the
588 * <a href="http://mathworld.wolfram.com/NaturalLogarithm.html" TARGET="_top">
589 * natural logarithm</a> of this complex number.
590 * <p>
591 * Implements the formula: <pre>
592 * <code> log(a + bi) = ln(|a + bi|) + arg(a + bi)i</code></pre>
593 * where ln on the right hand side is {@link java.lang.Math#log},
594 * <code>|a + bi|</code> is the modulus, {@link Complex#abs}, and
595 * <code>arg(a + bi) = {@link java.lang.Math#atan2}(b, a)</code></p>
596 * <p>
597 * Returns {@link Complex#NaN} if either real or imaginary part of the
598 * input argument is <code>NaN</code>.</p>
599 * <p>
600 * Infinite (or critical) values in real or imaginary parts of the input may
601 * result in infinite or NaN values returned in parts of the result.<pre>
602 * Examples:
603 * <code>
604 * log(1 ± INFINITY i) = INFINITY ± (π/2)i
605 * log(INFINITY + i) = INFINITY + 0i
606 * log(-INFINITY + i) = INFINITY + πi
607 * log(INFINITY ± INFINITY i) = INFINITY ± (π/4)i
608 * log(-INFINITY ± INFINITY i) = INFINITY ± (3π/4)i
609 * log(0 + 0i) = -INFINITY + 0i
610 * </code></pre></p>
611 *
612 * @return ln of this complex number.
613 * @since 1.2
614 */
615 public Complex log() {
616 if (isNaN()) {
617 return Complex.NaN;
618 }
619
620 return createComplex(Math.log(abs()),
621 Math.atan2(imaginary, real));
622 }
623
624 /**
625 * Returns of value of this complex number raised to the power of <code>x</code>.
626 * <p>
627 * Implements the formula: <pre>
628 * <code> y<sup>x</sup> = exp(x·log(y))</code></pre>
629 * where <code>exp</code> and <code>log</code> are {@link #exp} and
630 * {@link #log}, respectively.</p>
631 * <p>
632 * Returns {@link Complex#NaN} if either real or imaginary part of the
633 * input argument is <code>NaN</code> or infinite, or if <code>y</code>
634 * equals {@link Complex#ZERO}.</p>
635 *
636 * @param x the exponent.
637 * @return <code>this</code><sup><code>x</code></sup>
638 * @throws NullPointerException if x is null
639 * @since 1.2
640 */
641 public Complex pow(Complex x) {
642 if (x == null) {
643 throw new NullPointerException();
644 }
645 return this.log().multiply(x).exp();
646 }
647
648 /**
649 * Compute the
650 * <a href="http://mathworld.wolfram.com/Sine.html" TARGET="_top">
651 * sine</a>
652 * of this complex number.
653 * <p>
654 * Implements the formula: <pre>
655 * <code> sin(a + bi) = sin(a)cosh(b) - cos(a)sinh(b)i</code></pre>
656 * where the (real) functions on the right-hand side are
657 * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
658 * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
659 * <p>
660 * Returns {@link Complex#NaN} if either real or imaginary part of the
661 * input argument is <code>NaN</code>.</p>
662 * <p>
663 * Infinite values in real or imaginary parts of the input may result in
664 * infinite or NaN values returned in parts of the result.<pre>
665 * Examples:
666 * <code>
667 * sin(1 ± INFINITY i) = 1 ± INFINITY i
668 * sin(±INFINITY + i) = NaN + NaN i
669 * sin(±INFINITY ± INFINITY i) = NaN + NaN i</code></pre></p>
670 *
671 * @return the sine of this complex number.
672 * @since 1.2
673 */
674 public Complex sin() {
675 if (isNaN()) {
676 return Complex.NaN;
677 }
678
679 return createComplex(Math.sin(real) * MathUtils.cosh(imaginary),
680 Math.cos(real) * MathUtils.sinh(imaginary));
681 }
682
683 /**
684 * Compute the
685 * <a href="http://mathworld.wolfram.com/HyperbolicSine.html" TARGET="_top">
686 * hyperbolic sine</a> of this complex number.
687 * <p>
688 * Implements the formula: <pre>
689 * <code> sinh(a + bi) = sinh(a)cos(b)) + cosh(a)sin(b)i</code></pre>
690 * where the (real) functions on the right-hand side are
691 * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
692 * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
693 * <p>
694 * Returns {@link Complex#NaN} if either real or imaginary part of the
695 * input argument is <code>NaN</code>.</p>
696 * <p>
697 * Infinite values in real or imaginary parts of the input may result in
698 * infinite or NaN values returned in parts of the result.<pre>
699 * Examples:
700 * <code>
701 * sinh(1 ± INFINITY i) = NaN + NaN i
702 * sinh(±INFINITY + i) = ± INFINITY + INFINITY i
703 * sinh(±INFINITY ± INFINITY i) = NaN + NaN i</code></pre></p>
704 *
705 * @return the hyperbolic sine of this complex number
706 * @since 1.2
707 */
708 public Complex sinh() {
709 if (isNaN()) {
710 return Complex.NaN;
711 }
712
713 return createComplex(MathUtils.sinh(real) * Math.cos(imaginary),
714 MathUtils.cosh(real) * Math.sin(imaginary));
715 }
716
717 /**
718 * Compute the
719 * <a href="http://mathworld.wolfram.com/SquareRoot.html" TARGET="_top">
720 * square root</a> of this complex number.
721 * <p>
722 * Implements the following algorithm to compute <code>sqrt(a + bi)</code>:
723 * <ol><li>Let <code>t = sqrt((|a| + |a + bi|) / 2)</code></li>
724 * <li><pre>if <code> a ≥ 0</code> return <code>t + (b/2t)i</code>
725 * else return <code>|b|/2t + sign(b)t i </code></pre></li>
726 * </ol>
727 * where <ul>
728 * <li><code>|a| = {@link Math#abs}(a)</code></li>
729 * <li><code>|a + bi| = {@link Complex#abs}(a + bi) </code></li>
730 * <li><code>sign(b) = {@link MathUtils#indicator}(b) </code>
731 * </ul></p>
732 * <p>
733 * Returns {@link Complex#NaN} if either real or imaginary part of the
734 * input argument is <code>NaN</code>.</p>
735 * <p>
736 * Infinite values in real or imaginary parts of the input may result in
737 * infinite or NaN values returned in parts of the result.<pre>
738 * Examples:
739 * <code>
740 * sqrt(1 ± INFINITY i) = INFINITY + NaN i
741 * sqrt(INFINITY + i) = INFINITY + 0i
742 * sqrt(-INFINITY + i) = 0 + INFINITY i
743 * sqrt(INFINITY ± INFINITY i) = INFINITY + NaN i
744 * sqrt(-INFINITY ± INFINITY i) = NaN ± INFINITY i
745 * </code></pre></p>
746 *
747 * @return the square root of this complex number
748 * @since 1.2
749 */
750 public Complex sqrt() {
751 if (isNaN()) {
752 return Complex.NaN;
753 }
754
755 if (real == 0.0 && imaginary == 0.0) {
756 return createComplex(0.0, 0.0);
757 }
758
759 double t = Math.sqrt((Math.abs(real) + abs()) / 2.0);
760 if (real >= 0.0) {
761 return createComplex(t, imaginary / (2.0 * t));
762 } else {
763 return createComplex(Math.abs(imaginary) / (2.0 * t),
764 MathUtils.indicator(imaginary) * t);
765 }
766 }
767
768 /**
769 * Compute the
770 * <a href="http://mathworld.wolfram.com/SquareRoot.html" TARGET="_top">
771 * square root</a> of 1 - <code>this</code><sup>2</sup> for this complex
772 * number.
773 * <p>
774 * Computes the result directly as
775 * <code>sqrt(Complex.ONE.subtract(z.multiply(z)))</code>.</p>
776 * <p>
777 * Returns {@link Complex#NaN} if either real or imaginary part of the
778 * input argument is <code>NaN</code>.</p>
779 * <p>
780 * Infinite values in real or imaginary parts of the input may result in
781 * infinite or NaN values returned in parts of the result.</p>
782 *
783 * @return the square root of 1 - <code>this</code><sup>2</sup>
784 * @since 1.2
785 */
786 public Complex sqrt1z() {
787 return createComplex(1.0, 0.0).subtract(this.multiply(this)).sqrt();
788 }
789
790 /**
791 * Compute the
792 * <a href="http://mathworld.wolfram.com/Tangent.html" TARGET="_top">
793 * tangent</a> of this complex number.
794 * <p>
795 * Implements the formula: <pre>
796 * <code>tan(a + bi) = sin(2a)/(cos(2a)+cosh(2b)) + [sinh(2b)/(cos(2a)+cosh(2b))]i</code></pre>
797 * where the (real) functions on the right-hand side are
798 * {@link java.lang.Math#sin}, {@link java.lang.Math#cos},
799 * {@link MathUtils#cosh} and {@link MathUtils#sinh}.</p>
800 * <p>
801 * Returns {@link Complex#NaN} if either real or imaginary part of the
802 * input argument is <code>NaN</code>.</p>
803 * <p>
804 * Infinite (or critical) values in real or imaginary parts of the input may
805 * result in infinite or NaN values returned in parts of the result.<pre>
806 * Examples:
807 * <code>
808 * tan(1 ± INFINITY i) = 0 + NaN i
809 * tan(±INFINITY + i) = NaN + NaN i
810 * tan(±INFINITY ± INFINITY i) = NaN + NaN i
811 * tan(±π/2 + 0 i) = ±INFINITY + NaN i</code></pre></p>
812 *
813 * @return the tangent of this complex number
814 * @since 1.2
815 */
816 public Complex tan() {
817 if (isNaN()) {
818 return Complex.NaN;
819 }
820
821 double real2 = 2.0 * real;
822 double imaginary2 = 2.0 * imaginary;
823 double d = Math.cos(real2) + MathUtils.cosh(imaginary2);
824
825 return createComplex(Math.sin(real2) / d, MathUtils.sinh(imaginary2) / d);
826 }
827
828 /**
829 * Compute the
830 * <a href="http://mathworld.wolfram.com/HyperbolicTangent.html" TARGET="_top">
831 * hyperbolic tangent</a> of this complex number.
832 * <p>
833 * Implements the formula: <pre>
834 * <code>tan(a + bi) = sinh(2a)/(cosh(2a)+cos(2b)) + [sin(2b)/(cosh(2a)+cos(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 values in real or imaginary parts of the input may result in
843 * infinite or NaN values returned in parts of the result.<pre>
844 * Examples:
845 * <code>
846 * tanh(1 ± INFINITY i) = NaN + NaN i
847 * tanh(±INFINITY + i) = NaN + 0 i
848 * tanh(±INFINITY ± INFINITY i) = NaN + NaN i
849 * tanh(0 + (π/2)i) = NaN + INFINITY i</code></pre></p>
850 *
851 * @return the hyperbolic tangent of this complex number
852 * @since 1.2
853 */
854 public Complex tanh() {
855 if (isNaN()) {
856 return Complex.NaN;
857 }
858
859 double real2 = 2.0 * real;
860 double imaginary2 = 2.0 * imaginary;
861 double d = MathUtils.cosh(real2) + Math.cos(imaginary2);
862
863 return createComplex(MathUtils.sinh(real2) / d, Math.sin(imaginary2) / d);
864 }
865
866 /**
867 * Create a complex number given the real and imaginary parts.
868 *
869 * @param real the real part
870 * @param imaginary the imaginary part
871 * @return a new complex number instance
872 * @since 1.2
873 */
874 protected Complex createComplex(double real, double imaginary) {
875 return new Complex(real, imaginary);
876 }
877 }