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