blob: 780a563f4b4842b1f8f311ec3997777a9c712e40 (
plain) (
blame)
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
|
//Chris Xiong 2022
//License: MPL-2.0
#ifndef COMPRESSED_VECTOR
#define COMPRESSED_VECTOR
#include <cstdint>
#include <cstddef>
#include <cassert>
#include <vector>
#include "base64.hpp"
template <class T, int B>
struct compressed_vector_hash;
/*limitations:
* current implementation never returns a reference
*/
template <class T, int B>
class compressed_vector
{
static_assert(std::is_unsigned<T>::value);
static_assert(sizeof(T) * 8 >= B);
static_assert(B > 0 && B < 64);
private:
const int P = 64 / B;
const uint64_t M = (1 << B) - 1;
std::vector<uint64_t> v;
size_t sz;
public:
compressed_vector() : sz(0) {}
void push_back(T val)
{
//assert(v <= M);
if (sz % P == 0)
v.push_back(0);
set(sz++, val);
}
void pop_back()
{
//assert(sz > 0);
if (--sz % P == 0)
v.pop_back();
else
//zero out the now unused bits
v[sz / P] &= ~(M << (sz % P * B));
}
T front() const {return get(0);}
T back() const {return get(sz - 1);}
T get(size_t i) const
{
assert(i < sz && (i / P) < v.size());
return (T)((v[i / P] >> (i % P * B)) & M);
}
void set(size_t i, T val)
{
assert(i < sz && (i / P) < v.size());
v[i / P] &= ~(M << (i % P * B));
v[i / P] |= ((uint64_t) val) << (i % P * B);
}
size_t size() const
{
return sz;
}
void clear()
{
sz = 0;
v.clear();
}
bool operator ==(const compressed_vector& other) const
{
return sz == other.sz && v == other.v;
}
// unsafe stuff! potentially invariant-breaking. only use for data exchanging.
void internal_container_resize(size_t ds)
{
v.resize(ds);
}
size_t internal_container_size()
{
return v.size();
}
void* internal_data()
{
return v.data();
}
void internal_set_size(int sz)
{
this->sz = sz;
}
friend struct compressed_vector_hash<T, B>;
};
template <class T, int B>
struct compressed_vector_hash
{
size_t operator()(compressed_vector<T, B> const& s) const noexcept
{
size_t ret = 0;
//Fibonacci hashing
for (size_t i = 0; i < s.v.size(); ++i) {
ret ^= (size_t)(s.v[i] & ~0U) + 0x9e3779b9 + (ret << 6) + (ret >> 2);
ret ^= (size_t)(s.v[i] >> 32) + 0x9e3779b9 + (ret << 6) + (ret >> 2);
}
return ret;
}
};
#endif
|