module  dynamic_memory

public  ::  example

contains

! Subroutines with variable-sized array arguments often need
! temporary, internal, working arrays.  If the subroutine is
! only going to be called a few times it is OK to let the
! subroutine do it's own memory management.  If it is going to
! be called many times it is often more efficient to let the
! caller do the memory management.

! This subroutine can be called as
!   call example(input, output) and it will do memory allocations
! or as
!   call example(input, output, work) and it will use "work"
! for working storage.

subroutine example (input, output, work)

real, intent(in),    dimension (:)                   :: input
real, intent(out),   dimension (:,:)                 :: output
real, intent(inout), dimension (:), optional, target :: work

real, pointer, dimension (:)  :: w1, w2
! w1 will be an array the same size as input
! w2 will be a one dimensional array that is the same size,
! but not the same shape, as output

if (present(work)) then         ! called with 3 arguments
  if (size(work) >= size(input) + size(output)) then
    w1 => work(1:size(input))   ! Use the first part for "array" w1
    w2 => work(size(input)+1:size(input)+size(output))  
  else
    print *, "Work array is too small!"
    stop
  endif
else  ! called with only 2 arguments, get temporary storage 
      ! from the operating system
  allocate (w1(size(input)), w2(size(output)))
endif

!  code which uses w1 and w2 as ordinary arrays
!  ...

if (present(work)) then
  return
else
  deallocate (w1, w2) ! Return the storage to the system
endif
end subroutine example

end module dynamic_memory
