Complex numbers and arithmetic

Back to: Main contents.

Contents

Complex numbers
Complex arithmetic
Complex arrays (the class Z1)
Java does not have a primitive complex type, and it is therefore necessary to implement complex numbers and operations on them as a class. For Jampack, the class is named Z--the standard name for double complex floating-point numbers. In this section we will first describe the fields and constructors defining a complex number and then turn to the methods that manipulate complex numbers. We will conclude with a description of the class Z1, which implements a one-dimensional array of complex numbers.

Complex numbers

Back to: Main contents, Top of section.

A complex number is an object of class Z. It consists simply of a real and an imaginary part:

public double re
The real part of the complex number

public double im
The imaginary part of the complex number

The class Z has four constructors.

public Z()
Creates a Z and initializes it to zero.

public Z(double x, double y)
Creates a Z whose real part is x and whose imaginary part is y.

public Z(double x)
Creates a Z whose real part is x and whose imaginary part is zero.

public Z(Z z)
Creates a Z and initializes it to another Z.

The class Z has complex versions of zero, one, and the imaginary unit.

public static final Z ZERO = new Z(0,0)

public static final Z ONE = new Z(1,0)

public static final Z I = new Z(0,1)

Complex arithmetic

Back to: Main contents, Top of section.

The style of complex operations on Zs is designed to minimize the construction of new Zz in inner loops. Most of the operations have the form a.op(b,c) in which a can be the same as b or c. Its effect is to assign the value of b.op.c to a. Thus to compute e = a*b + c*d you can write

z1.Times(a,b);
z2.Times(c,d);
e.Plus(z1,z2);

The intermediate quantities z1 and z2 may be thought of as registers that can be created at the beginning of the method doing the calculation. These registers can then be reused in subsequent calculations, which reduces the need to create new Zs.

The construction a.op(b, c) also returns a pointer to a. This means that you can code the above sequence in the more compact form

e.Plus(z1.Times(a,b), z2.Times(a,b));

Since Z is not a primitive object and the values of a Z may change, we discourage the use of the "=" operator with Zs. Instead of writing

z1 = z2;
which causes z1 and z2 to point to the same object, write
z1.Eq(z2);
which sets the value of z1 equal to the value of z2. Here is a list of the Z methods in alphabetical order.

public static double abs(Z z)
Returns the absolute value of z.

public static double abs1(Z z)
Returns the sum of the absolute values of the real and imaginary parts of z.

public Z Conj(Z a)
Sets this Z to the conjugate of a and returns this Z.

public Z Div(Z a, Z b)
Sets this Z to a/b and returns this Z.
Throws a JampackException if b is zero.

public Z Div(Z a, double b)
Sets this Z to a/b and returns this Z.
Throws a JampackException if b is zero.

public Z Eq(Z a)
Sets the real and imaginary parts of this Z to those of a and returns this Z.

public Z Eq(double a, double b)
Resets the real and imaginary of this Z to a and b and returns this Z.

public Z Exch(Z a)
Exchanges the this Z and a, so that the value of this Z is the original value of a and vice versa.

public boolean IsEqual(Z z1, Z z2)
Tests two Zs for equality.

public Z Minus(Z a)
Sets this Z to -a and returns this Z.

public Z Minus(Z a, Z b)
Sets this Z to a-b and returns this Z.

public Z Plus(Z a, Z b)
Sets this Z to a+b and returns this Z.

public Z Times(Z a, Z b)
Sets this Z to a*b and returns this Z.

public Z Times(double a, Z b)
Sets this Z to a*b and returns this Z.

public Z Sqrt(Z a)
Sets this Z to the principal value of the square root of a and returns this Z.

Complex arrays (the class Z1)

Back to: Main contents, Top of section.

The implementation of an array of complex numbers is not a straightforward matter. The problem is the interaction of array references with cache memories. For such references to be efficient it is necessary that references to consecutive array elements translate into references to consecutive memory locations, i.e., that an array be stored in a single block of memory. Although Java does not specify how arrays of floats or doubles are to be stored, most versions of the language seem indeed to store their elements contiguously in memory. The same is not true of the members of an array of classes. For example, when a one-dimensional array of Zs is declared, only space for pointers to the elements of the array is allocated. The actual elements must be constructed later. Since each construction is an individual affair, there is no guarantee that the members of the array will occupy consecutive locations in memory.

The Jampack solution to this problem is to create a special class, the class Z1, to implement one-dimensional complex arrays. The elements of the array are represented by two double arrays, one containing the real part and the other containing the imaginary part. The Z1 should not be confused with a vector class. It is intended primarily for working storage in matrix algorithms and does not participate in the matrix operations that are defined for the core matrix classes like Zmat. Moreover, a Z1 has no base index, so that all array references in a Z1 begin at zero--just like in an array of primitive objects.

The data fields of a Z1 are the following.

protected int n
The number of elements in the Z1

protected double re[]
The real part of the Z1

protected double im[]
The imaginary part of the Z1

The class Z1 has only one constructor.

public Z1(int n)
Creats a Z1 of length n and initializes it to zero.

Z1 has the following methods.

public Z get(int i)
Returns the i-th elements of this Z1.

public void put(int i, Z z)
Sets the i-th element of this Z1 to z.

public void put(int i, double real, double imag)
Sets the real and imaginary parts of the i-th element of this Z1.

public void Times(int i, Z z)
Multiplies the i-th element of this Z1 by z.