package jsci.maths;
import java.lang.Double;
import jsci.GlobalSettings;
import jsci.maths.algebras.*;
import jsci.maths.fields.*;
import jsci.maths.groups.AbelianGroup;
/**
* The Complex class encapsulates complex numbers.
* @jsci.planetmath Complex
* @version 2.25
* @author Mark Hale
*/
public final class Complex extends Object implements Field.Member, CStarAlgebra.Member {
private static final long serialVersionUID = 6561957920497208796L;
private double re;
private double im;
/**
* Caching.
*/
private transient boolean isModCached=false;
private transient double modCache;
private transient boolean isArgCached=false;
private transient double argCache;
/**
* The complex number 0+1i.
*/
public static final Complex I=ComplexField.I;
/**
* The complex number 1+0i.
*/
public static final Complex ONE=ComplexField.ONE;
/**
* The complex number 0+0i.
*/
public static final Complex ZERO=ComplexField.ZERO;
/**
* Constructs the complex number x+iy.
* @param x the real value of a complex number.
* @param y the imaginary value of a complex number.
*/
public Complex(final double x,final double y) {
re=x;
im=y;
}
/**
* Constructs the complex number represented by a string.
* @param s a string representing a complex number.
* @exception NumberFormatException if the string does not contain a parsable number.
*/
public Complex(final String s) throws NumberFormatException {
final int iPos = s.indexOf('i');
if(iPos == -1) {
// no 'i' so must be real
re = Double.parseDouble(s);
im = 0.0;
} else {
int signPos = indexOf(s, '+', '-', 1);
int expPos = indexOf(s, 'E', 'e', 1);
if(signPos == expPos+1)
signPos = indexOf(s, '+', '-', signPos+1);
String imStr;
if(signPos == -1) {
re=0.0;
imStr=s;
} else {
if(iPos=0.0)
buf.append("+");
buf.append(imag);
buf.append("i");
return buf.toString();
}
/**
* Returns a hashcode for this complex number.
*/
public int hashCode() {
return (int)(Math.exp(mod()));
}
/**
* Returns true if the modulus of this complex number is within the zero tolerance.
*/
public boolean isZero() {
return (mod() <= GlobalSettings.ZERO_TOL);
}
/**
* Returns true if either the real or imaginary part is NaN.
*/
public boolean isNaN() {
return (re==Double.NaN) || (im==Double.NaN);
}
/**
* Returns true if either the real or imaginary part is infinite.
*/
public boolean isInfinite() {
return (re==Double.POSITIVE_INFINITY) || (re==Double.NEGATIVE_INFINITY)
|| (im==Double.POSITIVE_INFINITY) || (im==Double.NEGATIVE_INFINITY);
}
/**
* Returns the real part of this complex number.
*/
public double real() {
return re;
}
/**
* Returns the imaginary part of this complex number.
*/
public double imag() {
return im;
}
/**
* Returns the modulus of this complex number.
*/
public double mod() {
if(isModCached)
return modCache;
modCache=mod(re,im);
isModCached=true;
return modCache;
}
private static double mod(final double real,final double imag) {
final double reAbs=Math.abs(real);
final double imAbs=Math.abs(imag);
if(reAbs==0.0 && imAbs==0.0)
return 0.0;
else if(reAbs* norm.
*/
public double norm() {
return mod();
}
public Object getSet() {
return ComplexField.getInstance();
}
//============
// OPERATIONS
//============
/**
* Returns the negative of this complex number.
*/
public AbelianGroup.Member negate() {
return new Complex(-re,-im);
}
/**
* Returns the inverse of this complex number.
*/
public Field.Member inverse() {
double denominator,real,imag;
if(Math.abs(re)/2 through
/2,
* -
through
).
* @param z a complex number.
*/
public static Complex asin(final Complex z) {
if(z.equals(ONE))
return ComplexField.PI_2;
else if(z.equals(ComplexField.MINUS_ONE))
return ComplexField.MINUS_PI_2;
else {
// atan(z/sqrt(1-z*z))
final Complex root=sqrt(1.0-z.re*z.re+z.im*z.im,-2.0*z.re*z.im);
final double zModSqr=z.re*z.re+z.im*z.im;
final double rootModSqr=root.re*root.re+root.im*root.im;
final double denom=rootModSqr+zModSqr+2.0*(root.re*z.im-root.im*z.re);
return log_2I((rootModSqr-zModSqr)/denom,2.0*(root.re*z.re+root.im*z.im)/denom);
}
}
// INVERSE COS
/**
* Returns the arc cosine of a complex number, in the range of
* (0.0 through
,
* 0.0 through
).
* @param z a complex number.
*/
public static Complex acos(final Complex z) {
if(z.equals(ONE))
return ZERO;
else if(z.equals(ComplexField.MINUS_ONE))
return ComplexField.PI;
else {
// atan(-z/sqrt(1-z*z))+PI/2
final Complex root=sqrt(1.0-z.re*z.re+z.im*z.im,-2.0*z.re*z.im);
final double zModSqr=z.re*z.re+z.im*z.im;
final double rootModSqr=root.re*root.re+root.im*root.im;
final double denom=rootModSqr+zModSqr+2.0*(root.im*z.re-root.re*z.im);
return log_2IplusPI_2((rootModSqr-zModSqr)/denom,-2.0*(root.re*z.re+root.im*z.im)/denom);
}
}
// INVERSE TAN
/**
* Returns the arc tangent of a complex number, in the range of
* (-
/2 through
/2,
* -
through
).
* @param z a complex number.
*/
public static Complex atan(final Complex z) {
// -i atanh(iz) = -i/2 log((1+iz)/(1-iz))
final double modSqr=z.modSqr();
final double denom=1.0+modSqr+2.0*z.im;
return log_2I((1.0-modSqr)/denom,2.0*z.re/denom);
}
// INVERSE SINH
/**
* Returns the arc hyperbolic sine of a complex number, in the range of
* (-
through
,
* -
/2 through
/2).
* @param z a complex number.
*/
public static Complex asinh(final Complex z) {
if(z.equals(I))
return ComplexField.PI_2_I;
else if(z.equals(ComplexField.MINUS_I))
return ComplexField.MINUS_PI_2_I;
else {
// log(z+sqrt(z*z+1))
final Complex root=sqrt(z.re*z.re-z.im*z.im+1.0,2.0*z.re*z.im);
return log(z.re+root.re,z.im+root.im);
}
}
// INVERSE COSH
/**
* Returns the arc hyperbolic cosine of a complex number, in the range of
* (0.0 through
,
* 0.0 through
).
* @param z a complex number.
*/
public static Complex acosh(final Complex z) {
if(z.equals(ONE))
return ZERO;
else if(z.equals(ComplexField.MINUS_ONE))
return ComplexField.PI_I;
else {
// log(z+sqrt(z*z-1))
final Complex root=sqrt(z.re*z.re-z.im*z.im-1.0,2.0*z.re*z.im);
return log(z.re+root.re,z.im+root.im);
}
}
// INVERSE TANH
/**
* Returns the arc hyperbolic tangent of a complex number, in the range of
* (-
through
,
* -
/2 through
/2).
* @param z a complex number.
*/
public static Complex atanh(final Complex z) {
// 1/2 log((1+z)/(1-z))
final double modSqr=z.modSqr();
final double denom=1.0+modSqr-2.0*z.re;
return log_2((1.0-modSqr)/denom,2.0*z.im/denom);
}
}
Ads help maintain this website.