Some Advanced Features of Procedures

Recursion

•      Recursive Calls

–   A procedure can call itself (Self Recursion)

–   A can call B, B calls C, etc,  Z calls A (Mutual Recursion)

•      Powerful Abstraction

–   Many functions are recursive in nature

–   Factorial, Fibonacci, etc.

        fact(0) = 1
        fact(n+1) = (n+1) * fact(n)

        fib(0) = 1
        fib(1) = 1
        fib(n+2) = fib(n+1) + fib(n)

•      Such functions can be directly encoded

Complex control Flow

•      Recursive functions abstracts out complex control flow

–  Different instance of the same procedure exists at a time

–  Termination and resumption of different instances correctly

–  Last called is exited first ( Last In First Out LIFO)

–  Use of stack data structure (stack overflow)

–  A lot of overhead in implementation

Factorial Example

Program fact
     Implicit none
     integer:: N, z
     read *, N
     call fct(N, z)
     print *, z
contains
    recursive subroutine fct(M, y)
    implicit none
    integer, intent(in):: M
    integer, intent(out):: y
    if (M >= 1) then
      call fct(M - 1, y)
      y = M * y
    else
      y = 1
    endif
   end subroutine

end program

Recursive Function

Program fact
   implicit none
   integer:: N, z
   read *, N
   z = fct(N)
   print *, z
contains
   recursive integer function fct(M) result(answer)
   implicit none
   integer:: M,  answer

   if (M /= 0) then
     answer = M * fct(M - 1)
   else
     answer = 1
   endif
   end function

end program

Fibonacci Numbers

Program fibonacci
  
implicit none
   integer:: N, z
   read *, N
   call fib(N, z)
   print *, z
contains
   recursive subroutine fib(M, y)
   implicit none
   integer, intent(in):: M
   integer, intent(out):: y
   integer:: y1, y2
   if (M > 1) then
     call fib(M - 1, y1)
     call fib(M - 1, y2)
     y = y1 + y2
   else
     y = 1
   endif
   end subroutine

end program

Tower of Hanoi Problem

•      Initial Configuration

Final Configuration

Rules

•      Only one disc can be moved at a time

•      bigger disc never placed over a smaller one

•      only one temporary pole

•      How to solve the problem?

Divide and Conquer

•      Reduce the problem size! How?

•      Consider the following situation:

Sub problems

•      How to transfer smaller (n-1) discs from initial pole to temporary pole?

•      How to transfer smaller (n-1) discs to the final pole from temporary pole?

•      These two problems are similar but with the problem size reduced and the initial and final poles being different

•      How to solve the sub problems?

–   Reduce further down (recursion)

•      When (n-1) = 1, the problem becomes trivial

Sub problems

Algorithm hanoi_tower (ndisks, init_pole, spare_pole,                

                                                                        fin_pole)

1. If (ndisks > 0) then

            1.1 hanoi_tower(ndisks - 1, init_pole, fin_pole, 

                                                                  spare_pole)

            1.2 transfer_disk(init_pole, fin_pole)

            1.3 hanoi_tower(ndisks - 1, spare_pole, init_pole,

                                                                          fin_pole)

     end

end

•      When the first argument is 0, no action, only empty recursive calls

•      Simplify by removing the recursive calls for the case ndiscs = 1

Fortran Solution

•      requires modeling the problem domain

•      Need software models for all real objects

•      Discs, poles, movements etc.

•      Discs as numbers, poles as stacks, movements as pushes and pops

Quick Sort

•      quick sort is another sorting algorithm which when implemented properly gives the fastest known sorting algorithm for random inputs

•      useful for sorting arrays rather than lists

•      main idea – pick one element, put it in its correct position, all elements < than it to its left and others to its right

•      recursively sort left and right halves

•      expressed easily using recursion

Quick Sort

recursive subroutine quick_sort(a)

implicit none

integer, dimension(:), intent(inout) :: a

integer :: i,n

n = size(a)

if ( n > 1) then

call partition(a,i)

call quick_sort(a(:i-1))

call quick_sort(a(i+1:))

end if

contains

Partition

subroutine partition(a,j)

integer, dimension(:), intent(inout) :: a

integer,intent(out) :: j

integer :: i,temp

i = 1 ; j = size(a)

do

do

if ( i > j ) exit

if (a(i) > a(1)) exit

i = i+1

end do               

Partition

do

if ((j < i) .or. (a(j) <= a(1)))  exit

j = j-1

end do

if ( i >= j) exit

temp = a(i)

a(i) = a(j)

a(j) = temp

end do

temp = a(j) ; a(j) = a(1) ; a(1) = temp

end subroutine partition

end subroutine quick_sort

Tail Recursion

•      Any number of recursive calls

•      Complex control flow

•      Difficult to understand

•      Linear Recursion

•      Tail recursion

–    The recursive call occurs as the last statement

–    Can be easily translated to iterative programs

•      General recursive programs can also be translated to iterative programs

•      But this requires, in general, a stack (FIFO data structure)

•      Computationally expensive

Keyword Parameters

•       The actual parameter list should match the dummy parameter list in order

•       might prove to be cumbersome when argument lists are large

•       keyword argument is a solution to this problem

•       Suppose

         test(first, second, third)

                 ...

          end subroutine test

•        the following calls are legal:

         test(3, 6, 7)

         test(first = 3, third = 7, second = 6)

         test(3, third = 7, second = 6)

•       Explicit interface for the procedure required

•       Declare it in a module which can be `used' by the calling routine

Optional Parameters

•      Parameters can be optional

•      Declare

–   integer, intent(in), optional:: limit

 

•      The actual argument for limit can be left out in a call and default values can be used

•      A logical function to test whether an optional argument is present or not

 

        if (PRESENT(limit) then

             ...

        else

             ...

        endif