Functions and subroutines

 


 

Very often, a program has to perform a computation several times using different values, producing a single value each time. An example is the conversion of an angle in degrees to an equivalent in radians in Example 1 of the previous chapter.

In FORTRAN, such a computation can be defined as a function and referred to by a name followed by a list of the values (called arguments) which it uses, in parentheses, i.e.

name([argument_list])

where argument_list is an optional list of arguments separated by commas. Note that the parentheses must be included even if argument_list is omitted, i.e.

name()

Such a function reference can be used in the same way as a variable or array element, except that it cannot be the object of an assignment. Like a variable or array element, a function reference is evaluated and the value obtained is substituted for it in the expression in which it appears. The type of a function is the type of the value so obtained.

Thus, in the above example, a REAL function DGTORD might be defined to convert an angle in degrees to an equivalent in radians. The function would have a single argument, of type INTEGER, representing the value of the angle in degrees, and would be evaluated to obtain the equivalent in radians. The function might be used in an assignment statement like:

	RADIAN = DGTORD(DEGREE)

The definition of a function must include a definition of its type and the number and types of its arguments. In a function reference the number and type of the arguments must be as defined. Thus, for example:

	RADIAN = DGTORD(DEGREE,X)

would be an error.

As the above example illustrates, a function reference has an identical form to an array element, and may be used in a similar context. FORTRAN distinguishes between the two by checking whether the name has been declared as an array, and assuming that it is a function if it has not. Thus, for example, if DGTORD were declared as:

REAL DGTORD(100)

then DGTORD(DEGREE) would be interpreted as an array element and not a function reference.

Intrinsic functions

FORTRAN provides a wide range of intrinsic functions, which are defined as part of the language. Many of them have an argument, or list of arguments, which may be of different types in different references. Most, though not all, of these return a value of the same type as that of their arguments in any reference. For example, the function ABS returns the absolute value of its argument, which may be REAL or INTEGER. Thus

	ABS(X)

returns the absolute value of the REAL variable X as a REAL value, while

	ABS(N)

returns the absolute value of the INTEGER variable N as an INTEGER value.

A function of this kind is called a generic function. Its name really refers to a group of functions, the appropriate one being selected in each reference according to the type of the arguments.

Figure 18 is a list of some of the more frequently used intrinsic functions. I and R indicate INTEGER and REAL arguments respectively. Where an argument represents an angle, it must be in radians.

Name               Type       Definition                                  

ABS(IR)            Generic    Absolute value: IR                          

ACOS(R)            REAL       arccos(R)                                   

AINT(R)            REAL       Truncation: REAL(INT(R))                    

ANINT(R)           REAL       Nearest whole number: REAL(INT(R+0.5)) if   
                              R0                                          
                               REAL(INT(R0.5)) if R0                      

ASIN(R)            REAL       arcsin(R)                                   

ATAN(R)            REAL       arctan(R)                                   

COS(R)             REAL       cos(R)                                      

COSH(R)            REAL       cosh(R)                                     

DIM(IR1,IR2)       Generic    Positive difference: MAX(IR1-IR2,0)         

EXP(R)             REAL                                                   

INT(R)             INTEGER    INTEGER portion of R                        

LOG(R)             REAL       Natural logarithm: logeR                    

LOG10(R)           REAL       Common logarithm: log10R                    

MAX(IR1,IR2,...)   Generic    Largest of IR1,IR2,...                      

MIN(IR1,IR2,...)   Generic    Smallest of IR1,IR2,...                     

MOD(IR1,IR2)       Generic    Remainder: IR1-INT(IR1/IR2)*IR2             

NINT(R)            INTEGER    Nearest integer: INT(ANINT(R))              

REAL(I)            REAL       Real equivalent of I                        

SIGN(IR1,IR2)      Generic    Transfer of sign: IR1 if IR20               
                               IR1 if IR2<0                               

SIN(R)             REAL       sin(R)                                      

SINH(R)            REAL       sinh(R)                                     

SQRT(R)            REAL       R                                           

TAN(R)             REAL       tan(R)                                      

TANH(R)            REAL       tanh(R)                                     


Figure 18: Some common intrinsic functions

External functions

As well as using the intrinsic functions provided by the language, a programmer may create and use his/her own external functions. These functions may be included in the same source file as a program which uses them and compiled along with it, or may be written and compiled separately to obtain separate object files which are then linked to the object version of the program to obtain an executable program, in the same way as the library subprograms shown in Figure 3 on page 2. In either case, the program and functions are entirely independent program units.

A FORTRAN source file consists of one or more program units in any order. One of these may be a main program unit, which begins with an optional PROGRAM statement and ends with an END statement. The others are subprograms, which may be external functions or subroutines. (Subroutines are explained later in the chapter.)

An external function program unit begins with a FUNCTION statement and ends with an END statement.

Figure 19 illustrates a FORTRAN source file containing three program units, a main program MAIN and two functions FUN1 and FUN2. The order of the program units is immaterial.

PROGRAM MAIN
	.
	.
END
FUNCTION FUN1(arg1,...)
	.
	.
END
FUNCTION FUN2(arg1,...)
	.
	.
END

Figure 19: A FORTRAN source file containing two functions

Provided that the program MAIN includes no references to any other external functions, the file could be compiled, and the resulting object file linked with the library subprograms to obtain an executable program.

The functions might also be placed in one or two separate files and compiled separately from the main program. The object file or files thus obtained could then be linked with the library subprograms and the object version of the program MAIN or any other program containing references to them. In this way a programmer can create his/her own subprogram libraries for use by any program.

The FUNCTION statement

As shown above, an external function must begin with a FUNCTION statement. This has the form:

	[type] FUNCTION name([argument_list])

As before, square brackets indicate that an item is optional.

Type

Each function has a type corresponding to the type of value returned by a reference to it. As for variables, the type of a function may be specified explicitly or assigned implicitly according to the first letter of the function name. For example, the function:

	FUNCTION FUN1(arg1,...)

returns a value of type REAL, but

	INTEGER FUNCTION FUN1(arg1,...)

returns a value of type INTEGER.

If the type of a function differs from that implied by the first letter of its name, it must be declared in a type specification in any program which refers to it. Thus any program using the second version of FUN1 above would include the name FUN1 in an INTEGER type specification statement, e.g.

	INTEGER FUN1

The argument list

argument_list is an optional list of dummy arguments, separated by commas. Each dummy argument is a name similar to a variable or array name, which represents a corresponding actual argument used in a function reference. Dummy arguments, and variables used in a function, are defined only within it. They may therefore be identical to variable or array names used in any other program unit.

If a dummy argument represents an array, it must appear in a type specification or DIMENSION statement in the function. If it represents a variable, it may appear in a type specification, or may be typed by default.

Example:

	FUNCTION FUN1(A,B,N)
	REAL A(100)
	INTEGER B

Here, A represents a REAL array of dimension 100, and B and N represent INTEGER variables.

A function may have no arguments, e.g.

	FUNCTION NOARGS()

The function reference

As we have seen, a function reference has the form:

name(argument_list)

argument_list is a list of actual arguments, which must match the list of dummy arguments in the FUNCTION statement with respect to the number of arguments and the type of each argument. For example:

	REAL X(100)
		.
	RESULT = FUN1(X,J,10)

would be a valid reference to the function FUN1(A,B,N) shown above.

If a dummy argument is a variable name, the corresponding actual argument may be any expression of the same type, i.e. a constant, variable, array element or more complex arithmetic expression.

If a dummy argument is an array name, the actual argument may be an array or array element. The dimensions of the dummy array may be variable if they are also dummy arguments.

Example:

	REAL X(5,10)
		...
	Y = FUN(X,5,10)
		...
	END
	FUNCTION FUN(A,M,N)
	REAL A(M,N)
		...

Actual and dummy arguments

The dummy arguments and corresponding actual arguments provide a means of exchanging information between a program unit and a function.

Each actual argument refers to a word or other unit of storage. However, no storage is reserved for a dummy argument; it is simply a name. When a function reference is evaluated, the address of each actual argument is passed to the function, and the corresponding dummy argument is set to refer to it. The dummy argument may therefore be used in the function as a variable or array referring to the same unit of storage as the actual argument.

Thus if a dummy argument represents a variable, its value on entry to the function is that of the corresponding actual argument when the function is referenced. If its value is changed in the function by an assignment or READ statement, the actual argument will be correspondingly changed after the function reference has been evaluated.

Arrays as arguments

If a dummy argument is an array, the corresponding actual argument may be an array or array element. In the former case, the elements of the dummy array correspond to the elements of the actual array in the order of their storage in memory. This, however, does not imply that the subscripts are identical, or even that the two arrays have the same number of subscripts. For example, suppose that the function:

	FUNCTION FUN(A)
	REAL A(9,6)
		.
	END

is referenced by program MAIN as follows:

	PROGRAM MAIN
	REAL X(100),Y(0:5,-10,10)
		.
	F1 = FUN(X)
	F2 = FUN(Y)
		.
	END

Then the correspondence between some elements of the dummy array A and the actual arrays X and Y in the two function references is as shown below:

A(1,1)   X(1)     Y(0,-10)    

A(6,1)   X(6)     Y(5,-10)    

A(7,1)   X(7)     Y(0,-9)     

A(1,2)   X(10)    Y(3,-9)     

A(5,4)   X(32)    Y(1,-5)     

A(9,6)   X(54)    Y(5,-2)     


If the actual argument is an array element, the first element of the dummy array corresponds to that element. Thus, if the function references:

	F3 = FUN(X(15))
	F4 = FUN(Y(3,0))

were included in the program above, the following items would correspond in the two references:

A(1,1)   X(15)    Y(3,0)    

A(4,1)   X(18)    Y(0,1)    

A(9,1)   X(23)    Y(5,1)    

A(1,2)   X(24)    Y(0,2)    

A(5,4)   X(46)    Y(4,5)    

A(9,6)   X(68)    Y(2,9)    


Such complicated relationships between actual and dummy arguments can sometimes be useful, but are in general best avoided for reasons of clarity.

Evaluation of a function

Once the dummy arguments have been initialised as described above, the statements comprising the body of the function are executed. Any statement other than a reference to the function itself may be used. At least one statement must assign a value to the function name, either by assignment, or less commonly, by a READ statement. Execution of the function is stopped, and control returned to the program unit containing the function reference, by a RETURN statement, written simply as:

	RETURN

The value of the function name when RETURN is executed is returned as the function value to the program unit containing the function reference.

Examples

We can now write the function DGTORD suggested at the beginning of the chapter, to convert an INTEGER value representing an angle in degrees, to a REAL value representing the equivalent in radians. Our function uses the intrinsic function ATAN to compute the conversion factor.

	FUNCTION DGTORD(DEG)
	INTEGER DEG
	CONFAC = ATAN(1.0)/45.0
	DGTORD = DEG*CONFAC
	RETURN
	END

As a second example, the following function returns the mean of an array of N real numbers.

	REAL FUNCTION MEAN(A,N)
	REAL A(N)
	SUM = 0.0
	DO 10, I=1,N
	10	SUM = SUM+A(I)
	MEAN = SUM/N
	RETURN
	END

Note that, since the type of this function differs from that implied by the first letter of its name, any program referring to it must declare the name in a type specification, e.g.

	REAL MEAN

Statement functions

If a function involves only a computation which can be written as a single statement, it may be declared as a statement function in any program unit which refers to it. The declaration has the form:

name(argument_list) = expression

where:

name          is the name of the statement function.                     

argument_list is a list of dummy arguments.                              
                                                                         

expression    is an expression which may include constants, variables    
              and array elements defined in the same program unit, and   
              function references.                                       


The declaration must be placed after all type specifications, but before the first executable statement.

Thus the function DGTORD might be declared as a statement function in the program ANGLES:

	DGTORD(DEGREE) = DEGREE*ATAN(1.0)/45.0

Rules

The name of a statement function must be different from that of any variable or array in the same program unit.

The type of a statement function may be specified explicitly in a separate type specification or determined implicitly by the first letter of its name.

A dummy argument may have the same name as a variable or array in the same program unit. If so, it has the same type as the variable or array but is otherwise distinct from it and shares none of its attributes. For example, in the program ANGLES, the dummy argument DEGREE of the statement function DGTORD has the same name as the variable DEGREE declared in the program, and therefore has the correct (INTEGER) type, but is a different entity. If the program included the declaration:

	INTEGER DEGREE(100)

the dummy argument DEGREE would be an INTEGER variable, not an array.

If a dummy argument does not have the same name as a variable or array in the same program unit, it is typed implicitly according to its first letter, e.g.

	DGTORD(IDEG) = IDEG*ATAN(1.0)/45.0

expression may include references to functions, including statement functions. Any statement function must have been previously defined in the same program unit.

Subroutines

A subroutine is a subprogram similar in most respects to a function. Like a function, a subroutine has a list of dummy arguments used to exchange information between the subroutine and a program unit referring to it. Unlike a function, a subroutine does not return a value via its name (and therefore has no type), but it may return one or more values via its arguments.

A subroutine subprogram begins with a SUBROUTINE statement and ends with END. The SUBROUTINE statement has the form:

	SUBROUTINE name[(argument_list)]

where name and argument_list have the same meanings as in the FUNCTION statement. The square brackets indicate that the item (argument_list) is optional, i.e. a subroutine may have no arguments, in which case the SUBROUTINE statement is simply:

	SUBROUTINE name

As for a function, a subroutine must include at least one RETURN statement to return control to the program unit referring to it.

A subroutine is referenced by a CALL statement, which has the form:

	CALL name[(argument_list)]

where argument_list is a list of actual arguments corresponding to the dummy arguments in the SUBROUTINE statement. The rules governing the relationship between actual and dummy arguments are the same as for functions.

Functions (intrinsic and external) and subroutines are often called procedures.

In Example 1 of Chapter 8, the steps required to print a page header and column headers at the top of each page might be written as a subroutine. The steps are:

  1. Increment the page number.
  2. Print a page header, page number and column headers, followed by a blank line.

The subroutine therefore has two dummy arguments, one representing the page number and the other representing the output device, and includes the WRITE statement and FORMAT statements required to print the page and column headers. The subroutine follows:

	SUBROUTINE HEADER(PAGENO,OUTPUT)
C PRINT PAGE HEADER, NUMBER AND COLUMN HEADERS
	INTEGER PAGENO,OUTPUT
	PAGENO = PAGENO+1
	WRITE(OUTPUT,100)PAGENO
	100	FORMAT(1H1//1X,'DEGREES TO RADIANS CONVERSION TABLE',
	*	T74,'PAGE',I2//1X,'DEGREES  RADIANS'/)
	RETURN
	END

Note that the argument OUTPUT is used to receive a value from the calling program, while PAGENO both receives and returns a value.

The degrees to radians conversion program can now be rewritten using the subroutine HEADER and function DGTORD as follows:

	PROGRAM ANGLES
	INTEGER DEGREE,PAGENO,OUT
	DATA OUT/6/
C UNIT NUMBER FOR OUTPUT. A DIFFERENT DEVICE COULD BE USED BY
C CHANGING THIS VALUE
	DATA PAGENO/0/
	DO 10, DEGREE = 1,360
	N = DEGREE-1
	IF (N/40*40 .EQ. N) THEN
	CALL HEADER(PAGENO,OUT)
	ELSE IF (N/10*10 .EQ.N) THEN
		WRITE(OUT,110)
	END IF
	10	WRITE(OUT,120)DEGREE,DGTORD(DEGREE)
	110	FORMAT(1X)
	120	FORMAT(1X,I5,T10,F7.5)
	END

Figure 20: Degrees to radians conversion program (version 4)

Procedures as arguments

A program unit can pass the names of procedures as arguments to a function or subroutine. The calling program unit must declare these names in an EXTERNAL statement for external procedures (functions or subroutines), or INTRINSIC statement for intrinsic functions. The statements have the form:

EXTERNAL list

and INTRINSIC list

respectively, where list is a list of external procedures, or intrinsic functions respectively.

If an actual argument is a procedure name, the corresponding dummy argument may be:

  1. used as a procedure in a CALL statement or function reference, or:
  2. passed as an actual argument to another procedure. In this case, it must be listed in an EXTERNAL statement.

In this way, a procedure name can be passed from one procedure to another for as many levels as required.

Example 1

In Figure 21, the program MAIN passes the names of the subroutine ANALYS and the intrinsic function SQRT as actual arguments to the subroutine SUB1, corresponding to its dummy arguments SUB and FUN respectively. In SUB1, SUB appears in a CALL statement in which it is replaced in this instance by a call of ANALYS, while FUN appears in an EXTERNAL statement and is passed as an actual argument to SUB2, corresponding to its dummy argument F. In SUB2, F appears followed by a left parenthesis. Because F is not declared as an array, this is interpreted as a function reference, and is replaced by a reference to SQRT.

Note that although SQRT is an intrinsic function and is declared as such in program MAIN, FUN, the corresponding dummy argument of subroutine SUB1, is declared in SUB1 as EXTERNAL because FUN is a dummy procedure name corresponding to a function defined externally to SUB1.

	PROGRAM MAIN
	EXTERNAL ANALYS
	INTRINSIC SQRT
		.
	CALL SUB1(ANALYS,SQRT,A,B)
		.
	END
	SUBROUTINE SUB1(SUB,FUN,X,Y)
	EXTERNAL FUN
		.
	CALL SUB(...)
		.
	CALL SUB2(FUN,X,Y)
		.
	END
	SUBROUTINE SUB2(F,P,Q)
		.
	Q = F(P)
		.
	END

Figure 21: Procedures as arguments

Example 2

In Figure 22, the subroutine TRIG has three dummy arguments, X representing an angle in radians, F representing a trigonometric function, and Y representing that function of X. The main program includes four calls to TRIG, using the intrinsic functions SIN, COS and TAN and the external function COT, which computes the cotangent.

	PROGRAM MAIN
	EXTERNAL COT
	INTRINSIC SIN,COS,TAN
		.
	CALL TRIG(ANGLE,SIN,SINE)
		.
	CALL TRIG(ANGLE,COS,COSINE)
		.
	CALL TRIG(ANGLE,TAN,TANGT)
		.
	CALL TRIG(ANGLE,COT,COTAN)
		.
	END
	SUBROUTINE TRIG(X,F,Y)
	Y = F(X)
	RETURN
	END
	FUNCTION COT(X)
	COT = 1.0/TAN(X)
	RETURN
	END

Figure 22: Subroutine to compute any trigonometric function.

Local variables

The variables used in a subprogram, other than its arguments, are local variables, defined only within it, and therefore distinct from any identically named variables used elsewhere. When a RETURN statement is executed, they become undefined, and their addresses may be used by other program units. Therefore, if a subprogram is executed several times, the values of its local variables are not preserved from one execution to the next.

The values of local variables can be preserved by a SAVE statement, which has the form:

	SAVE [variable_list]

where variable_list is a list of local variables, separated by commas. The statement causes the values of all variables in variable_list to be saved. If variable_list is omitted, the values of all local variables are saved.

SAVE is a non-executable statement and must be placed before the first executable statement or DATA statement.

Example:

Each time the following function is executed, it prints a message indicating how many times it has been referenced.

	FUNCTION AVE(X,Y)
	INTEGER COUNT
	SAVE COUNT
	DATA COUNT/0/
	COUNT = COUNT+1
	WRITE(6,10)COUNT
		...
	10	FORMAT(1X,'FUNCTION AVE REFERENCED',I3,' TIMES.')
			...
	END

[Contents]  [Previous]  [Next]  [Home]

NDP77
http://www.ndp77.net
webmaster Massimo F. ARENA
webmaster@ndp77.net
2004:02:14:17:30:17