10#include "../base/base_uses.f90"
41 TYPE private_item_type
43 INTEGER(kind=int_4),
DIMENSION(2) :: key = 0_int_4
44 TYPE(call_stat_type),
POINTER ::
value => null()
45 INTEGER(KIND=int_8) :: hash = 0_int_8
46 TYPE(private_item_type),
POINTER :: next => null()
47 END TYPE private_item_type
50 TYPE private_item_p_type
52 TYPE(private_item_type),
POINTER :: p => null()
53 END TYPE private_item_p_type
58 TYPE(private_item_p_type),
DIMENSION(:),
POINTER :: buckets => null()
64 INTEGER(kind=int_4),
DIMENSION(2) :: key = 0_int_4
79 INTEGER,
INTENT(in),
OPTIONAL :: initial_capacity
81 INTEGER :: initial_capacity_
83 IF (
PRESENT(initial_capacity))
THEN
84 initial_capacity_ = initial_capacity
86 initial_capacity_ = 11
89 IF (initial_capacity_ < 1)
THEN
90 cpabort(
"initial_capacity < 1")
93 IF (
ASSOCIATED(hash_map%buckets))
THEN
94 cpabort(
"hash map is already initialized.")
97 ALLOCATE (hash_map%buckets(initial_capacity_))
108 FUNCTION callgraph_isready(hash_map)
RESULT(res)
111 res =
ASSOCIATED(hash_map%buckets)
112 END FUNCTION callgraph_isready
123 TYPE(private_item_type),
POINTER :: item, prev_item
126 cpassert(
ASSOCIATED(hash_map%buckets))
128 DO i = 1,
size(hash_map%buckets)
129 item => hash_map%buckets(i)%p
130 DO WHILE (
ASSOCIATED(item))
133 DEALLOCATE (prev_item)
137 DEALLOCATE (hash_map%buckets)
150 INTEGER(kind=int_4),
DIMENSION(2),
INTENT(in) :: key
152 INTEGER(KIND=int_8) ::
hash
153 cpassert(
ASSOCIATED(hash_map%buckets))
155 hash = callgraph_hash_function(key)
156 CALL callgraph_set_hashed(hash_map, key,
value,
hash)
167 RECURSIVE SUBROUTINE callgraph_set_hashed(hash_map, key, value, hash)
169 INTEGER(kind=int_4),
DIMENSION(2),
intent(in) :: key
171 INTEGER(KIND=int_8),
intent(in) ::
hash
172 TYPE(private_item_type),
POINTER :: item, new_item
173 INTEGER(KIND=int_8) ::
idx
175 idx = mod(
hash, int(
size(hash_map%buckets), kind=
int_8)) + 1
178 item => hash_map%buckets(
idx)%p
179 DO WHILE (
ASSOCIATED(item))
180 IF (item%hash ==
hash)
THEN
181 IF (callgraph_keys_equal(item%key, key))
THEN
190 IF (4*hash_map%size > 3*
size(hash_map%buckets))
THEN
191 call callgraph_change_capacity(hash_map, 2*
size(hash_map%buckets))
192 idx = mod(
hash, int(
size(hash_map%buckets), kind=
int_8)) + 1
199 new_item%value =>
value
200 new_item%next => hash_map%buckets(
idx)%p
201 hash_map%buckets(
idx)%p => new_item
202 hash_map%size = hash_map%size + 1
204 END SUBROUTINE callgraph_set_hashed
212 RECURSIVE SUBROUTINE callgraph_change_capacity(hash_map, new_capacity)
214 INTEGER,
INTENT(in) :: new_capacity
215 INTEGER :: i, old_size, new_cap
216 TYPE(private_item_type),
POINTER :: item, prev_item
217 TYPE(private_item_p_type),
DIMENSION(:),
POINTER :: old_buckets
218 new_cap = new_capacity
220 IF (new_cap > huge(i))
THEN
221 IF (
size(hash_map%buckets) == huge(i))
RETURN
224 cpassert(new_cap >= 1)
225 cpassert(4*hash_map%size < 3*new_cap)
227 old_size = hash_map%size
228 old_buckets => hash_map%buckets
229 ALLOCATE (hash_map%buckets(new_capacity))
231 DO i = 1,
size(old_buckets)
232 item => old_buckets(i)%p
233 DO WHILE (
ASSOCIATED(item))
234 CALL callgraph_set_hashed(hash_map, item%key, item%value, item%hash)
237 DEALLOCATE (prev_item)
241 DEALLOCATE (old_buckets)
243 cpassert(old_size == hash_map%size)
244 END SUBROUTINE callgraph_change_capacity
258 INTEGER(kind=int_4),
DIMENSION(2),
INTENT(in) :: key
259 TYPE(
call_stat_type),
POINTER,
INTENT(in),
OPTIONAL :: default_value
261 TYPE(private_item_type),
POINTER :: item
262 INTEGER(KIND=int_8) ::
hash,
idx
264 cpassert(
ASSOCIATED(hash_map%buckets))
266 hash = callgraph_hash_function(key)
267 idx = mod(
hash, int(
size(hash_map%buckets), kind=
int_8)) + 1
269 item => hash_map%buckets(
idx)%p
270 DO WHILE (
ASSOCIATED(item))
271 IF (item%hash ==
hash)
THEN
272 IF (callgraph_keys_equal(item%key, key))
THEN
280 IF (
PRESENT(default_value))
THEN
281 value =>default_value
285 cpabort(
"Key not found.")
295 SUBROUTINE callgraph_del(hash_map, key)
297 INTEGER(kind=int_4),
DIMENSION(2),
INTENT(in) :: key
298 TYPE(private_item_type),
POINTER :: item, prev_item
299 INTEGER(KIND=int_8) ::
hash,
idx
301 cpassert(
ASSOCIATED(hash_map%buckets))
303 hash = callgraph_hash_function(key)
304 idx = mod(
hash, int(
size(hash_map%buckets), kind=
int_8)) + 1
306 item => hash_map%buckets(
idx)%p
308 DO WHILE (
ASSOCIATED(item))
309 IF (item%hash ==
hash)
THEN
310 IF (callgraph_keys_equal(item%key, key))
THEN
311 IF (
ASSOCIATED(prev_item))
THEN
312 prev_item%next => item%next
314 hash_map%buckets(
idx)%p => item%next
317 hash_map%size = hash_map%size - 1
325 cpabort(
"Key not found.")
326 END SUBROUTINE callgraph_del
338 cpassert(
ASSOCIATED(hash_map%buckets))
351 INTEGER(kind=int_4),
DIMENSION(2),
INTENT(IN) :: key
353 TYPE(private_item_type),
POINTER :: item
354 INTEGER(KIND=int_8) ::
hash,
idx
356 cpassert(
ASSOCIATED(hash_map%buckets))
359 IF (hash_map%size == 0)
RETURN
361 hash = callgraph_hash_function(key)
362 idx = mod(
hash, int(
size(hash_map%buckets), kind=
int_8)) + 1
364 item => hash_map%buckets(
idx)%p
365 DO WHILE (
ASSOCIATED(item))
366 IF (item%hash ==
hash)
THEN
367 IF (callgraph_keys_equal(item%key, key))
THEN
388 TYPE(private_item_type),
POINTER :: item
391 cpassert(
ASSOCIATED(hash_map%buckets))
393 ALLOCATE (items(hash_map%size))
395 DO i = 1,
size(hash_map%buckets)
396 item => hash_map%buckets(i)%p
397 DO WHILE (
ASSOCIATED(item))
398 items(j)%key =item%key
399 items(j)%value =>item%value
405 cpassert(j == hash_map%size + 1)
417 SUBROUTINE callgraph_update(hash_map, from_hash_map)
423 cpassert(
ASSOCIATED(hash_map%buckets))
424 cpassert(
ASSOCIATED(from_hash_map%buckets))
427 DO i = 1,
size(from_items)
428 CALL callgraph_set(hash_map, from_items(i)%key, from_items(i)%value)
430 DEALLOCATE (from_items)
431 END SUBROUTINE callgraph_update
439 PURE FUNCTION callgraph_hash_function(key)
RESULT(hash)
440 INTEGER(kind=int_4),
DIMENSION(2),
INTENT(in) :: key
441 INTEGER(KIND=int_8) ::
hash
443 INTEGER(kind=int_8) :: k1, k2
446 hash = ior(k1, ishft(k2, 32))
447 END FUNCTION callgraph_hash_function
454 PURE FUNCTION callgraph_keys_equal(key1, key2)
RESULT(res)
455 INTEGER(kind=int_4),
DIMENSION(2),
INTENT(in) :: key1, key2
458 res = all(key1 == key2)
459 END FUNCTION callgraph_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.
subroutine, public callgraph_destroy(hash_map)
Deallocated the internal data-structures if the given hash map. Caution: If the stored keys or values...
integer function, public callgraph_size(hash_map)
Returns the number of key/value-items currently stored in the hash map.
subroutine, public callgraph_init(hash_map, initial_capacity)
Allocates the internal data-structures of the given hash map.
type(callgraph_item_type) function, dimension(:), pointer, public callgraph_items(hash_map)
Returns a pointer to an array of all key/value-items stored in the hash map. Caution: The caller is r...
logical function, public callgraph_haskey(hash_map, key)
Checks whether a given key is currently stored in the hash_map.
type(call_stat_type) function, pointer, public callgraph_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...
subroutine, public callgraph_set(hash_map, key, value)
Stores, and possibly overwrites, a given value under a given key.
Defines the basic variable types.
integer, parameter, public int_8
integer, parameter, public int_4
Types used by timings.F and timings_report.F The types in this module are used within dict or list,...