-
Notifications
You must be signed in to change notification settings - Fork 39
/
Copy pathIndirectContext.hpp
50 lines (43 loc) · 1.38 KB
/
IndirectContext.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
#pragma once
#include "Array.hpp"
#include <cassert>
#include <cstdint>
template<typename T>
class IndirectContext {
private:
Array<T> data;
T *ctx;
const uint32_t ctxMask, inputMask, inputBits, contextBits;
public:
IndirectContext(const int bitsPerContext, const int inputBits, const int contextBits = sizeof(T)*8) :
data(UINT64_C(1) << bitsPerContext), ctx(&data[0]),
ctxMask((UINT32_C(1) << bitsPerContext) - 1),
inputMask((UINT32_C(1) << inputBits) - 1),
inputBits(inputBits),
contextBits(contextBits) {
assert(bitsPerContext > 0 && bitsPerContext <= 20);
assert(inputBits > 0 && inputBits <= 8);
assert(contextBits <= sizeof(T)*8);
if (contextBits < sizeof(T) * 8) // need for leading bit -> include it
reset();
}
void reset() {
for (uint64_t i = 0; i < data.size(); ++i) {
data[i] = contextBits < sizeof(T) * 8 ? 1 : 0; // 1: leading bit to indicate the number of used bits
}
}
void operator+=(const uint32_t i) {
assert(i <= inputMask);
// note: when the context is fully mature, we need to keep the leading bit in front of the contextbits as the MSB
T leadingBit = (*ctx) & (1 << contextBits);
(*ctx) <<= inputBits;
(*ctx) |= i | leadingBit;
(*ctx) &= (1 << (contextBits + 1)) - 1;
};
void operator=(const uint32_t i) {
ctx = &data[i & ctxMask];
}
T& operator()() {
return *ctx;
};
};