Click here to Skip to main content
15,879,326 members
Articles / Programming Languages / C++

Multi-hashing

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
9 Apr 2019MIT 4.8K   2   3
Multi-hashing

Yes, I totally invented this term. What I mean by it is producing multiple hashes from a single key. Like this (if the syntax is unfamiliar to you, read this):

C++
auto [h1, h2, h3] = hashNT<3>("key");

Or like this (for non-template version which returns a vector):

C++
auto hashes = hashN("key", 3);

Why? One place where I needed such sorcery was my bloom filter implementation. The idea is simple: one key, multiple hashes, repeatable (multiple calls with the same key produce the same hashes). But how? STL only comes with one hashing function. True, but it comes with multiple random number generators which can be seeded with a hash!

The solution then is to hash once, seed the random number generator, and make multiple calls to the RNG, like this (multi_hash.hpp):

C++
#pragma once

#include <array>
#include <vector>
#include <random>
#include <algorithm>
#include <functional>

template<typename T>
auto hashN(const T& key, std::size_t N) -> std::vector<std::size_t>
{
	std::minstd_rand0 rng(std::hash<T>{}(key));
	std::vector<std::size_t> hashes(N);
	std::generate(std::begin(hashes), std::end(hashes), rng);
	return hashes;
}

template<std::size_t N, typename T>
auto hashNT(const T& key) -> std::array<std::size_t, N>
{
	std::minstd_rand0 rng(std::hash<T>{}(key));
	std::array<std::size_t, N> hashes{};
	std::generate(std::begin(hashes), std::end(hashes), rng);
	return hashes;
}

You can use it like this (multi_hash.cpp):

C++
#include <iostream>
#include <string>
#include "multi_hash.hpp"

using namespace std;

void arr()
{
	string s1 = "Vorbrodt's C++ Blog";
	string s2 = "Vorbrodt's C++ Blog";
	string s3 = "https://vorbrodt.blog";

	auto h1 = hashN(s1, 3);
	auto h2 = hashN(s2, 3);
	auto h3 = hashN(s3, 3);

	cout << "HashN('" << s1 << "'):" << endl;
	for(auto it : h1) cout << it << endl;
	cout << endl;

	cout << "HashN('" << s2 << "'):" << endl;
	for(auto it : h2) cout << it << endl;
	cout << endl;

	cout << "HashN('" << s3 << "'):" << endl;
	for(auto it : h3) cout << it << endl;
	cout << endl;
}

void temp()
{
	string s1 = "Vorbrodt's C++ Blog";
	string s2 = "Vorbrodt's C++ Blog";
	string s3 = "https://vorbrodt.blog";

	auto [s1h1, s1h2, s1h3] = hashNT<3>(s1);
	auto [s2h1, s2h2, s2h3] = hashNT<3>(s2);
	auto [s3h1, s3h2, s3h3] = hashNT<3>(s3);

	cout << "HashNT('" << s1 << "'):" << endl;
	cout << s1h1 << endl << s1h2 << endl << s1h3 << endl << endl;

	cout << "HashNT('" << s2 << "'):" << endl;
	cout << s2h1 << endl << s2h2 << endl << s2h3 << endl << endl;

	cout << "HashNT('" << s3 << "'):" << endl;
	cout << s3h1 << endl << s3h2 << endl << s3h3 << endl << endl;
}

int main()
{
	arr();
	temp();
}

Program output:

HashN(‘Vorbrodt’s C++ Blog’):
1977331388
699200791
437177953

HashN(‘Vorbrodt’s C++ Blog’):
1977331388
699200791
437177953

HashN(‘https://vorbrodt.blog’):
1924360287
1619619789
1594567998

HashNT(‘Vorbrodt’s C++ Blog’):
1977331388
699200791
437177953

HashNT(‘Vorbrodt’s C++ Blog’):
1977331388
699200791
437177953

HashNT(‘https://vorbrodt.blog’):
1924360287
1619619789
1594567998
This article was originally posted at https://vorbrodt.blog/2019/04/09/multi-hashing

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
Software Developer (Senior)
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
koothkeeper11-Apr-19 10:10
professionalkoothkeeper11-Apr-19 10:10 
PraiseVery Useful Pin
koothkeeper11-Apr-19 10:10
professionalkoothkeeper11-Apr-19 10:10 
This is a very useful tool! Thanks so much for posting!
Sincerely,

Keith E. Cooper

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.