c++ - 如何编写和调用std::hash? -用于gmp的mpz_class和mpz_t

标签 c++ hash unordered-map gmp

我认为大部分工作都在这里完成,最后只剩下一些细节。继续阅读。
我正在尝试编写粘合代码,以使用MurmurHash3哈希C++中GMP库的大整数(mpz_tmpz_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());
}

}

最佳答案

找到了适合我的解决方案:

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());
}

}

然后,您可以使用哈希函数,如下所示:
#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

评论被赞赏。

关于c++ - 如何编写和调用std::hash? -用于gmp的mpz_class和mpz_t,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62452712/

相关文章:

c++ - 将相机旋转到模型的中心

c++ - 是否有(足够快的)解决方法来乘以超出内存限制的矩阵?

c++ - MFC CWinApp 程序中的输入框?

python - 在 python 中制作一个可哈希的整数列表

c++ - map /unordered_map : Prefer find() and then at() or try at() catch out_of_range?

c++ - 与普通 DLL 相比,使用 COM 有什么优势?

c# - 如何从整数生成 MD5 哈希(32/64 个字符)

c++ - 一个好的 vector 散列函数

c++ - 如何打印嵌套 std::unordered_map 的内容?

c++ - 为什么 C++11/Boost `unordered_map` 在删除时不重新散列?