Reformat whole codebase using Android Studio
This commit is contained in:
parent
d5322667d5
commit
c15913c1ab
161 changed files with 15124 additions and 18537 deletions
|
|
@ -1,8 +1,7 @@
|
|||
package btools.util;
|
||||
|
||||
|
||||
public class BitCoderContext
|
||||
{
|
||||
public class BitCoderContext {
|
||||
private byte[] ab;
|
||||
private int idxMax;
|
||||
private int idx = -1;
|
||||
|
|
@ -19,13 +18,11 @@ public class BitCoderContext
|
|||
|
||||
private static final int[] bm2bits = new int[256];
|
||||
|
||||
static
|
||||
{
|
||||
static {
|
||||
// fill varbits lookup table
|
||||
|
||||
BitCoderContext bc = new BitCoderContext( new byte[4] );
|
||||
for( int i=0; i<4096; i++ )
|
||||
{
|
||||
BitCoderContext bc = new BitCoderContext(new byte[4]);
|
||||
for (int i = 0; i < 4096; i++) {
|
||||
bc.reset();
|
||||
bc.bits = 14;
|
||||
bc.b = 0x1000 + i;
|
||||
|
|
@ -34,16 +31,14 @@ public class BitCoderContext
|
|||
vl_values[i] = bc.decodeVarBits2();
|
||||
vl_length[i] = bc.getReadingBitPosition() - b0;
|
||||
}
|
||||
for( int i=0; i<4096; i++ )
|
||||
{
|
||||
for (int i = 0; i < 4096; i++) {
|
||||
bc.reset();
|
||||
int b0 = bc.getWritingBitPosition();
|
||||
bc.encodeVarBits2( i );
|
||||
bc.encodeVarBits2(i);
|
||||
vc_values[i] = bc.b;
|
||||
vc_length[i] = bc.getWritingBitPosition() - b0;
|
||||
}
|
||||
for( int i=0; i<1024; i++ )
|
||||
{
|
||||
for (int i = 0; i < 1024; i++) {
|
||||
bc.reset();
|
||||
bc.bits = 14;
|
||||
bc.b = 0x1000 + i;
|
||||
|
|
@ -52,37 +47,31 @@ public class BitCoderContext
|
|||
vl_values[i] = bc.decodeVarBits2();
|
||||
vl_length[i] = bc.getReadingBitPosition() - b0;
|
||||
}
|
||||
for( int b=0; b<256; b++ )
|
||||
{
|
||||
for (int b = 0; b < 256; b++) {
|
||||
int r = 0;
|
||||
for( int i=0; i<8; i++ )
|
||||
{
|
||||
if ( (b & (1<<i) ) != 0 ) r |= 1 << (7-i);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if ((b & (1 << i)) != 0) r |= 1 << (7 - i);
|
||||
}
|
||||
reverse_byte[b] = r;
|
||||
}
|
||||
for( int b=0; b<8; b++ )
|
||||
{
|
||||
bm2bits[1<<b] = b;
|
||||
for (int b = 0; b < 8; b++) {
|
||||
bm2bits[1 << b] = b;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public BitCoderContext( byte[] ab )
|
||||
{
|
||||
public BitCoderContext(byte[] ab) {
|
||||
this.ab = ab;
|
||||
idxMax = ab.length-1;
|
||||
idxMax = ab.length - 1;
|
||||
}
|
||||
|
||||
public final void reset( byte[] ab )
|
||||
{
|
||||
public final void reset(byte[] ab) {
|
||||
this.ab = ab;
|
||||
idxMax = ab.length-1;
|
||||
idxMax = ab.length - 1;
|
||||
reset();
|
||||
}
|
||||
|
||||
public final void reset()
|
||||
{
|
||||
public final void reset() {
|
||||
idx = -1;
|
||||
bits = 0;
|
||||
b = 0;
|
||||
|
|
@ -98,78 +87,67 @@ public class BitCoderContext
|
|||
*
|
||||
* @see #decodeVarBits
|
||||
*/
|
||||
public final void encodeVarBits2( int value )
|
||||
{
|
||||
public final void encodeVarBits2(int value) {
|
||||
int range = 0;
|
||||
while (value > range)
|
||||
{
|
||||
encodeBit( false );
|
||||
while (value > range) {
|
||||
encodeBit(false);
|
||||
value -= range + 1;
|
||||
range = 2 * range + 1;
|
||||
}
|
||||
encodeBit( true );
|
||||
encodeBounded( range, value );
|
||||
encodeBit(true);
|
||||
encodeBounded(range, value);
|
||||
}
|
||||
|
||||
public final void encodeVarBits( int value )
|
||||
{
|
||||
if ( (value & 0xfff) == value )
|
||||
{
|
||||
public final void encodeVarBits(int value) {
|
||||
if ((value & 0xfff) == value) {
|
||||
flushBuffer();
|
||||
b |= vc_values[value] << bits;
|
||||
bits += vc_length[value];
|
||||
}
|
||||
else
|
||||
{
|
||||
encodeVarBits2( value ); // slow fallback for large values
|
||||
bits += vc_length[value];
|
||||
} else {
|
||||
encodeVarBits2(value); // slow fallback for large values
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #encodeVarBits
|
||||
*/
|
||||
public final int decodeVarBits2()
|
||||
{
|
||||
public final int decodeVarBits2() {
|
||||
int range = 0;
|
||||
while (!decodeBit())
|
||||
{
|
||||
while (!decodeBit()) {
|
||||
range = 2 * range + 1;
|
||||
}
|
||||
return range + decodeBounded( range );
|
||||
return range + decodeBounded(range);
|
||||
}
|
||||
|
||||
public final int decodeVarBits()
|
||||
{
|
||||
public final int decodeVarBits() {
|
||||
fillBuffer();
|
||||
int b12 = b & 0xfff;
|
||||
int len = vl_length[b12];
|
||||
if ( len <= 12 )
|
||||
{
|
||||
if (len <= 12) {
|
||||
b >>>= len;
|
||||
bits -= len;
|
||||
return vl_values[b12]; // full value lookup
|
||||
}
|
||||
if ( len <= 23 ) // // only length lookup
|
||||
if (len <= 23) // // only length lookup
|
||||
{
|
||||
int len2 = len >> 1;
|
||||
b >>>= (len2+1);
|
||||
int mask = 0xffffffff >>> ( 32 - len2 );
|
||||
b >>>= (len2 + 1);
|
||||
int mask = 0xffffffff >>> (32 - len2);
|
||||
mask += b & mask;
|
||||
b >>>= len2;
|
||||
bits -= len;
|
||||
return mask;
|
||||
}
|
||||
if ( (b & 0xffffff) != 0 )
|
||||
{
|
||||
if ((b & 0xffffff) != 0) {
|
||||
// here we just know len in [25..47]
|
||||
// ( fillBuffer guarantees only 24 bits! )
|
||||
b >>>= 12;
|
||||
int len3 = 1 + (vl_length[b & 0xfff]>>1);
|
||||
int len3 = 1 + (vl_length[b & 0xfff] >> 1);
|
||||
b >>>= len3;
|
||||
int len2 = 11 + len3;
|
||||
bits -= len2+1;
|
||||
bits -= len2 + 1;
|
||||
fillBuffer();
|
||||
int mask = 0xffffffff >>> ( 32 - len2 );
|
||||
int mask = 0xffffffff >>> (32 - len2);
|
||||
mask += b & mask;
|
||||
b >>>= len2;
|
||||
bits -= len2;
|
||||
|
|
@ -179,29 +157,24 @@ public class BitCoderContext
|
|||
}
|
||||
|
||||
|
||||
public final void encodeBit( boolean value )
|
||||
{
|
||||
if (bits > 31)
|
||||
{
|
||||
ab[++idx] = (byte)(b & 0xff);
|
||||
public final void encodeBit(boolean value) {
|
||||
if (bits > 31) {
|
||||
ab[++idx] = (byte) (b & 0xff);
|
||||
b >>>= 8;
|
||||
bits -=8;
|
||||
bits -= 8;
|
||||
}
|
||||
if ( value )
|
||||
{
|
||||
if (value) {
|
||||
b |= 1 << bits;
|
||||
}
|
||||
bits++;
|
||||
}
|
||||
|
||||
public final boolean decodeBit()
|
||||
{
|
||||
if ( bits == 0 )
|
||||
{
|
||||
public final boolean decodeBit() {
|
||||
if (bits == 0) {
|
||||
bits = 8;
|
||||
b = ab[++idx] & 0xff;
|
||||
}
|
||||
boolean value = ( ( b & 1 ) != 0 );
|
||||
boolean value = ((b & 1) != 0);
|
||||
b >>>= 1;
|
||||
bits--;
|
||||
return value;
|
||||
|
|
@ -213,19 +186,14 @@ public class BitCoderContext
|
|||
* this is variable length encoding, with the shorter codes
|
||||
* for the central value range
|
||||
*/
|
||||
public final void encodeBounded( int max, int value )
|
||||
{
|
||||
public final void encodeBounded(int max, int value) {
|
||||
int im = 1; // integer mask
|
||||
while (im <= max)
|
||||
{
|
||||
if ( ( value & im ) != 0 )
|
||||
{
|
||||
encodeBit( true );
|
||||
while (im <= max) {
|
||||
if ((value & im) != 0) {
|
||||
encodeBit(true);
|
||||
max -= im;
|
||||
}
|
||||
else
|
||||
{
|
||||
encodeBit( false );
|
||||
} else {
|
||||
encodeBit(false);
|
||||
}
|
||||
im <<= 1;
|
||||
}
|
||||
|
|
@ -233,20 +201,18 @@ public class BitCoderContext
|
|||
|
||||
/**
|
||||
* decode an integer in the range 0..max (inclusive).
|
||||
*
|
||||
* @see #encodeBounded
|
||||
*/
|
||||
public final int decodeBounded( int max )
|
||||
{
|
||||
public final int decodeBounded(int max) {
|
||||
int value = 0;
|
||||
int im = 1; // integer mask
|
||||
while (( value | im ) <= max)
|
||||
{
|
||||
if ( bits == 0 )
|
||||
{
|
||||
while ((value | im) <= max) {
|
||||
if (bits == 0) {
|
||||
bits = 8;
|
||||
b = ab[++idx] & 0xff;
|
||||
}
|
||||
if ( ( b & 1 ) != 0 )
|
||||
if ((b & 1) != 0)
|
||||
value |= im;
|
||||
b >>>= 1;
|
||||
bits--;
|
||||
|
|
@ -255,67 +221,57 @@ public class BitCoderContext
|
|||
return value;
|
||||
}
|
||||
|
||||
public final int decodeBits( int count )
|
||||
{
|
||||
public final int decodeBits(int count) {
|
||||
fillBuffer();
|
||||
int mask = 0xffffffff >>> ( 32 - count );
|
||||
int mask = 0xffffffff >>> (32 - count);
|
||||
int value = b & mask;
|
||||
b >>>= count;
|
||||
bits -= count;
|
||||
return value;
|
||||
}
|
||||
|
||||
public final int decodeBitsReverse( int count )
|
||||
{
|
||||
public final int decodeBitsReverse(int count) {
|
||||
fillBuffer();
|
||||
int value = 0;
|
||||
while( count > 8 )
|
||||
{
|
||||
value = (value << 8) | reverse_byte[ b & 0xff ];
|
||||
b >>=8;
|
||||
count -=8;
|
||||
bits -=8;
|
||||
while (count > 8) {
|
||||
value = (value << 8) | reverse_byte[b & 0xff];
|
||||
b >>= 8;
|
||||
count -= 8;
|
||||
bits -= 8;
|
||||
fillBuffer();
|
||||
}
|
||||
value = (value << count) | reverse_byte[ b & 0xff ] >> (8-count);
|
||||
value = (value << count) | reverse_byte[b & 0xff] >> (8 - count);
|
||||
bits -= count;
|
||||
b >>= count;
|
||||
return value;
|
||||
}
|
||||
|
||||
private void fillBuffer()
|
||||
{
|
||||
while (bits < 24)
|
||||
{
|
||||
if ( idx++ < idxMax )
|
||||
{
|
||||
private void fillBuffer() {
|
||||
while (bits < 24) {
|
||||
if (idx++ < idxMax) {
|
||||
b |= (ab[idx] & 0xff) << bits;
|
||||
}
|
||||
bits += 8;
|
||||
}
|
||||
}
|
||||
|
||||
private void flushBuffer()
|
||||
{
|
||||
while (bits > 7)
|
||||
{
|
||||
ab[++idx] = (byte)(b & 0xff);
|
||||
private void flushBuffer() {
|
||||
while (bits > 7) {
|
||||
ab[++idx] = (byte) (b & 0xff);
|
||||
b >>>= 8;
|
||||
bits -=8;
|
||||
bits -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* flushes and closes the (write-mode) context
|
||||
*
|
||||
* flushes and closes the (write-mode) context
|
||||
*
|
||||
* @return the encoded length in bytes
|
||||
*/
|
||||
public final int closeAndGetEncodedLength()
|
||||
{
|
||||
public final int closeAndGetEncodedLength() {
|
||||
flushBuffer();
|
||||
if ( bits > 0 )
|
||||
{
|
||||
ab[++idx] = (byte)(b & 0xff);
|
||||
if (bits > 0) {
|
||||
ab[++idx] = (byte) (b & 0xff);
|
||||
}
|
||||
return idx + 1;
|
||||
}
|
||||
|
|
@ -323,51 +279,43 @@ public class BitCoderContext
|
|||
/**
|
||||
* @return the encoded length in bits
|
||||
*/
|
||||
public final int getWritingBitPosition()
|
||||
{
|
||||
public final int getWritingBitPosition() {
|
||||
return (idx << 3) + 8 + bits;
|
||||
}
|
||||
|
||||
public final int getReadingBitPosition()
|
||||
{
|
||||
public final int getReadingBitPosition() {
|
||||
return (idx << 3) + 8 - bits;
|
||||
}
|
||||
|
||||
public final void setReadingBitPosition(int pos)
|
||||
{
|
||||
public final void setReadingBitPosition(int pos) {
|
||||
idx = pos >>> 3;
|
||||
bits = (idx << 3) + 8 - pos;
|
||||
b = ab[idx] & 0xff;
|
||||
b >>>= (8-bits);
|
||||
b >>>= (8 - bits);
|
||||
}
|
||||
|
||||
public static void main( String[] args )
|
||||
{
|
||||
public static void main(String[] args) {
|
||||
byte[] ab = new byte[581969];
|
||||
BitCoderContext ctx = new BitCoderContext( ab );
|
||||
for ( int i = 0; i < 31; i++ )
|
||||
{
|
||||
ctx.encodeVarBits( (1<<i)+3 );
|
||||
BitCoderContext ctx = new BitCoderContext(ab);
|
||||
for (int i = 0; i < 31; i++) {
|
||||
ctx.encodeVarBits((1 << i) + 3);
|
||||
}
|
||||
for ( int i = 0; i < 100000; i+=13 )
|
||||
{
|
||||
ctx.encodeVarBits( i );
|
||||
for (int i = 0; i < 100000; i += 13) {
|
||||
ctx.encodeVarBits(i);
|
||||
}
|
||||
ctx.closeAndGetEncodedLength();
|
||||
ctx = new BitCoderContext( ab );
|
||||
ctx = new BitCoderContext(ab);
|
||||
|
||||
for ( int i = 0; i < 31; i++ )
|
||||
{
|
||||
for (int i = 0; i < 31; i++) {
|
||||
int value = ctx.decodeVarBits();
|
||||
int v0 = (1<<i)+3;
|
||||
if ( !(v0 == value ) )
|
||||
throw new RuntimeException( "value mismatch value=" + value + "v0=" + v0 );
|
||||
int v0 = (1 << i) + 3;
|
||||
if (!(v0 == value))
|
||||
throw new RuntimeException("value mismatch value=" + value + "v0=" + v0);
|
||||
}
|
||||
for ( int i = 0; i < 100000; i+=13 )
|
||||
{
|
||||
for (int i = 0; i < 100000; i += 13) {
|
||||
int value = ctx.decodeVarBits();
|
||||
if ( !(value == i ) )
|
||||
throw new RuntimeException( "value mismatch i=" + i + "v=" + value );
|
||||
if (!(value == i))
|
||||
throw new RuntimeException("value mismatch i=" + i + "v=" + value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,60 +1,53 @@
|
|||
package btools.util;
|
||||
|
||||
public final class ByteArrayUnifier implements IByteArrayUnifier
|
||||
{
|
||||
public final class ByteArrayUnifier implements IByteArrayUnifier {
|
||||
private byte[][] byteArrayCache;
|
||||
private int[] crcCrosscheck;
|
||||
private int size;
|
||||
|
||||
public ByteArrayUnifier( int size, boolean validateImmutability )
|
||||
{
|
||||
public ByteArrayUnifier(int size, boolean validateImmutability) {
|
||||
this.size = size;
|
||||
byteArrayCache = new byte[size][];
|
||||
if ( validateImmutability ) crcCrosscheck = new int[size];
|
||||
if (validateImmutability) crcCrosscheck = new int[size];
|
||||
}
|
||||
|
||||
/**
|
||||
* Unify a byte array in order to reuse instances when possible.
|
||||
* The byte arrays are assumed to be treated as immutable,
|
||||
* allowing the reuse
|
||||
* @param ab the byte array to unify
|
||||
*
|
||||
* @param ab the byte array to unify
|
||||
* @return the cached instance or the input instanced if not cached
|
||||
*/
|
||||
public byte[] unify( byte[] ab )
|
||||
{
|
||||
return unify( ab, 0, ab.length );
|
||||
public byte[] unify(byte[] ab) {
|
||||
return unify(ab, 0, ab.length);
|
||||
}
|
||||
|
||||
public byte[] unify( byte[] ab, int offset, int len )
|
||||
{
|
||||
int crc = Crc32.crc( ab, offset, len );
|
||||
int idx = ( crc & 0xfffffff ) % size;
|
||||
public byte[] unify(byte[] ab, int offset, int len) {
|
||||
int crc = Crc32.crc(ab, offset, len);
|
||||
int idx = (crc & 0xfffffff) % size;
|
||||
byte[] abc = byteArrayCache[idx];
|
||||
if ( abc != null && abc.length == len )
|
||||
{
|
||||
if (abc != null && abc.length == len) {
|
||||
int i = 0;
|
||||
while (i < len)
|
||||
{
|
||||
if ( ab[offset + i] != abc[i] )
|
||||
while (i < len) {
|
||||
if (ab[offset + i] != abc[i])
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
if ( i == len )
|
||||
if (i == len)
|
||||
return abc;
|
||||
}
|
||||
if ( crcCrosscheck != null )
|
||||
{
|
||||
if ( byteArrayCache[idx] != null )
|
||||
{
|
||||
if (crcCrosscheck != null) {
|
||||
if (byteArrayCache[idx] != null) {
|
||||
byte[] abold = byteArrayCache[idx];
|
||||
int crcold = Crc32.crc( abold, 0, abold.length );
|
||||
if ( crcold != crcCrosscheck[idx] )
|
||||
throw new IllegalArgumentException( "ByteArrayUnifier: immutablity validation failed!" );
|
||||
int crcold = Crc32.crc(abold, 0, abold.length);
|
||||
if (crcold != crcCrosscheck[idx])
|
||||
throw new IllegalArgumentException("ByteArrayUnifier: immutablity validation failed!");
|
||||
}
|
||||
crcCrosscheck[idx] = crc;
|
||||
}
|
||||
byte[] nab = new byte[len];
|
||||
System.arraycopy( ab, offset, nab, 0, len );
|
||||
System.arraycopy(ab, offset, nab, 0, len);
|
||||
byteArrayCache[idx] = nab;
|
||||
return nab;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,72 +6,63 @@
|
|||
package btools.util;
|
||||
|
||||
|
||||
public class ByteDataReader
|
||||
{
|
||||
public class ByteDataReader {
|
||||
protected byte[] ab;
|
||||
protected int aboffset;
|
||||
protected int aboffsetEnd;
|
||||
|
||||
public ByteDataReader( byte[] byteArray )
|
||||
{
|
||||
ab = byteArray;
|
||||
aboffsetEnd = ab == null ? 0 : ab.length;
|
||||
public ByteDataReader(byte[] byteArray) {
|
||||
ab = byteArray;
|
||||
aboffsetEnd = ab == null ? 0 : ab.length;
|
||||
}
|
||||
|
||||
public ByteDataReader( byte[] byteArray, int offset )
|
||||
{
|
||||
ab = byteArray;
|
||||
aboffset = offset;
|
||||
aboffsetEnd = ab == null ? 0 : ab.length;
|
||||
public ByteDataReader(byte[] byteArray, int offset) {
|
||||
ab = byteArray;
|
||||
aboffset = offset;
|
||||
aboffsetEnd = ab == null ? 0 : ab.length;
|
||||
}
|
||||
|
||||
public final void reset( byte[] byteArray )
|
||||
{
|
||||
|
||||
public final void reset(byte[] byteArray) {
|
||||
ab = byteArray;
|
||||
aboffset = 0;
|
||||
aboffsetEnd = ab == null ? 0 : ab.length;
|
||||
}
|
||||
|
||||
|
||||
public final int readInt()
|
||||
{
|
||||
int i3 = ab[aboffset++]& 0xff;
|
||||
int i2 = ab[aboffset++]& 0xff;
|
||||
int i1 = ab[aboffset++]& 0xff;
|
||||
int i0 = ab[aboffset++]& 0xff;
|
||||
return (i3 << 24) + (i2 << 16) + (i1 << 8) + i0;
|
||||
|
||||
public final int readInt() {
|
||||
int i3 = ab[aboffset++] & 0xff;
|
||||
int i2 = ab[aboffset++] & 0xff;
|
||||
int i1 = ab[aboffset++] & 0xff;
|
||||
int i0 = ab[aboffset++] & 0xff;
|
||||
return (i3 << 24) + (i2 << 16) + (i1 << 8) + i0;
|
||||
}
|
||||
|
||||
public final long readLong()
|
||||
{
|
||||
long i7 = ab[aboffset++]& 0xff;
|
||||
long i6 = ab[aboffset++]& 0xff;
|
||||
long i5 = ab[aboffset++]& 0xff;
|
||||
long i4 = ab[aboffset++]& 0xff;
|
||||
long i3 = ab[aboffset++]& 0xff;
|
||||
long i2 = ab[aboffset++]& 0xff;
|
||||
long i1 = ab[aboffset++]& 0xff;
|
||||
long i0 = ab[aboffset++]& 0xff;
|
||||
return (i7 << 56) + (i6 << 48) + (i5 << 40) + (i4 << 32) + (i3 << 24) + (i2 << 16) + (i1 << 8) + i0;
|
||||
public final long readLong() {
|
||||
long i7 = ab[aboffset++] & 0xff;
|
||||
long i6 = ab[aboffset++] & 0xff;
|
||||
long i5 = ab[aboffset++] & 0xff;
|
||||
long i4 = ab[aboffset++] & 0xff;
|
||||
long i3 = ab[aboffset++] & 0xff;
|
||||
long i2 = ab[aboffset++] & 0xff;
|
||||
long i1 = ab[aboffset++] & 0xff;
|
||||
long i0 = ab[aboffset++] & 0xff;
|
||||
return (i7 << 56) + (i6 << 48) + (i5 << 40) + (i4 << 32) + (i3 << 24) + (i2 << 16) + (i1 << 8) + i0;
|
||||
}
|
||||
|
||||
public final boolean readBoolean()
|
||||
{
|
||||
int i0 = ab[aboffset++]& 0xff;
|
||||
return i0 != 0;
|
||||
public final boolean readBoolean() {
|
||||
int i0 = ab[aboffset++] & 0xff;
|
||||
return i0 != 0;
|
||||
}
|
||||
|
||||
public final byte readByte()
|
||||
{
|
||||
int i0 = ab[aboffset++] & 0xff;
|
||||
return (byte)(i0);
|
||||
public final byte readByte() {
|
||||
int i0 = ab[aboffset++] & 0xff;
|
||||
return (byte) (i0);
|
||||
}
|
||||
|
||||
public final short readShort()
|
||||
{
|
||||
int i1 = ab[aboffset++] & 0xff;
|
||||
int i0 = ab[aboffset++] & 0xff;
|
||||
return (short)( (i1 << 8) | i0);
|
||||
public final short readShort() {
|
||||
int i1 = ab[aboffset++] & 0xff;
|
||||
int i0 = ab[aboffset++] & 0xff;
|
||||
return (short) ((i1 << 8) | i0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -79,75 +70,66 @@ public class ByteDataReader
|
|||
*
|
||||
* @return the pointer to the first byte after that section
|
||||
*/
|
||||
public final int getEndPointer()
|
||||
{
|
||||
public final int getEndPointer() {
|
||||
int size = readVarLengthUnsigned();
|
||||
return aboffset + size;
|
||||
}
|
||||
|
||||
public final byte[] readDataUntil( int endPointer )
|
||||
{
|
||||
public final byte[] readDataUntil(int endPointer) {
|
||||
int size = endPointer - aboffset;
|
||||
if ( size == 0 )
|
||||
{
|
||||
if (size == 0) {
|
||||
return null;
|
||||
}
|
||||
byte[] data = new byte[size];
|
||||
readFully( data );
|
||||
readFully(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
public final byte[] readVarBytes()
|
||||
{
|
||||
public final byte[] readVarBytes() {
|
||||
int len = readVarLengthUnsigned();
|
||||
if ( len == 0 )
|
||||
{
|
||||
if (len == 0) {
|
||||
return null;
|
||||
}
|
||||
byte[] bytes = new byte[len];
|
||||
readFully( bytes );
|
||||
readFully(bytes);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public final int readVarLengthSigned()
|
||||
{
|
||||
int v = readVarLengthUnsigned();
|
||||
return ( v & 1 ) == 0 ? v >> 1 : -(v >> 1 );
|
||||
public final int readVarLengthSigned() {
|
||||
int v = readVarLengthUnsigned();
|
||||
return (v & 1) == 0 ? v >> 1 : -(v >> 1);
|
||||
}
|
||||
|
||||
public final int readVarLengthUnsigned()
|
||||
{
|
||||
public final int readVarLengthUnsigned() {
|
||||
byte b;
|
||||
int v = (b=ab[aboffset++]) & 0x7f;
|
||||
if ( b >= 0 ) return v;
|
||||
v |= ( (b=ab[aboffset++]) & 0x7f ) << 7;
|
||||
if ( b >= 0 ) return v;
|
||||
v |= ( (b=ab[aboffset++]) & 0x7f ) << 14;
|
||||
if ( b >= 0 ) return v;
|
||||
v |= ( (b=ab[aboffset++]) & 0x7f ) << 21;
|
||||
if ( b >= 0 ) return v;
|
||||
v |= ( (b=ab[aboffset++]) & 0xf ) << 28;
|
||||
int v = (b = ab[aboffset++]) & 0x7f;
|
||||
if (b >= 0) return v;
|
||||
v |= ((b = ab[aboffset++]) & 0x7f) << 7;
|
||||
if (b >= 0) return v;
|
||||
v |= ((b = ab[aboffset++]) & 0x7f) << 14;
|
||||
if (b >= 0) return v;
|
||||
v |= ((b = ab[aboffset++]) & 0x7f) << 21;
|
||||
if (b >= 0) return v;
|
||||
v |= ((b = ab[aboffset++]) & 0xf) << 28;
|
||||
return v;
|
||||
}
|
||||
|
||||
public final void readFully( byte[] ta )
|
||||
{
|
||||
System.arraycopy( ab, aboffset, ta, 0, ta.length );
|
||||
aboffset += ta.length;
|
||||
public final void readFully(byte[] ta) {
|
||||
System.arraycopy(ab, aboffset, ta, 0, ta.length);
|
||||
aboffset += ta.length;
|
||||
}
|
||||
|
||||
public final boolean hasMoreData()
|
||||
{
|
||||
public final boolean hasMoreData() {
|
||||
return aboffset < aboffsetEnd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder( "[" );
|
||||
for( int i=0; i<ab.length; i++ ) sb.append( i == 0 ? " " : ", " ).append( Integer.toString( ab[i] ) );
|
||||
sb.append( " ]" );
|
||||
return sb.toString();
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("[");
|
||||
for (int i = 0; i < ab.length; i++)
|
||||
sb.append(i == 0 ? " " : ", ").append(Integer.toString(ab[i]));
|
||||
sb.append(" ]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,91 +6,75 @@
|
|||
package btools.util;
|
||||
|
||||
|
||||
public class ByteDataWriter extends ByteDataReader
|
||||
{
|
||||
public ByteDataWriter( byte[] byteArray )
|
||||
{
|
||||
super ( byteArray );
|
||||
public class ByteDataWriter extends ByteDataReader {
|
||||
public ByteDataWriter(byte[] byteArray) {
|
||||
super(byteArray);
|
||||
}
|
||||
|
||||
public final void writeInt( int v )
|
||||
{
|
||||
ab[aboffset++] = (byte)( (v >> 24) & 0xff );
|
||||
ab[aboffset++] = (byte)( (v >> 16) & 0xff );
|
||||
ab[aboffset++] = (byte)( (v >> 8) & 0xff );
|
||||
ab[aboffset++] = (byte)( (v ) & 0xff );
|
||||
public final void writeInt(int v) {
|
||||
ab[aboffset++] = (byte) ((v >> 24) & 0xff);
|
||||
ab[aboffset++] = (byte) ((v >> 16) & 0xff);
|
||||
ab[aboffset++] = (byte) ((v >> 8) & 0xff);
|
||||
ab[aboffset++] = (byte) ((v) & 0xff);
|
||||
}
|
||||
|
||||
public final void writeLong( long v )
|
||||
{
|
||||
ab[aboffset++] = (byte)( (v >> 56) & 0xff );
|
||||
ab[aboffset++] = (byte)( (v >> 48) & 0xff );
|
||||
ab[aboffset++] = (byte)( (v >> 40) & 0xff );
|
||||
ab[aboffset++] = (byte)( (v >> 32) & 0xff );
|
||||
ab[aboffset++] = (byte)( (v >> 24) & 0xff );
|
||||
ab[aboffset++] = (byte)( (v >> 16) & 0xff );
|
||||
ab[aboffset++] = (byte)( (v >> 8) & 0xff );
|
||||
ab[aboffset++] = (byte)( (v ) & 0xff );
|
||||
public final void writeLong(long v) {
|
||||
ab[aboffset++] = (byte) ((v >> 56) & 0xff);
|
||||
ab[aboffset++] = (byte) ((v >> 48) & 0xff);
|
||||
ab[aboffset++] = (byte) ((v >> 40) & 0xff);
|
||||
ab[aboffset++] = (byte) ((v >> 32) & 0xff);
|
||||
ab[aboffset++] = (byte) ((v >> 24) & 0xff);
|
||||
ab[aboffset++] = (byte) ((v >> 16) & 0xff);
|
||||
ab[aboffset++] = (byte) ((v >> 8) & 0xff);
|
||||
ab[aboffset++] = (byte) ((v) & 0xff);
|
||||
}
|
||||
|
||||
public final void writeBoolean( boolean v)
|
||||
{
|
||||
ab[aboffset++] = (byte)( v ? 1 : 0 );
|
||||
public final void writeBoolean(boolean v) {
|
||||
ab[aboffset++] = (byte) (v ? 1 : 0);
|
||||
}
|
||||
|
||||
public final void writeByte( int v )
|
||||
{
|
||||
ab[aboffset++] = (byte)( (v ) & 0xff );
|
||||
public final void writeByte(int v) {
|
||||
ab[aboffset++] = (byte) ((v) & 0xff);
|
||||
}
|
||||
|
||||
public final void writeShort( int v )
|
||||
{
|
||||
ab[aboffset++] = (byte)( (v >> 8) & 0xff );
|
||||
ab[aboffset++] = (byte)( (v ) & 0xff );
|
||||
public final void writeShort(int v) {
|
||||
ab[aboffset++] = (byte) ((v >> 8) & 0xff);
|
||||
ab[aboffset++] = (byte) ((v) & 0xff);
|
||||
}
|
||||
|
||||
public final void write( byte[] sa )
|
||||
{
|
||||
System.arraycopy( sa, 0, ab, aboffset, sa.length );
|
||||
public final void write(byte[] sa) {
|
||||
System.arraycopy(sa, 0, ab, aboffset, sa.length);
|
||||
aboffset += sa.length;
|
||||
}
|
||||
|
||||
public final void write( byte[] sa, int offset, int len )
|
||||
{
|
||||
System.arraycopy( sa, offset, ab, aboffset, len );
|
||||
public final void write(byte[] sa, int offset, int len) {
|
||||
System.arraycopy(sa, offset, ab, aboffset, len);
|
||||
aboffset += len;
|
||||
}
|
||||
|
||||
public final void writeVarBytes( byte[] sa )
|
||||
{
|
||||
if ( sa == null )
|
||||
{
|
||||
writeVarLengthUnsigned( 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
public final void writeVarBytes(byte[] sa) {
|
||||
if (sa == null) {
|
||||
writeVarLengthUnsigned(0);
|
||||
} else {
|
||||
int len = sa.length;
|
||||
writeVarLengthUnsigned( len );
|
||||
write( sa, 0, len );
|
||||
writeVarLengthUnsigned(len);
|
||||
write(sa, 0, len);
|
||||
}
|
||||
}
|
||||
|
||||
public final void writeModeAndDesc( boolean isReverse, byte[] sa )
|
||||
{
|
||||
public final void writeModeAndDesc(boolean isReverse, byte[] sa) {
|
||||
int len = sa == null ? 0 : sa.length;
|
||||
int sizecode = len << 1 | ( isReverse ? 1 : 0 );
|
||||
writeVarLengthUnsigned( sizecode );
|
||||
if ( len > 0 )
|
||||
{
|
||||
write( sa, 0, len );
|
||||
int sizecode = len << 1 | (isReverse ? 1 : 0);
|
||||
writeVarLengthUnsigned(sizecode);
|
||||
if (len > 0) {
|
||||
write(sa, 0, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public final byte[] toByteArray()
|
||||
{
|
||||
public final byte[] toByteArray() {
|
||||
byte[] c = new byte[aboffset];
|
||||
System.arraycopy( ab, 0, c, 0, aboffset );
|
||||
System.arraycopy(ab, 0, c, 0, aboffset);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
|
@ -102,76 +86,66 @@ public class ByteDataWriter extends ByteDataReader
|
|||
*
|
||||
* @return the offset of the placeholder
|
||||
*/
|
||||
public final int writeSizePlaceHolder()
|
||||
{
|
||||
public final int writeSizePlaceHolder() {
|
||||
return aboffset++;
|
||||
}
|
||||
|
||||
public final void injectSize( int sizeoffset )
|
||||
{
|
||||
public final void injectSize(int sizeoffset) {
|
||||
int size = 0;
|
||||
int datasize = aboffset-sizeoffset-1;
|
||||
int datasize = aboffset - sizeoffset - 1;
|
||||
int v = datasize;
|
||||
do
|
||||
{
|
||||
do {
|
||||
v >>= 7;
|
||||
size++;
|
||||
}
|
||||
while( v != 0 );
|
||||
if ( size > 1 ) // doesn't fit -> shift the data after the placeholder
|
||||
while (v != 0);
|
||||
if (size > 1) // doesn't fit -> shift the data after the placeholder
|
||||
{
|
||||
System.arraycopy( ab, sizeoffset+1, ab, sizeoffset+size, datasize );
|
||||
System.arraycopy(ab, sizeoffset + 1, ab, sizeoffset + size, datasize);
|
||||
}
|
||||
aboffset = sizeoffset;
|
||||
writeVarLengthUnsigned( datasize );
|
||||
writeVarLengthUnsigned(datasize);
|
||||
aboffset = sizeoffset + size + datasize;
|
||||
}
|
||||
|
||||
public final void writeVarLengthSigned( int v )
|
||||
{
|
||||
writeVarLengthUnsigned( v < 0 ? ( (-v) << 1 ) | 1 : v << 1 );
|
||||
public final void writeVarLengthSigned(int v) {
|
||||
writeVarLengthUnsigned(v < 0 ? ((-v) << 1) | 1 : v << 1);
|
||||
}
|
||||
|
||||
public final void writeVarLengthUnsigned( int v )
|
||||
{
|
||||
public final void writeVarLengthUnsigned(int v) {
|
||||
int i7 = v & 0x7f;
|
||||
if ( ( v >>>= 7 ) == 0 )
|
||||
{
|
||||
ab[aboffset++] = (byte) ( i7 );
|
||||
if ((v >>>= 7) == 0) {
|
||||
ab[aboffset++] = (byte) (i7);
|
||||
return;
|
||||
}
|
||||
ab[aboffset++] = (byte) ( i7 | 0x80 );
|
||||
ab[aboffset++] = (byte) (i7 | 0x80);
|
||||
|
||||
i7 = v & 0x7f;
|
||||
if ( ( v >>>= 7 ) == 0 )
|
||||
{
|
||||
ab[aboffset++] = (byte) ( i7 );
|
||||
if ((v >>>= 7) == 0) {
|
||||
ab[aboffset++] = (byte) (i7);
|
||||
return;
|
||||
}
|
||||
ab[aboffset++] = (byte) ( i7 | 0x80 );
|
||||
ab[aboffset++] = (byte) (i7 | 0x80);
|
||||
|
||||
i7 = v & 0x7f;
|
||||
if ( ( v >>>= 7 ) == 0 )
|
||||
{
|
||||
ab[aboffset++] = (byte) ( i7 );
|
||||
if ((v >>>= 7) == 0) {
|
||||
ab[aboffset++] = (byte) (i7);
|
||||
return;
|
||||
}
|
||||
ab[aboffset++] = (byte) ( i7 | 0x80 );
|
||||
ab[aboffset++] = (byte) (i7 | 0x80);
|
||||
|
||||
i7 = v & 0x7f;
|
||||
if ( ( v >>>= 7 ) == 0 )
|
||||
{
|
||||
ab[aboffset++] = (byte) ( i7 );
|
||||
if ((v >>>= 7) == 0) {
|
||||
ab[aboffset++] = (byte) (i7);
|
||||
return;
|
||||
}
|
||||
ab[aboffset++] = (byte) ( i7 | 0x80 );
|
||||
ab[aboffset++] = (byte) (i7 | 0x80);
|
||||
|
||||
ab[aboffset++] = (byte) ( v );
|
||||
ab[aboffset++] = (byte) (v);
|
||||
return;
|
||||
}
|
||||
|
||||
public int size()
|
||||
{
|
||||
public int size() {
|
||||
return aboffset;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,18 +4,15 @@
|
|||
*/
|
||||
package btools.util;
|
||||
|
||||
public final class CheapAngleMeter
|
||||
{
|
||||
public final class CheapAngleMeter {
|
||||
private double cosangle;
|
||||
|
||||
public double getCosAngle()
|
||||
{
|
||||
public double getCosAngle() {
|
||||
return cosangle;
|
||||
}
|
||||
|
||||
public double calcAngle( int lon0, int lat0, int lon1, int lat1, int lon2, int lat2 )
|
||||
{
|
||||
double[] lonlat2m = CheapRuler.getLonLatToMeterScales( lat1 );
|
||||
public double calcAngle(int lon0, int lat0, int lon1, int lat1, int lon2, int lat2) {
|
||||
double[] lonlat2m = CheapRuler.getLonLatToMeterScales(lat1);
|
||||
double lon2m = lonlat2m[0];
|
||||
double lat2m = lonlat2m[1];
|
||||
double dx10 = (lon1 - lon0) * lon2m;
|
||||
|
|
@ -23,33 +20,30 @@ public final class CheapAngleMeter
|
|||
double dx21 = (lon2 - lon1) * lon2m;
|
||||
double dy21 = (lat2 - lat1) * lat2m;
|
||||
|
||||
double dd = Math.sqrt( (dx10*dx10 + dy10*dy10)*(dx21*dx21 + dy21*dy21) );
|
||||
if ( dd == 0. ) { cosangle = 1.; return 0.; }
|
||||
double sinp = (dy10*dx21 - dx10*dy21)/dd;
|
||||
double cosp = (dy10*dy21 + dx10*dx21)/dd;
|
||||
double dd = Math.sqrt((dx10 * dx10 + dy10 * dy10) * (dx21 * dx21 + dy21 * dy21));
|
||||
if (dd == 0.) {
|
||||
cosangle = 1.;
|
||||
return 0.;
|
||||
}
|
||||
double sinp = (dy10 * dx21 - dx10 * dy21) / dd;
|
||||
double cosp = (dy10 * dy21 + dx10 * dx21) / dd;
|
||||
cosangle = cosp;
|
||||
|
||||
double offset = 0.;
|
||||
double s2 = sinp*sinp;
|
||||
if ( s2 > 0.5 )
|
||||
{
|
||||
if ( sinp > 0. )
|
||||
{
|
||||
double s2 = sinp * sinp;
|
||||
if (s2 > 0.5) {
|
||||
if (sinp > 0.) {
|
||||
offset = 90.;
|
||||
sinp = -cosp;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
offset = -90.;
|
||||
sinp = cosp;
|
||||
}
|
||||
s2 = cosp*cosp;
|
||||
}
|
||||
else if ( cosp < 0. )
|
||||
{
|
||||
s2 = cosp * cosp;
|
||||
} else if (cosp < 0.) {
|
||||
sinp = -sinp;
|
||||
offset = sinp > 0. ? -180. : 180.;
|
||||
}
|
||||
return offset + sinp * ( 57.4539 + s2 * ( 9.57565 + s2 * ( 4.30904 + s2 * 2.56491 ) ) );
|
||||
return offset + sinp * (57.4539 + s2 * (9.57565 + s2 * (4.30904 + s2 * 2.56491)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ public final class CheapRuler {
|
|||
* See
|
||||
* https://blog.mapbox.com/fast-geodesic-approximations-with-cheap-ruler-106f229ad016
|
||||
* for more details.
|
||||
*
|
||||
* <p>
|
||||
* Original code is at https://github.com/mapbox/cheap-ruler under ISC license.
|
||||
*
|
||||
* <p>
|
||||
* This is implemented as a Singleton to have a unique cache for the cosine
|
||||
* values across all the code.
|
||||
*/
|
||||
|
|
@ -28,12 +28,12 @@ public final class CheapRuler {
|
|||
*/
|
||||
static {
|
||||
for (int i = 0; i < SCALE_CACHE_LENGTH; i++) {
|
||||
SCALE_CACHE[i] = calcKxKyFromILat( i*SCALE_CACHE_INCREMENT + SCALE_CACHE_INCREMENT/2 );
|
||||
SCALE_CACHE[i] = calcKxKyFromILat(i * SCALE_CACHE_INCREMENT + SCALE_CACHE_INCREMENT / 2);
|
||||
}
|
||||
}
|
||||
|
||||
private static double[] calcKxKyFromILat(int ilat) {
|
||||
double lat = DEG_TO_RAD*(ilat*ILATLNG_TO_LATLNG - 90);
|
||||
double lat = DEG_TO_RAD * (ilat * ILATLNG_TO_LATLNG - 90);
|
||||
double cos = Math.cos(lat);
|
||||
double cos2 = 2 * cos * cos - 1;
|
||||
double cos3 = 2 * cos * cos2 - cos;
|
||||
|
|
@ -53,26 +53,26 @@ public final class CheapRuler {
|
|||
*
|
||||
* @return [lon->meter,lat->meter]
|
||||
*/
|
||||
public static double[] getLonLatToMeterScales( int ilat ) {
|
||||
return SCALE_CACHE[ ilat / SCALE_CACHE_INCREMENT ];
|
||||
public static double[] getLonLatToMeterScales(int ilat) {
|
||||
return SCALE_CACHE[ilat / SCALE_CACHE_INCREMENT];
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the distance (in meters) between two points represented by their
|
||||
* (integer) latitude and longitude.
|
||||
*
|
||||
* @param ilon1 Integer longitude for the start point. this is (longitude in degrees + 180) * 1e6.
|
||||
* @param ilat1 Integer latitude for the start point, this is (latitude + 90) * 1e6.
|
||||
* @param ilon2 Integer longitude for the end point, this is (longitude + 180) * 1e6.
|
||||
* @param ilat2 Integer latitude for the end point, this is (latitude + 90) * 1e6.
|
||||
* @return The distance between the two points, in meters.
|
||||
*
|
||||
* @param ilon1 Integer longitude for the start point. this is (longitude in degrees + 180) * 1e6.
|
||||
* @param ilat1 Integer latitude for the start point, this is (latitude + 90) * 1e6.
|
||||
* @param ilon2 Integer longitude for the end point, this is (longitude + 180) * 1e6.
|
||||
* @param ilat2 Integer latitude for the end point, this is (latitude + 90) * 1e6.
|
||||
* @return The distance between the two points, in meters.
|
||||
* <p>
|
||||
* Note:
|
||||
* Integer longitude is ((longitude in degrees) + 180) * 1e6.
|
||||
* Integer latitude is ((latitude in degrees) + 90) * 1e6.
|
||||
*/
|
||||
public static double distance(int ilon1, int ilat1, int ilon2, int ilat2) {
|
||||
double[] kxky = getLonLatToMeterScales( ( ilat1 + ilat2 ) >> 1 );
|
||||
double[] kxky = getLonLatToMeterScales((ilat1 + ilat2) >> 1);
|
||||
double dlon = (ilon1 - ilon2) * kxky[0];
|
||||
double dlat = (ilat1 - ilat2) * kxky[1];
|
||||
return Math.sqrt(dlat * dlat + dlon * dlon); // in m
|
||||
|
|
|
|||
|
|
@ -1,328 +1,285 @@
|
|||
package btools.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Memory efficient Map to map a long-key to an object-value
|
||||
*
|
||||
* Implementation is such that basically the 12 bytes
|
||||
* per entry is allocated that's needed to store
|
||||
* a long- and an object-value.
|
||||
* This class does not implement the Map interface
|
||||
* because it's not complete (remove() is not implemented,
|
||||
* CompactLongMap can only grow.)
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
public class CompactLongMap<V>
|
||||
{
|
||||
private long[][] al;
|
||||
private int[] pa;
|
||||
private int size = 0;
|
||||
private int _maxKeepExponent = 14; // the maximum exponent to keep the invalid arrays
|
||||
|
||||
protected V value_in;
|
||||
protected V value_out;
|
||||
|
||||
protected static final int MAXLISTS = 31; // enough for size Integer.MAX_VALUE
|
||||
private static boolean earlyDuplicateCheck;
|
||||
|
||||
public CompactLongMap()
|
||||
{
|
||||
// pointer array
|
||||
pa = new int[MAXLISTS];
|
||||
|
||||
// allocate key lists
|
||||
al = new long[MAXLISTS][];
|
||||
al[0] = new long[1]; // make the first array (the transient buffer)
|
||||
|
||||
// same for the values
|
||||
vla = new Object[MAXLISTS][];
|
||||
vla[0] = new Object[1];
|
||||
|
||||
earlyDuplicateCheck = Boolean.getBoolean( "earlyDuplicateCheck" );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* The Map extension:
|
||||
* next 5 protected methods are needed to implement value-support
|
||||
* overwrite them all to support value structures other than the
|
||||
* long-values implemented here as a sample.
|
||||
*
|
||||
* Furthermore, put() and get() method need to be implemented
|
||||
* to access the values.
|
||||
*
|
||||
* Note that this map does not behave exactly like java.util.Map
|
||||
* - put(..) with already existing key throws exception
|
||||
* - get(..) with non-existing key thros exception
|
||||
*
|
||||
* If you have keys that cannot easily be mapped on long's, use
|
||||
* a hash-function to do the mapping. But note that, in comparison
|
||||
* to java.util.HashMap, in that case the keys itself are not saved,
|
||||
* only the hash-values, so you need to be sure that random duplicate
|
||||
* hashs are either excluded by the structure of your data or that
|
||||
* you can handle the possible IllegalArgumentException
|
||||
*
|
||||
*/
|
||||
|
||||
private Object[][] vla; // value list array
|
||||
|
||||
|
||||
public boolean put( long id, V value )
|
||||
{
|
||||
try
|
||||
{
|
||||
value_in = value;
|
||||
if ( contains( id, true ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
vla[0][0] = value;
|
||||
_add( id );
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
value_in = null;
|
||||
value_out = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as put( id, value ) but duplicate check
|
||||
* is skipped for performance. Be aware that you
|
||||
* can get a duplicate exception later on if the
|
||||
* map is restructured!
|
||||
* with System parameter earlyDuplicateCheck=true you
|
||||
* can enforce the early duplicate check for debugging
|
||||
*
|
||||
* @param id the key to insert
|
||||
* @param value the value to insert object
|
||||
* @exception IllegalArgumentException for duplicates if enabled
|
||||
*/
|
||||
public void fastPut( long id, V value )
|
||||
{
|
||||
if ( earlyDuplicateCheck && contains( id ) )
|
||||
{
|
||||
throw new IllegalArgumentException( "duplicate key found in early check: " + id );
|
||||
}
|
||||
vla[0][0] = value;
|
||||
_add( id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value for the given id
|
||||
* @param id the key to query
|
||||
* @return the object, or null if id not known
|
||||
*/
|
||||
public V get( long id )
|
||||
{
|
||||
try
|
||||
{
|
||||
if ( contains( id, false ) )
|
||||
{
|
||||
return value_out;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
value_out = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the number of entries in this map
|
||||
*/
|
||||
public int size()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
private boolean _add( long id )
|
||||
{
|
||||
if ( size == Integer.MAX_VALUE )
|
||||
{
|
||||
throw new IllegalArgumentException( "cannot grow beyond size Integer.MAX_VALUE" );
|
||||
}
|
||||
|
||||
// put the new entry in the first array
|
||||
al[0][0] = id;
|
||||
|
||||
// determine the first empty array
|
||||
int bp = size++; // treat size as bitpattern
|
||||
int idx = 1;
|
||||
int n = 1;
|
||||
|
||||
pa[0] = 1;
|
||||
pa[1] = 1;
|
||||
|
||||
while ( (bp&1) == 1 )
|
||||
{
|
||||
bp >>= 1;
|
||||
pa[idx++] = n;
|
||||
n <<= 1;
|
||||
}
|
||||
|
||||
// create it if not existant
|
||||
if ( al[idx] == null )
|
||||
{
|
||||
al[idx] = new long[n];
|
||||
vla[idx] = new Object[n];
|
||||
}
|
||||
|
||||
// now merge the contents of arrays 0...idx-1 into idx
|
||||
while ( n > 0 )
|
||||
{
|
||||
long maxId = 0;
|
||||
int maxIdx = -1;
|
||||
|
||||
for ( int i=0; i<idx; i++ )
|
||||
{
|
||||
int p = pa[i];
|
||||
if ( p > 0 )
|
||||
{
|
||||
long currentId = al[i][p-1];
|
||||
if ( maxIdx < 0 || currentId > maxId )
|
||||
{
|
||||
maxIdx = i;
|
||||
maxId = currentId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// current maximum found, copy to target array
|
||||
if ( n < al[idx].length && maxId == al[idx][n] )
|
||||
{
|
||||
throw new IllegalArgumentException( "duplicate key found in late check: " + maxId );
|
||||
}
|
||||
--n;
|
||||
al[idx][n] = maxId;
|
||||
vla[idx][n] = vla[maxIdx][pa[maxIdx]-1];
|
||||
|
||||
--pa[maxIdx];
|
||||
}
|
||||
|
||||
// de-allocate empty arrays of a certain size (fix at 64kByte)
|
||||
while ( idx-- > _maxKeepExponent )
|
||||
{
|
||||
al[idx] = null;
|
||||
vla[idx] = null;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if "id" is contained in this set.
|
||||
*/
|
||||
public boolean contains( long id )
|
||||
{
|
||||
try
|
||||
{
|
||||
return contains( id, false );
|
||||
}
|
||||
finally
|
||||
{
|
||||
value_out = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean contains( long id, boolean doPut )
|
||||
{
|
||||
// determine the first empty array
|
||||
int bp = size; // treat size as bitpattern
|
||||
int idx = 1;
|
||||
|
||||
while ( bp != 0 )
|
||||
{
|
||||
if ( (bp&1) == 1 )
|
||||
{
|
||||
// array at idx is valid, check
|
||||
if ( contains( idx, id, doPut ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
bp >>= 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// does sorted array "a" contain "id" ?
|
||||
private boolean contains( int idx, long id, boolean doPut )
|
||||
{
|
||||
long[] a = al[idx];
|
||||
int offset = a.length;
|
||||
int n = 0;
|
||||
|
||||
while ( (offset >>= 1) > 0 )
|
||||
{
|
||||
int nn = n + offset;
|
||||
if ( a[nn] <= id )
|
||||
{
|
||||
n = nn;
|
||||
}
|
||||
}
|
||||
if ( a[n] == id )
|
||||
{
|
||||
value_out = (V)vla[idx][n];
|
||||
if ( doPut ) vla[idx][n] = value_in;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void moveToFrozenArrays( long[] faid, ArrayList<V> flv )
|
||||
{
|
||||
for( int i=1; i<MAXLISTS; i++ )
|
||||
{
|
||||
pa[i] = 0;
|
||||
}
|
||||
|
||||
for( int ti = 0; ti < size; ti++ ) // target-index
|
||||
{
|
||||
int bp = size; // treat size as bitpattern
|
||||
int minIdx = -1;
|
||||
long minId = 0;
|
||||
int idx = 1;
|
||||
while ( bp != 0 )
|
||||
{
|
||||
if ( (bp&1) == 1 )
|
||||
{
|
||||
int p = pa[idx];
|
||||
if ( p < al[idx].length )
|
||||
{
|
||||
long currentId = al[idx][p];
|
||||
if ( minIdx < 0 || currentId < minId )
|
||||
{
|
||||
minIdx = idx;
|
||||
minId = currentId;
|
||||
}
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
bp >>= 1;
|
||||
}
|
||||
faid[ti] = minId;
|
||||
flv.add( (V)vla[minIdx][pa[minIdx]] );
|
||||
pa[minIdx]++;
|
||||
|
||||
if ( ti > 0 && faid[ti-1] == minId )
|
||||
{
|
||||
throw new IllegalArgumentException( "duplicate key found in late check: " + minId );
|
||||
}
|
||||
}
|
||||
|
||||
// free the non-frozen arrays
|
||||
al = null;
|
||||
vla = null;
|
||||
}
|
||||
|
||||
}
|
||||
package btools.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Memory efficient Map to map a long-key to an object-value
|
||||
* <p>
|
||||
* Implementation is such that basically the 12 bytes
|
||||
* per entry is allocated that's needed to store
|
||||
* a long- and an object-value.
|
||||
* This class does not implement the Map interface
|
||||
* because it's not complete (remove() is not implemented,
|
||||
* CompactLongMap can only grow.)
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
public class CompactLongMap<V> {
|
||||
private long[][] al;
|
||||
private int[] pa;
|
||||
private int size = 0;
|
||||
private int _maxKeepExponent = 14; // the maximum exponent to keep the invalid arrays
|
||||
|
||||
protected V value_in;
|
||||
protected V value_out;
|
||||
|
||||
protected static final int MAXLISTS = 31; // enough for size Integer.MAX_VALUE
|
||||
private static boolean earlyDuplicateCheck;
|
||||
|
||||
public CompactLongMap() {
|
||||
// pointer array
|
||||
pa = new int[MAXLISTS];
|
||||
|
||||
// allocate key lists
|
||||
al = new long[MAXLISTS][];
|
||||
al[0] = new long[1]; // make the first array (the transient buffer)
|
||||
|
||||
// same for the values
|
||||
vla = new Object[MAXLISTS][];
|
||||
vla[0] = new Object[1];
|
||||
|
||||
earlyDuplicateCheck = Boolean.getBoolean("earlyDuplicateCheck");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* The Map extension:
|
||||
* next 5 protected methods are needed to implement value-support
|
||||
* overwrite them all to support value structures other than the
|
||||
* long-values implemented here as a sample.
|
||||
*
|
||||
* Furthermore, put() and get() method need to be implemented
|
||||
* to access the values.
|
||||
*
|
||||
* Note that this map does not behave exactly like java.util.Map
|
||||
* - put(..) with already existing key throws exception
|
||||
* - get(..) with non-existing key thros exception
|
||||
*
|
||||
* If you have keys that cannot easily be mapped on long's, use
|
||||
* a hash-function to do the mapping. But note that, in comparison
|
||||
* to java.util.HashMap, in that case the keys itself are not saved,
|
||||
* only the hash-values, so you need to be sure that random duplicate
|
||||
* hashs are either excluded by the structure of your data or that
|
||||
* you can handle the possible IllegalArgumentException
|
||||
*
|
||||
*/
|
||||
|
||||
private Object[][] vla; // value list array
|
||||
|
||||
|
||||
public boolean put(long id, V value) {
|
||||
try {
|
||||
value_in = value;
|
||||
if (contains(id, true)) {
|
||||
return true;
|
||||
}
|
||||
vla[0][0] = value;
|
||||
_add(id);
|
||||
return false;
|
||||
} finally {
|
||||
value_in = null;
|
||||
value_out = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as put( id, value ) but duplicate check
|
||||
* is skipped for performance. Be aware that you
|
||||
* can get a duplicate exception later on if the
|
||||
* map is restructured!
|
||||
* with System parameter earlyDuplicateCheck=true you
|
||||
* can enforce the early duplicate check for debugging
|
||||
*
|
||||
* @param id the key to insert
|
||||
* @param value the value to insert object
|
||||
* @throws IllegalArgumentException for duplicates if enabled
|
||||
*/
|
||||
public void fastPut(long id, V value) {
|
||||
if (earlyDuplicateCheck && contains(id)) {
|
||||
throw new IllegalArgumentException("duplicate key found in early check: " + id);
|
||||
}
|
||||
vla[0][0] = value;
|
||||
_add(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value for the given id
|
||||
*
|
||||
* @param id the key to query
|
||||
* @return the object, or null if id not known
|
||||
*/
|
||||
public V get(long id) {
|
||||
try {
|
||||
if (contains(id, false)) {
|
||||
return value_out;
|
||||
}
|
||||
return null;
|
||||
} finally {
|
||||
value_out = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the number of entries in this map
|
||||
*/
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
private boolean _add(long id) {
|
||||
if (size == Integer.MAX_VALUE) {
|
||||
throw new IllegalArgumentException("cannot grow beyond size Integer.MAX_VALUE");
|
||||
}
|
||||
|
||||
// put the new entry in the first array
|
||||
al[0][0] = id;
|
||||
|
||||
// determine the first empty array
|
||||
int bp = size++; // treat size as bitpattern
|
||||
int idx = 1;
|
||||
int n = 1;
|
||||
|
||||
pa[0] = 1;
|
||||
pa[1] = 1;
|
||||
|
||||
while ((bp & 1) == 1) {
|
||||
bp >>= 1;
|
||||
pa[idx++] = n;
|
||||
n <<= 1;
|
||||
}
|
||||
|
||||
// create it if not existant
|
||||
if (al[idx] == null) {
|
||||
al[idx] = new long[n];
|
||||
vla[idx] = new Object[n];
|
||||
}
|
||||
|
||||
// now merge the contents of arrays 0...idx-1 into idx
|
||||
while (n > 0) {
|
||||
long maxId = 0;
|
||||
int maxIdx = -1;
|
||||
|
||||
for (int i = 0; i < idx; i++) {
|
||||
int p = pa[i];
|
||||
if (p > 0) {
|
||||
long currentId = al[i][p - 1];
|
||||
if (maxIdx < 0 || currentId > maxId) {
|
||||
maxIdx = i;
|
||||
maxId = currentId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// current maximum found, copy to target array
|
||||
if (n < al[idx].length && maxId == al[idx][n]) {
|
||||
throw new IllegalArgumentException("duplicate key found in late check: " + maxId);
|
||||
}
|
||||
--n;
|
||||
al[idx][n] = maxId;
|
||||
vla[idx][n] = vla[maxIdx][pa[maxIdx] - 1];
|
||||
|
||||
--pa[maxIdx];
|
||||
}
|
||||
|
||||
// de-allocate empty arrays of a certain size (fix at 64kByte)
|
||||
while (idx-- > _maxKeepExponent) {
|
||||
al[idx] = null;
|
||||
vla[idx] = null;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if "id" is contained in this set.
|
||||
*/
|
||||
public boolean contains(long id) {
|
||||
try {
|
||||
return contains(id, false);
|
||||
} finally {
|
||||
value_out = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean contains(long id, boolean doPut) {
|
||||
// determine the first empty array
|
||||
int bp = size; // treat size as bitpattern
|
||||
int idx = 1;
|
||||
|
||||
while (bp != 0) {
|
||||
if ((bp & 1) == 1) {
|
||||
// array at idx is valid, check
|
||||
if (contains(idx, id, doPut)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
bp >>= 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// does sorted array "a" contain "id" ?
|
||||
private boolean contains(int idx, long id, boolean doPut) {
|
||||
long[] a = al[idx];
|
||||
int offset = a.length;
|
||||
int n = 0;
|
||||
|
||||
while ((offset >>= 1) > 0) {
|
||||
int nn = n + offset;
|
||||
if (a[nn] <= id) {
|
||||
n = nn;
|
||||
}
|
||||
}
|
||||
if (a[n] == id) {
|
||||
value_out = (V) vla[idx][n];
|
||||
if (doPut) vla[idx][n] = value_in;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void moveToFrozenArrays(long[] faid, ArrayList<V> flv) {
|
||||
for (int i = 1; i < MAXLISTS; i++) {
|
||||
pa[i] = 0;
|
||||
}
|
||||
|
||||
for (int ti = 0; ti < size; ti++) // target-index
|
||||
{
|
||||
int bp = size; // treat size as bitpattern
|
||||
int minIdx = -1;
|
||||
long minId = 0;
|
||||
int idx = 1;
|
||||
while (bp != 0) {
|
||||
if ((bp & 1) == 1) {
|
||||
int p = pa[idx];
|
||||
if (p < al[idx].length) {
|
||||
long currentId = al[idx][p];
|
||||
if (minIdx < 0 || currentId < minId) {
|
||||
minIdx = idx;
|
||||
minId = currentId;
|
||||
}
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
bp >>= 1;
|
||||
}
|
||||
faid[ti] = minId;
|
||||
flv.add((V) vla[minIdx][pa[minIdx]]);
|
||||
pa[minIdx]++;
|
||||
|
||||
if (ti > 0 && faid[ti - 1] == minId) {
|
||||
throw new IllegalArgumentException("duplicate key found in late check: " + minId);
|
||||
}
|
||||
}
|
||||
|
||||
// free the non-frozen arrays
|
||||
al = null;
|
||||
vla = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,217 +1,187 @@
|
|||
package btools.util;
|
||||
|
||||
/**
|
||||
* Memory efficient Set for long-keys
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
public class CompactLongSet
|
||||
{
|
||||
private long[][] al;
|
||||
private int[] pa;
|
||||
private int size = 0;
|
||||
private int _maxKeepExponent = 14; // the maximum exponent to keep the invalid arrays
|
||||
|
||||
protected static final int MAXLISTS = 31; // enough for size Integer.MAX_VALUE
|
||||
|
||||
public CompactLongSet()
|
||||
{
|
||||
// pointer array
|
||||
pa = new int[MAXLISTS];
|
||||
|
||||
// allocate key lists
|
||||
al = new long[MAXLISTS][];
|
||||
al[0] = new long[1]; // make the first array (the transient buffer)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the number of entries in this set
|
||||
*/
|
||||
public int size()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* add a long value to this set if not yet in.
|
||||
* @param id the value to add to this set.
|
||||
* @return true if "id" already contained in this set.
|
||||
*/
|
||||
public boolean add( long id )
|
||||
{
|
||||
if ( contains( id ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
_add( id );
|
||||
return false;
|
||||
}
|
||||
|
||||
public void fastAdd( long id )
|
||||
{
|
||||
_add( id );
|
||||
}
|
||||
|
||||
private void _add( long id )
|
||||
{
|
||||
if ( size == Integer.MAX_VALUE )
|
||||
{
|
||||
throw new IllegalArgumentException( "cannot grow beyond size Integer.MAX_VALUE" );
|
||||
}
|
||||
|
||||
// put the new entry in the first array
|
||||
al[0][0] = id;
|
||||
|
||||
// determine the first empty array
|
||||
int bp = size++; // treat size as bitpattern
|
||||
int idx = 1;
|
||||
int n = 1;
|
||||
|
||||
pa[0] = 1;
|
||||
pa[1] = 1;
|
||||
|
||||
while ( (bp&1) == 1 )
|
||||
{
|
||||
bp >>= 1;
|
||||
pa[idx++] = n;
|
||||
n <<= 1;
|
||||
}
|
||||
|
||||
// create it if not existant
|
||||
if ( al[idx] == null )
|
||||
{
|
||||
al[idx] = new long[n];
|
||||
}
|
||||
|
||||
// now merge the contents of arrays 0...idx-1 into idx
|
||||
while ( n > 0 )
|
||||
{
|
||||
long maxId = 0;
|
||||
int maxIdx = -1;
|
||||
|
||||
for ( int i=0; i<idx; i++ )
|
||||
{
|
||||
int p = pa[i];
|
||||
if ( p > 0 )
|
||||
{
|
||||
long currentId = al[i][p-1];
|
||||
if ( maxIdx < 0 || currentId > maxId )
|
||||
{
|
||||
maxIdx = i;
|
||||
maxId = currentId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// current maximum found, copy to target array
|
||||
if ( n < al[idx].length && maxId == al[idx][n] )
|
||||
{
|
||||
throw new IllegalArgumentException( "duplicate key found in late check: " + maxId );
|
||||
}
|
||||
--n;
|
||||
al[idx][n] = maxId;
|
||||
|
||||
--pa[maxIdx];
|
||||
}
|
||||
|
||||
// de-allocate empty arrays of a certain size (fix at 64kByte)
|
||||
while ( idx-- > _maxKeepExponent )
|
||||
{
|
||||
al[idx] = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if "id" is contained in this set.
|
||||
*/
|
||||
public boolean contains( long id )
|
||||
{
|
||||
// determine the first empty array
|
||||
int bp = size; // treat size as bitpattern
|
||||
int idx = 1;
|
||||
|
||||
while ( bp != 0 )
|
||||
{
|
||||
if ( (bp&1) == 1 )
|
||||
{
|
||||
// array at idx is valid, check
|
||||
if ( contains( idx, id ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
bp >>= 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// does sorted array "a" contain "id" ?
|
||||
private boolean contains( int idx, long id )
|
||||
{
|
||||
long[] a = al[idx];
|
||||
int offset = a.length;
|
||||
int n = 0;
|
||||
|
||||
while ( (offset >>= 1) > 0 )
|
||||
{
|
||||
int nn = n + offset;
|
||||
if ( a[nn] <= id )
|
||||
{
|
||||
n = nn;
|
||||
}
|
||||
}
|
||||
if ( a[n] == id )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void moveToFrozenArray( long[] faid )
|
||||
{
|
||||
for( int i=1; i<MAXLISTS; i++ )
|
||||
{
|
||||
pa[i] = 0;
|
||||
}
|
||||
|
||||
for( int ti = 0; ti < size; ti++ ) // target-index
|
||||
{
|
||||
int bp = size; // treat size as bitpattern
|
||||
int minIdx = -1;
|
||||
long minId = 0;
|
||||
int idx = 1;
|
||||
while ( bp != 0 )
|
||||
{
|
||||
if ( (bp&1) == 1 )
|
||||
{
|
||||
int p = pa[idx];
|
||||
if ( p < al[idx].length )
|
||||
{
|
||||
long currentId = al[idx][p];
|
||||
if ( minIdx < 0 || currentId < minId )
|
||||
{
|
||||
minIdx = idx;
|
||||
minId = currentId;
|
||||
}
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
bp >>= 1;
|
||||
}
|
||||
faid[ti] = minId;
|
||||
pa[minIdx]++;
|
||||
|
||||
if ( ti > 0 && faid[ti-1] == minId )
|
||||
{
|
||||
throw new IllegalArgumentException( "duplicate key found in late check: " + minId );
|
||||
}
|
||||
}
|
||||
|
||||
// free the non-frozen array
|
||||
al = null;
|
||||
}
|
||||
|
||||
}
|
||||
package btools.util;
|
||||
|
||||
/**
|
||||
* Memory efficient Set for long-keys
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
public class CompactLongSet {
|
||||
private long[][] al;
|
||||
private int[] pa;
|
||||
private int size = 0;
|
||||
private int _maxKeepExponent = 14; // the maximum exponent to keep the invalid arrays
|
||||
|
||||
protected static final int MAXLISTS = 31; // enough for size Integer.MAX_VALUE
|
||||
|
||||
public CompactLongSet() {
|
||||
// pointer array
|
||||
pa = new int[MAXLISTS];
|
||||
|
||||
// allocate key lists
|
||||
al = new long[MAXLISTS][];
|
||||
al[0] = new long[1]; // make the first array (the transient buffer)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the number of entries in this set
|
||||
*/
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* add a long value to this set if not yet in.
|
||||
*
|
||||
* @param id the value to add to this set.
|
||||
* @return true if "id" already contained in this set.
|
||||
*/
|
||||
public boolean add(long id) {
|
||||
if (contains(id)) {
|
||||
return true;
|
||||
}
|
||||
_add(id);
|
||||
return false;
|
||||
}
|
||||
|
||||
public void fastAdd(long id) {
|
||||
_add(id);
|
||||
}
|
||||
|
||||
private void _add(long id) {
|
||||
if (size == Integer.MAX_VALUE) {
|
||||
throw new IllegalArgumentException("cannot grow beyond size Integer.MAX_VALUE");
|
||||
}
|
||||
|
||||
// put the new entry in the first array
|
||||
al[0][0] = id;
|
||||
|
||||
// determine the first empty array
|
||||
int bp = size++; // treat size as bitpattern
|
||||
int idx = 1;
|
||||
int n = 1;
|
||||
|
||||
pa[0] = 1;
|
||||
pa[1] = 1;
|
||||
|
||||
while ((bp & 1) == 1) {
|
||||
bp >>= 1;
|
||||
pa[idx++] = n;
|
||||
n <<= 1;
|
||||
}
|
||||
|
||||
// create it if not existant
|
||||
if (al[idx] == null) {
|
||||
al[idx] = new long[n];
|
||||
}
|
||||
|
||||
// now merge the contents of arrays 0...idx-1 into idx
|
||||
while (n > 0) {
|
||||
long maxId = 0;
|
||||
int maxIdx = -1;
|
||||
|
||||
for (int i = 0; i < idx; i++) {
|
||||
int p = pa[i];
|
||||
if (p > 0) {
|
||||
long currentId = al[i][p - 1];
|
||||
if (maxIdx < 0 || currentId > maxId) {
|
||||
maxIdx = i;
|
||||
maxId = currentId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// current maximum found, copy to target array
|
||||
if (n < al[idx].length && maxId == al[idx][n]) {
|
||||
throw new IllegalArgumentException("duplicate key found in late check: " + maxId);
|
||||
}
|
||||
--n;
|
||||
al[idx][n] = maxId;
|
||||
|
||||
--pa[maxIdx];
|
||||
}
|
||||
|
||||
// de-allocate empty arrays of a certain size (fix at 64kByte)
|
||||
while (idx-- > _maxKeepExponent) {
|
||||
al[idx] = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if "id" is contained in this set.
|
||||
*/
|
||||
public boolean contains(long id) {
|
||||
// determine the first empty array
|
||||
int bp = size; // treat size as bitpattern
|
||||
int idx = 1;
|
||||
|
||||
while (bp != 0) {
|
||||
if ((bp & 1) == 1) {
|
||||
// array at idx is valid, check
|
||||
if (contains(idx, id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
bp >>= 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// does sorted array "a" contain "id" ?
|
||||
private boolean contains(int idx, long id) {
|
||||
long[] a = al[idx];
|
||||
int offset = a.length;
|
||||
int n = 0;
|
||||
|
||||
while ((offset >>= 1) > 0) {
|
||||
int nn = n + offset;
|
||||
if (a[nn] <= id) {
|
||||
n = nn;
|
||||
}
|
||||
}
|
||||
if (a[n] == id) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void moveToFrozenArray(long[] faid) {
|
||||
for (int i = 1; i < MAXLISTS; i++) {
|
||||
pa[i] = 0;
|
||||
}
|
||||
|
||||
for (int ti = 0; ti < size; ti++) // target-index
|
||||
{
|
||||
int bp = size; // treat size as bitpattern
|
||||
int minIdx = -1;
|
||||
long minId = 0;
|
||||
int idx = 1;
|
||||
while (bp != 0) {
|
||||
if ((bp & 1) == 1) {
|
||||
int p = pa[idx];
|
||||
if (p < al[idx].length) {
|
||||
long currentId = al[idx][p];
|
||||
if (minIdx < 0 || currentId < minId) {
|
||||
minIdx = idx;
|
||||
minId = currentId;
|
||||
}
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
bp >>= 1;
|
||||
}
|
||||
faid[ti] = minId;
|
||||
pa[minIdx]++;
|
||||
|
||||
if (ti > 0 && faid[ti - 1] == minId) {
|
||||
throw new IllegalArgumentException("duplicate key found in late check: " + minId);
|
||||
}
|
||||
}
|
||||
|
||||
// free the non-frozen array
|
||||
al = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,52 +5,49 @@ package btools.util;
|
|||
*
|
||||
* @author ab
|
||||
*/
|
||||
public final class Crc32
|
||||
{
|
||||
public static int crc( byte[] ab, int offset, int len )
|
||||
{
|
||||
int crc = 0xFFFFFFFF;
|
||||
public final class Crc32 {
|
||||
public static int crc(byte[] ab, int offset, int len) {
|
||||
int crc = 0xFFFFFFFF;
|
||||
int end = offset + len;
|
||||
for( int j=offset; j<end; j++ )
|
||||
{
|
||||
for (int j = offset; j < end; j++) {
|
||||
crc = (crc >>> 8) ^ crctable[(crc ^ ab[j]) & 0xff];
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
private static int[] crctable = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
|
||||
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
|
||||
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
|
||||
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
|
||||
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
|
||||
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
|
||||
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
|
||||
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
|
||||
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
|
||||
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
|
||||
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
|
||||
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
|
||||
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
|
||||
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
|
||||
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
|
||||
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
|
||||
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
|
||||
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
|
||||
};
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
|
||||
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
|
||||
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
|
||||
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
|
||||
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
|
||||
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
|
||||
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
|
||||
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
|
||||
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
|
||||
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
|
||||
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
|
||||
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
|
||||
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
|
||||
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
|
||||
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
|
||||
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
|
||||
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
|
||||
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,233 +1,202 @@
|
|||
package btools.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Special Memory efficient Map to map a long-key to
|
||||
* a "small" value (some bits only) where it is expected
|
||||
* that the keys are dense, so that we can use more or less
|
||||
* a simple array as the best-fit data model (except for
|
||||
* the 32-bit limit of arrays!)
|
||||
*
|
||||
* Target application are osm-node ids which are in the
|
||||
* range 0...3 billion and basically dense (=only few
|
||||
* nodes deleted)
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
public class DenseLongMap
|
||||
{
|
||||
private ArrayList<byte[]> blocklist = new ArrayList<byte[]>(4096);
|
||||
|
||||
private int blocksize; // bytes per bitplane in one block
|
||||
private int blocksizeBits;
|
||||
private long blocksizeBitsMask;
|
||||
private int maxvalue = 254; // fixed due to 8 bit lookup table
|
||||
private int[] bitplaneCount = new int[8];
|
||||
private long putCount = 0L;
|
||||
private long getCount = 0L;
|
||||
|
||||
/**
|
||||
* Creates a DenseLongMap for the default block size
|
||||
* ( 512 bytes per bitplane, covering a key range of 4096 keys )
|
||||
* Note that one value range is limited to 0..254
|
||||
*/
|
||||
public DenseLongMap()
|
||||
{
|
||||
this(512);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DenseLongMap for the given block size
|
||||
*
|
||||
* @param blocksize bytes per bit-plane
|
||||
*/
|
||||
public DenseLongMap( int blocksize )
|
||||
{
|
||||
int bits = 4;
|
||||
while( bits < 28 && (1 << bits) != blocksize )
|
||||
{
|
||||
bits++;
|
||||
}
|
||||
if ( bits == 28 )
|
||||
{
|
||||
throw new RuntimeException( "not a valid blocksize: " + blocksize + " ( expected 1 << bits with bits in (4..27) )");
|
||||
}
|
||||
blocksizeBits = bits + 3;
|
||||
blocksizeBitsMask = (1L << blocksizeBits ) -1;
|
||||
this.blocksize = blocksize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void put( long key, int value )
|
||||
{
|
||||
putCount++;
|
||||
|
||||
if ( value < 0 || value > maxvalue )
|
||||
{
|
||||
throw new IllegalArgumentException( "value out of range (0.." + maxvalue + "): " + value );
|
||||
}
|
||||
|
||||
int blockn = (int)(key >> blocksizeBits);
|
||||
int offset = (int)(key & blocksizeBitsMask);
|
||||
|
||||
byte[] block = blockn < blocklist.size() ? blocklist.get( blockn ) : null;
|
||||
|
||||
int valuebits = 1;
|
||||
if ( block == null )
|
||||
{
|
||||
block = new byte[sizeForBits(valuebits)];
|
||||
bitplaneCount[0] ++;
|
||||
|
||||
while (blocklist.size() < blockn+1 )
|
||||
{
|
||||
blocklist.add(null);
|
||||
}
|
||||
blocklist.set( blockn, block );
|
||||
}
|
||||
else
|
||||
{
|
||||
// check how many bitplanes we have from the arraysize
|
||||
while( sizeForBits( valuebits) < block.length )
|
||||
{
|
||||
valuebits++;
|
||||
}
|
||||
}
|
||||
int headersize = 1 << valuebits;
|
||||
|
||||
byte v = (byte)(value + 1); // 0 is reserved (=unset)
|
||||
|
||||
// find the index in the lookup table or the first entry
|
||||
int idx = 1;
|
||||
while( idx < headersize )
|
||||
{
|
||||
if ( block[idx] == 0 )
|
||||
{
|
||||
block[idx] = v; // create new entry
|
||||
}
|
||||
if ( block[idx] == v )
|
||||
{
|
||||
break;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
if ( idx == headersize )
|
||||
{
|
||||
block = expandBlock( block, valuebits );
|
||||
block[idx] = v; // create new entry
|
||||
blocklist.set( blockn, block );
|
||||
valuebits++;
|
||||
headersize = 1 << valuebits;
|
||||
}
|
||||
|
||||
int bitmask = 1 << (offset & 0x7);
|
||||
int invmask = bitmask ^ 0xff;
|
||||
int probebit = 1;
|
||||
int blockidx = (offset >> 3) + headersize;
|
||||
|
||||
for( int i=0; i < valuebits; i++ )
|
||||
{
|
||||
if ( ( idx & probebit ) != 0 )
|
||||
{
|
||||
block[blockidx] |= bitmask;
|
||||
}
|
||||
else
|
||||
{
|
||||
block[blockidx] &= invmask;
|
||||
}
|
||||
probebit <<= 1;
|
||||
blockidx += blocksize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private int sizeForBits( int bits )
|
||||
{
|
||||
// size is lookup table + datablocks
|
||||
return ( 1 << bits ) + blocksize * bits;
|
||||
}
|
||||
|
||||
private byte[] expandBlock( byte[] block, int valuebits )
|
||||
{
|
||||
bitplaneCount[valuebits] ++;
|
||||
byte[] newblock = new byte[sizeForBits(valuebits+1)];
|
||||
int headersize = 1 << valuebits;
|
||||
System.arraycopy(block, 0, newblock, 0, headersize ); // copy header
|
||||
System.arraycopy(block, headersize, newblock, 2*headersize, block.length - headersize ); // copy data
|
||||
return newblock;
|
||||
}
|
||||
|
||||
public int getInt( long key )
|
||||
{
|
||||
// bit-stats on first get
|
||||
if ( getCount++ == 0L )
|
||||
{
|
||||
System.out.println( "**** DenseLongMap stats ****" );
|
||||
System.out.println( "putCount=" + putCount );
|
||||
for( int i=0; i<8; i++ )
|
||||
{
|
||||
System.out.println( i + "-bitplanes=" +bitplaneCount[i] );
|
||||
}
|
||||
System.out.println( "****************************" );
|
||||
}
|
||||
|
||||
/* actual stats for the 30x45 raster and 512 blocksize with filtered nodes:
|
||||
*
|
||||
**** DenseLongMap stats ****
|
||||
putCount=858518399
|
||||
0-bitplanes=783337
|
||||
1-bitplanes=771490
|
||||
2-bitplanes=644578
|
||||
3-bitplanes=210767
|
||||
4-bitplanes=439
|
||||
5-bitplanes=0
|
||||
6-bitplanes=0
|
||||
7-bitplanes=0
|
||||
*
|
||||
* This is a total of 1,2 GB
|
||||
* (1.234.232.832+7.381.126+15.666.740 for body/header/object-overhead )
|
||||
*/
|
||||
|
||||
if ( key < 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
int blockn = (int)(key >> blocksizeBits);
|
||||
int offset = (int)(key & blocksizeBitsMask);
|
||||
|
||||
byte[] block = blockn < blocklist.size() ? blocklist.get( blockn ) : null;
|
||||
|
||||
if ( block == null )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// check how many bitplanes we have from the arrayzize
|
||||
int valuebits = 1;
|
||||
while( sizeForBits( valuebits) < block.length )
|
||||
{
|
||||
valuebits++;
|
||||
}
|
||||
int headersize = 1 << valuebits;
|
||||
|
||||
int bitmask = 1 << (offset & 7);
|
||||
int probebit = 1;
|
||||
int blockidx = (offset >> 3) + headersize;
|
||||
int idx = 0; // 0 is reserved (=unset)
|
||||
|
||||
for( int i=0; i < valuebits; i++ )
|
||||
{
|
||||
if ( ( block[blockidx] & bitmask ) != 0 )
|
||||
{
|
||||
idx |= probebit;
|
||||
}
|
||||
probebit <<= 1;
|
||||
blockidx += blocksize;
|
||||
}
|
||||
|
||||
// lookup that value in the lookup header
|
||||
return ((256 + block[idx]) & 0xff ) -1;
|
||||
}
|
||||
|
||||
}
|
||||
package btools.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Special Memory efficient Map to map a long-key to
|
||||
* a "small" value (some bits only) where it is expected
|
||||
* that the keys are dense, so that we can use more or less
|
||||
* a simple array as the best-fit data model (except for
|
||||
* the 32-bit limit of arrays!)
|
||||
* <p>
|
||||
* Target application are osm-node ids which are in the
|
||||
* range 0...3 billion and basically dense (=only few
|
||||
* nodes deleted)
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
public class DenseLongMap {
|
||||
private ArrayList<byte[]> blocklist = new ArrayList<byte[]>(4096);
|
||||
|
||||
private int blocksize; // bytes per bitplane in one block
|
||||
private int blocksizeBits;
|
||||
private long blocksizeBitsMask;
|
||||
private int maxvalue = 254; // fixed due to 8 bit lookup table
|
||||
private int[] bitplaneCount = new int[8];
|
||||
private long putCount = 0L;
|
||||
private long getCount = 0L;
|
||||
|
||||
/**
|
||||
* Creates a DenseLongMap for the default block size
|
||||
* ( 512 bytes per bitplane, covering a key range of 4096 keys )
|
||||
* Note that one value range is limited to 0..254
|
||||
*/
|
||||
public DenseLongMap() {
|
||||
this(512);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DenseLongMap for the given block size
|
||||
*
|
||||
* @param blocksize bytes per bit-plane
|
||||
*/
|
||||
public DenseLongMap(int blocksize) {
|
||||
int bits = 4;
|
||||
while (bits < 28 && (1 << bits) != blocksize) {
|
||||
bits++;
|
||||
}
|
||||
if (bits == 28) {
|
||||
throw new RuntimeException("not a valid blocksize: " + blocksize + " ( expected 1 << bits with bits in (4..27) )");
|
||||
}
|
||||
blocksizeBits = bits + 3;
|
||||
blocksizeBitsMask = (1L << blocksizeBits) - 1;
|
||||
this.blocksize = blocksize;
|
||||
}
|
||||
|
||||
|
||||
public void put(long key, int value) {
|
||||
putCount++;
|
||||
|
||||
if (value < 0 || value > maxvalue) {
|
||||
throw new IllegalArgumentException("value out of range (0.." + maxvalue + "): " + value);
|
||||
}
|
||||
|
||||
int blockn = (int) (key >> blocksizeBits);
|
||||
int offset = (int) (key & blocksizeBitsMask);
|
||||
|
||||
byte[] block = blockn < blocklist.size() ? blocklist.get(blockn) : null;
|
||||
|
||||
int valuebits = 1;
|
||||
if (block == null) {
|
||||
block = new byte[sizeForBits(valuebits)];
|
||||
bitplaneCount[0]++;
|
||||
|
||||
while (blocklist.size() < blockn + 1) {
|
||||
blocklist.add(null);
|
||||
}
|
||||
blocklist.set(blockn, block);
|
||||
} else {
|
||||
// check how many bitplanes we have from the arraysize
|
||||
while (sizeForBits(valuebits) < block.length) {
|
||||
valuebits++;
|
||||
}
|
||||
}
|
||||
int headersize = 1 << valuebits;
|
||||
|
||||
byte v = (byte) (value + 1); // 0 is reserved (=unset)
|
||||
|
||||
// find the index in the lookup table or the first entry
|
||||
int idx = 1;
|
||||
while (idx < headersize) {
|
||||
if (block[idx] == 0) {
|
||||
block[idx] = v; // create new entry
|
||||
}
|
||||
if (block[idx] == v) {
|
||||
break;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
if (idx == headersize) {
|
||||
block = expandBlock(block, valuebits);
|
||||
block[idx] = v; // create new entry
|
||||
blocklist.set(blockn, block);
|
||||
valuebits++;
|
||||
headersize = 1 << valuebits;
|
||||
}
|
||||
|
||||
int bitmask = 1 << (offset & 0x7);
|
||||
int invmask = bitmask ^ 0xff;
|
||||
int probebit = 1;
|
||||
int blockidx = (offset >> 3) + headersize;
|
||||
|
||||
for (int i = 0; i < valuebits; i++) {
|
||||
if ((idx & probebit) != 0) {
|
||||
block[blockidx] |= bitmask;
|
||||
} else {
|
||||
block[blockidx] &= invmask;
|
||||
}
|
||||
probebit <<= 1;
|
||||
blockidx += blocksize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private int sizeForBits(int bits) {
|
||||
// size is lookup table + datablocks
|
||||
return (1 << bits) + blocksize * bits;
|
||||
}
|
||||
|
||||
private byte[] expandBlock(byte[] block, int valuebits) {
|
||||
bitplaneCount[valuebits]++;
|
||||
byte[] newblock = new byte[sizeForBits(valuebits + 1)];
|
||||
int headersize = 1 << valuebits;
|
||||
System.arraycopy(block, 0, newblock, 0, headersize); // copy header
|
||||
System.arraycopy(block, headersize, newblock, 2 * headersize, block.length - headersize); // copy data
|
||||
return newblock;
|
||||
}
|
||||
|
||||
public int getInt(long key) {
|
||||
// bit-stats on first get
|
||||
if (getCount++ == 0L) {
|
||||
System.out.println("**** DenseLongMap stats ****");
|
||||
System.out.println("putCount=" + putCount);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
System.out.println(i + "-bitplanes=" + bitplaneCount[i]);
|
||||
}
|
||||
System.out.println("****************************");
|
||||
}
|
||||
|
||||
/* actual stats for the 30x45 raster and 512 blocksize with filtered nodes:
|
||||
*
|
||||
**** DenseLongMap stats ****
|
||||
putCount=858518399
|
||||
0-bitplanes=783337
|
||||
1-bitplanes=771490
|
||||
2-bitplanes=644578
|
||||
3-bitplanes=210767
|
||||
4-bitplanes=439
|
||||
5-bitplanes=0
|
||||
6-bitplanes=0
|
||||
7-bitplanes=0
|
||||
*
|
||||
* This is a total of 1,2 GB
|
||||
* (1.234.232.832+7.381.126+15.666.740 for body/header/object-overhead )
|
||||
*/
|
||||
|
||||
if (key < 0) {
|
||||
return -1;
|
||||
}
|
||||
int blockn = (int) (key >> blocksizeBits);
|
||||
int offset = (int) (key & blocksizeBitsMask);
|
||||
|
||||
byte[] block = blockn < blocklist.size() ? blocklist.get(blockn) : null;
|
||||
|
||||
if (block == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// check how many bitplanes we have from the arrayzize
|
||||
int valuebits = 1;
|
||||
while (sizeForBits(valuebits) < block.length) {
|
||||
valuebits++;
|
||||
}
|
||||
int headersize = 1 << valuebits;
|
||||
|
||||
int bitmask = 1 << (offset & 7);
|
||||
int probebit = 1;
|
||||
int blockidx = (offset >> 3) + headersize;
|
||||
int idx = 0; // 0 is reserved (=unset)
|
||||
|
||||
for (int i = 0; i < valuebits; i++) {
|
||||
if ((block[blockidx] & bitmask) != 0) {
|
||||
idx |= probebit;
|
||||
}
|
||||
probebit <<= 1;
|
||||
blockidx += blocksize;
|
||||
}
|
||||
|
||||
// lookup that value in the lookup header
|
||||
return ((256 + block[idx]) & 0xff) - 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,40 +10,34 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
|
||||
|
||||
public final class DiffCoderDataInputStream extends DataInputStream
|
||||
{
|
||||
public final class DiffCoderDataInputStream extends DataInputStream {
|
||||
private long[] lastValues = new long[10];
|
||||
|
||||
public DiffCoderDataInputStream( InputStream is )
|
||||
{
|
||||
super( is );
|
||||
}
|
||||
|
||||
public long readDiffed( int idx ) throws IOException
|
||||
{
|
||||
long d = readSigned();
|
||||
long v = lastValues[idx] + d;
|
||||
lastValues[idx] = v;
|
||||
return v;
|
||||
|
||||
public DiffCoderDataInputStream(InputStream is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
public long readSigned() throws IOException
|
||||
{
|
||||
long v = readUnsigned();
|
||||
return ( v & 1 ) == 0 ? v >> 1 : -(v >> 1 );
|
||||
public long readDiffed(int idx) throws IOException {
|
||||
long d = readSigned();
|
||||
long v = lastValues[idx] + d;
|
||||
lastValues[idx] = v;
|
||||
return v;
|
||||
}
|
||||
|
||||
public long readUnsigned() throws IOException
|
||||
{
|
||||
long v = 0;
|
||||
int shift = 0;
|
||||
for(;;)
|
||||
{
|
||||
long i7 = readByte() & 0xff;
|
||||
v |= (( i7 & 0x7f ) << shift);
|
||||
if ( ( i7 & 0x80 ) == 0 ) break;
|
||||
shift += 7;
|
||||
}
|
||||
return v;
|
||||
public long readSigned() throws IOException {
|
||||
long v = readUnsigned();
|
||||
return (v & 1) == 0 ? v >> 1 : -(v >> 1);
|
||||
}
|
||||
|
||||
public long readUnsigned() throws IOException {
|
||||
long v = 0;
|
||||
int shift = 0;
|
||||
for (; ; ) {
|
||||
long i7 = readByte() & 0xff;
|
||||
v |= ((i7 & 0x7f) << shift);
|
||||
if ((i7 & 0x80) == 0) break;
|
||||
shift += 7;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,36 +10,30 @@ import java.io.IOException;
|
|||
import java.io.OutputStream;
|
||||
|
||||
|
||||
public final class DiffCoderDataOutputStream extends DataOutputStream
|
||||
{
|
||||
public final class DiffCoderDataOutputStream extends DataOutputStream {
|
||||
private long[] lastValues = new long[10];
|
||||
|
||||
public DiffCoderDataOutputStream( OutputStream os )
|
||||
{
|
||||
super( os );
|
||||
}
|
||||
|
||||
public void writeDiffed( long v, int idx ) throws IOException
|
||||
{
|
||||
long d = v - lastValues[idx];
|
||||
lastValues[idx] = v;
|
||||
writeSigned( d );
|
||||
|
||||
public DiffCoderDataOutputStream(OutputStream os) {
|
||||
super(os);
|
||||
}
|
||||
|
||||
public void writeSigned( long v ) throws IOException
|
||||
{
|
||||
writeUnsigned( v < 0 ? ( (-v) << 1 ) | 1 : v << 1 );
|
||||
public void writeDiffed(long v, int idx) throws IOException {
|
||||
long d = v - lastValues[idx];
|
||||
lastValues[idx] = v;
|
||||
writeSigned(d);
|
||||
}
|
||||
|
||||
public void writeUnsigned( long v ) throws IOException
|
||||
{
|
||||
do
|
||||
{
|
||||
long i7 = v & 0x7f;
|
||||
v >>= 7;
|
||||
if ( v != 0 ) i7 |= 0x80;
|
||||
writeByte( (byte)( i7 & 0xff ) );
|
||||
}
|
||||
while( v != 0 );
|
||||
public void writeSigned(long v) throws IOException {
|
||||
writeUnsigned(v < 0 ? ((-v) << 1) | 1 : v << 1);
|
||||
}
|
||||
|
||||
public void writeUnsigned(long v) throws IOException {
|
||||
do {
|
||||
long i7 = v & 0x7f;
|
||||
v >>= 7;
|
||||
if (v != 0) i7 |= 0x80;
|
||||
writeByte((byte) (i7 & 0xff));
|
||||
}
|
||||
while (v != 0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,20 +5,17 @@ package btools.util;
|
|||
*
|
||||
* @author ab
|
||||
*/
|
||||
public class FastMath
|
||||
{
|
||||
public class FastMath {
|
||||
/**
|
||||
* Approximation to Math.exp for small negative arguments
|
||||
*/
|
||||
public static double exp( double e )
|
||||
{
|
||||
public static double exp(double e) {
|
||||
double x = e;
|
||||
double f = 1.;
|
||||
while( e < -1. )
|
||||
{
|
||||
while (e < -1.) {
|
||||
e += 1.;
|
||||
f *= 0.367879;
|
||||
}
|
||||
return f*( 1. + x*( 1. + x * ( 0.5 + x * ( 0.166667 + 0.0416667 * x) ) ) );
|
||||
return f * (1. + x * (1. + x * (0.5 + x * (0.166667 + 0.0416667 * x))));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,143 +1,120 @@
|
|||
package btools.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Frozen instance of Memory efficient Map
|
||||
*
|
||||
* This one is readily sorted into a singe array for faster access
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
public class FrozenLongMap<V> extends CompactLongMap<V>
|
||||
{
|
||||
private long[] faid;
|
||||
private ArrayList<V> flv;
|
||||
private int size = 0;
|
||||
private int p2size; // next power of 2 of size
|
||||
|
||||
public FrozenLongMap( CompactLongMap<V> map )
|
||||
{
|
||||
size = map.size();
|
||||
|
||||
faid = new long[size];
|
||||
flv = new ArrayList<V>(size);
|
||||
|
||||
map.moveToFrozenArrays( faid, flv );
|
||||
|
||||
p2size = 0x40000000;
|
||||
while( p2size > size ) p2size >>= 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean put( long id, V value )
|
||||
{
|
||||
try
|
||||
{
|
||||
value_in = value;
|
||||
if ( contains( id, true ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
throw new RuntimeException( "cannot only put on existing key in FrozenLongIntMap" );
|
||||
}
|
||||
finally
|
||||
{
|
||||
value_in = null;
|
||||
value_out = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fastPut( long id, V value )
|
||||
{
|
||||
throw new RuntimeException( "cannot put on FrozenLongIntMap" );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of entries in this set
|
||||
*/
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return true if "id" is contained in this set.
|
||||
*/
|
||||
@Override
|
||||
protected boolean contains( long id, boolean doPut )
|
||||
{
|
||||
if ( size == 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
long[] a = faid;
|
||||
int offset = p2size;
|
||||
int n = 0;
|
||||
|
||||
while ( offset> 0 )
|
||||
{
|
||||
int nn = n + offset;
|
||||
if ( nn < size && a[nn] <= id )
|
||||
{
|
||||
n = nn;
|
||||
}
|
||||
offset >>= 1;
|
||||
}
|
||||
if ( a[n] == id )
|
||||
{
|
||||
value_out = flv.get(n);
|
||||
if ( doPut )
|
||||
{
|
||||
flv.set( n, value_in );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the value for "id", or null if key unknown
|
||||
*/
|
||||
@Override
|
||||
public V get( long id )
|
||||
{
|
||||
if ( size == 0 )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
long[] a = faid;
|
||||
int offset = p2size;
|
||||
int n = 0;
|
||||
|
||||
while ( offset> 0 )
|
||||
{
|
||||
int nn = n + offset;
|
||||
if ( nn < size && a[nn] <= id )
|
||||
{
|
||||
n = nn;
|
||||
}
|
||||
offset >>= 1;
|
||||
}
|
||||
if ( a[n] == id )
|
||||
{
|
||||
return flv.get(n);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<V> getValueList()
|
||||
{
|
||||
return flv;
|
||||
}
|
||||
|
||||
public long[] getKeyArray()
|
||||
{
|
||||
return faid;
|
||||
}
|
||||
}
|
||||
package btools.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Frozen instance of Memory efficient Map
|
||||
* <p>
|
||||
* This one is readily sorted into a singe array for faster access
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
public class FrozenLongMap<V> extends CompactLongMap<V> {
|
||||
private long[] faid;
|
||||
private ArrayList<V> flv;
|
||||
private int size = 0;
|
||||
private int p2size; // next power of 2 of size
|
||||
|
||||
public FrozenLongMap(CompactLongMap<V> map) {
|
||||
size = map.size();
|
||||
|
||||
faid = new long[size];
|
||||
flv = new ArrayList<V>(size);
|
||||
|
||||
map.moveToFrozenArrays(faid, flv);
|
||||
|
||||
p2size = 0x40000000;
|
||||
while (p2size > size) p2size >>= 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean put(long id, V value) {
|
||||
try {
|
||||
value_in = value;
|
||||
if (contains(id, true)) {
|
||||
return true;
|
||||
}
|
||||
throw new RuntimeException("cannot only put on existing key in FrozenLongIntMap");
|
||||
} finally {
|
||||
value_in = null;
|
||||
value_out = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fastPut(long id, V value) {
|
||||
throw new RuntimeException("cannot put on FrozenLongIntMap");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of entries in this set
|
||||
*/
|
||||
@Override
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return true if "id" is contained in this set.
|
||||
*/
|
||||
@Override
|
||||
protected boolean contains(long id, boolean doPut) {
|
||||
if (size == 0) {
|
||||
return false;
|
||||
}
|
||||
long[] a = faid;
|
||||
int offset = p2size;
|
||||
int n = 0;
|
||||
|
||||
while (offset > 0) {
|
||||
int nn = n + offset;
|
||||
if (nn < size && a[nn] <= id) {
|
||||
n = nn;
|
||||
}
|
||||
offset >>= 1;
|
||||
}
|
||||
if (a[n] == id) {
|
||||
value_out = flv.get(n);
|
||||
if (doPut) {
|
||||
flv.set(n, value_in);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the value for "id", or null if key unknown
|
||||
*/
|
||||
@Override
|
||||
public V get(long id) {
|
||||
if (size == 0) {
|
||||
return null;
|
||||
}
|
||||
long[] a = faid;
|
||||
int offset = p2size;
|
||||
int n = 0;
|
||||
|
||||
while (offset > 0) {
|
||||
int nn = n + offset;
|
||||
if (nn < size && a[nn] <= id) {
|
||||
n = nn;
|
||||
}
|
||||
offset >>= 1;
|
||||
}
|
||||
if (a[n] == id) {
|
||||
return flv.get(n);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<V> getValueList() {
|
||||
return flv;
|
||||
}
|
||||
|
||||
public long[] getKeyArray() {
|
||||
return faid;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,81 +1,70 @@
|
|||
package btools.util;
|
||||
|
||||
/**
|
||||
* Frozen instance of Memory efficient Set
|
||||
*
|
||||
* This one is readily sorted into a singe array for faster access
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
public class FrozenLongSet extends CompactLongSet
|
||||
{
|
||||
private long[] faid;
|
||||
private int size = 0;
|
||||
private int p2size; // next power of 2 of size
|
||||
|
||||
public FrozenLongSet( CompactLongSet set )
|
||||
{
|
||||
size = set.size();
|
||||
|
||||
faid = new long[size];
|
||||
|
||||
set.moveToFrozenArray( faid );
|
||||
|
||||
p2size = 0x40000000;
|
||||
while( p2size > size ) p2size >>= 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add( long id )
|
||||
{
|
||||
throw new RuntimeException( "cannot add on FrozenLongSet" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fastAdd( long id )
|
||||
{
|
||||
throw new RuntimeException( "cannot add on FrozenLongSet" );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of entries in this set
|
||||
*/
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return true if "id" is contained in this set.
|
||||
*/
|
||||
@Override
|
||||
public boolean contains( long id )
|
||||
{
|
||||
if ( size == 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
long[] a = faid;
|
||||
int offset = p2size;
|
||||
int n = 0;
|
||||
|
||||
while ( offset> 0 )
|
||||
{
|
||||
int nn = n + offset;
|
||||
if ( nn < size && a[nn] <= id )
|
||||
{
|
||||
n = nn;
|
||||
}
|
||||
offset >>= 1;
|
||||
}
|
||||
if ( a[n] == id )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
package btools.util;
|
||||
|
||||
/**
|
||||
* Frozen instance of Memory efficient Set
|
||||
* <p>
|
||||
* This one is readily sorted into a singe array for faster access
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
public class FrozenLongSet extends CompactLongSet {
|
||||
private long[] faid;
|
||||
private int size = 0;
|
||||
private int p2size; // next power of 2 of size
|
||||
|
||||
public FrozenLongSet(CompactLongSet set) {
|
||||
size = set.size();
|
||||
|
||||
faid = new long[size];
|
||||
|
||||
set.moveToFrozenArray(faid);
|
||||
|
||||
p2size = 0x40000000;
|
||||
while (p2size > size) p2size >>= 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(long id) {
|
||||
throw new RuntimeException("cannot add on FrozenLongSet");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fastAdd(long id) {
|
||||
throw new RuntimeException("cannot add on FrozenLongSet");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of entries in this set
|
||||
*/
|
||||
@Override
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return true if "id" is contained in this set.
|
||||
*/
|
||||
@Override
|
||||
public boolean contains(long id) {
|
||||
if (size == 0) {
|
||||
return false;
|
||||
}
|
||||
long[] a = faid;
|
||||
int offset = p2size;
|
||||
int n = 0;
|
||||
|
||||
while (offset > 0) {
|
||||
int nn = n + offset;
|
||||
if (nn < size && a[nn] <= id) {
|
||||
n = nn;
|
||||
}
|
||||
offset >>= 1;
|
||||
}
|
||||
if (a[n] == id) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package btools.util;
|
||||
|
||||
public interface IByteArrayUnifier
|
||||
{
|
||||
byte[] unify( byte[] ab, int offset, int len );
|
||||
public interface IByteArrayUnifier {
|
||||
byte[] unify(byte[] ab, int offset, int len);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,53 +1,44 @@
|
|||
package btools.util;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Behaves like an Array of list
|
||||
* with lazy list-allocation at getList
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
public class LazyArrayOfLists<E>
|
||||
{
|
||||
private ArrayList<ArrayList<E>> lists;
|
||||
|
||||
public LazyArrayOfLists( int size )
|
||||
{
|
||||
lists = new ArrayList<ArrayList<E>>( size );
|
||||
for ( int i = 0; i< size; i++ )
|
||||
{
|
||||
lists.add( null );
|
||||
}
|
||||
}
|
||||
|
||||
public List<E> getList( int idx )
|
||||
{
|
||||
ArrayList<E> list = lists.get( idx );
|
||||
if ( list == null )
|
||||
{
|
||||
list = new ArrayList<E>();
|
||||
lists.set( idx, list );
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public int getSize( int idx )
|
||||
{
|
||||
List<E> list = lists.get( idx );
|
||||
return list == null ? 0 : list.size();
|
||||
}
|
||||
|
||||
public void trimAll()
|
||||
{
|
||||
for ( int idx = 0; idx< lists.size(); idx++ )
|
||||
{
|
||||
ArrayList<E> list = lists.get( idx );
|
||||
if ( list != null )
|
||||
{
|
||||
list.trimToSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
package btools.util;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Behaves like an Array of list
|
||||
* with lazy list-allocation at getList
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
public class LazyArrayOfLists<E> {
|
||||
private ArrayList<ArrayList<E>> lists;
|
||||
|
||||
public LazyArrayOfLists(int size) {
|
||||
lists = new ArrayList<ArrayList<E>>(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
lists.add(null);
|
||||
}
|
||||
}
|
||||
|
||||
public List<E> getList(int idx) {
|
||||
ArrayList<E> list = lists.get(idx);
|
||||
if (list == null) {
|
||||
list = new ArrayList<E>();
|
||||
lists.set(idx, list);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public int getSize(int idx) {
|
||||
List<E> list = lists.get(idx);
|
||||
return list == null ? 0 : list.size();
|
||||
}
|
||||
|
||||
public void trimAll() {
|
||||
for (int idx = 0; idx < lists.size(); idx++) {
|
||||
ArrayList<E> list = lists.get(idx);
|
||||
if (list != null) {
|
||||
list.trimToSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,43 +1,36 @@
|
|||
package btools.util;
|
||||
|
||||
/**
|
||||
* dynamic list of primitive longs
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
public class LongList
|
||||
{
|
||||
private long[] a;
|
||||
private int size;
|
||||
|
||||
public LongList( int capacity )
|
||||
{
|
||||
a = capacity < 4 ? new long[4] : new long[capacity];
|
||||
}
|
||||
|
||||
public void add( long value )
|
||||
{
|
||||
if ( size == a.length )
|
||||
{
|
||||
long[] aa = new long[2*size];
|
||||
System.arraycopy( a, 0, aa, 0, size );
|
||||
a = aa;
|
||||
}
|
||||
a[size++] = value;
|
||||
}
|
||||
|
||||
public long get( int idx )
|
||||
{
|
||||
if ( idx >= size )
|
||||
{
|
||||
throw new IndexOutOfBoundsException( "list size=" + size + " idx=" + idx );
|
||||
}
|
||||
return a[idx];
|
||||
}
|
||||
|
||||
public int size()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
}
|
||||
package btools.util;
|
||||
|
||||
/**
|
||||
* dynamic list of primitive longs
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
public class LongList {
|
||||
private long[] a;
|
||||
private int size;
|
||||
|
||||
public LongList(int capacity) {
|
||||
a = capacity < 4 ? new long[4] : new long[capacity];
|
||||
}
|
||||
|
||||
public void add(long value) {
|
||||
if (size == a.length) {
|
||||
long[] aa = new long[2 * size];
|
||||
System.arraycopy(a, 0, aa, 0, size);
|
||||
a = aa;
|
||||
}
|
||||
a[size++] = value;
|
||||
}
|
||||
|
||||
public long get(int idx) {
|
||||
if (idx >= size) {
|
||||
throw new IndexOutOfBoundsException("list size=" + size + " idx=" + idx);
|
||||
}
|
||||
return a[idx];
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,114 +5,93 @@ package btools.util;
|
|||
*
|
||||
* @author ab
|
||||
*/
|
||||
public final class LruMap
|
||||
{
|
||||
public final class LruMap {
|
||||
private int hashbins;
|
||||
private int maxsize;
|
||||
private int size;
|
||||
|
||||
|
||||
private LruMapNode lru;
|
||||
private LruMapNode mru;
|
||||
|
||||
private LruMapNode[] binArray;
|
||||
|
||||
public LruMap( int bins, int size)
|
||||
{
|
||||
public LruMap(int bins, int size) {
|
||||
hashbins = bins;
|
||||
maxsize = size;
|
||||
binArray = new LruMapNode[hashbins];
|
||||
}
|
||||
|
||||
public LruMapNode get( LruMapNode key )
|
||||
{
|
||||
int bin = ( key.hash & 0xfffffff ) % hashbins;
|
||||
|
||||
|
||||
public LruMapNode get(LruMapNode key) {
|
||||
int bin = (key.hash & 0xfffffff) % hashbins;
|
||||
|
||||
LruMapNode e = binArray[bin];
|
||||
while ( e != null )
|
||||
{
|
||||
if ( key.equals( e ) )
|
||||
{
|
||||
while (e != null) {
|
||||
if (key.equals(e)) {
|
||||
return e;
|
||||
}
|
||||
e = e.nextInBin;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// put e to the mru end of the queue
|
||||
public void touch( LruMapNode e )
|
||||
{
|
||||
public void touch(LruMapNode e) {
|
||||
LruMapNode n = e.next;
|
||||
LruMapNode p = e.previous;
|
||||
|
||||
if ( n == null )
|
||||
{
|
||||
|
||||
if (n == null) {
|
||||
return; // already at mru
|
||||
}
|
||||
n.previous = p;
|
||||
if ( p != null )
|
||||
{
|
||||
if (p != null) {
|
||||
p.next = n;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
lru = n;
|
||||
}
|
||||
|
||||
|
||||
mru.next = e;
|
||||
e.previous = mru;
|
||||
e.previous = mru;
|
||||
e.next = null;
|
||||
mru = e;
|
||||
}
|
||||
|
||||
public LruMapNode removeLru()
|
||||
{
|
||||
if ( size < maxsize )
|
||||
{
|
||||
|
||||
public LruMapNode removeLru() {
|
||||
if (size < maxsize) {
|
||||
return null;
|
||||
}
|
||||
size--;
|
||||
// unlink the lru from it's bin-queue
|
||||
int bin = ( lru.hashCode() & 0xfffffff ) % hashbins;
|
||||
int bin = (lru.hashCode() & 0xfffffff) % hashbins;
|
||||
LruMapNode e = binArray[bin];
|
||||
if ( e == lru )
|
||||
{
|
||||
if (e == lru) {
|
||||
binArray[bin] = lru.nextInBin;
|
||||
}
|
||||
else
|
||||
{
|
||||
while( e != null )
|
||||
{
|
||||
} else {
|
||||
while (e != null) {
|
||||
LruMapNode prev = e;
|
||||
e = e.nextInBin;
|
||||
if ( e == lru )
|
||||
{
|
||||
if (e == lru) {
|
||||
prev.nextInBin = lru.nextInBin;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LruMapNode res = lru;
|
||||
lru = lru.next;
|
||||
lru.previous = null;
|
||||
return res;
|
||||
}
|
||||
|
||||
public void put( LruMapNode val )
|
||||
{
|
||||
int bin = ( val.hashCode() & 0xfffffff ) % hashbins;
|
||||
public void put(LruMapNode val) {
|
||||
int bin = (val.hashCode() & 0xfffffff) % hashbins;
|
||||
val.nextInBin = binArray[bin];
|
||||
binArray[bin] = val;
|
||||
|
||||
val.previous = mru;
|
||||
|
||||
val.previous = mru;
|
||||
val.next = null;
|
||||
if ( mru == null )
|
||||
{
|
||||
if (mru == null) {
|
||||
lru = val;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
mru.next = val;
|
||||
}
|
||||
mru = val;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
package btools.util;
|
||||
|
||||
public abstract class LruMapNode
|
||||
{
|
||||
public abstract class LruMapNode {
|
||||
LruMapNode nextInBin; // next entry for hash-bin
|
||||
LruMapNode next; // next in lru sequence (towards mru)
|
||||
LruMapNode previous; // previous in lru sequence (towards lru)
|
||||
|
||||
|
||||
public int hash;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
|
||||
|
||||
public final class MixCoderDataInputStream extends DataInputStream
|
||||
{
|
||||
public final class MixCoderDataInputStream extends DataInputStream {
|
||||
private int lastValue;
|
||||
private int repCount;
|
||||
private int diffshift;
|
||||
|
|
@ -22,15 +21,12 @@ public final class MixCoderDataInputStream extends DataInputStream
|
|||
private static final int[] vl_values = BitCoderContext.vl_values;
|
||||
private static final int[] vl_length = BitCoderContext.vl_length;
|
||||
|
||||
public MixCoderDataInputStream( InputStream is )
|
||||
{
|
||||
super( is );
|
||||
public MixCoderDataInputStream(InputStream is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
public int readMixed() throws IOException
|
||||
{
|
||||
if ( repCount == 0 )
|
||||
{
|
||||
public int readMixed() throws IOException {
|
||||
if (repCount == 0) {
|
||||
boolean negative = decodeBit();
|
||||
int d = decodeVarBits() + diffshift;
|
||||
repCount = decodeVarBits() + 1;
|
||||
|
|
@ -41,37 +37,32 @@ public final class MixCoderDataInputStream extends DataInputStream
|
|||
return lastValue;
|
||||
}
|
||||
|
||||
public final boolean decodeBit() throws IOException
|
||||
{
|
||||
public final boolean decodeBit() throws IOException {
|
||||
fillBuffer();
|
||||
boolean value = ( ( b & 1 ) != 0 );
|
||||
boolean value = ((b & 1) != 0);
|
||||
b >>>= 1;
|
||||
bits--;
|
||||
return value;
|
||||
}
|
||||
|
||||
public final int decodeVarBits2() throws IOException
|
||||
{
|
||||
public final int decodeVarBits2() throws IOException {
|
||||
int range = 0;
|
||||
while (!decodeBit())
|
||||
{
|
||||
while (!decodeBit()) {
|
||||
range = 2 * range + 1;
|
||||
}
|
||||
return range + decodeBounded( range );
|
||||
return range + decodeBounded(range);
|
||||
}
|
||||
|
||||
/**
|
||||
* decode an integer in the range 0..max (inclusive).
|
||||
*
|
||||
* @see #encodeBounded
|
||||
*/
|
||||
public final int decodeBounded( int max ) throws IOException
|
||||
{
|
||||
public final int decodeBounded(int max) throws IOException {
|
||||
int value = 0;
|
||||
int im = 1; // integer mask
|
||||
while (( value | im ) <= max)
|
||||
{
|
||||
if ( decodeBit() )
|
||||
{
|
||||
while ((value | im) <= max) {
|
||||
if (decodeBit()) {
|
||||
value |= im;
|
||||
}
|
||||
im <<= 1;
|
||||
|
|
@ -84,38 +75,35 @@ public final class MixCoderDataInputStream extends DataInputStream
|
|||
* @see #encodeVarBits
|
||||
*/
|
||||
|
||||
public final int decodeVarBits() throws IOException
|
||||
{
|
||||
public final int decodeVarBits() throws IOException {
|
||||
fillBuffer();
|
||||
int b12 = b & 0xfff;
|
||||
int len = vl_length[b12];
|
||||
if ( len <= 12 )
|
||||
{
|
||||
if (len <= 12) {
|
||||
b >>>= len;
|
||||
bits -= len;
|
||||
return vl_values[b12]; // full value lookup
|
||||
}
|
||||
if ( len <= 23 ) // // only length lookup
|
||||
if (len <= 23) // // only length lookup
|
||||
{
|
||||
int len2 = len >> 1;
|
||||
b >>>= (len2+1);
|
||||
int mask = 0xffffffff >>> ( 32 - len2 );
|
||||
b >>>= (len2 + 1);
|
||||
int mask = 0xffffffff >>> (32 - len2);
|
||||
mask += b & mask;
|
||||
b >>>= len2;
|
||||
bits -= len;
|
||||
return mask;
|
||||
}
|
||||
if ( (b & 0xffffff) != 0 )
|
||||
{
|
||||
if ((b & 0xffffff) != 0) {
|
||||
// here we just know len in [25..47]
|
||||
// ( fillBuffer guarantees only 24 bits! )
|
||||
b >>>= 12;
|
||||
int len3 = 1 + (vl_length[b & 0xfff]>>1);
|
||||
int len3 = 1 + (vl_length[b & 0xfff] >> 1);
|
||||
b >>>= len3;
|
||||
int len2 = 11 + len3;
|
||||
bits -= len2+1;
|
||||
bits -= len2 + 1;
|
||||
fillBuffer();
|
||||
int mask = 0xffffffff >>> ( 32 - len2 );
|
||||
int mask = 0xffffffff >>> (32 - len2);
|
||||
mask += b & mask;
|
||||
b >>>= len2;
|
||||
bits -= len2;
|
||||
|
|
@ -124,14 +112,11 @@ public final class MixCoderDataInputStream extends DataInputStream
|
|||
return decodeVarBits2(); // no chance, use the slow one
|
||||
}
|
||||
|
||||
private void fillBuffer() throws IOException
|
||||
{
|
||||
while (bits < 24)
|
||||
{
|
||||
private void fillBuffer() throws IOException {
|
||||
while (bits < 24) {
|
||||
int nextByte = read();
|
||||
|
||||
if ( nextByte != -1 )
|
||||
{
|
||||
|
||||
if (nextByte != -1) {
|
||||
b |= (nextByte & 0xff) << bits;
|
||||
}
|
||||
bits += 8;
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ import java.io.IOException;
|
|||
import java.io.OutputStream;
|
||||
|
||||
|
||||
public final class MixCoderDataOutputStream extends DataOutputStream
|
||||
{
|
||||
public final class MixCoderDataOutputStream extends DataOutputStream {
|
||||
private int lastValue;
|
||||
private int lastLastValue;
|
||||
private int repCount;
|
||||
|
|
@ -23,28 +22,24 @@ public final class MixCoderDataOutputStream extends DataOutputStream
|
|||
public static int[] diffs = new int[100];
|
||||
public static int[] counts = new int[100];
|
||||
|
||||
public MixCoderDataOutputStream( OutputStream os )
|
||||
{
|
||||
super( os );
|
||||
public MixCoderDataOutputStream(OutputStream os) {
|
||||
super(os);
|
||||
}
|
||||
|
||||
public void writeMixed( int v ) throws IOException
|
||||
{
|
||||
if ( v != lastValue && repCount > 0 )
|
||||
{
|
||||
public void writeMixed(int v) throws IOException {
|
||||
if (v != lastValue && repCount > 0) {
|
||||
int d = lastValue - lastLastValue;
|
||||
lastLastValue = lastValue;
|
||||
|
||||
encodeBit( d < 0 );
|
||||
if ( d < 0 )
|
||||
{
|
||||
|
||||
encodeBit(d < 0);
|
||||
if (d < 0) {
|
||||
d = -d;
|
||||
}
|
||||
encodeVarBits( d-diffshift );
|
||||
encodeVarBits( repCount-1 );
|
||||
|
||||
if ( d < 100 ) diffs[d]++;
|
||||
if ( repCount < 100 ) counts[repCount]++;
|
||||
encodeVarBits(d - diffshift);
|
||||
encodeVarBits(repCount - 1);
|
||||
|
||||
if (d < 100) diffs[d]++;
|
||||
if (repCount < 100) counts[repCount]++;
|
||||
|
||||
diffshift = 1;
|
||||
repCount = 0;
|
||||
|
|
@ -54,59 +49,48 @@ public final class MixCoderDataOutputStream extends DataOutputStream
|
|||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException
|
||||
{
|
||||
public void flush() throws IOException {
|
||||
int v = lastValue;
|
||||
writeMixed( v+1 );
|
||||
writeMixed(v + 1);
|
||||
lastValue = v;
|
||||
repCount = 0;
|
||||
if ( bm > 1 )
|
||||
{
|
||||
writeByte( (byte)b ); // flush bit-coding
|
||||
if (bm > 1) {
|
||||
writeByte((byte) b); // flush bit-coding
|
||||
}
|
||||
}
|
||||
|
||||
public final void encodeBit( boolean value ) throws IOException
|
||||
{
|
||||
if ( bm == 0x100 )
|
||||
{
|
||||
writeByte( (byte)b );
|
||||
public final void encodeBit(boolean value) throws IOException {
|
||||
if (bm == 0x100) {
|
||||
writeByte((byte) b);
|
||||
bm = 1;
|
||||
b = 0;
|
||||
}
|
||||
if ( value )
|
||||
{
|
||||
if (value) {
|
||||
b |= bm;
|
||||
}
|
||||
bm <<= 1;
|
||||
}
|
||||
|
||||
public final void encodeVarBits( int value ) throws IOException
|
||||
{
|
||||
public final void encodeVarBits(int value) throws IOException {
|
||||
int range = 0;
|
||||
while (value > range)
|
||||
{
|
||||
encodeBit( false );
|
||||
while (value > range) {
|
||||
encodeBit(false);
|
||||
value -= range + 1;
|
||||
range = 2 * range + 1;
|
||||
}
|
||||
encodeBit( true );
|
||||
encodeBounded( range, value );
|
||||
encodeBit(true);
|
||||
encodeBounded(range, value);
|
||||
}
|
||||
|
||||
public final void encodeBounded( int max, int value ) throws IOException
|
||||
{
|
||||
public final void encodeBounded(int max, int value) throws IOException {
|
||||
int im = 1; // integer mask
|
||||
while (im <= max)
|
||||
{
|
||||
if ( bm == 0x100 )
|
||||
{
|
||||
writeByte( (byte)b );
|
||||
while (im <= max) {
|
||||
if (bm == 0x100) {
|
||||
writeByte((byte) b);
|
||||
bm = 1;
|
||||
b = 0;
|
||||
}
|
||||
if ( ( value & im ) != 0 )
|
||||
{
|
||||
if ((value & im) != 0) {
|
||||
b |= bm;
|
||||
max -= im;
|
||||
}
|
||||
|
|
@ -115,9 +99,8 @@ public final class MixCoderDataOutputStream extends DataOutputStream
|
|||
}
|
||||
}
|
||||
|
||||
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] );
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
package btools.util;
|
||||
|
||||
|
||||
public interface ProgressListener
|
||||
{
|
||||
public interface ProgressListener {
|
||||
public void updateProgress(String task, int progress);
|
||||
|
||||
|
||||
public boolean isCanceled();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,31 +3,24 @@ package btools.util;
|
|||
/**
|
||||
* a median filter with additional edge reduction
|
||||
*/
|
||||
public final class ReducedMedianFilter
|
||||
{
|
||||
public final class ReducedMedianFilter {
|
||||
private int nsamples;
|
||||
private double[] weights;
|
||||
private int[] values;
|
||||
|
||||
public ReducedMedianFilter( int size )
|
||||
{
|
||||
public ReducedMedianFilter(int size) {
|
||||
weights = new double[size];
|
||||
values = new int[size];
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
public void reset() {
|
||||
nsamples = 0;
|
||||
}
|
||||
|
||||
public void addSample( double weight, int value )
|
||||
{
|
||||
if ( weight > 0. )
|
||||
{
|
||||
for( int i=0; i<nsamples; i++ )
|
||||
{
|
||||
if ( values[i] == value )
|
||||
{
|
||||
public void addSample(double weight, int value) {
|
||||
if (weight > 0.) {
|
||||
for (int i = 0; i < nsamples; i++) {
|
||||
if (values[i] == value) {
|
||||
weights[i] += weight;
|
||||
return;
|
||||
}
|
||||
|
|
@ -38,63 +31,52 @@ public final class ReducedMedianFilter
|
|||
}
|
||||
}
|
||||
|
||||
public double calcEdgeReducedMedian( double fraction )
|
||||
{
|
||||
removeEdgeWeight( (1. - fraction)/2., true );
|
||||
removeEdgeWeight( (1. - fraction)/2., false );
|
||||
public double calcEdgeReducedMedian(double fraction) {
|
||||
removeEdgeWeight((1. - fraction) / 2., true);
|
||||
removeEdgeWeight((1. - fraction) / 2., false);
|
||||
|
||||
double totalWeight = 0.;
|
||||
double totalValue = 0.;
|
||||
for( int i=0; i<nsamples; i++ )
|
||||
{
|
||||
for (int i = 0; i < nsamples; i++) {
|
||||
double w = weights[i];
|
||||
totalWeight += w;
|
||||
totalValue += w*values[i];
|
||||
totalValue += w * values[i];
|
||||
}
|
||||
return totalValue / totalWeight;
|
||||
}
|
||||
|
||||
|
||||
private void removeEdgeWeight( double excessWeight, boolean high )
|
||||
{
|
||||
while ( excessWeight > 0. )
|
||||
{
|
||||
// first pass to find minmax value
|
||||
double totalWeight = 0.;
|
||||
int minmax = 0;
|
||||
for( int i=0; i<nsamples; i++ )
|
||||
{
|
||||
double w = weights[i];
|
||||
if ( w > 0. )
|
||||
{
|
||||
int v = values[i];
|
||||
if ( totalWeight == 0. || ( high ? v > minmax : v < minmax ) )
|
||||
{
|
||||
minmax = v;
|
||||
}
|
||||
totalWeight += w;
|
||||
}
|
||||
}
|
||||
|
||||
if ( totalWeight < excessWeight ) throw new IllegalArgumentException( "ups, not enough weight to remove" );
|
||||
private void removeEdgeWeight(double excessWeight, boolean high) {
|
||||
while (excessWeight > 0.) {
|
||||
// first pass to find minmax value
|
||||
double totalWeight = 0.;
|
||||
int minmax = 0;
|
||||
for (int i = 0; i < nsamples; i++) {
|
||||
double w = weights[i];
|
||||
if (w > 0.) {
|
||||
int v = values[i];
|
||||
if (totalWeight == 0. || (high ? v > minmax : v < minmax)) {
|
||||
minmax = v;
|
||||
}
|
||||
totalWeight += w;
|
||||
}
|
||||
}
|
||||
|
||||
// second pass to remove
|
||||
for( int i=0; i<nsamples; i++ )
|
||||
{
|
||||
if ( values[i] == minmax && weights[i] > 0. )
|
||||
{
|
||||
if ( excessWeight > weights[i] )
|
||||
{
|
||||
excessWeight -= weights[i];
|
||||
weights[i] = 0.;
|
||||
}
|
||||
else
|
||||
{
|
||||
weights[i] -= excessWeight;
|
||||
excessWeight = 0.;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (totalWeight < excessWeight)
|
||||
throw new IllegalArgumentException("ups, not enough weight to remove");
|
||||
|
||||
// second pass to remove
|
||||
for (int i = 0; i < nsamples; i++) {
|
||||
if (values[i] == minmax && weights[i] > 0.) {
|
||||
if (excessWeight > weights[i]) {
|
||||
excessWeight -= weights[i];
|
||||
weights[i] = 0.;
|
||||
} else {
|
||||
weights[i] -= excessWeight;
|
||||
excessWeight = 0.;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,27 +7,23 @@ import java.util.Random;
|
|||
*
|
||||
* @author ab
|
||||
*/
|
||||
public final class SortedHeap<V>
|
||||
{
|
||||
public final class SortedHeap<V> {
|
||||
private int size;
|
||||
private int peaksize;
|
||||
private SortedBin first;
|
||||
private SortedBin second;
|
||||
private SortedBin firstNonEmpty;
|
||||
|
||||
public SortedHeap()
|
||||
{
|
||||
public SortedHeap() {
|
||||
clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the lowest key value, or null if none
|
||||
*/
|
||||
public V popLowestKeyValue()
|
||||
{
|
||||
public V popLowestKeyValue() {
|
||||
SortedBin bin = firstNonEmpty;
|
||||
if ( firstNonEmpty == null )
|
||||
{
|
||||
if (firstNonEmpty == null) {
|
||||
return null;
|
||||
}
|
||||
size--;
|
||||
|
|
@ -35,8 +31,7 @@ public final class SortedHeap<V>
|
|||
return (V) minBin.dropLowest();
|
||||
}
|
||||
|
||||
private static final class SortedBin
|
||||
{
|
||||
private static final class SortedBin {
|
||||
SortedHeap parent;
|
||||
SortedBin next;
|
||||
SortedBin nextNonEmpty;
|
||||
|
|
@ -46,8 +41,7 @@ public final class SortedHeap<V>
|
|||
int lv; // low value
|
||||
int lp; // low pointer
|
||||
|
||||
SortedBin( int binsize, SortedHeap parent )
|
||||
{
|
||||
SortedBin(int binsize, SortedHeap parent) {
|
||||
this.binsize = binsize;
|
||||
this.parent = parent;
|
||||
al = new int[binsize];
|
||||
|
|
@ -55,24 +49,18 @@ public final class SortedHeap<V>
|
|||
lp = binsize;
|
||||
}
|
||||
|
||||
SortedBin next()
|
||||
{
|
||||
if ( next == null )
|
||||
{
|
||||
next = new SortedBin( binsize << 1, parent );
|
||||
SortedBin next() {
|
||||
if (next == null) {
|
||||
next = new SortedBin(binsize << 1, parent);
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
Object dropLowest()
|
||||
{
|
||||
Object dropLowest() {
|
||||
int lpOld = lp;
|
||||
if ( ++lp == binsize )
|
||||
{
|
||||
if (++lp == binsize) {
|
||||
unlink();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
lv = al[lp];
|
||||
}
|
||||
Object res = vla[lpOld];
|
||||
|
|
@ -80,19 +68,15 @@ public final class SortedHeap<V>
|
|||
return res;
|
||||
}
|
||||
|
||||
void unlink()
|
||||
{
|
||||
void unlink() {
|
||||
SortedBin neBin = parent.firstNonEmpty;
|
||||
if ( neBin == this )
|
||||
{
|
||||
if (neBin == this) {
|
||||
parent.firstNonEmpty = nextNonEmpty;
|
||||
return;
|
||||
}
|
||||
for(;;)
|
||||
{
|
||||
for (; ; ) {
|
||||
SortedBin next = neBin.nextNonEmpty;
|
||||
if ( next == this )
|
||||
{
|
||||
if (next == this) {
|
||||
neBin.nextNonEmpty = nextNonEmpty;
|
||||
return;
|
||||
}
|
||||
|
|
@ -100,30 +84,25 @@ public final class SortedHeap<V>
|
|||
}
|
||||
}
|
||||
|
||||
void add( int key, Object value )
|
||||
{
|
||||
void add(int key, Object value) {
|
||||
int p = lp;
|
||||
for(;;)
|
||||
{
|
||||
if ( p == binsize || key < al[p] )
|
||||
{
|
||||
al[p-1] = key;
|
||||
vla[p-1] = value;
|
||||
for (; ; ) {
|
||||
if (p == binsize || key < al[p]) {
|
||||
al[p - 1] = key;
|
||||
vla[p - 1] = value;
|
||||
lv = al[--lp];
|
||||
return;
|
||||
}
|
||||
al[p-1] = al[p];
|
||||
vla[p-1] = vla[p];
|
||||
al[p - 1] = al[p];
|
||||
vla[p - 1] = vla[p];
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
// unrolled version of above for binsize = 4
|
||||
void add4( int key, Object value )
|
||||
{
|
||||
void add4(int key, Object value) {
|
||||
int p = lp--;
|
||||
if ( p == 4 || key < al[p] )
|
||||
{
|
||||
if (p == 4 || key < al[p]) {
|
||||
lv = al[p - 1] = key;
|
||||
vla[p - 1] = value;
|
||||
return;
|
||||
|
|
@ -132,8 +111,7 @@ public final class SortedHeap<V>
|
|||
vla[p - 1] = vla[p];
|
||||
p++;
|
||||
|
||||
if ( p == 4 || key < al[p] )
|
||||
{
|
||||
if (p == 4 || key < al[p]) {
|
||||
al[p - 1] = key;
|
||||
vla[p - 1] = value;
|
||||
return;
|
||||
|
|
@ -142,8 +120,7 @@ public final class SortedHeap<V>
|
|||
vla[p - 1] = vla[p];
|
||||
p++;
|
||||
|
||||
if ( p == 4 || key < al[p] )
|
||||
{
|
||||
if (p == 4 || key < al[p]) {
|
||||
al[p - 1] = key;
|
||||
vla[p - 1] = value;
|
||||
return;
|
||||
|
|
@ -156,72 +133,71 @@ public final class SortedHeap<V>
|
|||
}
|
||||
|
||||
// unrolled loop for performance sake
|
||||
SortedBin getMinBin()
|
||||
{
|
||||
SortedBin getMinBin() {
|
||||
SortedBin minBin = this;
|
||||
SortedBin bin = this;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ( (bin = bin.nextNonEmpty) == null ) return minBin;
|
||||
if ( bin.lv < minBin.lv ) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
if ((bin = bin.nextNonEmpty) == null) return minBin;
|
||||
if (bin.lv < minBin.lv) minBin = bin;
|
||||
return minBin;
|
||||
}
|
||||
}
|
||||
|
|
@ -229,31 +205,26 @@ public final class SortedHeap<V>
|
|||
/**
|
||||
* add a key value pair to the heap
|
||||
*
|
||||
* @param key the key to insert
|
||||
* @param value the value to insert object
|
||||
* @param key the key to insert
|
||||
* @param value the value to insert object
|
||||
*/
|
||||
public void add( int key, V value )
|
||||
{
|
||||
public void add(int key, V value) {
|
||||
size++;
|
||||
|
||||
if ( first.lp == 0 && second.lp == 0) // both full ?
|
||||
if (first.lp == 0 && second.lp == 0) // both full ?
|
||||
{
|
||||
sortUp();
|
||||
}
|
||||
if ( first.lp > 0 )
|
||||
{
|
||||
first.add4( key, value );
|
||||
if ( firstNonEmpty != first )
|
||||
{
|
||||
if (first.lp > 0) {
|
||||
first.add4(key, value);
|
||||
if (firstNonEmpty != first) {
|
||||
first.nextNonEmpty = firstNonEmpty;
|
||||
firstNonEmpty = first;
|
||||
}
|
||||
}
|
||||
else // second bin not full
|
||||
} else // second bin not full
|
||||
{
|
||||
second.add4( key, value );
|
||||
if ( first.nextNonEmpty != second )
|
||||
{
|
||||
second.add4(key, value);
|
||||
if (first.nextNonEmpty != second) {
|
||||
second.nextNonEmpty = first.nextNonEmpty;
|
||||
first.nextNonEmpty = second;
|
||||
}
|
||||
|
|
@ -261,10 +232,8 @@ public final class SortedHeap<V>
|
|||
|
||||
}
|
||||
|
||||
private void sortUp()
|
||||
{
|
||||
if ( size > peaksize )
|
||||
{
|
||||
private void sortUp() {
|
||||
if (size > peaksize) {
|
||||
peaksize = size;
|
||||
}
|
||||
|
||||
|
|
@ -272,75 +241,66 @@ public final class SortedHeap<V>
|
|||
int cnt = 8; // value count of first 2 bins is always 8
|
||||
SortedBin tbin = second; // target bin
|
||||
SortedBin lastNonEmpty = second;
|
||||
do
|
||||
{
|
||||
do {
|
||||
tbin = tbin.next();
|
||||
int nentries = tbin.binsize - tbin.lp;
|
||||
if ( nentries > 0 )
|
||||
{
|
||||
if (nentries > 0) {
|
||||
cnt += nentries;
|
||||
lastNonEmpty = tbin;
|
||||
}
|
||||
}
|
||||
while( cnt > tbin.binsize );
|
||||
while (cnt > tbin.binsize);
|
||||
|
||||
int[] al_t = tbin.al;
|
||||
Object[] vla_t = tbin.vla;
|
||||
int tp = tbin.binsize-cnt; // target pointer
|
||||
int tp = tbin.binsize - cnt; // target pointer
|
||||
|
||||
// unlink any higher, non-empty arrays
|
||||
SortedBin otherNonEmpty = lastNonEmpty.nextNonEmpty;
|
||||
lastNonEmpty.nextNonEmpty = null;
|
||||
|
||||
// now merge the content of these non-empty bins into the target bin
|
||||
while( firstNonEmpty != null )
|
||||
{
|
||||
while (firstNonEmpty != null) {
|
||||
// copy current minimum to target array
|
||||
SortedBin minBin = firstNonEmpty.getMinBin();
|
||||
al_t[tp] = minBin.lv;
|
||||
vla_t[tp++] = minBin.dropLowest();
|
||||
}
|
||||
|
||||
tp = tbin.binsize-cnt;
|
||||
tp = tbin.binsize - cnt;
|
||||
tbin.lp = tp; // new target low pointer
|
||||
tbin.lv = tbin.al[tp];
|
||||
tbin.nextNonEmpty = otherNonEmpty;
|
||||
firstNonEmpty = tbin;
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
public void clear() {
|
||||
size = 0;
|
||||
first = new SortedBin( 4, this );
|
||||
second = new SortedBin( 4, this );
|
||||
first = new SortedBin(4, this);
|
||||
second = new SortedBin(4, this);
|
||||
firstNonEmpty = null;
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public int getPeakSize()
|
||||
{
|
||||
public int getPeakSize() {
|
||||
return peaksize;
|
||||
}
|
||||
|
||||
public int getExtract( Object[] targetArray )
|
||||
{
|
||||
public int getExtract(Object[] targetArray) {
|
||||
int tsize = targetArray.length;
|
||||
int div = size / tsize + 1;
|
||||
int tp = 0;
|
||||
|
||||
int lpi = 0;
|
||||
SortedBin bin = firstNonEmpty;
|
||||
while( bin != null )
|
||||
{
|
||||
while (bin != null) {
|
||||
lpi += bin.lp;
|
||||
Object[] vlai = bin.vla;
|
||||
int n = bin.binsize;
|
||||
while (lpi < n)
|
||||
{
|
||||
while (lpi < n) {
|
||||
targetArray[tp++] = vlai[lpi];
|
||||
lpi += div;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,137 +11,108 @@ import java.util.Locale;
|
|||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
public class StackSampler extends Thread
|
||||
{
|
||||
private DateFormat df = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss,SSS", new Locale( "en", "US" ) );
|
||||
public class StackSampler extends Thread {
|
||||
private DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS", new Locale("en", "US"));
|
||||
private BufferedWriter bw;
|
||||
private Random rand = new Random();
|
||||
|
||||
private int interval;
|
||||
private int flushCnt = 0;
|
||||
|
||||
|
||||
private volatile boolean stopped;
|
||||
|
||||
public StackSampler( File logfile, int interval )
|
||||
{
|
||||
public StackSampler(File logfile, int interval) {
|
||||
this.interval = interval;
|
||||
try
|
||||
{
|
||||
bw = new BufferedWriter( new OutputStreamWriter( new FileOutputStream( logfile, true ) ) );
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
printError( "StackSampler: " + e.getMessage() );
|
||||
try {
|
||||
bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(logfile, true)));
|
||||
} catch (Exception e) {
|
||||
printError("StackSampler: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
protected void printError( String msg )
|
||||
{
|
||||
System.out.println( msg );
|
||||
protected void printError(String msg) {
|
||||
System.out.println(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
while( !stopped )
|
||||
{
|
||||
public void run() {
|
||||
while (!stopped) {
|
||||
dumpThreads();
|
||||
}
|
||||
if ( bw != null )
|
||||
{
|
||||
try
|
||||
{
|
||||
if (bw != null) {
|
||||
try {
|
||||
bw.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch( Exception e ) {}
|
||||
}
|
||||
}
|
||||
|
||||
public void dumpThreads()
|
||||
{
|
||||
try
|
||||
{
|
||||
int wait1 = rand.nextInt( interval );
|
||||
public void dumpThreads() {
|
||||
try {
|
||||
int wait1 = rand.nextInt(interval);
|
||||
int wait2 = interval - wait1;
|
||||
Thread.sleep( wait1 );
|
||||
StringBuilder sb = new StringBuilder( df.format( new Date() ) + " THREADDUMP\n" );
|
||||
Thread.sleep(wait1);
|
||||
StringBuilder sb = new StringBuilder(df.format(new Date()) + " THREADDUMP\n");
|
||||
Map<Thread, StackTraceElement[]> allThreads = Thread.getAllStackTraces();
|
||||
for ( Map.Entry<Thread, StackTraceElement[]> e : allThreads.entrySet() )
|
||||
{
|
||||
for (Map.Entry<Thread, StackTraceElement[]> e : allThreads.entrySet()) {
|
||||
Thread t = e.getKey();
|
||||
if ( t == Thread.currentThread() )
|
||||
{
|
||||
if (t == Thread.currentThread()) {
|
||||
continue; // not me
|
||||
}
|
||||
|
||||
StackTraceElement[] stack = e.getValue();
|
||||
if ( !matchesFilter( stack ) )
|
||||
{
|
||||
if (!matchesFilter(stack)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sb.append( " (ID=" ).append( t.getId() ).append( " \"" ).append( t.getName() ).append( "\" " ).append( t.getState() ).append( "\n" );
|
||||
for ( StackTraceElement line : stack )
|
||||
{
|
||||
sb.append( " " ).append( line.toString() ).append( "\n" );
|
||||
sb.append(" (ID=").append(t.getId()).append(" \"").append(t.getName()).append("\" ").append(t.getState()).append("\n");
|
||||
for (StackTraceElement line : stack) {
|
||||
sb.append(" ").append(line.toString()).append("\n");
|
||||
}
|
||||
sb.append( "\n" );
|
||||
sb.append("\n");
|
||||
}
|
||||
bw.write( sb.toString() );
|
||||
if ( flushCnt++ >= 0 )
|
||||
{
|
||||
bw.write(sb.toString());
|
||||
if (flushCnt++ >= 0) {
|
||||
flushCnt = 0;
|
||||
bw.flush();
|
||||
}
|
||||
Thread.sleep( wait2 );
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Thread.sleep(wait2);
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
public void close()
|
||||
{
|
||||
public void close() {
|
||||
stopped = true;
|
||||
interrupt();
|
||||
}
|
||||
|
||||
private boolean matchesFilter( StackTraceElement[] stack )
|
||||
{
|
||||
private boolean matchesFilter(StackTraceElement[] stack) {
|
||||
boolean positiveMatch = false;
|
||||
for ( StackTraceElement e : stack )
|
||||
{
|
||||
for (StackTraceElement e : stack) {
|
||||
String s = e.toString();
|
||||
if ( s.indexOf( "btools" ) >= 0 )
|
||||
{
|
||||
if (s.indexOf("btools") >= 0) {
|
||||
positiveMatch = true;
|
||||
}
|
||||
if ( s.indexOf( "Thread.sleep" ) >= 0 || s.indexOf( "PlainSocketImpl.socketAccept" ) >= 0 )
|
||||
{
|
||||
if (s.indexOf("Thread.sleep") >= 0 || s.indexOf("PlainSocketImpl.socketAccept") >= 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return positiveMatch;
|
||||
}
|
||||
|
||||
public static void main( String[] args ) throws Exception
|
||||
{
|
||||
System.out.println( "StackSampler..." );
|
||||
Class<?> clazz = Class.forName( args[0] );
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.out.println("StackSampler...");
|
||||
Class<?> clazz = Class.forName(args[0]);
|
||||
String[] args2 = new String[args.length - 1];
|
||||
for ( int i = 1; i < args.length; i++ )
|
||||
{
|
||||
for (int i = 1; i < args.length; i++) {
|
||||
args2[i - 1] = args[i];
|
||||
}
|
||||
StackSampler t = new StackSampler( new File( "stacks.log" ), 1000 );
|
||||
StackSampler t = new StackSampler(new File("stacks.log"), 1000);
|
||||
t.start();
|
||||
try
|
||||
{
|
||||
clazz.getMethod( "main", String[].class ).invoke( null, new Object[]{ args2 } );
|
||||
}
|
||||
finally
|
||||
{
|
||||
try {
|
||||
clazz.getMethod("main", String[].class).invoke(null, new Object[]{args2});
|
||||
} finally {
|
||||
t.close();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,53 +3,44 @@ package btools.util;
|
|||
/**
|
||||
* Some methods for String handling
|
||||
*/
|
||||
public class StringUtils
|
||||
{
|
||||
private static char[] xmlChr = new char[] { '&', '<', '>', '\'', '"', '\t', '\n', '\r' };
|
||||
private static String[] xmlEsc = new String[]{ "&", "<", ">", "'", """, "	", "
", "
" };
|
||||
public class StringUtils {
|
||||
private static char[] xmlChr = new char[]{'&', '<', '>', '\'', '"', '\t', '\n', '\r'};
|
||||
private static String[] xmlEsc = new String[]{"&", "<", ">", "'", """, "	", "
", "
"};
|
||||
|
||||
private static char[] jsnChr = new char[] { '\'', '"', '\\', '/' };
|
||||
private static String[] jsnEsc = new String[]{ "\\'", "\\\"", "\\\\", "\\/" };
|
||||
private static char[] jsnChr = new char[]{'\'', '"', '\\', '/'};
|
||||
private static String[] jsnEsc = new String[]{"\\'", "\\\"", "\\\\", "\\/"};
|
||||
|
||||
/**
|
||||
* Escape a literal to put into a json document
|
||||
*/
|
||||
public static String escapeJson( String s )
|
||||
{
|
||||
return escape( s, jsnChr, jsnEsc );
|
||||
public static String escapeJson(String s) {
|
||||
return escape(s, jsnChr, jsnEsc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape a literal to put into a xml document
|
||||
*/
|
||||
public static String escapeXml10( String s )
|
||||
{
|
||||
return escape( s, xmlChr, xmlEsc );
|
||||
public static String escapeXml10(String s) {
|
||||
return escape(s, xmlChr, xmlEsc);
|
||||
}
|
||||
|
||||
private static String escape( String s, char[] chr, String[] esc )
|
||||
{
|
||||
private static String escape(String s, char[] chr, String[] esc) {
|
||||
StringBuilder sb = null;
|
||||
for( int i=0; i<s.length(); i++ )
|
||||
{
|
||||
char c = s.charAt( i );
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
char c = s.charAt(i);
|
||||
int j = 0;
|
||||
while( j<chr.length )
|
||||
{
|
||||
if (c == chr[j])
|
||||
{
|
||||
if ( sb == null )
|
||||
{
|
||||
sb = new StringBuilder( s.substring( 0, i ) );
|
||||
}
|
||||
sb.append( esc[j] );
|
||||
break;
|
||||
}
|
||||
j++;
|
||||
while (j < chr.length) {
|
||||
if (c == chr[j]) {
|
||||
if (sb == null) {
|
||||
sb = new StringBuilder(s.substring(0, i));
|
||||
}
|
||||
sb.append(esc[j]);
|
||||
break;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
if ( sb != null && j==chr.length )
|
||||
{
|
||||
sb.append( c );
|
||||
if (sb != null && j == chr.length) {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return sb == null ? s : sb.toString();
|
||||
|
|
|
|||
|
|
@ -1,206 +1,180 @@
|
|||
package btools.util;
|
||||
|
||||
/**
|
||||
* TinyDenseLongMap implements the DenseLongMap interface
|
||||
* but actually is made for a medium count of non-dense keys
|
||||
*
|
||||
* It's used as a replacement for DenseLongMap where we
|
||||
* have limited memory and far less keys than maykey
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
public class TinyDenseLongMap extends DenseLongMap
|
||||
{
|
||||
private long[][] al;
|
||||
private int[] pa;
|
||||
private int size = 0;
|
||||
private int _maxKeepExponent = 14; // the maximum exponent to keep the invalid arrays
|
||||
|
||||
protected static final int MAXLISTS = 31; // enough for size Integer.MAX_VALUE
|
||||
|
||||
public TinyDenseLongMap()
|
||||
{
|
||||
super();
|
||||
|
||||
// pointer array
|
||||
pa = new int[MAXLISTS];
|
||||
|
||||
// allocate key lists
|
||||
al = new long[MAXLISTS][];
|
||||
al[0] = new long[1]; // make the first array (the transient buffer)
|
||||
|
||||
// same for the values
|
||||
vla = new byte[MAXLISTS][];
|
||||
vla[0] = new byte[1];
|
||||
}
|
||||
|
||||
|
||||
private byte[][] vla; // value list array
|
||||
|
||||
private void fillReturnValue(byte[] rv, int idx, int p )
|
||||
{
|
||||
rv[0] = vla[idx][p];
|
||||
if ( rv.length == 2 )
|
||||
{
|
||||
vla[idx][p] = rv[1];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put( long id, int value )
|
||||
{
|
||||
byte[] rv = new byte[2];
|
||||
rv[1] = (byte)value;
|
||||
if ( contains( id, rv ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
vla[0][0] = (byte)value;
|
||||
_add( id );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the byte for the given id
|
||||
* @param id the key to query
|
||||
* @return the object
|
||||
* @exception IllegalArgumentException if id is unknown
|
||||
*/
|
||||
@Override
|
||||
public int getInt( long id )
|
||||
{
|
||||
byte[] rv = new byte[1];
|
||||
if ( contains( id, rv ) )
|
||||
{
|
||||
return rv[0];
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
private boolean _add( long id )
|
||||
{
|
||||
if ( size == Integer.MAX_VALUE )
|
||||
{
|
||||
throw new IllegalArgumentException( "cannot grow beyond size Integer.MAX_VALUE" );
|
||||
}
|
||||
|
||||
// put the new entry in the first array
|
||||
al[0][0] = id;
|
||||
|
||||
// determine the first empty array
|
||||
int bp = size++; // treat size as bitpattern
|
||||
int idx = 1;
|
||||
int n = 1;
|
||||
|
||||
pa[0] = 1;
|
||||
pa[1] = 1;
|
||||
|
||||
while ( (bp&1) == 1 )
|
||||
{
|
||||
bp >>= 1;
|
||||
pa[idx++] = n;
|
||||
n <<= 1;
|
||||
}
|
||||
|
||||
// create it if not existant
|
||||
if ( al[idx] == null )
|
||||
{
|
||||
al[idx] = new long[n];
|
||||
vla[idx] = new byte[n];
|
||||
}
|
||||
|
||||
// now merge the contents of arrays 0...idx-1 into idx
|
||||
while ( n > 0 )
|
||||
{
|
||||
long maxId = 0;
|
||||
int maxIdx = -1;
|
||||
|
||||
for ( int i=0; i<idx; i++ )
|
||||
{
|
||||
int p = pa[i];
|
||||
if ( p > 0 )
|
||||
{
|
||||
long currentId = al[i][p-1];
|
||||
if ( maxIdx < 0 || currentId > maxId )
|
||||
{
|
||||
maxIdx = i;
|
||||
maxId = currentId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// current maximum found, copy to target array
|
||||
if ( n < al[idx].length && maxId == al[idx][n] )
|
||||
{
|
||||
throw new IllegalArgumentException( "duplicate key found in late check: " + maxId );
|
||||
}
|
||||
--n;
|
||||
al[idx][n] = maxId;
|
||||
vla[idx][n] = vla[maxIdx][pa[maxIdx]-1];
|
||||
|
||||
--pa[maxIdx];
|
||||
}
|
||||
|
||||
// de-allocate empty arrays of a certain size (fix at 64kByte)
|
||||
while ( idx-- > _maxKeepExponent )
|
||||
{
|
||||
al[idx] = null;
|
||||
vla[idx] = null;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private boolean contains( long id, byte[] rv )
|
||||
{
|
||||
// determine the first empty array
|
||||
int bp = size; // treat size as bitpattern
|
||||
int idx = 1;
|
||||
|
||||
while ( bp != 0 )
|
||||
{
|
||||
if ( (bp&1) == 1 )
|
||||
{
|
||||
// array at idx is valid, check
|
||||
if ( contains( idx, id, rv ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
bp >>= 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// does sorted array "a" contain "id" ?
|
||||
private boolean contains( int idx, long id, byte[] rv )
|
||||
{
|
||||
long[] a = al[idx];
|
||||
int offset = a.length;
|
||||
int n = 0;
|
||||
|
||||
while ( (offset >>= 1) > 0 )
|
||||
{
|
||||
int nn = n + offset;
|
||||
if ( a[nn] <= id )
|
||||
{
|
||||
n = nn;
|
||||
}
|
||||
}
|
||||
if ( a[n] == id )
|
||||
{
|
||||
if ( rv != null )
|
||||
{
|
||||
fillReturnValue( rv, idx, n );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
package btools.util;
|
||||
|
||||
/**
|
||||
* TinyDenseLongMap implements the DenseLongMap interface
|
||||
* but actually is made for a medium count of non-dense keys
|
||||
* <p>
|
||||
* It's used as a replacement for DenseLongMap where we
|
||||
* have limited memory and far less keys than maykey
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
public class TinyDenseLongMap extends DenseLongMap {
|
||||
private long[][] al;
|
||||
private int[] pa;
|
||||
private int size = 0;
|
||||
private int _maxKeepExponent = 14; // the maximum exponent to keep the invalid arrays
|
||||
|
||||
protected static final int MAXLISTS = 31; // enough for size Integer.MAX_VALUE
|
||||
|
||||
public TinyDenseLongMap() {
|
||||
super();
|
||||
|
||||
// pointer array
|
||||
pa = new int[MAXLISTS];
|
||||
|
||||
// allocate key lists
|
||||
al = new long[MAXLISTS][];
|
||||
al[0] = new long[1]; // make the first array (the transient buffer)
|
||||
|
||||
// same for the values
|
||||
vla = new byte[MAXLISTS][];
|
||||
vla[0] = new byte[1];
|
||||
}
|
||||
|
||||
|
||||
private byte[][] vla; // value list array
|
||||
|
||||
private void fillReturnValue(byte[] rv, int idx, int p) {
|
||||
rv[0] = vla[idx][p];
|
||||
if (rv.length == 2) {
|
||||
vla[idx][p] = rv[1];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(long id, int value) {
|
||||
byte[] rv = new byte[2];
|
||||
rv[1] = (byte) value;
|
||||
if (contains(id, rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
vla[0][0] = (byte) value;
|
||||
_add(id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the byte for the given id
|
||||
*
|
||||
* @param id the key to query
|
||||
* @return the object
|
||||
* @throws IllegalArgumentException if id is unknown
|
||||
*/
|
||||
@Override
|
||||
public int getInt(long id) {
|
||||
byte[] rv = new byte[1];
|
||||
if (contains(id, rv)) {
|
||||
return rv[0];
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
private boolean _add(long id) {
|
||||
if (size == Integer.MAX_VALUE) {
|
||||
throw new IllegalArgumentException("cannot grow beyond size Integer.MAX_VALUE");
|
||||
}
|
||||
|
||||
// put the new entry in the first array
|
||||
al[0][0] = id;
|
||||
|
||||
// determine the first empty array
|
||||
int bp = size++; // treat size as bitpattern
|
||||
int idx = 1;
|
||||
int n = 1;
|
||||
|
||||
pa[0] = 1;
|
||||
pa[1] = 1;
|
||||
|
||||
while ((bp & 1) == 1) {
|
||||
bp >>= 1;
|
||||
pa[idx++] = n;
|
||||
n <<= 1;
|
||||
}
|
||||
|
||||
// create it if not existant
|
||||
if (al[idx] == null) {
|
||||
al[idx] = new long[n];
|
||||
vla[idx] = new byte[n];
|
||||
}
|
||||
|
||||
// now merge the contents of arrays 0...idx-1 into idx
|
||||
while (n > 0) {
|
||||
long maxId = 0;
|
||||
int maxIdx = -1;
|
||||
|
||||
for (int i = 0; i < idx; i++) {
|
||||
int p = pa[i];
|
||||
if (p > 0) {
|
||||
long currentId = al[i][p - 1];
|
||||
if (maxIdx < 0 || currentId > maxId) {
|
||||
maxIdx = i;
|
||||
maxId = currentId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// current maximum found, copy to target array
|
||||
if (n < al[idx].length && maxId == al[idx][n]) {
|
||||
throw new IllegalArgumentException("duplicate key found in late check: " + maxId);
|
||||
}
|
||||
--n;
|
||||
al[idx][n] = maxId;
|
||||
vla[idx][n] = vla[maxIdx][pa[maxIdx] - 1];
|
||||
|
||||
--pa[maxIdx];
|
||||
}
|
||||
|
||||
// de-allocate empty arrays of a certain size (fix at 64kByte)
|
||||
while (idx-- > _maxKeepExponent) {
|
||||
al[idx] = null;
|
||||
vla[idx] = null;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private boolean contains(long id, byte[] rv) {
|
||||
// determine the first empty array
|
||||
int bp = size; // treat size as bitpattern
|
||||
int idx = 1;
|
||||
|
||||
while (bp != 0) {
|
||||
if ((bp & 1) == 1) {
|
||||
// array at idx is valid, check
|
||||
if (contains(idx, id, rv)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
bp >>= 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// does sorted array "a" contain "id" ?
|
||||
private boolean contains(int idx, long id, byte[] rv) {
|
||||
long[] a = al[idx];
|
||||
int offset = a.length;
|
||||
int n = 0;
|
||||
|
||||
while ((offset >>= 1) > 0) {
|
||||
int nn = n + offset;
|
||||
if (a[nn] <= id) {
|
||||
n = nn;
|
||||
}
|
||||
}
|
||||
if (a[n] == id) {
|
||||
if (rv != null) {
|
||||
fillReturnValue(rv, idx, n);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,61 +3,49 @@ package btools.util;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class BitCoderContextTest
|
||||
{
|
||||
public class BitCoderContextTest {
|
||||
@Test
|
||||
public void varBitsEncodeDecodeTest()
|
||||
{
|
||||
public void varBitsEncodeDecodeTest() {
|
||||
byte[] ab = new byte[581969];
|
||||
BitCoderContext ctx = new BitCoderContext( ab );
|
||||
for ( int i = 0; i < 31; i++ )
|
||||
{
|
||||
ctx.encodeVarBits( (1<<i)+3 );
|
||||
BitCoderContext ctx = new BitCoderContext(ab);
|
||||
for (int i = 0; i < 31; i++) {
|
||||
ctx.encodeVarBits((1 << i) + 3);
|
||||
}
|
||||
for ( int i = 0; i < 100000; i+=13 )
|
||||
{
|
||||
ctx.encodeVarBits( i );
|
||||
for (int i = 0; i < 100000; i += 13) {
|
||||
ctx.encodeVarBits(i);
|
||||
}
|
||||
ctx.closeAndGetEncodedLength();
|
||||
ctx = new BitCoderContext( ab );
|
||||
ctx = new BitCoderContext(ab);
|
||||
|
||||
for ( int i = 0; i < 31; i++ )
|
||||
{
|
||||
for (int i = 0; i < 31; i++) {
|
||||
int value = ctx.decodeVarBits();
|
||||
int v0 = (1<<i)+3;
|
||||
Assert.assertTrue( "value mismatch value=" + value + "v0=" + v0, v0 == value );
|
||||
int v0 = (1 << i) + 3;
|
||||
Assert.assertTrue("value mismatch value=" + value + "v0=" + v0, v0 == value);
|
||||
}
|
||||
for ( int i = 0; i < 100000; i+=13 )
|
||||
{
|
||||
for (int i = 0; i < 100000; i += 13) {
|
||||
int value = ctx.decodeVarBits();
|
||||
Assert.assertTrue( "value mismatch i=" + i + "v=" + value, value == i );
|
||||
Assert.assertTrue("value mismatch i=" + i + "v=" + value, value == i);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void boundedEncodeDecodeTest()
|
||||
{
|
||||
public void boundedEncodeDecodeTest() {
|
||||
byte[] ab = new byte[581969];
|
||||
BitCoderContext ctx = new BitCoderContext( ab );
|
||||
for ( int max = 1; max < 1000; max++ )
|
||||
{
|
||||
for ( int val = 0; val <= max; val++ )
|
||||
{
|
||||
ctx.encodeBounded( max, val );
|
||||
BitCoderContext ctx = new BitCoderContext(ab);
|
||||
for (int max = 1; max < 1000; max++) {
|
||||
for (int val = 0; val <= max; val++) {
|
||||
ctx.encodeBounded(max, val);
|
||||
}
|
||||
}
|
||||
ctx.closeAndGetEncodedLength();
|
||||
|
||||
ctx = new BitCoderContext( ab );
|
||||
ctx = new BitCoderContext(ab);
|
||||
|
||||
for ( int max = 1; max < 1000; max++ )
|
||||
{
|
||||
for ( int val = 0; val <= max; val++ )
|
||||
{
|
||||
int valDecoded = ctx.decodeBounded( max );
|
||||
if ( valDecoded != val )
|
||||
{
|
||||
Assert.fail( "mismatch at max=" + max + " " + valDecoded + "<>" + val );
|
||||
for (int max = 1; max < 1000; max++) {
|
||||
for (int val = 0; val <= max; val++) {
|
||||
int valDecoded = ctx.decodeBounded(max);
|
||||
if (valDecoded != val) {
|
||||
Assert.fail("mismatch at max=" + max + " " + valDecoded + "<>" + val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,23 +6,19 @@ import java.util.HashSet;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ByteDataIOTest
|
||||
{
|
||||
public class ByteDataIOTest {
|
||||
@Test
|
||||
public void varLengthEncodeDecodeTest()
|
||||
{
|
||||
byte[] ab = new byte[4000];
|
||||
ByteDataWriter w = new ByteDataWriter( ab );
|
||||
for( int i=0; i<1000; i++ )
|
||||
{
|
||||
w.writeVarLengthUnsigned( i );
|
||||
public void varLengthEncodeDecodeTest() {
|
||||
byte[] ab = new byte[4000];
|
||||
ByteDataWriter w = new ByteDataWriter(ab);
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
w.writeVarLengthUnsigned(i);
|
||||
}
|
||||
ByteDataReader r = new ByteDataReader( ab );
|
||||
|
||||
for( int i=0; i<1000; i++ )
|
||||
{
|
||||
ByteDataReader r = new ByteDataReader(ab);
|
||||
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
int value = r.readVarLengthUnsigned();
|
||||
Assert.assertTrue( "value mismatch", value == i );
|
||||
Assert.assertTrue("value mismatch", value == i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ import org.junit.Test;
|
|||
|
||||
public class CheapAngleMeterTest {
|
||||
static int toOsmLon(double lon) {
|
||||
return (int)( ( lon + 180. ) / CheapRuler.ILATLNG_TO_LATLNG + 0.5);
|
||||
return (int) ((lon + 180.) / CheapRuler.ILATLNG_TO_LATLNG + 0.5);
|
||||
}
|
||||
|
||||
static int toOsmLat(double lat) {
|
||||
return (int)( ( lat + 90. ) / CheapRuler.ILATLNG_TO_LATLNG + 0.5);
|
||||
return (int) ((lat + 90.) / CheapRuler.ILATLNG_TO_LATLNG + 0.5);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -79,40 +79,38 @@ public class CheapAngleMeterTest {
|
|||
@Test
|
||||
public void testCalcAngle2() {
|
||||
CheapAngleMeter am = new CheapAngleMeter();
|
||||
int lon1 = 8500000;
|
||||
int lon1 = 8500000;
|
||||
int lat1 = 49500000;
|
||||
|
||||
double[] lonlat2m = CheapRuler.getLonLatToMeterScales( lat1 );
|
||||
|
||||
double[] lonlat2m = CheapRuler.getLonLatToMeterScales(lat1);
|
||||
double lon2m = lonlat2m[0];
|
||||
double lat2m = lonlat2m[1];
|
||||
|
||||
for ( double afrom = -175.; afrom < 180.; afrom += 10. )
|
||||
{
|
||||
double sf = Math.sin( afrom * Math.PI / 180. );
|
||||
double cf = Math.cos( afrom * Math.PI / 180. );
|
||||
|
||||
int lon0 = (int)(0.5+lon1 - cf*150./lon2m );
|
||||
int lat0 = (int)(0.5+lat1 - sf*150./lat2m );
|
||||
|
||||
for ( double ato = -177.; ato < 180.; ato += 10. )
|
||||
{
|
||||
double st = Math.sin( ato * Math.PI / 180. );
|
||||
double ct = Math.cos( ato * Math.PI / 180. );
|
||||
|
||||
int lon2 = (int)(0.5+lon1 + ct*250./lon2m);
|
||||
int lat2 = (int)(0.5+lat1 + st*250./lat2m);
|
||||
|
||||
for (double afrom = -175.; afrom < 180.; afrom += 10.) {
|
||||
double sf = Math.sin(afrom * Math.PI / 180.);
|
||||
double cf = Math.cos(afrom * Math.PI / 180.);
|
||||
|
||||
int lon0 = (int) (0.5 + lon1 - cf * 150. / lon2m);
|
||||
int lat0 = (int) (0.5 + lat1 - sf * 150. / lat2m);
|
||||
|
||||
for (double ato = -177.; ato < 180.; ato += 10.) {
|
||||
double st = Math.sin(ato * Math.PI / 180.);
|
||||
double ct = Math.cos(ato * Math.PI / 180.);
|
||||
|
||||
int lon2 = (int) (0.5 + lon1 + ct * 250. / lon2m);
|
||||
int lat2 = (int) (0.5 + lat1 + st * 250. / lat2m);
|
||||
|
||||
double a1 = afrom - ato;
|
||||
if ( a1 > 180. ) a1 -= 360.;
|
||||
if ( a1 < -180. ) a1 += 360.;
|
||||
double a2 = am.calcAngle( lon0, lat0, lon1, lat1, lon2, lat2 );
|
||||
double c1 = Math.cos( a1 * Math.PI / 180. );
|
||||
if (a1 > 180.) a1 -= 360.;
|
||||
if (a1 < -180.) a1 += 360.;
|
||||
double a2 = am.calcAngle(lon0, lat0, lon1, lat1, lon2, lat2);
|
||||
double c1 = Math.cos(a1 * Math.PI / 180.);
|
||||
double c2 = am.getCosAngle();
|
||||
|
||||
assertEquals( "angle mismatch for afrom=" + afrom + " ato=" + ato, a1, a2, 0.2 );
|
||||
assertEquals( "cosinus mismatch for afrom=" + afrom + " ato=" + ato, c1, c2, 0.001 );
|
||||
assertEquals("angle mismatch for afrom=" + afrom + " ato=" + ato, a1, a2, 0.2);
|
||||
assertEquals("cosinus mismatch for afrom=" + afrom + " ato=" + ato, c1, c2, 0.001);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,62 +6,54 @@ import java.util.HashMap;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class CompactMapTest
|
||||
{
|
||||
public class CompactMapTest {
|
||||
@Test
|
||||
public void hashMapComparisonTest()
|
||||
{
|
||||
hashMapComparison( 0, 1 );
|
||||
hashMapComparison( 1, 1 );
|
||||
hashMapComparison( 2, 2 );
|
||||
hashMapComparison( 3, 3 );
|
||||
hashMapComparison( 4, 4 );
|
||||
hashMapComparison( 5, 5 );
|
||||
hashMapComparison( 7, 10 );
|
||||
hashMapComparison( 8, 10 );
|
||||
hashMapComparison( 10000, 20000 );
|
||||
public void hashMapComparisonTest() {
|
||||
hashMapComparison(0, 1);
|
||||
hashMapComparison(1, 1);
|
||||
hashMapComparison(2, 2);
|
||||
hashMapComparison(3, 3);
|
||||
hashMapComparison(4, 4);
|
||||
hashMapComparison(5, 5);
|
||||
hashMapComparison(7, 10);
|
||||
hashMapComparison(8, 10);
|
||||
hashMapComparison(10000, 20000);
|
||||
}
|
||||
|
||||
private void hashMapComparison( int mapsize, int trycount )
|
||||
{
|
||||
Random rand = new Random( 12345 );
|
||||
HashMap<Long,String> hmap = new HashMap<Long,String>();
|
||||
private void hashMapComparison(int mapsize, int trycount) {
|
||||
Random rand = new Random(12345);
|
||||
HashMap<Long, String> hmap = new HashMap<Long, String>();
|
||||
CompactLongMap<String> cmap_slow = new CompactLongMap<String>();
|
||||
CompactLongMap<String> cmap_fast = new CompactLongMap<String>();
|
||||
|
||||
for( int i=0; i<mapsize; i++ )
|
||||
{
|
||||
for (int i = 0; i < mapsize; i++) {
|
||||
String s = "" + i;
|
||||
long k = mapsize < 10 ? i : rand.nextInt( 20000 );
|
||||
Long KK = new Long( k );
|
||||
long k = mapsize < 10 ? i : rand.nextInt(20000);
|
||||
Long KK = new Long(k);
|
||||
|
||||
if ( !hmap.containsKey( KK ) )
|
||||
{
|
||||
hmap.put( KK, s );
|
||||
cmap_slow.put( k, s );
|
||||
cmap_fast.fastPut( k, s );
|
||||
if (!hmap.containsKey(KK)) {
|
||||
hmap.put(KK, s);
|
||||
cmap_slow.put(k, s);
|
||||
cmap_fast.fastPut(k, s);
|
||||
}
|
||||
}
|
||||
|
||||
for( int i=0; i<trycount*2; i++ )
|
||||
{
|
||||
if ( i == trycount )
|
||||
{
|
||||
cmap_slow = new FrozenLongMap<String>( cmap_slow );
|
||||
cmap_fast = new FrozenLongMap<String>( cmap_fast );
|
||||
for (int i = 0; i < trycount * 2; i++) {
|
||||
if (i == trycount) {
|
||||
cmap_slow = new FrozenLongMap<String>(cmap_slow);
|
||||
cmap_fast = new FrozenLongMap<String>(cmap_fast);
|
||||
}
|
||||
long k = mapsize < 10 ? i : rand.nextInt( 20000 );
|
||||
Long KK = new Long( k );
|
||||
String s = hmap.get( KK );
|
||||
long k = mapsize < 10 ? i : rand.nextInt(20000);
|
||||
Long KK = new Long(k);
|
||||
String s = hmap.get(KK);
|
||||
|
||||
boolean contained = hmap.containsKey( KK );
|
||||
Assert.assertTrue( "containsKey missmatch (slow)", contained == cmap_slow.contains( k ) );
|
||||
Assert.assertTrue( "containsKey missmatch (fast)", contained == cmap_fast.contains( k ) );
|
||||
|
||||
if ( contained )
|
||||
{
|
||||
Assert.assertEquals( "object missmatch (fast)", s, cmap_fast.get( k ) );
|
||||
Assert.assertEquals( "object missmatch (slow)", s, cmap_slow.get( k ) );
|
||||
boolean contained = hmap.containsKey(KK);
|
||||
Assert.assertTrue("containsKey missmatch (slow)", contained == cmap_slow.contains(k));
|
||||
Assert.assertTrue("containsKey missmatch (fast)", contained == cmap_fast.contains(k));
|
||||
|
||||
if (contained) {
|
||||
Assert.assertEquals("object missmatch (fast)", s, cmap_fast.get(k));
|
||||
Assert.assertEquals("object missmatch (slow)", s, cmap_slow.get(k));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,55 +6,48 @@ import java.util.HashSet;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class CompactSetTest
|
||||
{
|
||||
public class CompactSetTest {
|
||||
@Test
|
||||
public void hashSetComparisonTest()
|
||||
{
|
||||
hashSetComparison( 0, 1 );
|
||||
hashSetComparison( 1, 1 );
|
||||
hashSetComparison( 2, 2 );
|
||||
hashSetComparison( 3, 3 );
|
||||
hashSetComparison( 4, 4 );
|
||||
hashSetComparison( 5, 5 );
|
||||
hashSetComparison( 7, 10 );
|
||||
hashSetComparison( 8, 10 );
|
||||
hashSetComparison( 10000, 20000 );
|
||||
public void hashSetComparisonTest() {
|
||||
hashSetComparison(0, 1);
|
||||
hashSetComparison(1, 1);
|
||||
hashSetComparison(2, 2);
|
||||
hashSetComparison(3, 3);
|
||||
hashSetComparison(4, 4);
|
||||
hashSetComparison(5, 5);
|
||||
hashSetComparison(7, 10);
|
||||
hashSetComparison(8, 10);
|
||||
hashSetComparison(10000, 20000);
|
||||
}
|
||||
|
||||
private void hashSetComparison( int setsize, int trycount )
|
||||
{
|
||||
Random rand = new Random( 12345 );
|
||||
private void hashSetComparison(int setsize, int trycount) {
|
||||
Random rand = new Random(12345);
|
||||
HashSet<Long> hset = new HashSet<Long>();
|
||||
CompactLongSet cset_slow = new CompactLongSet();
|
||||
CompactLongSet cset_fast = new CompactLongSet();
|
||||
|
||||
for( int i=0; i<setsize; i++ )
|
||||
{
|
||||
long k = setsize < 10 ? i : rand.nextInt( 20000 );
|
||||
Long KK = new Long( k );
|
||||
for (int i = 0; i < setsize; i++) {
|
||||
long k = setsize < 10 ? i : rand.nextInt(20000);
|
||||
Long KK = new Long(k);
|
||||
|
||||
if ( !hset.contains( KK ) )
|
||||
{
|
||||
hset.add( KK );
|
||||
cset_slow.add( k );
|
||||
cset_fast.fastAdd( k );
|
||||
if (!hset.contains(KK)) {
|
||||
hset.add(KK);
|
||||
cset_slow.add(k);
|
||||
cset_fast.fastAdd(k);
|
||||
}
|
||||
}
|
||||
|
||||
for( int i=0; i<trycount*2; i++ )
|
||||
{
|
||||
if ( i == trycount )
|
||||
{
|
||||
cset_slow = new FrozenLongSet( cset_slow );
|
||||
cset_fast = new FrozenLongSet( cset_fast );
|
||||
for (int i = 0; i < trycount * 2; i++) {
|
||||
if (i == trycount) {
|
||||
cset_slow = new FrozenLongSet(cset_slow);
|
||||
cset_fast = new FrozenLongSet(cset_fast);
|
||||
}
|
||||
long k = setsize < 10 ? i : rand.nextInt( 20000 );
|
||||
Long KK = new Long( k );
|
||||
long k = setsize < 10 ? i : rand.nextInt(20000);
|
||||
Long KK = new Long(k);
|
||||
|
||||
boolean contained = hset.contains( KK );
|
||||
Assert.assertTrue( "contains missmatch (slow)", contained == cset_slow.contains( k ) );
|
||||
Assert.assertTrue( "contains missmatch (fast)", contained == cset_fast.contains( k ) );
|
||||
boolean contained = hset.contains(KK);
|
||||
Assert.assertTrue("contains missmatch (slow)", contained == cset_slow.contains(k));
|
||||
Assert.assertTrue("contains missmatch (fast)", contained == cset_fast.contains(k));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,107 +7,94 @@ import java.util.HashSet;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class DenseLongMapTest
|
||||
{
|
||||
public class DenseLongMapTest {
|
||||
@Test
|
||||
public void hashMapComparisonTest()
|
||||
{
|
||||
hashMapComparison( 100000, 100000, 100000 );
|
||||
hashMapComparison( 100000, 100000, 13000000 );
|
||||
public void hashMapComparisonTest() {
|
||||
hashMapComparison(100000, 100000, 100000);
|
||||
hashMapComparison(100000, 100000, 13000000);
|
||||
}
|
||||
|
||||
private void hashMapComparison( int mapsize, int trycount, long keyrange )
|
||||
{
|
||||
Random rand = new Random( 12345 );
|
||||
HashMap<Long,Integer> hmap = new HashMap<Long,Integer>();
|
||||
DenseLongMap dmap = new DenseLongMap( 512 );
|
||||
private void hashMapComparison(int mapsize, int trycount, long keyrange) {
|
||||
Random rand = new Random(12345);
|
||||
HashMap<Long, Integer> hmap = new HashMap<Long, Integer>();
|
||||
DenseLongMap dmap = new DenseLongMap(512);
|
||||
|
||||
for( int i=0; i<mapsize; i++ )
|
||||
{
|
||||
int value = i%255;
|
||||
long k = (long)(rand.nextDouble()*keyrange);
|
||||
Long KK = new Long( k );
|
||||
for (int i = 0; i < mapsize; i++) {
|
||||
int value = i % 255;
|
||||
long k = (long) (rand.nextDouble() * keyrange);
|
||||
Long KK = new Long(k);
|
||||
|
||||
hmap.put( KK, new Integer ( value ) );
|
||||
dmap.put( k, value ); // duplicate puts allowed!
|
||||
hmap.put(KK, new Integer(value));
|
||||
dmap.put(k, value); // duplicate puts allowed!
|
||||
}
|
||||
|
||||
for( int i=0; i<trycount; i++ )
|
||||
{
|
||||
long k = (long)(rand.nextDouble()*keyrange);
|
||||
Long KK = new Long( k );
|
||||
Integer VV = hmap.get( KK );
|
||||
for (int i = 0; i < trycount; i++) {
|
||||
long k = (long) (rand.nextDouble() * keyrange);
|
||||
Long KK = new Long(k);
|
||||
Integer VV = hmap.get(KK);
|
||||
int hvalue = VV == null ? -1 : VV.intValue();
|
||||
int dvalue = dmap.getInt( k );
|
||||
int dvalue = dmap.getInt(k);
|
||||
|
||||
if ( hvalue != dvalue )
|
||||
{
|
||||
Assert.fail( "value missmatch for key " + k + " hashmap=" + hvalue + " densemap=" + dvalue );
|
||||
if (hvalue != dvalue) {
|
||||
Assert.fail("value missmatch for key " + k + " hashmap=" + hvalue + " densemap=" + dvalue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void oneBitTest()
|
||||
{
|
||||
public void oneBitTest() {
|
||||
int keyrange = 300000;
|
||||
int mapputs = 100000;
|
||||
int trycount = 100000;
|
||||
|
||||
Random rand = new Random( 12345 );
|
||||
Random rand = new Random(12345);
|
||||
HashSet<Long> hset = new HashSet<Long>();
|
||||
|
||||
DenseLongMap dmap = new DenseLongMap( 512 );
|
||||
for( int i=0; i<mapputs; i++ )
|
||||
{
|
||||
long k = (long)(rand.nextDouble()*keyrange);
|
||||
hset.add( new Long( k ) );
|
||||
dmap.put( k, 0 );
|
||||
DenseLongMap dmap = new DenseLongMap(512);
|
||||
for (int i = 0; i < mapputs; i++) {
|
||||
long k = (long) (rand.nextDouble() * keyrange);
|
||||
hset.add(new Long(k));
|
||||
dmap.put(k, 0);
|
||||
}
|
||||
for( int i=0; i<trycount; i++ )
|
||||
{
|
||||
long k = (long)(rand.nextDouble()*keyrange);
|
||||
boolean hcontains = hset.contains( new Long( k ) );
|
||||
boolean dcontains = dmap.getInt( k ) == 0;
|
||||
for (int i = 0; i < trycount; i++) {
|
||||
long k = (long) (rand.nextDouble() * keyrange);
|
||||
boolean hcontains = hset.contains(new Long(k));
|
||||
boolean dcontains = dmap.getInt(k) == 0;
|
||||
|
||||
if ( hcontains != dcontains )
|
||||
{
|
||||
Assert.fail( "value missmatch for key " + k + " hashset=" + hcontains + " densemap=" + dcontains );
|
||||
if (hcontains != dcontains) {
|
||||
Assert.fail("value missmatch for key " + k + " hashset=" + hcontains + " densemap=" + dcontains);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @Test - memory test disabled for load reasons
|
||||
public void memoryUsageTest()
|
||||
{
|
||||
public void memoryUsageTest() {
|
||||
int keyrange = 32000000;
|
||||
int mapputs = keyrange * 2;
|
||||
|
||||
Random rand = new Random( 12345 );
|
||||
DenseLongMap dmap = new DenseLongMap( 6 );
|
||||
Random rand = new Random(12345);
|
||||
DenseLongMap dmap = new DenseLongMap(6);
|
||||
|
||||
System.gc();
|
||||
long mem1 = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
|
||||
|
||||
for( int i=0; i<mapputs; i++ )
|
||||
{
|
||||
int value = i%63;
|
||||
long k = (long)(rand.nextDouble()*keyrange);
|
||||
dmap.put( k, value );
|
||||
for (int i = 0; i < mapputs; i++) {
|
||||
int value = i % 63;
|
||||
long k = (long) (rand.nextDouble() * keyrange);
|
||||
dmap.put(k, value);
|
||||
}
|
||||
|
||||
System.gc();
|
||||
long mem2 = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
|
||||
|
||||
long memusage = mem2-mem1;
|
||||
long memusage = mem2 - mem1;
|
||||
|
||||
if ( memusage > (keyrange/8)*7 )
|
||||
{
|
||||
Assert.fail( "memory usage too high: " + memusage + " for keyrange " + keyrange );
|
||||
if (memusage > (keyrange / 8) * 7) {
|
||||
Assert.fail("memory usage too high: " + memusage + " for keyrange " + keyrange);
|
||||
}
|
||||
|
||||
// need to use the map again for valid memory measure
|
||||
Assert.assertTrue( "out of range test", dmap.getInt(-1) == -1 );
|
||||
Assert.assertTrue("out of range test", dmap.getInt(-1) == -1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,57 +6,44 @@ import java.io.*;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class MixCoderTest
|
||||
{
|
||||
public class MixCoderTest {
|
||||
@Test
|
||||
public void mixEncodeDecodeTest() throws IOException
|
||||
{
|
||||
public void mixEncodeDecodeTest() throws IOException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
MixCoderDataOutputStream mco = new MixCoderDataOutputStream( baos );
|
||||
MixCoderDataOutputStream mco = new MixCoderDataOutputStream(baos);
|
||||
MixCoderDataInputStream mci = null;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
Random rnd = new Random( 1234 );
|
||||
for( int i=0; i<1500; i++ )
|
||||
{
|
||||
checkEncodeDecode( rnd.nextInt( 3800 ), mco, mci );
|
||||
for (; ; ) {
|
||||
Random rnd = new Random(1234);
|
||||
for (int i = 0; i < 1500; i++) {
|
||||
checkEncodeDecode(rnd.nextInt(3800), mco, mci);
|
||||
}
|
||||
for( int i=0; i<1500; i++ )
|
||||
{
|
||||
checkEncodeDecode( rnd.nextInt( 35 ), mco, mci );
|
||||
for (int i = 0; i < 1500; i++) {
|
||||
checkEncodeDecode(rnd.nextInt(35), mco, mci);
|
||||
}
|
||||
for( int i=0; i<1500; i++ )
|
||||
{
|
||||
checkEncodeDecode( 0, mco, mci );
|
||||
for (int i = 0; i < 1500; i++) {
|
||||
checkEncodeDecode(0, mco, mci);
|
||||
}
|
||||
for( int i=0; i<1500; i++ )
|
||||
{
|
||||
checkEncodeDecode( 1000, mco, mci );
|
||||
for (int i = 0; i < 1500; i++) {
|
||||
checkEncodeDecode(1000, mco, mci);
|
||||
}
|
||||
|
||||
if ( mco != null )
|
||||
{
|
||||
if (mco != null) {
|
||||
mco.close();
|
||||
mco = null;
|
||||
mci = new MixCoderDataInputStream( new ByteArrayInputStream( baos.toByteArray() ) );
|
||||
}
|
||||
else break;
|
||||
mci = new MixCoderDataInputStream(new ByteArrayInputStream(baos.toByteArray()));
|
||||
} else break;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkEncodeDecode( int v, MixCoderDataOutputStream mco, MixCoderDataInputStream mci ) throws IOException
|
||||
{
|
||||
if ( mco != null )
|
||||
{
|
||||
mco.writeMixed( v );
|
||||
private void checkEncodeDecode(int v, MixCoderDataOutputStream mco, MixCoderDataInputStream mci) throws IOException {
|
||||
if (mco != null) {
|
||||
mco.writeMixed(v);
|
||||
}
|
||||
if ( mci != null )
|
||||
{
|
||||
if (mci != null) {
|
||||
long vv = mci.readMixed();
|
||||
if ( vv != v )
|
||||
{
|
||||
Assert.assertTrue( "value mismatch: v=" + v + " vv=" + vv, false );
|
||||
if (vv != v) {
|
||||
Assert.assertTrue("value mismatch: v=" + v + " vv=" + vv, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,41 +6,38 @@ import java.io.*;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ReducedMedianFilterTest
|
||||
{
|
||||
public class ReducedMedianFilterTest {
|
||||
@Test
|
||||
public void reducedMedianFilterTest() throws IOException
|
||||
{
|
||||
ReducedMedianFilter f = new ReducedMedianFilter( 10 );
|
||||
public void reducedMedianFilterTest() throws IOException {
|
||||
ReducedMedianFilter f = new ReducedMedianFilter(10);
|
||||
f.reset();
|
||||
f.addSample( .2, 10 );
|
||||
f.addSample( .2, 10 );
|
||||
f.addSample( .2, 10 );
|
||||
f.addSample( .2, 15 );
|
||||
f.addSample( .2, 20 );
|
||||
|
||||
double m = f.calcEdgeReducedMedian( 0.5 );
|
||||
Assert.assertTrue( "median1 mismatch m=" + m + " expected 11.5", doubleEquals( m, 11.5 ) );
|
||||
f.addSample(.2, 10);
|
||||
f.addSample(.2, 10);
|
||||
f.addSample(.2, 10);
|
||||
f.addSample(.2, 15);
|
||||
f.addSample(.2, 20);
|
||||
|
||||
double m = f.calcEdgeReducedMedian(0.5);
|
||||
Assert.assertTrue("median1 mismatch m=" + m + " expected 11.5", doubleEquals(m, 11.5));
|
||||
|
||||
f.reset();
|
||||
f.addSample( .2, 10 );
|
||||
f.addSample( .2, 10 );
|
||||
f.addSample( .2, 10 );
|
||||
f.addSample( .2, 10 );
|
||||
f.addSample( .2, 20 );
|
||||
f.addSample(.2, 10);
|
||||
f.addSample(.2, 10);
|
||||
f.addSample(.2, 10);
|
||||
f.addSample(.2, 10);
|
||||
f.addSample(.2, 20);
|
||||
|
||||
m = f.calcEdgeReducedMedian( 1. );
|
||||
Assert.assertTrue( "median1 mismatch m=" + m + " expected 12", doubleEquals( m, 12. ) );
|
||||
m = f.calcEdgeReducedMedian(1.);
|
||||
Assert.assertTrue("median1 mismatch m=" + m + " expected 12", doubleEquals(m, 12.));
|
||||
|
||||
f.reset();
|
||||
f.addSample( .5, -10 );
|
||||
f.addSample( .5, 10 );
|
||||
m = f.calcEdgeReducedMedian( 0.5 );
|
||||
Assert.assertTrue( "median2 mismatch m=" + m + " expected 0", doubleEquals( m, 0. ) );
|
||||
f.addSample(.5, -10);
|
||||
f.addSample(.5, 10);
|
||||
m = f.calcEdgeReducedMedian(0.5);
|
||||
Assert.assertTrue("median2 mismatch m=" + m + " expected 0", doubleEquals(m, 0.));
|
||||
}
|
||||
|
||||
private boolean doubleEquals( double d1, double d2 )
|
||||
{
|
||||
private boolean doubleEquals(double d1, double d2) {
|
||||
double d = d1 - d2;
|
||||
return d < 1e-9 && d > -1e-9;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,59 +7,52 @@ import java.util.HashSet;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SortedHeapTest
|
||||
{
|
||||
public class SortedHeapTest {
|
||||
@Test
|
||||
public void sortedHeapTest1()
|
||||
{
|
||||
SortedHeap<String> sh = new SortedHeap<String>();
|
||||
Random rnd = new Random();
|
||||
for( int i = 0; i< 100000; i++ )
|
||||
{
|
||||
int val = rnd.nextInt( 1000000 );
|
||||
sh.add( val, "" + val );
|
||||
val = rnd.nextInt( 1000000 );
|
||||
sh.add( val, "" + val );
|
||||
sh.popLowestKeyValue();
|
||||
}
|
||||
public void sortedHeapTest1() {
|
||||
SortedHeap<String> sh = new SortedHeap<String>();
|
||||
Random rnd = new Random();
|
||||
for (int i = 0; i < 100000; i++) {
|
||||
int val = rnd.nextInt(1000000);
|
||||
sh.add(val, "" + val);
|
||||
val = rnd.nextInt(1000000);
|
||||
sh.add(val, "" + val);
|
||||
sh.popLowestKeyValue();
|
||||
}
|
||||
|
||||
int cnt = 0;
|
||||
int lastval = 0;
|
||||
for(;;)
|
||||
{
|
||||
String s = sh.popLowestKeyValue();
|
||||
if ( s == null ) break;
|
||||
cnt ++;
|
||||
int val = Integer.parseInt( s );
|
||||
Assert.assertTrue( "sorting test", val >= lastval );
|
||||
lastval = val;
|
||||
}
|
||||
Assert.assertTrue( "total count test", cnt == 100000 );
|
||||
int cnt = 0;
|
||||
int lastval = 0;
|
||||
for (; ; ) {
|
||||
String s = sh.popLowestKeyValue();
|
||||
if (s == null) break;
|
||||
cnt++;
|
||||
int val = Integer.parseInt(s);
|
||||
Assert.assertTrue("sorting test", val >= lastval);
|
||||
lastval = val;
|
||||
}
|
||||
Assert.assertTrue("total count test", cnt == 100000);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sortedHeapTest2()
|
||||
{
|
||||
SortedHeap<String> sh = new SortedHeap<String>();
|
||||
Random rnd = new Random();
|
||||
for( int i = 0; i< 100000; i++ )
|
||||
{
|
||||
sh.add( i, "" + i );
|
||||
}
|
||||
public void sortedHeapTest2() {
|
||||
SortedHeap<String> sh = new SortedHeap<String>();
|
||||
Random rnd = new Random();
|
||||
for (int i = 0; i < 100000; i++) {
|
||||
sh.add(i, "" + i);
|
||||
}
|
||||
|
||||
int cnt = 0;
|
||||
int expected = 0;
|
||||
for(;;)
|
||||
{
|
||||
String s = sh.popLowestKeyValue();
|
||||
if ( s == null ) break;
|
||||
cnt ++;
|
||||
int val = Integer.parseInt( s );
|
||||
Assert.assertTrue( "sequence test", val == expected );
|
||||
expected++;
|
||||
}
|
||||
Assert.assertTrue( "total count test", cnt == 100000 );
|
||||
int cnt = 0;
|
||||
int expected = 0;
|
||||
for (; ; ) {
|
||||
String s = sh.popLowestKeyValue();
|
||||
if (s == null) break;
|
||||
cnt++;
|
||||
int val = Integer.parseInt(s);
|
||||
Assert.assertTrue("sequence test", val == expected);
|
||||
expected++;
|
||||
}
|
||||
Assert.assertTrue("total count test", cnt == 100000);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,27 +3,22 @@ package btools.util;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class StringUtilsTest
|
||||
{
|
||||
private static String[] raw = new String[] { "hallo", "is 1<2 ?", "or 4>5 ?", "or 1<>2 ?", "\"hi\" 'there'" };
|
||||
private static String[] xml = new String[] { "hallo", "is 1<2 ?", "or 4>5 ?", "or 1<>2 ?", ""hi" 'there'" };
|
||||
private static String[] jsn = new String[] { "hallo", "is 1<2 ?", "or 4>5 ?", "or 1<>2 ?", "\\\"hi\\\" \\'there\\'" };
|
||||
public class StringUtilsTest {
|
||||
private static String[] raw = new String[]{"hallo", "is 1<2 ?", "or 4>5 ?", "or 1<>2 ?", "\"hi\" 'there'"};
|
||||
private static String[] xml = new String[]{"hallo", "is 1<2 ?", "or 4>5 ?", "or 1<>2 ?", ""hi" 'there'"};
|
||||
private static String[] jsn = new String[]{"hallo", "is 1<2 ?", "or 4>5 ?", "or 1<>2 ?", "\\\"hi\\\" \\'there\\'"};
|
||||
|
||||
@Test
|
||||
public void xmlEncodingTest()
|
||||
{
|
||||
for( int i=0; i<raw.length; i++ )
|
||||
{
|
||||
Assert.assertEquals( "xml encoding mismatch for raw: " + raw[i], xml[i], StringUtils.escapeXml10( raw[i] ) );
|
||||
}
|
||||
public void xmlEncodingTest() {
|
||||
for (int i = 0; i < raw.length; i++) {
|
||||
Assert.assertEquals("xml encoding mismatch for raw: " + raw[i], xml[i], StringUtils.escapeXml10(raw[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jsonEncodingTest()
|
||||
{
|
||||
for( int i=0; i<raw.length; i++ )
|
||||
{
|
||||
Assert.assertEquals( "json encoding mismatch for raw: " + raw[i], jsn[i], StringUtils.escapeJson( raw[i] ) );
|
||||
public void jsonEncodingTest() {
|
||||
for (int i = 0; i < raw.length; i++) {
|
||||
Assert.assertEquals("json encoding mismatch for raw: " + raw[i], jsn[i], StringUtils.escapeJson(raw[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue