MODFLOW 6 version 6.9.0.dev0
USGS Modular Hydrologic Model
Loading...
Searching...
No Matches
HashTable.f90
Go to the documentation of this file.
1!> @brief A chaining hash map for integers.
2!!
3!! Convenient for use as an index into arrays of arbitrary
4!! data type. The implementation is based on Arjen Markus'
5!! dictionary in the Flibs collection of Fortran utilities.
6!<
8
9 use kindmodule, only: dp, i4b
10
11 implicit none
12
13 private
14 public hashtabletype
15 public hash_table_cr
16 public hash_table_da
17
18 integer, parameter, private :: hash_size = 4993
19 integer, parameter, private :: multiplier = 31
20
21 type :: nodetype
22 character(len=:), allocatable :: key
23 integer(I4B) :: value
24 type(nodetype), pointer :: next => null()
25 contains
26 procedure :: add => list_add
27 end type nodetype
28
29 type :: buckettype
30 type(nodetype), pointer :: list => null()
31 end type buckettype
32
34 private
35 type(buckettype), pointer :: buckets(:) => null()
36 contains
37 procedure :: add => ht_add
38 procedure :: get => ht_get
39 procedure, private :: find_node
40 end type hashtabletype
41
42contains
43
44 !> @brief Create a hash table
45 subroutine hash_table_cr(map)
46 ! -- dummy
47 type(hashtabletype), pointer :: map
48 ! -- local
49 integer(I4B) :: i
50
51 ! -- allocate
52 allocate (map)
53 allocate (map%buckets(hash_size))
54
55 ! -- initialize nul buckets
56 do i = 1, hash_size
57 map%buckets(i)%list => null()
58 end do
59
60 end subroutine hash_table_cr
61
62 !> @brief Deallocate the hash table
63 subroutine hash_table_da(map)
64 ! -- dummy
65 type(hashtabletype), pointer :: map
66 ! -- local
67 integer(I4B) :: i
68
69 ! -- deallocate each bucket
70 do i = 1, size(map%buckets)
71 if (associated(map%buckets(i)%list)) then
72 call list_da(map%buckets(i)%list)
73 end if
74 end do
75
76 ! -- deallocate bucket array and hash table
77 deallocate (map%buckets)
78 deallocate (map)
79
80 end subroutine hash_table_da
81
82 !> @brief Associate the given key and value
83 subroutine ht_add(this, k, v)
84 ! -- dummy
85 class(hashtabletype) :: this
86 character(len=*), intent(in) :: k
87 integer(I4B), intent(in) :: v
88 ! -- local
89 type(nodetype), pointer :: node
90 integer(I4B) :: h
91
92 ! -- find the element corresponding to this key and replace index or
93 ! get an unassociated elem that corresponds to this key
94 node => this%find_node(k)
95
96 ! -- replace index or create new entry
97 if (associated(node)) then
98 node%value = v
99 else
100 h = hash(trim(k))
101 if (associated(this%buckets(h)%list)) then
102 call this%buckets(h)%list%add(k, v)
103 else
104 call list_cr(this%buckets(h)%list, k, v)
105 end if
106 end if
107
108 end subroutine ht_add
109
110 !> @brief Find the node containing the given key
111 function find_node(this, k) result(node)
112 ! -- dummy
113 class(hashtabletype) :: this !< the hash map
114 character(len=*), intent(in) :: k !< the key
115 ! -- local
116 type(nodetype), pointer :: node
117 integer(I4B) :: h
118
119 h = hash(trim(k))
120 node => this%buckets(h)%list
121
122 ! -- search bucket for node with matching key
123 do while (associated(node))
124 if (node%key == k) then
125 exit
126 else
127 node => node%next
128 end if
129 end do
130
131 end function find_node
132
133 !> @brief Get the value for the given key if it exists, otherwise return zero.
134 function ht_get(this, k) result(v)
135 ! -- dummy
136 class(hashtabletype) :: this !< the hash map
137 character(len=*), intent(in) :: k !< the key
138 ! -- return
139 integer(I4B) :: v
140 ! -- local
141 type(nodetype), pointer :: node
142
143 node => this%find_node(k)
144 if (associated(node)) then
145 v = node%value
146 else
147 v = 0
148 end if
149
150 end function ht_get
151
152 !> @brief Create a list with the given key/value pair
153 subroutine list_cr(list, k, v)
154 ! -- dummy
155 type(nodetype), pointer :: list !< pointer to the list
156 character(len=*), intent(in) :: k !< the first key
157 integer(I4B), intent(in) :: v !< the first value
158
159 allocate (list)
160 list%next => null()
161 list%key = k
162 list%value = v
163
164 end subroutine list_cr
165
166 !> @brief Add a key/value pair to the list
167 subroutine list_add(this, k, v)
168 ! -- dummy
169 class(nodetype) :: this !< the list
170 character(len=*), intent(in) :: k !< the key
171 integer(I4B), intent(in) :: v !< the value
172 ! -- local
173 type(nodetype), pointer :: next
174
175 allocate (next)
176 next%key = k
177 next%value = v
178 next%next => this%next
179 this%next => next
180
181 end subroutine list_add
182
183 !> @brief Deallocate the list
184 subroutine list_da(list)
185 ! -- dummy
186 type(nodetype), pointer, intent(in) :: list !< the list
187 ! -- local
188 type(nodetype), pointer :: curr
189 type(nodetype), pointer :: node
190
191 node => list
192 do while (associated(node))
193 curr => node
194 node => curr%next
195 deallocate (curr)
196 end do
197
198 end subroutine list_da
199
200 !> @brief Map a character string to an integer
201 function hash(k) result(h)
202 ! -- dummy
203 character(len=*), intent(in) :: k !< the key
204 ! -- local
205 integer(I4B) :: h
206 integer(I4B) :: i
207
208 h = 0
209 do i = 1, len(k)
210 h = modulo(multiplier * h + ichar(k(i:i)), hash_size)
211 end do
212 h = 1 + modulo(h - 1, hash_size)
213
214 end function hash
215
216end module hashtablemodule
A chaining hash map for integers.
Definition HashTable.f90:7
subroutine list_da(list)
Deallocate the list.
subroutine list_cr(list, k, v)
Create a list with the given key/value pair.
type(nodetype) function, pointer find_node(this, k)
Find the node containing the given key.
integer, parameter, private hash_size
Definition HashTable.f90:18
integer(i4b) function ht_get(this, k)
Get the value for the given key if it exists, otherwise return zero.
subroutine ht_add(this, k, v)
Associate the given key and value.
Definition HashTable.f90:84
integer(i4b) function hash(k)
Map a character string to an integer.
subroutine, public hash_table_cr(map)
Create a hash table.
Definition HashTable.f90:46
subroutine list_add(this, k, v)
Add a key/value pair to the list.
integer, parameter, private multiplier
Definition HashTable.f90:19
subroutine, public hash_table_da(map)
Deallocate the hash table.
Definition HashTable.f90:64
This module defines variable data types.
Definition kind.f90:8