Skip to content

Commit

Permalink
Addressing the feedback from Nov 7 and Nov 20 - part 6
Browse files Browse the repository at this point in the history
  • Loading branch information
yash-puligundla committed Dec 21, 2023
1 parent b095b1c commit b2187c3
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 64 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package htsjdk.samtools.cram.compression.rans;

import htsjdk.samtools.cram.CRAMException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

public abstract class RANSEncode<T extends RANSParams> {
private RANSEncodingSymbol[][] encodingSymbols;
Expand Down Expand Up @@ -35,20 +33,6 @@ protected void initializeRANSEncoder() {
}
}

protected ByteBuffer allocateOutputBuffer(final int inSize) {
// This calculation is identical to the one in samtools rANS_static.c
// Presumably the frequency table (always big enough for order 1) = 257*257,
// then * 3 for each entry (byte->symbol, 2 bytes -> scaled frequency),
// + 9 for the header (order byte, and 2 int lengths for compressed/uncompressed lengths).
final int compressedSize = (int) (inSize + 257 * 257 * 3 + 9);
final ByteBuffer outputBuffer = ByteBuffer.allocate(compressedSize);
if (outputBuffer.remaining() < compressedSize) {
throw new CRAMException("Failed to allocate sufficient buffer size for RANS coder.");
}
outputBuffer.order(ByteOrder.LITTLE_ENDIAN);
return outputBuffer;
}

protected void buildSymsOrder0(final int[] frequencies) {
updateEncodingSymbols(frequencies, getEncodingSymbols()[0]);
}
Expand Down
31 changes: 31 additions & 0 deletions src/main/java/htsjdk/samtools/cram/compression/rans/Utils.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package htsjdk.samtools.cram.compression.rans;

import htsjdk.samtools.cram.CRAMException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

final public class Utils {

Expand Down Expand Up @@ -191,4 +193,33 @@ public static void normaliseFrequenciesOrder1Shift(final int[][] F, final int sh
}
}
}

public static ByteBuffer allocateOutputBuffer(final int inSize) {
// This calculation is identical to the one in samtools rANS_static.c
// Presumably the frequency table (always big enough for order 1) = 257*257,
// then * 3 for each entry (byte->symbol, 2 bytes -> scaled frequency),
// + 9 for the header (order byte, and 2 int lengths for compressed/uncompressed lengths).
final int compressedSize = (int) (inSize + 257 * 257 * 3 + 9);
final ByteBuffer outputBuffer = ByteBuffer.allocate(compressedSize).order(ByteOrder.LITTLE_ENDIAN);
if (outputBuffer.remaining() < compressedSize) {
throw new CRAMException("Failed to allocate sufficient buffer size for RANS coder.");
}
return outputBuffer;
}

// returns a new LITTLE_ENDIAN ByteBuffer of size = bufferSize
public static ByteBuffer allocateByteBuffer(final int bufferSize){
return ByteBuffer.allocate(bufferSize).order(ByteOrder.LITTLE_ENDIAN);
}

// returns a LITTLE_ENDIAN ByteBuffer that is created by wrapping a byte[]
public static ByteBuffer wrap(final byte[] inputBytes){
return ByteBuffer.wrap(inputBytes).order(ByteOrder.LITTLE_ENDIAN);
}

// returns a LITTLE_ENDIAN ByteBuffer that is created by inputBuffer.slice()
public static ByteBuffer slice(final ByteBuffer inputBuffer){
return inputBuffer.slice().order(ByteOrder.LITTLE_ENDIAN);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
public class RANS4x8Decode extends RANSDecode {

private static final int RAW_BYTE_LENGTH = 4;
private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0);
private static final ByteBuffer EMPTY_BUFFER = Utils.allocateByteBuffer(0);

// This method assumes that inBuffer is already rewound.
// It uncompresses the data in the inBuffer, leaving it consumed.
Expand All @@ -39,7 +39,7 @@ public ByteBuffer uncompress(final ByteBuffer inBuffer) {

// uncompressed bytes length
final int outSize = inBuffer.getInt();
final ByteBuffer outBuffer = ByteBuffer.allocate(outSize);
final ByteBuffer outBuffer = Utils.allocateByteBuffer(outSize);
initializeRANSDecoder();
switch (order) {
case ZERO:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class RANS4x8Encode extends RANSEncode<RANS4x8Params> {
// streams smaller than this value don't have sufficient symbol context for ORDER-1 encoding,
// so always use ORDER-0
private static final int MINIMUM_ORDER_1_SIZE = 4;
private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0);
private static final ByteBuffer EMPTY_BUFFER = Utils.allocateByteBuffer(0);

// This method assumes that inBuffer is already rewound.
// It compresses the data in the inBuffer, leaving it consumed.
Expand Down Expand Up @@ -44,7 +44,7 @@ public ByteBuffer compress(final ByteBuffer inBuffer, final RANS4x8Params params

private ByteBuffer compressOrder0Way4(final ByteBuffer inBuffer) {
final int inputSize = inBuffer.remaining();
final ByteBuffer outBuffer = allocateOutputBuffer(inputSize);
final ByteBuffer outBuffer = Utils.allocateOutputBuffer(inputSize);

// move the output buffer ahead to the start of the frequency table (we'll come back and
// write the output stream prefix at the end of this method)
Expand All @@ -55,7 +55,7 @@ private ByteBuffer compressOrder0Way4(final ByteBuffer inBuffer) {

// using the normalised frequencies, set the RANSEncodingSymbols
buildSymsOrder0(normalizedFreq);
final ByteBuffer cp = outBuffer.slice();
final ByteBuffer cp = Utils.slice(outBuffer);

// write Frequency table
final int frequencyTableSize = writeFrequenciesOrder0(cp, normalizedFreq);
Expand All @@ -65,7 +65,7 @@ private ByteBuffer compressOrder0Way4(final ByteBuffer inBuffer) {
final RANSEncodingSymbol[] syms = getEncodingSymbols()[0];
final int in_size = inBuffer.remaining();
long rans0, rans1, rans2, rans3;
final ByteBuffer ptr = cp.slice();
final ByteBuffer ptr = Utils.slice(cp);
rans0 = Constants.RANS_4x8_LOWER_BOUND;
rans1 = Constants.RANS_4x8_LOWER_BOUND;
rans2 = Constants.RANS_4x8_LOWER_BOUND;
Expand Down Expand Up @@ -94,6 +94,7 @@ private ByteBuffer compressOrder0Way4(final ByteBuffer inBuffer) {
rans0 = syms[0xFF & c0].putSymbol4x8(rans0, ptr);
}

ptr.order(ByteOrder.BIG_ENDIAN);
ptr.putInt((int) rans3);
ptr.putInt((int) rans2);
ptr.putInt((int) rans1);
Expand All @@ -111,7 +112,7 @@ private ByteBuffer compressOrder0Way4(final ByteBuffer inBuffer) {

private ByteBuffer compressOrder1Way4(final ByteBuffer inBuffer) {
final int inSize = inBuffer.remaining();
final ByteBuffer outBuffer = allocateOutputBuffer(inSize);
final ByteBuffer outBuffer = Utils.allocateOutputBuffer(inSize);

// move to start of frequency
outBuffer.position(Constants.RANS_4x8_PREFIX_BYTE_LENGTH);
Expand All @@ -122,7 +123,7 @@ private ByteBuffer compressOrder1Way4(final ByteBuffer inBuffer) {
// using the normalised frequencies, set the RANSEncodingSymbols
buildSymsOrder1(normalizedFreq);

final ByteBuffer cp = outBuffer.slice();
final ByteBuffer cp = Utils.slice(outBuffer);
final int frequencyTableSize = writeFrequenciesOrder1(cp, normalizedFreq);
inBuffer.rewind();
final int in_size = inBuffer.remaining();
Expand Down Expand Up @@ -155,7 +156,7 @@ private ByteBuffer compressOrder1Way4(final ByteBuffer inBuffer) {
byte l3 = inBuffer.get(in_size - 1);

// Slicing is needed for buffer reversing later
final ByteBuffer ptr = cp.slice();
final ByteBuffer ptr = Utils.slice(cp);
final RANSEncodingSymbol[][] syms = getEncodingSymbols();
for (i3 = in_size - 2; i3 > 4 * isz4 - 2 && i3 >= 0; i3--) {
final byte c3 = inBuffer.get(i3);
Expand Down Expand Up @@ -216,7 +217,6 @@ private static void writeCompressionPrefix(
// go back to the beginning of the stream and write the prefix values
// write the (ORDER as a single byte at offset 0)
outBuffer.put(0, (byte) (order == RANSParams.ORDER.ZERO ? 0 : 1));
outBuffer.order(ByteOrder.LITTLE_ENDIAN);
// move past the ORDER and write the compressed size
outBuffer.putInt(Constants.RANS_4x8_ORDER_BYTE_LENGTH, frequencyTableSize + compressedBlobSize);
// move past the compressed size and write the uncompressed size
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import java.util.Arrays;

public class RANSNx16Decode extends RANSDecode {
private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0);
private static final ByteBuffer EMPTY_BUFFER = Utils.allocateByteBuffer(0);
private static final int FREQ_TABLE_OPTIONALLY_COMPRESSED_MASK = 0x01;
private static final int RLE_META_OPTIONALLY_COMPRESSED_MASK = 0x01;

Expand Down Expand Up @@ -80,14 +80,14 @@ private ByteBuffer uncompress(final ByteBuffer inBuffer, final int outSize) {

// If CAT is set then, the input is uncompressed
if (ransNx16Params.isCAT()) {
outBuffer = inBuffer.slice();
outBuffer = Utils.slice(inBuffer);

// While resetting the position to the end is not strictly necessary,
// it is being done for the sake of completeness and
// to meet the requirements of the tests that verify the boundary conditions.
inBuffer.position(inBuffer.limit());
} else {
outBuffer = ByteBuffer.allocate(uncompressedSize);
outBuffer = Utils.allocateByteBuffer(uncompressedSize);

// uncompressedSize is 0 in cases where Pack flag is used
// and number of distinct symbols in the raw data is 1
Expand Down Expand Up @@ -194,9 +194,8 @@ private void uncompressOrder1WayN(
inBuffer.get(compressedFreqTable,0,compressedLength);

// decode the compressedFreqTable to get the uncompressedFreqTable using RANS Nx16, N=4 Order 0 uncompress
freqTableSource = ByteBuffer.allocate(uncompressedLength);
final ByteBuffer compressedFrequencyTableBuffer = ByteBuffer.wrap(compressedFreqTable);
compressedFrequencyTableBuffer.order(ByteOrder.LITTLE_ENDIAN);
freqTableSource = Utils.allocateByteBuffer(uncompressedLength);
final ByteBuffer compressedFrequencyTableBuffer = Utils.wrap(compressedFreqTable);

// uncompress using RANSNx16 Order 0, Nway = 4
// formatFlags = (~RANSNx16Params.ORDER_FLAG_MASK & ~RANSNx16Params.N32_FLAG_MASK) = ~(RANSNx16Params.ORDER_FLAG_MASK | RANSNx16Params.N32_FLAG_MASK)
Expand Down Expand Up @@ -364,14 +363,13 @@ private ByteBuffer decodeRLEMeta(
if ((uncompressedRLEMetaDataLength & RLE_META_OPTIONALLY_COMPRESSED_MASK)!=0) {
final byte[] uncompressedRLEMetaDataArray = new byte[(uncompressedRLEMetaDataLength-1)/2];
inBuffer.get(uncompressedRLEMetaDataArray, 0, (uncompressedRLEMetaDataLength-1)/2);
uncompressedRLEMetaData = ByteBuffer.wrap(uncompressedRLEMetaDataArray);
uncompressedRLEMetaData = Utils.wrap(uncompressedRLEMetaDataArray);
} else {
final int compressedRLEMetaDataLength = Utils.readUint7(inBuffer);
final byte[] compressedRLEMetaDataArray = new byte[compressedRLEMetaDataLength];
inBuffer.get(compressedRLEMetaDataArray,0,compressedRLEMetaDataLength);
final ByteBuffer compressedRLEMetaData = ByteBuffer.wrap(compressedRLEMetaDataArray);
compressedRLEMetaData.order(ByteOrder.LITTLE_ENDIAN);
uncompressedRLEMetaData = ByteBuffer.allocate(uncompressedRLEMetaDataLength / 2);
final ByteBuffer compressedRLEMetaData = Utils.wrap(compressedRLEMetaDataArray);
uncompressedRLEMetaData = Utils.allocateByteBuffer(uncompressedRLEMetaDataLength / 2);
// uncompress using Order 0 and N = Nway
uncompressOrder0WayN(
compressedRLEMetaData,
Expand All @@ -395,7 +393,7 @@ private ByteBuffer decodeRLE(
final int[] rleSymbols,
final ByteBuffer uncompressedRLEMetaData,
final int uncompressedRLEOutputLength) {
final ByteBuffer rleOutBuffer = ByteBuffer.allocate(uncompressedRLEOutputLength);
final ByteBuffer rleOutBuffer = Utils.allocateByteBuffer(uncompressedRLEOutputLength);
int j = 0;
for(int i = 0; j< uncompressedRLEOutputLength; i++){
final byte sym = inBuffer.get(i);
Expand All @@ -416,7 +414,7 @@ private ByteBuffer decodePack(
final byte[] packMappingTable,
final int numSymbols,
final int uncompressedPackOutputLength) {
final ByteBuffer outBufferPack = ByteBuffer.allocate(uncompressedPackOutputLength);
final ByteBuffer outBufferPack = Utils.allocateByteBuffer(uncompressedPackOutputLength);
int j = 0;
if (numSymbols <= 1) {
for (int i=0; i < uncompressedPackOutputLength; i++){
Expand Down Expand Up @@ -483,7 +481,7 @@ private ByteBuffer decodeStripe(final ByteBuffer inBuffer, final int outSize){
}

// Transpose
final ByteBuffer outBuffer = ByteBuffer.allocate(outSize);
final ByteBuffer outBuffer = Utils.allocateByteBuffer(outSize);
for (int j = 0; j <numInterleaveStreams; j++) {
for (int i = 0; i < uncompressedLengths[j]; i++) {
outBuffer.put((i*numInterleaveStreams)+j, transposedData[j].get(i));
Expand Down
Loading

0 comments on commit b2187c3

Please sign in to comment.