TRANSFER function (introduced in Fortran 95) is a somewhat strange function that can be used to do some interesting things not otherwise possible in earlier versions of the language. In fact, it can be used to achieve a sort of poor-man’s polymorphism. It can also still be useful in modern Fortran.
All this function does is transfers the bitwise representation of one variable into another variable. This is different from casting a variable of one type to another. For example:
program transfer_example use iso_fortran_env integer(int64) :: i real(real64) :: d i = 1 d = i !d is 1.0000000000000000 d = transfer(i,d) !d is 4.9406564584124654E-324 end program transfer_example
The following example shows how to use
TRANSFER to create a hash function that can operate on any variable or derived type. The dummy argument of the
hash_anything function is an unlimited polymorphic variable (
class(*)). The bitwise representation of this variable is then transferred into a character string big enough to hold it (making use of the Fortran 2008
STORAGE_SIZE intrinsic), which can then be hashed using any hash function that takes a character string as an input (a basic DJB method is used here).
module hash_module !integer kind to use for the hash: use iso_fortran_env, only: ip => INT32 implicit none contains function hash_anything(v) result(hash) !! Hash anything, using unlimited !! polymorphic variable and transfer() class(*),intent(in) :: v integer(ip) :: hash !!a default character string !!with the same size as v: character(len=ceiling(dble(storage_size(v))/& dble(storage_size(' ')))) :: str str = transfer(v,str) !transfer bits of v into !string of the same size hash = djb_hash(str) !hash it end function hash_anything function djb_hash(str) result(hash) !! Character string hashing with !! the DJB algorithm. From . character(len=*),intent(in) :: str integer(ip) :: hash integer :: i hash = 5381_ip do i=1,len(str) hash = (ishft(hash,5_ip) + hash) + & ichar(str(i:i)) end do end function djb_hash end module hash_module