hashtabs.f90
MODULE hash_tables
!  mlevels and step define the hash function; set to  prime numbers as required
   integer, parameter                         :: step = 123      
   integer, parameter                         :: mlevels = 99139
!     examples of  prime numbers 
!        small(ish) : 50021, 99139 
!        medium     :  333667, 524827
!        large      : 1299877, 2000003, 
!        huge       : 4000079, 6026179, 8034709  
   integer, save                              :: mlists
   integer, dimension(:,:), allocatable, save :: hlist, running, position
   integer, dimension(:), allocatable, save   :: nlevels
 
  contains
 
! ======================
  subroutine hash_setup
! ======================
 
  implicit none
  integer :: ii
 
  allocate( hlist(0:mlevels,mlists),running(0:mlevels,mlists), &
&           position(0:mlevels,mlists), nlevels(mlists), stat = ii)
  if( ii /=0 ) stop 'alloc hashtabs'
 
  hlist = 0; position = 0; running = 0;  nlevels = 0
 
  return
  end subroutine hash_setup
 
! ======================
  subroutine hash_deall
! ======================
 
  implicit none
  integer :: ii
 
  deallocate( hlist , running, position, nlevels, stat = ii)
  if( ii /= 0) stop 'deall hashtabs'
 
  return
  end subroutine hash_deall
 
! =====================================================
  subroutine hash_it (idorig, ivar, idnew, ipos, noadd)
! =====================================================
 
  implicit none
  integer, intent(in)  :: idorig, ivar
  integer, intent(out) :: idnew, ipos
  logical, intent(in)  :: noadd
  integer              :: ii
 
  if(ivar < 1 .or. ivar > mlists) stop 'HASH : list no.'
 
  idnew = 0; ipos = 0;  if (idorig == 0) return
  ii = mod(idorig,mlevels)+1
 
  do 
      if (hlist(ii,ivar) == idorig) exit          ! ID found
      if (hlist(ii,ivar) == 0 ) then              ! empty cell in hash table
         if( noadd ) return
         nlevels(ivar) = nlevels(ivar) + 1
         if(nlevels(ivar) >= mlevels) stop 'HASH: increase size'
         hlist(ii,ivar) = idorig
         running(ii,ivar) = nlevels(ivar)
         position(nlevels(ivar),ivar) = ii
         exit
      else
         ii = ii + step
         if (ii > mlevels) ii = ii - mlevels
      end if
  end do
  idnew = running(ii, ivar); ipos = position(ii, ivar)
 
  return
  end subroutine hash_it
 
! ==========================================
  integer function hash_idorig (idnew, ivar)
! ==========================================
 
  implicit none
  integer, intent(in) :: idnew, ivar
  integer             :: ii
 
  ii = position(idnew,ivar)
  hash_idorig = hlist(ii,ivar)
 
  return
  end function hash_idorig
 
end module hash_tables
!                                      karin meyer