CHAPTER 9
FUNCTIONS AND SUBROUTINES
In the preceding chapters, we have written, compiled, and
executed Fortran programs using only the principal program unit, or main program. Secondary program units, or
subprograms, were mentioned in Section 1.1 when listing
the different types of program units. Subprograms are optional; therefore, we had no need to deal with them until
now.
This chapter describes the use of subprograms, specifically functions and subroutines.
When dealing with complex applications, it is often advisable to segment a large
program unit into several units of more manageable size.
Each of these units could be tested and debugged individually, and later assembled into an executable program.
An executable program is a set of logically related program units comprising exactly one main program and zero
or more subprograms. Note that since subprograms are optional, the executable program does not need to have any
subprograms.
Subprograms are program units whose purpose is to
perform a specific task on behalf of another program unit,
referred to as the invoking or calling program. In Fortran,
functions are invoked or referenced; subroutines are
called. Normally, the invoking or calling program passes
on to the subprogram a set of arguments. The subprogram
uses these arguments to compute the results and to pass
them back and return control to the invoking or calling
program.
The argument list in the invoking or calling program is
the actual argument list. The corresponding argument list
in the subprogram being invoked or called is the dummy
argument list. The actual argument list must match the
dummy argument list in number, order, and data type.
There are two types of subprograms:
- Built-in (intrinsic) functions, described in Section 5.4,
and
- User-written (extrinsic) subprograms, which are of three
types:
a.
Functions,
b.
Subroutines, and
c. Block data.
This chapter deals with functions and subroutines.
Block data subprograms are described in Section 11.4.
A function is a program unit that has FUNCTION as its
first statement and END as its last statement. It is invoked
with a function reference from another program unit.
Typically, a function performs one or more computations,
but can return only one value to the invoking program
unit.
A subroutine is a program unit that has SUBROUTINE
as its first statement and END as its last statement. It is
called with a CALL statement from another program unit.
Typically, a subroutine performs several computations,
and can return several values to the calling program unit.
9.1 STATEMENT FUNCTIONS
A statement function is a special type of function that
has the following properties:
- It is defined by a single statement
- It appears within a program unit
- It is invoked with a function reference only from within
the defining program unit.
Strictly speaking, a statement function is not a subprogram because it is not a program unit. (Recall that a program unit must finish with an END statement).
The statement function definition takes the form
statefunc(a,b,c) = expression
where statefunc is the statement function name; a, b, and c
are the dummy arguments, and expression is an arithmetic
or logical expression. The dummy arguments in the statement function definition cannot be constants. The number
of dummy arguments is at least one, and is not limited.
The statement function definitions should be placed
immediately after the specification block (Section 8.1),
preceding all executable statements (see Fig. 1.1).
As an example, the statement function definition
VOLCYL(RAD,HEI)= PI*RAD**2*HEI
defines the volume of a cylinder (VOLCYL), with arguments cylinder radius (RAD) and height (HEI), as equal to
π (PI) times the square of the cylinder radius (RAD**2)
times the cylinder height (HEI).
The statement function reference takes the form
y = statefunc(a1,b1,c1)
where statefunc is the statement function name, and a1,
b1, and c1 are the actual arguments. The actual argument
list must match the dummy argument list in number, order,
and data type.
The actual arguments in the statement function refer
ence may be constants or variables. However, if an actual
argument is a variable, it must have been assigned a value
prior to the statement function reference.
For example, the statement function reference
DIFFERENCE= VOLCYL(4.,6.) - VOLCYL(2.,3.)
is connected to the prior example. It refers to the statement function VOLCYL
to calculate the difference between
the volumes of two cylinders, the larger of radius = 4. and
height = 6., and the smaller of radius = 2., and height = 3.
The data type of a statement function is determined by
an explicit declaration (INTEGER or REAL, and CHARACTER), or by following the rules for implicit type declaration (variable names starting with I, J, K, L, M, or N are
integers; otherwise, they are real).
Statement functions are subject to the following rules:
The actual argument list must match the dummy argument list in number, order, and data type.
The statement function name cannot be used for some
other entity in the same program unit.
Dummy argument names can be used for some other entities in the same program unit.
A statement function reference must appear as or be part
of an expression, that is, always on the right side on an
assignment statement, and not on the left side.
The following are additional examples of statement
function definitions:
VOLUMESPH(RAD)= 1.333333*PI*RAD**3
HYPOTENUSE(A,B)= SQRT(A**2 + B**2)
COSH(X)= 0.5*(EXP(X) + EXP(-X))
The first example defines a statement function to calculate the volume of a sphere of radius . The second
example defines a statement function to calculate the
hypotenuse of a right triangle of sides A and B. The third
example defines a statement function to calculate the
hyperbolic cosine of an angle X.
The following are appropriate references to these statement functions. The value of XANGLE must have been de
fined previously.
DIFFERENCE= VOLUMESPH(4.) - VOLUMESPH(3.)
C= HYPOTENUSE(3.,4.)
Z= COSH(XANGLE) + 6.7
Example Program: Use of Statement Functions
C234567890
PROGRAM ABC
C-----CALCULATES HYPOTENUSE OF 5 RIGHT TRIANGLES
PARAMETER (NV= 5)
DIMENSION A(NV),B(NV),C(NV)
DATA A /1.2,3.4,4.9,5.2,8.9/
DATA B /2.3,5.6,6.7,4.3,2.7/
C-----THIS IS THE STATEMENT FUNCTION DEFINITION
HYPOTENUSE(SA,SB)= SQRT(SA**2 + SB**2)
DO 10 J= 1,NV
C-----THIS IS THE STATEMENT FUNCTION REFERENCE
C(J)= HYPOTENUSE(A(J),B(J))
WRITE(6,100)'THE VALUES ARE: ',A(J),B(J),C(J)
10 END DO
100 FORMAT(1X,3F10.2)
END
|
9.2 FUNCTIONS
A function subprogram is a program unit that has a FUNCTION statement as its first statement and an END as its
last statement.
FUNCTION ABC(X,Y,Z)
...
END
In this example, the symbol ... stands for a set of
statements that define the function's computing procedure.
A function subprogram has zero or more RETURN
statements located anywhere in the program unit, i.e., following the FUNCTION statement and preceding the END
statement. The purpose of the RETURN statement is to
return control to the invoking program whenever it is required. Control is returned to the statement immediately
following the function reference. The RETURN statement
may be omitted if there is only one RETURN statement in
the entire program unit, and it immediately precedes the
END statement. In this case, an implicit RETURN is executed when control reaches the END statement.
The FUNCTION statement consists of the keyword
FUNCTION (Table 1.1) followed by the function's name,
which is a scalar variable (Section 7.1), and a dummy argument list enclosed in parentheses. The input to the func
tion is the argument list. The output from the function is
contained in the function's name. That is, once the function is executed, the result of the computing procedure is
stored in the function's name.
An example of the function statement is
FUNCTION ABC(X,Y,Z)
where ABC is the function name, and X, Y, Z are the
dummy arguments.
An appropriate reference to this function is
SUM= ABC(1.,3.,5.) + ABC(2.,4.,6.)
where the function ABC(X,Y,Z) is evaluated twice, each
time with a different actual argument list, and the results
are summed and stored in SUM. Note that the actual argument list matches the dummy argument list in number, order, and data type.
The data type of a function name is determined by using an explicit declaration in the FUNCTION statement
(INTEGER, REAL, DOUBLE PRECISION, LOGICAL,
or CHARACTER), or by following the usual rules for implicit type declaration. For instance, function ABC above
is implicitly declared as REAL because its name starts
with the letter A. If function ABC is to store an integer
value, the following form of the function statement is required:
INTEGER FUNCTION ABC(X,Y,Z)
Likewise, if the function
FUNCTION INDEX(P,Q)
which would normally yield an integer, is to store a real
value, the following form is required:
REAL FUNCTION INDEX(P,Q)
A character function is also possible. For instance, if a
function TIME is to store a character value of length equal
to 40 characters, the following form of the function statement is required:
CHARACTER*40 FUNCTION TIME
Alternatively, in the following example
CHARACTER*(*) FUNCTION TIME
the function TIME assumes the length declared for in the
invoking program unit.
Example: Main Program and
Function Subprogram with
Variable Actual Arguments
C234567890
PROGRAM MAIN_ABC
READ(5,*) A,B
ANSWER= C(A,B)
WRITE(6,100)'THE HYPOTENUSE IS= ',ANSWER
100 FORMAT(1X,A,F10.2)
END
C-----END OF PROGRAM MAIN_ABC
C-----BEGINNING OF FUNCTION C
FUNCTION C(A,B)
C= SQRT(A**2 + B**2)
END
C-----END OF FUNCTION C
|
This example reads the two sides of a right triangle A
and B, invokes the function C to calculate and write the
hypotenuse (ANSWER), preceded by an appropriate label
(THE HYPOTENUSE IS= ). Note that
The function reference in the invoking program must include the actual argument list, as in
ANSWER= C(A,B), and
The function name C must be defined somewhere in the
functions's computing procedure, as in C= SQRT(A**2 + B**2).
In this example, the actual and dummy arguments are
variables and have the same name (A and B). A variation
using constants for the actual arguments is shown in the
next example.
Example: Main Program and
Function Subprogram with
Constant Actual Arguments
C234567890
PROGRAM MAIN_ABC
ANSWER= C(3.,4.)
WRITE(6,100)'THE HYPOTENUSE IS= ',ANSWER
100 FORMAT(1X,A,F10.2)
END
C-----END OF PROGRAM MAIN_ABC
C-----BEGINNING OF FUNCTION C
FUNCTION C(A,B)
C= SQRT(A**2 + B**2)
END
C-----END OF FUNCTION C
|
Things to keep in mind with regard
to function subprograms:
Make sure that the function statement
includes the dummy argument list, as in
FUNCTION C(A,B) above.
Always define the function's value within the
function's computing procedure, as in
C= SQRT(A**2 + B**2) above. Note that the
definition of the function value does not include the argument list.
Always end a function with an END statement. If necessary, use one or more RETURN
statements in the function's computing procedure.
In the invoking program unit, always reference a function by placing it to the right of the
equal sign, as in ANSWER= C(3.,4.) above.
Always include the actual argument list in the
function reference.
|
9.3 SUBROUTINES
A subroutine subprogram is a program unit that has a
SUBROUTINE statement as its first statement and an
END as its last statement.
SUBROUTINE QUADR(A,B,C,R1,R2)
...
END
Like the function subprogram, a subroutine has zero or
more RETURN statements to return control to the calling
program whenever it is required. Control is returned to the
statement immediately following the respective CALL
statement. As with functions, the RETURN statement may
be omitted if there is only one RETURN statement in the
entire program unit, and it immediately precedes the END
statement.
The SUBROUTINE statement consists of the keyword
SUBROUTINE (Table 1.1) followed by the subroutine's
name and a dummy argument list enclosed in parentheses.
The subroutine name is not a scalar variable and cannot
store a value. Both input and output to the subroutine are
contained in the argument list.
An example of the subroutine statement is
SUBROUTINE QUADR(A,B,C,R1,R2)
where QUADR is the subroutine name, and A, B, C, R1,
and R2 are the dummy arguments. This subroutine will
calculate the roots of a quadratic equation ax2 + bx + c = 0
with coefficients A, B, and C as input, and roots R1 and
R2 as output.
Unlike a function, which is referenced by simply
invoking its name, a subroutine is referenced by using a
CALL statement (Table 1.1). An appropriate call to subroutine QUADR is shown in the following sequence of
statements:
DATA A,B,C /1.,-12.,35./
CALL QUADR(A,B,C,R1,R2)
WRITE(6,*)'ROOT 1 IS= ',R1
WRITE(6,*)'ROOT 2 IS= ',R2
The following examples show the use of subroutines.
Example: Main Program and Subroutine with
Actual and Dummy Argument Lists
Having the Same Variable Names
C234567890
C-----BEGINNING OF PROGRAM MAIN_QUADR
PROGRAM MAIN_QUADR
LOGICAL FLAG
DATA FLAG /.FALSE./
READ(5,*) A,B,C
CALL QUADR(A,B,C,RR1,RR2,CRR,CRI,FLAG)
IF(FLAG.NEQV..TRUE.) THEN
WRITE(6,100) 'THE FIRST REAL ROOT IS= ',RR1
WRITE(6,100) 'THE SECOND REAL ROOT IS= ',RR2
ELSE
1'THE FIRST COMPLEX ROOT = ',CRR,'+',CRI,'i'
WRITE(6,200)
1'THE SECOND COMPLEX ROOT='CRR'-'CRI,'i'
ENDIF
100 FORMAT(1X,A,F8.2)
200 FORMAT(1X,2(A,F8.2),A)
END
C-----END OF PROGRAM MAIN_QUADR
C-----BEGINNING OF SUBROUTINE QUADR
SUBROUTINE QUADR(A,B,C,RR1,RR2,CRR,CRI,FLAG)
LOGICAL FLAG
DISC= B**2 - 4*A*C
IF(DISC.GE.O.) THEN
RR1= (-B + SQRT(DISC))/(2*A)
RR2= (-B - SQRT(DISC))/(2*A)
ELSE
CRR= -B/(2*A) CRI= SQRT(-DISC)/(2*A)
FLAG= .TRUE.
ENDIF
END
C-----END OF SUBROUTINE QUADR
|
Example 1 reads the three coefficients A, B, and C of a
quadratic equation, calls subroutine QUADR to calculate
and write the roots, whether real or complex. Notice that
the actual and dummy arguments have the same name.
A variation of the above example using different names
for actual and dummy arguments is shown below.
Example: Main Program and Subroutine with
Actual and Dummy Argument Lists
Having Different Variable Names
C234567890
C-----BEGINNING OF PROGRAM MAIN_QUADR
PROGRAM MAIN_QUADR
LOGICAL FLAG
DATA FLAG /.FALSE./
READ(5,*) A,B,C
CALL QUADR(AC,BC,CC,RROOT1,RROOT2,CRREAL,CRIMAG,FLAG)
IF(FLAG.NEQV..TRUE.) THEN
WRITE(6,100) 'THE FIRST REAL ROOT IS= ',RROOT1
WRITE(6,100) 'THE SECOND REAL ROOT IS= ',RROOT2
ELSE
1'THE FIRST COMPLEX ROOT = ',CRREAL,'+',CRIMAG,'i'
WRITE(6,200)
1'THE SECOND COMPLEX ROOT='CRREAL'-'CRIMAG,'i'
ENDIF
100 FORMAT(1X,A,F8.2)
200 FORMAT(1X,2(A,F8.2),A)
END
C-----END OF PROGRAM MAIN_QUADR
C-----BEGINNING OF SUBROUTINE QUADR
SUBROUTINE QUADR(A,B,C,RR1,RR2,CRR,CRI,FLAG)
LOGICAL FLAG
DISC= B**2 - 4*A*C
IF(DISC.GE.O.) THEN
RR1= (-B + SQRT(DISC))/(2*A)
RR2= (-B - SQRT(DISC))/(2*A)
ELSE
CRR= -B/(2*A) CRI= SQRT(-DISC)/(2*A)
FLAG= .TRUE.
ENDIF
END
C-----END OF SUBROUTINE QUADR
|
In this example, the actual argument list (in the CALL
statement) matches the dummy argument list (in the SUBROUTINE statement) in number, order, and data type, but
not in name. This permits the linkage of calling program
and subroutine through the CALL and SUBROUTINE
statements, provided the corresponding actual and dummy
argument lists match in number, order, and data type, regardless of the variable names.
A variable name which is used exclusively within a
subroutine (for instance, DISC in both examples), cannot
be referenced in the calling program, because it is not an
argument, and therefore, it was not passed back to the calling program. In other words, the calling program has not
been informed of the value of DISC. However, the variable FLAG can be referenced in the calling program, be
cause it is an argument, and it was passed back to the calling program.
Also, note that subroutine QUADR does not have an
explicit RETURN statement. An implicit RETURN is exe
cuted when control reaches the END statement. A RETURN statement is used when the subprogram logic re
quires that control be returned to the calling program
before it has had the chance to reach the END statement.
Multiple RETURN statements are used when the subprogram logic requires that control be returned to the calling
program from one of many places within the subroutine.
9.4 COMMON STATEMENT
Recall how a subroutine connects an actual argument list
with its dummy argument list, storing corresponding arguments in the same storage location. This is why corresponding argument lists should match in number, order,
and data type. Inside the subroutine, the value of an argument has the dummy variable name; outside the subroutine, it has the actual variable name. In essence, it is the
same value, but with two names.
A COMMON statement is a way of defining common
areas of physical storage, to be accessed by two or more
program units. Defining variables in COMMON does
away with the need to pass arguments to subprograms.
Since the variables in COMMON are already held in common areas of storage, they can have only one value.
A common block is a contiguous area of physical stor
age that may be accessed by one or more program units.
The COMMON statement specifies a common block and
the order in which scalar and/or subscripted variables are
stored in it. The COMMON statement is a nonexecutable
statement that is placed in the specification block of a program unit (see Section 8.1).
A COMMON statement can be labeled or unlabeled.
A labeled COMMON specifies a named common block.
The label identifies the named common block and makes it
unique among common blocks. An unlabeled COMMON
specifies a blank common block. An executable program
may have only one blank common block.
The COMMON statement takes the form
COMMON /label1/ a,b,c /label2/ d,e,f
where label1 is the label of a first common block, with a,
b, and c as its listed variables, and label2 is the label of a
second common block, with d, e, and f as its listed variables.
The above statement can also be written in two separate lines or statements:
COMMON /label1/ a,b,c
COMMON /label2/ d,e,f
An example of a blank common block is:
COMMON // p,q,r
The double slash (//) is optional in a blank COMMON. Hence, this COMMON statement can also be written as:
COMMON p,q,r
Two or more corresponding common blocks, which
have the same label but are placed in different program
units, have the same physical storage area and can share
information when the program units are part of one executable program. Adhere to the following guidelines regarding COMMON statements:
The variable lists in corresponding common blocks must
agree in number, order and data type, but not necessarily in name.
COMMON statements can double as array declarators,
to take the place of DIMENSION or other declaration
statements.
Two or more common blocks may have the same named
or blank label. In this case, the variable list following
each successive appearance of the named or blank label
is treated as a continuation of the block associated with
the named or blank label.
Values defined by PARAMETER statements can only
be passed as arguments; they cannot be passed in
COMMON statements.
A common block label is a variable. It may have the
same name as a variable, but not the name of a function,
subroutine, or entry (See Section 9.7).
Variables can be shared by program units by passing:
- All of them as arguments, as in the examples of the preceding section (Section 9.3).
- Some as arguments and the rest in common blocks, as in
the first example of this section.
- All of them in common blocks, as in the second example of this section.
Example: Use of Common Blocks with
Some Variables Passed as Arguments
and Some in Common Blocks
C234567890
C-----BEGINNING OF PROGRAM MAIN_QUADR
PROGRAM MAIN_QUADR
COMMON AC,BC,CC,FLAG
LOGICAL FLAG
DATA FLAG /.FALSE./
READ(5,*) AC,BC,CC
CALL QUADR(RROOT1,RROOT2,CRREAL,CRIMAG)
IF(FLAG.NEQV..TRUE.) THEN
WRITE(6,100) 'THE FIRST REAL ROOT IS= ',RROOT1
WRITE(6,100) 'THE SECOND REAL ROOT IS= ',RROOT2
ELSE
1'THE FIRST COMPLEX ROOT = ',CRREAL,'+',CRIMAG,'i'
WRITE(6,200)
1'THE SECOND COMPLEX ROOT='CRREAL'-'CRIMAG,'i'
ENDIF
100 FORMAT(1X,A,F8.2)
200 FORMAT(1X,2(A,F8.2),A)
END
C-----END OF PROGRAM MAIN_QUADR
C-----BEGINNING OF SUBROUTINE QUADR
SUBROUTINE QUADR(RR1,RR2,CRR,CRI,FLAG)
COMMON AC,BC,CC,FLAG
LOGICAL FLAG
DISC= B**2 - 4*A*C
IF(DISC.GE.O.) THEN
RR1= (-B + SQRT(DISC))/(2*A)
RR2= (-B - SQRT(DISC))/(2*A)
ELSE
CRR= -B/(2*A) CRI= SQRT(-DISC)/(2*A)
FLAG= .TRUE.
ENDIF
END
C-----END OF SUBROUTINE QUADR
|
In the above example, a blank COMMON statement
list the variables AC, BC, CC, and FLAG in the main program, and the corresponding variables A, B, C, and FLAG
in the subroutine. The results of the subroutine computations (the roots of the quadratic) are passed as arguments.
Example: Use of Common Blocks with
All Variables Passed in Common Blocks
C234567890
C-----BEGINNING OF PROGRAM MAIN_QUADR
PROGRAM MAIN_QUADR
COMMON AC,BC,CC,FLAG
COMMON /ROOTS/ RROOT1,RROOT2,CRREAL.CRIMAG
LOGICAL FLAG
DATA FLAG /.FALSE./
READ(5,*) AC,BC,CC
CALL QUADR
IF(FLAG.NEQV..TRUE.) THEN
WRITE(6,100) 'THE FIRST REAL ROOT IS= ',RROOT1
WRITE(6,100) 'THE SECOND REAL ROOT IS= ',RROOT2
ELSE
1'THE FIRST COMPLEX ROOT = ',CRREAL,'+',CRIMAG,'i'
WRITE(6,200)
1'THE SECOND COMPLEX ROOT='CRREAL'-'CRIMAG,'i'
ENDIF
100 FORMAT(1X,A,F8.2)
200 FORMAT(1X,2(A,F8.2),A)
END
C-----END OF PROGRAM MAIN_QUADR
C-----BEGINNING OF SUBROUTINE QUADR
SUBROUTINE QUADR
COMMON A,B,C,FLAG
COMMON /ROOTS/ RR1,RR2,CRR,CRI
LOGICAL FLAG
DISC= B**2 - 4*A*C
IF(DISC.GE.O.) THEN
RR1= (-B + SQRT(DISC))/(2*A)
RR2= (-B - SQRT(DISC))/(2*A)
ELSE
CRR= -B/(2*A) CRI= SQRT(-DISC)/(2*A)
FLAG= .TRUE.
ENDIF
END
C-----END OF SUBROUTINE QUADR
|
In the above example, a COMMON block labeled
ROOTS lists variables RROOT1, RROOT2, CRREAL,
and CRIMAG in the main program, and the corresponding
variables RR1, RR2, CRR, and CRI in the subroutine.
There is no need to pass any arguments.
The use of different variable names in corresponding
common blocks is solely to provide flexibility in naming
variables, to allow main program and subprogram to be
developed independently of one another, say, by different
people. The linkage in meaning, if not in name, is through
the COMMON block.
Examples of the use of COMMON blocks follow.
Example 1
In the main program:
DIMENSION A(10),B(15)
COMMON /LABEL1/ A,B,ITEM,JOB
In the subprogram:
COMMON /LABEL1/ X(10),Y(15),K,L
Real arrays A and B in the main program share the
same storage space with real arrays X and Y in the subprogram. Integer variables ITEM and JOB in the main program share the same storage space with integer variables
K and L in the subprogram. In other words, A and X, B
and Y, ITEM and K, JOB and L have the same value as far
as the executable program is concerned. In the main program, X would be referred with the name A; conversely, in
the subprogram, A would be referred with the name X;
and so on. Although the variables have different names,
they match in number of elements, order, and data type.
Notice that there is no DIMENSION statement in the subprogram; the subscripted variables are being declared directly in the common block.
Example 2
In the main program:
DIMENSION A(10),B(15),C(25)
COMMON /LABEL2/ A,B,C,I,J,K
In the subprogram:
COMMON /LABEL2/ X(25),Y(25),L(3)
This example further shows the correspondence in
number of elements, order, and data type. Real arrays A
and B in the main program share the same storage space
with real array X in the subprogram. Real array C in the
main program shares the same storage space with real array Y in the subprogram. Integer variables I, J, and K in
the main program share the same storage space with integer array L in the subprogram. In the subprogram, the
subscripted variables are being declared directly in the common block. Such mixing of arrays and variable names is
allowed, although seldom necessary.
Example 3
In the main program:
DIMENSION A(10),B(15),C(25)
COMMON /LABEL3/ A,B
COMMON /LABEL4/ C,I,J,K
In the subprogram:
COMMON /LABEL3/ X(25)
COMMON /LABEL4/ Y(25)
COMMON /LABEL4/ L(3)
Real arrays A and B in the main program share the
same storage space with real array X in the subprogram.
Real array C in the main program shares the same storage
space with real array Y in the subprogram. Integer variables I, J, and K in the main program share the same stor
age space with integer array L in the subprogram. In the
subprogram, the second common block LABEL4 is a continuation of the first common block LABEL4. The use of
continuation common blocks may lead to confusion and is
best avoided.
Example 4
In the main program:
COMMON /LABEL5/ A(15),B(10)
COMMON /LABEL6/ C(25),I,J,K
In the subprogram:
COMMON /LABEL5/ X(25)
COMMON /LABEL6/ Y(25),L(3)
This example is similar to Example 3. In this case, the
COMMON statement is doubling as an array declarator in
both program and subprogram. Real arrays A and B in the
main program share the same storage space with real array
X in the subprogram. Real array C and integer variables I,
J, and K in the main program share the same storage space
with real array Y and integer array L in the subprogram.
Example 5
In the main program:
COMMON /LABEL7/ I,J,A(10),B(5),C(5)
In the subprogram:
COMMON /LABEL7/ X(10),Y(15),K
This example is invalid and will cause a compilation or
execution error. The list of scalar and subcripted variables
in corresponding common blocks do not match in number,
order, or data type. A mismatch in any of these would be
sufficient to invalidate the COMMON statements.
9.5 ADJUSTABLE ARRAYS
Main program and subprograms, particularly subroutines,
can share subscripted variables by passing them as arguments or in common blocks. The array sizes are specified
in DIMENSION or COMMON statements.
It is often convenient to size the arrays only in the main
program, rather than in both main program and subroutine.
In this way, the subroutine can be used without modification for applications requiring different array dimensions.
When array sizes are defined in the main program only,
and automatically adjusted in the subroutines, the arrays
are said to be "adjustable."
There are two ways to specify adjustable arrays:
- By passing array names in argument lists.
- By passing array names in common blocks.
The following examples illustrate the use of adjustable
arrays. In Example 1, a two-dimensional array A of M = 4
rows by N = 6 columns is initialized with a DATA statement (all elements are equal to 5. for simplicity). The
main program ARRAY_SUM calls subroutine SUBSUM
to sum up all the elements of the matrix and writes the result (SUM) in the main program. Array A and parameters
M and N are passed to the subroutine as arguments.
Example 2 is similar to Example 1, but a COMMON
block is used to declare and share the array. In the subroutine, the dimension of array A is set at (1,1), the base location of the array, to indicate that it is to be adjusted during
execution to the sizes (M,N) that are being passed as arguments.
The COMMON statement is particularly useful when
there are many variables to be shared, and it would be too
cumbersome to pass all of them as arguments. Otherwise,
the COMMON statement should be used sparingly.
Example 1: Adjustable Arrays Passed as Arguments
C234567890
PROGRAM ARRAY_SUM
PARAMETER (M=4,N=6)
DIMENSION A(M,N)
DATA A /24*5./
CALL SUBSUM(A,M,N,SUM)
WRITE(6,100) 'THE ARRAY SUM IS= ',SUM
100 FORMAT(1X,A,F6.0)
END
C-----END OF PROGRAM ARRAY_SUM
SUBROUTINE SUBSUM(A,M,N,SUM)
DIMENSION A(M,N)
DO 10 J= 1,N
DO 10 K= 1,M
SUM= SUM + A(J,K)
10 END DO
END
C-----END OF SUBROUTINE SUBSUM
|
Example 2: Adjustable Arrays Passed in COMMON
C234567890
PROGRAM ARRAY_SUM
PARAMETER (M=4,N=6)
DIMENSION A(M,N)
DATA A /24*5./
CALL SUBSUM(A,M,N,SUM)
WRITE(6,100) 'THE ARRAY SUM IS= ',SUM
100 FORMAT(1X,A,F6.0)
END
C-----END OF PROGRAM ARRAY_SUM
SUBROUTINE SUBSUM(A,M,N,SUM)
COMMON A(1,1)
DO 10 J= 1,N
DO 10 K= 1,M
SUM= SUM + A(J,K)
10 END DO
END
C-----END OF SUBROUTINE SUBSUM
|
Notice that the actual size of array A is defined only in
the main program's PARAMETER statement. Any change
in the PARAMETER statement will be automatically reflected throughout the executable program.
Local vs Global Variables
Recall that a variable name which is used exclusively
within a subroutine cannot be referenced in the calling program, because it was not passed as an argument or listed in
a common block. This leads us to the concept of local vs
global variables.
Local scalar and subcripted variables are those not
passed as arguments or listed in common blocks. Local
variables have local meaning, that is, they can be used
only within the defining program unit. On the other hand,
global scalar and subcripted variables are those passed as
arguments or listed in common blocks. Global variables
have global meaning, that is, they can be shared by various
program units of an executable program. Unlike global arrays, local arrays are not adjustable,
which may be undesirable in some cases. In order to force
an otherwise local array to become adjustable, it is necessary to convert it to a global array. This can be accom
plished by linking it to a corresponding dummy array in the
calling program. The conversion of a local array into a
global array is illustrated by Examples 3 and 4 below.
In Example 3, the two-dimensional matrix A is read
and passed to subroutine MATMUL, where it is multiplied
by matrix B, defined locally in the subroutine. The result,
matrix C, is passed back to the main program and printed.
Note that matrix B is local to subroutine MATMUL. Its
dimensions (3,2) are fixed in the subroutine; therefore,
they are nonadjustable. Any change in the main program's
PARAMETER statement will not cause a change in the
subroutine's DIMENSION statement. In Example 4, matrix B is globalized by listing it as an argument in the
SUBROUTINE statement. An adjustable array DUMMY
(corresponding to matrix B) is dimensioned in the main
program and listed as an argument in the CALL statement.
Example 3: Local Variable with Nonadjustable
Dimension
C234567890
PARAMETER (MZ=2,NZ=3)
DIMENSION A(MZ,NZ),C(MZ,MZ)
READ(5,100) ((A(J,K),K=1,NZ),J=1,MZ)
CALL MATMUL(A,C,MZ,NZ)
WRITE(6,200) ((C(J,K),K=1,MZ),J=1,MZ)
100 FORMAT(3F5.0)
200 FORMAT(2F5.0)
END
SUBROUTINE MATMUL(A,C,MZ,NZ)
DIMENSION A(MZ,NZ),C(MZ,MZ)
DIMENSION B(3,2)
DO 10 J= 1,NZ
DO 10 K= 1,MZ
B(J,K)= 15.
10 END DO
DO 20 J= 1,MZ
DO 20 K= 1,MZ
DO 20 L= 1,NZ
C(J,K)= C(J,K) + A(J,L)*B(L,K)
20 END DO
END
|
Example 4: Conversion of Local to Global Variable
C234567890
PARAMETER (MZ=2,NZ=3)
DIMENSION A(MZ,NZ),C(MZ,MZ)
DIMENSION DUMMY(NZ,MZ)
READ(5,100) ((A(J,K),K=1,NZ),J=1,MZ)
CALL MATMUL(A,C,MZ,NZ,DUMMY)
WRITE(6,200) ((C(J,K),K=1,MZ),J=1,MZ)
100 FORMAT(3F5.0)
200 FORMAT(2F5.0)
END
SUBROUTINE MATMUL(A,C,MZ,NZ,B)
DIMENSION A(MZ,NZ),C(MZ,MZ)
DIMENSION B(NZ,MZ)
DO 10 J= 1,NZ
DO 10 K= 1,MZ
B(J,K)= 15.
10 END DO
DO 20 J= 1,MZ
DO 20 K= 1,MZ
DO 20 L= 1,NZ
C(J,K)= C(J,K) + A(J,L)*B(L,K)
20 END DO
END
|
In Examples 3 and 4, compare the following:
In Example 3, variable B does not appear anywhere in
the main program. Therefore, it is local to the subroutine. Local variables are dimensioned in the program
unit where they occur. Thus, B cannot be sized as an
adjustable array.
In Example 4, variable B does appear as one of the
dummy arguments listed in the SUBROUTINE state
ment. Therefore, it is global to the executable program.
It is linked to the main program by defining and sizing a
variable DUMMY in the main program, and passing it
as an actual argument in the CALL statement in the
same place as B in the SUBROUTINE statement. In
fact, B and DUMMY are one and the same, particularly
as far as their value is concerned. Accordingly, B can
be sized in the subroutine as an adjustable array.
Things to keep in mind with regard to
functions and subroutines:
- Make sure that each function statement has at
least one argument.
- Make sure that corresponding actual and
dummy argument lists match in number, order,
and data type. Violating this rule could be the
cause of serious errors, which may go unde
tected for some time.
- Do not reference local variables, i.e., those not
passed as arguments or in common blocks, in
the invoking or calling program unit.
- Do not use names of functions or subroutines
as names of common blocks.
|
9.6 EXTERNAL AND INTRINSIC STATEMENTS
So far in this chapter, we have passed variables as arguments to subprograms. However, functions may also be
passed as arguments to subprograms, by using the EXTERNAL and INTRINSIC statements.
The EXTERNAL statement is used to pass user-defined functions (Section 9.2), which are referred to as
external functions because they are not readily recognized
by the processor. The INTRINSIC statement is used to
pass built-in functions (Section 5.4), which are referred to
as intrinsic functions because they are readily recognized
by the processor. When required, the EXTERNAL and INTRINSIC statements are placed in the specification block
of the main program.
The EXTERNAL statement takes the form:
EXTERNAL extrfunc
where extrfunc is an external function name.
If the function name extrfunc happens to be the same as
that of an intrinsic function, the EXTERNAL statement
takes precedence. All subsequent references to extrfunc
are to the external function.
The INTRINSIC statement takes the form:
INTRINSIC intrfunc
where intrfunc is an intrinsic function name. The INTRINSIC statement is required only when intrinsic functions are
being passed as arguments.
A function name that is specified in an EXTERNAL or
INTRINSIC statement can now be used as an actual argument. Then, the subprogram can use the corresponding
dummy argument in an appropriate function reference.
The following example illustrates the use of EXTERNAL and INTRINSIC statements.
Example Program: External and Intrinsic Statements
C234567890
PROGRAM TRIGONOMETRY
EXTERNAL COT,SEC,CSC
INTRINSIC SIN,COS,TAN
PARAMETER (PI=3.141593)
WRITE(6,100) 'ENTER ANGLE IN DEGREES: '
READ(5,*) ANGLED
ANGLE= ANGLED*PI/180.
CALL TRIG(ANGLE,SIN,SINE)
CALL TRIG(ANGLE,COS,COSINE)
CALL TRIG(ANGLE,TAN,TANGENT)
CALL TRIG(ANGLE,COT,COTANGENT)
CALL TRIG(ANGLE,SEC,SECANT)
CALL TRIG(ANGLE,CSC,COSECANT)
WRITE(6,200) 'THE SINE IS= ',SINE
WRITE(6,200) 'THE COSINE IS= ',COSINE
WRITE(6,200) 'THE TANGENT IS= ',TANGENT
WRITE(6,200) 'THE COTANGENT IS= ',COTANGENT
WRITE(6,200) 'THE SECANT IS= ',SECANT
WRITE(6,200) 'THE COSECANT IS= ',COSECANT
100 FORMAT(1X,A,$)
200 FORMAT(1X,A,F10.3)
END
C-----BEGINNING OF SUBROUTINE TRIG
SUBROUTINE TRIG(A,F,Y)
Y= F(A)
END
C-----BEGINNING OF FUNCTION COT
FUNCTION COT(X)
COT= COS(X)/SIN(X)
END
C-----BEGINNING OF FUNCTION SEC
FUNCTION SEC(X)
SEC= 1/COS(X)
END
C-----BEGINNING OF FUNCTION CSC
FUNCTION CSC(X)
CSC= 1/SIN(X)
END
|
This example calculates the value of all six trigonometric functions for an angle ANGLED (in degrees), which is
read interactively. The calculations are made by passing
the angle (in radians) and the various trigonometric functions, both intrinsic and external, to subroutine TRIG.
Note the following:
The functions COT, SEC, and CSC are external to the
processor. They are defined as such with an EXTERNAL statement.
The functions SIN, COS, and TAN are intrinsic to the
processor. These functions are being passed as arguments to subroutine TRIG. Therefore, an INTRINSIC
statement is required in the main program.
The CALL statements to subroutine TRIG (a total of six
calls, one for each trigonometric function) list the angle,
the function, and the value of the function (the result of
the computation) as actual arguments.
The SUBROUTINE statement lists the angle A, the
function F, and the value of the function Y as dummy
arguments.
The external functions COT, SEC, and CSC appear as
part of the executable program. As with all program
units, they end with an END statement.
- The actual and dummy arguments for all subprograms
match in number, order, and data type (variable or function).
9.7 SUMMARY
This chapter describes the use of subprograms. Subprograms are units of a larger executable program, which
comprises exactly one main program and zero or more
subprograms.
Subprograms perform specific tasks on behalf of
another program unit, which is referred to as the invoking or calling program. The invoking or calling program
may be either the main program or another subprogram.
A function is a subprogram that performs one or more
computations, but returns only one value to the invoking
program unit.
A subroutine is a subprogram that typically performs
several computations and returns several values to the
calling program unit.
A statement function is not a subprogram because it is
not a program unit. Unlike a function, a statement function: (1) is defined by a single statement, (2) appears
within a program unit, and (3) is invoked with a function reference only from within the defining program
unit.
A COMMON statement allows the definition of common areas of storage, to be shared and accessed by two
or more program units.
The EXTERNAL statement is used to pass user-defined
functions as arguments to subprograms.
The INTRINSIC statement is used to pass built-in functions as arguments to subprograms.
CHAPTER 9--PROBLEMS
Write a main program that references a function FACTORIAL to
calculate the factorial of argument N, where N is an integer less than or equal
to 30. The output, printed by the main program, should read: THE
FACTORIAL OF _______ IS ____________. If the entered
number is greater than 30, the message ENTERED NUMBER IS OUT
OF RANGE should be generated inside the function, passed back to the
main program, and printed instead of a numeric answer.
Write a main program that references a function SEGMENT to calculate
the area of a segment of a circle of radius r and subtending angle θ.
[As= (1/2)r2(θ - sin θ), with θ in radians]. Input and output should be
either SI units (m) or U.S. customary units (ft). The main program
should print the result as appropriate: THE AREA OF A SEGMENT
OF RADIUS ____ METERS AND SUBTENDING ANGLE
_______DEGREES IS _______ SQUARE METERS. Test your
program first with r= 2.5 m, θ= 135o; then, with r= 5.2 feet, θ= 165o.
Write a main program to read a two-dimensional array of M rows by N
columns, and to reference three functions, ABIG, JBIG, and KBIG, to
determine the value of the largest element, and its row and column position, respectively.
Test your program with the following array.
11. 34. 67. -12. 23. 76. 12.
-10.5 43. 78. 112. -13. -12. 56.5
120. 56. 23. 78. 90. 111. 90.1
Write a main program to read a two-dimensional array of M rows by N
columns, and to call a subroutine AJKBIG to determine the value of the
largest element, and its row and column position. Print the results in
the main program. Test your program with the data of Problem 9.3.
Write a main program that references a function TRAPEZOIDAL to
calculate a definite integral using the trapezoidal formula. The input is
an array of equally-spaced ordinates y0, y1, y2, y3, ..., yn, separated by a
discrete interval h. The trapezoidal formula is:
Area= (h/2) (y0 + 2y1 + 2y2 + 2y3 + ... + 2yn-2 + 2yn-1 + yn).
Print the result (THE AREA BY THE TRAPEZOIDAL FORMULA
IS __________ ) in the main program. Test your program with the
following data: h= 2, n= 10, and y(0:n)= 2.,3.,4.,3.,4.,5.,6.,7.,8.,7.,6.
Write a main program that calls a subroutine SIMPSON to calculate a
definite integral using Simpson's rule. The input is an array of equally-
spaced ordinates y0, y1, y2, y3, ..., yn, (n even), separated by a discrete
interval h. Simpson's rule is:
Area= (h/3) (y0 + 4y1 + 2y2 + 4y3 + ... + 2yn-2 + 4yn-1 + yn).
Print the result (THE AREA BY SIMPSON'S RULE IS
__________ ) in the main program. Test your program with the data
of Problem 9.5.
Write a subroutine to accept a six-digit number representing a date, for
instance, 062094, and to return day, month, and year, with the month a
three-character alphanumeric, such as in: 20 JUN 94. The subroutine
should test for out-of-range month (greater than 12) or day (greater than
31) such as 132589 or 113245, in which case it should issue an appropriate message and stop execution. Test your subroutine with the examples given here. Print the results in the calling program.
Write a subroutine to multiply two-dimensional arrays A and B to obtain
an array C. Test your subroutine with the data of Example Program,
Section 8.8. Print the array C in the calling program. Note that array
initialization in subroutines is not possible with DATA statements.
Write a subroutine that solves for either sin nθ or cos nθ, where n is an
integer between 2 and 4. [Look up the multiple angle formulas in a math
handbook]. Pass n as a parameter to each of two external functions, one
that calculates sin nθ and another cos nθ. Then, in the main program,
calculate tan nθ= (sin nθ)/(cos nθ).
Test your main program, subroutine, and functions with θ= 45o. Provide for the event that some calculated values for the tangent may be infinite. Print the results in the main
program.
Write a function that will sum up the rows and columns of a square matrix of size MZ, to obtain two one-dimensional arrays. Then, multiply
these two arrays to obtain the value of the function. Test your function
with the following matrix (MZ=4):
3.0 4.0 5.0 6.0
4.0 5.0 6.0 7.0
5.0 6.0 7.0 8.0
6.0 7.0 8.0 9.0 Use dummy arrays in main program to size local variables in the function. Print the result in the main program.
Write a subroutine that solves for sinh 2θ, cosh 2θ, and tanh 2θ.
[sinh 2θ = 2 sinhθ × coshθ; and cosh 2θ = 1 + 2 sinh2θ]. Write
appropriate functions for sinhθ, coshθ, tanhθ, sinh 2θ, cosh 2θ, and tanh 2θ.
Test your main program, functions, and subroutine with θ = 45o. Print
the results in the main program.
Write a program that references a function AREA to calculate the area
of a regular polygon of n sides, each of length b. The formula for the
area is: A= (1/4) nb2 cot(π/n). Include the extrinsic function cot(x).
Test your function AREA with n= 6, b= 1.5 m.
Write a subroutine that accepts a two-dimensional array A, of m rows by
n columns, multiplies all entries by a factor k passed as argument, and
stores the result in the same storage location. Test your subroutine with
the following data:
3.0 4.0 5.0 6.0 7.0
5.0 7.0 -9.0 7.0 5.0
7.0 8.0 9.0 8.0 7.0 The factor is k= -3. Print the result in the calling program.
Write a subroutine to calculate the flow area and wetted perimeter of a
parabolic channel of flow depth a and top width b.
The formulas are:
A= (2/3) ab
P= (1/2) (b2 + 16a2)1/2 + [b2/(8a)] ln{[4a +
(b2 + 16a2)1/2 ]/b}.
Test your subroutine with the following data: a= 1.5; b= 2.5. Print the
results in the main program.
Write a subroutine to calculate the parameters a, b, and c of Problem
8.17 (the two-predictor variable nonlinear regression). Set maximum
array size equal to 100. Test your subroutine with the given data. Print
the results in the main program.
|