-
Notifications
You must be signed in to change notification settings - Fork 25
/
sequence_collection.hpp
127 lines (107 loc) · 3.82 KB
/
sequence_collection.hpp
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
#pragma once
#include "bitvector_collection.hpp"
#include "compact_elias_fano.hpp"
#include "integer_codes.hpp"
#include "global_parameters.hpp"
#include "semiasync_queue.hpp"
namespace ds2i {
template <typename IndexedSequence>
class sequence_collection {
public:
typedef typename IndexedSequence::enumerator enumerator_type;
sequence_collection()
{}
class builder {
public:
builder(global_parameters const& params)
: m_queue(1 << 24)
, m_params(params)
, m_sequences(params)
{}
template <typename Iterator>
void add_sequence(Iterator begin, uint64_t last_element, uint64_t n)
{
if (!n) throw std::invalid_argument("Sequence must be nonempty");
// make_shared does not seem to work
std::shared_ptr<sequence_adder<Iterator>>
ptr(new sequence_adder<Iterator>(*this, begin, last_element, n));
m_queue.add_job(ptr, n);
}
void build(sequence_collection& sq)
{
m_queue.complete();
sq.m_params = m_params;
m_sequences.build(sq.m_sequences);
}
private:
template <typename Iterator>
struct sequence_adder : semiasync_queue::job {
sequence_adder(builder& b,
Iterator begin,
uint64_t last_element,
uint64_t n)
: b(b)
, begin(begin)
, last_element(last_element)
, n(n)
{}
virtual void prepare()
{
// store approximation of the universe as smallest power of two
// that can represent last_element
uint64_t universe_bits = ceil_log2(last_element);
write_gamma(bits, universe_bits);
write_gamma_nonzero(bits, n);
IndexedSequence::write(bits, begin,
(uint64_t(1) << universe_bits) + 1, n,
b.m_params);
}
virtual void commit()
{
b.m_sequences.append(bits);
}
builder& b;
Iterator begin;
uint64_t last_element;
uint64_t n;
succinct::bit_vector_builder bits;
};
semiasync_queue m_queue;
global_parameters m_params;
bitvector_collection::builder m_sequences;
};
size_t size() const
{
return m_sequences.size();
}
enumerator_type operator[](size_t i) const
{
assert(i < size());
auto it = m_sequences.get(m_params, i);
uint64_t universe_bits = read_gamma(it);
uint64_t n = read_gamma_nonzero(it);
return enumerator_type(m_sequences.bits(), it.position(),
(uint64_t(1) << universe_bits) + 1, n,
m_params);
}
void swap(sequence_collection& other)
{
std::swap(m_params, other.m_params);
std::swap(m_size, other.m_size);
m_sequences.swap(other.m_sequences);
}
template <typename Visitor>
void map(Visitor& visit)
{
visit
(m_params, "m_params")
(m_size, "m_size")
(m_sequences, "m_sequences")
;
}
private:
global_parameters m_params;
size_t m_size;
bitvector_collection m_sequences;
};
}