如何编写和调用 std::hash? - 对于 gmp 的 mpz_class 和 mpz_t
Posted
技术标签:
【中文标题】如何编写和调用 std::hash? - 对于 gmp 的 mpz_class 和 mpz_t【英文标题】:How to write and call std::hash? - for gmp's mpz_class and mpz_t 【发布时间】:2020-06-18 14:46:25 【问题描述】:我认为大部分工作都在这里完成,最后缺少一点细节。继续阅读。
我正在尝试编写胶水代码,用于使用MurmurHash3 散列 C++ 中 GMP 库的大整数(mpz_t
和 mpz_class
)。我这样做是为了以后在std::unordered_map<mpz_class, int>
中使用它们。
我希望代码能够以有用的方式编译 32 位和 64 位系统,并且在需要 128 位系统时易于扩展。为此我编写了MurmurHash3_size_t()
函数,它调用MurmurHash3 的正确哈希函数,然后将结果转换为size_t
。我假设size_t
在 32/64/128 位系统方面具有正确的位大小。 (我不知道这个假设是否有用。)这部分代码编译得很好。
当我想定义std::hash
函数时,问题就出现了。我的代码出现编译器错误(请参阅代码中的注释)。如何正确编写这些std::hash
函数以及如何调用它们?
(click to view MurmurHash3.h)
文件hash_mpz.cpp
:
#include "hash_mpz.h"
#include <gmpxx.h>
#include "MurmurHash3.h"
size_t MurmurHash3_size_t(const void *key, int len, uint32_t seed)
#if SIZE_MAX==0xffffffff
size_t result;
MurmurHash3_x86_32(key, len, seed, &result);
return result;
#elif SIZE_MAX==0xffffffffffffffff
size_t result[2];
MurmurHash3_x64_128(key, len, seed, &result);
return result[0] ^ result[1];
#else
#error cannot determine correct version of MurmurHash3, because SIZE_MAX is neither 0xffffffff nor 0xffffffffffffffff
#endif
namespace std
size_t hash<mpz_t>::operator()(const mpz_t &x) const
// found 1846872219 by randomly hitting digits on my keyboard
return MurmurHash3_size_t(x->_mp_d, x->_mp_size * sizeof(mp_limb_t), 1846872219);
size_t hash<mpz_class>::operator()(const mpz_class &x) const
// compiler error in next statement
// error: no matching function for call to ‘std::hash<__mpz_struct [1]>::operator()(mpz_srcptr)’
return hash<mpz_t>::operator()(x.get_mpz_t());
【问题讨论】:
请随意评论目标系统的位大小的确定,因为我不确定什么是最好/最便携的方法。 C++ std::hash for GMP's big integer types mpz_class and mpz_t 页面可能会为您提供解决方案。虽然它不使用 murmurhash,但它提供了使用 C++17 的内置数据散列算法string_view
散列 mpz_t
和 mpz_class
的代码。
【参考方案1】:
找到适合我的解决方案:
namespace std
size_t hash<mpz_srcptr>::operator()(const mpz_srcptr x) const
// found 1846872219 by randomly typing digits on my keyboard
return MurmurHash3_size_t(x->_mp_d, x->_mp_size * sizeof(mp_limb_t),
1846872219);
size_t hash<mpz_t>::operator()(const mpz_t &x) const
return hash<mpz_srcptr> ((mpz_srcptr) x);
size_t hash<mpz_class>::operator()(const mpz_class &x) const
return hash<mpz_srcptr> (x.get_mpz_t());
那么就可以使用hash函数如下:
#include <iostream>
#include <gmpxx.h>
#include <unordered_map>
#include "hash_mpz.h"
using namespace std;
int main()
mpz_class a;
mpz_ui_pow_ui(a.get_mpz_t(), 168, 16);
cout << "a : " << a << endl;
cout << "hash(a): " << (hash<mpz_class> (a)) << endl;
unordered_map<mpz_class, int> map;
map[a] = 2;
cout << "map[a] : " << map[a] << endl;
return 0;
输出:
a : 402669288768856477614113920779288576
hash(a): 11740158581999522595
map[a] : 2
欢迎评论。
【讨论】:
以上是关于如何编写和调用 std::hash? - 对于 gmp 的 mpz_class 和 mpz_t的主要内容,如果未能解决你的问题,请参考以下文章
如何在大量无损压缩图像中提取重复的图像对(完全相同)?如何在内存中 std::hash?
哈希<std::string> 与哈希<std::string_view>