30 #if defined(__GFORTRAN__) && __GNUC__ < 7
31 character(len=128),
pointer :: key
33 character(len=:),
pointer :: key
35 class(*),
pointer :: val
38 type(hash_entry),
pointer :: next => null()
41 type :: hash_entry_ptr
42 type(hash_entry),
pointer :: ptr => null()
43 end type hash_entry_ptr
46 type(hash_entry_ptr),
allocatable :: table(:)
51 procedure :: destroy => destroy
52 procedure :: length => length
53 procedure :: has_key => has_key
54 procedure :: max_key_len => max_key_len
55 procedure :: keys => keys
56 procedure :: get => get
57 procedure :: get_with_cnt => get_with_cnt
58 procedure :: put => put
59 procedure :: accumurate => accumurate
60 procedure :: debug => debug
64 module procedure :: table_new
75 integer,
parameter :: init_size = 64
76 integer,
parameter :: hash_p = 19
77 integer,
parameter :: hash_max = 124901413
78 integer,
parameter :: size_max = 2**26
84 type(
hash_table) function table_new() result(tbl)
85 allocate( tbl%table(init_size) )
91 end function table_new
95 subroutine destroy(self)
97 type(hash_entry),
pointer :: e, e_old
100 do idx = 1, self%size
101 e => self%table(idx)%ptr
102 do while (
associated(e) )
103 deallocate( e%key, e%val )
110 deallocate( self%table )
116 end subroutine destroy
122 integer function length(self)
131 logical function has_key(self, key)
result(res)
133 character(len=*),
intent(in) :: key
135 type(hash_entry),
pointer :: e
140 idx = get_index(hash, self%size)
141 e => self%table(idx)%ptr
142 do while (
associated(e) )
143 if ( e%key == key )
then
154 integer function max_key_len(self, key)
156 character(len=*),
intent(in) :: key
158 max_key_len = self%max_len
160 end function max_key_len
164 subroutine keys(self, ary)
166 character(len=*),
intent(out) :: ary(:)
167 type(hash_entry),
pointer :: e
170 if (
size(ary) < self%len )
then
171 write(*,*)
"size of ary is not enough: ", self%len
176 do idx = 1, self%size
177 e => self%table(idx)%ptr
178 do while (
associated(e) )
189 function get(self, key)
result(val)
191 character(len=*),
intent(in) :: key
192 class(*),
pointer :: val
194 type(hash_entry),
pointer :: e
199 idx = get_index(hash, self%size)
200 e => self%table(idx)%ptr
201 do while (
associated(e) )
202 if ( e%key == key )
then
214 subroutine get_with_cnt(self, key, val, cnt)
216 character(len=*),
intent(in) :: key
217 class(*),
pointer,
intent(out) :: val
218 integer,
intent(out) :: cnt
220 type(hash_entry),
pointer :: e
225 idx = get_index(hash, self%size)
226 e => self%table(idx)%ptr
227 do while (
associated(e) )
228 if ( e%key == key )
then
236 end subroutine get_with_cnt
240 subroutine put(self, key, val)
242 character(len=*),
intent(in) :: key
243 class(*),
intent(in) :: val
245 type(hash_entry),
pointer :: e
250 idx = get_index(hash, self%size)
253 e => self%table(idx)%ptr
254 do while (
associated(e) )
255 if ( e%key == key )
then
257 allocate( e%val, source=val )
264 call new_entry(self, idx, hash, key, val)
271 subroutine accumurate(self, key, val)
273 character(len=*),
intent(in) :: key
274 real(rp),
intent(in) :: val
276 type(hash_entry),
pointer :: e
281 idx = get_index(hash, self%size)
284 e => self%table(idx)%ptr
285 do while (
associated(e) )
286 if ( e%key == key )
then
287 select type ( v => e%val )
293 write(*,*)
"type is invalid"
302 call new_entry(self, idx, hash, key, val)
305 end subroutine accumurate
310 function get_hash(key)
result(hash)
311 character(len=*),
intent(in) :: key
317 do i = 1, len_trim(key)
318 hash = mod( hash * hash_p + ichar(key(i:i)), hash_max)
321 end function get_hash
323 function get_index(hash, size)
result(idx)
324 integer,
intent(in) :: hash
325 integer,
intent(in) :: size
328 idx = iand(hash, size-1) + 1
331 end function get_index
333 subroutine new_entry(self, idx, hash, key, val)
335 integer,
intent(in) :: idx, hash
336 character(len=*),
intent(in) :: key
337 class(*),
intent(in) :: val
339 type(hash_entry),
pointer :: e_new
345 key_len = len_trim(key)
346 #if defined(__GFORTRAN__) && __GNUC__ < 7
347 if ( key_len > 128 )
then
348 log_error(
"new_entry",*)
'length of the key must be <=128: ', key_len
352 allocate( e_new%key, source=key )
353 allocate( e_new%val, source=val )
356 e_new%next => self%table(idx)%ptr
357 self%table(idx)%ptr => e_new
358 self%len = self%len + 1
359 self%max_len = max(self%max_len, key_len)
362 if ( self%len * 2 >= self%size )
then
363 if ( self%size == size_max )
return
364 new_size = min( self%size * 2, size_max )
366 type(hash_entry_ptr) :: table(new_size)
367 type(hash_entry),
pointer :: e, next
368 integer :: i, idx_new
371 e => self%table(i)%ptr
372 do while (
associated(e) )
374 idx_new = get_index(e%hash, new_size)
375 e%next => table(idx_new)%ptr
376 table(idx_new)%ptr => e
380 deallocate( self%table )
381 allocate( self%table(new_size) )
383 self%table(i)%ptr => table(i)%ptr
390 end subroutine new_entry
392 subroutine debug(self)
394 type(hash_entry),
pointer :: e
397 write(*,
'(a5,a32,a3,a8,a15,a2,a4,a10)')
'id',
"key",
" ",
"val",
"cnt",
", ",
"idx",
"hash"
399 do idx = 1, self%size
400 e => self%table(idx)%ptr
401 do while (
associated(e) )
402 select type(v => e%val)
404 write(*,
'(i5,a32,a3,f15.3,i8,a2,i4,i10)') i, trim(e%key),
" => ", v, e%cnt,
", ", idx, e%hash
406 write(*,
'(i5,a32,a3,i15,i8,a2,i4,i10)') i, trim(e%key),
" => ", v, e%cnt,
", ", idx, e%hash
408 write(*,
'(i5,a32,a3,a15,i8,a2,i4,i10)') i, trim(e%key),
" => ",
"type", e%cnt,
", ", idx, e%hash