forked from lemire/rollinghashcpp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
characterhash.h
88 lines (75 loc) · 2.83 KB
/
characterhash.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#ifndef CHARACTERHASH
#define CHARACTERHASH
typedef unsigned long long uint64;
typedef unsigned int uint32;
typedef unsigned int uint;
#include <cassert>
#include <iostream>
#include <stdexcept>
#include "mersennetwister.h"
using namespace std;
class mersenneRNG {
public:
mersenneRNG(uint32 maxval) : mtr(),n(maxval) {};
uint32 operator()() {
return static_cast<uint32>(mtr.randInt(n));
}
void seed(uint32 seedval) {
mtr.seed(seedval);
}
void seed() {
mtr.seed();
}
uint32 rand_max() {
return n;
}
private:
MTRand mtr;
int n;
};
template <typename hashvaluetype>
#if __cplusplus >= 201402L
constexpr
#endif
hashvaluetype maskfnc(int bits) {
assert(bits>0);
assert(static_cast<size_t>(bits)<=sizeof(hashvaluetype)*8);
hashvaluetype x = static_cast<hashvaluetype>(1) << (bits - 1);
return x ^ (x - 1);
}
template <typename hashvaluetype = uint32, typename chartype = unsigned char>
class CharacterHash {
public:
CharacterHash(hashvaluetype maxval) {
if(sizeof(hashvaluetype) <=4) {
mersenneRNG randomgenerator(static_cast<uint32>(maxval));
for(size_t k =0; k<nbrofchars; ++k)
hashvalues[k] = static_cast<hashvaluetype>(randomgenerator());
} else if (sizeof(hashvaluetype) == 8) {
mersenneRNG randomgenerator(static_cast<uint32>(maxval>>32));
mersenneRNG randomgeneratorbase((maxval>>32) ==0 ? static_cast<uint32>(maxval) : 0xFFFFFFFFU);
for(size_t k =0; k<nbrofchars; ++k)
hashvalues[k] = static_cast<hashvaluetype>(randomgeneratorbase())
| (static_cast<hashvaluetype>(randomgenerator()) << 32);
} else throw runtime_error("unsupported hash value type");
}
CharacterHash(hashvaluetype maxval, uint32 seed1, uint32 seed2) {
if(sizeof(hashvaluetype) <=4) {
mersenneRNG randomgenerator(static_cast<uint32>(maxval));
randomgenerator.seed(seed1);
for(size_t k =0; k<nbrofchars; ++k)
hashvalues[k] = static_cast<hashvaluetype>(randomgenerator());
} else if (sizeof(hashvaluetype) == 8) {
mersenneRNG randomgenerator(static_cast<uint32>(maxval>>32));
mersenneRNG randomgeneratorbase((maxval>>32) ==0 ? static_cast<uint32>(maxval) : 0xFFFFFFFFU);
randomgenerator.seed(seed1);
randomgeneratorbase.seed(seed2);
for(size_t k =0; k<nbrofchars; ++k)
hashvalues[k] = static_cast<hashvaluetype>(randomgeneratorbase())
| (static_cast<hashvaluetype>(randomgenerator()) << 32);
} else throw runtime_error("unsupported hash value type");
}
enum {nbrofchars = 1 << ( sizeof(chartype)*8 )};
hashvaluetype hashvalues[1 << ( sizeof(chartype)*8 )];
};
#endif