Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create Complex Numbers Utils #5128

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
106bd45
Update directory
rozi26 Apr 29, 2024
191697c
Update directory
rozi26 Apr 29, 2024
de68d67
add basic complex numbers methods and unit tests
rozi26 Apr 30, 2024
fcfeea7
add trigs
rozi26 Apr 30, 2024
175e125
add links to sources
rozi26 Apr 30, 2024
6ce45ca
add exceptions for the trigonometric functions
rozi26 Apr 30, 2024
61b3cc5
format the code using clang
rozi26 Apr 30, 2024
f6fe7c2
add unit tests
rozi26 Apr 30, 2024
0f6c801
Merge branch 'master' of https://github.com/rozi26/java_algo_fork1
rozi26 Apr 30, 2024
2764454
run clang format on the test file
rozi26 Apr 30, 2024
8ecf1ff
Merge branch 'master' into feature/improve_code_look
rozi26 May 2, 2024
b813d2d
Merge branch 'feature/improve_code_look' of https://github.com/rozi26…
rozi26 May 2, 2024
b30eaab
temp changes
rozi26 May 2, 2024
0bf5319
make the code ready for pull request
rozi26 May 2, 2024
799ba61
make the code ready for pull request
rozi26 May 2, 2024
d5d6ee0
change the order or final static
rozi26 May 2, 2024
3495410
Update src/test/java/com/thealgorithms/maths/ComplexNumberUtilTest.java
rozi26 May 7, 2024
95cae76
Update src/main/java/com/thealgorithms/maths/ComplexNumberUtil.java
rozi26 May 7, 2024
592f443
Update src/main/java/com/thealgorithms/maths/ComplexNumberUtil.java
rozi26 May 7, 2024
6f12753
Update src/main/java/com/thealgorithms/maths/ComplexNumberUtil.java
rozi26 May 7, 2024
428b97d
Merge branch 'master' into feature/improve_code_look
rozi26 May 7, 2024
d629eec
Update directory
rozi26 May 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@
* [CircularConvolutionFFT](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/CircularConvolutionFFT.java)
* [CollatzConjecture](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/CollatzConjecture.java)
* [Combinations](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/Combinations.java)
* [ComplexNumberUtil](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/ComplexNumberUtil.java)
* [Convolution](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/Convolution.java)
* [ConvolutionFFT](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/ConvolutionFFT.java)
* [CrossCorrelation](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/CrossCorrelation.java)
Expand Down Expand Up @@ -726,10 +727,12 @@
* [CeilTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/CeilTest.java)
* [CollatzConjectureTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/CollatzConjectureTest.java)
* [CombinationsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/CombinationsTest.java)
* [ComplexNumberUtilTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/ComplexNumberUtilTest.java)
* [CrossCorrelationTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/CrossCorrelationTest.java)
* [DigitalRootTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/DigitalRootTest.java)
* [DistanceFormulaTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/DistanceFormulaTest.java)
* [DudeneyNumberTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/DudeneyNumberTest.java)
* [FactorialRecursionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/FactorialRecursionTest.java)
* [FactorialTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/FactorialTest.java)
* [FastInverseSqrtTests](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/FastInverseSqrtTests.java)
* [FFTTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/FFTTest.java)
Expand Down Expand Up @@ -762,7 +765,9 @@
* [MillerRabinPrimalityCheckTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/MillerRabinPrimalityCheckTest.java)
* [MinValueTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/MinValueTest.java)
* [MobiusFunctionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/MobiusFunctionTest.java)
* [ModeTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/ModeTest.java)
* [NthUglyNumberTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/NthUglyNumberTest.java)
* [NumberOfDigitsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/NumberOfDigitsTest.java)
* [PalindromeNumberTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/PalindromeNumberTest.java)
* [ParseIntegerTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/ParseIntegerTest.java)
* [PascalTriangleTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/PascalTriangleTest.java)
Expand Down
264 changes: 264 additions & 0 deletions src/main/java/com/thealgorithms/maths/ComplexNumberUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
package com.thealgorithms.maths;

public class ComplexNumberUtil {

public static class ComplexNumber {
public final double REAL;
public final double IMAGINARY;

public ComplexNumber(double real, double imaginary) {
REAL = real;
IMAGINARY = imaginary;
}

@Override
public boolean equals(Object obj) {
if (obj instanceof ComplexNumber num) {
return this.REAL == num.REAL && this.IMAGINARY == num.IMAGINARY;
}

return super.equals(obj);
}

@Override
public String toString() {
return REAL + ((IMAGINARY < 0) ? (" - " + Math.abs(IMAGINARY)) : (" + " + IMAGINARY)) + "i";
}
}

public static final ComplexNumber ZERO = new ComplexNumber(0, 0);
public static final ComplexNumber ONE = new ComplexNumber(1, 0);
public static final ComplexNumber TWO = new ComplexNumber(2, 0);
public static final ComplexNumber PLUS_I = new ComplexNumber(0, 1);
public static final ComplexNumber MINUS_I = new ComplexNumber(0, -1);

/**
* add two complex numbers
* @param num1 the first complex number
* @param num2 the second complex number
* @return the sum of num1 and num2
*/
public static ComplexNumber add(ComplexNumber num1, ComplexNumber num2) {
return new ComplexNumber(num1.REAL + num2.REAL, num1.IMAGINARY + num2.IMAGINARY);
}
Comment on lines +41 to +43
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you decide to make it a static method? In the standard implementation of Complex add is an object method.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to make it a static method for a few reasons:

Uniformity in Code: The file MatrixUtil.java, which is similar to this, uses static methods for the operations.
Ease of Expansion: Creating independent static methods makes it easier to add more advanced operations for complex numbers than integrating additional code into the ComplexNumber class itself.
Clarity: I find it easier to conceptualize operations as direct interactions between two entities, A and B (i.e., how do you add them), rather than how one adds B to A.

These are my reasons, but if you believe it should be an instance method, I would be happy to make that change.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making them static you loose all of the object oriented magic. The whole thing could be then simpler, because the ComplexNumberUtil would not be needed. Furthermore, you have marked both of the fields REAL and IMAGINARY as final, so it is pretty clear that the add method will not change them.


/**
* Subtracts the second complex number from the first complex number.
*
* @param num1 the first complex number
* @param num2 the second complex number
* @return the result of subtracting num2 from num1
*/
public static ComplexNumber subtract(ComplexNumber num1, ComplexNumber num2) {
return new ComplexNumber(num1.REAL - num2.REAL, num1.IMAGINARY - num2.IMAGINARY);
}

/**
* Multiplies two complex numbers.
*
* @param num1 the first complex number
* @param num2 the second complex number
* @return the product of num1 and num2
* @link <a href="https://en.wikipedia.org/wiki/Complex_number#Multiplication">...</a>
*/
public static ComplexNumber multiply(ComplexNumber num1, ComplexNumber num2) {
return new ComplexNumber(num1.REAL * num2.REAL - num1.IMAGINARY * num2.IMAGINARY, num1.REAL * num2.IMAGINARY + num1.IMAGINARY * num2.REAL);
}

/**
* Divides the first complex number by the second complex number.
*
* @param num1 the numerator complex number
* @param num2 the denominator complex number
* @return the result of dividing num1 by num2
* @throws RuntimeException if the divisor (num2) is zero
* @link <a href="https://en.wikipedia.org/wiki/Complex_number#Complex_conjugate,_absolute_value_and_argument">...</a>
*/
public static ComplexNumber divide(ComplexNumber num1, ComplexNumber num2) {
final double divisor = num2.REAL * num2.REAL + num2.IMAGINARY * num2.IMAGINARY;
if (divisor == 0) {
throw new RuntimeException("Cannot divide by zero");
}

return new ComplexNumber((num1.REAL * num2.REAL + num1.IMAGINARY * num2.IMAGINARY) / divisor, (num1.IMAGINARY * num2.REAL - num1.REAL * num2.IMAGINARY) / divisor);
}

/**
* Computes the absolute value (magnitude) of a complex number.
*
* @param num the complex number
* @return the absolute value of num
* @link <a href="https://en.wikipedia.org/wiki/Complex_number#Complex_conjugate,_absolute_value_and_argument">...</a>
*/
public static double abs(ComplexNumber num) {
return Math.sqrt(num.REAL * num.REAL + num.IMAGINARY * num.IMAGINARY);
}

/**
* Computes the exponential function of a complex number.
*
* @param num the complex number
* @return e raised to the power of num
* @link <a href="https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex">...</a>
*/
public static ComplexNumber exp(ComplexNumber num) {
final double coefficient = Math.exp(num.REAL);
return new ComplexNumber(coefficient * Math.cos(num.IMAGINARY), coefficient * Math.sin(num.IMAGINARY));
}

/**
* Computes the natural logarithm of a complex number.
rozi26 marked this conversation as resolved.
Show resolved Hide resolved
*
* @param num the complex number
* @return the natural logarithm of num
* @throws RuntimeException if num is zero
* @link <a href="https://en.wikipedia.org/wiki/Complex_logarithm#Calculating_the_principal_value">...</a>
*/
public static ComplexNumber ln(ComplexNumber num) {
rozi26 marked this conversation as resolved.
Show resolved Hide resolved
if (num.equals(ZERO)) {
throw new RuntimeException("Cannot take the logarithm of zero");
}

return new ComplexNumber(Math.log(abs(num)), Math.atan2(num.IMAGINARY, num.REAL));
}

/**
* Computes the power of a complex number raised to another complex number.
*
* @param num1 the base complex number
* @param num2 the exponent complex number
* @return num1 raised to the power of num2
* link <a href="https://en.wikipedia.org/wiki/Exponentiation#Complex_exponents_with_a_positive_real_base">...</a>
*/
public static ComplexNumber pow(ComplexNumber num1, ComplexNumber num2) {
if (num1.equals(ZERO)) {
return num2.equals(ZERO) ? ONE : ZERO;
}

return exp(multiply(ln(num1), num2));
}

/**
* Computes the square root of a complex number.
rozi26 marked this conversation as resolved.
Show resolved Hide resolved
*
* @param num the complex number
* @return the square root of num
*/
public static ComplexNumber sqrt(ComplexNumber num) {
return pow(num, new ComplexNumber(0.5, 0));
}

/**
* Computes the sine of a complex number.
*
* @param num the complex number
* @return the sine of num
* @link <a href="https://en.wikipedia.org/wiki/Trigonometric_functions#Relationship_to_exponential_function_">...</a>(Euler's_formula)
*/
public static ComplexNumber sin(ComplexNumber num) {
ComplexNumber exp1 = exp(multiply(num, PLUS_I));
ComplexNumber exp2 = exp(multiply(num, MINUS_I));
return divide(subtract(exp1, exp2), multiply(new ComplexNumber(2, 0), PLUS_I));
}

/**
* Computes the cosine of a complex number.
*
* @param num the complex number
* @return the cosine of num
* @link <a href="https://en.wikipedia.org/wiki/Trigonometric_functions#Relationship_to_exponential_function_">...</a>(Euler's_formula)
*/
public static ComplexNumber cos(ComplexNumber num) {
ComplexNumber exp1 = exp(multiply(num, PLUS_I));
ComplexNumber exp2 = exp(multiply(num, MINUS_I));
return divide(add(exp1, exp2), TWO);
}

/**
* Computes the tangent of a complex number.
*
* @param num the complex number
* @return the tangent of num
* @throws RuntimeException if <code>num.real = pi*(n+0.5)</code>
* @link <a href="https://en.wikipedia.org/wiki/Trigonometric_functions#Right-angled_triangle_definitions">...</a>
*/
public static ComplexNumber tan(ComplexNumber num) {
if (num.REAL % Math.PI == Math.PI / 2) {
throw new RuntimeException("Cannot take the tan of a number where the real part can be expressed as pi*(n+0.5)");
}

return divide(sin(num), cos(num));
}

/**
* Computes the cotangent of a complex number.
*
* @param num the complex number
* @return the cotangent of num
* @throws RuntimeException if <code>num.real = pi*n</code>
* @link <a href="https://en.wikipedia.org/wiki/Trigonometric_functions#Right-angled_triangle_definitions">...</a>
*/
public static ComplexNumber cot(ComplexNumber num) {
if (num.REAL % Math.PI == 0) {
throw new RuntimeException("Cannot take the cot of number with real part dividable by pi");
}

return divide(cos(num), sin(num));
}

/**
* Computes the arcsine of a complex number.
*
* @param num the complex number
* @return the arcsine of num
* @link <a href="https://en.wikipedia.org/wiki/Inverse_trigonometric_functions#Extension_to_the_complex_plane">...</a>
*/
public static ComplexNumber arcsin(ComplexNumber num) {
ComplexNumber temp = sqrt(subtract(ONE, multiply(num, num)));
return multiply(MINUS_I, ln(add(multiply(PLUS_I, num), temp)));
}

/**
* Computes the arccosine of a complex number.
*
* @param num the complex number
* @return the arccosine of num
* @link <a href="https://en.wikipedia.org/wiki/Inverse_trigonometric_functions#Extension_to_the_complex_plane">...</a>
*/
public static ComplexNumber arccos(ComplexNumber num) {
ComplexNumber temp = sqrt(subtract(ONE, multiply(num, num)));
return multiply(MINUS_I, ln(add(num, multiply(temp, PLUS_I))));
}

/**
* Computes the arctangent of a complex number.
*
* @param num the complex number
* @return the arctangent of num
* @throws RuntimeException if <code>num=i</code> or <code>num=-i</code>
* @link <a href="https://en.wikipedia.org/wiki/Inverse_trigonometric_functions#Extension_to_the_complex_plane">...</a>
*/
public static ComplexNumber arctan(ComplexNumber num) {
if (num.equals(PLUS_I) || num.equals(MINUS_I)) {
throw new RuntimeException("Cannot take the arctan of " + num);
}

return multiply(divide(MINUS_I, TWO), ln(divide(subtract(PLUS_I, num), add(PLUS_I, num))));
}

/**
* Computes the arccotangent of a complex number.
*
* @param num the complex number
* @return the arccotangent of num
* @throws RuntimeException if <code>num=i</code> or <code>num=-i</code>
* @link <a href="https://en.wikipedia.org/wiki/Inverse_trigonometric_functions#Extension_to_the_complex_plane">...</a>
*/
public static ComplexNumber arccot(ComplexNumber num) {
if (num.equals(PLUS_I) || num.equals(MINUS_I)) {
throw new RuntimeException("Cannot take the arccot of " + num);
}

return multiply(divide(MINUS_I, TWO), ln(divide(add(num, PLUS_I), subtract(num, PLUS_I))));
}
}