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