Reformat whole codebase using Android Studio
This commit is contained in:
parent
d5322667d5
commit
c15913c1ab
161 changed files with 15124 additions and 18537 deletions
|
|
@ -5,11 +5,10 @@ import btools.util.BitCoderContext;
|
|||
/**
|
||||
* Container for some re-usable databuffers for the decoder
|
||||
*/
|
||||
public final class DataBuffers
|
||||
{
|
||||
public final class DataBuffers {
|
||||
public byte[] iobuffer;
|
||||
public byte[] tagbuf1 = new byte[256];
|
||||
public BitCoderContext bctx1 = new BitCoderContext( tagbuf1 );
|
||||
public BitCoderContext bctx1 = new BitCoderContext(tagbuf1);
|
||||
public byte[] bbuf1 = new byte[65636];
|
||||
public int[] ibuf1 = new int[4096];
|
||||
public int[] ibuf2 = new int[2048];
|
||||
|
|
@ -17,17 +16,15 @@ public final class DataBuffers
|
|||
public int[] alon = new int[2048];
|
||||
public int[] alat = new int[2048];
|
||||
|
||||
public DataBuffers()
|
||||
{
|
||||
this( new byte[65636] );
|
||||
public DataBuffers() {
|
||||
this(new byte[65636]);
|
||||
}
|
||||
|
||||
/**
|
||||
* construct a set of databuffers except
|
||||
* for 'iobuffer', where the given array is used
|
||||
*/
|
||||
public DataBuffers( byte[] iobuffer )
|
||||
{
|
||||
public DataBuffers(byte[] iobuffer) {
|
||||
this.iobuffer = iobuffer;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,16 +3,14 @@ package btools.codec;
|
|||
/**
|
||||
* Special integer fifo suitable for 3-pass encoding
|
||||
*/
|
||||
public class IntegerFifo3Pass
|
||||
{
|
||||
public class IntegerFifo3Pass {
|
||||
private int[] a;
|
||||
private int size;
|
||||
private int pos;
|
||||
|
||||
private int pass;
|
||||
|
||||
public IntegerFifo3Pass( int capacity )
|
||||
{
|
||||
public IntegerFifo3Pass(int capacity) {
|
||||
a = capacity < 4 ? new int[4] : new int[capacity];
|
||||
}
|
||||
|
||||
|
|
@ -20,8 +18,7 @@ public class IntegerFifo3Pass
|
|||
* Starts a new encoding pass and resets the reading pointer
|
||||
* from the stats collected in pass2 and writes that to the given context
|
||||
*/
|
||||
public void init()
|
||||
{
|
||||
public void init() {
|
||||
pass++;
|
||||
pos = 0;
|
||||
}
|
||||
|
|
@ -29,14 +26,11 @@ public class IntegerFifo3Pass
|
|||
/**
|
||||
* writes to the fifo in pass2
|
||||
*/
|
||||
public void add( int value )
|
||||
{
|
||||
if ( pass == 2 )
|
||||
{
|
||||
if ( size == a.length )
|
||||
{
|
||||
public void add(int value) {
|
||||
if (pass == 2) {
|
||||
if (size == a.length) {
|
||||
int[] aa = new int[2 * size];
|
||||
System.arraycopy( a, 0, aa, 0, size );
|
||||
System.arraycopy(a, 0, aa, 0, size);
|
||||
a = aa;
|
||||
}
|
||||
a[size++] = value;
|
||||
|
|
@ -46,16 +40,13 @@ public class IntegerFifo3Pass
|
|||
/**
|
||||
* reads from the fifo in pass3 (in pass1/2 returns just 1)
|
||||
*/
|
||||
public int getNext()
|
||||
{
|
||||
return pass == 3 ? get( pos++ ) : 1;
|
||||
public int getNext() {
|
||||
return pass == 3 ? get(pos++) : 1;
|
||||
}
|
||||
|
||||
private int get( int idx )
|
||||
{
|
||||
if ( idx >= size )
|
||||
{
|
||||
throw new IndexOutOfBoundsException( "list size=" + size + " idx=" + idx );
|
||||
private int get(int idx) {
|
||||
if (idx >= size) {
|
||||
throw new IndexOutOfBoundsException("list size=" + size + " idx=" + idx);
|
||||
}
|
||||
return a[idx];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@ package btools.codec;
|
|||
/**
|
||||
* Simple container for a list of lists of integers
|
||||
*/
|
||||
public class LinkedListContainer
|
||||
{
|
||||
public class LinkedListContainer {
|
||||
private int[] ia; // prev, data, prev, data, ...
|
||||
private int size;
|
||||
private int[] startpointer; // 0=void, odd=head-data-cell
|
||||
|
|
@ -12,49 +11,44 @@ public class LinkedListContainer
|
|||
|
||||
/**
|
||||
* Construct a container for the given number of lists
|
||||
*
|
||||
* <p>
|
||||
* If no default-buffer is given, an int[nlists*4] is constructed,
|
||||
* able to hold 2 entries per list on average
|
||||
*
|
||||
* @param nlists the number of lists
|
||||
* @param nlists the number of lists
|
||||
* @param defaultbuffer an optional data array for re-use (gets replaced if too small)
|
||||
*/
|
||||
public LinkedListContainer( int nlists, int[] defaultbuffer )
|
||||
{
|
||||
ia = defaultbuffer == null ? new int[nlists*4] : defaultbuffer;
|
||||
startpointer = new int[nlists];
|
||||
public LinkedListContainer(int nlists, int[] defaultbuffer) {
|
||||
ia = defaultbuffer == null ? new int[nlists * 4] : defaultbuffer;
|
||||
startpointer = new int[nlists];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a data element to the given list
|
||||
*
|
||||
* @param listNr the list to add the data to
|
||||
* @param data the data value
|
||||
* @param data the data value
|
||||
*/
|
||||
public void addDataElement( int listNr, int data )
|
||||
{
|
||||
if ( size + 2 > ia.length )
|
||||
{
|
||||
public void addDataElement(int listNr, int data) {
|
||||
if (size + 2 > ia.length) {
|
||||
resize();
|
||||
}
|
||||
ia[size++] = startpointer[ listNr ];
|
||||
startpointer[ listNr ] = size;
|
||||
ia[size++] = startpointer[listNr];
|
||||
startpointer[listNr] = size;
|
||||
ia[size++] = data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize a list for reading
|
||||
*
|
||||
* @param listNr the list to initialize
|
||||
* @return the number of entries in that list
|
||||
*/
|
||||
public int initList( int listNr )
|
||||
{
|
||||
public int initList(int listNr) {
|
||||
int cnt = 0;
|
||||
int lp = listpointer = startpointer[ listNr ];
|
||||
while( lp != 0 )
|
||||
{
|
||||
lp = ia[ lp-1 ];
|
||||
int lp = listpointer = startpointer[listNr];
|
||||
while (lp != 0) {
|
||||
lp = ia[lp - 1];
|
||||
cnt++;
|
||||
}
|
||||
return cnt;
|
||||
|
|
@ -67,21 +61,18 @@ public class LinkedListContainer
|
|||
* @return the data element
|
||||
* @throws IllegalArgumentException if no more element
|
||||
*/
|
||||
public int getDataElement()
|
||||
{
|
||||
if ( listpointer == 0 )
|
||||
{
|
||||
throw new IllegalArgumentException( "no more element!" );
|
||||
public int getDataElement() {
|
||||
if (listpointer == 0) {
|
||||
throw new IllegalArgumentException("no more element!");
|
||||
}
|
||||
int data = ia[ listpointer ];
|
||||
listpointer = ia[ listpointer-1 ];
|
||||
int data = ia[listpointer];
|
||||
listpointer = ia[listpointer - 1];
|
||||
return data;
|
||||
}
|
||||
|
||||
private void resize()
|
||||
{
|
||||
int[] ia2 = new int[2*ia.length];
|
||||
System.arraycopy( ia, 0, ia2, 0, ia.length );
|
||||
|
||||
private void resize() {
|
||||
int[] ia2 = new int[2 * ia.length];
|
||||
System.arraycopy(ia, 0, ia2, 0, ia.length);
|
||||
ia = ia2;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,21 +5,20 @@ import btools.util.ByteDataWriter;
|
|||
/**
|
||||
* a micro-cache is a data cache for an area of some square kilometers or some
|
||||
* hundreds or thousands nodes
|
||||
*
|
||||
* <p>
|
||||
* This is the basic io-unit: always a full microcache is loaded from the
|
||||
* data-file if a node is requested at a position not yet covered by the caches
|
||||
* already loaded
|
||||
*
|
||||
* <p>
|
||||
* The nodes are represented in a compact way (typical 20-50 bytes per node),
|
||||
* but in a way that they do not depend on each other, and garbage collection is
|
||||
* supported to remove the nodes already consumed from the cache.
|
||||
*
|
||||
* <p>
|
||||
* The cache-internal data representation is different from that in the
|
||||
* data-files, where a cache is encoded as a whole, allowing more
|
||||
* redundancy-removal for a more compact encoding
|
||||
*/
|
||||
public class MicroCache extends ByteDataWriter
|
||||
{
|
||||
public class MicroCache extends ByteDataWriter {
|
||||
protected int[] faid;
|
||||
protected int[] fapos;
|
||||
protected int size = 0;
|
||||
|
|
@ -35,25 +34,21 @@ public class MicroCache extends ByteDataWriter
|
|||
|
||||
public static boolean debug = false;
|
||||
|
||||
protected MicroCache( byte[] ab )
|
||||
{
|
||||
super( ab );
|
||||
protected MicroCache(byte[] ab) {
|
||||
super(ab);
|
||||
}
|
||||
|
||||
public final static MicroCache emptyNonVirgin = new MicroCache( null );
|
||||
public final static MicroCache emptyNonVirgin = new MicroCache(null);
|
||||
|
||||
static
|
||||
{
|
||||
static {
|
||||
emptyNonVirgin.virgin = false;
|
||||
}
|
||||
|
||||
public static MicroCache emptyCache()
|
||||
{
|
||||
return new MicroCache( null ); // TODO: singleton?
|
||||
public static MicroCache emptyCache() {
|
||||
return new MicroCache(null); // TODO: singleton?
|
||||
}
|
||||
|
||||
protected void init( int size )
|
||||
{
|
||||
protected void init(int size) {
|
||||
this.size = size;
|
||||
delcount = 0;
|
||||
delbytes = 0;
|
||||
|
|
@ -62,35 +57,31 @@ public class MicroCache extends ByteDataWriter
|
|||
p2size >>= 1;
|
||||
}
|
||||
|
||||
public final void finishNode( long id )
|
||||
{
|
||||
public final void finishNode(long id) {
|
||||
fapos[size] = aboffset;
|
||||
faid[size] = shrinkId( id );
|
||||
faid[size] = shrinkId(id);
|
||||
size++;
|
||||
}
|
||||
|
||||
public final void discardNode()
|
||||
{
|
||||
aboffset = startPos( size );
|
||||
public final void discardNode() {
|
||||
aboffset = startPos(size);
|
||||
}
|
||||
|
||||
public final int getSize()
|
||||
{
|
||||
public final int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public final int getDataSize()
|
||||
{
|
||||
public final int getDataSize() {
|
||||
return ab == null ? 0 : ab.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the internal reader (aboffset, aboffsetEnd) to the body data for the given id
|
||||
*
|
||||
* <p>
|
||||
* If a node is not found in an empty cache, this is usually an edge-effect
|
||||
* (data-file does not exist or neighboured data-files of differnt age),
|
||||
* but is can as well be a symptom of a node-identity breaking bug.
|
||||
*
|
||||
* <p>
|
||||
* Current implementation always returns false for not-found, however, for
|
||||
* regression testing, at least for the case that is most likely a bug
|
||||
* (node found but marked as deleted = ready for garbage collection
|
||||
|
|
@ -98,38 +89,31 @@ public class MicroCache extends ByteDataWriter
|
|||
*
|
||||
* @return true if id was found
|
||||
*/
|
||||
public final boolean getAndClear( long id64 )
|
||||
{
|
||||
if ( size == 0 )
|
||||
{
|
||||
public final boolean getAndClear(long id64) {
|
||||
if (size == 0) {
|
||||
return false;
|
||||
}
|
||||
int id = shrinkId( id64 );
|
||||
int id = shrinkId(id64);
|
||||
int[] a = faid;
|
||||
int offset = p2size;
|
||||
int n = 0;
|
||||
|
||||
while (offset > 0)
|
||||
{
|
||||
while (offset > 0) {
|
||||
int nn = n + offset;
|
||||
if ( nn < size && a[nn] <= id )
|
||||
{
|
||||
if (nn < size && a[nn] <= id) {
|
||||
n = nn;
|
||||
}
|
||||
offset >>= 1;
|
||||
}
|
||||
if ( a[n] == id )
|
||||
{
|
||||
if ( ( fapos[n] & 0x80000000 ) == 0 )
|
||||
{
|
||||
aboffset = startPos( n );
|
||||
if (a[n] == id) {
|
||||
if ((fapos[n] & 0x80000000) == 0) {
|
||||
aboffset = startPos(n);
|
||||
aboffsetEnd = fapos[n];
|
||||
fapos[n] |= 0x80000000; // mark deleted
|
||||
delbytes += aboffsetEnd - aboffset;
|
||||
delcount++;
|
||||
return true;
|
||||
}
|
||||
else // .. marked as deleted
|
||||
} else // .. marked as deleted
|
||||
{
|
||||
// throw new RuntimeException( "MicroCache: node already consumed: id=" + id );
|
||||
}
|
||||
|
|
@ -137,43 +121,35 @@ public class MicroCache extends ByteDataWriter
|
|||
return false;
|
||||
}
|
||||
|
||||
protected final int startPos( int n )
|
||||
{
|
||||
protected final int startPos(int n) {
|
||||
return n > 0 ? fapos[n - 1] & 0x7fffffff : 0;
|
||||
}
|
||||
|
||||
public final int collect( int threshold )
|
||||
{
|
||||
if ( delcount <= threshold )
|
||||
{
|
||||
public final int collect(int threshold) {
|
||||
if (delcount <= threshold) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virgin = false;
|
||||
|
||||
int nsize = size - delcount;
|
||||
if ( nsize == 0 )
|
||||
{
|
||||
if (nsize == 0) {
|
||||
faid = null;
|
||||
fapos = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
int[] nfaid = new int[nsize];
|
||||
int[] nfapos = new int[nsize];
|
||||
int idx = 0;
|
||||
|
||||
byte[] nab = new byte[ab.length - delbytes];
|
||||
int nab_off = 0;
|
||||
for ( int i = 0; i < size; i++ )
|
||||
{
|
||||
for (int i = 0; i < size; i++) {
|
||||
int pos = fapos[i];
|
||||
if ( ( pos & 0x80000000 ) == 0 )
|
||||
{
|
||||
int start = startPos( i );
|
||||
if ((pos & 0x80000000) == 0) {
|
||||
int start = startPos(i);
|
||||
int end = fapos[i];
|
||||
int len = end - start;
|
||||
System.arraycopy( ab, start, nab, nab_off, len );
|
||||
System.arraycopy(ab, start, nab, nab_off, len);
|
||||
nfaid[idx] = faid[i];
|
||||
nab_off += len;
|
||||
nfapos[idx] = nab_off;
|
||||
|
|
@ -185,17 +161,15 @@ public class MicroCache extends ByteDataWriter
|
|||
ab = nab;
|
||||
}
|
||||
int deleted = delbytes;
|
||||
init( nsize );
|
||||
init(nsize);
|
||||
return deleted;
|
||||
}
|
||||
|
||||
public final void unGhost()
|
||||
{
|
||||
public final void unGhost() {
|
||||
ghost = false;
|
||||
delcount = 0;
|
||||
delbytes = 0;
|
||||
for ( int i = 0; i < size; i++ )
|
||||
{
|
||||
for (int i = 0; i < size; i++) {
|
||||
fapos[i] &= 0x7fffffff; // clear deleted flags
|
||||
}
|
||||
}
|
||||
|
|
@ -203,201 +177,168 @@ public class MicroCache extends ByteDataWriter
|
|||
/**
|
||||
* @return the 64-bit global id for the given cache-position
|
||||
*/
|
||||
public final long getIdForIndex( int i )
|
||||
{
|
||||
public final long getIdForIndex(int i) {
|
||||
int id32 = faid[i];
|
||||
return expandId( id32 );
|
||||
return expandId(id32);
|
||||
}
|
||||
|
||||
/**
|
||||
* expand a 32-bit micro-cache-internal id into a 64-bit (lon|lat) global-id
|
||||
*
|
||||
*
|
||||
* @see #shrinkId
|
||||
*/
|
||||
public long expandId( int id32 )
|
||||
{
|
||||
throw new IllegalArgumentException( "expandId for empty cache" );
|
||||
public long expandId(int id32) {
|
||||
throw new IllegalArgumentException("expandId for empty cache");
|
||||
}
|
||||
|
||||
/**
|
||||
* shrink a 64-bit (lon|lat) global-id into a a 32-bit micro-cache-internal id
|
||||
*
|
||||
*
|
||||
* @see #expandId
|
||||
*/
|
||||
public int shrinkId( long id64 )
|
||||
{
|
||||
throw new IllegalArgumentException( "shrinkId for empty cache" );
|
||||
public int shrinkId(long id64) {
|
||||
throw new IllegalArgumentException("shrinkId for empty cache");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the given lon/lat position is internal for that micro-cache
|
||||
*/
|
||||
public boolean isInternal( int ilon, int ilat )
|
||||
{
|
||||
throw new IllegalArgumentException( "isInternal for empty cache" );
|
||||
public boolean isInternal(int ilon, int ilat) {
|
||||
throw new IllegalArgumentException("isInternal for empty cache");
|
||||
}
|
||||
|
||||
/**
|
||||
* (stasticially) encode the micro-cache into the format used in the datafiles
|
||||
*
|
||||
* @param buffer
|
||||
* byte array to encode into (considered big enough)
|
||||
*
|
||||
* @param buffer byte array to encode into (considered big enough)
|
||||
* @return the size of the encoded data
|
||||
*/
|
||||
public int encodeMicroCache( byte[] buffer )
|
||||
{
|
||||
throw new IllegalArgumentException( "encodeMicroCache for empty cache" );
|
||||
public int encodeMicroCache(byte[] buffer) {
|
||||
throw new IllegalArgumentException("encodeMicroCache for empty cache");
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the content of this microcache to another
|
||||
*
|
||||
*
|
||||
* @return null if equals, else a diff-report
|
||||
*/
|
||||
public String compareWith( MicroCache mc )
|
||||
{
|
||||
String msg = _compareWith( mc );
|
||||
if ( msg != null )
|
||||
{
|
||||
StringBuilder sb = new StringBuilder( msg );
|
||||
sb.append( "\nencode cache:\n" ).append( summary() );
|
||||
sb.append( "\ndecode cache:\n" ).append( mc.summary() );
|
||||
public String compareWith(MicroCache mc) {
|
||||
String msg = _compareWith(mc);
|
||||
if (msg != null) {
|
||||
StringBuilder sb = new StringBuilder(msg);
|
||||
sb.append("\nencode cache:\n").append(summary());
|
||||
sb.append("\ndecode cache:\n").append(mc.summary());
|
||||
return sb.toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String summary()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder( "size=" + size + " aboffset=" + aboffset );
|
||||
for ( int i = 0; i < size; i++ )
|
||||
{
|
||||
sb.append( "\nidx=" + i + " faid=" + faid[i] + " fapos=" + fapos[i] );
|
||||
private String summary() {
|
||||
StringBuilder sb = new StringBuilder("size=" + size + " aboffset=" + aboffset);
|
||||
for (int i = 0; i < size; i++) {
|
||||
sb.append("\nidx=" + i + " faid=" + faid[i] + " fapos=" + fapos[i]);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String _compareWith( MicroCache mc )
|
||||
{
|
||||
if ( size != mc.size )
|
||||
{
|
||||
private String _compareWith(MicroCache mc) {
|
||||
if (size != mc.size) {
|
||||
return "size missmatch: " + size + "->" + mc.size;
|
||||
}
|
||||
for ( int i = 0; i < size; i++ )
|
||||
{
|
||||
if ( faid[i] != mc.faid[i] )
|
||||
{
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (faid[i] != mc.faid[i]) {
|
||||
return "faid missmatch at index " + i + ":" + faid[i] + "->" + mc.faid[i];
|
||||
}
|
||||
int start = i > 0 ? fapos[i - 1] : 0;
|
||||
int end = fapos[i] < mc.fapos[i] ? fapos[i] : mc.fapos[i];
|
||||
int len = end - start;
|
||||
for ( int offset = 0; offset < len; offset++ )
|
||||
{
|
||||
if ( mc.ab.length <= start + offset )
|
||||
{
|
||||
for (int offset = 0; offset < len; offset++) {
|
||||
if (mc.ab.length <= start + offset) {
|
||||
return "data buffer too small";
|
||||
}
|
||||
if ( ab[start + offset] != mc.ab[start + offset] )
|
||||
{
|
||||
if (ab[start + offset] != mc.ab[start + offset]) {
|
||||
return "data missmatch at index " + i + " offset=" + offset;
|
||||
}
|
||||
}
|
||||
if ( fapos[i] != mc.fapos[i] )
|
||||
{
|
||||
if (fapos[i] != mc.fapos[i]) {
|
||||
return "fapos missmatch at index " + i + ":" + fapos[i] + "->" + mc.fapos[i];
|
||||
}
|
||||
}
|
||||
if ( aboffset != mc.aboffset )
|
||||
{
|
||||
if (aboffset != mc.aboffset) {
|
||||
return "datasize missmatch: " + aboffset + "->" + mc.aboffset;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void calcDelta( MicroCache mc1, MicroCache mc2 )
|
||||
{
|
||||
int idx1 = 0;
|
||||
int idx2 = 0;
|
||||
public void calcDelta(MicroCache mc1, MicroCache mc2) {
|
||||
int idx1 = 0;
|
||||
int idx2 = 0;
|
||||
|
||||
while( idx1 < mc1.size || idx2 < mc2.size )
|
||||
{
|
||||
int id1 = idx1 < mc1.size ? mc1.faid[idx1] : Integer.MAX_VALUE;
|
||||
int id2 = idx2 < mc2.size ? mc2.faid[idx2] : Integer.MAX_VALUE;
|
||||
int id;
|
||||
if ( id1 >= id2 )
|
||||
{
|
||||
id = id2;
|
||||
int start2 = idx2 > 0 ? mc2.fapos[idx2 - 1] : 0;
|
||||
int len2 = mc2.fapos[idx2++] - start2;
|
||||
while (idx1 < mc1.size || idx2 < mc2.size) {
|
||||
int id1 = idx1 < mc1.size ? mc1.faid[idx1] : Integer.MAX_VALUE;
|
||||
int id2 = idx2 < mc2.size ? mc2.faid[idx2] : Integer.MAX_VALUE;
|
||||
int id;
|
||||
if (id1 >= id2) {
|
||||
id = id2;
|
||||
int start2 = idx2 > 0 ? mc2.fapos[idx2 - 1] : 0;
|
||||
int len2 = mc2.fapos[idx2++] - start2;
|
||||
|
||||
if ( id1 == id2 )
|
||||
{
|
||||
// id exists in both caches, compare data
|
||||
int start1 = idx1 > 0 ? mc1.fapos[idx1 - 1] : 0;
|
||||
int len1 = mc1.fapos[idx1++] - start1;
|
||||
if ( len1 == len2 )
|
||||
{
|
||||
int i = 0;
|
||||
while( i<len1 )
|
||||
{
|
||||
if ( mc1.ab[start1+i] != mc2.ab[start2+i] )
|
||||
{
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if ( i == len1 )
|
||||
{
|
||||
continue; // same data -> do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
write( mc2.ab, start2, len2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
idx1++;
|
||||
id = id1; // deleted node
|
||||
}
|
||||
fapos[size] = aboffset;
|
||||
faid[size] = id;
|
||||
size++;
|
||||
}
|
||||
if (id1 == id2) {
|
||||
// id exists in both caches, compare data
|
||||
int start1 = idx1 > 0 ? mc1.fapos[idx1 - 1] : 0;
|
||||
int len1 = mc1.fapos[idx1++] - start1;
|
||||
if (len1 == len2) {
|
||||
int i = 0;
|
||||
while (i < len1) {
|
||||
if (mc1.ab[start1 + i] != mc2.ab[start2 + i]) {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (i == len1) {
|
||||
continue; // same data -> do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
write(mc2.ab, start2, len2);
|
||||
} else {
|
||||
idx1++;
|
||||
id = id1; // deleted node
|
||||
}
|
||||
fapos[size] = aboffset;
|
||||
faid[size] = id;
|
||||
size++;
|
||||
}
|
||||
}
|
||||
|
||||
public void addDelta( MicroCache mc1, MicroCache mc2, boolean keepEmptyNodes )
|
||||
{
|
||||
int idx1 = 0;
|
||||
int idx2 = 0;
|
||||
public void addDelta(MicroCache mc1, MicroCache mc2, boolean keepEmptyNodes) {
|
||||
int idx1 = 0;
|
||||
int idx2 = 0;
|
||||
|
||||
while( idx1 < mc1.size || idx2 < mc2.size )
|
||||
{
|
||||
int id1 = idx1 < mc1.size ? mc1.faid[idx1] : Integer.MAX_VALUE;
|
||||
int id2 = idx2 < mc2.size ? mc2.faid[idx2] : Integer.MAX_VALUE;
|
||||
if ( id1 >= id2 ) // data from diff file wins
|
||||
{
|
||||
int start2 = idx2 > 0 ? mc2.fapos[idx2 - 1] : 0;
|
||||
int len2 = mc2.fapos[idx2++] - start2;
|
||||
if ( keepEmptyNodes || len2 > 0 )
|
||||
{
|
||||
write( mc2.ab, start2, len2 );
|
||||
fapos[size] = aboffset;
|
||||
faid[size++] = id2;
|
||||
}
|
||||
if ( id1 == id2 ) // // id exists in both caches
|
||||
{
|
||||
idx1++;
|
||||
}
|
||||
}
|
||||
else // use data from base file
|
||||
{
|
||||
int start1 = idx1 > 0 ? mc1.fapos[idx1 - 1] : 0;
|
||||
int len1 = mc1.fapos[idx1++] - start1;
|
||||
write( mc1.ab, start1, len1 );
|
||||
fapos[size] = aboffset;
|
||||
faid[size++] = id1;
|
||||
}
|
||||
}
|
||||
while (idx1 < mc1.size || idx2 < mc2.size) {
|
||||
int id1 = idx1 < mc1.size ? mc1.faid[idx1] : Integer.MAX_VALUE;
|
||||
int id2 = idx2 < mc2.size ? mc2.faid[idx2] : Integer.MAX_VALUE;
|
||||
if (id1 >= id2) // data from diff file wins
|
||||
{
|
||||
int start2 = idx2 > 0 ? mc2.fapos[idx2 - 1] : 0;
|
||||
int len2 = mc2.fapos[idx2++] - start2;
|
||||
if (keepEmptyNodes || len2 > 0) {
|
||||
write(mc2.ab, start2, len2);
|
||||
fapos[size] = aboffset;
|
||||
faid[size++] = id2;
|
||||
}
|
||||
if (id1 == id2) // // id exists in both caches
|
||||
{
|
||||
idx1++;
|
||||
}
|
||||
} else // use data from base file
|
||||
{
|
||||
int start1 = idx1 > 0 ? mc1.fapos[idx1 - 1] : 0;
|
||||
int len1 = mc1.fapos[idx1++] - start1;
|
||||
write(mc1.ab, start1, len1);
|
||||
fapos[size] = aboffset;
|
||||
faid[size++] = id1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,222 +9,204 @@ import btools.util.IByteArrayUnifier;
|
|||
* MicroCache2 is the new format that uses statistical encoding and
|
||||
* is able to do access filtering and waypoint matching during encoding
|
||||
*/
|
||||
public final class MicroCache2 extends MicroCache
|
||||
{
|
||||
public final class MicroCache2 extends MicroCache {
|
||||
private int lonBase;
|
||||
private int latBase;
|
||||
private int cellsize;
|
||||
|
||||
public MicroCache2( int size, byte[] databuffer, int lonIdx, int latIdx, int divisor )
|
||||
{
|
||||
super( databuffer ); // sets ab=databuffer, aboffset=0
|
||||
public MicroCache2(int size, byte[] databuffer, int lonIdx, int latIdx, int divisor) {
|
||||
super(databuffer); // sets ab=databuffer, aboffset=0
|
||||
|
||||
faid = new int[size];
|
||||
fapos = new int[size];
|
||||
this.size = 0;
|
||||
cellsize = 1000000 / divisor;
|
||||
lonBase = lonIdx*cellsize;
|
||||
latBase = latIdx*cellsize;
|
||||
}
|
||||
|
||||
public byte[] readUnified( int len, IByteArrayUnifier u )
|
||||
{
|
||||
byte[] b = u.unify( ab, aboffset, len );
|
||||
aboffset += len;
|
||||
return b;
|
||||
lonBase = lonIdx * cellsize;
|
||||
latBase = latIdx * cellsize;
|
||||
}
|
||||
|
||||
public MicroCache2( StatCoderContext bc, DataBuffers dataBuffers, int lonIdx, int latIdx, int divisor, TagValueValidator wayValidator, WaypointMatcher waypointMatcher )
|
||||
{
|
||||
super( null );
|
||||
public byte[] readUnified(int len, IByteArrayUnifier u) {
|
||||
byte[] b = u.unify(ab, aboffset, len);
|
||||
aboffset += len;
|
||||
return b;
|
||||
}
|
||||
|
||||
public MicroCache2(StatCoderContext bc, DataBuffers dataBuffers, int lonIdx, int latIdx, int divisor, TagValueValidator wayValidator, WaypointMatcher waypointMatcher) {
|
||||
super(null);
|
||||
cellsize = 1000000 / divisor;
|
||||
lonBase = lonIdx*cellsize;
|
||||
latBase = latIdx*cellsize;
|
||||
lonBase = lonIdx * cellsize;
|
||||
latBase = latIdx * cellsize;
|
||||
|
||||
TagValueCoder wayTagCoder = new TagValueCoder( bc, dataBuffers, wayValidator );
|
||||
TagValueCoder nodeTagCoder = new TagValueCoder( bc, dataBuffers, null );
|
||||
NoisyDiffCoder nodeIdxDiff = new NoisyDiffCoder( bc );
|
||||
NoisyDiffCoder nodeEleDiff = new NoisyDiffCoder( bc );
|
||||
TagValueCoder wayTagCoder = new TagValueCoder(bc, dataBuffers, wayValidator);
|
||||
TagValueCoder nodeTagCoder = new TagValueCoder(bc, dataBuffers, null);
|
||||
NoisyDiffCoder nodeIdxDiff = new NoisyDiffCoder(bc);
|
||||
NoisyDiffCoder nodeEleDiff = new NoisyDiffCoder(bc);
|
||||
NoisyDiffCoder extLonDiff = new NoisyDiffCoder(bc);
|
||||
NoisyDiffCoder extLatDiff = new NoisyDiffCoder(bc);
|
||||
NoisyDiffCoder transEleDiff = new NoisyDiffCoder( bc );
|
||||
NoisyDiffCoder transEleDiff = new NoisyDiffCoder(bc);
|
||||
|
||||
size = bc.decodeNoisyNumber( 5 );
|
||||
size = bc.decodeNoisyNumber(5);
|
||||
faid = size > dataBuffers.ibuf2.length ? new int[size] : dataBuffers.ibuf2;
|
||||
fapos = size > dataBuffers.ibuf3.length ? new int[size] : dataBuffers.ibuf3;
|
||||
|
||||
|
||||
|
||||
int[] alon = size > dataBuffers.alon.length ? new int[size] : dataBuffers.alon;
|
||||
int[] alat = size > dataBuffers.alat.length ? new int[size] : dataBuffers.alat;
|
||||
|
||||
if ( debug ) System.out.println( "*** decoding cache of size=" + size + " for lonIdx=" + lonIdx + " latIdx=" + latIdx );
|
||||
|
||||
bc.decodeSortedArray( faid, 0, size, 29, 0 );
|
||||
|
||||
for( int n = 0; n<size; n++ )
|
||||
{
|
||||
long id64 = expandId( faid[n] );
|
||||
alon[n] = (int)(id64 >> 32);
|
||||
alat[n] = (int)(id64 & 0xffffffff);
|
||||
int[] alon = size > dataBuffers.alon.length ? new int[size] : dataBuffers.alon;
|
||||
int[] alat = size > dataBuffers.alat.length ? new int[size] : dataBuffers.alat;
|
||||
|
||||
if (debug)
|
||||
System.out.println("*** decoding cache of size=" + size + " for lonIdx=" + lonIdx + " latIdx=" + latIdx);
|
||||
|
||||
bc.decodeSortedArray(faid, 0, size, 29, 0);
|
||||
|
||||
for (int n = 0; n < size; n++) {
|
||||
long id64 = expandId(faid[n]);
|
||||
alon[n] = (int) (id64 >> 32);
|
||||
alat[n] = (int) (id64 & 0xffffffff);
|
||||
}
|
||||
|
||||
int netdatasize = bc.decodeNoisyNumber( 10 );
|
||||
|
||||
int netdatasize = bc.decodeNoisyNumber(10);
|
||||
ab = netdatasize > dataBuffers.bbuf1.length ? new byte[netdatasize] : dataBuffers.bbuf1;
|
||||
aboffset = 0;
|
||||
|
||||
int[] validBits = new int[(size+31)>>5];
|
||||
int[] validBits = new int[(size + 31) >> 5];
|
||||
|
||||
int finaldatasize = 0;
|
||||
|
||||
LinkedListContainer reverseLinks = new LinkedListContainer( size, dataBuffers.ibuf1 );
|
||||
LinkedListContainer reverseLinks = new LinkedListContainer(size, dataBuffers.ibuf1);
|
||||
|
||||
int selev = 0;
|
||||
for( int n=0; n<size; n++ ) // loop over nodes
|
||||
{
|
||||
for (int n = 0; n < size; n++) // loop over nodes
|
||||
{
|
||||
int ilon = alon[n];
|
||||
int ilat = alat[n];
|
||||
|
||||
|
||||
// future escapes (turn restrictions?)
|
||||
short trExceptions = 0;
|
||||
int featureId = bc.decodeVarBits();
|
||||
if ( featureId == 13 )
|
||||
{
|
||||
if (featureId == 13) {
|
||||
fapos[n] = aboffset;
|
||||
validBits[ n >> 5 ] |= 1 << n; // mark dummy-node valid
|
||||
validBits[n >> 5] |= 1 << n; // mark dummy-node valid
|
||||
continue; // empty node escape (delta files only)
|
||||
}
|
||||
while( featureId != 0 )
|
||||
{
|
||||
int bitsize = bc.decodeNoisyNumber( 5 );
|
||||
while (featureId != 0) {
|
||||
int bitsize = bc.decodeNoisyNumber(5);
|
||||
|
||||
if ( featureId == 2 ) // exceptions to turn-restriction
|
||||
if (featureId == 2) // exceptions to turn-restriction
|
||||
{
|
||||
trExceptions = (short)bc.decodeBounded( 1023 );
|
||||
}
|
||||
else if ( featureId == 1 ) // turn-restriction
|
||||
trExceptions = (short) bc.decodeBounded(1023);
|
||||
} else if (featureId == 1) // turn-restriction
|
||||
{
|
||||
writeBoolean( true );
|
||||
writeShort( trExceptions ); // exceptions from previous feature
|
||||
writeBoolean(true);
|
||||
writeShort(trExceptions); // exceptions from previous feature
|
||||
trExceptions = 0;
|
||||
|
||||
writeBoolean( bc.decodeBit() ); // isPositive
|
||||
writeInt( ilon + bc.decodeNoisyDiff( 10 ) ); // fromLon
|
||||
writeInt( ilat + bc.decodeNoisyDiff( 10 ) ); // fromLat
|
||||
writeInt( ilon + bc.decodeNoisyDiff( 10 ) ); // toLon
|
||||
writeInt( ilat + bc.decodeNoisyDiff( 10 ) ); // toLat
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int i=0; i< bitsize; i++ ) bc.decodeBit(); // unknown feature, just skip
|
||||
writeBoolean(bc.decodeBit()); // isPositive
|
||||
writeInt(ilon + bc.decodeNoisyDiff(10)); // fromLon
|
||||
writeInt(ilat + bc.decodeNoisyDiff(10)); // fromLat
|
||||
writeInt(ilon + bc.decodeNoisyDiff(10)); // toLon
|
||||
writeInt(ilat + bc.decodeNoisyDiff(10)); // toLat
|
||||
} else {
|
||||
for (int i = 0; i < bitsize; i++) bc.decodeBit(); // unknown feature, just skip
|
||||
}
|
||||
featureId = bc.decodeVarBits();
|
||||
}
|
||||
writeBoolean( false );
|
||||
writeBoolean(false);
|
||||
|
||||
selev += nodeEleDiff.decodeSignedValue();
|
||||
writeShort( (short) selev );
|
||||
writeShort((short) selev);
|
||||
TagValueWrapper nodeTags = nodeTagCoder.decodeTagValueSet();
|
||||
writeVarBytes( nodeTags == null ? null : nodeTags.data );
|
||||
writeVarBytes(nodeTags == null ? null : nodeTags.data);
|
||||
|
||||
int links = bc.decodeNoisyNumber( 1 );
|
||||
if ( debug ) System.out.println( "*** decoding node " + ilon + "/" + ilat + " with links=" + links );
|
||||
for( int li=0; li<links; li++ )
|
||||
{
|
||||
int links = bc.decodeNoisyNumber(1);
|
||||
if (debug)
|
||||
System.out.println("*** decoding node " + ilon + "/" + ilat + " with links=" + links);
|
||||
for (int li = 0; li < links; li++) {
|
||||
int sizeoffset = 0;
|
||||
int nodeIdx = n + nodeIdxDiff.decodeSignedValue();
|
||||
|
||||
|
||||
int dlon_remaining;
|
||||
int dlat_remaining;
|
||||
|
||||
boolean isReverse = false;
|
||||
if ( nodeIdx != n ) // internal (forward-) link
|
||||
if (nodeIdx != n) // internal (forward-) link
|
||||
{
|
||||
dlon_remaining = alon[nodeIdx] - ilon;
|
||||
dlat_remaining = alat[nodeIdx] - ilat;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
isReverse = bc.decodeBit();
|
||||
dlon_remaining = extLonDiff.decodeSignedValue();
|
||||
dlat_remaining = extLatDiff.decodeSignedValue();
|
||||
}
|
||||
if ( debug ) System.out.println( "*** decoding link to " + (ilon+dlon_remaining) + "/" + (ilat+dlat_remaining) + " extern=" + (nodeIdx == n) );
|
||||
if (debug)
|
||||
System.out.println("*** decoding link to " + (ilon + dlon_remaining) + "/" + (ilat + dlat_remaining) + " extern=" + (nodeIdx == n));
|
||||
|
||||
TagValueWrapper wayTags = wayTagCoder.decodeTagValueSet();
|
||||
|
||||
boolean linkValid = wayTags != null || wayValidator == null;
|
||||
if ( linkValid )
|
||||
{
|
||||
if (linkValid) {
|
||||
int startPointer = aboffset;
|
||||
sizeoffset = writeSizePlaceHolder();
|
||||
|
||||
writeVarLengthSigned( dlon_remaining );
|
||||
writeVarLengthSigned( dlat_remaining );
|
||||
writeVarLengthSigned(dlon_remaining);
|
||||
writeVarLengthSigned(dlat_remaining);
|
||||
|
||||
validBits[ n >> 5 ] |= 1 << n; // mark source-node valid
|
||||
if ( nodeIdx != n ) // valid internal (forward-) link
|
||||
validBits[n >> 5] |= 1 << n; // mark source-node valid
|
||||
if (nodeIdx != n) // valid internal (forward-) link
|
||||
{
|
||||
reverseLinks.addDataElement( nodeIdx, n ); // register reverse link
|
||||
finaldatasize += 1 + aboffset-startPointer; // reserve place for reverse
|
||||
validBits[ nodeIdx >> 5 ] |= 1 << nodeIdx; // mark target-node valid
|
||||
reverseLinks.addDataElement(nodeIdx, n); // register reverse link
|
||||
finaldatasize += 1 + aboffset - startPointer; // reserve place for reverse
|
||||
validBits[nodeIdx >> 5] |= 1 << nodeIdx; // mark target-node valid
|
||||
}
|
||||
writeModeAndDesc( isReverse, wayTags == null ? null : wayTags.data );
|
||||
writeModeAndDesc(isReverse, wayTags == null ? null : wayTags.data);
|
||||
}
|
||||
|
||||
if ( !isReverse ) // write geometry for forward links only
|
||||
if (!isReverse) // write geometry for forward links only
|
||||
{
|
||||
WaypointMatcher matcher = wayTags == null || wayTags.accessType < 2 ? null : waypointMatcher;
|
||||
int ilontarget = ilon + dlon_remaining;
|
||||
int ilattarget = ilat + dlat_remaining;
|
||||
if ( matcher != null )
|
||||
{
|
||||
if ( !matcher.start( ilon, ilat, ilontarget, ilattarget ) )
|
||||
{
|
||||
if (matcher != null) {
|
||||
if (!matcher.start(ilon, ilat, ilontarget, ilattarget)) {
|
||||
matcher = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int transcount = bc.decodeVarBits();
|
||||
if ( debug ) System.out.println( "*** decoding geometry with count=" + transcount );
|
||||
int count = transcount+1;
|
||||
for( int i=0; i<transcount; i++ )
|
||||
{
|
||||
int dlon = bc.decodePredictedValue( dlon_remaining/count );
|
||||
int dlat = bc.decodePredictedValue( dlat_remaining/count );
|
||||
if (debug) System.out.println("*** decoding geometry with count=" + transcount);
|
||||
int count = transcount + 1;
|
||||
for (int i = 0; i < transcount; i++) {
|
||||
int dlon = bc.decodePredictedValue(dlon_remaining / count);
|
||||
int dlat = bc.decodePredictedValue(dlat_remaining / count);
|
||||
dlon_remaining -= dlon;
|
||||
dlat_remaining -= dlat;
|
||||
count--;
|
||||
int elediff = transEleDiff.decodeSignedValue();
|
||||
if ( wayTags != null )
|
||||
{
|
||||
writeVarLengthSigned( dlon );
|
||||
writeVarLengthSigned( dlat );
|
||||
writeVarLengthSigned( elediff );
|
||||
if (wayTags != null) {
|
||||
writeVarLengthSigned(dlon);
|
||||
writeVarLengthSigned(dlat);
|
||||
writeVarLengthSigned(elediff);
|
||||
}
|
||||
|
||||
if ( matcher != null ) matcher.transferNode( ilontarget - dlon_remaining, ilattarget - dlat_remaining );
|
||||
|
||||
if (matcher != null)
|
||||
matcher.transferNode(ilontarget - dlon_remaining, ilattarget - dlat_remaining);
|
||||
}
|
||||
if ( matcher != null ) matcher.end();
|
||||
if (matcher != null) matcher.end();
|
||||
}
|
||||
if ( linkValid )
|
||||
{
|
||||
injectSize( sizeoffset );
|
||||
if (linkValid) {
|
||||
injectSize(sizeoffset);
|
||||
}
|
||||
}
|
||||
fapos[n] = aboffset;
|
||||
}
|
||||
|
||||
|
||||
// calculate final data size
|
||||
int finalsize = 0;
|
||||
int startpos = 0;
|
||||
for( int i=0; i<size; i++ )
|
||||
{
|
||||
for (int i = 0; i < size; i++) {
|
||||
int endpos = fapos[i];
|
||||
if ( ( validBits[ i >> 5 ] & (1 << i ) ) != 0 )
|
||||
{
|
||||
finaldatasize += endpos-startpos;
|
||||
finalsize++;
|
||||
if ((validBits[i >> 5] & (1 << i)) != 0) {
|
||||
finaldatasize += endpos - startpos;
|
||||
finalsize++;
|
||||
}
|
||||
startpos = endpos;
|
||||
}
|
||||
|
|
@ -240,29 +222,26 @@ public final class MicroCache2 extends MicroCache
|
|||
size = 0;
|
||||
|
||||
startpos = 0;
|
||||
for ( int n = 0; n < sizeOld; n++ )
|
||||
{
|
||||
for (int n = 0; n < sizeOld; n++) {
|
||||
int endpos = faposOld[n];
|
||||
if ( ( validBits[ n >> 5 ] & (1 << n ) ) != 0 )
|
||||
{
|
||||
if ((validBits[n >> 5] & (1 << n)) != 0) {
|
||||
int len = endpos - startpos;
|
||||
System.arraycopy( abOld, startpos, ab, aboffset, len );
|
||||
if ( debug )
|
||||
System.out.println( "*** copied " + len + " bytes from " + aboffset + " for node " + n );
|
||||
System.arraycopy(abOld, startpos, ab, aboffset, len);
|
||||
if (debug)
|
||||
System.out.println("*** copied " + len + " bytes from " + aboffset + " for node " + n);
|
||||
aboffset += len;
|
||||
|
||||
int cnt = reverseLinks.initList( n );
|
||||
if ( debug )
|
||||
System.out.println( "*** appending " + cnt + " reverse links for node " + n );
|
||||
int cnt = reverseLinks.initList(n);
|
||||
if (debug)
|
||||
System.out.println("*** appending " + cnt + " reverse links for node " + n);
|
||||
|
||||
for ( int ri = 0; ri < cnt; ri++ )
|
||||
{
|
||||
for (int ri = 0; ri < cnt; ri++) {
|
||||
int nodeIdx = reverseLinks.getDataElement();
|
||||
int sizeoffset = writeSizePlaceHolder();
|
||||
writeVarLengthSigned( alon[nodeIdx] - alon[n] );
|
||||
writeVarLengthSigned( alat[nodeIdx] - alat[n] );
|
||||
writeModeAndDesc( true, null );
|
||||
injectSize( sizeoffset );
|
||||
writeVarLengthSigned(alon[nodeIdx] - alon[n]);
|
||||
writeVarLengthSigned(alat[nodeIdx] - alat[n]);
|
||||
writeModeAndDesc(true, null);
|
||||
injectSize(sizeoffset);
|
||||
}
|
||||
faid[size] = faidOld[n];
|
||||
fapos[size] = aboffset;
|
||||
|
|
@ -270,65 +249,59 @@ public final class MicroCache2 extends MicroCache
|
|||
}
|
||||
startpos = endpos;
|
||||
}
|
||||
init( size );
|
||||
init(size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long expandId( int id32 )
|
||||
{
|
||||
public long expandId(int id32) {
|
||||
int dlon = 0;
|
||||
int dlat = 0;
|
||||
|
||||
for( int bm = 1; bm < 0x8000; bm <<= 1 )
|
||||
{
|
||||
if ( (id32 & 1) != 0 ) dlon |= bm;
|
||||
if ( (id32 & 2) != 0 ) dlat |= bm;
|
||||
for (int bm = 1; bm < 0x8000; bm <<= 1) {
|
||||
if ((id32 & 1) != 0) dlon |= bm;
|
||||
if ((id32 & 2) != 0) dlat |= bm;
|
||||
id32 >>= 2;
|
||||
}
|
||||
|
||||
int lon32 = lonBase + dlon;
|
||||
int lat32 = latBase + dlat;
|
||||
|
||||
return ((long)lon32)<<32 | lat32;
|
||||
return ((long) lon32) << 32 | lat32;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int shrinkId( long id64 )
|
||||
{
|
||||
int lon32 = (int)(id64 >> 32);
|
||||
int lat32 = (int)(id64 & 0xffffffff);
|
||||
public int shrinkId(long id64) {
|
||||
int lon32 = (int) (id64 >> 32);
|
||||
int lat32 = (int) (id64 & 0xffffffff);
|
||||
int dlon = lon32 - lonBase;
|
||||
int dlat = lat32 - latBase;
|
||||
int id32 = 0;
|
||||
|
||||
for( int bm = 0x4000; bm > 0; bm >>= 1 )
|
||||
{
|
||||
for (int bm = 0x4000; bm > 0; bm >>= 1) {
|
||||
id32 <<= 2;
|
||||
if ( ( dlon & bm ) != 0 ) id32 |= 1;
|
||||
if ( ( dlat & bm ) != 0 ) id32 |= 2;
|
||||
if ((dlon & bm) != 0) id32 |= 1;
|
||||
if ((dlat & bm) != 0) id32 |= 2;
|
||||
}
|
||||
return id32;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInternal( int ilon, int ilat )
|
||||
{
|
||||
public boolean isInternal(int ilon, int ilat) {
|
||||
return ilon >= lonBase && ilon < lonBase + cellsize
|
||||
&& ilat >= latBase && ilat < latBase + cellsize;
|
||||
&& ilat >= latBase && ilat < latBase + cellsize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int encodeMicroCache( byte[] buffer )
|
||||
{
|
||||
HashMap<Long,Integer> idMap = new HashMap<Long,Integer>();
|
||||
for( int n=0; n<size; n++ ) // loop over nodes
|
||||
public int encodeMicroCache(byte[] buffer) {
|
||||
HashMap<Long, Integer> idMap = new HashMap<Long, Integer>();
|
||||
for (int n = 0; n < size; n++) // loop over nodes
|
||||
{
|
||||
idMap.put( Long.valueOf( expandId( faid[n] ) ), Integer.valueOf( n ) );
|
||||
idMap.put(Long.valueOf(expandId(faid[n])), Integer.valueOf(n));
|
||||
}
|
||||
|
||||
IntegerFifo3Pass linkCounts = new IntegerFifo3Pass( 256 );
|
||||
IntegerFifo3Pass transCounts = new IntegerFifo3Pass( 256 );
|
||||
IntegerFifo3Pass restrictionBits = new IntegerFifo3Pass( 16 );
|
||||
IntegerFifo3Pass linkCounts = new IntegerFifo3Pass(256);
|
||||
IntegerFifo3Pass transCounts = new IntegerFifo3Pass(256);
|
||||
IntegerFifo3Pass restrictionBits = new IntegerFifo3Pass(16);
|
||||
|
||||
TagValueCoder wayTagCoder = new TagValueCoder();
|
||||
TagValueCoder nodeTagCoder = new TagValueCoder();
|
||||
|
|
@ -337,182 +310,173 @@ public final class MicroCache2 extends MicroCache
|
|||
NoisyDiffCoder extLonDiff = new NoisyDiffCoder();
|
||||
NoisyDiffCoder extLatDiff = new NoisyDiffCoder();
|
||||
NoisyDiffCoder transEleDiff = new NoisyDiffCoder();
|
||||
|
||||
|
||||
int netdatasize = 0;
|
||||
|
||||
for(int pass=1;; pass++) // 3 passes: counters, stat-collection, encoding
|
||||
for (int pass = 1; ; pass++) // 3 passes: counters, stat-collection, encoding
|
||||
{
|
||||
boolean dostats = pass == 3;
|
||||
boolean dodebug = debug && pass == 3;
|
||||
|
||||
if ( pass < 3 ) netdatasize = fapos[size-1];
|
||||
|
||||
StatCoderContext bc = new StatCoderContext( buffer );
|
||||
|
||||
if (pass < 3) netdatasize = fapos[size - 1];
|
||||
|
||||
StatCoderContext bc = new StatCoderContext(buffer);
|
||||
|
||||
linkCounts.init();
|
||||
transCounts.init();
|
||||
restrictionBits.init();
|
||||
|
||||
wayTagCoder.encodeDictionary( bc );
|
||||
if ( dostats ) bc.assignBits( "wayTagDictionary" );
|
||||
nodeTagCoder.encodeDictionary( bc );
|
||||
if ( dostats ) bc.assignBits( "nodeTagDictionary" );
|
||||
nodeIdxDiff.encodeDictionary( bc );
|
||||
nodeEleDiff.encodeDictionary( bc );
|
||||
extLonDiff.encodeDictionary( bc );
|
||||
extLatDiff.encodeDictionary( bc );
|
||||
transEleDiff.encodeDictionary( bc );
|
||||
if ( dostats ) bc.assignBits( "noisebits" );
|
||||
bc.encodeNoisyNumber( size, 5 );
|
||||
if ( dostats ) bc.assignBits( "nodecount" );
|
||||
bc.encodeSortedArray( faid, 0, size, 0x20000000, 0 );
|
||||
if ( dostats ) bc.assignBits( "node-positions" );
|
||||
bc.encodeNoisyNumber( netdatasize, 10 ); // net-size
|
||||
if ( dostats ) bc.assignBits( "netdatasize" );
|
||||
if ( dodebug ) System.out.println( "*** encoding cache of size=" + size );
|
||||
wayTagCoder.encodeDictionary(bc);
|
||||
if (dostats) bc.assignBits("wayTagDictionary");
|
||||
nodeTagCoder.encodeDictionary(bc);
|
||||
if (dostats) bc.assignBits("nodeTagDictionary");
|
||||
nodeIdxDiff.encodeDictionary(bc);
|
||||
nodeEleDiff.encodeDictionary(bc);
|
||||
extLonDiff.encodeDictionary(bc);
|
||||
extLatDiff.encodeDictionary(bc);
|
||||
transEleDiff.encodeDictionary(bc);
|
||||
if (dostats) bc.assignBits("noisebits");
|
||||
bc.encodeNoisyNumber(size, 5);
|
||||
if (dostats) bc.assignBits("nodecount");
|
||||
bc.encodeSortedArray(faid, 0, size, 0x20000000, 0);
|
||||
if (dostats) bc.assignBits("node-positions");
|
||||
bc.encodeNoisyNumber(netdatasize, 10); // net-size
|
||||
if (dostats) bc.assignBits("netdatasize");
|
||||
if (dodebug) System.out.println("*** encoding cache of size=" + size);
|
||||
int lastSelev = 0;
|
||||
|
||||
for( int n=0; n<size; n++ ) // loop over nodes
|
||||
|
||||
for (int n = 0; n < size; n++) // loop over nodes
|
||||
{
|
||||
aboffset = startPos( n );
|
||||
aboffset = startPos(n);
|
||||
aboffsetEnd = fapos[n];
|
||||
if ( dodebug ) System.out.println( "*** encoding node " + n + " from " + aboffset + " to " + aboffsetEnd );
|
||||
if (dodebug)
|
||||
System.out.println("*** encoding node " + n + " from " + aboffset + " to " + aboffsetEnd);
|
||||
|
||||
long id64 = expandId( faid[n] );
|
||||
int ilon = (int)(id64 >> 32);
|
||||
int ilat = (int)(id64 & 0xffffffff);
|
||||
long id64 = expandId(faid[n]);
|
||||
int ilon = (int) (id64 >> 32);
|
||||
int ilat = (int) (id64 & 0xffffffff);
|
||||
|
||||
if ( aboffset == aboffsetEnd )
|
||||
{
|
||||
bc.encodeVarBits( 13 ); // empty node escape (delta files only)
|
||||
if (aboffset == aboffsetEnd) {
|
||||
bc.encodeVarBits(13); // empty node escape (delta files only)
|
||||
continue;
|
||||
}
|
||||
|
||||
// write turn restrictions
|
||||
while( readBoolean() )
|
||||
{
|
||||
while (readBoolean()) {
|
||||
short exceptions = readShort(); // except bikes, psv, ...
|
||||
if ( exceptions != 0 )
|
||||
{
|
||||
bc.encodeVarBits( 2 ); // 2 = tr exceptions
|
||||
bc.encodeNoisyNumber( 10 , 5 ); // bit-count
|
||||
bc.encodeBounded( 1023 , exceptions & 1023 );
|
||||
if (exceptions != 0) {
|
||||
bc.encodeVarBits(2); // 2 = tr exceptions
|
||||
bc.encodeNoisyNumber(10, 5); // bit-count
|
||||
bc.encodeBounded(1023, exceptions & 1023);
|
||||
}
|
||||
bc.encodeVarBits( 1 ); // 1 = turn restriction
|
||||
bc.encodeNoisyNumber( restrictionBits.getNext(), 5 ); // bit-count using look-ahead fifo
|
||||
bc.encodeVarBits(1); // 1 = turn restriction
|
||||
bc.encodeNoisyNumber(restrictionBits.getNext(), 5); // bit-count using look-ahead fifo
|
||||
long b0 = bc.getWritingBitPosition();
|
||||
bc.encodeBit( readBoolean() ); // isPositive
|
||||
bc.encodeNoisyDiff( readInt() - ilon, 10 ); // fromLon
|
||||
bc.encodeNoisyDiff( readInt() - ilat, 10 ); // fromLat
|
||||
bc.encodeNoisyDiff( readInt() - ilon, 10 ); // toLon
|
||||
bc.encodeNoisyDiff( readInt() - ilat, 10 ); // toLat
|
||||
restrictionBits.add( (int)( bc.getWritingBitPosition() - b0 ) );
|
||||
bc.encodeBit(readBoolean()); // isPositive
|
||||
bc.encodeNoisyDiff(readInt() - ilon, 10); // fromLon
|
||||
bc.encodeNoisyDiff(readInt() - ilat, 10); // fromLat
|
||||
bc.encodeNoisyDiff(readInt() - ilon, 10); // toLon
|
||||
bc.encodeNoisyDiff(readInt() - ilat, 10); // toLat
|
||||
restrictionBits.add((int) (bc.getWritingBitPosition() - b0));
|
||||
}
|
||||
bc.encodeVarBits( 0 ); // end of extra data
|
||||
bc.encodeVarBits(0); // end of extra data
|
||||
|
||||
if ( dostats ) bc.assignBits( "extradata" );
|
||||
if (dostats) bc.assignBits("extradata");
|
||||
|
||||
int selev = readShort();
|
||||
nodeEleDiff.encodeSignedValue( selev - lastSelev );
|
||||
if ( dostats ) bc.assignBits( "nodeele" );
|
||||
nodeEleDiff.encodeSignedValue(selev - lastSelev);
|
||||
if (dostats) bc.assignBits("nodeele");
|
||||
lastSelev = selev;
|
||||
nodeTagCoder.encodeTagValueSet( readVarBytes() );
|
||||
if ( dostats ) bc.assignBits( "nodeTagIdx" );
|
||||
nodeTagCoder.encodeTagValueSet(readVarBytes());
|
||||
if (dostats) bc.assignBits("nodeTagIdx");
|
||||
int nlinks = linkCounts.getNext();
|
||||
if ( dodebug ) System.out.println( "*** nlinks=" + nlinks );
|
||||
bc.encodeNoisyNumber( nlinks, 1 );
|
||||
if ( dostats ) bc.assignBits( "link-counts" );
|
||||
|
||||
if (dodebug) System.out.println("*** nlinks=" + nlinks);
|
||||
bc.encodeNoisyNumber(nlinks, 1);
|
||||
if (dostats) bc.assignBits("link-counts");
|
||||
|
||||
nlinks = 0;
|
||||
while( hasMoreData() ) // loop over links
|
||||
while (hasMoreData()) // loop over links
|
||||
{
|
||||
// read link data
|
||||
int startPointer = aboffset;
|
||||
int endPointer = getEndPointer();
|
||||
|
||||
|
||||
int ilonlink = ilon + readVarLengthSigned();
|
||||
int ilatlink = ilat + readVarLengthSigned();
|
||||
|
||||
|
||||
int sizecode = readVarLengthUnsigned();
|
||||
boolean isReverse = ( sizecode & 1 ) != 0;
|
||||
boolean isReverse = (sizecode & 1) != 0;
|
||||
int descSize = sizecode >> 1;
|
||||
byte[] description = null;
|
||||
if ( descSize > 0 )
|
||||
{
|
||||
if (descSize > 0) {
|
||||
description = new byte[descSize];
|
||||
readFully( description );
|
||||
readFully(description);
|
||||
}
|
||||
|
||||
long link64 = ((long)ilonlink)<<32 | ilatlink;
|
||||
Integer idx = idMap.get( Long.valueOf( link64 ) );
|
||||
|
||||
long link64 = ((long) ilonlink) << 32 | ilatlink;
|
||||
Integer idx = idMap.get(Long.valueOf(link64));
|
||||
boolean isInternal = idx != null;
|
||||
|
||||
if ( isReverse && isInternal )
|
||||
{
|
||||
if ( dodebug ) System.out.println( "*** NOT encoding link reverse=" + isReverse + " internal=" + isInternal );
|
||||
netdatasize -= aboffset-startPointer;
|
||||
if (isReverse && isInternal) {
|
||||
if (dodebug)
|
||||
System.out.println("*** NOT encoding link reverse=" + isReverse + " internal=" + isInternal);
|
||||
netdatasize -= aboffset - startPointer;
|
||||
continue; // do not encode internal reverse links
|
||||
}
|
||||
if ( dodebug ) System.out.println( "*** encoding link reverse=" + isReverse + " internal=" + isInternal );
|
||||
if (dodebug)
|
||||
System.out.println("*** encoding link reverse=" + isReverse + " internal=" + isInternal);
|
||||
nlinks++;
|
||||
|
||||
if ( isInternal )
|
||||
{
|
||||
|
||||
if (isInternal) {
|
||||
int nodeIdx = idx.intValue();
|
||||
if ( dodebug ) System.out.println( "*** target nodeIdx=" + nodeIdx );
|
||||
if ( nodeIdx == n ) throw new RuntimeException( "ups: self ref?" );
|
||||
nodeIdxDiff.encodeSignedValue( nodeIdx - n );
|
||||
if ( dostats ) bc.assignBits( "nodeIdx" );
|
||||
if (dodebug) System.out.println("*** target nodeIdx=" + nodeIdx);
|
||||
if (nodeIdx == n) throw new RuntimeException("ups: self ref?");
|
||||
nodeIdxDiff.encodeSignedValue(nodeIdx - n);
|
||||
if (dostats) bc.assignBits("nodeIdx");
|
||||
} else {
|
||||
nodeIdxDiff.encodeSignedValue(0);
|
||||
bc.encodeBit(isReverse);
|
||||
extLonDiff.encodeSignedValue(ilonlink - ilon);
|
||||
extLatDiff.encodeSignedValue(ilatlink - ilat);
|
||||
if (dostats) bc.assignBits("externalNode");
|
||||
}
|
||||
else
|
||||
{
|
||||
nodeIdxDiff.encodeSignedValue( 0 );
|
||||
bc.encodeBit( isReverse );
|
||||
extLonDiff.encodeSignedValue( ilonlink - ilon );
|
||||
extLatDiff.encodeSignedValue( ilatlink - ilat );
|
||||
if ( dostats ) bc.assignBits( "externalNode" );
|
||||
}
|
||||
wayTagCoder.encodeTagValueSet( description );
|
||||
if ( dostats ) bc.assignBits( "wayDescIdx" );
|
||||
|
||||
if ( !isReverse )
|
||||
{
|
||||
byte[] geometry = readDataUntil( endPointer );
|
||||
wayTagCoder.encodeTagValueSet(description);
|
||||
if (dostats) bc.assignBits("wayDescIdx");
|
||||
|
||||
if (!isReverse) {
|
||||
byte[] geometry = readDataUntil(endPointer);
|
||||
// write transition nodes
|
||||
int count = transCounts.getNext();
|
||||
if ( dodebug ) System.out.println( "*** encoding geometry with count=" + count );
|
||||
bc.encodeVarBits( count++ );
|
||||
if ( dostats ) bc.assignBits( "transcount" );
|
||||
if (dodebug) System.out.println("*** encoding geometry with count=" + count);
|
||||
bc.encodeVarBits(count++);
|
||||
if (dostats) bc.assignBits("transcount");
|
||||
int transcount = 0;
|
||||
if ( geometry != null )
|
||||
{
|
||||
if (geometry != null) {
|
||||
int dlon_remaining = ilonlink - ilon;
|
||||
int dlat_remaining = ilatlink - ilat;
|
||||
|
||||
ByteDataReader r = new ByteDataReader( geometry );
|
||||
while ( r.hasMoreData() )
|
||||
{
|
||||
|
||||
ByteDataReader r = new ByteDataReader(geometry);
|
||||
while (r.hasMoreData()) {
|
||||
transcount++;
|
||||
|
||||
|
||||
int dlon = r.readVarLengthSigned();
|
||||
int dlat = r.readVarLengthSigned();
|
||||
bc.encodePredictedValue( dlon, dlon_remaining/count );
|
||||
bc.encodePredictedValue( dlat, dlat_remaining/count );
|
||||
bc.encodePredictedValue(dlon, dlon_remaining / count);
|
||||
bc.encodePredictedValue(dlat, dlat_remaining / count);
|
||||
dlon_remaining -= dlon;
|
||||
dlat_remaining -= dlat;
|
||||
if ( count > 1 ) count--;
|
||||
if ( dostats ) bc.assignBits( "transpos" );
|
||||
transEleDiff.encodeSignedValue( r.readVarLengthSigned() );
|
||||
if ( dostats ) bc.assignBits( "transele" );
|
||||
if (count > 1) count--;
|
||||
if (dostats) bc.assignBits("transpos");
|
||||
transEleDiff.encodeSignedValue(r.readVarLengthSigned());
|
||||
if (dostats) bc.assignBits("transele");
|
||||
}
|
||||
}
|
||||
transCounts.add( transcount );
|
||||
transCounts.add(transcount);
|
||||
}
|
||||
}
|
||||
linkCounts.add( nlinks );
|
||||
linkCounts.add(nlinks);
|
||||
}
|
||||
if ( pass == 3 )
|
||||
{
|
||||
if (pass == 3) {
|
||||
return bc.closeAndGetEncodedLength();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,12 +4,11 @@ package btools.codec;
|
|||
* Encoder/Decoder for signed integers that automatically detects the typical
|
||||
* range of these numbers to determine a noisy-bit count as a very simple
|
||||
* dictionary
|
||||
*
|
||||
* <p>
|
||||
* Adapted for 3-pass encoding (counters -> statistics -> encoding )
|
||||
* but doesn't do anything at pass1
|
||||
*/
|
||||
public final class NoisyDiffCoder
|
||||
{
|
||||
public final class NoisyDiffCoder {
|
||||
private int tot;
|
||||
private int[] freqs;
|
||||
private int noisybits;
|
||||
|
|
@ -19,8 +18,7 @@ public final class NoisyDiffCoder
|
|||
/**
|
||||
* Create a decoder and read the noisy-bit count from the gibe context
|
||||
*/
|
||||
public NoisyDiffCoder( StatCoderContext bc )
|
||||
{
|
||||
public NoisyDiffCoder(StatCoderContext bc) {
|
||||
noisybits = bc.decodeVarBits();
|
||||
this.bc = bc;
|
||||
}
|
||||
|
|
@ -28,60 +26,49 @@ public final class NoisyDiffCoder
|
|||
/**
|
||||
* Create an encoder for 3-pass-encoding
|
||||
*/
|
||||
public NoisyDiffCoder()
|
||||
{
|
||||
public NoisyDiffCoder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* encodes a signed int (pass3 only, stats collection in pass2)
|
||||
*/
|
||||
public void encodeSignedValue( int value )
|
||||
{
|
||||
if ( pass == 3 )
|
||||
{
|
||||
bc.encodeNoisyDiff( value, noisybits );
|
||||
}
|
||||
else if ( pass == 2 )
|
||||
{
|
||||
count( value < 0 ? -value : value );
|
||||
public void encodeSignedValue(int value) {
|
||||
if (pass == 3) {
|
||||
bc.encodeNoisyDiff(value, noisybits);
|
||||
} else if (pass == 2) {
|
||||
count(value < 0 ? -value : value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* decodes a signed int
|
||||
*/
|
||||
public int decodeSignedValue()
|
||||
{
|
||||
return bc.decodeNoisyDiff( noisybits );
|
||||
public int decodeSignedValue() {
|
||||
return bc.decodeNoisyDiff(noisybits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new encoding pass and (in pass3) calculates the noisy-bit count
|
||||
* from the stats collected in pass2 and writes that to the given context
|
||||
*/
|
||||
public void encodeDictionary( StatCoderContext bc )
|
||||
{
|
||||
if ( ++pass == 3 )
|
||||
{
|
||||
public void encodeDictionary(StatCoderContext bc) {
|
||||
if (++pass == 3) {
|
||||
// how many noisy bits?
|
||||
for ( noisybits = 0; noisybits < 14 && tot > 0; noisybits++ )
|
||||
{
|
||||
if ( freqs[noisybits] < ( tot >> 1 ) )
|
||||
for (noisybits = 0; noisybits < 14 && tot > 0; noisybits++) {
|
||||
if (freqs[noisybits] < (tot >> 1))
|
||||
break;
|
||||
}
|
||||
bc.encodeVarBits( noisybits );
|
||||
bc.encodeVarBits(noisybits);
|
||||
}
|
||||
this.bc = bc;
|
||||
}
|
||||
|
||||
private void count( int value )
|
||||
{
|
||||
if ( freqs == null )
|
||||
private void count(int value) {
|
||||
if (freqs == null)
|
||||
freqs = new int[14];
|
||||
int bm = 1;
|
||||
for ( int i = 0; i < 14; i++ )
|
||||
{
|
||||
if ( value < bm )
|
||||
for (int i = 0; i < 14; i++) {
|
||||
if (value < bm)
|
||||
break;
|
||||
else
|
||||
freqs[i]++;
|
||||
|
|
|
|||
|
|
@ -4,23 +4,19 @@ import java.util.TreeMap;
|
|||
|
||||
import btools.util.BitCoderContext;
|
||||
|
||||
public final class StatCoderContext extends BitCoderContext
|
||||
{
|
||||
public final class StatCoderContext extends BitCoderContext {
|
||||
private static TreeMap<String, long[]> statsPerName;
|
||||
private long lastbitpos = 0;
|
||||
|
||||
|
||||
private static final int[] noisy_bits = new int[1024];
|
||||
|
||||
static
|
||||
{
|
||||
static {
|
||||
// noisybits lookup
|
||||
for( int i=0; i<1024; i++ )
|
||||
{
|
||||
for (int i = 0; i < 1024; i++) {
|
||||
int p = i;
|
||||
int noisybits = 0;
|
||||
while (p > 2)
|
||||
{
|
||||
while (p > 2) {
|
||||
noisybits++;
|
||||
p >>= 1;
|
||||
}
|
||||
|
|
@ -29,29 +25,25 @@ public final class StatCoderContext extends BitCoderContext
|
|||
}
|
||||
|
||||
|
||||
public StatCoderContext( byte[] ab )
|
||||
{
|
||||
super( ab );
|
||||
public StatCoderContext(byte[] ab) {
|
||||
super(ab);
|
||||
}
|
||||
|
||||
/**
|
||||
* assign the de-/encoded bits since the last call assignBits to the given
|
||||
* name. Used for encoding statistics
|
||||
*
|
||||
*
|
||||
* @see #getBitReport
|
||||
*/
|
||||
public void assignBits( String name )
|
||||
{
|
||||
public void assignBits(String name) {
|
||||
long bitpos = getWritingBitPosition();
|
||||
if ( statsPerName == null )
|
||||
{
|
||||
if (statsPerName == null) {
|
||||
statsPerName = new TreeMap<String, long[]>();
|
||||
}
|
||||
long[] stats = statsPerName.get( name );
|
||||
if ( stats == null )
|
||||
{
|
||||
long[] stats = statsPerName.get(name);
|
||||
if (stats == null) {
|
||||
stats = new long[2];
|
||||
statsPerName.put( name, stats );
|
||||
statsPerName.put(name, stats);
|
||||
}
|
||||
stats[0] += bitpos - lastbitpos;
|
||||
stats[1] += 1;
|
||||
|
|
@ -60,20 +52,17 @@ public final class StatCoderContext extends BitCoderContext
|
|||
|
||||
/**
|
||||
* Get a textual report on the bit-statistics
|
||||
*
|
||||
*
|
||||
* @see #assignBits
|
||||
*/
|
||||
public static String getBitReport()
|
||||
{
|
||||
if ( statsPerName == null )
|
||||
{
|
||||
public static String getBitReport() {
|
||||
if (statsPerName == null) {
|
||||
return "<empty bit report>";
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for ( String name : statsPerName.keySet() )
|
||||
{
|
||||
long[] stats = statsPerName.get( name );
|
||||
sb.append( name + " count=" + stats[1] + " bits=" + stats[0] + "\n" );
|
||||
for (String name : statsPerName.keySet()) {
|
||||
long[] stats = statsPerName.get(name);
|
||||
sb.append(name + " count=" + stats[1] + " bits=" + stats[0] + "\n");
|
||||
}
|
||||
statsPerName = null;
|
||||
return sb.toString();
|
||||
|
|
@ -82,76 +71,65 @@ public final class StatCoderContext extends BitCoderContext
|
|||
/**
|
||||
* encode an unsigned integer with some of of least significant bits
|
||||
* considered noisy
|
||||
*
|
||||
*
|
||||
* @see #decodeNoisyNumber
|
||||
*/
|
||||
public void encodeNoisyNumber( int value, int noisybits )
|
||||
{
|
||||
if ( value < 0 )
|
||||
{
|
||||
throw new IllegalArgumentException( "encodeVarBits expects positive value" );
|
||||
public void encodeNoisyNumber(int value, int noisybits) {
|
||||
if (value < 0) {
|
||||
throw new IllegalArgumentException("encodeVarBits expects positive value");
|
||||
}
|
||||
if ( noisybits > 0 )
|
||||
{
|
||||
int mask = 0xffffffff >>> ( 32 - noisybits );
|
||||
encodeBounded( mask, value & mask );
|
||||
if (noisybits > 0) {
|
||||
int mask = 0xffffffff >>> (32 - noisybits);
|
||||
encodeBounded(mask, value & mask);
|
||||
value >>= noisybits;
|
||||
}
|
||||
encodeVarBits( value );
|
||||
encodeVarBits(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* decode an unsigned integer with some of of least significant bits
|
||||
* considered noisy
|
||||
*
|
||||
*
|
||||
* @see #encodeNoisyNumber
|
||||
*/
|
||||
public int decodeNoisyNumber( int noisybits )
|
||||
{
|
||||
int value = decodeBits( noisybits );
|
||||
return value | ( decodeVarBits() << noisybits );
|
||||
public int decodeNoisyNumber(int noisybits) {
|
||||
int value = decodeBits(noisybits);
|
||||
return value | (decodeVarBits() << noisybits);
|
||||
}
|
||||
|
||||
/**
|
||||
* encode a signed integer with some of of least significant bits considered
|
||||
* noisy
|
||||
*
|
||||
*
|
||||
* @see #decodeNoisyDiff
|
||||
*/
|
||||
public void encodeNoisyDiff( int value, int noisybits )
|
||||
{
|
||||
if ( noisybits > 0 )
|
||||
{
|
||||
value += 1 << ( noisybits - 1 );
|
||||
int mask = 0xffffffff >>> ( 32 - noisybits );
|
||||
encodeBounded( mask, value & mask );
|
||||
public void encodeNoisyDiff(int value, int noisybits) {
|
||||
if (noisybits > 0) {
|
||||
value += 1 << (noisybits - 1);
|
||||
int mask = 0xffffffff >>> (32 - noisybits);
|
||||
encodeBounded(mask, value & mask);
|
||||
value >>= noisybits;
|
||||
}
|
||||
encodeVarBits( value < 0 ? -value : value );
|
||||
if ( value != 0 )
|
||||
{
|
||||
encodeBit( value < 0 );
|
||||
encodeVarBits(value < 0 ? -value : value);
|
||||
if (value != 0) {
|
||||
encodeBit(value < 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* decode a signed integer with some of of least significant bits considered
|
||||
* noisy
|
||||
*
|
||||
*
|
||||
* @see #encodeNoisyDiff
|
||||
*/
|
||||
public int decodeNoisyDiff( int noisybits )
|
||||
{
|
||||
public int decodeNoisyDiff(int noisybits) {
|
||||
int value = 0;
|
||||
if ( noisybits > 0 )
|
||||
{
|
||||
value = decodeBits( noisybits ) - ( 1 << ( noisybits - 1 ) );
|
||||
if (noisybits > 0) {
|
||||
value = decodeBits(noisybits) - (1 << (noisybits - 1));
|
||||
}
|
||||
int val2 = decodeVarBits() << noisybits;
|
||||
if ( val2 != 0 )
|
||||
{
|
||||
if ( decodeBit() )
|
||||
{
|
||||
if (val2 != 0) {
|
||||
if (decodeBit()) {
|
||||
val2 = -val2;
|
||||
}
|
||||
}
|
||||
|
|
@ -161,38 +139,34 @@ public final class StatCoderContext extends BitCoderContext
|
|||
/**
|
||||
* encode a signed integer with the typical range and median taken from the
|
||||
* predicted value
|
||||
*
|
||||
*
|
||||
* @see #decodePredictedValue
|
||||
*/
|
||||
public void encodePredictedValue( int value, int predictor )
|
||||
{
|
||||
public void encodePredictedValue(int value, int predictor) {
|
||||
int p = predictor < 0 ? -predictor : predictor;
|
||||
int noisybits = 0;
|
||||
|
||||
while (p > 2)
|
||||
{
|
||||
while (p > 2) {
|
||||
noisybits++;
|
||||
p >>= 1;
|
||||
}
|
||||
encodeNoisyDiff( value - predictor, noisybits );
|
||||
encodeNoisyDiff(value - predictor, noisybits);
|
||||
}
|
||||
|
||||
/**
|
||||
* decode a signed integer with the typical range and median taken from the
|
||||
* predicted value
|
||||
*
|
||||
*
|
||||
* @see #encodePredictedValue
|
||||
*/
|
||||
public int decodePredictedValue( int predictor )
|
||||
{
|
||||
public int decodePredictedValue(int predictor) {
|
||||
int p = predictor < 0 ? -predictor : predictor;
|
||||
int noisybits = 0;
|
||||
while (p > 1023)
|
||||
{
|
||||
while (p > 1023) {
|
||||
noisybits++;
|
||||
p >>= 1;
|
||||
}
|
||||
return predictor + decodeNoisyDiff( noisybits + noisy_bits[p] );
|
||||
return predictor + decodeNoisyDiff(noisybits + noisy_bits[p]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -201,30 +175,22 @@ public final class StatCoderContext extends BitCoderContext
|
|||
* number of values with the current bit being 0. This yields an number of
|
||||
* bits per value that only depends on the typical distance between subsequent
|
||||
* values and also benefits
|
||||
*
|
||||
* @param values
|
||||
* the array to encode
|
||||
* @param offset
|
||||
* position in this array where to start
|
||||
* @param subsize
|
||||
* number of values to encode
|
||||
* @param nextbit
|
||||
* bitmask with the most significant bit set to 1
|
||||
* @param mask
|
||||
* should be 0
|
||||
*
|
||||
* @param values the array to encode
|
||||
* @param offset position in this array where to start
|
||||
* @param subsize number of values to encode
|
||||
* @param nextbit bitmask with the most significant bit set to 1
|
||||
* @param mask should be 0
|
||||
*/
|
||||
public void encodeSortedArray( int[] values, int offset, int subsize, int nextbit, int mask )
|
||||
{
|
||||
if ( subsize == 1 ) // last-choice shortcut
|
||||
public void encodeSortedArray(int[] values, int offset, int subsize, int nextbit, int mask) {
|
||||
if (subsize == 1) // last-choice shortcut
|
||||
{
|
||||
while (nextbit != 0)
|
||||
{
|
||||
encodeBit( ( values[offset] & nextbit ) != 0 );
|
||||
while (nextbit != 0) {
|
||||
encodeBit((values[offset] & nextbit) != 0);
|
||||
nextbit >>= 1;
|
||||
}
|
||||
}
|
||||
if ( nextbit == 0 )
|
||||
{
|
||||
if (nextbit == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -234,71 +200,55 @@ public final class StatCoderContext extends BitCoderContext
|
|||
// count 0-bit-fraction
|
||||
int i = offset;
|
||||
int end = subsize + offset;
|
||||
for ( ; i < end; i++ )
|
||||
{
|
||||
if ( ( values[i] & mask ) != data )
|
||||
{
|
||||
for (; i < end; i++) {
|
||||
if ((values[i] & mask) != data) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
int size1 = i - offset;
|
||||
int size2 = subsize - size1;
|
||||
|
||||
encodeBounded( subsize, size1 );
|
||||
if ( size1 > 0 )
|
||||
{
|
||||
encodeSortedArray( values, offset, size1, nextbit >> 1, mask );
|
||||
encodeBounded(subsize, size1);
|
||||
if (size1 > 0) {
|
||||
encodeSortedArray(values, offset, size1, nextbit >> 1, mask);
|
||||
}
|
||||
if ( size2 > 0 )
|
||||
{
|
||||
encodeSortedArray( values, i, size2, nextbit >> 1, mask );
|
||||
if (size2 > 0) {
|
||||
encodeSortedArray(values, i, size2, nextbit >> 1, mask);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param values the array to encode
|
||||
* @param offset position in this array where to start
|
||||
* @param subsize number of values to encode
|
||||
* @param nextbit bitmask with the most significant bit set to 1
|
||||
* @param value should be 0
|
||||
* @see #encodeSortedArray
|
||||
*
|
||||
* @param values
|
||||
* the array to encode
|
||||
* @param offset
|
||||
* position in this array where to start
|
||||
* @param subsize
|
||||
* number of values to encode
|
||||
* @param nextbit
|
||||
* bitmask with the most significant bit set to 1
|
||||
* @param value
|
||||
* should be 0
|
||||
*/
|
||||
public void decodeSortedArray( int[] values, int offset, int subsize, int nextbitpos, int value )
|
||||
{
|
||||
if ( subsize == 1 ) // last-choice shortcut
|
||||
public void decodeSortedArray(int[] values, int offset, int subsize, int nextbitpos, int value) {
|
||||
if (subsize == 1) // last-choice shortcut
|
||||
{
|
||||
if ( nextbitpos >= 0 )
|
||||
{
|
||||
value |= decodeBitsReverse( nextbitpos+1 );
|
||||
if (nextbitpos >= 0) {
|
||||
value |= decodeBitsReverse(nextbitpos + 1);
|
||||
}
|
||||
values[offset] = value;
|
||||
return;
|
||||
}
|
||||
if ( nextbitpos < 0 )
|
||||
{
|
||||
while (subsize-- > 0)
|
||||
{
|
||||
if (nextbitpos < 0) {
|
||||
while (subsize-- > 0) {
|
||||
values[offset++] = value;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int size1 = decodeBounded( subsize );
|
||||
int size1 = decodeBounded(subsize);
|
||||
int size2 = subsize - size1;
|
||||
|
||||
if ( size1 > 0 )
|
||||
{
|
||||
decodeSortedArray( values, offset, size1, nextbitpos-1, value );
|
||||
if (size1 > 0) {
|
||||
decodeSortedArray(values, offset, size1, nextbitpos - 1, value);
|
||||
}
|
||||
if ( size2 > 0 )
|
||||
{
|
||||
decodeSortedArray( values, offset + size1, size2, nextbitpos-1, value | (1 << nextbitpos) );
|
||||
if (size2 > 0) {
|
||||
decodeSortedArray(values, offset + size1, size2, nextbitpos - 1, value | (1 << nextbitpos));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,51 +8,42 @@ import btools.util.BitCoderContext;
|
|||
|
||||
/**
|
||||
* Encoder/Decoder for way-/node-descriptions
|
||||
*
|
||||
* <p>
|
||||
* It detects identical descriptions and sorts them
|
||||
* into a huffman-tree according to their frequencies
|
||||
*
|
||||
* <p>
|
||||
* Adapted for 3-pass encoding (counters -> statistics -> encoding )
|
||||
* but doesn't do anything at pass1
|
||||
*/
|
||||
public final class TagValueCoder
|
||||
{
|
||||
public final class TagValueCoder {
|
||||
private HashMap<TagValueSet, TagValueSet> identityMap;
|
||||
private Object tree;
|
||||
private BitCoderContext bc;
|
||||
private int pass;
|
||||
private int nextTagValueSetId;
|
||||
|
||||
public void encodeTagValueSet( byte[] data )
|
||||
{
|
||||
if ( pass == 1 )
|
||||
{
|
||||
public void encodeTagValueSet(byte[] data) {
|
||||
if (pass == 1) {
|
||||
return;
|
||||
}
|
||||
TagValueSet tvsProbe = new TagValueSet(nextTagValueSetId);
|
||||
tvsProbe.data = data;
|
||||
TagValueSet tvs = identityMap.get( tvsProbe );
|
||||
if ( pass == 3 )
|
||||
{
|
||||
bc.encodeBounded( tvs.range - 1, tvs.code );
|
||||
}
|
||||
else if ( pass == 2 )
|
||||
{
|
||||
if ( tvs == null )
|
||||
{
|
||||
TagValueSet tvs = identityMap.get(tvsProbe);
|
||||
if (pass == 3) {
|
||||
bc.encodeBounded(tvs.range - 1, tvs.code);
|
||||
} else if (pass == 2) {
|
||||
if (tvs == null) {
|
||||
tvs = tvsProbe;
|
||||
nextTagValueSetId++;
|
||||
identityMap.put( tvs, tvs );
|
||||
identityMap.put(tvs, tvs);
|
||||
}
|
||||
tvs.frequency++;
|
||||
}
|
||||
}
|
||||
|
||||
public TagValueWrapper decodeTagValueSet()
|
||||
{
|
||||
public TagValueWrapper decodeTagValueSet() {
|
||||
Object node = tree;
|
||||
while (node instanceof TreeNode)
|
||||
{
|
||||
while (node instanceof TreeNode) {
|
||||
TreeNode tn = (TreeNode) node;
|
||||
boolean nextBit = bc.decodeBit();
|
||||
node = nextBit ? tn.child2 : tn.child1;
|
||||
|
|
@ -60,104 +51,87 @@ public final class TagValueCoder
|
|||
return (TagValueWrapper) node;
|
||||
}
|
||||
|
||||
public void encodeDictionary( BitCoderContext bc )
|
||||
{
|
||||
if ( ++pass == 3 )
|
||||
{
|
||||
if ( identityMap.size() == 0 )
|
||||
{
|
||||
public void encodeDictionary(BitCoderContext bc) {
|
||||
if (++pass == 3) {
|
||||
if (identityMap.size() == 0) {
|
||||
TagValueSet dummy = new TagValueSet(nextTagValueSetId++);
|
||||
identityMap.put( dummy, dummy );
|
||||
identityMap.put(dummy, dummy);
|
||||
}
|
||||
PriorityQueue<TagValueSet> queue = new PriorityQueue<TagValueSet>(2*identityMap.size(), new TagValueSet.FrequencyComparator());
|
||||
PriorityQueue<TagValueSet> queue = new PriorityQueue<TagValueSet>(2 * identityMap.size(), new TagValueSet.FrequencyComparator());
|
||||
queue.addAll(identityMap.values());
|
||||
while (queue.size() > 1)
|
||||
{
|
||||
while (queue.size() > 1) {
|
||||
TagValueSet node = new TagValueSet(nextTagValueSetId++);
|
||||
node.child1 = queue.poll();
|
||||
node.child2 = queue.poll();
|
||||
node.frequency = node.child1.frequency + node.child2.frequency;
|
||||
queue.add( node );
|
||||
queue.add(node);
|
||||
}
|
||||
TagValueSet root = queue.poll();
|
||||
root.encode( bc, 1, 0 );
|
||||
root.encode(bc, 1, 0);
|
||||
}
|
||||
this.bc = bc;
|
||||
}
|
||||
|
||||
public TagValueCoder( BitCoderContext bc, DataBuffers buffers, TagValueValidator validator )
|
||||
{
|
||||
tree = decodeTree( bc, buffers, validator );
|
||||
public TagValueCoder(BitCoderContext bc, DataBuffers buffers, TagValueValidator validator) {
|
||||
tree = decodeTree(bc, buffers, validator);
|
||||
this.bc = bc;
|
||||
}
|
||||
|
||||
public TagValueCoder()
|
||||
{
|
||||
public TagValueCoder() {
|
||||
identityMap = new HashMap<TagValueSet, TagValueSet>();
|
||||
}
|
||||
|
||||
private Object decodeTree( BitCoderContext bc, DataBuffers buffers, TagValueValidator validator )
|
||||
{
|
||||
private Object decodeTree(BitCoderContext bc, DataBuffers buffers, TagValueValidator validator) {
|
||||
boolean isNode = bc.decodeBit();
|
||||
if ( isNode )
|
||||
{
|
||||
if (isNode) {
|
||||
TreeNode node = new TreeNode();
|
||||
node.child1 = decodeTree( bc, buffers, validator );
|
||||
node.child2 = decodeTree( bc, buffers, validator );
|
||||
node.child1 = decodeTree(bc, buffers, validator);
|
||||
node.child2 = decodeTree(bc, buffers, validator);
|
||||
return node;
|
||||
}
|
||||
|
||||
byte[] buffer = buffers.tagbuf1;
|
||||
BitCoderContext ctx = buffers.bctx1;
|
||||
ctx.reset( buffer );
|
||||
BitCoderContext ctx = buffers.bctx1;
|
||||
ctx.reset(buffer);
|
||||
|
||||
int inum = 0;
|
||||
int lastEncodedInum = 0;
|
||||
|
||||
boolean hasdata = false;
|
||||
for ( ;; )
|
||||
{
|
||||
for (; ; ) {
|
||||
int delta = bc.decodeVarBits();
|
||||
if ( !hasdata )
|
||||
{
|
||||
if ( delta == 0 )
|
||||
{
|
||||
if (!hasdata) {
|
||||
if (delta == 0) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if ( delta == 0 )
|
||||
{
|
||||
ctx.encodeVarBits( 0 );
|
||||
if (delta == 0) {
|
||||
ctx.encodeVarBits(0);
|
||||
break;
|
||||
}
|
||||
inum += delta;
|
||||
|
||||
int data = bc.decodeVarBits();
|
||||
|
||||
if ( validator == null || validator.isLookupIdxUsed( inum ) )
|
||||
{
|
||||
if (validator == null || validator.isLookupIdxUsed(inum)) {
|
||||
hasdata = true;
|
||||
ctx.encodeVarBits( inum - lastEncodedInum );
|
||||
ctx.encodeVarBits( data );
|
||||
ctx.encodeVarBits(inum - lastEncodedInum);
|
||||
ctx.encodeVarBits(data);
|
||||
lastEncodedInum = inum;
|
||||
}
|
||||
}
|
||||
|
||||
byte[] res;
|
||||
int len = ctx.closeAndGetEncodedLength();
|
||||
if ( validator == null )
|
||||
{
|
||||
if (validator == null) {
|
||||
res = new byte[len];
|
||||
System.arraycopy( buffer, 0, res, 0, len );
|
||||
}
|
||||
else
|
||||
{
|
||||
res = validator.unify( buffer, 0, len );
|
||||
System.arraycopy(buffer, 0, res, 0, len);
|
||||
} else {
|
||||
res = validator.unify(buffer, 0, len);
|
||||
}
|
||||
|
||||
int accessType = validator == null ? 2 : validator.accessType( res );
|
||||
if ( accessType > 0 )
|
||||
{
|
||||
int accessType = validator == null ? 2 : validator.accessType(res);
|
||||
if (accessType > 0) {
|
||||
TagValueWrapper w = new TagValueWrapper();
|
||||
w.data = res;
|
||||
w.accessType = accessType;
|
||||
|
|
@ -166,14 +140,12 @@ public final class TagValueCoder
|
|||
return null;
|
||||
}
|
||||
|
||||
public static final class TreeNode
|
||||
{
|
||||
public static final class TreeNode {
|
||||
public Object child1;
|
||||
public Object child2;
|
||||
}
|
||||
|
||||
public static final class TagValueSet
|
||||
{
|
||||
public static final class TagValueSet {
|
||||
public byte[] data;
|
||||
public int frequency;
|
||||
public int code;
|
||||
|
|
@ -182,66 +154,51 @@ public final class TagValueCoder
|
|||
public TagValueSet child2;
|
||||
private int id; // serial number to make the comparator well defined in case of equal frequencies
|
||||
|
||||
public TagValueSet( int id )
|
||||
{
|
||||
public TagValueSet(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void encode( BitCoderContext bc, int range, int code )
|
||||
{
|
||||
public void encode(BitCoderContext bc, int range, int code) {
|
||||
this.range = range;
|
||||
this.code = code;
|
||||
boolean isNode = child1 != null;
|
||||
bc.encodeBit( isNode );
|
||||
if ( isNode )
|
||||
{
|
||||
child1.encode( bc, range << 1, code );
|
||||
child2.encode( bc, range << 1, code + range );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( data == null )
|
||||
{
|
||||
bc.encodeVarBits( 0 );
|
||||
bc.encodeBit(isNode);
|
||||
if (isNode) {
|
||||
child1.encode(bc, range << 1, code);
|
||||
child2.encode(bc, range << 1, code + range);
|
||||
} else {
|
||||
if (data == null) {
|
||||
bc.encodeVarBits(0);
|
||||
return;
|
||||
}
|
||||
BitCoderContext src = new BitCoderContext( data );
|
||||
for ( ;; )
|
||||
{
|
||||
BitCoderContext src = new BitCoderContext(data);
|
||||
for (; ; ) {
|
||||
int delta = src.decodeVarBits();
|
||||
bc.encodeVarBits( delta );
|
||||
if ( delta == 0 )
|
||||
{
|
||||
bc.encodeVarBits(delta);
|
||||
if (delta == 0) {
|
||||
break;
|
||||
}
|
||||
int data = src.decodeVarBits();
|
||||
bc.encodeVarBits( data );
|
||||
bc.encodeVarBits(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals( Object o )
|
||||
{
|
||||
if ( o instanceof TagValueSet )
|
||||
{
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof TagValueSet) {
|
||||
TagValueSet tvs = (TagValueSet) o;
|
||||
if ( data == null )
|
||||
{
|
||||
if (data == null) {
|
||||
return tvs.data == null;
|
||||
}
|
||||
if ( tvs.data == null )
|
||||
{
|
||||
if (tvs.data == null) {
|
||||
return data == null;
|
||||
}
|
||||
if ( data.length != tvs.data.length )
|
||||
{
|
||||
if (data.length != tvs.data.length) {
|
||||
return false;
|
||||
}
|
||||
for ( int i = 0; i < data.length; i++ )
|
||||
{
|
||||
if ( data[i] != tvs.data[i] )
|
||||
{
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
if (data[i] != tvs.data[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -251,39 +208,34 @@ public final class TagValueCoder
|
|||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
if ( data == null )
|
||||
{
|
||||
public int hashCode() {
|
||||
if (data == null) {
|
||||
return 0;
|
||||
}
|
||||
int h = 17;
|
||||
for ( int i = 0; i < data.length; i++ )
|
||||
{
|
||||
h = ( h << 8 ) + data[i];
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
h = (h << 8) + data[i];
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
public static class FrequencyComparator implements Comparator<TagValueSet>
|
||||
{
|
||||
public static class FrequencyComparator implements Comparator<TagValueSet> {
|
||||
|
||||
@Override
|
||||
public int compare(TagValueSet tvs1, TagValueSet tvs2) {
|
||||
if ( tvs1.frequency < tvs2.frequency )
|
||||
if (tvs1.frequency < tvs2.frequency)
|
||||
return -1;
|
||||
if ( tvs1.frequency > tvs2.frequency )
|
||||
if (tvs1.frequency > tvs2.frequency)
|
||||
return 1;
|
||||
|
||||
// to avoid ordering instability, decide on the id if frequency is equal
|
||||
if ( tvs1.id < tvs2.id )
|
||||
if (tvs1.id < tvs2.id)
|
||||
return -1;
|
||||
if ( tvs1.id > tvs2.id )
|
||||
if (tvs1.id > tvs2.id)
|
||||
return 1;
|
||||
|
||||
if ( tvs1 != tvs2 )
|
||||
{
|
||||
throw new RuntimeException( "identity corruption!" );
|
||||
if (tvs1 != tvs2) {
|
||||
throw new RuntimeException("identity corruption!");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,16 @@
|
|||
package btools.codec;
|
||||
|
||||
|
||||
public interface TagValueValidator
|
||||
{
|
||||
public interface TagValueValidator {
|
||||
/**
|
||||
* @param tagValueSet the way description to check
|
||||
* @return 0 = nothing, 1=no matching, 2=normal
|
||||
*/
|
||||
public int accessType( byte[] tagValueSet );
|
||||
public int accessType(byte[] tagValueSet);
|
||||
|
||||
public byte[] unify( byte[] tagValueSet, int offset, int len );
|
||||
public byte[] unify(byte[] tagValueSet, int offset, int len);
|
||||
|
||||
public boolean isLookupIdxUsed( int idx );
|
||||
public boolean isLookupIdxUsed(int idx);
|
||||
|
||||
public void setDecodeForbidden( boolean decodeForbidden );
|
||||
public void setDecodeForbidden(boolean decodeForbidden);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ package btools.codec;
|
|||
* TagValueWrapper wrapps a description bitmap
|
||||
* to add the access-type
|
||||
*/
|
||||
public final class TagValueWrapper
|
||||
{
|
||||
public final class TagValueWrapper {
|
||||
public byte[] data;
|
||||
public int accessType;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,10 @@ package btools.codec;
|
|||
* from the decoder to find the closest
|
||||
* matches to the waypoints
|
||||
*/
|
||||
public interface WaypointMatcher
|
||||
{
|
||||
boolean start( int ilonStart, int ilatStart, int ilonTarget, int ilatTarget );
|
||||
void transferNode( int ilon, int ilat );
|
||||
public interface WaypointMatcher {
|
||||
boolean start(int ilonStart, int ilatStart, int ilonTarget, int ilatTarget);
|
||||
|
||||
void transferNode(int ilon, int ilat);
|
||||
|
||||
void end();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,50 +3,39 @@ package btools.codec;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class LinkedListContainerTest
|
||||
{
|
||||
public class LinkedListContainerTest {
|
||||
@Test
|
||||
public void linkedListTest1()
|
||||
{
|
||||
public void linkedListTest1() {
|
||||
int nlists = 553;
|
||||
|
||||
LinkedListContainer llc = new LinkedListContainer( nlists, null );
|
||||
LinkedListContainer llc = new LinkedListContainer(nlists, null);
|
||||
|
||||
for ( int ln = 0; ln < nlists; ln++ )
|
||||
{
|
||||
for ( int i = 0; i < 10; i++ )
|
||||
{
|
||||
llc.addDataElement( ln, ln * i );
|
||||
for (int ln = 0; ln < nlists; ln++) {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
llc.addDataElement(ln, ln * i);
|
||||
}
|
||||
}
|
||||
|
||||
for ( int i = 0; i < 10; i++ )
|
||||
{
|
||||
for ( int ln = 0; ln < nlists; ln++ )
|
||||
{
|
||||
llc.addDataElement( ln, ln * i );
|
||||
for (int i = 0; i < 10; i++) {
|
||||
for (int ln = 0; ln < nlists; ln++) {
|
||||
llc.addDataElement(ln, ln * i);
|
||||
}
|
||||
}
|
||||
|
||||
for ( int ln = 0; ln < nlists; ln++ )
|
||||
{
|
||||
int cnt = llc.initList( ln );
|
||||
Assert.assertTrue( "list size test", cnt == 20 );
|
||||
for (int ln = 0; ln < nlists; ln++) {
|
||||
int cnt = llc.initList(ln);
|
||||
Assert.assertTrue("list size test", cnt == 20);
|
||||
|
||||
for ( int i = 19; i >= 0; i-- )
|
||||
{
|
||||
for (int i = 19; i >= 0; i--) {
|
||||
int data = llc.getDataElement();
|
||||
Assert.assertTrue( "data value test", data == ln * ( i % 10 ) );
|
||||
Assert.assertTrue("data value test", data == ln * (i % 10));
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
llc.getDataElement();
|
||||
Assert.fail( "no more elements expected" );
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
Assert.fail("no more elements expected");
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,100 +6,79 @@ import java.util.Random;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class StatCoderContextTest
|
||||
{
|
||||
public class StatCoderContextTest {
|
||||
@Test
|
||||
public void noisyVarBitsEncodeDecodeTest()
|
||||
{
|
||||
public void noisyVarBitsEncodeDecodeTest() {
|
||||
byte[] ab = new byte[40000];
|
||||
StatCoderContext ctx = new StatCoderContext( ab );
|
||||
for ( int noisybits = 1; noisybits < 12; noisybits++ )
|
||||
{
|
||||
for ( int i = 0; i < 1000; i++ )
|
||||
{
|
||||
ctx.encodeNoisyNumber( i, noisybits );
|
||||
StatCoderContext ctx = new StatCoderContext(ab);
|
||||
for (int noisybits = 1; noisybits < 12; noisybits++) {
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
ctx.encodeNoisyNumber(i, noisybits);
|
||||
}
|
||||
}
|
||||
ctx.closeAndGetEncodedLength();
|
||||
ctx = new StatCoderContext( ab );
|
||||
ctx = new StatCoderContext(ab);
|
||||
|
||||
for ( int noisybits = 1; noisybits < 12; noisybits++ )
|
||||
{
|
||||
for ( int i = 0; i < 1000; i++ )
|
||||
{
|
||||
int value = ctx.decodeNoisyNumber( noisybits );
|
||||
if ( value != i )
|
||||
{
|
||||
Assert.fail( "value mismatch: noisybits=" + noisybits + " i=" + i + " value=" + value );
|
||||
for (int noisybits = 1; noisybits < 12; noisybits++) {
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
int value = ctx.decodeNoisyNumber(noisybits);
|
||||
if (value != i) {
|
||||
Assert.fail("value mismatch: noisybits=" + noisybits + " i=" + i + " value=" + value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noisySignedVarBitsEncodeDecodeTest()
|
||||
{
|
||||
public void noisySignedVarBitsEncodeDecodeTest() {
|
||||
byte[] ab = new byte[80000];
|
||||
StatCoderContext ctx = new StatCoderContext( ab );
|
||||
for ( int noisybits = 0; noisybits < 12; noisybits++ )
|
||||
{
|
||||
for ( int i = -1000; i < 1000; i++ )
|
||||
{
|
||||
ctx.encodeNoisyDiff( i, noisybits );
|
||||
StatCoderContext ctx = new StatCoderContext(ab);
|
||||
for (int noisybits = 0; noisybits < 12; noisybits++) {
|
||||
for (int i = -1000; i < 1000; i++) {
|
||||
ctx.encodeNoisyDiff(i, noisybits);
|
||||
}
|
||||
}
|
||||
ctx.closeAndGetEncodedLength();
|
||||
ctx = new StatCoderContext( ab );
|
||||
ctx = new StatCoderContext(ab);
|
||||
|
||||
for ( int noisybits = 0; noisybits < 12; noisybits++ )
|
||||
{
|
||||
for ( int i = -1000; i < 1000; i++ )
|
||||
{
|
||||
int value = ctx.decodeNoisyDiff( noisybits );
|
||||
if ( value != i )
|
||||
{
|
||||
Assert.fail( "value mismatch: noisybits=" + noisybits + " i=" + i + " value=" + value );
|
||||
for (int noisybits = 0; noisybits < 12; noisybits++) {
|
||||
for (int i = -1000; i < 1000; i++) {
|
||||
int value = ctx.decodeNoisyDiff(noisybits);
|
||||
if (value != i) {
|
||||
Assert.fail("value mismatch: noisybits=" + noisybits + " i=" + i + " value=" + value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void predictedValueEncodeDecodeTest()
|
||||
{
|
||||
public void predictedValueEncodeDecodeTest() {
|
||||
byte[] ab = new byte[80000];
|
||||
StatCoderContext ctx = new StatCoderContext( ab );
|
||||
for ( int value = -100; value < 100; value += 5 )
|
||||
{
|
||||
for ( int predictor = -200; predictor < 200; predictor += 7 )
|
||||
{
|
||||
ctx.encodePredictedValue( value, predictor );
|
||||
StatCoderContext ctx = new StatCoderContext(ab);
|
||||
for (int value = -100; value < 100; value += 5) {
|
||||
for (int predictor = -200; predictor < 200; predictor += 7) {
|
||||
ctx.encodePredictedValue(value, predictor);
|
||||
}
|
||||
}
|
||||
ctx.closeAndGetEncodedLength();
|
||||
ctx = new StatCoderContext( ab );
|
||||
ctx = new StatCoderContext(ab);
|
||||
|
||||
for ( int value = -100; value < 100; value += 5 )
|
||||
{
|
||||
for ( int predictor = -200; predictor < 200; predictor += 7 )
|
||||
{
|
||||
int decodedValue = ctx.decodePredictedValue( predictor );
|
||||
if ( value != decodedValue )
|
||||
{
|
||||
Assert.fail( "value mismatch: value=" + value + " predictor=" + predictor + " decodedValue=" + decodedValue );
|
||||
for (int value = -100; value < 100; value += 5) {
|
||||
for (int predictor = -200; predictor < 200; predictor += 7) {
|
||||
int decodedValue = ctx.decodePredictedValue(predictor);
|
||||
if (value != decodedValue) {
|
||||
Assert.fail("value mismatch: value=" + value + " predictor=" + predictor + " decodedValue=" + decodedValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sortedArrayEncodeDecodeTest()
|
||||
{
|
||||
public void sortedArrayEncodeDecodeTest() {
|
||||
Random rand = new Random();
|
||||
int size = 1000000;
|
||||
int[] values = new int[size];
|
||||
for ( int i = 0; i < size; i++ )
|
||||
{
|
||||
for (int i = 0; i < size; i++) {
|
||||
values[i] = rand.nextInt() & 0x0fffffff;
|
||||
}
|
||||
values[5] = 175384; // force collision
|
||||
|
|
@ -108,23 +87,21 @@ public class StatCoderContextTest
|
|||
values[15] = 275384; // force neighbours
|
||||
values[18] = 275385;
|
||||
|
||||
Arrays.sort( values );
|
||||
Arrays.sort(values);
|
||||
|
||||
byte[] ab = new byte[3000000];
|
||||
StatCoderContext ctx = new StatCoderContext( ab );
|
||||
ctx.encodeSortedArray( values, 0, size, 0x08000000, 0 );
|
||||
StatCoderContext ctx = new StatCoderContext(ab);
|
||||
ctx.encodeSortedArray(values, 0, size, 0x08000000, 0);
|
||||
|
||||
ctx.closeAndGetEncodedLength();
|
||||
ctx = new StatCoderContext( ab );
|
||||
ctx = new StatCoderContext(ab);
|
||||
|
||||
int[] decodedValues = new int[size];
|
||||
ctx.decodeSortedArray( decodedValues, 0, size, 27, 0 );
|
||||
ctx.decodeSortedArray(decodedValues, 0, size, 27, 0);
|
||||
|
||||
for ( int i = 0; i < size; i++ )
|
||||
{
|
||||
if ( values[i] != decodedValues[i] )
|
||||
{
|
||||
Assert.fail( "mismatch at i=" + i + " " + values[i] + "<>" + decodedValues[i] );
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (values[i] != decodedValues[i]) {
|
||||
Assert.fail("mismatch at i=" + i + " " + values[i] + "<>" + decodedValues[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue