1 /* 2 * Copyright (C) 2012 Alberto Irurueta Carro (alberto@irurueta.com) 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 package com.irurueta.algebra; 17 18 import java.io.Serializable; 19 import java.util.Objects; 20 21 /** 22 * Class defining a Complex number having real and imaginary parts. 23 */ 24 public class Complex implements Serializable, Cloneable { 25 26 /** 27 * Real part of the complex number. 28 */ 29 private double real; 30 31 /** 32 * Imaginary part of the complex number. 33 */ 34 private double imaginary; 35 36 /** 37 * Constructor. Sets both real and imaginary parts to zero. 38 */ 39 public Complex() { 40 real = imaginary = 0.0; 41 } 42 43 /** 44 * Creates new Complex number having provided real value and an 45 * imaginary part equal to zero. 46 * 47 * @param real Real part. 48 */ 49 public Complex(final double real) { 50 this.real = real; 51 imaginary = 0.0; 52 } 53 54 /** 55 * Creates new Complex number having provided real and imaginary parts. 56 * 57 * @param real Real part. 58 * @param imaginary Imaginary part. 59 */ 60 public Complex(final double real, final double imaginary) { 61 this.real = real; 62 this.imaginary = imaginary; 63 } 64 65 /** 66 * Creates new Complex number by copying provided value. 67 * 68 * @param initValue Initial value to be copied. 69 */ 70 public Complex(final Complex initValue) { 71 this.real = initValue.real; 72 this.imaginary = initValue.imaginary; 73 } 74 75 /** 76 * Returns real part of complex number. 77 * 78 * @return Real part. 79 */ 80 public double getReal() { 81 return real; 82 } 83 84 /** 85 * Sets real part of complex number. 86 * 87 * @param real Real part. 88 */ 89 public void setReal(final double real) { 90 this.real = real; 91 } 92 93 /** 94 * Returns imaginary part of complex number. 95 * 96 * @return Imaginary part. 97 */ 98 public double getImaginary() { 99 return imaginary; 100 } 101 102 /** 103 * Sets imaginary part of complex number. 104 * 105 * @param imaginary Imaginary part. 106 */ 107 public void setImaginary(final double imaginary) { 108 this.imaginary = imaginary; 109 } 110 111 /** 112 * Sets both real and imaginary parts of this complex number. 113 * 114 * @param real Real part. 115 * @param imaginary Imaginary part. 116 */ 117 public void setRealAndImaginary(final double real, final double imaginary) { 118 this.real = real; 119 this.imaginary = imaginary; 120 } 121 122 /** 123 * Returns modulus of current complex number, which is equal to the 124 * length of the vector formed by the real and imaginary parts. 125 * 126 * @return Modulus. 127 */ 128 public double getModulus() { 129 return Math.sqrt(real * real + imaginary * imaginary); 130 } 131 132 /** 133 * Returns phase of current complex number, in radians. 134 * Phase is equal to the angle of the vector formed by the real and 135 * imaginary parts. 136 * 137 * @return Phase in radians. 138 */ 139 public double getPhase() { 140 return Math.atan2(imaginary, real); 141 } 142 143 /** 144 * Sets both modulus and phase of this complex number. 145 * 146 * @param modulus Modulus to be set. 147 * @param phase Phase to be set in radians. 148 */ 149 public void setModulusAndPhase(final double modulus, final double phase) { 150 real = modulus * Math.cos(phase); 151 imaginary = modulus * Math.sin(phase); 152 } 153 154 /** 155 * Computes the complex conjugate of this instance and stores the 156 * result into provided complex instance. 157 * The complex conjugate is obtained by negating the sign of the 158 * imaginary part. 159 * 160 * @param result Complex instance where conjugate is stored. 161 */ 162 public void conjugate(final Complex result) { 163 result.real = real; 164 result.imaginary = -imaginary; 165 } 166 167 /** 168 * Computes the complex conjugate of this instance and returns the 169 * result as a new instance. 170 * 171 * @return Complex conjugate. 172 */ 173 public Complex conjugateAndReturnNew() { 174 final var result = new Complex(); 175 conjugate(result); 176 return result; 177 } 178 179 /** 180 * Changes this instance into its complex conjugate. 181 */ 182 public void conjugate() { 183 conjugate(this); 184 } 185 186 /** 187 * Adds this instance with provided complex value and stores the result 188 * in provided instance 189 * 190 * @param other Complex to be added to current instance. 191 * @param result Complex instance where result is stored. 192 */ 193 public void add(final Complex other, final Complex result) { 194 result.real = real + other.real; 195 result.imaginary = imaginary + other.imaginary; 196 } 197 198 /** 199 * Adds this instance to provided complex and returns the result as a new 200 * instance. 201 * 202 * @param other Complex to be added to current instance. 203 * @return Result of summation. 204 */ 205 public Complex addAndReturnNew(final Complex other) { 206 final var result = new Complex(); 207 add(other, result); 208 return result; 209 } 210 211 /** 212 * Adds provided complex into this instance 213 * 214 * @param other Complex to be added to current instance. 215 */ 216 public void add(final Complex other) { 217 add(other, this); 218 } 219 220 /** 221 * Subtracts provided instance from this instance and stores the result 222 * in provided instance. 223 * 224 * @param other Complex to be subtracted from this instance. 225 * @param result Complex instance where result is stored. 226 */ 227 public void subtract(final Complex other, final Complex result) { 228 result.real = real - other.real; 229 result.imaginary = imaginary - other.imaginary; 230 } 231 232 /** 233 * Subtracts provided instance from this instance and returns the result 234 * as a new instance 235 * 236 * @param other Complex to be subtracted from current instance. 237 * @return Result of subtraction. 238 */ 239 public Complex subtractAndReturnNew(final Complex other) { 240 final var result = new Complex(); 241 subtract(other, result); 242 return result; 243 } 244 245 /** 246 * Subtracts provided complex from this instance. 247 * 248 * @param other Complex to be subtracted from current instance. 249 */ 250 public void subtract(final Complex other) { 251 subtract(other, this); 252 } 253 254 /** 255 * Multiplies this instance with provided instance and stores the result 256 * in provided instance. 257 * 258 * @param other Complex to be multiplied to this instance 259 * @param result Complex instance where result is stored. 260 */ 261 public void multiply(final Complex other, final Complex result) { 262 final var tmpReal = (real * other.real) - (imaginary * other.imaginary); 263 final var tmpImaginary = (imaginary * other.real) + (real * other.imaginary); 264 265 result.real = tmpReal; 266 result.imaginary = tmpImaginary; 267 } 268 269 /** 270 * Multiplies provided instance with this instance and returns the result 271 * as a new instance. 272 * 273 * @param other Complex to be multiplied to current instance. 274 * @return Result of multiplication. 275 */ 276 public Complex multiplyAndReturnNew(final Complex other) { 277 final var result = new Complex(); 278 multiply(other, result); 279 return result; 280 } 281 282 /** 283 * Multiplies provided complex with this instance. 284 * 285 * @param other Complex to be multiplied to this instance. 286 */ 287 public void multiply(final Complex other) { 288 multiply(other, this); 289 } 290 291 /** 292 * Divides this instance by provided instance and stores the result in 293 * provided instance. 294 * 295 * @param other Complex to divide this instance by. 296 * @param result Complex instance where result is stored. 297 */ 298 public void divide(final Complex other, final Complex result) { 299 final var tmpReal = ((real * other.real) + (imaginary * other.imaginary)) 300 / ((other.real * other.real) + (other.imaginary * other.imaginary)); 301 final var tmpImaginary = ((imaginary * other.real) - (real * other.imaginary)) 302 / ((other.real * other.real) + (other.imaginary * other.imaginary)); 303 304 result.real = tmpReal; 305 result.imaginary = tmpImaginary; 306 } 307 308 /** 309 * Divides this instance by provided instance and returns the result as 310 * a new instance. 311 * 312 * @param other Complex to divide this instance by. 313 * @return Result of division. 314 */ 315 public Complex divideAndReturnNew(final Complex other) { 316 final var result = new Complex(); 317 divide(other, result); 318 return result; 319 } 320 321 /** 322 * Divides this instance by provided complex. 323 * 324 * @param other Complex to divide this instance by. 325 */ 326 public void divide(final Complex other) { 327 divide(other, this); 328 } 329 330 /** 331 * Multiplies this instance by provided scalar value (multiplying both 332 * real and imaginary parts by provided value) and stores the result in 333 * provided complex instance. 334 * 335 * @param scalar Value to multiply this instance by. 336 * @param result Complex where result of multiplication is stored. 337 */ 338 public void multiplyByScalar(final double scalar, final Complex result) { 339 result.real = scalar * real; 340 result.imaginary = scalar * imaginary; 341 } 342 343 /** 344 * Multiplies this instance by provided scalar value (multiplying both 345 * real and imaginary parts by provided value) and returns the result 346 * as a new instance. 347 * 348 * @param scalar Value to multiply this instance by. 349 * @return Result of multiplication by scalar. 350 */ 351 public Complex multiplyByScalarAndReturnNew(final double scalar) { 352 final var result = new Complex(); 353 multiplyByScalar(scalar, result); 354 return result; 355 } 356 357 /** 358 * Multiplies this instance by provided scalar 359 * 360 * @param scalar Value to multiply this instance by. 361 */ 362 public void multiplyByScalar(final double scalar) { 363 multiplyByScalar(scalar, this); 364 } 365 366 /** 367 * Computes the power of this instance by provided exponent and stores 368 * the result in provided instance. 369 * 370 * @param exponent Exponent to power this instance by. 371 * @param result Complex where the power is stored. 372 */ 373 public void pow(final double exponent, final Complex result) { 374 result.setModulusAndPhase(Math.pow(getModulus(), exponent), getPhase() * exponent); 375 } 376 377 /** 378 * Computes the power of this instance by provided exponent and returns 379 * the result as a new instance. 380 * 381 * @param exponent Exponent to power this instance by. 382 * @return Complex where the power is stored. 383 */ 384 public Complex powAndReturnNew(final double exponent) { 385 final var result = new Complex(); 386 pow(exponent, result); 387 return result; 388 } 389 390 /** 391 * Computes the power of this instance by provided exponent 392 * 393 * @param exponent Exponent to power this instance by. 394 */ 395 public void pow(final double exponent) { 396 pow(exponent, this); 397 } 398 399 /** 400 * Computes the squared root of this instance and returns the result as 401 * a new instance. 402 * 403 * @param result Complex where squared root is stored. 404 */ 405 public void sqrt(final Complex result) { 406 pow(0.5, result); 407 } 408 409 /** 410 * Computes the squared root of this instance and returns the result as a 411 * new instance. 412 * 413 * @return Squared root of this instance. 414 */ 415 public Complex sqrtAndReturnNew() { 416 final var result = new Complex(); 417 sqrt(result); 418 return result; 419 } 420 421 /** 422 * Computes the squared root of this instance 423 */ 424 public void sqrt() { 425 sqrt(this); 426 } 427 428 /** 429 * Determines whether two Complex objects are equal or not. 430 * Two Complex are considered to be equal if both their real and imaginary 431 * parts are equal. 432 * 433 * @param obj Object to compare. 434 * @return True if both Complex objects are equal. 435 */ 436 @Override 437 public boolean equals(final Object obj) { 438 if (obj == this) { 439 return true; 440 } 441 if (obj == null) { 442 return false; 443 } 444 if (!(obj instanceof Complex other)) { 445 return false; 446 } 447 448 return equals(other, 0.0); 449 } 450 451 /** 452 * Computes the hashcode of this instance. 453 * 454 * @return Hashcode 455 */ 456 @Override 457 public int hashCode() { 458 return Objects.hash(real, imaginary); 459 } 460 461 /** 462 * Determines whether two Complex objects are equal or not up to a certain 463 * level of tolerance in both their real and imaginary parts. When the 464 * difference in both their real and imaginary parts is below the tolerance 465 * level, then both instances are considered to be equal. 466 * 467 * @param other Other Complex to compare. 468 * @param tolerance Margin of tolerance. 469 * @return Returns true if both Complex instances are considered to be 470 * equal. 471 */ 472 public boolean equals(final Complex other, final double tolerance) { 473 if (Math.abs(real - other.real) > tolerance) { 474 return false; 475 } 476 return Math.abs(imaginary - other.imaginary) <= tolerance; 477 } 478 479 /** 480 * Makes a copy of this instance having the same real and imaginary parts. 481 * 482 * @return a copy of this instance. 483 * @throws CloneNotSupportedException if clone fails. 484 */ 485 @Override 486 public Complex clone() throws CloneNotSupportedException { 487 final var result = (Complex) super.clone(); 488 result.setRealAndImaginary(real, imaginary); 489 return result; 490 } 491 492 /** 493 * Copies provided value into current instance. 494 * 495 * @param value Value to copy from. 496 */ 497 public void copyFrom(final Complex value) { 498 this.real = value.real; 499 this.imaginary = value.imaginary; 500 } 501 }