9#include "../base/base_uses.f90"
40 TYPE private_item_type
42 CHARACTER(LEN=default_string_length) :: key =
""
43 INTEGER(kind=int_4) ::
value = 0_int_4
44 INTEGER(KIND=int_8) :: hash = 0_int_8
45 TYPE(private_item_type),
POINTER :: next => null()
46 END TYPE private_item_type
49 TYPE private_item_p_type
51 TYPE(private_item_type),
POINTER :: p => null()
52 END TYPE private_item_p_type
57 TYPE(private_item_p_type),
DIMENSION(:),
POINTER :: buckets => null()
63 CHARACTER(LEN=default_string_length) :: key =
""
64 INTEGER(kind=int_4) ::
value = 0_int_4
78 INTEGER,
INTENT(in),
OPTIONAL :: initial_capacity
80 INTEGER :: initial_capacity_
82 IF (
PRESENT(initial_capacity))
THEN
83 initial_capacity_ = initial_capacity
85 initial_capacity_ = 11
88 IF (initial_capacity_ < 1) &
89 cpabort(
"initial_capacity < 1")
91 IF (
ASSOCIATED(hash_map%buckets)) &
92 cpabort(
"hash map is already initialized.")
94 ALLOCATE (hash_map%buckets(initial_capacity_))
105 FUNCTION routine_map_isready(hash_map)
RESULT(res)
108 res =
ASSOCIATED(hash_map%buckets)
109 END FUNCTION routine_map_isready
120 TYPE(private_item_type),
POINTER :: item, prev_item
123 cpassert(
ASSOCIATED(hash_map%buckets))
125 DO i = 1,
size(hash_map%buckets)
126 item => hash_map%buckets(i)%p
127 DO WHILE (
ASSOCIATED(item))
130 DEALLOCATE (prev_item)
134 DEALLOCATE (hash_map%buckets)
147 CHARACTER(LEN=default_string_length),
INTENT(in) :: key
148 INTEGER(kind=int_4),
INTENT(in) :: value
149 INTEGER(KIND=int_8) ::
hash
150 cpassert(
ASSOCIATED(hash_map%buckets))
152 hash = routine_map_hash_function(key)
153 CALL routine_map_set_hashed(hash_map, key,
value,
hash)
164 RECURSIVE SUBROUTINE routine_map_set_hashed(hash_map, key, value, hash)
166 CHARACTER(LEN=default_string_length),
intent(in) :: key
167 INTEGER(kind=int_4),
intent(in) :: value
168 INTEGER(KIND=int_8),
intent(in) ::
hash
169 TYPE(private_item_type),
POINTER :: item, new_item
170 INTEGER(KIND=int_8) ::
idx
172 idx = mod(
hash, int(
size(hash_map%buckets), kind=
int_8)) + 1
175 item => hash_map%buckets(
idx)%p
176 DO WHILE (
ASSOCIATED(item))
177 IF (item%hash ==
hash)
THEN
178 IF (routine_map_keys_equal(item%key, key))
THEN
187 IF (4*hash_map%size > 3*
size(hash_map%buckets))
THEN
188 call routine_map_change_capacity(hash_map, 2*
size(hash_map%buckets))
189 idx = mod(
hash, int(
size(hash_map%buckets), kind=
int_8)) + 1
196 new_item%value =
value
197 new_item%next => hash_map%buckets(
idx)%p
198 hash_map%buckets(
idx)%p => new_item
199 hash_map%size = hash_map%size + 1
201 END SUBROUTINE routine_map_set_hashed
209 RECURSIVE SUBROUTINE routine_map_change_capacity(hash_map, new_capacity)
211 INTEGER,
INTENT(in) :: new_capacity
212 INTEGER :: i, old_size, new_cap
213 TYPE(private_item_type),
POINTER :: item, prev_item
214 TYPE(private_item_p_type),
DIMENSION(:),
POINTER :: old_buckets
215 new_cap = new_capacity
217 IF (new_cap > huge(i))
THEN
218 IF (
size(hash_map%buckets) == huge(i))
RETURN
221 cpassert(new_cap >= 1)
222 cpassert(4*hash_map%size < 3*new_cap)
224 old_size = hash_map%size
225 old_buckets => hash_map%buckets
226 ALLOCATE (hash_map%buckets(new_capacity))
228 DO i = 1,
size(old_buckets)
229 item => old_buckets(i)%p
230 DO WHILE (
ASSOCIATED(item))
231 CALL routine_map_set_hashed(hash_map, item%key, item%value, item%hash)
234 DEALLOCATE (prev_item)
238 DEALLOCATE (old_buckets)
240 cpassert(old_size == hash_map%size)
241 END SUBROUTINE routine_map_change_capacity
255 CHARACTER(LEN=default_string_length),
INTENT(in) :: key
256 INTEGER(kind=int_4),
INTENT(in),
OPTIONAL :: default_value
257 INTEGER(kind=int_4) :: value
258 TYPE(private_item_type),
POINTER :: item
259 INTEGER(KIND=int_8) ::
hash,
idx
261 cpassert(
ASSOCIATED(hash_map%buckets))
263 hash = routine_map_hash_function(key)
264 idx = mod(
hash, int(
size(hash_map%buckets), kind=
int_8)) + 1
266 item => hash_map%buckets(
idx)%p
267 DO WHILE (
ASSOCIATED(item))
268 IF (item%hash ==
hash)
THEN
269 IF (routine_map_keys_equal(item%key, key))
THEN
277 IF (
PRESENT(default_value))
THEN
282 cpabort(
"Key not found.")
292 SUBROUTINE routine_map_del(hash_map, key)
294 CHARACTER(LEN=default_string_length),
INTENT(in) :: key
295 TYPE(private_item_type),
POINTER :: item, prev_item
296 INTEGER(KIND=int_8) ::
hash,
idx
298 cpassert(
ASSOCIATED(hash_map%buckets))
300 hash = routine_map_hash_function(key)
301 idx = mod(
hash, int(
size(hash_map%buckets), kind=
int_8)) + 1
303 item => hash_map%buckets(
idx)%p
305 DO WHILE (
ASSOCIATED(item))
306 IF (item%hash ==
hash)
THEN
307 IF (routine_map_keys_equal(item%key, key))
THEN
308 IF (
ASSOCIATED(prev_item))
THEN
309 prev_item%next => item%next
311 hash_map%buckets(
idx)%p => item%next
314 hash_map%size = hash_map%size - 1
322 cpabort(
"Key not found.")
323 END SUBROUTINE routine_map_del
335 cpassert(
ASSOCIATED(hash_map%buckets))
348 CHARACTER(LEN=default_string_length),
INTENT(IN) :: key
350 TYPE(private_item_type),
POINTER :: item
351 INTEGER(KIND=int_8) ::
hash,
idx
353 cpassert(
ASSOCIATED(hash_map%buckets))
356 IF (hash_map%size == 0)
RETURN
358 hash = routine_map_hash_function(key)
359 idx = mod(
hash, int(
size(hash_map%buckets), kind=
int_8)) + 1
361 item => hash_map%buckets(
idx)%p
362 DO WHILE (
ASSOCIATED(item))
363 IF (item%hash ==
hash)
THEN
364 IF (routine_map_keys_equal(item%key, key))
THEN
385 TYPE(private_item_type),
POINTER :: item
388 cpassert(
ASSOCIATED(hash_map%buckets))
390 ALLOCATE (items(hash_map%size))
392 DO i = 1,
size(hash_map%buckets)
393 item => hash_map%buckets(i)%p
394 DO WHILE (
ASSOCIATED(item))
395 items(j)%key =item%key
396 items(j)%value =item%value
402 cpassert(j == hash_map%size + 1)
414 SUBROUTINE routine_map_update(hash_map, from_hash_map)
420 cpassert(
ASSOCIATED(hash_map%buckets))
421 cpassert(
ASSOCIATED(from_hash_map%buckets))
424 DO i = 1,
size(from_items)
427 DEALLOCATE (from_items)
428 END SUBROUTINE routine_map_update
444 PURE FUNCTION routine_map_hash_function(key)
RESULT(hash)
445 CHARACTER(LEN=*),
INTENT(IN) :: key
446 INTEGER(KIND=int_8) ::
hash
448 INTEGER(KIND=int_8),
PARAMETER :: b32 = 2_int_8**32 - 1_int_8
454 hash = iand(
hash + ichar(key(i:i)), b32)
456 hash = iand(ieor(
hash, iand(ishft(
hash, -6), b32)), b32)
459 hash = iand(ieor(
hash, iand(ishft(
hash, -11), b32)), b32)
461 END FUNCTION routine_map_hash_function
468 PURE FUNCTION routine_map_keys_equal(key1, key2)
RESULT(res)
469 CHARACTER(LEN=*),
INTENT(IN) :: key1, key2
473 END FUNCTION routine_map_keys_equal
static unsigned int hash(const unsigned int row, const unsigned int col)
Private hash function based on Cantor pairing function. https://en.wikipedia.org/wiki/Pairing_functio...
static GRID_HOST_DEVICE int idx(const orbital a)
Return coset index of given orbital angular momentum.
Defines the basic variable types.
integer, parameter, public int_8
integer, parameter, public default_string_length
integer, parameter, public int_4
integer(kind=int_4) function, public routine_map_get(hash_map, key, default_value)
Gets a value for a given key from the hash map. If the key is not found the default_value will be ret...
integer function, public routine_map_size(hash_map)
Returns the number of key/value-items currently stored in the hash map.
subroutine, public routine_map_init(hash_map, initial_capacity)
Allocates the internal data-structures of the given hash map.
logical function, public routine_map_haskey(hash_map, key)
Checks whether a given key is currently stored in the hash_map.
type(routine_map_item_type) function, dimension(:), pointer, public routine_map_items(hash_map)
Returns a pointer to an array of all key/value-items stored in the hash map. Caution: The caller is r...
subroutine, public routine_map_destroy(hash_map)
Deallocated the internal data-structures if the given hash map. Caution: If the stored keys or values...
subroutine, public routine_map_set(hash_map, key, value)
Stores, and possibly overwrites, a given value under a given key.