I have working simplish arithmetic encoder based on Drdobbs ARcoder. The de/encoding algorithm boils down to maintaining symbol probabilities in array and updating them. The problem is that I would like to expand it to support growing number of symbols than fixed +256 or so symbols. The current implementation
of update_model() and getsym() are too slow if number of symbols increase too much.
Can I convert the cumulative_freq array into tree like data-structure for faster lookup and updating? I don't mind if the algorithm ends up consuming more memory as long as it scales better.
const u32 MAX_INPUT_VAL = 255;
const u32 CODE_RESCALE = MAX_INPUT_VAL+1;
const u32 CODE_EOF = MAX_INPUT_VAL+2;
const u32 CUMULATIVE_TOTAL = MAX_INPUT_VAL+3; // total sum of all frequencies before.
const u32 CODES_END = MAX_INPUT_VAL+4;
u32 cumulative_freq[CODES_END];
// (Init symbol freqs)
for(u32 i = 0; i < CODES_END; ++i) {
cumulative_freq[i] = i;
}
// update value propability
void update_model(u32 v) {
// how can I make this scale better for more symbols?
for(code_t i = v + 1; i < CODES_END; ++i) {
cumulative_freq[i]++;
}
}
struct sym {
u32 low;
u32 high;
u32 count;
};
// encode symbol: get symbol propability
sym propability(u32 v) {
sym p{cumulative_freq[v], cumulative_freq[v+1], cumulative_freq[CUMULATIVE_TOTAL]};
update_model(v);
return p;
}
// decode symbol:
std::pair<sym, u32> getsym(u64 prop) {
// how can I make this scale better for more symbols?
for(u32 i = 0; i < CUMULATIVE_TOTAL; ++i) {
if(prop < cumulative_freq[i+1]) {
sym p{cumulative_freq[i],cumulative_freq[i+1],cumulative_freq[CUMULATIVE_TOTAL]};
update_model(i);
return {p,i};
}
}
// error: decode failed.
}