package Jampack;
/**
* Z is a mutable complex variable class. It is designed to
* perform complex arithmetic without creating a new Z at
* each operation. Specifically, binary operations have the
* form c.op(a,b), in which a, b, and c need not be different.
* The method places the complex number a.op.b in
* c. The method also returns a pointer to c. Thus the
* class supports two styles of programming. For example
* to compute e = a*b + c*d you can write
*
* z1.Times(a,b)
* z2.Times(c,d)
* e.Plus(z1,z2)
*
* or
*
* e.Plus(z1.Times(a,b), z2.Times(a,b))
*
* Since objects of class Z are mutable, the use of the assignment
* operator "=" with these objects is deprecated. Use Eq.
*
* The functions are reasonably resistent to overflow and underflow.
* But the more complicated ones could almost certainly be improved.
@version Pre-alpha
@author G. W. Stewart
*/
public class Z{
/** Complex 1. */
public static final Z ONE = new Z(1,0);
/** Complex 0. */
public static final Z ZERO = new Z(0,0);
/** Imaginary unit. */
public static final Z I = new Z(0,1);
/** The real part of Z. */
public double re;
/** The imaginary part of Z. */
public double im;
/**
* Creates a Z and initializes it to zero.
@return a Z initialized to zero.
*/
public Z(){
re = 0.;
im = 0.;
}
/**
* Creates a Z and initializes its real and imaginary parts.
@param x a double
@param y a double
@return x + iy
*/
public Z(double x, double y){
re = x;
im = y;
}
/**
* Creates a Z and initializes its real part.
@param x a double
@return x + i*0
*/
public Z(double x){
re = x;
im = 0;
}
/**
* Creates a Z and initializes it to another Z.
@param a a Z
@return a
*/
public Z(Z a){
re = a.re;
im = a.im;
}
/**
* Tests two Z'z for equality.
@param z1 a Z
@param z2 a Z
@return true if z1=z2, otherwise false
*/
public boolean IsEqual(Z z1, Z z2){
if (z1.re == z2.re && z1.im == z2.im){
return true;
}
else{
return false;
}
}
/**
* Resets the real and imaginary parts of a Z to those of another Z.
@param a a Z
@return this = a;
*/
public Z Eq(Z a){
re = a.re;
im = a.im;
return this;
}
/**
* Resets the real and imaginary parts of a Z.
@param a a double
@param b a double
@return this = a + ib
*/
public Z Eq(double a, double b){
re = a;
im = b;
return this;
}
/**
* Interchanges the real and imaginary parts of two Z's.
@param a a Z
@return this = a, with a set to the original
value of this.
*/
public Z Exch(Z a){
double t;
t = re; re = a.re; a.re = t;
t = im; im = a.im; a.im = t;
return this;
}
/**
Computes the 1-norm of a Z
*/
public static double abs1(Z z){
return Math.abs(z.re) + Math.abs(z.im);
}
/**
Computes the absolute value of a Z.
@param z a Z
@return the absolute vaue of Z
*/
public static double abs(Z z){
double are, aim, rho;
are = Math.abs(z.re);
aim = Math.abs(z.im);
if (are+aim == 0) return 0;
if (are >= aim){
rho = aim/are;
return are*Math.sqrt(1+rho*rho);
}
else{
rho = are/aim;
return aim*Math.sqrt(1+rho*rho);
}
}
/**
* Computes the conjugate of a Z.
@param a a Z
@return this = conj(a);
*/
public Z Conj(Z a){
re = a.re;
im = -a.im;
return this;
}
/**
* Computes unary minus of a Z.
@param a a Z
@return this = -a;
*/
public Z Minus(Z a){
re = -a.re;
im = -a.im;
return this;
}
/**
* Computes the sum of two Z's.
@param a a Z
@param b a Z
@return this = a + b
*/
public Z Plus(Z a, Z b){
re = a.re + b.re;
im = a.im + b.im;
return this;
}
/**
* Computes the difference of two Z's.
@param a a Z
@param b a Z
@return this = a - b
*/
public Z Minus(Z a, Z b){
re = a.re - b.re;
im = a.im - b.im;
return this;
}
/**
* Computes the product of two Z's.
@param a a Z
@param b a Z
@return this = ab
*/
public Z Times(Z a, Z b){
double tre;
tre = a.re*b.re - a.im*b.im;
im = a.im*b.re + a.re*b.im;
re = tre;
return this;
}
/**
* Computes the product of a double and a Z.
@param a a double
@param b a Z
@return this = ab
*/
public Z Times(double a, Z b){
re = a*b.re;
im = a*b.im;
return this;
}
/**
* Computes the quotient of two Z's. Throws a JampackException if
* the denominator is zero.
@param a a Z
@param b a Z
@return this = a/b
@exception JampackException
Thrown if b is zero.
*/
public Z Div(Z a, Z b)
throws JampackException{
double avi, t, tre, tim;
avi = abs(b);
if (avi == 0){
throw new JampackException
("Divide by zero.");
}
avi = 1./avi;
tre = b.re*avi;
tim = -b.im*avi;
t = (a.re*tre - a.im*tim)*avi;
im = (a.im*tre + a.re*tim)*avi;
re = t;
return this;
}
/**
* Computes the quotient of a Z and a double. Throws a JampackException
* if the denominator is zero.
@param a a Z
@param b a double
@return this = a/b
@exception JampackException
Thrown if b is zero.
*/
public Z Div(Z a, double b)
throws JampackException{
if (b == 0){
throw new JampackException
("Divide by zero.");
}
re = a.re/b;
im = a.im/b;
return this;
}
/**
* Computes the principal value of the square root of a Z.
@param a a Z
@param this = sqrt(a)
*/
public Z Sqrt(Z a){
double t, tre, tim;
t = Z.abs(a);
if (Math.abs(a.re) <= Math.abs(a.im)){
// No cancellation in these formulas
tre = Math.sqrt(0.5*(t+a.re));
tim = Math.sqrt(0.5*(t-a.re));
}
else{
// Stable computation of the above formulas
if (a.re > 0){
tre = t + a.re;
tim = Math.abs(a.im)*Math.sqrt(0.5/tre);
tre = Math.sqrt(0.5*tre);
}
else{
tim = t - a.re;
tre = Math.abs(a.im)*Math.sqrt(0.5/tim);
tim = Math.sqrt(0.5*tim);
}
}
if (a.im < 0)
tim = -tim;
re = tre;
im = tim;
return this;
}
}
Ads help maintain this website.