Index: src/java/org/apache/lucene/util/packed/PackedInts.java =================================================================== --- src/java/org/apache/lucene/util/packed/PackedInts.java (revision 997211) +++ src/java/org/apache/lucene/util/packed/PackedInts.java (working copy) @@ -76,8 +76,14 @@ int getBitsPerValue(); /** Returns number of values */ int size(); + /** Returns the current position of the enum */ + int docID(); + /** Skips to the position in the enum and returns its value. + * @return the value at the given position + * @throws IOException if reading the value throws an IOException*/ + long advance(int position) throws IOException; } - + /** * A packed integer array that can be modified. * @lucene.internal @@ -192,10 +198,9 @@ final int bitsPerValue = in.readVInt(); assert bitsPerValue > 0 && bitsPerValue <= 64: "bitsPerValue=" + bitsPerValue; final int valueCount = in.readVInt(); - return new PackedReaderIterator(bitsPerValue, valueCount, in); } - + /** * Create a packed integer array with the given amount of values initialized * to 0. the valueCount and the bitsPerValue cannot be changed after creation. Index: src/java/org/apache/lucene/util/packed/PackedReaderIterator.java =================================================================== --- src/java/org/apache/lucene/util/packed/PackedReaderIterator.java (revision 997211) +++ src/java/org/apache/lucene/util/packed/PackedReaderIterator.java (working copy) @@ -21,12 +21,13 @@ import java.io.IOException; -class PackedReaderIterator implements PackedInts.ReaderIterator { +final class PackedReaderIterator implements PackedInts.ReaderIterator { private long pending; private int pendingBitsLeft; private final IndexInput in; private final int bitsPerValue; private final int valueCount; + private int position = -1; // masks[n-1] masks for bottom n bits private final long[] masks; @@ -38,7 +39,6 @@ this.bitsPerValue = bitsPerValue; this.in = in; - masks = new long[bitsPerValue]; long v = 1; @@ -61,24 +61,51 @@ pending = in.readLong(); pendingBitsLeft = 64; } - - if (pendingBitsLeft >= bitsPerValue) { - // not split - final long result = (pending >> (pendingBitsLeft - bitsPerValue)) & masks[bitsPerValue-1]; + + final long result; + if (pendingBitsLeft >= bitsPerValue) { // not split + result = (pending >> (pendingBitsLeft - bitsPerValue)) & masks[bitsPerValue-1]; pendingBitsLeft -= bitsPerValue; - return result; - } else { - // split + } else { // split final int bits1 = bitsPerValue - pendingBitsLeft; final long result1 = (pending & masks[pendingBitsLeft-1]) << bits1; pending = in.readLong(); final long result2 = (pending >> (64 - bits1)) & masks[bits1-1]; pendingBitsLeft = 64 + pendingBitsLeft - bitsPerValue; - return result1 | result2; + result = result1 | result2; } + + ++position; + return result; } public void close() throws IOException { in.close(); } + + public int docID() { + return position; + } + + public long advance(final int ord) throws IOException{ + assert ord < valueCount : "ord must be less than valueCount"; + assert ord > position : "ord must be greater than the current position"; + final long bits = (long) bitsPerValue; + final int posToSkip = ord - 1 - position; + final long bitsToSkip = (bits * (long)posToSkip); + if(bitsToSkip < pendingBitsLeft ){ // enough bits left - no seek required + pendingBitsLeft -= bitsToSkip; + }else { + final long skip = bitsToSkip-pendingBitsLeft; + final long closestByte = (skip >> 6) << 3; + if(closestByte != 0) { // need to seek + final long filePointer = in.getFilePointer(); + in.seek(filePointer + closestByte); + } + pending = in.readLong(); + pendingBitsLeft = 64 - (int)(skip % 64); + } + position = ord-1; + return next(); + } } Index: src/test/org/apache/lucene/util/packed/TestPackedInts.java =================================================================== --- src/test/org/apache/lucene/util/packed/TestPackedInts.java (revision 997211) +++ src/test/org/apache/lucene/util/packed/TestPackedInts.java (working copy) @@ -70,7 +70,7 @@ w.finish(); final long fp = out.getFilePointer(); out.close(); - + {// test reader IndexInput in = d.openInput("out.bin"); PackedInts.Reader r = PackedInts.getReader(in); assertEquals(fp, in.getFilePointer()); @@ -80,16 +80,41 @@ + r.getClass().getSimpleName(), values[i], r.get(i)); } in.close(); - - in = d.openInput("out.bin"); - PackedInts.ReaderIterator r2 = PackedInts.getReaderIterator(in); + } + { // test reader iterator next + IndexInput in = d.openInput("out.bin"); + PackedInts.ReaderIterator r = PackedInts.getReaderIterator(in); for(int i=0;i