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)