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 }