Index: src/test/org/apache/lucene/util/TestBitVector.java =================================================================== --- src/test/org/apache/lucene/util/TestBitVector.java (revision 765030) +++ src/test/org/apache/lucene/util/TestBitVector.java (working copy) @@ -218,4 +218,60 @@ } return equal; } + + private static int[] subsetPattern = new int[] { 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1 }; + + /** + * Tests BitVector.subset() against the above pattern + */ + public void testSubset() { + doTestSubset(0, 0); + doTestSubset(0, 20); + doTestSubset(0, 7); + doTestSubset(0, 8); + doTestSubset(0, 9); + doTestSubset(0, 15); + doTestSubset(0, 16); + doTestSubset(0, 17); + doTestSubset(1, 7); + doTestSubset(1, 8); + doTestSubset(1, 9); + doTestSubset(1, 15); + doTestSubset(1, 16); + doTestSubset(1, 17); + doTestSubset(7, 14); + doTestSubset(7, 15); + doTestSubset(7, 16); + doTestSubset(8, 15); + } + + /** + * Compare a subset against the corresponding portion of the test pattern + */ + private void doTestSubset(int start, int end) { + BitVector full = createSubsetTestVector(); + BitVector subset = full.subset(start, end); + assertEquals(end - start, subset.size()); + int count = 0; + for (int i = start, j = 0; i < end; i++, j++) { + if (subsetPattern[i] == 1) { + count++; + assertTrue(subset.get(j)); + } else { + assertFalse(subset.get(j)); + } + } + assertEquals(count, subset.count()); + } + + private BitVector createSubsetTestVector() { + BitVector bv = new BitVector(subsetPattern.length); + for (int i = 0; i < subsetPattern.length; i++) { + if (subsetPattern[i] == 1) { + bv.set(i); + } + } + return bv; + } + } Index: src/java/org/apache/lucene/util/BitVector.java =================================================================== --- src/java/org/apache/lucene/util/BitVector.java (revision 765030) +++ src/java/org/apache/lucene/util/BitVector.java (working copy) @@ -238,5 +238,30 @@ n -= BYTE_COUNTS[bits[last] & 0xFF]; } } - + + /** + * Retrieve a subset of this BitVector. + * + * @param start + * starting index, inclusive + * @param end + * ending index, exclusive + * @return subset + */ + public BitVector subset(int start, int end) { + if (start < 0 || end > size() || end < start) + throw new IndexOutOfBoundsException(); + // Special case -- return empty vector is start == end + if (end == start) return new BitVector(0); + byte[] bits = new byte[((end - start - 1) >>> 3) + 1]; + int s = start >>> 3; + for (int i = 0; i < bits.length; i++) { + int cur = 0xFF & this.bits[i + s]; + int next = i + s + 1 >= this.bits.length ? 0 : 0xFF & this.bits[i + s + 1]; + bits[i] = (byte) ((cur >>> (start & 7)) | ((next << (8 - (start & 7))))); + } + int bitsToClear = (bits.length * 8 - (end - start)) % 8; + bits[bits.length - 1] &= ~(0xFF << (8 - bitsToClear)); + return new BitVector(bits, end - start); + } }