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 }