public class BitVector extends PersistentObject
Individual indexed bits can be examined, set, or cleared.
Subranges can quickly be extracted, copied and replaced.
Quick iteration over subranges is provided by optimized internal iterators (forEach() methods).
One BitVector
may be used to modify the contents of another
BitVector
through logical AND, OR, XOR and other similar operations.
All operations consider the bits 0..size()-1 and nothing else. Operations involving two bitvectors (like AND, OR, XOR, etc.) will throw an IllegalArgumentException if the secondary bit vector has a size smaller than the receiver.
A BitVector is never automatically resized, but it can manually be grown or shrinked via setSize(...).
For use cases that need to store several bits per information entity, quick accessors are provided that interpret subranges as 64 bit long integers.
Why this class? Fist, boolean[] take one byte per stored bit. This class takes one bit per stored bit. Second, many applications find the semantics of java.util.BitSet not particularly helpful for their needs. Third, operations working on all bits of a bitvector are extremely quick. For example, on NT, Pentium Pro 200 Mhz, SunJDK1.2.2, java -classic, for two bitvectors A,B (both much larger than processor cache), the following results are obtained.
Note that this implementation is not synchronized.
QuickBitVector
,
BitMatrix
,
BitSet
,
Serialized FormModifier and Type | Field and Description |
---|---|
protected long[] |
bits
The bits of this object.
|
protected int |
nbits |
serialVersionUID
Constructor and Description |
---|
BitVector(int size)
Constructs a bit vector that holds size bits.
|
BitVector(long[] bits,
int size)
You normally need not use this method.
|
Modifier and Type | Method and Description |
---|---|
void |
and(BitVector other)
Performs a logical AND of the receiver with another bit vector (A = A & B).
|
void |
andNot(BitVector other)
Clears all of the bits in receiver whose corresponding
bit is set in the other bitvector (A = A \ B).
|
int |
cardinality()
Returns the number of bits currently in the true state.
|
protected static void |
checkRangeFromTo(int from,
int to,
int theSize)
Checks if the given range is within the contained array's bounds.
|
protected void |
checkSize(BitVector other)
Sanity check for operations requiring another bitvector with at least the same size.
|
void |
clear()
Clears all bits of the receiver.
|
void |
clear(int bitIndex)
Changes the bit with index bitIndex to the "clear" (false) state.
|
Object |
clone()
Cloning this
BitVector produces a new BitVector
that is equal to it. |
BitVector |
copy()
Returns a deep copy of the receiver; calls
clone() and casts the result. |
long[] |
elements()
You normally need not use this method.
|
void |
elements(long[] bits,
int size)
You normally need not use this method.
|
boolean |
equals(Object obj)
Compares this object against the specified object.
|
boolean |
forEachIndexFromToInState(int from,
int to,
boolean state,
IntProcedure procedure)
Applies a procedure to each bit index within the specified range that holds a bit in the given state.
|
boolean |
get(int bitIndex)
Returns from the bitvector the value of the bit with the specified index.
|
long |
getLongFromTo(int from,
int to)
Returns a long value representing bits of the receiver from index from to index to.
|
boolean |
getQuick(int bitIndex)
Returns from the bitvector the value of the bit with the specified index; WARNING: Does not check preconditions.
|
int |
hashCode()
Returns a hash code value for the receiver.
|
int |
indexOfFromTo(int from,
int to,
boolean state)
Returns the index of the first occurrence of the specified
state.
|
void |
not()
Performs a logical NOT on the bits of the receiver (A = ~A).
|
protected int |
numberOfBitsInPartialUnit()
Returns the number of bits used in the trailing PARTIAL unit.
|
protected int |
numberOfFullUnits()
Returns the number of units that are FULL (not PARTIAL).
|
void |
or(BitVector other)
Performs a logical OR of the receiver with another bit vector (A = A | B).
|
BitVector |
partFromTo(int from,
int to)
Constructs and returns a new bit vector which is a copy of the given range.
|
void |
put(int bitIndex,
boolean value)
Sets the bit with index bitIndex to the state specified by value.
|
void |
putLongFromTo(long value,
int from,
int to)
Sets bits of the receiver from index
from to index to to the bits of value . |
void |
putQuick(int bitIndex,
boolean value)
Sets the bit with index bitIndex to the state specified by value; WARNING: Does not check preconditions.
|
void |
replaceFromToWith(int from,
int to,
BitVector source,
int sourceFrom)
Replaces the bits of the receiver in the given range with the bits of another bit vector.
|
void |
replaceFromToWith(int from,
int to,
boolean value)
Sets the bits in the given range to the state specified by value.
|
void |
set(int bitIndex)
Changes the bit with index bitIndex to the "set" (true) state.
|
void |
setSize(int newSize)
Shrinks or expands the receiver so that it holds newSize bits.
|
int |
size()
Returns the size of the receiver.
|
String |
toString()
Returns a string representation of the receiver.
|
void |
xor(BitVector other)
Performs a logical XOR of the receiver with another bit vector (A = A ^ B).
|
protected long[] bits
protected int nbits
public BitVector(long[] bits, int size)
A bitvector is modelled as a long array, i.e. long[] bits holds bits of a bitvector. Each long value holds 64 bits. The i-th bit is stored in bits[i/64] at bit position i % 64 (where bit position 0 refers to the least significant bit and 63 refers to the most significant bit).
IllegalArgumentException
- if size < 0 || size > bits.length*64.public BitVector(int size)
size
- the number of bits the bit vector shall have.IllegalArgumentException
- if size < 0.public void and(BitVector other)
true
if and only if it already had the
value true
and the corresponding bit in the other bit vector
argument has the value true
.other
- a bit vector.IllegalArgumentException
- if size() > other.size().public void andNot(BitVector other)
other
- a bitvector with which to mask the receiver.IllegalArgumentException
- if size() > other.size().public int cardinality()
protected static void checkRangeFromTo(int from, int to, int theSize)
protected void checkSize(BitVector other)
public void clear()
public void clear(int bitIndex)
bitIndex
- the index of the bit to be cleared.IndexOutOfBoundsException
- if bitIndex<0 || bitIndex>=size()public Object clone()
BitVector
produces a new BitVector
that is equal to it.
The clone of the bit vector is another bit vector that has exactly the
same bits set to true
as this bit vector and the same
current size, but independent state.clone
in class PersistentObject
public BitVector copy()
clone()
and casts the result.public long[] elements()
A bitvector is modelled as a long array, i.e. long[] bits holds bits of a bitvector. Each long value holds 64 bits. The i-th bit is stored in bits[i/64] at bit position i % 64 (where bit position 0 refers to the least significant bit and 63 refers to the most significant bit).
public void elements(long[] bits, int size)
A bitvector is modelled as a long array, i.e. long[] bits holds bits of a bitvector. Each long value holds 64 bits. The i-th bit is stored in bits[i/64] at bit position i % 64 (where bit position 0 refers to the least significant bit and 63 refers to the most significant bit).
bits
- the backing bits of the bit vector.size
- the number of bits the bit vector shall hold.IllegalArgumentException
- if size < 0 || size > bits.length*64.public boolean equals(Object obj)
true
if and only if the argument is
not null
and is a BitVector
object
that has the same size as the receiver and
the same bits set to true
as the receiver.
That is, for every nonnegative int
index k
,
((BitVector)obj).get(k) == this.get(k)must be true.
public boolean forEachIndexFromToInState(int from, int to, boolean state, IntProcedure procedure)
Optimized for speed. Particularly quick if one of the following conditions holds
from
- the leftmost search position, inclusive.to
- the rightmost search position, inclusive.state
- element to search for.procedure
- a procedure object taking as argument the current bit index. Stops iteration if the procedure returns false, otherwise continues.IndexOutOfBoundsException
- if (size()>0 && (from<0 || from>to || to>=size())).public boolean get(int bitIndex)
bitIndex
- the bit index.IndexOutOfBoundsException
- if bitIndex<0 || bitIndex>=size()public long getLongFromTo(int from, int to)
from
, ..., bit to-from
set to bit to
.
All other bits of the return value are set to 0.
If to-from+1==0 then returns zero (0L).from
- index of start bit (inclusive).to
- index of end bit (inclusive).IndexOutOfBoundsException
- if from<0 || from>=size() || to<0 || to>=size() || to-from+1<0 || to-from+1>64public boolean getQuick(int bitIndex)
Provided with invalid parameters this method may return invalid values without throwing any exception. You should only use this method when you are absolutely sure that the index is within bounds. Precondition (unchecked): bitIndex >= 0 && bitIndex < size().
bitIndex
- the bit index.public int hashCode()
Suppose the bits in the receiver were to be stored
in an array of long
integers called, say,
bits
, in such a manner that bit k
is
set in the receiver (for nonnegative values of
k
) if and only if the expression
((k>>6) < bits.length) && ((bits[k>>6] & (1L << (bit & 0x3F))) != 0)is true. Then the following definition of the
hashCode
method would be a correct implementation of the actual algorithm:
public int hashCode() { long h = 1234; for (int i = bits.length; --i >= 0; ) { h ^= bits[i] * (i + 1); } return (int)((h >> 32) ^ h); }Note that the hash code values change if the set of bits is altered.
public int indexOfFromTo(int from, int to, boolean state)
-1
if the receiver does not contain this state.
Searches between from
, inclusive and to
, inclusive.
Optimized for speed. Preliminary performance (200Mhz Pentium Pro, JDK 1.2, NT): size=10^6, from=0, to=size-1, receiver contains matching state in the very end --> 0.002 seconds elapsed time.
state
- state to search for.from
- the leftmost search position, inclusive.to
- the rightmost search position, inclusive.-1
if the element is not found.IndexOutOfBoundsException
- if (size()>0 && (from<0 || from>to || to>=size())).public void not()
protected int numberOfBitsInPartialUnit()
protected int numberOfFullUnits()
public void or(BitVector other)
true
if and only if it either already had the
value true
or the corresponding bit in the other bit vector
argument has the value true
.other
- a bit vector.IllegalArgumentException
- if size() > other.size().public BitVector partFromTo(int from, int to)
from
- the start index within the receiver, inclusive.to
- the end index within the receiver, inclusive.IndexOutOfBoundsException
- if size()>0 && (from<0 || from>to || to>=size())).public void put(int bitIndex, boolean value)
bitIndex
- the index of the bit to be changed.value
- the value to be stored in the bit.IndexOutOfBoundsException
- if bitIndex<0 || bitIndex>=size()public void putLongFromTo(long value, int from, int to)
from
to index to
to the bits of value
.
Bit from
is set to bit 0 of value
, ..., bit to
is set to bit to-from
of value
.
All other bits stay unaffected.
If to-from+1==0 then does nothing.value
- the value to be copied into the receiver.from
- index of start bit (inclusive).to
- index of end bit (inclusive).IndexOutOfBoundsException
- if from<0 || from>=size() || to<0 || to>=size() || to-from+1<0 || to-from+1>64.public void putQuick(int bitIndex, boolean value)
Provided with invalid parameters this method may set invalid values without throwing any exception. You should only use this method when you are absolutely sure that the index is within bounds. Precondition (unchecked): bitIndex >= 0 && bitIndex < size().
bitIndex
- the index of the bit to be changed.value
- the value to be stored in the bit.public void replaceFromToWith(int from, int to, BitVector source, int sourceFrom)
Optimized for speed. Preliminary performance (200Mhz Pentium Pro, JDK 1.2, NT): replace 10^6 ill aligned bits --> 0.02 seconds elapsed time.
from
- the start index within the receiver, inclusive.to
- the end index within the receiver, inclusive.source
- the source bitvector to copy from.sourceFrom
- the start index within source, inclusive.IndexOutOfBoundsException
- if size()>0 && (from<0 || from>to || to>=size() || sourceFrom<0 || sourceFrom+to-from+1>source.size())).public void replaceFromToWith(int from, int to, boolean value)
Optimized for speed. Preliminary performance (200Mhz Pentium Pro, JDK 1.2, NT): replace 10^6 ill aligned bits --> 0.002 seconds elapsed time.
from
- the start index, inclusive.to
- the end index, inclusive.value
- the value to be stored in the bits of the range.IndexOutOfBoundsException
- if size()>0 && (from<0 || from>to || to>=size()).public void set(int bitIndex)
bitIndex
- the index of the bit to be set.IndexOutOfBoundsException
- if bitIndex<0 || bitIndex>=size()public void setSize(int newSize)
newSize
- the number of bits the bit vector shall have.IllegalArgumentException
- if size < 0.public int size()
public String toString()
public void xor(BitVector other)
true
if and only if one of the following statements holds:
true
, and the
corresponding bit in the argument has the value false
.
false
, and the
corresponding bit in the argument has the value true
.
other
- a bit vector.IllegalArgumentException
- if size() > other.size().Copyright © 2006–2019 SYSTAP, LLC DBA Blazegraph. All rights reserved.