Skip to content

Fix in the procedure remove of chaining hashmaps #788

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/stdlib_hashmap_chaining.f90
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,7 @@ module subroutine remove_chaining_entry(map, key, existed)
centry % next => bentry
map % inverse(inmap) % target => null()
map % num_free = map % num_free + 1
map % num_entries = map % num_entries - 1

end subroutine remove_chaining_entry

Expand Down
100 changes: 100 additions & 0 deletions test/hashmaps/test_maps.fypp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ contains
, new_unittest("chaining-maps-${hash_}$-${size_}$-byte-words", test_${hash_}$_${size_}$_byte_words) &
#:endfor
#:endfor
, new_unittest("chaining-maps-removal-spec", test_removal_spec) &
]

end subroutine collect_stdlib_chaining_maps
Expand Down Expand Up @@ -173,6 +174,55 @@ contains

end subroutine

subroutine test_removal_spec(error)
!! Test following code provided by @jannisteunissen
!! https://github.com/fortran-lang/stdlib/issues/785
type(error_type), allocatable, intent(out) :: error

type(chaining_hashmap_type) :: map
type(key_type) :: key
integer, parameter :: n_max = 500
integer :: n
integer, allocatable :: key_counts(:)
integer, allocatable :: seed(:)
integer(int8) :: int32_int8(4)
integer(int32) :: keys(n_max)
real(dp) :: r_uniform(n_max)
logical :: existed, present

call random_seed(size = n)
allocate(seed(n), source = 123456)
call random_seed(put = seed)

call random_number(r_uniform)
keys = nint(r_uniform * n_max * 0.25_dp)

call map%init(fnv_1_hasher, slots_bits=10)

do n = 1, n_max
call set(key, transfer(keys(n), int32_int8))
call map%key_test(key, present)
if (present) then
call map%remove(key, existed)
call check(error, existed, "chaining-removal-spec: Key not found in entry removal.")
else
call map%map_entry(key)
end if
end do

! Count number of keys that occur an odd number of times
allocate(key_counts(minval(keys):maxval(keys)), source = 0)
do n = 1, n_max
key_counts(keys(n)) = key_counts(keys(n)) + 1
end do
n = sum(iand(key_counts, 1))

call check(error, map%entries(), n, &
"chaining-removal-spec: Number of expected keys and entries are different.")
return

end subroutine

end module

module test_stdlib_open_maps
Expand Down Expand Up @@ -215,6 +265,7 @@ contains
, new_unittest("open-maps-${hash_}$-${size_}$-byte-words", test_${hash_}$_${size_}$_byte_words) &
#:endfor
#:endfor
, new_unittest("open-maps-removal-spec", test_removal_spec) &
]

end subroutine collect_stdlib_open_maps
Expand Down Expand Up @@ -347,6 +398,55 @@ contains

end subroutine

subroutine test_removal_spec(error)
!! Test following code provided by @jannisteunissen
!! https://github.com/fortran-lang/stdlib/issues/785
type(error_type), allocatable, intent(out) :: error

type(open_hashmap_type) :: map
type(key_type) :: key
integer, parameter :: n_max = 500
integer :: n
integer, allocatable :: key_counts(:)
integer, allocatable :: seed(:)
integer(int8) :: int32_int8(4)
integer(int32) :: keys(n_max)
real(dp) :: r_uniform(n_max)
logical :: existed, present

call random_seed(size = n)
allocate(seed(n), source = 123456)
call random_seed(put = seed)

call random_number(r_uniform)
keys = nint(r_uniform * n_max * 0.25_dp)

call map%init(fnv_1_hasher, slots_bits=10)

do n = 1, n_max
call set(key, transfer(keys(n), int32_int8))
call map%key_test(key, present)
if (present) then
call map%remove(key, existed)
call check(error, existed, "open-removal-spec: Key not found in entry removal.")
else
call map%map_entry(key)
end if
end do

! Count number of keys that occur an odd number of times
allocate(key_counts(minval(keys):maxval(keys)), source = 0)
do n = 1, n_max
key_counts(keys(n)) = key_counts(keys(n)) + 1
end do
n = sum(iand(key_counts, 1))

call check(error, map%entries(), n, &
"open-removal-spec: Number of expected keys and entries are different.")
return

end subroutine

end module


Expand Down
Loading