package com.compomics.util.experiment.identification.protein_inference.fm_index;
/**
* Rank as used in the FM index.
*
* @author Dominik Kopczynski
*/
public class Rank {
/**
* The length.
*/
private final int length;
/**
* The bit field.
*/
private final long[] bitfield;
/**
* The sums.
*/
private final int[] sums;
/**
* The sums.
*/
private final byte[] sumsSecondLevel;
/**
* The shift.
*/
private final int shift = 6;
/**
* The mask.
*/
private final int mask = 63;
/**
* Constructor.
*
* @param text the text
* @param aAlphabet the alphabet
*/
public Rank(byte[] text, long[] aAlphabet) {
length = text.length;
int field_len = (length >>> 6) + 1;
bitfield = new long[field_len];
sums = new int[(length >>> 8) + 1];
sums[0] = 0;
sumsSecondLevel = new byte[field_len];
sumsSecondLevel[0] = 0;
for (int i = 0; i < length; ++i) {
int cell = i >>> shift;
int pos = i & mask;
if (pos == 0) {
bitfield[cell] = 0;
}
long bit = (aAlphabet[text[i] >>> shift] >>> (text[i] & mask)) & 1L;
bitfield[cell] |= (bit << pos);
if (pos == 0 && i != 0) {
if ((i & 255) == 0) {
sumsSecondLevel[cell] = 0;
} else {
sumsSecondLevel[cell] = (byte) (sumsSecondLevel[cell - 1] + (byte) (Long.bitCount(bitfield[cell - 1])));
}
}
if (((i & 255) == 0) && i != 0) {
sums[i >>> 8] = sums[(i >>> 8) - 1] + (sumsSecondLevel[cell - 1] & 0xFF) + Long.bitCount(bitfield[cell - 1]);
}
}
}
/**
* Returns the rank.
*
* @param index the value
* @param zeros the zeros
* @return the rank
*/
public int getRank(int index, boolean zeros) {
int cell = index >>> shift;
int pos = index & mask;
long active_ones = bitfield[cell] << (mask - pos);
int count_ones = (sumsSecondLevel[cell] & 0xFF) + sums[index >>> 8] + Long.bitCount(active_ones);
return zeros ? index + 1 - count_ones : count_ones;
}
/**
* Returns the rank of ones.
*
* @param index the value
* @return the rank
*/
public final int getRankOne(int index) {
final int cell = index >>> shift;
final int pos = index & mask;
final long active_ones = bitfield[cell] << (mask - pos);
final int count_ones = (sumsSecondLevel[cell] & 0xFF) + sums[index >>> 8] + Long.bitCount(active_ones);
return count_ones;
}
/**
* Returns the rank of zeros.
*
* @param index the value
* @return the rank
*/
public int getRankZero(int index) {
int cell = index >>> shift;
int pos = index & mask;
long active_ones = bitfield[cell] << (mask - pos);
int count_ones = (sumsSecondLevel[cell] & 0xFF) + sums[index >>> 8] + Long.bitCount(active_ones);
return index + 1 - count_ones;
}
/**
* Returns true if the value is equal to one.
*
* @param index the value
* @return true if the value is equal to one
*/
public boolean isOne(int index) {
int cell = index >>> shift;
int pos = index & mask;
return (((bitfield[cell] >>> pos) & 1L) == 1);
}
/**
* Returns true if the value is equal to one.
*
* @param index the value
* @return the bit
*/
public int isOneInt(int index) {
int cell = index >>> shift;
int pos = index & mask;
return (int)((bitfield[cell] >>> pos) & 1L);
}
/**
* Returns the number of bytes for the allocated arrays.
*
* @return the number of bytes for the allocated arrays
*/
public int getAllocatedBytes() {
return (bitfield.length << 3) + (sums.length << 2) + sumsSecondLevel.length;
}
}