Complex Math¶
Most mathematical operations on real numbers have a compatible implementation on complex numbers. Compatible in this case means that the result for an argument that happens to be real, matches the result of the real version of the function as long as the function has a defined result for the argument. There is a lot more to it. One way to derive compatible complex versions of such functions is to perform Taylor series expansion and then use those with complex arguments.
Principal square root¶
Similar to real numbers, the square root of a complex number is a complex number that, when multiplied to itself yields the orginal number. In the real number case, what we call the square root is actually the principal square root. E.g. the square root of 16 is 4. The other (non-principal) value that, when multiplied with itself yields 16 is -4. In the complex number space, there are also two solutions to the equation s * s = z
. the principal square root of a complex number is the one that has the highest real component.
Complex z = new Complex(3, -5);
System.out.println(z);
System.out.println(ComplexMath.sqrt(z));
Outputs:
Complex [re=3.0, im=-5.0]
Complex [re=2.101303392521568, im=-1.1897377641407583]
The other complex number that, when squared, yields the same result can be obtained by rotating by π, or by negating (multiplying by -1.0
). Ignoring rounding errors (due to the limited precision of the internal representation of π) the results of negating or rotating by π are identical. As the internal representation stores the real and imaginary components, negating is both faster and more accurate:
System.out.println(ComplexMath.sqrt(z).rotate(Math.PI));
System.out.println(ComplexMath.sqrt(z).times(-1));
Outputs
Complex [re=-2.101303392521568, im=1.1897377641407585]
Complex [re=-2.101303392521568, im=1.1897377641407583]
Principal cube root¶
Unlike the real number space, the cube root of a complex number actually has three candidate values. The one with the highest real component is the principal cube root. The others can be obtained by rotating over 2 * π / 3
and 4 * π / 3
:
System.out.println(ComplexMath.cbrt(z));
System.out.println(ComplexMath.cbrt(z).rotate(2 * Math.PI / 3));
System.out.println(ComplexMath.cbrt(z).rotate(4 * Math.PI / 3));
Outputs
Complex [re=3.0, im=-5.0]
Complex [re=1.6947703899454605, im=-0.6061065307696287]
Complex [re=-0.32248154192657685, im=1.7707674766592425]
Complex [re=-1.3722888480188837, im=-1.1646609458896129]
Exponential function¶
The exponential function raises Eulers constant e
(about 2.7182818284590452354) to a specified power. The normal implementation takes a real argument. The implementation in ComplexMath
takes a Complex
argument:
Complex z = new Complex(3, -5);
System.out.println(z);
System.out.println(ComplexMath.exp(z));
Outputs:
Complex [re=3.0, im=-5.0]
Complex [re=5.697507299833739, im=19.26050892528742]
Natural logarithm¶
The inverse of the exponential function is the natural logarithm. In the java Math
library, the natural logarithm function is named log
. We find this utterly confusing and elected to name the equivalent function for complex numbers ln
:
Complex z = new Complex(3, -5);
System.out.println(z);
System.out.println(ComplexMath.ln(z));
Outputs:
Complex [re=3.0, im=-5.0]
Complex [re=1.7631802623080808, im=-1.0303768265243125]
Sine, cosine, tangent¶
The trigonometric functions sine, cosine and tangent have counterparts in the complex domain:
Complex z = new Complex(3, -5);
System.out.println(z);
System.out.println(ComplexMath.sin(z));
System.out.println(ComplexMath.cos(z));
System.out.println(ComplexMath.tan(z));
Unlike these functions for real values; the results of sine and cosine are not limited to [-1, +1]
:
Complex [re=3.0, im=-5.0]
Complex [re=10.472508533940392, im=73.46062169567367]
Complex [re=-73.46729221264526, im=10.471557674805572]
Complex [re=-2.5368676207676027E-5, im=-0.9999128201513536]
Inverse sine, inverse cosine, inverse tangent¶
The inverse functions are named asin
, acos
and atan
(in literature these are sometimes named arcsin
, arccos
and arctan
):
Complex z = new Complex(3, -5);
System.out.println(z);
System.out.println(ComplexMath.asin(z));
System.out.println(ComplexMath.acos(z));
System.out.println(ComplexMath.atan(z));
Outputs:
Complex [re=3.0, im=-5.0]
Complex [re=0.5339990695941685, im=-2.4598315216234345]
Complex [re=1.036797257200728, im=2.4598315216234345]
Complex [re=1.4808695768986575, im=-0.14694666622552974]
Hyperbolic sine, hyperbolic cosine, hyperbolic tangent¶
These hyperbolic functions are named sinh
, cosh
and tanh
:
Complex z = new Complex(3, -5);
System.out.println(z);
System.out.println(ComplexMath.sinh(z));
System.out.println(ComplexMath.cosh(z));
System.out.println(ComplexMath.tanh(z));
Outputs:
Complex [re=3.0, im=-5.0]
Complex [re=2.841692295606352, im=9.654125476854839]
Complex [re=2.855815004227387, im=9.606383448432581]
Complex [re=1.0041647106948153, im=0.002708235836224072]
Inverse hyperbolic sine, inverse hyperbolic cosine, inverse hyperbolic tangent¶
Even though the inverse hyperbolic functions are not implemented in the java Math
library we elected to add the complex versions to our ComplexMath
library:
Complex z = new Complex(3, -5);
System.out.println(z);
System.out.println(ComplexMath.asinh(z));
System.out.println(ComplexMath.acosh(z));
System.out.println(ComplexMath.atanh(z));
Outputs:
Complex [re=3.0, im=-5.0]
Complex [re=2.4529137425028096, im=-1.0238217465117878]
Complex [re=2.4598315216234345, im=-1.036797257200728]
Complex [re=0.08656905917945844, im=-1.4236790442393028]