View Javadoc
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 }