Fortran - Procedures

A procedure is a group of statements that perform a well-defined task and can be invoked from your program. Information (or data) is passed to the calling program, to the procedure as arguments.
There are two types of procedures −
Functions
Subroutines
A function is a procedure that returns a single quantity. A function should not modify its arguments.
The returned quantity is known as function value, and it is denoted by the function name.
Syntax
Syntax for a function is as follows −
function name(arg1, arg2, ....)  
   [declarations, including those for the arguments]   
   [executable statements] 
end function [name]

The following example demonstrates a function named area_of_circle. It calculates the area of a circle with radius r.
program calling_func

   real :: a
   a = area_of_circle(2.0) 
   
   Print *, "The area of a circle with radius 2.0 is"
   Print *, a
   
end program calling_func


! this function computes the area of a circle with radius r  
function area_of_circle (r)  

! function result     
implicit none      

   ! dummy arguments        
   real :: area_of_circle   
   
   ! local variables 
   real :: r     
   real :: pi
   
   pi = 4 * atan (1.0)     
   area_of_circle = pi * r**2  
   
end function area_of_circle
When you compile and execute the above program, it produces the following result −
The area of a circle with radius 2.0 is
   12.5663710   

Please note that −
You must specify implicit none in both the main program as well as the procedure.
You must specify implicit none in both the main program as well as the procedure.
The argument r in the called function is called dummy argument.
The argument r in the called function is called dummy argument.
If you want the returned value to be stored in some other name than the function name, you can use the result option.
You can specify the return variable name as −
function name(arg1, arg2, ....) result (return_var_name)  
   [declarations, including those for the arguments]   
   [executable statements] 
end function [name]

A subroutine does not return a value, however it can modify its arguments.
Syntax
subroutine name(arg1, arg2, ....)    
   [declarations, including those for the arguments]    
   [executable statements]  
end subroutine [name]

You need to invoke a subroutine using the call statement.
The following example demonstrates the definition and use of a subroutine swap, that changes the values of its arguments.
program calling_func
implicit none

   real :: a, b
   a = 2.0
   b = 3.0
   
   Print *, "Before calling swap"
   Print *, "a = ", a
   Print *, "b = ", b
   
   call swap(a, b)
   
   Print *, "After calling swap"
   Print *, "a = ", a
   Print *, "b = ", b
   
end program calling_func


subroutine swap(x, y) 
implicit none

   real :: x, y, temp   
   
   temp = x  
   x = y 
   y = temp  
   
end subroutine swap
When you compile and execute the above program, it produces the following result −
Before calling swap
a = 2.00000000    
b = 3.00000000    
After calling swap
a = 3.00000000    
b = 2.00000000   

The intent attribute allows you to specify the intention with which arguments are used in the procedure. The following table provides the values of the intent attribute −
The following example demonstrates the concept −
program calling_func
implicit none

   real :: x, y, z, disc
   
   x = 1.0
   y = 5.0
   z = 2.0
   
   call intent_example(x, y, z, disc)
   
   Print *, "The value of the discriminant is"
   Print *, disc
   
end program calling_func


subroutine intent_example (a, b, c, d)     
implicit none     

   ! dummy arguments      
   real, intent (in) :: a     
   real, intent (in) :: b      
   real, intent (in) :: c    
   real, intent (out) :: d   
   
   d = b * b - 4.0 * a * c 
   
end subroutine intent_example
When you compile and execute the above program, it produces the following result −
The value of the discriminant is
   17.0000000    

Recursion occurs when a programming languages allows you to call a function inside the same function. It is called recursive call of the function.
When a procedure calls itself, directly or indirectly, is called a recursive procedure. You should declare this type of procedures by preceding the word recursive before its declaration.
When a function is used recursively, the result option has to be used.
Following is an example, which calculates factorial for a given number using a recursive procedure −
program calling_func
implicit none

   integer :: i, f
   i = 15
   
   Print *, "The value of factorial 15 is"
   f = myfactorial(15)
   Print *, f
   
end program calling_func

! computes the factorial of n (n!)      
recursive function myfactorial (n) result (fac)  
! function result     
implicit none     

   ! dummy arguments     
   integer :: fac     
   integer, intent (in) :: n     
   
   select case (n)         
      case (0:1)         
         fac = 1         
      case default    
         fac = n * myfactorial (n-1)  
   end select 
   
end function myfactorial
When a procedure is contained within a program, it is called the internal procedure of the program. The syntax for containing an internal procedure is as follows −
program program_name     
   implicit none         
   ! type declaration statements         
   ! executable statements    
   . . .     
   contains         
   ! internal procedures      
   . . .  
end program program_name

The following example demonstrates the concept −
program mainprog  
implicit none 

   real :: a, b 
   a = 2.0
   b = 3.0
   
   Print *, "Before calling swap"
   Print *, "a = ", a
   Print *, "b = ", b
   
   call swap(a, b)
   
   Print *, "After calling swap"
   Print *, "a = ", a
   Print *, "b = ", b
 
contains   
   subroutine swap(x, y)     
      real :: x, y, temp      
      temp = x 
      x = y  
      y = temp   
   end subroutine swap 
   
end program mainprog   
When you compile and execute the above program, it produces the following result −
Before calling swap
a = 2.00000000    
b = 3.00000000    
After calling swap
a = 3.00000000    
b = 2.00000000   

 Print
 Add Notes
 Bookmark this page