/* Copyright (c) 2008, Avian Contributors

   Permission to use, copy, modify, and/or distribute this software
   for any purpose with or without fee is hereby granted, provided
   that the above copyright notice and this permission notice appear
   in all copies.

   There is NO WARRANTY for this software.  See license.txt for
   details. */

package java.util;

import java.io.Serializable;

/**
 * @author zsombor
 * 
 */
public class BitSet implements Serializable, Cloneable {

  final static int  BITS_PER_LONG       = 64;
  final static int  BITS_PER_LONG_SHIFT = 6;
  final static long MASK                = 0xFFFFFFFFFFFFFFFFL;

  private long[]    bits;

  private static int longPosition(int index) {
    return index >> BITS_PER_LONG_SHIFT;
  }

  private static long bitPosition(int index) {
    return 1L << (index % BITS_PER_LONG);
  }

  public BitSet(int bitLength) {
    if (bitLength % BITS_PER_LONG == 0) {
      enlarge(longPosition(bitLength));
    } else {
      enlarge(longPosition(bitLength) + 1);
    }
  }

  public BitSet() {
    enlarge(1);
  }

  public void and(BitSet otherBits) {
    int max = Math.max(bits.length, otherBits.bits.length);
    for (int i = 0; i < max; i++) {
      bits[i] &= otherBits.bits[i];
    }
  }

  public void andNot(BitSet otherBits) {
    int max = Math.max(bits.length, otherBits.bits.length);
    enlarge(max);
    for (int i = 0; i < max; i++) {
      bits[i] &= ~otherBits.bits[i];
    }
  }

  public void or(BitSet otherBits) {
    int max = Math.max(bits.length, otherBits.bits.length);
    enlarge(max);
    for (int i = 0; i < max; i++) {
      bits[i] |= otherBits.bits[i];
    }
  }

  public void xor(BitSet otherBits) {
    int max = Math.max(bits.length, otherBits.bits.length);
    enlarge(max);
    for (int i = 0; i < max; i++) {
      bits[i] ^= otherBits.bits[i];
    }
  }

  private void enlarge(int newSize) {
    if (bits == null || bits.length <= newSize) {
      long[] newBits = new long[newSize + 1];
      if (bits != null) {
        System.arraycopy(bits, 0, newBits, 0, bits.length);
      }
      bits = newBits;
    }
  }

  public void clear(int index) {
    int pos = longPosition(index);
    if (pos < bits.length) {
      bits[pos] &= (MASK ^ bitPosition(index));
    }
  }

  public boolean get(int index) {
    int pos = longPosition(index);
    if (pos < bits.length) {
      return (bits[pos] & bitPosition(index)) != 0;
    }
    return false;
  }

  public void set(int index) {
    int pos = longPosition(index);
    enlarge(pos);
    bits[pos] |= bitPosition(index);
  }

  public void set(int start, int end) {
    for (int i = start; i < end; i++) {
      set(i);
    }
  }

  public void clear(int start, int end) {
    for (int i = start; i < end; i++) {
      clear(i);
    }
  }

  public boolean isEmpty() {
    for (int i = 0; i < bits.length; i++) {
      if (bits[i] != 0) {
        return false;
      }
    }
    return true;
  }

  public boolean intersects(BitSet otherBits) {
    int max = Math.max(bits.length, otherBits.bits.length);
    for (int i = 0; i < max; i++) {
      if ((bits[i] & otherBits.bits[i]) != 0) {
        return true;
      }
    }
    return false;
  }

  public int length() {
    return bits.length << BITS_PER_LONG_SHIFT;
  }

  public int nextSetBit(int fromIndex) {
    return nextBit(fromIndex, false);
  }

  private int nextBit(int fromIndex, boolean bitClear) {
    int pos = longPosition(fromIndex);
    if (pos >= bits.length) {
      return -1;
    }
    int current = fromIndex;
    do {
      long currValue = bits[pos];
      if (currValue == 0) {
        pos++;
        current = pos << BITS_PER_LONG_SHIFT;
      } else {
        do {
          long bitPos = bitPosition(current);
          if (((currValue & bitPos) != 0) ^ bitClear) {
            return current;
          } else {
            current++;
          }
        } while (current % BITS_PER_LONG != 0);
      }
      pos++;
    } while (pos < bits.length);

    return -1;
  }

  public int nextClearBit(int fromIndex) {
    return nextBit(fromIndex, true);
  }

}

@@ -1110,34 +1110,34 @@
 its) %7B%0A    int m
-ax
+in
  = Math.max(bits
@@ -1121,34 +1121,34 @@
 int min = Math.m
-ax
+in
 (bits.length, ot
@@ -1186,34 +1186,34 @@
 int i = 0; i %3C m
-ax
+in
 ; i++) %7B%0A      b
@@ -1239,32 +1239,104 @@
 .bits%5Bi%5D;%0A    %7D%0A
+    for (int i = min; i %3C bits.length; i++) %7B %0A      bits%5Bi%5D = 0;%0A    %7D%0A
   %7D%0A%0A  public vo
@@ -1435,32 +1435,92 @@
   enlarge(max);%0A
+    int min = Math.min(bits.length, otherBits.bits.length);%0A
     for (int i =
@@ -1520,34 +1520,34 @@
 int i = 0; i %3C m
-ax
+in
 ; i++) %7B%0A      b
@@ -1694,32 +1694,92 @@
   enlarge(max);%0A
+    int min = Math.min(bits.length, otherBits.bits.length);%0A
     for (int i =
@@ -1779,34 +1779,34 @@
 int i = 0; i %3C m
-ax
+in
 ; i++) %7B%0A      b
@@ -1957,24 +1957,84 @@
 large(max);%0A
+    int min = Math.min(bits.length, otherBits.bits.length);%0A
     for (int
@@ -2038,34 +2038,34 @@
 int i = 0; i %3C m
-ax
+in
 ; i++) %7B%0A      b
@@ -2179,17 +2179,16 @@
 length %3C
-=
  newSize

fix and-ing, or-ing, etc BitSet with variant size