package btools.codec; /** * Encoder/Decoder for signed integers that automatically detects the typical * range of these numbers to determine a noisy-bit count as a very simple * dictionary *
* Adapted for 3-pass encoding (counters -> statistics -> encoding ) * but doesn't do anything at pass1 */ public final class NoisyDiffCoder { private int tot; private int[] freqs; private int noisybits; private StatCoderContext bc; private int pass; /** * Create a decoder and read the noisy-bit count from the gibe context */ public NoisyDiffCoder(StatCoderContext bc) { noisybits = bc.decodeVarBits(); this.bc = bc; } /** * Create an encoder for 3-pass-encoding */ public NoisyDiffCoder() { } /** * encodes a signed int (pass3 only, stats collection in pass2) */ public void encodeSignedValue(int value) { if (pass == 3) { bc.encodeNoisyDiff(value, noisybits); } else if (pass == 2) { count(value < 0 ? -value : value); } } /** * decodes a signed int */ public int decodeSignedValue() { return bc.decodeNoisyDiff(noisybits); } /** * Starts a new encoding pass and (in pass3) calculates the noisy-bit count * from the stats collected in pass2 and writes that to the given context */ public void encodeDictionary(StatCoderContext bc) { if (++pass == 3) { // how many noisy bits? for (noisybits = 0; noisybits < 14 && tot > 0; noisybits++) { if (freqs[noisybits] < (tot >> 1)) break; } bc.encodeVarBits(noisybits); } this.bc = bc; } private void count(int value) { if (freqs == null) freqs = new int[14]; int bm = 1; for (int i = 0; i < 14; i++) { if (value < bm) break; else freqs[i]++; bm <<= 1; } tot++; } }