next up previous contents
Next: FUNCTION statements Up: Subprograms Previous: Introduction

   
SUBROUTINE, CALL and RETURN statements

The division of a program into subprograms, and the sharing of data using an argument list is shown in the following example:-

 
        DIMENSION  IA(10),IB(5)
 
        DO 100 I=1,10
100     IA(I)=I
 
        NCOPY=5
200     CALL UCOPY(IA,IB,NCOPY)
 
300     CALL UCOPY(IA,IA(2),9)
 
        STOP
        END
 
c**************************************************
 
        SUBROUTINE UCOPY(IIN,IOUT,NWDS)
 
        DIMENSION  IIN(2),IOUT(2)
 
        DO 100 I=1,NWDS
100     IOUT(I)=IIN(I)
 
        RETURN
        END

This program consists of two routines each terminated by its END statement. The first routine has no special starting statement and so is assumed to be the MAIN routine. When execution of the program starts it will begin with this routine, not because it came first but because it is main. The second routine starts with a SUBROUTINE statement which declares it to have the name UCOPY and that, when called, it will be passed 3 arguments, the first two are arrays and the last is a variable. When the program runs IA is filled with the numbers 1,2,...10 and then the statement 200 is reached which is a call to UCOPY passing over 3 arguments - the arrays IA, IB, and the variable NCOPY that has the value 5. The array arguments are passed BY ADDRESS. That is to say, the positions in memory of IA and IB are passed to UCOPY and are used to define the starting points of the arrays IIN and IOUT. This means that there is an important difference in the two DIMENSION statements. The statement :-

DIMENSION IA(10),IB(5)
declares two single dimension arrays and reserves memory space for them. The statement :-
DIMENSION IIN(2),IOUT(2)
also declares two single dimension arrays but, because their names appear in the argument list of the SUBROUTINE statement does not reserve memory. IIN and IOUT are not local arrays in UCOPY but are defined each time UCOPY is called. So the size declared need not be the full length - often single dimension arrays are declared to be 2 or even 1 ! element long. The last argument of the UCOPY is a variable and is passed BY VALUE i.e. the value in NCOPY (which is 5) is stored in NWDS. When UCOPY has finished the value in NWDS will be copied back into the variable NCOPY. In general a subroutine can have any number of argument or none at all, in which case the brackets are omitted from the CALL and SUBROUTINE statements. Any type of data e.g. real, integer, character etc. can be used as arguments but the type must be consistant between the CALL and the SUBROUTINE e.g. UCOPY must not be called with a third argument having a value of 9.0 for this would store a real in an integer variable. The subroutine UCOPY copies one array into another and on this first call copies the values 1,2..5 into IB. The RETURN statement causes control to pass back to the calling routine with statement 200 complete. The main routine now executes statement 300. This time UCOPY is called with IIN starting at the beginning of IA, IOUT starting at the second element of IA and NWDS equal to 9. (Note the use of the constant in the calling argument list). As the copying of the array proceeds IOUT(1) is set equal to IIN(1) which in fact means that IA(2) is set equal to IA(1). Next IOUT(2) is set equal to IIN(2) i.e. IA(3) is set equal to IA(2). The net result is the value in IA(1) is propagated throughout the array. This serves to underline the fact that IIN and IOUT are not local to UCOPY at all. Although the last argument used in all the call to UCOPY was a constant, this does not stop FORTRAN from returning the value in NWDS. It is returned into a variable in MAIN, created by FORTRAN, to hold the constant 9. Should NWDS be changed then this constant would be corrupted which could produce very odd results if the constant were used again in MAIN. Because array arguments do not reserve memory in the called routine, they can be called with variable length dimensions as illustrated by this subroutine that multiplies 2 matrices together:-

 
        DIMENSION A(7,5),B(5,6),C(7,6)
 
.
.
.
 
        CALL MXMPY(A,B,C,7,5,6)
 
.
.
 
        END
 
        SUBROUTINE MXMPY(A,B,C,N1,N2,N3)
 
C       Multiply matrices A by B and return results in C
 
        DIMENSION A(N1,N2),B(N2,N3),C(N1,N3)
 
 
        DO 100 I1=1,N1
        DO 100 I3=1,N3
        C(I1,I3)=0
        DO 100 I2=1,N2
100     C(I1,I3)=C(I1,I3)+A(I1,I2)*B(I2,I3)
 
 
        RETURN
        END
The DIMENSION statement in MXMPY tells FORTRAN how the arrays will be arranged in memory - this information is not passed when the program is running - only the starting addresses are transmitted. This means that a calling routine could pass an array and the called routine declare it with a different number of dimensions. This is not generally a good practice unless the programmer is using his or her knowledge of the way an array is organised to process a subarray within it. For example suppose we have:-
DIMENSION A(7,11),B(7,15)
then we could use UCOPY (shown earlier) to copy A(1,5),A(2,5)... A(7,5) into B(1,9),B(2,9)...B(7,9) by:-
CALL UCOPY(A(1,5),B(1,9),7)
because we know that these elements are contiguous (i.e. adjacent). However, UCOPY could not be used to copy say A(3,1),A(3,2)... into B(6,1),B(6,2)...

Exercise 15
Write a subroutine CROSS(A,B,C) that forms the 3-vector cross product of A and B and stores the results in C. Use this subroutine within a second one called TCROSS(A,B,C,D) to calculate (AxB)xC and return the result in D. Add a MAIN subprogram to pass test data to TCROSS and type out the results.
* * *

Besides the subroutines written by the user there are many available in libraries ready to be built into programs - see section 19 for more details.


next up previous contents
Next: FUNCTION statements Up: Subprograms Previous: Introduction
n west (APC)
2000-03-08