diff --git a/prism/src/common/IterableBitSet.java b/prism/src/common/IterableBitSet.java index 9d2ec873..9697d18c 100644 --- a/prism/src/common/IterableBitSet.java +++ b/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:

* for (Integer index : getSetBits(set)) { ... }
*/ -public class IterableBitSet implements Iterable +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 { 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 { - 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 { - 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 } @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 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 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 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 } test.clear(); - for (@SuppressWarnings("unused") Integer index : getSetBits(test)) { + for (@SuppressWarnings("unused") + Integer index : getSetBits(test)) { throw new RuntimeException("BitSet should be empty!"); } }