80 lines
1.8 KiB
Java
80 lines
1.8 KiB
Java
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
|
|
* <p>
|
|
* 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++;
|
|
}
|
|
}
|