diff --git a/classpath/java/util/BitSet.java b/classpath/java/util/BitSet.java index e45fbee355..6705c01cb7 100644 --- a/classpath/java/util/BitSet.java +++ b/classpath/java/util/BitSet.java @@ -32,6 +32,11 @@ public class BitSet implements Serializable, Cloneable { return 1L << (index % BITS_PER_LONG); } + private static long getTrueMask(int fromIndex, int toIndex) { + int currentRange = toIndex - fromIndex; + return (MASK >>> (BITS_PER_LONG - currentRange)) << (fromIndex % BITS_PER_LONG); + } + public BitSet(int bitLength) { if (bitLength % BITS_PER_LONG == 0) { enlarge(longPosition(bitLength)); @@ -80,30 +85,6 @@ 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 newPartition) { if (bits == null || bits.length < (newPartition + 1)) { @@ -115,13 +96,6 @@ public class BitSet implements Serializable, Cloneable { } } - public void clear(int index) { - int pos = longPosition(index); - if (pos < bits.length) { - bits[pos] &= (MASK ^ bitPosition(index)); - } - } - public boolean get(int index) { int pos = longPosition(index); if (pos < bits.length) { @@ -130,6 +104,23 @@ public class BitSet implements Serializable, Cloneable { return false; } + 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) { + MaskInfoIterator iter = new MaskInfoIterator(fromIndex, toIndex); + enlarge(iter.getLastPartition()); + while (iter.hasNext()) { + MaskInfo info = iter.next(); + bits[info.partitionIndex] ^= info.mask; + } + } + } + public void set(int index) { int pos = longPosition(index); enlarge(pos); @@ -137,14 +128,26 @@ public class BitSet implements Serializable, Cloneable { } public void set(int start, int end) { - for (int i = start; i < end; i++) { - set(i); + MaskInfoIterator iter = new MaskInfoIterator(start, end); + enlarge(iter.getLastPartition()); + while (iter.hasNext()) { + MaskInfo info = iter.next(); + bits[info.partitionIndex] |= info.mask; + } + } + + public void clear(int index) { + int pos = longPosition(index); + if (pos < bits.length) { + bits[pos] &= (MASK ^ bitPosition(index)); } } public void clear(int start, int end) { - for (int i = start; i < end; i++) { - clear(i); + MaskInfoIterator iter = new MaskInfoIterator(start, end); + while (iter.hasNext()) { + MaskInfo info = iter.next(); + bits[info.partitionIndex] &= (MASK ^ info.mask); } } @@ -214,4 +217,51 @@ public class BitSet implements Serializable, Cloneable { return numSetBits; } + + private static class MaskInfoIterator implements Iterator { + private int basePartition; + private int numPartitionsToTraverse; + private int currentPartitionOffset; + private int toIndex; + private int currentFirstIndex; + + public MaskInfoIterator(int fromIndex, int toIndex) { + this.basePartition = longPosition(fromIndex); + this.numPartitionsToTraverse = longPosition(toIndex - 1) - basePartition + 1; + this.currentPartitionOffset = 0; + this.toIndex = toIndex; + this.currentFirstIndex = fromIndex; + } + + public MaskInfo next() { + int currentToIndex = Math.min(toIndex, (basePartition + currentPartitionOffset + 1) * BITS_PER_LONG); + long mask = getTrueMask(currentFirstIndex, currentToIndex); + MaskInfo info = new MaskInfo(mask, basePartition + currentPartitionOffset); + currentFirstIndex = currentToIndex; + currentPartitionOffset++; + return info; + } + + public boolean hasNext() { + return currentPartitionOffset < numPartitionsToTraverse; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + public int getLastPartition() { + return basePartition + numPartitionsToTraverse - 1; + } + } + + private static class MaskInfo { + public long mask; + public int partitionIndex; + + public MaskInfo(long mask, int partitionIndex) { + this.mask = mask; + this.partitionIndex = partitionIndex; + } + } } diff --git a/classpath/java/util/EnumSet.java b/classpath/java/util/EnumSet.java index 49e8f7624f..aebcbda46a 100644 --- a/classpath/java/util/EnumSet.java +++ b/classpath/java/util/EnumSet.java @@ -53,7 +53,7 @@ public class EnumSet> extends AbstractSet { public static >EnumSet allOf(Class elementType) { EnumSet enumSet = createEmptyEnumSet(elementType); - addAllElementsToSet(Arrays.asList(elementType.getEnumConstants()), enumSet); + enumSet.bitset.set(0, elementType.getEnumConstants().length); return enumSet; } diff --git a/test/BitsetTest.java b/test/BitsetTest.java index b28ab939c2..6609eb60dd 100644 --- a/test/BitsetTest.java +++ b/test/BitsetTest.java @@ -48,6 +48,7 @@ public class BitsetTest { assertEquals("after 100, 102 is empty", 102, bits.nextClearBit(100)); testFlip(); + testClear(); BitSet expandingSet = new BitSet(); //should force us to have 3 partitions. @@ -79,6 +80,30 @@ public class BitsetTest { } assertTrue("70 should be false", !bitset.get(70)); } + + private static void testClear() { + BitSet bitset = new BitSet(); + bitset.set(0, 20); + assertCardinality(bitset, 20); + + bitset.clear(1); + assertTrue("bit 1 should be 0", !bitset.get(1)); + assertCardinality(bitset, 19); + + bitset.clear(0, 3); + assertTrue("bit 0 should be 0", !bitset.get(0)); + assertTrue("bit 1 should be 0", !bitset.get(1)); + assertTrue("bit 2 should be 0", !bitset.get(2)); + assertTrue("bit 3 should be 1", bitset.get(3)); + assertCardinality(bitset, 17); + + bitset = new BitSet(70); + bitset.flip(0, 65); + for (int i=0; i < 65; ++i) { + assertTrue("bit " + i + " should be set", bitset.get(i)); + } + assertTrue("bit 65 should not be set", !bitset.get(65)); + } static void assertTrue(String msg, boolean flag) { if (flag) {