Equivalence, Complex Variables and Functions
Scalar variables: X, Y, Z, I, J, K, etc.Each variable uses the number of bytes of memory required for a single element of its type on the machine being used. For example, on the Sun default REAL variables use 4 bytes. So the statement:
REAL X, Y, Z
allocates 4 bytes of memory to X, Y and Z and the program unit will recognize that arithmetic operations using X, Y and Z should be performed using the rules for real numbers.
If additional precision in the computation is required, you can allocate on the Sun four more bytes for a total of 8 bytes using the statement:
REAL*8 X, Y, Z
On other machines, the default number of bytes and the floating point representations used may be different. For example, on the Cray supercomputer, the statement
REAL X, Y, Z
allocates 8 bytes of memory to the variable X, Y, Z.
Unless you have a very particular application requiring very high precision, it is best to use the default number of bytes.
Similarly, integer scalar variables are allocated memory using:
INTEGER I, J, K
On the Sun the default specification is for 4 bytes of memory to be
allocated per integer variable. On the Cray, the above statement would
allocate 8 bytes of memory per variable.
Each variable uses the number of bytes required for a single element of its type on the machine being used (just as for scalar variables) multiplied by the number of elements in the vector. You can use the parameter statement to define the extent (length) of each vector and the type statement to allocate the memory:
PARAMETER (NX = 100, NY = 200, NZ = 300)
REAL X(NX), Y(NY), Z(NZ)
On the Sun, default REAL variables require 4 bytes (8 bytes for the Cray) so the vector X, now has been allocated NX*4 = 100*4 = 400 bytes of memory. Similarily, Y has 800 bytes and Z has 1200 bytes allocated.
Complex variables have two parts, the real and imaginary elements. On the Sun, the real element requires 4 bytes and the imaginary element requires 4 bytes. The statement:
PARAMETER (NC = 1000)
COMPLEX XC(NC)
defines a complex vector XC of length NC = 1000 and allocates 8 bytes
(4 bytes for the real and 4 bytes for the imaginary) to each complex element
for a total of NC*8 = 8000 bytes.
Integer and logical variables can also have extent and the length of the vector can be defined using the type statements:
INTEGER I(NI), J(NJ), K(NK)
where NI*4 bytes are allocated (e.g., on the Sun) to the integer variable I, etc.
or,
LOGICAL LIST (NL)
Logical variables are usually allocated the same number of bytes as the default integer variables even though only 1 bit is required to determine its value of true or false.
Matrices: X(NR, NC), I(NR, NC)Each variable uses the number of bytes of memory required for a single element of its type on the machine being used multiplied by the extent of the variable:
PARAMETER (NR = 1000, NC = 100)
REAL X(NR, NC)
In this case, if the default real variable length is 4 bytes, the number of bytes of memory allocated to the variable X is:
NR ´ NC ´ 4 or
1000 ´ 100 ´ 4 = 400,000 bytes
Similarly,
COMPLEX C(NR, NC)
would allocate NR ´ NC ´ 4 ´ 2 (because complex) = 800,000 bytes
Storage Order:In Fortran memory is allocated contiguously from the startingaddress of the variable. The leftmost index always moves through memory the most rapidly. Consider the following:
PARAMETER (NR = 2, NC = 3)
REAL X(NR, NC)
We think of the matrix X as follows:
X(1,1) X(1,2) X(1,3)
X(2,1) X(2,2) X(2,3)
The elements are stored in memory however as:
X(1,1)
X(2,1)
X(1,2)
X(2,2)
X(1,3)
X(2,3)
This storage order does have a serious consequence on the performance of your program when the number of elements is large. The rule is to always try to reference your matrix elements from left to right, i.e. access memory in a sequential way whenever possible:
Example:
PARAMETER (NR = 100000, NC = 10000)
REAL X(NR, NC)
SUM = 0
DO IR = 1, NR
DO IC = 1, NC
SUM = SUM + X(IR, IC)
END DO
END DO
In this case, IC varies most rapidly so the loop skips through 100,000 memory elements for each iteration of the IC loop. Where:
DO IC = 1, NC
DO IR = 1, NR
SUM = SUM + X(IR, IC)
END DO
END DO
will address the elements of X sequentially in memory.
Equivalence Statements: The EQUIVALENCE statement is usually the last statement of the declaration type statements. It allows you to reference the same memory locations by using different variable names. The variable types may also be different.Equivalence Examples:
Scalar Example:
REAL A, B
EQUIVALENCE (A, B)
So therefore, the statement
C = A + B
is the same as:
C = A + A
or
C = B + B
Vector Example:
REAL A(10), B(2)
EQUIVALENCE (B (1), A (8))
This associates memory locations B(1) with A(8) and B(2) with A(9), as shown in the diagram below:
Fourier Transform Example:
The Fourier transform is:
or
where w = 2*pi*f
Here F(w) has a real, u(w), and imaginary, v(w), component even though f(t) is a real function.
Suppose we call a subroutine that performs an in place Fourier transform:
CALL FFT (F, NT, –1)
The original data series F of NT points is composed of real numbers, but it will come out complex, since this subroutine will return the Fourier transform of F in place, i.e., in the same memory locations.
The following illustrates how the equivalence statement can be used to ease programming:
REAL F(8), P(8)
COMPLEX FC (4)
EQUIVALENCE (F(1), FC(1))
NT = 8
CALL FFT (F, NT, –1)
DO J = 1, NT/2
P (J) = F (2*J-1)**2 + F (2*J)**2
END DO
However; there is an easier way.
DO J = 1, NT/2
P (J) = REAL (FC (J) * CONJG (FC (J) ) )
END DO
or (less efficient):
DO J = 1, NT/2
P (J) = CABS (FC(J)) **2
END DO
Some useful complex functions are:
CSQRT, CEXP, AIMAG, REAL, CABS
Arrays in Fortran 90 can be allocated dynamically(i.e at run time). For example, if we want to have a 2-dimensional array of integers whose size shall be decided at run time it can be done in fortran 90 by using the following declaration
integer, allocatable :: X( : , :)
! Use the keyword allocatable to tell the compiler that its size shall
be determined at run time. No memory is allocated at this time
! to store X
integer i
! A variable to read the value of array size
print *, 'Enter the size of array'
read *,i
allocate(X(i,i))
! Call the function allocate which allocates memory ar run time