package edu.berkeley.nlp.lm.bits;
public class CompressionUtils
{
public static BitList variableCompress(final long n, final int radix) {
final int numBits = getNumBits(n);
final int bitsPerDigit = radix - 1;
final int numDigits = getNumDigits(numBits, bitsPerDigit);
final BitList bits = writeUnary(numDigits);
final int numBitsToOutput = numDigits * bitsPerDigit;
writeNormalBinary(n, bits, numBitsToOutput);
assert bits.size() < Long.SIZE;
return bits;
}
public static long variableDecompress(final BitStream input, final int radix) {
final int numBitsInDigit = radix - 1;
final int numDigits = readUnary(input);
final long nextBits = input.next(numBitsInDigit * numDigits);
return nextBits;
}
/**
* @param input
* @return
*/
private static int readUnary(final BitStream input) {
return input.nextConsecutiveZeros();
}
/**
* @param n
* @param bits
* @param numBitsToOutput
*/
private static void writeNormalBinary(final long n, final BitList bits, final int numBitsToOutput) {
long mask = 1L << (numBitsToOutput - 1);
for (int i = 0; i < numBitsToOutput; ++i) {
bits.add((n & mask) != 0);
mask >>>= 1;
}
}
/**
* @param numDigits
* @return
*/
private static BitList writeUnary(final int numDigits) {
final BitList bits = new BitList();
for (int i = 0; i < numDigits; ++i) {
bits.add(i == numDigits - 1);
}
return bits;
}
/**
* @param delta
* @return
*/
private static int getNumBits(final long delta) {
return Long.SIZE - Long.numberOfLeadingZeros(delta);
}
/**
* @param numBits
* @param bitsPerDigit
* @return
*/
private static int getNumDigits(final int numBits, final int bitsPerDigit) {
int numDigits = (numBits / bitsPerDigit) + ((numBits % bitsPerDigit) == 0 ? 0 : 1);
numDigits = Math.max(1, numDigits);
return numDigits;
}
}