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; } }