HASH: Add generic function xxh64().

This function calculates the XXH64 has using a sequence of bytes, or
integer(kind=1) vector.

Signed-off-by: Grzegorz Kowal <grzegorz@amuncode.org>
This commit is contained in:
Grzegorz Kowal 2020-05-13 17:20:36 -03:00
parent 5696b87e37
commit 3690d5c3bf

View File

@ -55,7 +55,7 @@ module hash
! declare public subroutines
!
public :: xxh64_integer, xxh64_long, xxh64_double, xxh64_complex
public :: xxh64, xxh64_integer, xxh64_long, xxh64_double, xxh64_complex
!- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
!
@ -70,6 +70,113 @@ module hash
!
!===============================================================================
!
! function XXH64:
! --------------
!
! Function calculates XXH64 hash for a given sequence of bytes.
!
! Arguments:
!
! input - the input sequence of bytes;
!
!===============================================================================
!
integer(kind=8) function xxh64(input) result(hash)
implicit none
! subroutine arguments
!
integer(kind=1), dimension(:), intent(in) :: input
! local variables
!
integer(kind=8) :: length, remaining, offset
! local arrays
!
integer(kind=8), dimension(4) :: lane, chunk
!-------------------------------------------------------------------------------
!
length = size(input)
hash = 0_8
offset = 1_8
remaining = length
if (remaining >= 32_8) then
lane(1) = seed + prime1 + prime2
lane(2) = seed + prime2
lane(3) = seed + 0_8
lane(4) = seed - prime1
do while (remaining >= 32_8)
chunk(1:4) = transfer(input(offset:offset+31), 1_8, 4)
lane(1) = xxh64_round(lane(1), chunk(1))
lane(2) = xxh64_round(lane(2), chunk(2))
lane(3) = xxh64_round(lane(3), chunk(3))
lane(4) = xxh64_round(lane(4), chunk(4))
offset = offset + 32_8
remaining = remaining - 32_8
end do
hash = xxh64_rotl(lane(1), 1) + xxh64_rotl(lane(2), 7) + &
xxh64_rotl(lane(3), 12) + xxh64_rotl(lane(4), 18)
hash = xxh64_merge(hash, lane(1))
hash = xxh64_merge(hash, lane(2))
hash = xxh64_merge(hash, lane(3))
hash = xxh64_merge(hash, lane(4))
else
hash = seed + prime5
end if
hash = hash + length
do while (remaining >= 8_8)
chunk(1) = transfer(input(offset:offset+7), 1_8)
hash = ieor(hash, xxh64_round(0_8, chunk(1)))
hash = xxh64_rotl(hash, 27)
hash = hash * prime1 + prime4
offset = offset + 8_8
remaining = remaining - 8_8
end do
if (remaining >= 4) then
chunk(1) = transfer((/ input(offset:offset+3), 0_1, 0_1, 0_1, 0_1 /), 1_8)
hash = ieor(hash, chunk(1) * prime1)
hash = xxh64_rotl(hash, 23)
hash = hash * prime2 + prime3
offset = offset + 4_8
remaining = remaining - 4_8
end if
do while (remaining > 0_8)
chunk(1) = transfer((/ input(offset), 0_1, 0_1, 0_1, &
0_1, 0_1, 0_1, 0_1 /), 1_8)
hash = ieor(hash, chunk(1) * prime5)
hash = xxh64_rotl(hash, 11)
hash = hash * prime1
offset = offset + 1_8
remaining = remaining - 1_8
end do
hash = xxh64_aval(hash)
return
!-------------------------------------------------------------------------------
!
end function xxh64
!
!===============================================================================
!
! function XXH64_INTEGER:
! ----------------------
!