123 lines
2.4 KiB
Java
123 lines
2.4 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 final void encodeBit( boolean value ) throws IOException
|
|
{
|
|
if ( bm == 0x100 )
|
|
{
|
|
writeByte( (byte)b );
|
|
bm = 1;
|
|
b = 0;
|
|
}
|
|
if ( value )
|
|
{
|
|
b |= bm;
|
|
}
|
|
bm <<= 1;
|
|
}
|
|
|
|
public final 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 final 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] );
|
|
}
|
|
}
|