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