package ser.androidbitset;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.LongBuffer;
import java.util.Arrays;
public class JDKBitSet implements Cloneable, Serializable {
private static final int ADDRESS_BITS_PER_WORD = 6;
private static final int BITS_PER_WORD = 64;
private static final int BIT_INDEX_MASK = 63;
private static final long WORD_MASK = -1L;
private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[]{new ObjectStreamField("bits", long[].class)};
private long[] words;
private transient int wordsInUse = 0;
private transient boolean sizeIsSticky = false;
private static final long serialVersionUID = 7997698588986878753L;
private static int wordIndex(int bitIndex) {
return bitIndex >> 6;
}
private void checkInvariants() {
assert this.wordsInUse == 0 || this.words[this.wordsInUse - 1] != 0L;
assert this.wordsInUse >= 0 && this.wordsInUse <= this.words.length;
assert this.wordsInUse == this.words.length || this.words[this.wordsInUse] == 0L;
}
private void recalculateWordsInUse() {
int i;
for(i = this.wordsInUse - 1; i >= 0 && this.words[i] == 0L; --i) {
;
}
this.wordsInUse = i + 1;
}
public JDKBitSet() {
this.initWords(64);
this.sizeIsSticky = false;
}
public JDKBitSet(int nbits) {
if(nbits < 0) {
throw new NegativeArraySizeException("nbits < 0: " + nbits);
} else {
this.initWords(nbits);
this.sizeIsSticky = true;
}
}
private void initWords(int nbits) {
this.words = new long[wordIndex(nbits - 1) + 1];
}
private JDKBitSet(long[] words) {
this.words = words;
this.wordsInUse = words.length;
this.checkInvariants();
}
public static JDKBitSet valueOf(long[] longs) {
int n;
for(n = longs.length; n > 0 && longs[n - 1] == 0L; --n) {
;
}
return new JDKBitSet(Arrays.copyOf(longs, n));
}
public static JDKBitSet valueOf(LongBuffer lb) {
lb = lb.slice();
int n;
for(n = lb.remaining(); n > 0 && lb.get(n - 1) == 0L; --n) {
;
}
long[] words = new long[n];
lb.get(words);
return new JDKBitSet(words);
}
public static JDKBitSet valueOf(byte[] bytes) {
return valueOf((ByteBuffer)ByteBuffer.wrap(bytes));
}
public static JDKBitSet valueOf(ByteBuffer bb) {
bb = bb.slice().order(ByteOrder.LITTLE_ENDIAN);
int n;
for(n = bb.remaining(); n > 0 && bb.get(n - 1) == 0; --n) {
;
}
long[] words = new long[(n + 7) / 8];
bb.limit(n);
int i;
for(i = 0; bb.remaining() >= 8; words[i++] = bb.getLong()) {
;
}
int remaining = bb.remaining();
for(int j = 0; j < remaining; ++j) {
words[i] |= ((long)bb.get() & 255L) << 8 * j;
}
return new JDKBitSet(words);
}
public byte[] toByteArray() {
int n = this.wordsInUse;
if(n == 0) {
return new byte[0];
} else {
int len = 8 * (n - 1);
for(long bytes = this.words[n - 1]; bytes != 0L; bytes >>>= 8) {
++len;
}
byte[] var7 = new byte[len];
ByteBuffer bb = ByteBuffer.wrap(var7).order(ByteOrder.LITTLE_ENDIAN);
for(int x = 0; x < n - 1; ++x) {
bb.putLong(this.words[x]);
}
for(long var8 = this.words[n - 1]; var8 != 0L; var8 >>>= 8) {
bb.put((byte)((int)(var8 & 255L)));
}
return var7;
}
}
public long[] toLongArray() {
return Arrays.copyOf(this.words, this.wordsInUse);
}
private void ensureCapacity(int wordsRequired) {
if(this.words.length < wordsRequired) {
int request = Math.max(2 * this.words.length, wordsRequired);
this.words = Arrays.copyOf(this.words, request);
this.sizeIsSticky = false;
}
}
private void expandTo(int wordIndex) {
int wordsRequired = wordIndex + 1;
if(this.wordsInUse < wordsRequired) {
this.ensureCapacity(wordsRequired);
this.wordsInUse = wordsRequired;
}
}
private static void checkRange(int fromIndex, int toIndex) {
if(fromIndex < 0) {
throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex);
} else if(toIndex < 0) {
throw new IndexOutOfBoundsException("toIndex < 0: " + toIndex);
} else if(fromIndex > toIndex) {
throw new IndexOutOfBoundsException("fromIndex: " + fromIndex + " > toIndex: " + toIndex);
}
}
public void flip(int bitIndex) {
if(bitIndex < 0) {
throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);
} else {
int wordIndex = wordIndex(bitIndex);
this.expandTo(wordIndex);
this.words[wordIndex] ^= 1L << bitIndex;
this.recalculateWordsInUse();
this.checkInvariants();
}
}
public void flip(int fromIndex, int toIndex) {
checkRange(fromIndex, toIndex);
if(fromIndex != toIndex) {
int startWordIndex = wordIndex(fromIndex);
int endWordIndex = wordIndex(toIndex - 1);
this.expandTo(endWordIndex);
long firstWordMask = -1L << fromIndex;
long lastWordMask = -1L >>> -toIndex;
if(startWordIndex == endWordIndex) {
this.words[startWordIndex] ^= firstWordMask & lastWordMask;
} else {
this.words[startWordIndex] ^= firstWordMask;
for(int i = startWordIndex + 1; i < endWordIndex; ++i) {
this.words[i] = ~this.words[i];
}
this.words[endWordIndex] ^= lastWordMask;
}
this.recalculateWordsInUse();
this.checkInvariants();
}
}
public void set(int bitIndex) {
if(bitIndex < 0) {
throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);
} else {
int wordIndex = wordIndex(bitIndex);
this.expandTo(wordIndex);
this.words[wordIndex] |= 1L << bitIndex;
this.checkInvariants();
}
}
public void set(int bitIndex, boolean value) {
if(value) {
this.set(bitIndex);
} else {
this.clear(bitIndex);
}
}
public void set(int fromIndex, int toIndex) {
checkRange(fromIndex, toIndex);
if(fromIndex != toIndex) {
int startWordIndex = wordIndex(fromIndex);
int endWordIndex = wordIndex(toIndex - 1);
this.expandTo(endWordIndex);
long firstWordMask = -1L << fromIndex;
long lastWordMask = -1L >>> -toIndex;
if(startWordIndex == endWordIndex) {
this.words[startWordIndex] |= firstWordMask & lastWordMask;
} else {
this.words[startWordIndex] |= firstWordMask;
for(int i = startWordIndex + 1; i < endWordIndex; ++i) {
this.words[i] = -1L;
}
this.words[endWordIndex] |= lastWordMask;
}
this.checkInvariants();
}
}
public void set(int fromIndex, int toIndex, boolean value) {
if(value) {
this.set(fromIndex, toIndex);
} else {
this.clear(fromIndex, toIndex);
}
}
public void clear(int bitIndex) {
if(bitIndex < 0) {
throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);
} else {
int wordIndex = wordIndex(bitIndex);
if(wordIndex < this.wordsInUse) {
this.words[wordIndex] &= ~(1L << bitIndex);
this.recalculateWordsInUse();
this.checkInvariants();
}
}
}
public void clear(int fromIndex, int toIndex) {
checkRange(fromIndex, toIndex);
if(fromIndex != toIndex) {
int startWordIndex = wordIndex(fromIndex);
if(startWordIndex < this.wordsInUse) {
int endWordIndex = wordIndex(toIndex - 1);
if(endWordIndex >= this.wordsInUse) {
toIndex = this.length();
endWordIndex = this.wordsInUse - 1;
}
long firstWordMask = -1L << fromIndex;
long lastWordMask = -1L >>> -toIndex;
if(startWordIndex == endWordIndex) {
this.words[startWordIndex] &= ~(firstWordMask & lastWordMask);
} else {
this.words[startWordIndex] &= ~firstWordMask;
for(int i = startWordIndex + 1; i < endWordIndex; ++i) {
this.words[i] = 0L;
}
this.words[endWordIndex] &= ~lastWordMask;
}
this.recalculateWordsInUse();
this.checkInvariants();
}
}
}
public void clear() {
while(this.wordsInUse > 0) {
this.words[--this.wordsInUse] = 0L;
}
}
public boolean get(int bitIndex) {
if(bitIndex < 0) {
throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);
} else {
this.checkInvariants();
int wordIndex = wordIndex(bitIndex);
return wordIndex < this.wordsInUse && (this.words[wordIndex] & 1L << bitIndex) != 0L;
}
}
public JDKBitSet get(int fromIndex, int toIndex) {
checkRange(fromIndex, toIndex);
this.checkInvariants();
int len = this.length();
if(len > fromIndex && fromIndex != toIndex) {
if(toIndex > len) {
toIndex = len;
}
JDKBitSet result = new JDKBitSet(toIndex - fromIndex);
int targetWords = wordIndex(toIndex - fromIndex - 1) + 1;
int sourceIndex = wordIndex(fromIndex);
boolean wordAligned = (fromIndex & 63) == 0;
for(int lastWordMask = 0; lastWordMask < targetWords - 1; ++sourceIndex) {
result.words[lastWordMask] = wordAligned?this.words[sourceIndex]:this.words[sourceIndex] >>> fromIndex | this.words[sourceIndex + 1] << -fromIndex;
++lastWordMask;
}
long var10 = -1L >>> -toIndex;
result.words[targetWords - 1] = (toIndex - 1 & 63) < (fromIndex & 63)?this.words[sourceIndex] >>> fromIndex | (this.words[sourceIndex + 1] & var10) << -fromIndex:(this.words[sourceIndex] & var10) >>> fromIndex;
result.wordsInUse = targetWords;
result.recalculateWordsInUse();
result.checkInvariants();
return result;
} else {
return new JDKBitSet(0);
}
}
public int nextSetBit(int fromIndex) {
if(fromIndex < 0) {
throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex);
} else {
this.checkInvariants();
int u = wordIndex(fromIndex);
if(u >= this.wordsInUse) {
return -1;
} else {
long word;
for(word = this.words[u] & -1L << fromIndex; word == 0L; word = this.words[u]) {
++u;
if(u == this.wordsInUse) {
return -1;
}
}
return u * 64 + Long.numberOfTrailingZeros(word);
}
}
}
public int nextClearBit(int fromIndex) {
if(fromIndex < 0) {
throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex);
} else {
this.checkInvariants();
int u = wordIndex(fromIndex);
if(u >= this.wordsInUse) {
return fromIndex;
} else {
long word;
for(word = ~this.words[u] & -1L << fromIndex; word == 0L; word = ~this.words[u]) {
++u;
if(u == this.wordsInUse) {
return this.wordsInUse * 64;
}
}
return u * 64 + Long.numberOfTrailingZeros(word);
}
}
}
public int previousSetBit(int fromIndex) {
if(fromIndex < 0) {
if(fromIndex == -1) {
return -1;
} else {
throw new IndexOutOfBoundsException("fromIndex < -1: " + fromIndex);
}
} else {
this.checkInvariants();
int u = wordIndex(fromIndex);
if(u >= this.wordsInUse) {
return this.length() - 1;
} else {
long word;
for(word = this.words[u] & -1L >>> -(fromIndex + 1); word == 0L; word = this.words[u]) {
if(u-- == 0) {
return -1;
}
}
return (u + 1) * 64 - 1 - Long.numberOfLeadingZeros(word);
}
}
}
public int previousClearBit(int fromIndex) {
if(fromIndex < 0) {
if(fromIndex == -1) {
return -1;
} else {
throw new IndexOutOfBoundsException("fromIndex < -1: " + fromIndex);
}
} else {
this.checkInvariants();
int u = wordIndex(fromIndex);
if(u >= this.wordsInUse) {
return fromIndex;
} else {
long word;
for(word = ~this.words[u] & -1L >>> -(fromIndex + 1); word == 0L; word = ~this.words[u]) {
if(u-- == 0) {
return -1;
}
}
return (u + 1) * 64 - 1 - Long.numberOfLeadingZeros(word);
}
}
}
public int length() {
return this.wordsInUse == 0?0:64 * (this.wordsInUse - 1) + (64 - Long.numberOfLeadingZeros(this.words[this.wordsInUse - 1]));
}
public boolean isEmpty() {
return this.wordsInUse == 0;
}
public boolean intersects(JDKBitSet set) {
for(int i = Math.min(this.wordsInUse, set.wordsInUse) - 1; i >= 0; --i) {
if((this.words[i] & set.words[i]) != 0L) {
return true;
}
}
return false;
}
public int cardinality() {
int sum = 0;
for(int i = 0; i < this.wordsInUse; ++i) {
sum += Long.bitCount(this.words[i]);
}
return sum;
}
public void and(JDKBitSet set) {
if(this != set) {
while(this.wordsInUse > set.wordsInUse) {
this.words[--this.wordsInUse] = 0L;
}
for(int i = 0; i < this.wordsInUse; ++i) {
this.words[i] &= set.words[i];
}
this.recalculateWordsInUse();
this.checkInvariants();
}
}
public void or(JDKBitSet set) {
if(this != set) {
int wordsInCommon = Math.min(this.wordsInUse, set.wordsInUse);
if(this.wordsInUse < set.wordsInUse) {
this.ensureCapacity(set.wordsInUse);
this.wordsInUse = set.wordsInUse;
}
for(int i = 0; i < wordsInCommon; ++i) {
this.words[i] |= set.words[i];
}
if(wordsInCommon < set.wordsInUse) {
System.arraycopy(set.words, wordsInCommon, this.words, wordsInCommon, this.wordsInUse - wordsInCommon);
}
this.checkInvariants();
}
}
public void xor(JDKBitSet set) {
int wordsInCommon = Math.min(this.wordsInUse, set.wordsInUse);
if(this.wordsInUse < set.wordsInUse) {
this.ensureCapacity(set.wordsInUse);
this.wordsInUse = set.wordsInUse;
}
for(int i = 0; i < wordsInCommon; ++i) {
this.words[i] ^= set.words[i];
}
if(wordsInCommon < set.wordsInUse) {
System.arraycopy(set.words, wordsInCommon, this.words, wordsInCommon, set.wordsInUse - wordsInCommon);
}
this.recalculateWordsInUse();
this.checkInvariants();
}
public void andNot(JDKBitSet set) {
for(int i = Math.min(this.wordsInUse, set.wordsInUse) - 1; i >= 0; --i) {
this.words[i] &= ~set.words[i];
}
this.recalculateWordsInUse();
this.checkInvariants();
}
public int hashCode() {
long h = 1234L;
int i = this.wordsInUse;
while(true) {
--i;
if(i < 0) {
return (int)(h >> 32 ^ h);
}
h ^= this.words[i] * (long)(i + 1);
}
}
public int size() {
return this.words.length * 64;
}
public boolean equals(Object obj) {
if(!(obj instanceof JDKBitSet)) {
return false;
} else if(this == obj) {
return true;
} else {
JDKBitSet set = (JDKBitSet)obj;
this.checkInvariants();
set.checkInvariants();
if(this.wordsInUse != set.wordsInUse) {
return false;
} else {
for(int i = 0; i < this.wordsInUse; ++i) {
if(this.words[i] != set.words[i]) {
return false;
}
}
return true;
}
}
}
public Object clone() {
if(!this.sizeIsSticky) {
this.trimToSize();
}
try {
JDKBitSet e = (JDKBitSet)super.clone();
e.words = (long[])this.words.clone();
e.checkInvariants();
return e;
} catch (CloneNotSupportedException var2) {
throw new InternalError();
}
}
private void trimToSize() {
if(this.wordsInUse != this.words.length) {
this.words = Arrays.copyOf(this.words, this.wordsInUse);
this.checkInvariants();
}
}
private void writeObject(ObjectOutputStream s) throws IOException {
this.checkInvariants();
if(!this.sizeIsSticky) {
this.trimToSize();
}
ObjectOutputStream.PutField fields = s.putFields();
fields.put("bits", this.words);
s.writeFields();
}
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField fields = s.readFields();
this.words = (long[])((long[])fields.get("bits", (Object)null));
this.wordsInUse = this.words.length;
this.recalculateWordsInUse();
this.sizeIsSticky = this.words.length > 0 && this.words[this.words.length - 1] == 0L;
this.checkInvariants();
}
public String toString() {
this.checkInvariants();
int numBits = this.wordsInUse > 128?this.cardinality():this.wordsInUse * 64;
StringBuilder b = new StringBuilder(6 * numBits + 2);
b.append('{');
int i = this.nextSetBit(0);
if(i != -1) {
b.append(i);
for(i = this.nextSetBit(i + 1); i >= 0; i = this.nextSetBit(i + 1)) {
int endOfRun = this.nextClearBit(i);
do {
b.append(", ").append(i);
++i;
} while(i < endOfRun);
}
}
b.append('}');
return b.toString();
}
}