The MD5 and SHA hash functions are cryptographic hash functions, which are great for ensuring a uniform distribution of entries in the hash table. However, these hash functions are relatively expensive, and the finite size of the hash table means that at some point (adding enough entities to a table of a given size) more than one KVP will start mapping into the same bin.
I would like to recommend that alternate hash functions be made available as part of Petaca. My favorite, cheap, quick and dirty hash function with a decent distribution is Bob Jenkin's "One at a time" hash: https://en.wikipedia.org/wiki/Jenkins_hash_function#one-at-a-time My tests indicate a relatively uniform distribution when hashing strings.
The only complication with implementing this hash function in Fortran is that there is no unsigned integer type. However, all Fortran integer implementations are done using twos compliment which has the same over-flow, wrap-around behavior as unsigned integers. As a result the absolute value of the hash function result may be used prior to modular division for indexing into the hash table array, without adversely effecting the uniformity of the hash function distribution. (At least until the table size becomes greater than huge(hash_result_integer)
at which point, you can just use a larger signed Fortran integer.)
Here is the implementation I usually use:
elemental function hash(str)
!! Bob Jenkins' one-at-a-time hash function
!! Map a given character string onto an integer. For best performance,
!! this should be:
!! 1. fast
!! 2. deterministic
!! 3. uniformly distributed over the integers
!! 4. chaotic
!! See <http://burtleburtle.net/bob/hash/doobs.html>, and
!! <http://www.stanford.edu/class/ee380/Abstracts/121017-slides.pdf>
!! (slides from talk of google cityhash developers to Stanford)
character(len=*), intent(in) :: str
!! string to hash
integer(selected_int_kind(8)) :: hash
!! Numeric hash
character(len=len(str)) :: str2
integer(selected_int_kind(8)) :: i, stlen
str2 = adjustl(str)
stlen = len(trim(str2))
hash = 0
do i = 1,stlen
hash = hash + ichar(str2(i:i))
hash = hash + ishft(hash,10)
hash = ieor(hash,ishft(hash,-6))
end do
hash = hash + ishft(hash,3)
hash = ieor(hash,ishft(hash,-11))
hash = abs(hash + ishft(hash,15))
end function
I'm pretty busy at the moment, but if you're amenable to including this as an option, I may try to find the time required to submit a PR to implement this.