diff --git a/classpath/java/util/BitSet.java b/classpath/java/util/BitSet.java index 685f8f6520..2b6ada1203 100644 --- a/classpath/java/util/BitSet.java +++ b/classpath/java/util/BitSet.java @@ -80,6 +80,30 @@ public class BitSet implements Serializable, Cloneable { bits[i] ^= otherBits.bits[i]; } } + + public void flip(int index) { + flip(index, index+1); + } + + public void flip(int fromIndex, int toIndex) { + if (fromIndex > toIndex || fromIndex < 0 || toIndex < 0) { + throw new IndexOutOfBoundsException(); + } else if (fromIndex != toIndex) { + int basePartition = longPosition(fromIndex); + int lastPartition = longPosition(toIndex - 1); //range is [fromIndex, toIndex) + int numPartitionsToTraverse = lastPartition - basePartition + 1; + enlarge(lastPartition); + + int currentFirstIndex = fromIndex; + for (int i = 0; i < numPartitionsToTraverse; ++i) { + int currentToIndex = Math.min(toIndex, (basePartition + i + 1) * BITS_PER_LONG); + int currentRange = currentToIndex - currentFirstIndex; + long mask = (((1L << currentRange) - 1L) << (currentFirstIndex % BITS_PER_LONG)); + bits[i + basePartition] ^= mask; + currentFirstIndex = currentToIndex; + } + } + } private void enlarge(int newSize) { if (bits == null || bits.length < newSize) { diff --git a/test/BitsetTest.java b/test/BitsetTest.java index 70de6e3688..6ffc28fb67 100644 --- a/test/BitsetTest.java +++ b/test/BitsetTest.java @@ -47,6 +47,33 @@ public class BitsetTest { assertEquals("after 5, 6 is empty", 6, bits.nextClearBit(5)); assertEquals("after 100, 102 is empty", 102, bits.nextClearBit(100)); + testFlip(); + } + + private static void testFlip() { + /* simple case */ + BitSet bitset = new BitSet(); + bitset.set(0); + bitset.flip(0, 0); + assertTrue("Should not be flipped with 0 length range", bitset.get(0)); + bitset.flip(0, 1); + assertTrue("Should be false with range of one", !bitset.get(0)); + bitset.flip(0); + assertTrue("Should be true again", bitset.get(0)); + + /* need to grow */ + bitset.flip(1000); + assertTrue("1000 should be true", bitset.get(1000)); + assertTrue("1001 should be false", !bitset.get(1001)); + assertTrue("999 should be false", !bitset.get(999)); + + /* Range over 2 segments */ + bitset.flip(60, 70); + assertTrue("59 should be false", !bitset.get(59)); + for (int i=60; i < 70; ++i) { + assertTrue(i + " should be true", bitset.get(i)); + } + assertTrue("70 should be false", !bitset.get(70)); } static void assertTrue(String msg, boolean flag) {