107 lines
2.2 KiB
Java
107 lines
2.2 KiB
Java
/**
|
|
* DataOutputStream for fast-compact encoding of number sequences
|
|
*
|
|
* @author ab
|
|
*/
|
|
package btools.util;
|
|
|
|
import java.io.DataOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.OutputStream;
|
|
|
|
|
|
public final class MixCoderDataOutputStream extends DataOutputStream {
|
|
private int lastValue;
|
|
private int lastLastValue;
|
|
private int repCount;
|
|
private int diffshift;
|
|
|
|
private int bm = 1; // byte mask (write mode)
|
|
private int b = 0;
|
|
|
|
public static int[] diffs = new int[100];
|
|
public static int[] counts = new int[100];
|
|
|
|
public MixCoderDataOutputStream(OutputStream os) {
|
|
super(os);
|
|
}
|
|
|
|
public void writeMixed(int v) throws IOException {
|
|
if (v != lastValue && repCount > 0) {
|
|
int d = lastValue - lastLastValue;
|
|
lastLastValue = lastValue;
|
|
|
|
encodeBit(d < 0);
|
|
if (d < 0) {
|
|
d = -d;
|
|
}
|
|
encodeVarBits(d - diffshift);
|
|
encodeVarBits(repCount - 1);
|
|
|
|
if (d < 100) diffs[d]++;
|
|
if (repCount < 100) counts[repCount]++;
|
|
|
|
diffshift = 1;
|
|
repCount = 0;
|
|
}
|
|
lastValue = v;
|
|
repCount++;
|
|
}
|
|
|
|
@Override
|
|
public void flush() throws IOException {
|
|
int v = lastValue;
|
|
writeMixed(v + 1);
|
|
lastValue = v;
|
|
repCount = 0;
|
|
if (bm > 1) {
|
|
writeByte((byte) b); // flush bit-coding
|
|
}
|
|
}
|
|
|
|
public void encodeBit(boolean value) throws IOException {
|
|
if (bm == 0x100) {
|
|
writeByte((byte) b);
|
|
bm = 1;
|
|
b = 0;
|
|
}
|
|
if (value) {
|
|
b |= bm;
|
|
}
|
|
bm <<= 1;
|
|
}
|
|
|
|
public void encodeVarBits(int value) throws IOException {
|
|
int range = 0;
|
|
while (value > range) {
|
|
encodeBit(false);
|
|
value -= range + 1;
|
|
range = 2 * range + 1;
|
|
}
|
|
encodeBit(true);
|
|
encodeBounded(range, value);
|
|
}
|
|
|
|
public void encodeBounded(int max, int value) throws IOException {
|
|
int im = 1; // integer mask
|
|
while (im <= max) {
|
|
if (bm == 0x100) {
|
|
writeByte((byte) b);
|
|
bm = 1;
|
|
b = 0;
|
|
}
|
|
if ((value & im) != 0) {
|
|
b |= bm;
|
|
max -= im;
|
|
}
|
|
bm <<= 1;
|
|
im <<= 1;
|
|
}
|
|
}
|
|
|
|
public static void stats() {
|
|
for (int i = 1; i < 100; i++) System.out.println("diff[" + i + "] = " + diffs[i]);
|
|
for (int i = 1; i < 100; i++) System.out.println("counts[" + i + "] = " + counts[i]);
|
|
}
|
|
}
|