summaryrefslogtreecommitdiffstats
path: root/luni/src/main/java/java/util/BitSet.java
diff options
context:
space:
mode:
Diffstat (limited to 'luni/src/main/java/java/util/BitSet.java')
-rw-r--r--luni/src/main/java/java/util/BitSet.java861
1 files changed, 861 insertions, 0 deletions
diff --git a/luni/src/main/java/java/util/BitSet.java b/luni/src/main/java/java/util/BitSet.java
new file mode 100644
index 0000000..aa60be0
--- /dev/null
+++ b/luni/src/main/java/java/util/BitSet.java
@@ -0,0 +1,861 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util;
+
+import java.io.Serializable;
+
+import org.apache.harmony.luni.util.Msg;
+
+/**
+ * The {@code BitSet} class implements a bit field. Each element in a
+ * {@code BitSet} can be on(1) or off(0). A {@code BitSet} is created with a
+ * given size and grows if this size is exceeded. Growth is always rounded to a
+ * 64 bit boundary.
+ *
+ * @since Android 1.0
+ */
+public class BitSet implements Serializable, Cloneable {
+ private static final long serialVersionUID = 7997698588986878753L;
+
+ // Size in bits of the data type being used in the bits array
+ private static final int ELM_SIZE = 64;
+
+ private long[] bits;
+
+ /**
+ * Create a new {@code BitSet} with size equal to 64 bits.
+ *
+ * @see #clear(int)
+ * @see #set(int)
+ * @see #clear()
+ * @see #clear(int, int)
+ * @see #set(int, boolean)
+ * @see #set(int, int)
+ * @see #set(int, int, boolean)
+ * @since Android 1.0
+ */
+ public BitSet() {
+ this(64);
+ }
+
+ /**
+ * Create a new {@code BitSet} with size equal to nbits. If nbits is not a
+ * multiple of 64, then create a {@code BitSet} with size nbits rounded to
+ * the next closest multiple of 64.
+ *
+ * @param nbits
+ * the size of the bit set.
+ * @throws NegativeArraySizeException
+ * if {@code nbits} is negative.
+ * @see #clear(int)
+ * @see #set(int)
+ * @see #clear()
+ * @see #clear(int, int)
+ * @see #set(int, boolean)
+ * @see #set(int, int)
+ * @see #set(int, int, boolean)
+ * @since Android 1.0
+ */
+ public BitSet(int nbits) {
+ if (nbits >= 0) {
+ bits = new long[(nbits / ELM_SIZE) + (nbits % ELM_SIZE > 0 ? 1 : 0)];
+ } else {
+ throw new NegativeArraySizeException();
+ }
+ }
+
+ /**
+ * Private constructor called from get(int, int) method
+ *
+ * @param bits
+ * the size of the bit set
+ */
+ private BitSet(long[] bits) {
+ this.bits = bits;
+ }
+
+ /**
+ * Creates a copy of this {@code BitSet}.
+ *
+ * @return a copy of this {@code BitSet}.
+ * @since Android 1.0
+ */
+ @Override
+ public Object clone() {
+ try {
+ BitSet clone = (BitSet) super.clone();
+ clone.bits = bits.clone();
+ return clone;
+ } catch (CloneNotSupportedException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Compares the argument to this {@code BitSet} and returns whether they are
+ * equal. The object must be an instance of {@code BitSet} with the same
+ * bits set.
+ *
+ * @param obj
+ * the {@code BitSet} object to compare.
+ * @return a {@code boolean} indicating whether or not this {@code BitSet} and
+ * {@code obj} are equal.
+ * @see #hashCode
+ * @since Android 1.0
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof BitSet) {
+ long[] bsBits = ((BitSet) obj).bits;
+ int length1 = bits.length, length2 = bsBits.length;
+ // If one of the BitSets is larger than the other, check to see if
+ // any of
+ // its extra bits are set. If so return false.
+ if (length1 <= length2) {
+ for (int i = 0; i < length1; i++) {
+ if (bits[i] != bsBits[i]) {
+ return false;
+ }
+ }
+ for (int i = length1; i < length2; i++) {
+ if (bsBits[i] != 0) {
+ return false;
+ }
+ }
+ } else {
+ for (int i = 0; i < length2; i++) {
+ if (bits[i] != bsBits[i]) {
+ return false;
+ }
+ }
+ for (int i = length2; i < length1; i++) {
+ if (bits[i] != 0) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Increase the size of the internal array to accommodate {@code pos} bits.
+ * The new array max index will be a multiple of 64.
+ *
+ * @param pos
+ * the index the new array needs to be able to access.
+ * @since Android 1.0
+ */
+ private void growBits(int pos) {
+ pos++; // Inc to get correct bit count
+ long[] tempBits = new long[(pos / ELM_SIZE)
+ + (pos % ELM_SIZE > 0 ? 1 : 0)];
+ System.arraycopy(bits, 0, tempBits, 0, bits.length);
+ bits = tempBits;
+ }
+
+ /**
+ * Computes the hash code for this {@code BitSet}. If two {@code BitSet}s are equal
+ * the have to return the same result for {@code hashCode()}.
+ *
+ * @return the {@code int} representing the hash code for this bit
+ * set.
+ * @see #equals
+ * @see java.util.Hashtable
+ * @since Android 1.0
+ */
+ @Override
+ public int hashCode() {
+ long x = 1234;
+ // for (int i = 0, length = bits.length; i < length; i+=2)
+ // x ^= (bits[i] + ((long)bits[i+1] << 32)) * (i/2 + 1);
+ for (int i = 0, length = bits.length; i < length; i++) {
+ x ^= bits[i] * (i + 1);
+ }
+ return (int) ((x >> 32) ^ x);
+ }
+
+ /**
+ * Retrieves the bit at index {@code pos}. Grows the {@code BitSet} if
+ * {@code pos > size}.
+ *
+ * @param pos
+ * the index of the bit to be retrieved.
+ * @return {@code true} if the bit at {@code pos} is set,
+ * {@code false} otherwise.
+ * @throws IndexOutOfBoundsException
+ * if {@code pos} is negative.
+ * @see #clear(int)
+ * @see #set(int)
+ * @see #clear()
+ * @see #clear(int, int)
+ * @see #set(int, boolean)
+ * @see #set(int, int)
+ * @see #set(int, int, boolean)
+ * @since Android 1.0
+ */
+ public boolean get(int pos) {
+ if (pos >= 0) {
+ if (pos < bits.length * ELM_SIZE) {
+ return (bits[pos / ELM_SIZE] & (1L << (pos % ELM_SIZE))) != 0;
+ }
+ return false;
+ }
+ // Negative index specified
+ throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
+ }
+
+ /**
+ * Retrieves the bits starting from {@code pos1} to {@code pos2} and returns
+ * back a new bitset made of these bits. Grows the {@code BitSet} if
+ * {@code pos2 > size}.
+ *
+ * @param pos1
+ * beginning position.
+ * @param pos2
+ * ending position.
+ * @return new bitset of the range specified.
+ * @throws IndexOutOfBoundsException
+ * if {@code pos1} or {@code pos2} is negative, or if
+ * {@code pos2} is smaller than {@code pos1}.
+ * @see #get(int)
+ * @since Android 1.0
+ */
+ public BitSet get(int pos1, int pos2) {
+ if (pos1 >= 0 && pos2 >= 0 && pos2 >= pos1) {
+ int last = (bits.length * ELM_SIZE);
+ if (pos1 >= last || pos1 == pos2) {
+ return new BitSet(0);
+ }
+ if (pos2 > last) {
+ pos2 = last;
+ }
+
+ int idx1 = pos1 / ELM_SIZE;
+ int idx2 = (pos2 - 1) / ELM_SIZE;
+ long factor1 = (~0L) << (pos1 % ELM_SIZE);
+ long factor2 = (~0L) >>> (ELM_SIZE - (pos2 % ELM_SIZE));
+
+ if (idx1 == idx2) {
+ long result = (bits[idx1] & (factor1 & factor2)) >>> (pos1 % ELM_SIZE);
+ return new BitSet(new long[] { result });
+ }
+ long[] newbits = new long[idx2 - idx1 + 1];
+ // first fill in the first and last indexes in the new bitset
+ newbits[0] = bits[idx1] & factor1;
+ newbits[newbits.length - 1] = bits[idx2] & factor2;
+
+ // fill in the in between elements of the new bitset
+ for (int i = 1; i < idx2 - idx1; i++) {
+ newbits[i] = bits[idx1 + i];
+ }
+
+ // shift all the elements in the new bitset to the right by pos1
+ // % ELM_SIZE
+ int numBitsToShift = pos1 % ELM_SIZE;
+ if (numBitsToShift != 0) {
+ for (int i = 0; i < newbits.length; i++) {
+ // shift the current element to the right regardless of
+ // sign
+ newbits[i] = newbits[i] >>> (numBitsToShift);
+
+ // apply the last x bits of newbits[i+1] to the current
+ // element
+ if (i != newbits.length - 1) {
+ newbits[i] |= newbits[i + 1] << (ELM_SIZE - (numBitsToShift));
+ }
+ }
+ }
+ return new BitSet(newbits);
+ }
+ throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
+ }
+
+ /**
+ * Sets the bit at index {@code pos} to 1. Grows the {@code BitSet} if
+ * {@code pos > size}.
+ *
+ * @param pos
+ * the index of the bit to set.
+ * @throws IndexOutOfBoundsException
+ * if {@code pos} is negative.
+ * @see #clear(int)
+ * @see #clear()
+ * @see #clear(int, int)
+ * @since Android 1.0
+ */
+ public void set(int pos) {
+ if (pos >= 0) {
+ if (pos >= bits.length * ELM_SIZE) {
+ growBits(pos);
+ }
+ bits[pos / ELM_SIZE] |= 1L << (pos % ELM_SIZE);
+ } else {
+ throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Sets the bit at index {@code pos} to {@code val}. Grows the
+ * {@code BitSet} if {@code pos > size}.
+ *
+ * @param pos
+ * the index of the bit to set.
+ * @param val
+ * value to set the bit.
+ * @throws IndexOutOfBoundsException
+ * if {@code pos} is negative.
+ * @see #set(int)
+ * @since Android 1.0
+ */
+ public void set(int pos, boolean val) {
+ if (val) {
+ set(pos);
+ } else {
+ clear(pos);
+ }
+ }
+
+ /**
+ * Sets the bits starting from {@code pos1} to {@code pos2}. Grows the
+ * {@code BitSet} if {@code pos2 > size}.
+ *
+ * @param pos1
+ * beginning position.
+ * @param pos2
+ * ending position.
+ * @throws IndexOutOfBoundsException
+ * if {@code pos1} or {@code pos2} is negative, or if
+ * {@code pos2} is smaller than {@code pos1}.
+ * @see #set(int)
+ * @since Android 1.0
+ */
+ public void set(int pos1, int pos2) {
+ if (pos1 >= 0 && pos2 >= 0 && pos2 >= pos1) {
+ if (pos1 == pos2) {
+ return;
+ }
+ if (pos2 >= bits.length * ELM_SIZE) {
+ growBits(pos2);
+ }
+
+ int idx1 = pos1 / ELM_SIZE;
+ int idx2 = (pos2 - 1) / ELM_SIZE;
+ long factor1 = (~0L) << (pos1 % ELM_SIZE);
+ long factor2 = (~0L) >>> (ELM_SIZE - (pos2 % ELM_SIZE));
+
+ if (idx1 == idx2) {
+ bits[idx1] |= (factor1 & factor2);
+ } else {
+ bits[idx1] |= factor1;
+ bits[idx2] |= factor2;
+ for (int i = idx1 + 1; i < idx2; i++) {
+ bits[i] |= (~0L);
+ }
+ }
+ } else {
+ throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Sets the bits starting from {@code pos1} to {@code pos2} to the given
+ * {@code val}. Grows the {@code BitSet} if {@code pos2 > size}.
+ *
+ * @param pos1
+ * beginning position.
+ * @param pos2
+ * ending position.
+ * @param val
+ * value to set these bits.
+ * @throws IndexOutOfBoundsException
+ * if {@code pos1} or {@code pos2} is negative, or if
+ * {@code pos2} is smaller than {@code pos1}.
+ * @see #set(int,int)
+ * @since Android 1.0
+ */
+ public void set(int pos1, int pos2, boolean val) {
+ if (val) {
+ set(pos1, pos2);
+ } else {
+ clear(pos1, pos2);
+ }
+ }
+
+ /**
+ * Clears all the bits in this {@code BitSet}.
+ *
+ * @see #clear(int)
+ * @see #clear(int, int)
+ * @since Android 1.0
+ */
+ public void clear() {
+ for (int i = 0; i < bits.length; i++) {
+ bits[i] = 0L;
+ }
+ }
+
+ /**
+ * Clears the bit at index {@code pos}. Grows the {@code BitSet} if
+ * {@code pos > size}.
+ *
+ * @param pos
+ * the index of the bit to clear.
+ * @throws IndexOutOfBoundsException
+ * if {@code pos} is negative.
+ * @see #clear(int, int)
+ * @since Android 1.0
+ */
+ public void clear(int pos) {
+ if (pos >= 0) {
+ if (pos < bits.length * ELM_SIZE) {
+ bits[pos / ELM_SIZE] &= ~(1L << (pos % ELM_SIZE));
+ }
+ } else {
+ // Negative index specified
+ throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Clears the bits starting from {@code pos1} to {@code pos2}. Grows the
+ * {@code BitSet} if {@code pos2 > size}.
+ *
+ * @param pos1
+ * beginning position.
+ * @param pos2
+ * ending position.
+ * @throws IndexOutOfBoundsException
+ * if {@code pos1} or {@code pos2} is negative, or if
+ * {@code pos2} is smaller than {@code pos1}.
+ * @see #clear(int)
+ * @since Android 1.0
+ */
+ public void clear(int pos1, int pos2) {
+ if (pos1 >= 0 && pos2 >= 0 && pos2 >= pos1) {
+ int last = (bits.length * ELM_SIZE);
+ if (pos1 >= last || pos1 == pos2) {
+ return;
+ }
+ if (pos2 > last) {
+ pos2 = last;
+ }
+
+ int idx1 = pos1 / ELM_SIZE;
+ int idx2 = (pos2 - 1) / ELM_SIZE;
+ long factor1 = (~0L) << (pos1 % ELM_SIZE);
+ long factor2 = (~0L) >>> (ELM_SIZE - (pos2 % ELM_SIZE));
+
+ if (idx1 == idx2) {
+ bits[idx1] &= ~(factor1 & factor2);
+ } else {
+ bits[idx1] &= ~factor1;
+ bits[idx2] &= ~factor2;
+ for (int i = idx1 + 1; i < idx2; i++) {
+ bits[i] = 0L;
+ }
+ }
+ } else {
+ throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Flips the bit at index {@code pos}. Grows the {@code BitSet} if
+ * {@code pos > size}.
+ *
+ * @param pos
+ * the index of the bit to flip.
+ * @throws IndexOutOfBoundsException
+ * if {@code pos} is negative.
+ * @see #flip(int, int)
+ * @since Android 1.0
+ */
+ public void flip(int pos) {
+ if (pos >= 0) {
+ if (pos >= bits.length * ELM_SIZE) {
+ growBits(pos);
+ }
+ bits[pos / ELM_SIZE] ^= 1L << (pos % ELM_SIZE);
+ } else {
+ throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Flips the bits starting from {@code pos1} to {@code pos2}. Grows the
+ * {@code BitSet} if {@code pos2 > size}.
+ *
+ * @param pos1
+ * beginning position.
+ * @param pos2
+ * ending position.
+ * @throws IndexOutOfBoundsException
+ * if {@code pos1} or {@code pos2} is negative, or if
+ * {@code pos2} is smaller than {@code pos1}.
+ * @see #flip(int)
+ * @since Android 1.0
+ */
+ public void flip(int pos1, int pos2) {
+ if (pos1 >= 0 && pos2 >= 0 && pos2 >= pos1) {
+ if (pos1 == pos2) {
+ return;
+ }
+ if (pos2 >= bits.length * ELM_SIZE) {
+ growBits(pos2);
+ }
+
+ int idx1 = pos1 / ELM_SIZE;
+ int idx2 = (pos2 - 1) / ELM_SIZE;
+ long factor1 = (~0L) << (pos1 % ELM_SIZE);
+ long factor2 = (~0L) >>> (ELM_SIZE - (pos2 % ELM_SIZE));
+
+ if (idx1 == idx2) {
+ bits[idx1] ^= (factor1 & factor2);
+ } else {
+ bits[idx1] ^= factor1;
+ bits[idx2] ^= factor2;
+ for (int i = idx1 + 1; i < idx2; i++) {
+ bits[i] ^= (~0L);
+ }
+ }
+ } else {
+ throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Checks if these two {@code BitSet}s have at least one bit set to true in the same
+ * position.
+ *
+ * @param bs
+ * {@code BitSet} used to calculate the intersection.
+ * @return {@code true} if bs intersects with this {@code BitSet},
+ * {@code false} otherwise.
+ * @since Android 1.0
+ */
+ public boolean intersects(BitSet bs) {
+ long[] bsBits = bs.bits;
+ int length1 = bits.length, length2 = bsBits.length;
+
+ if (length1 <= length2) {
+ for (int i = 0; i < length1; i++) {
+ if ((bits[i] & bsBits[i]) != 0L) {
+ return true;
+ }
+ }
+ } else {
+ for (int i = 0; i < length2; i++) {
+ if ((bits[i] & bsBits[i]) != 0L) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Performs the logical AND of this {@code BitSet} with another
+ * {@code BitSet}. The values of this {@code BitSet} are changed accordingly.
+ *
+ * @param bs
+ * {@code BitSet} to AND with.
+ * @see #or
+ * @see #xor
+ * @since Android 1.0
+ */
+
+ public void and(BitSet bs) {
+ long[] bsBits = bs.bits;
+ int length1 = bits.length, length2 = bsBits.length;
+ if (length1 <= length2) {
+ for (int i = 0; i < length1; i++) {
+ bits[i] &= bsBits[i];
+ }
+ } else {
+ for (int i = 0; i < length2; i++) {
+ bits[i] &= bsBits[i];
+ }
+ for (int i = length2; i < length1; i++) {
+ bits[i] = 0;
+ }
+ }
+ }
+
+ /**
+ * Clears all bits in the receiver which are also set in the parameter
+ * {@code BitSet}. The values of this {@code BitSet} are changed accordingly.
+ *
+ * @param bs
+ * {@code BitSet} to ANDNOT with.
+ * @since Android 1.0
+ */
+ public void andNot(BitSet bs) {
+ long[] bsBits = bs.bits;
+ int range = bits.length < bsBits.length ? bits.length : bsBits.length;
+ for (int i = 0; i < range; i++) {
+ bits[i] &= ~bsBits[i];
+ }
+ }
+
+ /**
+ * Performs the logical OR of this {@code BitSet} with another {@code BitSet}.
+ * The values of this {@code BitSet} are changed accordingly.
+ *
+ * @param bs
+ * {@code BitSet} to OR with.
+ * @see #xor
+ * @see #and
+ * @since Android 1.0
+ */
+ public void or(BitSet bs) {
+ int nbits = bs.length();
+ int length = nbits / ELM_SIZE + (nbits % ELM_SIZE > 0 ? 1 : 0);
+ if (length > bits.length) {
+ growBits(nbits - 1);
+ }
+ long[] bsBits = bs.bits;
+ for (int i = 0; i < length; i++) {
+ bits[i] |= bsBits[i];
+ }
+ }
+
+ /**
+ * Performs the logical XOR of this {@code BitSet} with another {@code BitSet}.
+ * The values of this {@code BitSet} are changed accordingly.
+ *
+ * @param bs
+ * {@code BitSet} to XOR with.
+ * @see #or
+ * @see #and
+ * @since Android 1.0
+ */
+ public void xor(BitSet bs) {
+ int nbits = bs.length();
+ int length = nbits / ELM_SIZE + (nbits % ELM_SIZE > 0 ? 1 : 0);
+ if (length > bits.length) {
+ growBits(nbits - 1);
+ }
+ long[] bsBits = bs.bits;
+ for (int i = 0; i < length; i++) {
+ bits[i] ^= bsBits[i];
+ }
+
+ }
+
+ /**
+ * Returns the number of bits this {@code BitSet} has.
+ *
+ * @return the number of bits contained in this {@code BitSet}.
+ * @see #length
+ * @since Android 1.0
+ */
+ public int size() {
+ return bits.length * ELM_SIZE;
+ }
+
+ /**
+ * Returns the number of bits up to and including the highest bit set.
+ *
+ * @return the length of the {@code BitSet}.
+ * @since Android 1.0
+ */
+ public int length() {
+ int idx = bits.length - 1;
+ while (idx >= 0 && bits[idx] == 0) {
+ --idx;
+ }
+ if (idx == -1) {
+ return 0;
+ }
+ int i = ELM_SIZE - 1;
+ long val = bits[idx];
+ while ((val & (1L << i)) == 0 && i > 0) {
+ i--;
+ }
+ return idx * ELM_SIZE + i + 1;
+ }
+
+ /**
+ * Returns a string containing a concise, human-readable description of the
+ * receiver.
+ *
+ * @return a comma delimited list of the indices of all bits that are set.
+ * @since Android 1.0
+ */
+ @Override
+ public String toString() {
+ StringBuffer sb = new StringBuffer(bits.length / 2);
+ int bitCount = 0;
+ sb.append('{');
+ boolean comma = false;
+ for (int i = 0; i < bits.length; i++) {
+ if (bits[i] == 0) {
+ bitCount += ELM_SIZE;
+ continue;
+ }
+ for (int j = 0; j < ELM_SIZE; j++) {
+ if (((bits[i] & (1L << j)) != 0)) {
+ if (comma) {
+ sb.append(", "); //$NON-NLS-1$
+ }
+ sb.append(bitCount);
+ comma = true;
+ }
+ bitCount++;
+ }
+ }
+ sb.append('}');
+ return sb.toString();
+ }
+
+ /**
+ * Returns the position of the first bit that is {@code true} on or after {@code pos}.
+ *
+ * @param pos
+ * the starting position (inclusive).
+ * @return -1 if there is no bits that are set to {@code true} on or after {@code pos}.
+ * @since Android 1.0
+ */
+ public int nextSetBit(int pos) {
+ if (pos >= 0) {
+ if (pos >= bits.length * ELM_SIZE) {
+ return -1;
+ }
+
+ int idx = pos / ELM_SIZE;
+ // first check in the same bit set element
+ if (bits[idx] != 0L) {
+ for (int j = pos % ELM_SIZE; j < ELM_SIZE; j++) {
+ if (((bits[idx] & (1L << j)) != 0)) {
+ return idx * ELM_SIZE + j;
+ }
+ }
+
+ }
+ idx++;
+ while (idx < bits.length && bits[idx] == 0L) {
+ idx++;
+ }
+ if (idx == bits.length) {
+ return -1;
+ }
+
+ // we know for sure there is a bit set to true in this element
+ // since the bitset value is not 0L
+ for (int j = 0; j < ELM_SIZE; j++) {
+ if (((bits[idx] & (1L << j)) != 0)) {
+ return idx * ELM_SIZE + j;
+ }
+ }
+
+ return -1;
+ }
+ throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the position of the first bit that is {@code false} on or after {@code pos}.
+ *
+ * @param pos
+ * the starting position (inclusive).
+ * @return the position of the next bit set to {@code false}, even if it is further
+ * than this {@code BitSet}'s size.
+ * @since Android 1.0
+ */
+ public int nextClearBit(int pos) {
+ if (pos >= 0) {
+ int bssize = bits.length * ELM_SIZE;
+ if (pos >= bssize) {
+ return pos;
+ }
+
+ int idx = pos / ELM_SIZE;
+ // first check in the same bit set element
+ if (bits[idx] != (~0L)) {
+ for (int j = pos % ELM_SIZE; j < ELM_SIZE; j++) {
+ if (((bits[idx] & (1L << j)) == 0)) {
+ return idx * ELM_SIZE + j;
+ }
+ }
+
+ }
+ idx++;
+ while (idx < bits.length && bits[idx] == (~0L)) {
+ idx++;
+ }
+ if (idx == bits.length) {
+ return bssize;
+ }
+
+ // we know for sure there is a bit set to true in this element
+ // since the bitset value is not 0L
+ for (int j = 0; j < ELM_SIZE; j++) {
+ if (((bits[idx] & (1L << j)) == 0)) {
+ return idx * ELM_SIZE + j;
+ }
+ }
+
+ return bssize;
+ }
+ throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
+ }
+
+ /**
+ * Returns true if all the bits in this {@code BitSet} are set to false.
+ *
+ * @return {@code true} if the {@code BitSet} is empty,
+ * {@code false} otherwise.
+ * @since Android 1.0
+ */
+ public boolean isEmpty() {
+ for (int idx = 0; idx < bits.length; idx++) {
+ if (bits[idx] != 0L) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns the number of bits that are {@code true} in this {@code BitSet}.
+ *
+ * @return the number of {@code true} bits in the set.
+ * @since Android 1.0
+ */
+ public int cardinality() {
+ int count = 0;
+ for (int idx = 0; idx < bits.length; idx++) {
+ long temp = bits[idx];
+ if (temp != 0L) {
+ for (int i = 0; i < ELM_SIZE; i++) {
+ if ((temp & (1L << i)) != 0L) {
+ count++;
+ }
+ }
+ }
+ }
+ return count;
+ }
+}