Man page of libmodhash

MODHASH(3)         Library Functions Manual         MODHASH(3)

NAME
       MODHASH  -  Implementation  of an ordered, automatically resizing, hash
       table for fortran 90

SYNOPSYS
       use modhash

       subroutine init(this,m,keylen,notfound): initialize hash table
       this:  class(hashtable)

       m: integer, intent(in), optional: Size of table, default 100
       if m < 1 or absent : size will be 100

       keylen: integer, intent(in), optional: Use at least keylen and at  most
       2*keylen characters computing the hash value.
       If keylen .le. 0: use all characters.

       notfound:  character(len=*), intent(in), optional: Value to return from
       lookup() when key is not found
       default ""

       usetrim: logical, intent(in), optional: .true.: Use trim  on  keys  and
       values, else do not use trim
       default .true.

       Note: init can be used on an existing hashtable, the existing hashtable
       will be cleaned.
       See also: resize.

       function insert(this,key,val) result(r): insert key/value pair in  hash
       table
       this:  class(hashtable)

       key, val: character(len=*), intent(in): Key/value pair to insert in the
       hash table.

       r:   logical, intent(out): .true. on success
       Normally, one expects this always to be .true.
       Note: if the number of items exceeds 0.7 * the size of  the  hashtable,
       the hashtable is resized.

       function  lookup(this,key,success) result(val): return value associated
       with key
       this: class(hashtable)

       key:  character(len=*), intent(in): Key to search for.

       success: logical, intent(out), optional: .true. if key is  found,  else
       .false.

       val: character(len=:), allocatable: Value associated with key.
       If key is not found, val = notfound (see init()).

       subroutine delete(this,key): deletes key/value pair
       this: class(hashtable)

       key:  character(len=*), intent(in): Key to delete.

       Note:  the key/value pair is marked as deleted, if you want to optimize
       the hash table after many deletions, use resize().

       function find(this,key) result(j): find index of key in hash table
       this: class(hashtable)

       key:  character(len=*), intent(in): Key to find.

       j:    integer: Index to be used with getkey and getval.
       If key not found: j = 0
       Usage is not recommended.
       See also: lookup()

       function getkey(this,j) result(key): return key at index
       this: class(hashtable)

       j:    integer, intent(in): Index to use.

       key: character(len=:), allocatable: Key on index j.
       Note: no check is done on validity of j.
       Usage is not recommended.
       See also: lookup()

       function getval(this,j) result(val): return value at index
       this: class(hashtable)

       j:    integer, intent(in): Index to use.

       val: character(len=:), allocatable: Value on index j.
       Note: No check is done on validity of j.
       Usage is not recommended.
       See also: lookup()

       subroutine stats(this,m,items,collisions,resizes,deletions,
       keylen,notfound): statistics about the hash table
       this: class(hashtable)

       m:    integer, intent(out), optional: Size of hash table.

       items: integer, intent(out), optional: Number  of  key/value  pairs  in
       hash table, including deleted items.

       collisions:  integer, intent(out), optional: Total number of collisions
       (i.e. different keys with same hash value).

       resizes: integer, intent(out), optional: Total number of resizes of the
       hash table.

       deletions:  integer,  intent(out),  optional:  Total  number of deleted
       items in the hash table.

       keylen: integer, intent(out), optional: Keylen used, see init().

       notfound: character(len=:), intent(out), allocatable,  optional:  Value
       returned by lookup() if key not found.

       subroutine  getentry(this,  n, r, key, val, del): main purpose: Get all
       entries from the hash table.
       this: class(hashtable)

       n:     integer, intent(inout)
       input: index of item to visit
       output: actual index used

       r:     logical, intent(out): .true. if item found, else .false.

       del:   logical, intent(out): .true. if found item was deleted,  .false.
       otherwize

       key, val: character(len=:), allocatable, intent(out): key/value pair of
       item.  If not found: val = notfound (see init())

       Note: this subroutine can be used to list all entries in the  hash  ta‐
       ble, see example.

       subroutine resize(this,n): resize hash table, get rid of deletions
       this: class(hashtable)

       n:    integer, intent(in), optional
       if  not  present: New size is calculated to allocate space for approxi‐
       mately two times the current not-deleted items.
       == 0: New size is calculated to hold the current not-deleted items.
       != 0: The new size will be n. If this value is to low to hold the  not-
       deleted items: no resizing will be done.

       Note: resizing is automatically done in insert() when needed.

       subroutine cleanup(this) : deallocates contents of hash table
       this: class(hashtable)

EXAMPLE PROGRAM
    ---->

    program example
      use modhash
      implicit none
      type(hashtable) :: h
      logical     :: success, del
      integer     :: j,dels,items,i
      character(len=:), allocatable :: key,val
      print *,"Initializing..."
      call h%init(notfound="NOT FOUND")
      print *,"Inserting..."
      success = h%insert("first key","first value")
      success = h%insert("2nd key","2nd value")
      success = h%insert("3rd key","3rd value")
      j = h%find("first key")   ! not recommended, use lookup
      key = h%getkey(j)     ! not recommended, use lookup
      val = h%getval(j)     ! not recommended, use lookup
      print *, "Using stats ..."
      call h%stats(deletions=dels, items=items)
      print *,"deletions:",dels,"items",items
      print *,"Using lookup ..."
      val = h%lookup("2nd key")
      print *,"2nd key: ",val
      print *,"Using lookup with not existing key ..."
      val = h%lookup("xnd key")
      print *,"xnd key: ",val
      print *,"Deleting:"
      call h%delete("first key")
      print *, "Using stats again ..."
      call h%stats(deletions=dels, items=items)
      print *,"deletions:",dels,"items",items
      print *,"All entries ..."
      i = 1
      success = .true.
      do while(success)
         call h%getentry(i, success, key, val, del)
         if (success) print *,"key: ",key," value: ",val," deleted:",del
         i = i+1
      enddo
      print *,"Resizing ..."
      call h%resize(0)
      print *, "Using stats again ..."
      call h%stats(deletions=dels, items=items)
      print *,"deletions:",dels,"items",items
      print *,"removing contents of hash table ..."
      call h%cleanup
    end program example

    <----

EXAMPLE PROGRAM USING TRANSFER
    ---->

       !  example  using modhash with other data types, using transfer program
       cryst
      use modhash
      implicit none
      integer(selected_int_kind(3)) :: hkl(3,2)
      type reftype
         real e
         real r
         integer(selected_int_kind(2)) :: m
      end type reftype
      type(reftype)   :: a,b,c
      type(hashtable) :: h
      real        :: eps = 0.00001

      character(len=:), allocatable :: hc,rc
      logical           :: success

      allocate(character(len=sizeof(hkl(:,1))) :: hc)
      allocate(character(len=sizeof(a))    :: rc)

      print *,"len hc:",len(hc)
      print *,"len rc:",len(rc)
      hkl(1,1) = 2
      hkl(2,1) = 3
      hkl(3,1) = 0
      a%e=2.1
      a%m=4
      a%r=0.3

      hkl(1,2) = 0
      hkl(2,2) = 7
      hkl(3,2) = 3

      b%e=1.8
      b%m=1
      b%r=0.2

      call h%init(usetrim=.false.)

      success = h%insert(transfer(hkl(:,1),hc),transfer(a,rc))
      success = h%insert(transfer(hkl(:,2),hc),transfer(b,rc))

      c = transfer(h%lookup(transfer(hkl(:,1),hc)),c)
      print *,c
      if (aboutequal(c%e, a%e) .and. &
      &   aboutequal(c%r, a%r) .and. &
      &   c%m == a%m) then
         print *,'OK'
      else
         stop 1
      endif
      c = transfer(h%lookup(transfer(hkl(:,2),hc)),c)
      print *,c
      if (aboutequal(c%e, b%e) .and. &
      &   aboutequal(c%r, b%r) .and. &
      &   c%m == b%m) then
         print *,'OK'
      else
         stop 1
      endif
      c = transfer(h%lookup(transfer([4,5,6],hc),success),c)
      if (success) then
         print *,c
         stop 1
      else
         print *,"not found"
         print *,'OK'
      endif

      print *,'all is well'

      contains
      logical function aboutequal(x,y)
         implicit none
         real, intent(in) :: x,y
         real         :: eps = 0.0001
         aboutequal = (x > y - eps .and. x < y + eps)
      end function aboutequal

       end program cryst

    <----

       Compile this programs like:

       If you installed modhash 'properly' and have pkgconfig:

       gfortran `pkg-config --cflags modhash` -o example example.f90 \
        `pkg-config --libs modhash`

       Otherwise if modhash is installed in /home/me/software:

       gfortran -I/home/me/include -o example example.f90 \
        -L/home/me/lib -lmodhash

COPYRIGHT
       This is free software; see the source for copying conditions.  There is
       NO  warranty;  not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
       PURPOSE.

                     2018               MODHASH(3)