Last active
November 1, 2022 02:51
-
-
Save cab1729/1349284 to your computer and use it in GitHub Desktop.
Code Samples - Core Java/Math: Complex Numbers/Functions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.Serializable; | |
import java.util.Formattable; | |
import java.util.Formatter; | |
/** | |
* Complex number class. A Complex consists of a real and imaginary | |
* part of type {@link double}.<p> | |
* | |
* Note: The methods inherited from <code>Number</code> return | |
* the value of the real part of the complex number. | |
* | |
* main reference: Schaum's Outlines - Complex Variables | |
* | |
* @author Jose Menes | |
*/ | |
public class Complex extends Number | |
implements Formattable, Serializable { | |
/** | |
* | |
*/ | |
private static final long serialVersionUID = -7417547029717136577L; | |
public static final int ZERO = 0; | |
public static final int ONE = 1; | |
public static final int NONE = -1; | |
public static final Complex I = new Complex(ZERO, ONE); | |
public static final Complex nI = new Complex(ZERO, NONE); | |
public static final Complex e = new Complex(StrictMath.E, ZERO); | |
public static final long INFINITE = Long.MAX_VALUE; | |
public Complex(double real) | |
{ | |
this(real, ZERO); | |
} | |
public Complex(double real, double imag) | |
{ | |
this.real = real; | |
this.imag = imag; | |
} | |
/** | |
* @return real part of complex number | |
*/ | |
public double real() | |
{ | |
return this.real; | |
} | |
/** | |
* @return imaginary part of complex number | |
*/ | |
public double imag() | |
{ | |
return this.imag; | |
} | |
/** | |
* add two complex numbers | |
* @param z - complex number to add to this number | |
* @return | |
*/ | |
public Complex add(Complex z) | |
{ | |
return new Complex( | |
this.real + z.real(), this.imag + z.imag()); | |
} | |
/** | |
* subtract two complex numbers | |
* @param z - complex number to subtract from this number | |
* @return | |
*/ | |
public Complex subtract(Complex z) | |
{ | |
return new Complex( | |
this.real - z.real(), this.imag - z.imag()); | |
} | |
/** | |
* multiply two complex numbers | |
* @param z - complex number to multiply by | |
* @return | |
*/ | |
public Complex multiply(Complex z) | |
{ | |
// if both Im(this) and Im(z) are zero use double arithmetic | |
if (this.imag == 0. || z.imag() == 0.) | |
{ | |
return new Complex(this.real*z.real()); | |
} | |
return new Complex( | |
(this.real*z.real()) - (this.imag* z.imag()), | |
(this.real*z.imag()) + (this.imag* z.real())); | |
} | |
/** | |
* Divide two complex numbers | |
* @param z - the complex denominator/divisor | |
* @return | |
*/ | |
public Complex divide(Complex z) | |
{ | |
double c = z.real(); | |
double d = z.imag(); | |
// check for Re,Im(z) == 0 to avoid +/-infinity in result | |
double zreal2 = 0.0; | |
if (c != 0.0) | |
{ | |
zreal2 = StrictMath.pow(c, 2.); | |
} | |
double zimag2 = 0.0; | |
if (d != 0.0) | |
{ | |
zimag2 = StrictMath.pow(d, 2.); | |
} | |
double ac = this.real*c; | |
double bd = this.imag*d; | |
double bc = this.imag*c; | |
double ad = this.real*d; | |
return new Complex((ac+bd)/(zreal2+zimag2),(bc-ad)/(zreal2+zimag2)); | |
} | |
/** | |
* @param z | |
* @return true if z == this | |
*/ | |
public boolean equals(Complex z) | |
{ | |
if (this.real == z.real() || this.imag == z.imag()) | |
{ | |
return true; | |
} | |
return false; | |
} | |
/** | |
* Return the square modulus of a complex number z | |
* @param z | |
* @return | |
*/ | |
public static double abs(Complex z) | |
{ | |
return | |
StrictMath.sqrt(StrictMath.pow(z.real(), 2) + StrictMath.pow(z.imag(), 2)); | |
} | |
/** | |
* return the complex angle of z | |
* (value returned should be between -Pi and Pi) | |
* @param z | |
* @return | |
*/ | |
public static double arg(Complex z) | |
{ | |
double theta = StrictMath.atan2(z.imag(),z.real()); | |
return theta; | |
} | |
/** | |
* Exponentiation (e^a+bi) | |
* @param z | |
* @return <code>e<sup>z</sup></code>. | |
*/ | |
public static Complex exp(Complex z) | |
{ | |
if (z.imag() == 0.0) | |
return new Complex(StrictMath.exp(z.real()),ONE); | |
Complex ex = new Complex(StrictMath.exp(z.real()), ZERO); | |
return ex.multiply( | |
new Complex(StrictMath.cos(z.imag()), StrictMath.sin(z.imag()))); | |
} | |
/** | |
* Complex power | |
* @param z - the complex base | |
* @param y - the complex exponent | |
* @return | |
*/ | |
public static Complex pow(Complex z, Complex y) | |
{ | |
double c = y.real(); | |
double d = y.imag(); | |
// get polar of base | |
double r = Complex.abs(z); | |
double theta = Complex.arg(z); | |
Complex f1 = new Complex( | |
(StrictMath.pow(r, c)*StrictMath.pow(StrictMath.E, -d*theta)),ZERO); | |
Complex f2 = | |
new Complex( | |
StrictMath.cos(d*StrictMath.log(r)+c*theta), | |
StrictMath.sin(d*StrictMath.log(r)+c*theta)); | |
return f1.multiply(f2); | |
} | |
/** | |
* @return complex conjugate | |
*/ | |
public Complex conjugate() | |
{ | |
return new Complex(this.real, -1*this.imag); | |
} | |
/** | |
* @return negative of complex | |
*/ | |
public Complex neg() | |
{ | |
if (this.imag != 0) | |
return new Complex(-1*this.real, -1*this.imag); | |
else | |
return new Complex(-1*this.real); | |
} | |
/** | |
* Return the given complex number multiplied by i | |
* @param complex number z | |
* @return | |
*/ | |
public static Complex Iz(Complex z) | |
{ | |
Complex result; | |
if (z.imag() != 0.0) | |
result = new Complex(-1.*z.imag(), z.real()); | |
else | |
result = new Complex(z.imag(), z.real()); | |
return result; | |
} | |
/** | |
* Return the given complex number multiplied by -i | |
* @param complex number z | |
* @return | |
*/ | |
public static Complex nIz(Complex z) | |
{ | |
Complex result; | |
if (z.real() != 0.0) | |
result = new Complex(z.imag(), -1*z.real()); | |
else | |
result = new Complex(z.imag(), z.real()); | |
return result; | |
} | |
@Override | |
public double doubleValue() { | |
// TODO Auto-generated method stub | |
return Double.valueOf(this.real); | |
} | |
@Override | |
public float floatValue() { | |
// TODO Auto-generated method stub | |
return Float.parseFloat(Double.toString(this.real)); | |
} | |
@Override | |
public int intValue() { | |
// TODO Auto-generated method stub | |
return Integer.parseInt(Double.toString(this.real)); | |
} | |
@Override | |
public long longValue() { | |
// TODO Auto-generated method stub | |
return Long.parseLong(Double.toString(this.real)); | |
} | |
public void formatTo(Formatter arg0, int arg1, int arg2, int arg3) { | |
// TODO Auto-generated method stub | |
throw new NoSuchMethodError(); | |
} | |
@Override | |
public String toString() { | |
// TODO Auto-generated method stub | |
return String.valueOf(real) + " " + String.valueOf(imag) + "i"; | |
} | |
private double real; | |
private double imag; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Complex number functions. A Complex consists of a real and imaginary | |
* part of type {@link double}.<p> | |
* main reference: Schaum's Outlines - Complex Variables | |
* | |
* @author Jose Menes | |
*/ | |
public class ComplexFunctions { | |
public static final int ZERO = 0; | |
public static final int ONE = 1; | |
public static final int NONE = -1; | |
public static final Complex one = new Complex(1.); | |
public static final Complex I = new Complex(ZERO, ONE); | |
public static final Complex nI = I.neg(); | |
public static final Complex e = new Complex(StrictMath.E, ZERO); | |
public static final long INFINITE = Long.MAX_VALUE; | |
public static final double Pi = StrictMath.PI; | |
private static int INFINITY = 1000; | |
private ComplexFunctions() | |
{ | |
// prevent instantiation | |
} | |
/** | |
* Return the square modulus of a complex number z | |
* @param z | |
* @return | |
*/ | |
public static double abs(Complex z) | |
{ | |
return | |
StrictMath.hypot(z.real(), z.imag()); | |
} | |
/** | |
* return the complex angle of z | |
* (value returned should be between -Pi and Pi) | |
* @param z | |
* @return | |
*/ | |
public static double arg(Complex z) | |
{ | |
return StrictMath.atan2(z.imag(),z.real()); | |
} | |
/** | |
* Exponentiation (e^a+bi) | |
* @param z | |
* @return <code>e<sup>z</sup></code>. | |
*/ | |
public static Complex exp(Complex z) | |
{ | |
if (z.imag() == 0.0) | |
return new Complex(StrictMath.exp(z.real()),ONE); | |
Complex ex = new Complex(StrictMath.exp(z.real()), ZERO); | |
return ex.multiply( | |
new Complex(StrictMath.cos(z.imag()), StrictMath.sin(z.imag()))); | |
} | |
/** | |
* Complex power | |
* @param z - the complex base | |
* @param y - the complex exponent | |
* @return | |
*/ | |
public static Complex pow(Complex z, Complex y) | |
{ | |
// if both Im(z) and Im(y) are zero, treat as double arithmetic | |
if (z.imag() == 0.0 || y.imag() == 0.0) | |
{ | |
return new Complex(StrictMath.pow(z.real(),y.real())); | |
} | |
double c = y.real(); | |
double d = y.imag(); | |
// get polar of base | |
double r = Complex.abs(z); | |
double theta = Complex.arg(z); | |
Complex f1 = new Complex( | |
(StrictMath.pow(r, c)*StrictMath.pow(StrictMath.E, -d*theta)),ZERO); | |
Complex f2 = | |
new Complex( | |
StrictMath.cos(d*StrictMath.log(r)+c*theta), | |
StrictMath.sin(d*StrictMath.log(r)+c*theta)); | |
return f1.multiply(f2); | |
} | |
/** | |
* Complex number raised to a real power | |
* @param z - the complex base | |
* @param a - the real exponent | |
* @return | |
*/ | |
public static Complex pow(Complex z, double a) | |
{ | |
// if Im(z) is zero, treat as double arithmetic | |
if (z.imag() == 0.0) | |
{ | |
return new Complex(StrictMath.pow(z.real(),a)); | |
} | |
// get polar of base | |
double r = Complex.abs(z); | |
double theta = Complex.arg(z); | |
// check n significant digits to see if rounding is required | |
if (functions.frac(r) > 0.9999001) | |
{ | |
r = StrictMath.round(r); | |
} | |
double angle = theta*a; | |
double np = StrictMath.pow(r, a); | |
double Re = np*StrictMath.cos(angle); | |
if (functions.frac(Re) > 0.9999001) | |
{ | |
Re = StrictMath.round(Re); | |
} | |
double Im = np*StrictMath.sin(angle); | |
if (functions.frac(Im) > 0.9999001) | |
{ | |
Im = StrictMath.round(Im); | |
} | |
return new Complex(Re, Im); | |
} | |
/** | |
* Real number raised to a complex power | |
* @param a - the real base | |
* @param z - the complex exponent | |
* @return | |
*/ | |
public static Complex pow(double a, Complex z) | |
{ | |
double a2x = StrictMath.pow(a, z.real()); | |
if (functions.frac(a2x) > 0.9999001) | |
{ | |
a2x = StrictMath.round(a2x); | |
} | |
Complex ax = new Complex(a2x, ZERO); | |
Complex result = | |
new Complex(StrictMath.cos(z.imag()*StrictMath.log(a)), | |
StrictMath.sin(z.imag()*StrictMath.log(a))); | |
return ax.multiply(result); | |
} | |
/** | |
* find square root of complex number z | |
* @param z | |
* @return | |
*/ | |
public static Complex sqrt(Complex z) | |
{ | |
return sqrtn(z, 2); | |
} | |
/** | |
* Find nTh root of complex number | |
* @param z | |
* @param n | |
* @return | |
*/ | |
public static Complex sqrtn(Complex z, int n) | |
{ | |
// get polar of base | |
double r = Complex.abs(z); | |
// check n significant digits to see if rounding is required | |
if (functions.frac(r) > 0.9999001) | |
{ | |
r = StrictMath.round(r); | |
} | |
double theta = Complex.arg(z); | |
// note: adding Pi to angle reverses signs | |
double angle = theta/n; | |
// get nTh root of r | |
double nrt = StrictMath.pow(r, 1./n); | |
double Re = nrt*StrictMath.cos(angle); | |
if (functions.frac(Re) > 0.9999001) | |
{ | |
Re = StrictMath.round(Re); | |
} | |
double Im = nrt*StrictMath.sin(angle); | |
if (functions.frac(Im) > 0.9999001) | |
{ | |
Im = StrictMath.round(Im); | |
} | |
return new Complex( | |
Re, Im); | |
} | |
/** | |
* Natural logarithm of a complex number | |
* @param complex number z | |
* @return | |
*/ | |
public static Complex log(Complex z) | |
{ | |
// get polar form | |
double r = Complex.abs(z); | |
double theta = Complex.arg(z); | |
return new Complex(StrictMath.log(r), theta); | |
} | |
/** | |
* Trigonometric functions - sine | |
* @param z | |
* @return | |
*/ | |
public static Complex sin(Complex z) | |
{ | |
// if Im(z) is zero, handle as double arithmetic | |
if (z.imag() == 0.0) | |
{ | |
return new Complex(StrictMath.sin(z.real())); | |
} | |
return (exp(Complex.Iz(z))).subtract(exp(Complex.nIz(z))) | |
.divide(Complex.Iz(new Complex(2.))); | |
} | |
/** | |
* Trigonometric functions - cosine | |
* @param z | |
* @return | |
*/ | |
public static Complex cos(Complex z) | |
{ | |
// if Im(z) is zero, handle as double arithmetic | |
if (z.imag() == 0.0) | |
{ | |
return new Complex(StrictMath.cos(z.real())); | |
} | |
return (exp(Complex.Iz(z))).add(exp(Complex.nIz(z))) | |
.divide(new Complex(2.,0.)); | |
} | |
/** | |
* Trigonometric functions - secant | |
* @param z | |
* @return | |
*/ | |
public static Complex sec(Complex z) | |
{ | |
return one.divide(cos(z)); | |
} | |
/** | |
* Trigonometric functions - cosecant | |
* @param z | |
* @return | |
*/ | |
public static Complex csc(Complex z) | |
{ | |
return one.divide(sin(z)); | |
} | |
/** | |
* Trigonometric functions - tangent | |
* @param z | |
* @return | |
*/ | |
public static Complex tan(Complex z) | |
{ | |
return (sin(z)).divide(cos(z)); | |
} | |
/** | |
* Trigonometric functions - cotangent | |
* @param z | |
* @return | |
*/ | |
public static Complex cot(Complex z) | |
{ | |
return (cos(z)).divide(sin(z)); | |
} | |
/** | |
* Hyperbolic functions - sine | |
* @param z | |
* @return | |
*/ | |
public static Complex sinh(Complex z) | |
{ | |
return (exp(z)).subtract(exp(z.neg())) | |
.divide(new Complex(2.)); | |
} | |
/** | |
* Hyperbolic functions - cosine | |
* @param z | |
* @return | |
*/ | |
public static Complex cosh(Complex z) | |
{ | |
return (exp(z)).add(exp(z.neg())) | |
.divide(new Complex(2.)); | |
} | |
/** | |
* Hyperbolic functions - tangent | |
* @param z | |
* @return | |
*/ | |
public static Complex tanh(Complex z) | |
{ | |
return (sinh(z)).divide(cosh(z)); | |
} | |
/** | |
* Hyperbolic functions - cotangent | |
* @param z | |
* @return | |
*/ | |
public static Complex coth(Complex z) | |
{ | |
return (cosh(z)).divide(sinh(z)); | |
} | |
/** | |
* Hyperbolic functions - secant | |
* @param z | |
* @return | |
*/ | |
public static Complex sech(Complex z) | |
{ | |
return one.divide(cosh(z)); | |
} | |
/** | |
* Hyperbolic functions - cosecant | |
* @param z | |
* @return | |
*/ | |
public static Complex csch(Complex z) | |
{ | |
return one.divide(sinh(z)); | |
} | |
/** | |
* Inverse trigonometric functions - arcsin | |
* implemented using log form | |
* @param z | |
* @return | |
*/ | |
public static Complex asin(Complex z) | |
{ | |
Complex result = | |
nI.multiply( | |
log(Complex.Iz(z) | |
.add(sqrt(new Complex(1.).subtract(pow(z,2.)))))); | |
return result; | |
} | |
/** | |
* Inverse trigonometric functions - arcosine | |
* implemented using log form | |
* @param z | |
* @return | |
*/ | |
public static Complex acos(Complex z) | |
{ | |
Complex result = | |
nI.multiply( | |
log(z.add(sqrt(pow(z,2.).subtract(one))))); | |
double re = result.real(); | |
double im = result.imag(); | |
if (functions.frac(re) > 0.9999001) | |
{ | |
result = new Complex(StrictMath.round(re),im); | |
} | |
return result; | |
} | |
/** | |
* Inverse trigonometric functions - arctangent | |
* implemented using log form | |
* @param z | |
* @return | |
*/ | |
public static Complex atan(Complex z) | |
{ | |
Complex iz = Complex.Iz(z); | |
Complex result = | |
new Complex(0.,-.5) | |
.multiply(log(one.add(iz).divide(one.subtract(iz)))); | |
double re = result.real(); | |
double im = result.imag(); | |
if (functions.frac(re) > 0.9999001) | |
{ | |
result = new Complex(StrictMath.round(re),im); | |
} | |
return result; | |
} | |
/** | |
* Inverse trigonometric functions - arccosecant | |
* implemented using log form | |
* @param z | |
* @return | |
*/ | |
public static Complex acsc(Complex z) | |
{ | |
Complex result = | |
new Complex(0.,-.1) | |
.multiply(log(I.add(sqrt(pow(z,2.))).divide(z))); | |
double re = result.real(); | |
double im = result.imag(); | |
if (functions.frac(re) > 0.9999001) | |
{ | |
result = new Complex(StrictMath.round(re),im); | |
} | |
return result; | |
} | |
/** | |
* Inverse trigonometric functions - arcsecant | |
* implemented using log form | |
* @param z | |
* @return | |
*/ | |
public static Complex asec(Complex z) | |
{ | |
Complex result = | |
new Complex(0.,-.1) | |
.multiply(log(one.add(sqrt(one.subtract(pow(z,2.))).divide(z)))); | |
double re = result.real(); | |
double im = result.imag(); | |
if (functions.frac(re) > 0.9999001) | |
{ | |
result = new Complex(StrictMath.round(re),im); | |
} | |
return result; | |
} | |
/** | |
* Inverse trigonometric functions - arccotangent | |
* implemented using log form | |
* @param z | |
* @return | |
*/ | |
public static Complex acot(Complex z) | |
{ | |
Complex result = | |
new Complex(0.,-.5) | |
.multiply(log(z.add(I).divide(z.subtract(I)))); | |
double re = result.real(); | |
double im = result.imag(); | |
if (functions.frac(re) > 0.9999001) | |
{ | |
result = new Complex(StrictMath.round(re),im); | |
} | |
return result; | |
} | |
/** | |
* Inverse hyperbolic functions - arcsine | |
* implemented using log form | |
* @param z | |
* @return | |
*/ | |
public static Complex asinh(Complex z) | |
{ | |
Complex result = log(z.add(sqrt(pow(z,2.).add(one)))); | |
double re = result.real(); | |
// strip the sign for the rounding test | |
if (re < 0.0) | |
{ | |
re *= -1.; | |
} | |
// rounding check | |
if (functions.frac(re) > 0.9999001) | |
{ | |
result = new Complex(StrictMath.round(result.real()),result.imag()); | |
} | |
return result; | |
} | |
/** | |
* Inverse hyperbolic functions - arcosine | |
* implemented using log form | |
* @param z | |
* @return | |
*/ | |
public static Complex acosh(Complex z) | |
{ | |
Complex result = log(z.add(sqrt(pow(z,2.).subtract(one)))); | |
double re = result.real(); | |
// strip the sign for the rounding test | |
if (re < 0.0) | |
{ | |
re *= -1.; | |
} | |
// rounding check | |
if (functions.frac(re) > 0.9999001) | |
{ | |
result = new Complex(StrictMath.round(result.real()),result.imag()); | |
} | |
return result; | |
} | |
/** | |
* Inverse hyperbolic functions - arctangent | |
* implemented using log form | |
* @param z | |
* @return | |
*/ | |
public static Complex atanh(Complex z) | |
{ | |
Complex result = | |
new Complex(.5).multiply(log(one.add(z).divide(one.subtract(z)))); | |
double re = result.real(); | |
// strip the sign for the rounding test | |
if (re < 0.0) | |
{ | |
re *= -1.; | |
} | |
// rounding check | |
if (functions.frac(re) > 0.9999001) | |
{ | |
result = new Complex(StrictMath.round(result.real()),result.imag()); | |
} | |
return result; | |
} | |
/** | |
* Inverse hyperbolic functions - arcosecant | |
* implemented using log form | |
* @param z | |
* @return | |
*/ | |
public static Complex acsch(Complex z) | |
{ | |
Complex result = | |
log(one.add(sqrt(pow(z,2.).add(one))).divide(z)); | |
double re = result.real(); | |
// strip the sign for the rounding test | |
if (re < 0.0) | |
{ | |
re *= -1.; | |
} | |
// rounding check | |
if (functions.frac(re) > 0.9999001) | |
{ | |
result = new Complex(StrictMath.round(result.real()),result.imag()); | |
} | |
return result; | |
} | |
/** | |
* Inverse hyperbolic functions - arcsecant | |
* implemented using log form | |
* @param z | |
* @return | |
*/ | |
public static Complex asech(Complex z) | |
{ | |
Complex result = | |
log(one.add(sqrt(one.subtract(pow(z,2.))).divide(z))); | |
double re = result.real(); | |
// strip the sign for the rounding test | |
if (re < 0.0) | |
{ | |
re *= -1.; | |
} | |
// rounding check | |
if (functions.frac(re) > 0.9999001) | |
{ | |
result = new Complex(StrictMath.round(result.real()),result.imag()); | |
} | |
return result; | |
} | |
/** | |
* Inverse hyperbolic functions - arccotangent | |
* implemented using log form | |
* @param z | |
* @return | |
*/ | |
public static Complex acoth(Complex z) | |
{ | |
Complex result = | |
new Complex(.5).multiply( | |
log(z.add(one).divide(z.subtract(one)))); | |
double re = result.real(); | |
// strip the sign for the rounding test | |
if (re < 0.0) | |
{ | |
re *= -1.; | |
} | |
// rounding check | |
if (functions.frac(re) > 0.9999001) | |
{ | |
result = new Complex(StrictMath.round(result.real()),result.imag()); | |
} | |
return result; | |
} | |
/** | |
* extended Gamma function for complex arguments | |
* @param s | |
* @return | |
*/ | |
public static Complex PI(Complex s) | |
{ | |
int n = 1; | |
Complex result = (pow((double)n, one.subtract(s)) | |
.multiply(pow((double)n+1, s))) | |
.divide(s.add(one)); | |
for (n=2;n<INFINITY;n++) | |
{ | |
result = result.multiply((pow((double)n, one.subtract(s)) | |
.multiply(pow((double)n+1, s))) | |
.divide(s.add(new Complex((double)n)))); | |
} | |
return result; | |
} | |
public static void main(String[] args) | |
{ | |
// all tests moved to JUnit test case | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Where this will be used?