-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathDynamicFlatFIT.hpp
154 lines (129 loc) · 4.02 KB
/
DynamicFlatFIT.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
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
#ifndef __DYNAMIC_FLATFIT_H__
#define __DYNAMIC_FLATFIT_H__
#include<vector>
#include<iterator>
#include<algorithm>
#include<cassert>
#ifdef DEBUG
#define _IFDEBUG(x) x
#else
#define _IFDEBUG(x)
#endif
namespace dynamic_flatfit {
// grow and shrink factor: grow by a factor of THRES and
// shrink by THRES when the load drops below a factor of 2*THRES
const int THRES = 2;
const int LOW_CAP = 2;
template<typename valT, typename ptrT>
class __AggT {
public:
valT _val;
ptrT _next;
__AggT() {}
__AggT(valT val_)
: _val(val_) {}
__AggT(valT val_, ptrT next_)
: _val(val_), _next(next_) {}
};
template<typename binOpFunc>
class Aggregate {
public:
typedef uint32_t ptrT;
typedef typename binOpFunc::In inT;
typedef typename binOpFunc::Partial aggT;
typedef typename binOpFunc::Out outT;
typedef __AggT<aggT, ptrT> AggT;
Aggregate(binOpFunc binOp_, aggT identE_)
: _size(0), _buffer(LOW_CAP),
_ever_evicted(false),
_front(0), _back(-1),
_binOp(binOp_), _identE(identE_) {}
size_t size() { return _size; }
void insert(inT v) {
if (_size + 1 > (int) _buffer.size())
rescale_to(_buffer.size()*THRES, _size + 1);
int prev = (_size > 0)?_back:-1;
AggT vAgg = AggT(_binOp.lift(v), 0);
++_back; ++_size;
_back %= _buffer.size();
_buffer[_back] = vAgg;
if (prev>=0)
_buffer[prev]._next = _back;
}
void evict() {
_front = (_front + 1)%_buffer.size();
--_size;
if (_size < (int) _buffer.size()/(2*THRES))
rescale_to(_buffer.size()/THRES, _size);
}
outT query() {
// invariant: _tracing_indicies is empty coming in
if (_size == 0)
return _binOp.lower(_identE);
// for non-empty cases
for (int cur=_front;cur!=_back;cur=_buffer[cur]._next)
_tracing_indices.push_back(cur);
aggT theSum = _identE;
while (!_tracing_indices.empty()) {
int index = _tracing_indices.back();
theSum = _binOp.combine(_buffer[index]._val, theSum);
_buffer[index] = AggT(theSum, _back);
_tracing_indices.pop_back();
}
// invariant: _tracing_indicies is empty going out
return _binOp.lower(_binOp.combine(theSum, _buffer[_back]._val));
}
friend inline std::ostream& operator<<(std::ostream& os, Aggregate const& t) {
os << "(f=" << t._front << ",b=" << t._back << ",s=" << t._size << ") -- ";
for (int i=0;i<t._buffer.size();i++) {
os << "[" << t._buffer[i]._val << "; " << t._buffer[i]._next << "]";
}
return os;
}
private:
int _size;
std::vector<AggT> _buffer;
std::vector<int> _tracing_indices;
bool _ever_evicted;
int32_t _front, _back;
// the binary operator deck
binOpFunc _binOp;
aggT _identE;
void rescale_to(size_t new_size, size_t ensure_size) {
new_size = std::max(new_size, (size_t) LOW_CAP);
if (ensure_size > new_size) {
std::cerr << "Baka!!" << std::endl;
throw 1; // should never happen
}
std::vector<AggT> rescaled_buffer(new_size);
// pack and reindex the next pointers
size_t old_cap = _buffer.size();
for (int index=0;index<_size;++index) {
AggT & elt = _buffer[(_front + index)%old_cap];
rescaled_buffer[index] = elt;
int offset = (elt._next + old_cap - _front) % old_cap;
rescaled_buffer[index]._next = offset;
}
// swap
_buffer.swap(rescaled_buffer);
// reset front and back
// when _size == 0, we want _back = -1, so this has the right effect.
_front = 0;
_back = _size - 1;
}
};
template <class BinaryFunction, class T>
Aggregate<BinaryFunction>
make_aggregate(BinaryFunction f, T elem) {
return Aggregate<BinaryFunction>(f, elem);
}
template <typename BinaryFunction>
struct MakeAggregate {
template <typename T>
Aggregate<BinaryFunction> operator()(T elem) {
BinaryFunction f;
return make_aggregate<>(f, elem);
}
};
}
#endif