encode method
Implementation
List<int> encode(List<int> data) {
if (data.isEmpty) return [];
// build model
final freq = <int, int>{};
for (var b in data) {
freq[b] = (freq[b] ?? 0) + 1;
}
final alphabet = freq.keys.toList()..sort();
final counts = alphabet.map((a) => freq[a]!).toList();
final total = counts.fold<int>(0, (p, e) => p + e);
// cumulative
final cum = <int>[0];
for (var c in counts) {
cum.add(cum.last + c);
}
var low = 0;
var high = _maxvalue;
var bitsToFollow = 0;
final out = <int>[];
int bitBuffer = 0;
int bitCount = 0;
void outputBit(int bit) {
bitBuffer = (bitBuffer << 1) | (bit & 1);
bitCount++;
if (bitCount == 8) {
out.add(bitBuffer & 0xff);
bitBuffer = 0;
bitCount = 0;
}
}
void outputBitPlusFollow(int bit) {
outputBit(bit);
for (var i = 0; i < bitsToFollow; i++) {
outputBit(bit ^ 1);
}
bitsToFollow = 0;
}
for (var symByte in data) {
final idx = alphabet.indexOf(symByte);
final symLow = cum[idx];
final symHigh = cum[idx + 1];
final range = high - low + 1;
high = low + (range * symHigh ~/ total) - 1;
low = low + (range * symLow ~/ total);
// renormalize
while (true) {
if (high < _half) {
outputBitPlusFollow(0);
} else if (low >= _half) {
outputBitPlusFollow(1);
low -= _half;
high -= _half;
} else if (low >= _firstqtr && high < _thirdqtr) {
bitsToFollow++;
low -= _firstqtr;
high -= _firstqtr;
} else {
break;
}
low = low << 1;
high = (high << 1) | 1;
}
}
// finish: emit one bit and follow
bitsToFollow++;
if (low < _firstqtr) {
outputBitPlusFollow(0);
} else {
outputBitPlusFollow(1);
}
// flush remaining bits (pad with zeros)
if (bitCount > 0) {
out.add((bitBuffer << (8 - bitCount)) & 0xff);
}
return out;
}