-
Notifications
You must be signed in to change notification settings - Fork 2
/
tiny_id_func.h
155 lines (119 loc) · 3.76 KB
/
tiny_id_func.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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#ifndef TINY_INT_ID_FUNC_H
#define TINY_INT_ID_FUNC_H
#include <cstdint>
#include <utility>
#include "id_func.h"
#include "array_id_func.h"
template<int bit_count>
struct TinyIntIDFunc{
private:
static constexpr int entry_count_per_uint64 = 64/bit_count;
static constexpr std::uint64_t entry_mask = (std::uint64_t(1)<<bit_count) - std::uint64_t(1);
public:
static_assert(1<=bit_count && bit_count <= 64, "an integer with more than 64 bits is not tiny");
TinyIntIDFunc():preimage_(0){}
explicit TinyIntIDFunc(int preimage)
:preimage_(preimage), data_((preimage + entry_count_per_uint64 - 1) / entry_count_per_uint64){}
int preimage_count()const{
return preimage_;
}
template<class IDFunc>
TinyIntIDFunc(const IDFunc&other, typename std::enable_if<is_id_func<IDFunc>::value, void>::type*dummy=0)
:preimage_(other.preimage_count()), data_((other.preimage_count() + entry_count_per_uint64 - 1) / entry_count_per_uint64){
for(int i=0; i<preimage_count(); ++i)
set(i, other(i));
}
std::uint64_t operator()(int id)const{
assert(0 <= id && id < preimage_ && "id out of bounds");
int index = id / entry_count_per_uint64;
int offset = (id % entry_count_per_uint64)*bit_count;
return (data_[index] >> offset) & entry_mask;
}
void set(int id, std::uint64_t value){
assert(0 <= id && id < preimage_ && "id out of bounds");
assert(0 <= value && value <= entry_mask && "value out of bounds");
int index = id / entry_count_per_uint64;
int offset = (id % entry_count_per_uint64)*bit_count;
data_[index] ^= ((((data_[index] >> offset) & entry_mask) ^ value) << offset);
}
void fill(std::uint64_t value){
assert(0 <= value && value <= entry_mask && "value out of bounds");
if(bit_count == 1){
if(value == false)
data_.fill(0);
else
data_.fill((std::uint64_t)-1);
}else if(value == 0){
data_.fill(0);
}else{
std::uint64_t pattern = value;
int shift = bit_count;
while(shift < 64){
pattern |= pattern << shift;
shift <<= 1;
}
data_.fill(pattern);
}
}
std::uint64_t move(int id){
return operator()(id);
}
void swap(TinyIntIDFunc&other)noexcept{
std::swap(preimage_, other.preimage_);
data_.swap(other.data_);
}
template<class IDFunc>
TinyIntIDFunc operator=(const typename std::enable_if<is_id_func<IDFunc>::value, IDFunc>::type & other){
TinyIntIDFunc(other).swap(*this);
return *this;
}
int preimage_;
ArrayIDFunc<std::uint64_t> data_;
};
typedef TinyIntIDFunc<1> BitIDFunc;
inline BitIDFunc operator~(BitIDFunc f){
for(int i=0; i<f.data_.preimage_count(); ++i)
f.data_[i] = ~f.data_[i];
return std::move(f);
}
inline BitIDFunc&operator^=(BitIDFunc&l, const BitIDFunc&r){
assert(l.preimage_count() == r.preimage_count());
for(int i=0; i<l.data_.preimage_count(); ++i)
l.data_[i] ^= r.data_[i];
return l;
}
inline BitIDFunc&operator&=(BitIDFunc&l, const BitIDFunc&r){
assert(l.preimage_count() == r.preimage_count());
for(int i=0; i<l.data_.preimage_count(); ++i)
l.data_[i] &= r.data_[i];
return l;
}
inline BitIDFunc&operator|=(BitIDFunc&l, const BitIDFunc&r){
assert(l.preimage_count() == r.preimage_count());
for(int i=0; i<l.data_.preimage_count(); ++i)
l.data_[i] |= r.data_[i];
return l;
}
inline BitIDFunc&inplace_and_not(BitIDFunc&l, const BitIDFunc&r){
assert(l.preimage_count() == r.preimage_count());
for(int i=0; i<l.data_.preimage_count(); ++i)
l.data_[i] &= ~r.data_[i];
return l;
}
inline BitIDFunc operator^(BitIDFunc l, const BitIDFunc&r){
l ^= r;
return std::move(l);
}
inline BitIDFunc operator|(BitIDFunc l, const BitIDFunc&r){
l |= r;
return std::move(l);
}
inline BitIDFunc operator&(BitIDFunc l, const BitIDFunc&r){
l &= r;
return std::move(l);
}
inline BitIDFunc and_not(BitIDFunc l, const BitIDFunc&r){
inplace_and_not(l, r);
return std::move(l);
}
#endif