Hashing intgers to get 64bit output
I'm working with a 32bit PRNG and I'd like to get a 64bit integer out of it. You can take two random 32bit integers and combine them into a 64bit one this way:
uint64_t high = rand32();
uint64_t low = rand32();
uint64_t num64 = (high << 32) | low;
Someone on Reddit suggested using this cool hash to perform a similar task to "upgrade" a 32bit number into a 64bit one by hashing it:
// Borrowed from: https://elixir.bootlin.com/linux/v6.11.5/source/include/linux/hash.h
static inline uint64_t hash64(uint64_t val, unsigned bits) {
return (val * 0x61c8864680b583ebull) >> (64 - bits);
}
I needed this functionality in Perl so got some help from Reddit and wrote it up:
sub hash64 {
my ($val, $bits) = @_;
my $magic_constant = 7046029254386353131;
use integer; # This forces integer math and overflow
my $result = ($val * $magic_constant) >> (64 - $bits);
# Convert from signed int to unsigned
if ($result < 0) {
no integer;
$result += 18446744073709551615; # 2**64 - 1
$result += 1;
}
return $result;
}