- Intrinsic functions
- External functions
- Statement functions
- Subroutines
- Procedures as arguments
- Local variables

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.

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.

NameTypeDefinitionABS(IR)Generic Absolute value:IRACOS(R)REAL arccos(R)AINT(R)REAL Truncation:REAL(INT(R))ANINT(R)REAL Nearest whole number:REAL(INT(R+0.5))ifR0REAL(INT(R0.5))ifR0ASIN(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)REALINT(R)INTEGER INTEGER portion ofRLOG(R)REAL Natural logarithm: logeRLOG10(R)REAL Common logarithm: log10RMAX(IR1,IR2,...)Generic Largest ofIR1,IR2,...MIN(IR1,IR2,...)Generic Smallest ofIR1,IR2,...MOD(IR1,IR2)Generic Remainder:IR1-INT(IR1/IR2)*IR2NINT(R)INTEGER Nearest integer:INT(ANINT(R))REAL(I)REAL Real equivalent ofISIGN(IR1,IR2)Generic Transfer of sign:IR1 if IR20IR1 if IR2<0SIN(R)REAL sin(R)SINH(R)REAL sinh(R)SQRT(R)REALRTAN(R)REAL tan(R)TANH(R)REAL tanh(R)

*Figure 18: Some
common intrinsic 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.

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

[type] FUNCTIONname([argument_list])

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

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

*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()

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) ...

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.

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.

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.

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

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:

nameis the name of the statement function.argument_listis a list of dummy arguments.expressionis 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

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.

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

SUBROUTINEname[(argument_list)]

where *name** *and *argument**_*` list`
have the same meanings as in the

SUBROUTINEname

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:

CALLname[(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:

- Increment the page number.
- 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)*

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

`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:

- used as a procedure in a CALL statement or function reference, or:
- 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.*

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