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;
}
Leave A Reply
All content licensed under the Creative Commons License