#ifndef __DECODE_HPP__
#define __DECODE_HPP__
#include <iterator>
using namespace std;
void decode(reader &r, vector<size_t>& rle) {
constexpr uint64_t MAX_CODE = (((uint64_t)1) << CODE_VALUE_BITS)-1;
constexpr uint64_t ONE_FOURTH = (MAX_CODE + ((uint64_t)1))/4;
constexpr uint64_t ONE_HALF = ONE_FOURTH*2;
constexpr uint64_t THREE_FOURTHS = ONE_FOURTH*3;
uint64_t dict_size = read_bits(r, sizeof(uint64_t)*8);
std::map<uint64_t, uint64_t> lowers;
uint64_t count = 0;
for (uint64_t i = 0; i < dict_size; ++i) {
uint8_t key_len = read_bits(r, 6);
uint64_t key = read_bits(r, key_len);
uint8_t freq_len = read_bits(r, 6);
uint64_t freq = read_bits(r, freq_len);
lowers[count] = key;
count += freq;
}
uint64_t n_symbols = read_bits(r, sizeof(uint64_t)*8);
lowers[n_symbols] = 0;
uint64_t high = MAX_CODE;
uint64_t low = 0;
uint64_t value = 0;
value = read_bits(r, CODE_VALUE_BITS);
for ( ; ; ) {
uint64_t range = high - low + 1;
uint64_t scaled_value = ((value - low + 1) * n_symbols - 1 ) / range;
std::map<uint64_t, uint64_t>::iterator it = lowers.upper_bound(scaled_value);
uint64_t phigh = it->first;
it--;
uint64_t c = it->second;
rle.push_back(c);
uint64_t plow = it->first;
high = low + (range*phigh)/n_symbols -1;
low = low + (range*plow)/n_symbols;
for( ; ; ) {
if ( high < ONE_HALF ) {
} else if ( low >= ONE_HALF ) {
value -= ONE_HALF; low -= ONE_HALF;
high -= ONE_HALF;
} else if ( low >= ONE_FOURTH && high < THREE_FOURTHS ) {
value -= ONE_FOURTH;
low -= ONE_FOURTH;
high -= ONE_FOURTH;
} else
break;
low <<= 1;
high <<= 1;
high++;
value <<= 1;
value += read_bits(r, 1) ? 1 : 0;
}
if (rle.size() == n_symbols)
break;
}
}
#endif