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)
THEN
89 cpabort(
"initial_capacity < 1")
92 IF (
ASSOCIATED(hash_map%buckets))
THEN
93 cpabort(
"hash map is already initialized.")
96 ALLOCATE (hash_map%buckets(initial_capacity_))
107 FUNCTION routine_map_isready(hash_map)
RESULT(res)
110 res =
ASSOCIATED(hash_map%buckets)
111 END FUNCTION routine_map_isready
122 TYPE(private_item_type),
POINTER :: item, prev_item
125 cpassert(
ASSOCIATED(hash_map%buckets))
127 DO i = 1,
size(hash_map%buckets)
128 item => hash_map%buckets(i)%p
129 DO WHILE (
ASSOCIATED(item))
132 DEALLOCATE (prev_item)
136 DEALLOCATE (hash_map%buckets)
149 CHARACTER(LEN=default_string_length),
INTENT(in) :: key
150 INTEGER(kind=int_4),
INTENT(in) :: value
151 INTEGER(KIND=int_8) ::
hash
152 cpassert(
ASSOCIATED(hash_map%buckets))
154 hash = routine_map_hash_function(key)
155 CALL routine_map_set_hashed(hash_map, key,
value,
hash)
166 RECURSIVE SUBROUTINE routine_map_set_hashed(hash_map, key, value, hash)
168 CHARACTER(LEN=default_string_length),
intent(in) :: key
169 INTEGER(kind=int_4),
intent(in) :: value
170 INTEGER(KIND=int_8),
intent(in) ::
hash
171 TYPE(private_item_type),
POINTER :: item, new_item
172 INTEGER(KIND=int_8) ::
idx
174 idx = mod(
hash, int(
size(hash_map%buckets), kind=
int_8)) + 1
177 item => hash_map%buckets(
idx)%p
178 DO WHILE (
ASSOCIATED(item))
179 IF (item%hash ==
hash)
THEN
180 IF (routine_map_keys_equal(item%key, key))
THEN
189 IF (4*hash_map%size > 3*
size(hash_map%buckets))
THEN
190 call routine_map_change_capacity(hash_map, 2*
size(hash_map%buckets))
191 idx = mod(
hash, int(
size(hash_map%buckets), kind=
int_8)) + 1
198 new_item%value =
value
199 new_item%next => hash_map%buckets(
idx)%p
200 hash_map%buckets(
idx)%p => new_item
201 hash_map%size = hash_map%size + 1
203 END SUBROUTINE routine_map_set_hashed
211 RECURSIVE SUBROUTINE routine_map_change_capacity(hash_map, new_capacity)
213 INTEGER,
INTENT(in) :: new_capacity
214 INTEGER :: i, old_size, new_cap
215 TYPE(private_item_type),
POINTER :: item, prev_item
216 TYPE(private_item_p_type),
DIMENSION(:),
POINTER :: old_buckets
217 new_cap = new_capacity
219 IF (new_cap > huge(i))
THEN
220 IF (
size(hash_map%buckets) == huge(i))
RETURN
223 cpassert(new_cap >= 1)
224 cpassert(4*hash_map%size < 3*new_cap)
226 old_size = hash_map%size
227 old_buckets => hash_map%buckets
228 ALLOCATE (hash_map%buckets(new_capacity))
230 DO i = 1,
size(old_buckets)
231 item => old_buckets(i)%p
232 DO WHILE (
ASSOCIATED(item))
233 CALL routine_map_set_hashed(hash_map, item%key, item%value, item%hash)
236 DEALLOCATE (prev_item)
240 DEALLOCATE (old_buckets)
242 cpassert(old_size == hash_map%size)
243 END SUBROUTINE routine_map_change_capacity
257 CHARACTER(LEN=default_string_length),
INTENT(in) :: key
258 INTEGER(kind=int_4),
INTENT(in),
OPTIONAL :: default_value
259 INTEGER(kind=int_4) :: value
260 TYPE(private_item_type),
POINTER :: item
261 INTEGER(KIND=int_8) ::
hash,
idx
263 cpassert(
ASSOCIATED(hash_map%buckets))
265 hash = routine_map_hash_function(key)
266 idx = mod(
hash, int(
size(hash_map%buckets), kind=
int_8)) + 1
268 item => hash_map%buckets(
idx)%p
269 DO WHILE (
ASSOCIATED(item))
270 IF (item%hash ==
hash)
THEN
271 IF (routine_map_keys_equal(item%key, key))
THEN
279 IF (
PRESENT(default_value))
THEN
284 cpabort(
"Key not found.")
294 SUBROUTINE routine_map_del(hash_map, key)
296 CHARACTER(LEN=default_string_length),
INTENT(in) :: key
297 TYPE(private_item_type),
POINTER :: item, prev_item
298 INTEGER(KIND=int_8) ::
hash,
idx
300 cpassert(
ASSOCIATED(hash_map%buckets))
302 hash = routine_map_hash_function(key)
303 idx = mod(
hash, int(
size(hash_map%buckets), kind=
int_8)) + 1
305 item => hash_map%buckets(
idx)%p
307 DO WHILE (
ASSOCIATED(item))
308 IF (item%hash ==
hash)
THEN
309 IF (routine_map_keys_equal(item%key, key))
THEN
310 IF (
ASSOCIATED(prev_item))
THEN
311 prev_item%next => item%next
313 hash_map%buckets(
idx)%p => item%next
316 hash_map%size = hash_map%size - 1
324 cpabort(
"Key not found.")
325 END SUBROUTINE routine_map_del
337 cpassert(
ASSOCIATED(hash_map%buckets))
350 CHARACTER(LEN=default_string_length),
INTENT(IN) :: key
352 TYPE(private_item_type),
POINTER :: item
353 INTEGER(KIND=int_8) ::
hash,
idx
355 cpassert(
ASSOCIATED(hash_map%buckets))
358 IF (hash_map%size == 0)
RETURN
360 hash = routine_map_hash_function(key)
361 idx = mod(
hash, int(
size(hash_map%buckets), kind=
int_8)) + 1
363 item => hash_map%buckets(
idx)%p
364 DO WHILE (
ASSOCIATED(item))
365 IF (item%hash ==
hash)
THEN
366 IF (routine_map_keys_equal(item%key, key))
THEN
387 TYPE(private_item_type),
POINTER :: item
390 cpassert(
ASSOCIATED(hash_map%buckets))
392 ALLOCATE (items(hash_map%size))
394 DO i = 1,
size(hash_map%buckets)
395 item => hash_map%buckets(i)%p
396 DO WHILE (
ASSOCIATED(item))
397 items(j)%key =item%key
398 items(j)%value =item%value
404 cpassert(j == hash_map%size + 1)
416 SUBROUTINE routine_map_update(hash_map, from_hash_map)
422 cpassert(
ASSOCIATED(hash_map%buckets))
423 cpassert(
ASSOCIATED(from_hash_map%buckets))
426 DO i = 1,
size(from_items)
429 DEALLOCATE (from_items)
430 END SUBROUTINE routine_map_update
446 PURE FUNCTION routine_map_hash_function(key)
RESULT(hash)
447 CHARACTER(LEN=*),
INTENT(IN) :: key
448 INTEGER(KIND=int_8) ::
hash
450 INTEGER(KIND=int_8),
PARAMETER :: b32 = 2_int_8**32 - 1_int_8
456 hash = iand(
hash + ichar(key(i:i)), b32)
458 hash = iand(ieor(
hash, iand(ishft(
hash, -6), b32)), b32)
461 hash = iand(ieor(
hash, iand(ishft(
hash, -11), b32)), b32)
463 END FUNCTION routine_map_hash_function
470 PURE FUNCTION routine_map_keys_equal(key1, key2)
RESULT(res)
471 CHARACTER(LEN=*),
INTENT(IN) :: key1, key2
475 END FUNCTION routine_map_keys_equal
static unsigned int hash(const dbm_task_t task)
Private hash function based on Szudzik's elegant pairing. Using unsigned int to return a positive num...
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.