/*
* Javolution - Java(TM) Solution for Real-Time and Embedded Systems
* Copyright (C) 2012 - Javolution (http://javolution.org/)
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software is
* freely granted, provided that this notice is preserved.
*/
package javolution.util;
import static javolution.lang.Realtime.Limit.LINEAR;
import javolution.lang.Immutable;
import javolution.lang.Realtime;
import javolution.util.internal.bitset.BitSetServiceImpl;
import javolution.util.internal.bitset.UnmodifiableBitSetImpl;
import javolution.util.service.BitSetService;
/**
* <p> A high-performance bitset integrated with the collection framework as
* a set of {@link Index indices} and obeying the collection semantic
* for methods such as {@link #size} (cardinality) or {@link #equals}
* (same set of indices).</p>
*
* @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
* @version 6.0, July 21, 2013
*/
public class FastBitSet extends FastSet<Index> {
private static final long serialVersionUID = 0x600L; // Version.
/**
* Holds the bit set implementation.
*/
private final BitSetService service;
/**
* Returns a new bit set holding the specified indices
* (convenience method).
*/
public static FastBitSet of(Index... indices) {
FastBitSet set = new FastBitSet();
for (Index i : indices) set.add(i);
return set;
}
/**
* Creates an empty bit set.
*/
public FastBitSet() {
service = new BitSetServiceImpl();
}
/**
* Creates a bit set holding the specified bits.
*
* @param bits a long array containing a little-endian representation
* of a sequence of bits to be used as the initial bits of the
* new bit set.
*/
public FastBitSet(Immutable<long[]> bits) {
service = new BitSetServiceImpl(bits.value());
}
/**
* Creates a fast bit set based on the specified implementation.
*/
protected FastBitSet(BitSetService impl) {
this.service = impl;
}
////////////////////////////////////////////////////////////////////////////
// Views.
//
@Override
public FastBitSet unmodifiable() {
return new FastBitSet(new UnmodifiableBitSetImpl(service()));
}
////////////////////////////////////////////////////////////////////////////
// BitSet Operations.
//
/**
* Performs the logical AND operation on this bit set and the
* given bit set. This means it builds the intersection
* of the two sets. The result is stored into this bit set.
*
* @param that the second bit set.
*/
@Realtime(limit = LINEAR)
public void and(FastBitSet that) {
service.and(that.service);
}
/**
* Performs the logical AND operation on this bit set and the
* complement of the given bit set. This means it
* selects every element in the first set, that isn't in the
* second set. The result is stored into this bit set.
*
* @param that the second bit set
*/
@Realtime(limit = LINEAR)
public void andNot(FastBitSet that) {
service.andNot(that.service);
}
/**
* Returns the number of bits set to {@code true} (or the size of this
* set).
*
* @return the number of bits being set.
*/
public int cardinality() {
return service.cardinality();
}
/**
* Sets all bits in the set to {@code false} (empty the set).
*/
@Override
public void clear() {
service.clear();
}
/**
* Removes the specified integer value from this set. That is
* the corresponding bit is cleared.
*
* @param bitIndex a non-negative integer.
* @throws IndexOutOfBoundsException if {@code index < 0}
*/
public void clear(int bitIndex) {
service.clear(bitIndex);
}
/**
* Sets the bits from the specified {@code fromIndex} (inclusive) to the
* specified {@code toIndex} (exclusive) to {@code false}.
*
* @param fromIndex index of the first bit to be cleared.
* @param toIndex index after the last bit to be cleared.
* @throws IndexOutOfBoundsException if
* {@code (fromIndex < 0) | (toIndex < fromIndex)}
*/
@Realtime(limit = LINEAR)
public void clear(int fromIndex, int toIndex) {
service.clear(fromIndex, toIndex);
}
/**
* Sets the bit at the index to the opposite value.
*
* @param bitIndex the index of the bit.
* @throws IndexOutOfBoundsException if {@code bitIndex < 0}
*/
public void flip(int bitIndex) {
service.flip(bitIndex);
}
/**
* Sets a range of bits to the opposite value.
*
* @param fromIndex the low index (inclusive).
* @param toIndex the high index (exclusive).
* @throws IndexOutOfBoundsException if
* {@code (fromIndex < 0) | (toIndex < fromIndex)}
*/
@Realtime(limit = LINEAR)
public void flip(int fromIndex, int toIndex) {
service.flip(fromIndex, toIndex);
}
/**
* Returns {@code true } if the specified integer is in
* this bit set; {@code false } otherwise.
*
* @param bitIndex a non-negative integer.
* @return the value of the bit at the specified index.
* @throws IndexOutOfBoundsException if {@code bitIndex < 0}
*/
public boolean get(int bitIndex) {
return service.get(bitIndex);
}
/**
* Returns a new bit set composed of a range of bits from this one.
*
* @param fromIndex the low index (inclusive).
* @param toIndex the high index (exclusive).
* @return a context allocated bit set instance.
* @throws IndexOutOfBoundsException if
* {@code (fromIndex < 0) | (toIndex < fromIndex)}
*/
@Realtime(limit = LINEAR)
public FastBitSet get(int fromIndex, int toIndex) {
return new FastBitSet(service.get(fromIndex, toIndex));
}
/**
* Returns {@code true} if this bit set shares at least one
* common bit with the specified bit set.
*
* @param that the bit set to check for intersection
* @return {@code true} if the sets intersect; {@code false} otherwise.
*/
@Realtime(limit = LINEAR)
public boolean intersects(FastBitSet that) {
return service.intersects(that.service);
}
/**
* Returns the logical number of bits actually used by this bit
* set. It returns the index of the highest set bit plus one.
*
* <p> Note: This method does not return the number of set bits
* which is returned by {@link #size} </p>
*
* @return the index of the highest set bit plus one.
*/
public int length() {
return service.length();
}
/**
* Returns the index of the next {@code false} bit, from the specified bit
* (inclusive).
*
* @param fromIndex the start location.
* @return the first {@code false} bit.
* @throws IndexOutOfBoundsException if {@code fromIndex < 0}
*/
public int nextClearBit(int fromIndex) {
return service.nextClearBit(fromIndex);
}
/**
* Returns the index of the next {@code true} bit, from the specified bit
* (inclusive). If there is none, {@code -1} is returned.
* The following code will iterates through the bit set:[code]
* for (int i=nextSetBit(0); i >= 0; i = nextSetBit(i+1)) {
* ...
* }[/code]
*
* @param fromIndex the start location.
* @return the first {@code false} bit.
* @throws IndexOutOfBoundsException if {@code fromIndex < 0}
*/
public int nextSetBit(int fromIndex) {
return service.nextSetBit(fromIndex);
}
/**
* Returns the index of the previous {@code false} bit,
* from the specified bit (inclusive).
*
* @param fromIndex the start location.
* @return the first {@code false} bit.
* @throws IndexOutOfBoundsException if {@code fromIndex < -1}
*/
public int previousClearBit(int fromIndex) {
return service.previousClearBit(fromIndex);
}
/**
* Returns the index of the previous {@code true} bit, from the
* specified bit (inclusive). If there is none, {@code -1} is returned.
* The following code will iterates through the bit set:[code]
* for (int i = length(); (i = previousSetBit(i-1)) >= 0; ) {
* ...
* }[/code]
*
* @param fromIndex the start location.
* @return the first {@code false} bit.
* @throws IndexOutOfBoundsException if {@code fromIndex < -1}
*/
public int previousSetBit(int fromIndex) {
return service.previousSetBit(fromIndex);
}
/**
* Performs the logical OR operation on this bit set and the one specified.
* In other words, builds the union of the two sets.
* The result is stored into this bit set.
*
* @param that the second bit set.
*/
@Realtime(limit = LINEAR)
public void or(FastBitSet that) {
service.or(that.service);
}
/**
* Adds the specified integer to this set (corresponding bit is set to
* {@code true}.
*
* @param bitIndex a non-negative integer.
* @throws IndexOutOfBoundsException if {@code bitIndex < 0}
*/
public void set(int bitIndex) {
service.set(bitIndex);
}
/**
* Sets the bit at the given index to the specified value.
*
* @param bitIndex the position to set.
* @param value the value to set it to.
* @throws IndexOutOfBoundsException if {@code bitIndex < 0}
*/
public void set(int bitIndex, boolean value) {
service.set(bitIndex, value);
}
/**
* Sets the bits from the specified {@code fromIndex} (inclusive) to the
* specified {@code toIndex} (exclusive) to {@code true}.
*
* @param fromIndex index of the first bit to be set.
* @param toIndex index after the last bit to be set.
* @throws IndexOutOfBoundsException if
* {@code (fromIndex < 0) | (toIndex < fromIndex)}
*/
@Realtime(limit = LINEAR)
public void set(int fromIndex, int toIndex) {
if ((fromIndex < 0) || (toIndex < fromIndex)) throw new IndexOutOfBoundsException();
service.set(fromIndex, toIndex);
}
/**
* Sets the bits between from (inclusive) and to (exclusive) to the
* specified value.
*
* @param fromIndex the start range (inclusive).
* @param toIndex the end range (exclusive).
* @param value the value to set it to.
* @throws IndexOutOfBoundsException if {@code bitIndex < 0}
*/
@Realtime(limit = LINEAR)
public void set(int fromIndex, int toIndex, boolean value) {
service.set(fromIndex, toIndex, value);
}
/**
* Performs the logical XOR operation on this bit set and the one specified.
* In other words, builds the symmetric remainder of the two sets
* (the elements that are in one set, but not in the other).
* The result is stored into this bit set.
*
* @param that the second bit set.
*/
@Realtime(limit = LINEAR)
public void xor(FastBitSet that) {
service.xor(that.service);
}
////////////////////////////////////////////////////////////////////////////
// Misc.
//
@Override
protected BitSetService service() {
return service;
}
}