1 /* 2 * Copyright 2003-2005 The Apache Software Foundation. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.apache.commons.math.complex; 18 19 import java.io.Serializable; 20 import org.apache.commons.math.util.MathUtils; 21 22 /** 23 * Representation of a Complex number - a number which has both a 24 * real and imaginary part. 25 * <p> 26 * Implementations of arithmetic operations handle <code>NaN</code> and 27 * infinite values according to the rules for {@link java.lang.Double} 28 * arithmetic, applying definitional formulas and returning <code>NaN</code> or 29 * infinite values in real or imaginary parts as these arise in computation. 30 * See individual method javadocs for details. 31 * <p> 32 * {@link #equals} identifies all values with <code>NaN</code> in either real 33 * or imaginary part - e.g., <pre> 34 * <code>1 + NaNi == NaN + i == NaN + NaNi.</code></pre> 35 * 36 * @author Apache Software Foundation 37 * @version $Revision: 349309 $ $Date: 2005-11-27 13:55:08 -0700 (Sun, 27 Nov 2005) $ 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 "1.0 + 0.0i" */ 51 public static final Complex ONE = new Complex(1.0, 0.0); 52 53 /** A complex number representing "0.0 + 0.0i" */ 54 public static final Complex ZERO = new Complex(0.0, 0.0); 55 56 /** The imaginary part */ 57 protected double imaginary; 58 59 /** The real part */ 60 protected double real; 61 62 /** 63 * Create a complex number given the real and imaginary parts. 64 * 65 * @param real the real part 66 * @param imaginary the imaginary part 67 */ 68 public Complex(double real, double imaginary) { 69 super(); 70 this.real = real; 71 this.imaginary = imaginary; 72 } 73 74 /** 75 * Return the absolute value of this complex number. 76 * <p> 77 * Returns <code>NaN</code> if either real or imaginary part is 78 * <code>NaN</code> and <code>Double.POSITIVE_INFINITY</code> if 79 * neither part is <code>NaN</code>, but at least one part takes an infinite 80 * value. 81 * 82 * @return the absolute value 83 */ 84 public double abs() { 85 if (isNaN()) { 86 return Double.NaN; 87 } 88 89 if (isInfinite()) { 90 return Double.POSITIVE_INFINITY; 91 } 92 93 if (Math.abs(real) < Math.abs(imaginary)) { 94 if (imaginary == 0.0) { 95 return Math.abs(real); 96 } 97 double q = real / imaginary; 98 return (Math.abs(imaginary) * Math.sqrt(1 + q*q)); 99 } else { 100 if (real == 0.0) { 101 return Math.abs(imaginary); 102 } 103 double q = imaginary / real; 104 return (Math.abs(real) * Math.sqrt(1 + q*q)); 105 } 106 } 107 108 /** 109 * Return the sum of this complex number and the given complex number. 110 * <p> 111 * Uses the definitional formula 112 * <pre> 113 * (a + bi) + (c + di) = (a+c) + (b+d)i 114 * </pre> 115 * <p> 116 * If either this or <code>rhs</code> has a NaN value in either part, 117 * {@link #NaN} is returned; otherwise Inifinite and NaN values are 118 * returned in the parts of the result according to the rules for 119 * {@link java.lang.Double} arithmetic. 120 * 121 * @param rhs the other complex number 122 * @return the complex number sum 123 * @throws NullPointerException if <code>rhs</code> is null 124 */ 125 public Complex add(Complex rhs) { 126 return new Complex(real + rhs.getReal(), 127 imaginary + rhs.getImaginary()); 128 } 129 130 /** 131 * Return the conjugate of this complex number. The conjugate of 132 * "A + Bi" is "A - Bi". 133 * <p> 134 * {@link #NaN} is returned if either the real or imaginary 135 * part of this Complex number equals <code>Double.NaN</code>. 136 * <p> 137 * If the imaginary part is infinite, and the real part is not NaN, 138 * the returned value has infinite imaginary part of the opposite 139 * sign - e.g. the conjugate of <code>1 + POSITIVE_INFINITY i</code> 140 * is <code>1 - NEGATIVE_INFINITY i</code> 141 * 142 * @return the conjugate of this Complex object 143 */ 144 public Complex conjugate() { 145 if (isNaN()) { 146 return NaN; 147 } 148 return new Complex(real, -imaginary); 149 } 150 151 /** 152 * Return the quotient of this complex number and the given complex number. 153 * <p> 154 * Implements the definitional formula 155 * <pre><code> 156 * a + bi ac + bd + (bc - ad)i 157 * ----------- = ------------------------- 158 * c + di c<sup>2</sup> + d<sup>2</sup> 159 * </code></pre> 160 * but uses 161 * <a href="http://doi.acm.org/10.1145/1039813.1039814"> 162 * prescaling of operands</a> to limit the effects of overflows and 163 * underflows in the computation. 164 * <p> 165 * Infinite and NaN values are handled / returned according to the 166 * following rules, applied in the order presented: 167 * <ul> 168 * <li>If either this or <code>rhs</code> has a NaN value in either part, 169 * {@link #NaN} is returned.</li> 170 * <li>If <code>rhs</code> equals {@link #ZERO}, {@link #NaN} is returned. 171 * </li> 172 * <li>If this and <code>rhs</code> are both infinite, 173 * {@link #NaN} is returned.</li> 174 * <li>If this is finite (i.e., has no infinite or NaN parts) and 175 * <code>rhs</code> is infinite (one or both parts infinite), 176 * {@link #ZERO} is returned.</li> 177 * <li>If this is infinite and <code>rhs</code> is finite, NaN values are 178 * returned in the parts of the result if the {@link java.lang.Double} 179 * rules applied to the definitional formula force NaN results.</li> 180 * </ul> 181 * 182 * @param rhs the other complex number 183 * @return the complex number quotient 184 * @throws NullPointerException if <code>rhs</code> is null 185 */ 186 public Complex divide(Complex rhs) { 187 if (isNaN() || rhs.isNaN()) { 188 return NaN; 189 } 190 191 double c = rhs.getReal(); 192 double d = rhs.getImaginary(); 193 if (c == 0.0 && d == 0.0) { 194 return NaN; 195 } 196 197 if (rhs.isInfinite() && !isInfinite()) { 198 return ZERO; 199 } 200 201 if (Math.abs(c) < Math.abs(d)) { 202 if (d == 0.0) { 203 return new Complex(real/c, imaginary/c); 204 } 205 double q = c / d; 206 double denominator = c * q + d; 207 return new Complex((real * q + imaginary) / denominator, 208 (imaginary * q - real) / denominator); 209 } else { 210 if (c == 0.0) { 211 return new Complex(imaginary/d, -real/c); 212 } 213 double q = d / c; 214 double denominator = d * q + c; 215 return new Complex((imaginary * q + real) / denominator, 216 (imaginary - real * q) / denominator); 217 } 218 } 219 220 /** 221 * Test for the equality of two Complex objects. 222 * <p> 223 * If both the real and imaginary parts of two Complex numbers 224 * are exactly the same, and neither is <code>Double.NaN</code>, the two 225 * Complex objects are considered to be equal. 226 * <p> 227 * All <code>NaN</code> values are considered to be equal - i.e, if either 228 * (or both) real and imaginary parts of the complex number are equal 229 * to <code>Double.NaN</code>, the complex number is equal to 230 * <code>Complex.NaN</code>. 231 * 232 * @param other Object to test for equality to this 233 * @return true if two Complex objects are equal, false if 234 * object is null, not an instance of Complex, or 235 * not equal to this Complex instance 236 * 237 */ 238 public boolean equals(Object other) { 239 boolean ret; 240 241 if (this == other) { 242 ret = true; 243 } else if (other == null) { 244 ret = false; 245 } else { 246 try { 247 Complex rhs = (Complex)other; 248 if (rhs.isNaN()) { 249 ret = this.isNaN(); 250 } else { 251 ret = (Double.doubleToRawLongBits(real) == 252 Double.doubleToRawLongBits(rhs.getReal())) && 253 (Double.doubleToRawLongBits(imaginary) == 254 Double.doubleToRawLongBits(rhs.getImaginary())); 255 } 256 } catch (ClassCastException ex) { 257 // ignore exception 258 ret = false; 259 } 260 } 261 262 return ret; 263 } 264 265 /** 266 * Get a hashCode for the complex number. 267 * <p> 268 * All NaN values have the same hash code. 269 * 270 * @return a hash code value for this object 271 */ 272 public int hashCode() { 273 if (isNaN()) { 274 return 7; 275 } 276 return 37 * (17 * MathUtils.hash(imaginary) + 277 MathUtils.hash(real)); 278 } 279 280 /** 281 * Access the imaginary part. 282 * 283 * @return the imaginary part 284 */ 285 public double getImaginary() { 286 return imaginary; 287 } 288 289 /** 290 * Access the real part. 291 * 292 * @return the real part 293 */ 294 public double getReal() { 295 return real; 296 } 297 298 /** 299 * Returns true if either or both parts of this complex number is NaN; 300 * false otherwise 301 * 302 * @return true if either or both parts of this complex number is NaN; 303 * false otherwise 304 */ 305 public boolean isNaN() { 306 return Double.isNaN(real) || Double.isNaN(imaginary); 307 } 308 309 /** 310 * Returns true if either the real or imaginary part of this complex number 311 * takes an infinite value (either <code>Double.POSITIVE_INFINITY</code> or 312 * <code>Double.NEGATIVE_INFINITY</code>) and neither part 313 * is <code>NaN</code>. 314 * 315 * @return true if one or both parts of this complex number are infinite 316 * and neither part is <code>NaN</code> 317 */ 318 public boolean isInfinite() { 319 return !isNaN() && 320 (Double.isInfinite(real) || Double.isInfinite(imaginary)); 321 } 322 323 /** 324 * Return the product of this complex number and the given complex number. 325 * <p> 326 * Implements the definitional formula: 327 * <pre><code> 328 * (a + bi)(c + di) = (ac - bd) + (ad + bc)i 329 * </code></pre> 330 * <p> 331 * Returns {@link #NaN} if either this or <code>rhs</code> has one or more 332 * NaN parts. 333 * <p> 334 * Returns NaN or infinite values in components of the result per the 335 * definitional formula and and the rules for {@link java.lang.Double} 336 * arithmetic. Examples: 337 * <pre><code> 338 * (1 + i) (INF + i) = INF + INFi 339 * (1 + INFi) (1 - INFi) = INF + NaNi 340 * (-INF + -INFi)(1 + NaNi) = NaN + NaNi 341 * </code></pre> 342 * 343 * @param rhs the other complex number 344 * @return the complex number product 345 * @throws NullPointerException if <code>rhs</code> is null 346 */ 347 public Complex multiply(Complex rhs) { 348 if (isNaN() || rhs.isNaN()) { 349 return NaN; 350 } 351 return new Complex(real * rhs.real - imaginary * rhs.imaginary, 352 real * rhs.imaginary + imaginary * rhs.real); 353 } 354 355 /** 356 * Return the additive inverse of this complex number. 357 * <p> 358 * Returns <code>Complex.NaN</code> if either real or imaginary 359 * part of this Complex number equals <code>Double.NaN</code>. 360 * 361 * @return the negation of this complex number 362 */ 363 public Complex negate() { 364 if (isNaN()) { 365 return NaN; 366 } 367 368 return new Complex(-real, -imaginary); 369 } 370 371 /** 372 * Return the difference between this complex number and the given complex 373 * number. 374 * <p> 375 * Uses the definitional formula 376 * <pre> 377 * (a + bi) - (c + di) = (a-c) + (b-d)i 378 * </pre> 379 * <p> 380 * If either this or <code>rhs</code> has a NaN value in either part, 381 * {@link #NaN} is returned; otherwise inifinite and NaN values are 382 * returned in the parts of the result according to the rules for 383 * {@link java.lang.Double} arithmetic. 384 * 385 * @param rhs the other complex number 386 * @return the complex number difference 387 * @throws NullPointerException if <code>rhs</code> is null 388 */ 389 public Complex subtract(Complex rhs) { 390 if (isNaN() || rhs.isNaN()) { 391 return NaN; 392 } 393 394 return new Complex(real - rhs.getReal(), 395 imaginary - rhs.getImaginary()); 396 } 397 }