Browse Source

common.IterableBitSet: return a primitive OfInt iterator, allow reverse iteration [with Steffen Maercker]

git-svn-id: https://www.prismmodelchecker.org/svn/prism/prism/trunk@12083 bbc10eb1-c90d-0410-af57-cb519fbb1720
master
Joachim Klein 9 years ago
parent
commit
285ccd52e2
  1. 204
      prism/src/common/IterableBitSet.java

204
prism/src/common/IterableBitSet.java

@ -28,8 +28,10 @@
package common;
import java.util.BitSet;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.PrimitiveIterator.OfInt;
import common.iterable.IterableInt;
/**
* Convenience class to loop easily over the set/clear bits of a BitSet.
@ -37,10 +39,11 @@ import java.util.NoSuchElementException;
* For example:<br/><br/>
* <code>for (Integer index : getSetBits(set)) { ... }</code><br/>
*/
public class IterableBitSet implements Iterable<Integer>
public class IterableBitSet implements IterableInt
{
private BitSet set;
private boolean clearBits = false;
private boolean reversed = false;
private Integer maxIndex = null;
/**
@ -50,59 +53,127 @@ public class IterableBitSet implements Iterable<Integer>
{
this.set = set;
this.clearBits = false;
this.reversed = false;
}
/**
* Constructor for an Iterable that iterates over bits of the given set {@code set},
* up to the maximal index given by {@code maxIndex} (optional).
* If {@code clearBits} is {@code true}, iterate over the cleared bits instead of the set bits
* (requires {@code maxIndex} to be non-null).
* @param set the underlying BitSet
* @param maxIndex the maximal index for iteration (negative = iterate over the empty set, {@code null} = no restrictions)
* @param clearBits if true, iterate over the cleared bits in the BitSet
*/
public IterableBitSet(BitSet set, Integer maxIndex, boolean clearBits)
{
this(set, maxIndex, clearBits, false);
}
/**
* Constructor for an Iterable that iterates over bits of the given set {@code set},
* up to the maximal index given by {@code maxIndex}. If {@code clearBits} is {@code true},
* iterate over the cleared bits instead of the set bits.
* up to the maximal index given by {@code maxIndex} (optional).
* If {@code clearBits} is {@code true}, iterate over the cleared bits instead of the set bits
* (requires {@code maxIndex} to be non-null).
* If {@code reversed} is set, iterate in reverse order (highest to lowest).
* @param set the underlying BitSet
* @param maxIndex the maximal index for iteration (negative = iterate over the empty set)
* @param maxIndex the maximal index for iteration (negative = iterate over the empty set, {@code null} = no restrictions)
* @param clearBits if true, iterate over the cleared bits in the BitSet
* @param reversed if true, iterate in reversed order
*/
public IterableBitSet(BitSet set, int maxIndex, boolean clearBits)
public IterableBitSet(BitSet set, Integer maxIndex, boolean clearBits, boolean reversed)
{
this.set = set;
this.maxIndex = maxIndex;
this.clearBits = clearBits;
this.reversed = reversed;
}
/** Implementation of the iterator over the set bits */
private class SetBitsIterator implements Iterator<Integer> {
private int index = set.nextSetBit(0);
private class SetBitsIterator implements OfInt
{
private int current = -1;
private int next = set.nextSetBit(0);
@Override
public boolean hasNext() {
if (maxIndex != null && index > maxIndex) {
public boolean hasNext()
{
if (maxIndex != null && next > maxIndex) {
// limit to 0 ... maxIndex
return false;
}
return index >= 0;
return next >= 0;
}
@Override
public int nextInt()
{
if (hasNext()) {
current = next;
next = set.nextSetBit(current + 1);
return current;
}
throw new NoSuchElementException();
}
@Override
public void remove()
{
set.clear(current);
}
}
/** Implementation of the iterator over the set bits (reverse order) */
private class SetBitsReversedIterator implements OfInt
{
private int current = -1;
private int next = set.nextSetBit(0);
public SetBitsReversedIterator()
{
current = -1;
if (maxIndex != null) {
// only consider set bits with index <= maxIndex
next = set.previousSetBit(maxIndex);
} else {
next = set.length() - 1; // highest set bit
}
}
@Override
public boolean hasNext()
{
return next >= 0;
}
@Override
public Integer next() {
public int nextInt()
{
if (hasNext()) {
Integer next = index;
index = set.nextSetBit(index + 1);
return next;
current = next;
next = set.previousSetBit(current - 1);
return current;
}
throw new NoSuchElementException();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
public void remove()
{
set.clear(current);
}
}
/** Implementation of the iterator over the cleared bits, requires that {@code maxIndex != null} */
private class ClearBitsIterator implements Iterator<Integer> {
private int index = set.nextClearBit(0);
private class ClearBitsIterator implements OfInt
{
private int current = -1;
private int next = set.nextClearBit(0);
@Override
public boolean hasNext() {
if (index > maxIndex) {
public boolean hasNext()
{
if (next > maxIndex) {
// limit to 0 ... maxIndex
return false;
}
@ -110,27 +181,75 @@ public class IterableBitSet implements Iterable<Integer>
}
@Override
public Integer next() {
public int nextInt()
{
if (hasNext()) {
Integer next = index;
index = set.nextClearBit(index + 1);
return next;
current = next;
next = set.nextClearBit(current + 1);
return current;
}
throw new NoSuchElementException();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
public void remove()
{
set.set(current);
}
}
/** Implementation of the iterator over the clear bits (reverse order), requires that {@code maxIndex != null} */
private class ClearBitsReversedIterator implements OfInt
{
private int current = -1;
private int next = set.nextSetBit(0);
public ClearBitsReversedIterator()
{
current = -1;
// only consider clear bits with index <= maxIndex
next = set.previousClearBit(maxIndex);
}
@Override
public boolean hasNext()
{
return next >= 0;
}
@Override
public int nextInt()
{
if (hasNext()) {
current = next;
next = set.previousClearBit(current - 1);
return current;
}
throw new NoSuchElementException();
}
@Override
public void remove()
{
set.clear(current);
}
}
@Override
public Iterator<Integer> iterator() {
public OfInt iterator()
{
if (clearBits == false) {
return new SetBitsIterator();
if (reversed) {
return new SetBitsReversedIterator();
} else {
return new SetBitsIterator();
}
} else {
return new ClearBitsIterator();
if (reversed) {
return new ClearBitsReversedIterator();
} else {
return new ClearBitsIterator();
}
}
}
@ -144,6 +263,17 @@ public class IterableBitSet implements Iterable<Integer>
return new IterableBitSet(set);
}
/**
* Get an IterableBitSet that iterates over the bits of {@code set} that are set,
* in reverse order (highest to lowest index).
* @param set a BitSet
* @return an IterableBitSet over the set bits
*/
public static IterableBitSet getSetBitsReversed(BitSet set)
{
return new IterableBitSet(set, null, false, true);
}
/**
* Get an IterableBitSet that iterates over the cleared bits of {@code set}, up to {@code maxIndex}
* @param set a BitSet
@ -155,6 +285,17 @@ public class IterableBitSet implements Iterable<Integer>
return new IterableBitSet(set, maxIndex, true);
}
/**
* Get an IterableBitSet that iterates over the cleared bits of {@code set}, up to {@code maxIndex},
* in reverse order (highest to lowest index).
* @param set a BitSet
* @return an IterableBitSet over the set bits
*/
public static IterableBitSet getClearBitsReversed(BitSet set, int maxIndex)
{
return new IterableBitSet(set, maxIndex, true, true);
}
/**
* Simple test method.
*
@ -177,7 +318,8 @@ public class IterableBitSet implements Iterable<Integer>
}
test.clear();
for (@SuppressWarnings("unused") Integer index : getSetBits(test)) {
for (@SuppressWarnings("unused")
Integer index : getSetBits(test)) {
throw new RuntimeException("BitSet should be empty!");
}
}

Loading…
Cancel
Save