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