-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcompound_rb.hpp
More file actions
112 lines (101 loc) · 3.49 KB
/
compound_rb.hpp
File metadata and controls
112 lines (101 loc) · 3.49 KB
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
#ifndef COMPOUND_RB_H
#define COMPOUND_RB_H
#include "ringbuffer.hpp"
#include <vector>
#include <cassert>
/* CompoundRingBuffer<V,T,t0>
* A data structure to store a collection of variables at various
* time points, such that each variable has its own "expiration date"
* of how long data for that variable needs to be maintained in the
* ring buffer.
* V - data type for individual variables (must be uniform)
* T - data type for the timestamp value (default double)
* t0 - the data value defining the timestamp of the initial state (default 0)
*/
template<class V, class T = double>
class CompoundRingBuffer {
private:
std::vector< RingBuffer<V> > _stateVars;
std::vector<T> _maxDelays;
public:
RingBuffer<T> _timestamp;
RingBuffer<T> _h;
//Create a CRB to track N state variables, defining their maximum delays
// and initial values with provided vectors whose lengths must be N
CompoundRingBuffer(size_t n, T t0, T h0, std::vector<T>&& max_delays,
const std::vector<V>& init_vals):
_timestamp(), _h(), _stateVars(n), _maxDelays(max_delays) {
//Add two copies of the initial entry to keep update logic simpler
_timestamp[0] = t0;
_timestamp.append_to_head(t0);
_h[0] = h0;
_h.append_to_head(h0);
for (size_t index = 0; index < n; index++) {
init_vals.at(index)[0] = init_vals[index];
init_vals.at(index).append_to_head(init_vals[index]);
}
}
CompoundRingBuffer(size_t n, T t0, T h0, const std::vector<T>& max_delays,
const std::vector<V>& init_vals):
_timestamp(), _h(), _stateVars(n), _maxDelays(max_delays) {
assert(max_delays.size() >= n && init_vals.size() >= n);
//Add two copies of the initial entry to keep update logic simpler
_timestamp[0] = t0 - 1;
_timestamp.append_to_head(t0);
_h[0] = h0;
_h.append_to_head(h0);
for (size_t index = 0; index < n; index++) {
_stateVars.at(index)[0] = init_vals[index];
_stateVars.at(index).append_to_head(init_vals[index]);
}
}
CompoundRingBuffer() {}
void update(T t, T h, const std::vector<V>& vals) {
bool append_any = false;
assert(vals.size() >= _stateVars.size());
for (size_t i = 0; i < _stateVars.size(); i++) {
//If the timestamp of the new last item would still be more than
// maxDelay in the past for this state variable given the timestamp
// of the newest data entry, advance. Otherwise, extend.
if ( _timestamp[_timestamp.size()-1] < t - _maxDelays[i]) {
_stateVars[i].advance();
} else {
_stateVars[i].extend();
append_any = true;
}
_stateVars[i][0] = vals[i];
}
if (append_any) {
_timestamp.extend();
_h.extend();
} else {
_timestamp.advance();
_h.advance();
}
_timestamp[0] = t;
_h[0] = h;
}
size_t bisect(T target) const {
//Remember that values are sorted in "reverse" order
//Start, end inclusive range
size_t start = 0;
size_t end = _timestamp.size()-1;
while (start < end) {
size_t mid = (start + end) / 2;
if ( _timestamp[mid] < target ) {
end = mid;
} else {
start = mid+1;
}
}
// reduce to most recent sample if _timestamp[start] == _timstamp[start-1] (might happen for initial case)
while ((_timestamp[start] != 0) && (_timestamp[start] == _timestamp[start-1])) {
start--;
}
return start;
}
const RingBuffer<V>& operator[](size_t y_i) const {
return _stateVars[y_i];
}
};
#endif