content: package zemberek.core.collections;
  
  /**
   * A fixed size bit vector. Size can be maximum 2^31-1
   */
  public class FixedBitVector {
  
    private static final int[] setMasks = new int[32];
    private static final int[] resetMasks = new int[32];
  
    static {
      for (int i = 0; i < 32; i++) {
        setMasks[i] = 1 << i;
        resetMasks[i] = ~setMasks[i];
      }
    }
  
    public final int length;
    private int[] words;
  
    public FixedBitVector(int length) {
      if (length < 0) {
        throw new IllegalArgumentException("Length cannot be negative. But it is:" + length);
      }
      this.length = length;
      int wordCount = ((length + 31) >> 5);
      words = new int[wordCount];
    }
  
    /**
     * Used only for test purposes.
     *
     * @param bits bit string. It can contain space characters
     * @return bit vector equivalent.
     */
    static FixedBitVector fromBinaryString(String bits) {
      bits = bits.replaceAll("\\s+", "");
      FixedBitVector vector = new FixedBitVector(bits.length());
  
      for (int i = 0; i < bits.length(); i++) {
        if (bits.charAt(i) == '1') {
          vector.set(i);
        } else {
          vector.clear(i);
        }
      }
      return vector;
    }
  
    public boolean get(int n) {
      return (words[n >> 5] & setMasks[n & 31]) != 0;
    }
  
    public boolean safeGet(int n) {
      check(n);
      return (words[n >> 5] & setMasks[n & 31]) != 0;
    }
  
    private void check(int n) {
      if (n < 0 || n >= length) {
        throw new IllegalArgumentException(
            "Value must be between 0 and " + length + ". But it is " + n);
      }
    }
  
    public void set(int n) {
      words[n >> 5] |= setMasks[n & 31];
    }
  
    public void safeSet(int n) {
      check(n);
      words[n >> 5] |= setMasks[n & 31];
    }
  
    public void clear(int n) {
      words[n >> 5] &= resetMasks[n & 31];
    }
  
    public void safeClear(int n) {
      check(n);
      words[n >> 5] &= resetMasks[n & 31];
    }
  
    public int numberOfOnes() {
      int count = 0;
      for (int word : words) {
        count += Integer.bitCount(word);
      }
      return count;
    }
  
    public int numberOfNewOneBitCount(FixedBitVector other) {
      int total = 0;
      for (int i = 0; i < this.length; i++) {
        if (!this.get(i) && other.get(i)) {
          total++;
        }
      }
      return total;
    }
  
    public int differentBitCount(FixedBitVector other) {
      int total = 0;
      for (int i = 0; i < this.length; i++) {
        if (this.get(i) != other.get(i)) {
          total++;
        }
      }
      return total;
    }
  
    /**
     * @return number of zeroes
     */
    public int numberOfZeroes() {
      return length - numberOfOnes();
    }
  
    /**
     * @return an array containing 0 bit indexes.
     */
    public int[] zeroIndexes() {
      int[] zeroIndexes = new int[numberOfZeroes()];
      int j = 0;
      for (int i = 0; i < length; i++) {
        if (!get(i)) {
          zeroIndexes[j++] = i;
        }
      }
      return zeroIndexes;
    }
  }
  