org.jgroups.util.FixedSizeBitSet Maven / Gradle / Ivy
package org.jgroups.util;
/**
* Class copied from {@link java.util.BitSet}. Changes are that the FixedSizeBitSet doesn't expand, so access to it
* doesn't need to be synchronized, plus we only need a few methods so most methods of the old class have been removed.
* @author Bela Ban
*/
public class FixedSizeBitSet {
/*
* BitSets are packed into arrays of "words." Currently a word is a long, which consists of 64 bits, requiring
* 6 address bits. The choice of word size is determined purely by performance concerns.
*/
protected final static int ADDRESS_BITS_PER_WORD=6;
protected final static int BITS_PER_WORD=1 << ADDRESS_BITS_PER_WORD;
/* Used to shift left or right for a partial word mask */
protected static final long WORD_MASK=0xffffffffffffffffL;
protected long[] words;
protected int size;
public FixedSizeBitSet() {
}
/**
* Creates a bit set whose initial size is the range 0
through
* size-1
. All bits are initially false
.
* @param size the initial size of the bit set (in bits).
* @throws NegativeArraySizeException if the specified initial size is negative
*/
public FixedSizeBitSet(int size) {
if(size < 0) // nbits can't be negative; size 0 is OK
throw new NegativeArraySizeException("size < 0: " + size);
this.size=size;
words=new long[wordIndex(size - 1) + 1];
}
/**
* Sets the bit at the specified index to true
.
* @param index a bit index.
* @return true if the bit was 0 before, false otherwise
* @throws IndexOutOfBoundsException if the specified index is negative.
*/
public boolean set(int index) {
if(index < 0 || index >= size)
throw new IndexOutOfBoundsException("index: " + index);
int wordIndex=wordIndex(index);
boolean already_set=(words[wordIndex] & (1L << index)) != 0;
words[wordIndex]|=(1L << index); // Restores invariants
return !already_set;
}
/**
* Sets the bits from the specified {@code from} (inclusive) to the
* specified {@code to} (inclusive) to {@code true}.
*
* @param from index of the first bit to be set
* @param to index of the last bit to be set
* @throws IndexOutOfBoundsException if {@code from} is negative, or {@code to} is negative, or {@code from} is
* larger than {@code to}
*/
public void set(int from, int to) {
if(from < 0 || to < 0 || to < from || to >= size)
throw new IndexOutOfBoundsException("from=" + from + ", to=" + to);
// Increase capacity if necessary
int startWordIndex = wordIndex(from);
int endWordIndex = wordIndex(to);
long firstWordMask = WORD_MASK << from;
long lastWordMask = WORD_MASK >>> -(to+1);
if (startWordIndex == endWordIndex) {
// Case 1: One word
words[startWordIndex] |= (firstWordMask & lastWordMask);
} else {
// Case 2: Multiple words
// Handle first word
words[startWordIndex] |= firstWordMask;
// Handle intermediate words, if any
for (int i = startWordIndex+1; i < endWordIndex; i++)
words[i] = WORD_MASK;
// Handle last word (restores invariants)
words[endWordIndex] |= lastWordMask;
}
}
/**
* Sets the bit specified by the index to false
.
* @param index the index of the bit to be cleared.
* @throws IndexOutOfBoundsException if the specified index is negative.
*/
public void clear(int index) {
if(index < 0 || index >= size)
throw new IndexOutOfBoundsException("index: " + index);
int wordIndex=wordIndex(index);
words[wordIndex]&=~(1L << index);
}
/**
* Sets the bits from the specified {@code from} (inclusive) to the
* specified {@code to} (inclusive) to {@code false}.
*
* @param from index of the first bit to be cleared
* @param to index of the last bit to be cleared
* @throws IndexOutOfBoundsException if {@code from} is negative, or {@code to} is negative,
* or {@code from} is larger than {@code to}
*/
public void clear(int from, int to) {
if(from < 0 || to < 0 || to < from || to >= size)
throw new IndexOutOfBoundsException("from=" + from + ", to=" + to);
int startWordIndex = wordIndex(from);
int endWordIndex = wordIndex(to);
long firstWordMask = WORD_MASK << from;
long lastWordMask = WORD_MASK >>> -(to+1);
if (startWordIndex == endWordIndex) {
// Case 1: One word
words[startWordIndex] &= ~(firstWordMask & lastWordMask);
} else {
// Case 2: Multiple words
// Handle first word
words[startWordIndex] &= ~firstWordMask;
// Handle intermediate words, if any
for (int i = startWordIndex+1; i < endWordIndex; i++)
words[i] = 0;
// Handle last word
words[endWordIndex] &= ~lastWordMask;
}
}
/**
* Returns the value of the bit with the specified index. The value
* is true
if the bit with the index index
* is currently set in this bit set; otherwise, the result is false
.
* @param index the bit index.
* @return the value of the bit with the specified index.
* @throws IndexOutOfBoundsException if the specified index is negative.
*/
public boolean get(int index) {
if(index < 0 || index >= size)
throw new IndexOutOfBoundsException("index: " + index);
int wordIndex=wordIndex(index);
return (words[wordIndex] & (1L << index)) != 0;
}
/**
* Returns the index of the first bit that is set to true
that occurs on or after
* the specified starting index. If no such bit exists then -1 is returned.
*
* To iterate over the true
bits in a BitSet
,
* use the following loop:
*
*
* for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) {
* // operate on index i here
* }
* @param fromIndex the index to start checking from (inclusive).
* @return the index of the next set bit.
* @throws IndexOutOfBoundsException if the specified index is negative.
*/
public int nextSetBit(int fromIndex) {
if(fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex: " + fromIndex);
if(fromIndex >= size)
return -1;
int u=wordIndex(fromIndex);
long word=words[u] & (WORD_MASK << fromIndex);
while(true) {
if(word != 0)
return (u * BITS_PER_WORD) + Long.numberOfTrailingZeros(word);
if(++u == words.length)
return -1;
word=words[u];
}
}
/**
* Returns the index of the first bit that is set to false
* that occurs on or after the specified starting index.
* @param fromIndex the index to start checking from (inclusive).
* @return the index of the next clear bit.
* @throws IndexOutOfBoundsException if the specified index is negative.
*/
public int nextClearBit(int fromIndex) {
// Neither spec nor implementation handle bitsets of maximal length.
// See 4816253.
if(fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex: " + fromIndex);
if(fromIndex >= size)
return -1;
int u=wordIndex(fromIndex);
if(u >= words.length)
return fromIndex;
long word=~words[u] & (WORD_MASK << fromIndex);
while(true) {
if(word != 0)
return (u * BITS_PER_WORD) + Long.numberOfTrailingZeros(word);
if(++u == words.length)
return -1;
word=~words[u];
}
}
/**
* Returns the index of the nearest bit that is set to {@code true}
* that occurs on or before the specified starting index.
* If no such bit exists, or if {@code -1} is given as the
* starting index, then {@code -1} is returned.
* @param from the index to start checking from (inclusive)
* @return the index of the previous set bit, or {@code -1} if there is no such bit
* @throws IndexOutOfBoundsException if the specified index is less than {@code -1}
*/
public int previousSetBit(int from) {
if(from < 0 || from >= size)
throw new IndexOutOfBoundsException("index: " + from);
int u = wordIndex(from);
long word = words[u] & (WORD_MASK >>> -(from+1));
while (true) {
if (word != 0)
return (u+1) * BITS_PER_WORD - 1 - Long.numberOfLeadingZeros(word);
if (u-- == 0)
return -1;
word = words[u];
}
}
/**
* Returns the number of bits set to true in this bit set
* @return the number of bits set to true in this bit set
*/
public int cardinality() {
int sum=0;
for(int i=0; i < words.length; i++)
sum+=Long.bitCount(words[i]);
return sum;
}
public int size() {return size;}
/**
* Flips all bits: 1 --> 0 and 0 --> 1
*/
public void flip() {
int fromIndex=0, toIndex=size();
if (fromIndex == toIndex)
return;
int startWordIndex = wordIndex(fromIndex);
int endWordIndex = wordIndex(toIndex);
long firstWordMask = WORD_MASK << fromIndex;
long lastWordMask = WORD_MASK >>> -toIndex;
if (startWordIndex == endWordIndex) {
// Case 1: One word
words[startWordIndex] ^= (firstWordMask & lastWordMask);
} else {
// Case 2: Multiple words
// Handle first word
words[startWordIndex] ^= firstWordMask;
// Handle intermediate words, if any
for (int i = startWordIndex+1; i < endWordIndex; i++)
words[i] ^= WORD_MASK;
// Handle last word
words[endWordIndex] ^= lastWordMask;
}
}
/**
* Returns a string representation of this bit set. For every index
* for which this BitSet
contains a bit in the set
* state, the decimal representation of that index is included in
* the result. Such indices are listed in order from lowest to
* highest, separated by ", " (a comma and a space) and
* surrounded by braces, resulting in the usual mathematical
* notation for a set of integers.
* Overrides the toString
method of Object
.
*
Example:
*
* BitSet drPepper = new BitSet();
* Now drPepper.toString()
returns "{}
".
*
* drPepper.set(2);
* Now drPepper.toString()
returns "{2}
".
*
* drPepper.set(4);
* drPepper.set(10);
* Now drPepper.toString()
returns "{2, 4, 10}
".
* @return a string representation of this bit set.
*/
public String toString() {
if(cardinality() == 0)
return "{}";
StringBuilder sb=new StringBuilder("(").append(cardinality()).append("): {");
boolean first=true;
int num=Util.MAX_LIST_PRINT_SIZE;
for(int i=nextSetBit(0); i >= 0; i=nextSetBit(i + 1)) {
int endOfRun=nextClearBit(i);
if(first)
first=false;
else
sb.append(", ");
if(endOfRun != -1 && endOfRun-1 != i) {
sb.append(i).append('-').append(endOfRun-1);
i=endOfRun;
}
else
sb.append(i);
if(--num <= 0) {
sb.append(", ... ");
break;
}
}
sb.append('}');
return sb.toString();
}
protected static int wordIndex(int bitIndex) {
return bitIndex >> ADDRESS_BITS_PER_WORD;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy