encode method

List<int> encode(
  1. List<int> data
)

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;
}