8. Subprograms

General information

Just like Fortran 77, the language Fortran 90 allows for two types of subprograms: (1) Functions, and (2) Subroutines. In general, there are two forms of subprograms: (1) Internal, and (2) External. Internal subprograms are those routines that may appear within the main program by making use of the CONTAINS statement. We will not discuss these types of subprograms. External subprograms are those which appear in a separate program section after the main program END statement. This is simiilar to the practices we have already encountered in Fortran 77. We will discuss this type of subprogram.

Also, just like Fortran 77, function subprograms in Fortran 90 have an explicit type and are intended to return one value. Subroutine subprograms, on the other hand, have no explicit type and return multiple or no values through a parameter call list.

Because we will be focusing on external subprograms, it is essential that we make use of a feature of Fortran 90 known as the INTERFACE block. This block is safety feature which allows main programs and external subprograms to interface appropriately. An interface block ensures that the calling program and the subprogram have the correct number and type of arguments. This helps the compiler to detect incorrect usage of a subprogram at compile time. An interface block consists of:

   1. The number of arguments
   2. The type of each argument
   3. The type of the value(s) returned by the subprogram

We will address the various aspects of subprograms by a few examples.

Function subprograms

As an example of a program that makes use of a function subprogram, consider the following

PROGRAM Area
!---------------------------------------------------------------------
!
!  This program computes the area of a circle given the input radius
!
!  Uses:  FUNCTION Area_Circle (r)
!
!---------------------------------------------------------------------
IMPLICIT NONE

INTERFACE 
   FUNCTION Area_Circle (r)
     REAL, Area_Circle
     REAL, INTENT(IN) :: r
   END FUNCTION Area_Circle
END INTERFACE

! Declare local variables
REAL :: radius

!  Prompt user for radius of circle
write(*, '(A)', ADVANCE = "NO") "Enter the radius of the circle:  "
read(*,*) radius

! Write out area of circle using function call
write(*,100) "Area of circle with radius", radius, " is", &
            Area_Circle(radius)
100 format (A, 2x, F6.2, A, 2x, F11.2)

END PROGRAM Area

!-----Area_Circle----------------------------------------------------
!
!  Function to compute the area of a circle of given radius
!
!---------------------------------------------------------------------
FUNCTION Area_Circle(r)

IMPLICIT NONE
REAL :: Area_Circle
REAL, INTENT(IN) :: r

! Declare local constant Pi
REAL, PARAMETER :: Pi = 3.1415927

Area_Circle = Pi * r * r

END FUNCTION Area_Circle

This program makes use of the function Area_Circle to compute the area of a circle of radius r. The function appears after the END PROGRAM of the main program Area, so it is classified as an external subprogram. Because it is an external routine, the main program makes use of an interface block to define all of the parameters required by the function Area_Circle.

The Fortran 90 version of the function subprogram operates in much the same manner as the function subprogram in Fortran 77. Note that the only substantive difference here is the ability to explicitly declare the arguments of the function itself. Take special note of the type descriptor INTENT(IN). This attribute of the variable r in the function subprogram identifies the variable r as a strictly input variable. As such it cannot be modified by the subprogram and its modified value unintentionally returned to the main program.

Note also the use of the I/O specifier ADVANCE = "NO" in the write statement prompting the user for the radius of the circle. This option allows the line not to advance after the prompting statement is given. The line will advance on the screen after the user inputs the value of the radius.

Subroutine subprograms

An example of a Fortran 90 subroutine subprogram in action is given here

PROGRAM Area
!---------------------------------------------------------------------
!
!  This program computes the area of a circle given the input radius
!
!  Uses:  SUBROUTINE Compute_Area(r, Area)
!
!---------------------------------------------------------------------
IMPLICIT NONE

INTERFACE 
   SUBROUTINE Compute_Area(r, Area)
     REAL, INTENT(IN) :: r
     REAL, INTENT(OUT) :: Area
   END SUBROUTINE Compute_Area
END INTERFACE

! Declare local variables
REAL :: radius, Area_Circle

! Prompt user for radius of circle
write(*, '(A)', ADVANCE = "NO") "Enter the radius of the circle:  "
read(*,*) radius

! Call subroutine to compute area of circle
CALL Compute_Area(radius, Area_Circle)

! Write out area of circle 
write(*,100) "Area of circle with radius", radius, " is", &
            Area_Circle
100 format (A, 2x, F6.2, A, 2x, F11.2)

END PROGRAM Area

!-----Compute_Area---------------------------------------------------
!
!  Subroutine to compute the area of a circle of given radius
!
!---------------------------------------------------------------------
SUBROUTINE Compute_Area(r, Area)

IMPLICIT NONE
REAL, INTENT(IN) :: r
REAL, INTENT(OUT) :: Area

! Declare local constant Pi
REAL, PARAMETER :: Pi = 3.1415927

Area = Pi * r * r

END SUBROUTINE Compute_Area

This program makes use of the subroutine Compute_Area to compute the area of a circle of radius r. Again, the functionality here is much the same as that of subroutines in Fortran 77.

Note the use of the interface block to define the parameters in the external subroutine as well as the use of the attribute INTENT(OUT) for the return variable Area.

Recursive subprograms

Fortran 90 also allows the use of recursive subprograms. As an example of the utility of such a feature, look at this program which calculates the value of n! using a recirsive function subprogram:

PROGRAM Compute_Factorial
!---------------------------------------------------------------------
!
!  This program computes n! using a recursive function
!
!  Uses:  FUNCTION Factorial(n)
!
!---------------------------------------------------------------------
IMPLICIT NONE

INTERFACE 
   FUNCTION Factorial(n)
     INTEGER :: Factorial
     INTEGER, INTENT(IN) :: n
   END FUNCTION Factorial
END INTERFACE

! Declare local variables
INTEGER :: n

!  Prompt user for radius of circle
write(*, '(A)', ADVANCE = "NO") "Enter n for computing n!:  "
read(*,*) n

! Write out value of factorial using function call
write(*,100) n, "factorial is ", Factorial(n)
100 format (I3, 2x, A, 2x, I12)

END PROGRAM Compute_Factorial

!-----Factorial------------------------------------------------------
!
!  Function to calculate factorials resursively
!
!---------------------------------------------------------------------
RECURSIVE FUNCTION Factorial(n)  RESULT(Fact)

IMPLICIT NONE
INTEGER :: Fact
INTEGER, INTENT(IN) :: n

IF (n == 0) THEN
   Fact = 1
ELSE
   Fact = n * Factorial(n-1)
END IF

END FUNCTION Factorial

Note the attribute RECURSIVE applied to the function Factorial. Also note the RESULT value in the function. This syntax is needed so that the subprogram knows when (and what) to return to the main program when the recursive loop is finished.

Copyright 1996-7 by Stanford University. All rights reserved.