Index: lucene/core/src/resources/META-INF/services/org.apache.lucene.codecs.PostingsFormat =================================================================== --- lucene/core/src/resources/META-INF/services/org.apache.lucene.codecs.PostingsFormat (revision 1575909) +++ lucene/core/src/resources/META-INF/services/org.apache.lucene.codecs.PostingsFormat (working copy) @@ -15,3 +15,4 @@ org.apache.lucene.codecs.lucene40.Lucene40PostingsFormat org.apache.lucene.codecs.lucene41.Lucene41PostingsFormat +org.apache.lucene.codecs.nativemmap.NativeMMapPostingsFormat Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked2.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked2.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked2.java (working copy) @@ -39,6 +39,17 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations) { + for (int i = 0; i < iterations; ++i) { + final long block = unsafe.getLong(address); + address += 8; + for (int shift = 62; shift >= 0; shift -= 2) { + values[valuesOffset++] = (int) ((block >>> shift) & 3); + } + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { for (int j = 0; j < iterations; ++j) { final byte block = blocks[blocksOffset++]; Index: lucene/core/src/java/org/apache/lucene/util/packed/gen_BulkOperation.py =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/gen_BulkOperation.py (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/gen_BulkOperation.py (working copy) @@ -145,6 +145,11 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations) { + throw new UnsupportedOperationException(); + } + + @Override public void decode(long[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { throw new UnsupportedOperationException(); } @@ -205,6 +210,48 @@ f.write(" }\n") f.write(" }\n\n") + if bits == 32: + # Unsafe version: + f.write(" @Override\n") + f.write(" public void decode(long address, int blocksOffset, %s[] values, int valuesOffset, int iterations) {\n" %typ) + if bits < bpv: + f.write(" throw new UnsupportedOperationException();\n") + else: + f.write(" for (int i = 0; i < iterations; ++i) {\n") + mask = (1 << bpv) - 1 + + if is_power_of_two(bpv): + f.write(" final long block = unsafe.getLong(address);\n") + f.write(" address += 8;\n") + f.write(" for (int shift = %d; shift >= 0; shift -= %d) {\n" %(64 - bpv, bpv)) + f.write(" values[valuesOffset++] = %s(block >>> shift) & %d%s;\n" %(cast_start, mask, cast_end)) + f.write(" }\n") + else: + for i in xrange(0, values): + block_offset = i * bpv / 64 + bit_offset = (i * bpv) % 64 + if bit_offset == 0: + # start of block + f.write(" final long block%d = unsafe.getLong(address);\n" %block_offset); + f.write(" address += 8;\n") + f.write(" values[valuesOffset++] = %sblock%d >>> %d%s;\n" %(cast_start, block_offset, 64 - bpv, cast_end)) + elif bit_offset + bpv == 64: + # end of block + f.write(" values[valuesOffset++] = %sblock%d & %dL%s;\n" %(cast_start, block_offset, mask, cast_end)) + elif bit_offset + bpv < 64: + # middle of block + f.write(" values[valuesOffset++] = %s(block%d >>> %d) & %dL%s;\n" %(cast_start, block_offset, 64 - bit_offset - bpv, mask, cast_end)) + else: + # value spans across 2 blocks + mask1 = (1 << (64 - bit_offset)) -1 + shift1 = bit_offset + bpv - 64 + shift2 = 64 - shift1 + f.write(" final long block%d = unsafe.getLong(address);\n" % (block_offset+1)) + f.write(" address += 8;\n") + f.write(" values[valuesOffset++] = %s((block%d & %dL) << %d) | (block%d >>> %d)%s;\n" %(cast_start, block_offset, mask1, shift1, block_offset + 1, shift2, cast_end)) + f.write(" }\n") + f.write(" }\n\n") + byte_blocks, byte_values = block_value_count(bpv, 8) f.write(" @Override\n") @@ -278,7 +325,23 @@ * Efficient sequential read/write of packed integers. */\n''') + f.write('import java.lang.reflect.*;') + f.write('import sun.misc.Unsafe;\n') + f.write('abstract class BulkOperation implements PackedInts.Decoder, PackedInts.Encoder {\n') + f.write(''' + protected static final Unsafe unsafe; + + static { + try { + Field f = Unsafe.class.getDeclaredField("theUnsafe"); + f.setAccessible(true); + unsafe = (Unsafe) f.get(null); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + ''') f.write(' private static final BulkOperation[] packedBulkOps = new BulkOperation[] {\n') for bpv in xrange(1, 65): Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked21.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked21.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked21.java (working copy) @@ -120,6 +120,118 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations) { + for (int i = 0; i < iterations; ++i) { + final long block0 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (block0 >>> 43); + values[valuesOffset++] = (int) ((block0 >>> 22) & 2097151L); + values[valuesOffset++] = (int) ((block0 >>> 1) & 2097151L); + final long block1 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block0 & 1L) << 20) | (block1 >>> 44)); + values[valuesOffset++] = (int) ((block1 >>> 23) & 2097151L); + values[valuesOffset++] = (int) ((block1 >>> 2) & 2097151L); + final long block2 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block1 & 3L) << 19) | (block2 >>> 45)); + values[valuesOffset++] = (int) ((block2 >>> 24) & 2097151L); + values[valuesOffset++] = (int) ((block2 >>> 3) & 2097151L); + final long block3 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block2 & 7L) << 18) | (block3 >>> 46)); + values[valuesOffset++] = (int) ((block3 >>> 25) & 2097151L); + values[valuesOffset++] = (int) ((block3 >>> 4) & 2097151L); + final long block4 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block3 & 15L) << 17) | (block4 >>> 47)); + values[valuesOffset++] = (int) ((block4 >>> 26) & 2097151L); + values[valuesOffset++] = (int) ((block4 >>> 5) & 2097151L); + final long block5 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block4 & 31L) << 16) | (block5 >>> 48)); + values[valuesOffset++] = (int) ((block5 >>> 27) & 2097151L); + values[valuesOffset++] = (int) ((block5 >>> 6) & 2097151L); + final long block6 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block5 & 63L) << 15) | (block6 >>> 49)); + values[valuesOffset++] = (int) ((block6 >>> 28) & 2097151L); + values[valuesOffset++] = (int) ((block6 >>> 7) & 2097151L); + final long block7 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block6 & 127L) << 14) | (block7 >>> 50)); + values[valuesOffset++] = (int) ((block7 >>> 29) & 2097151L); + values[valuesOffset++] = (int) ((block7 >>> 8) & 2097151L); + final long block8 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block7 & 255L) << 13) | (block8 >>> 51)); + values[valuesOffset++] = (int) ((block8 >>> 30) & 2097151L); + values[valuesOffset++] = (int) ((block8 >>> 9) & 2097151L); + final long block9 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block8 & 511L) << 12) | (block9 >>> 52)); + values[valuesOffset++] = (int) ((block9 >>> 31) & 2097151L); + values[valuesOffset++] = (int) ((block9 >>> 10) & 2097151L); + final long block10 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block9 & 1023L) << 11) | (block10 >>> 53)); + values[valuesOffset++] = (int) ((block10 >>> 32) & 2097151L); + values[valuesOffset++] = (int) ((block10 >>> 11) & 2097151L); + final long block11 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block10 & 2047L) << 10) | (block11 >>> 54)); + values[valuesOffset++] = (int) ((block11 >>> 33) & 2097151L); + values[valuesOffset++] = (int) ((block11 >>> 12) & 2097151L); + final long block12 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block11 & 4095L) << 9) | (block12 >>> 55)); + values[valuesOffset++] = (int) ((block12 >>> 34) & 2097151L); + values[valuesOffset++] = (int) ((block12 >>> 13) & 2097151L); + final long block13 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block12 & 8191L) << 8) | (block13 >>> 56)); + values[valuesOffset++] = (int) ((block13 >>> 35) & 2097151L); + values[valuesOffset++] = (int) ((block13 >>> 14) & 2097151L); + final long block14 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block13 & 16383L) << 7) | (block14 >>> 57)); + values[valuesOffset++] = (int) ((block14 >>> 36) & 2097151L); + values[valuesOffset++] = (int) ((block14 >>> 15) & 2097151L); + final long block15 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block14 & 32767L) << 6) | (block15 >>> 58)); + values[valuesOffset++] = (int) ((block15 >>> 37) & 2097151L); + values[valuesOffset++] = (int) ((block15 >>> 16) & 2097151L); + final long block16 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block15 & 65535L) << 5) | (block16 >>> 59)); + values[valuesOffset++] = (int) ((block16 >>> 38) & 2097151L); + values[valuesOffset++] = (int) ((block16 >>> 17) & 2097151L); + final long block17 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block16 & 131071L) << 4) | (block17 >>> 60)); + values[valuesOffset++] = (int) ((block17 >>> 39) & 2097151L); + values[valuesOffset++] = (int) ((block17 >>> 18) & 2097151L); + final long block18 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block17 & 262143L) << 3) | (block18 >>> 61)); + values[valuesOffset++] = (int) ((block18 >>> 40) & 2097151L); + values[valuesOffset++] = (int) ((block18 >>> 19) & 2097151L); + final long block19 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block18 & 524287L) << 2) | (block19 >>> 62)); + values[valuesOffset++] = (int) ((block19 >>> 41) & 2097151L); + values[valuesOffset++] = (int) ((block19 >>> 20) & 2097151L); + final long block20 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block19 & 1048575L) << 1) | (block20 >>> 63)); + values[valuesOffset++] = (int) ((block20 >>> 42) & 2097151L); + values[valuesOffset++] = (int) ((block20 >>> 21) & 2097151L); + values[valuesOffset++] = (int) (block20 & 2097151L); + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { for (int i = 0; i < iterations; ++i) { final int byte0 = blocks[blocksOffset++] & 0xFF; Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked17.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked17.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked17.java (working copy) @@ -116,6 +116,110 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations) { + for (int i = 0; i < iterations; ++i) { + final long block0 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (block0 >>> 47); + values[valuesOffset++] = (int) ((block0 >>> 30) & 131071L); + values[valuesOffset++] = (int) ((block0 >>> 13) & 131071L); + final long block1 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block0 & 8191L) << 4) | (block1 >>> 60)); + values[valuesOffset++] = (int) ((block1 >>> 43) & 131071L); + values[valuesOffset++] = (int) ((block1 >>> 26) & 131071L); + values[valuesOffset++] = (int) ((block1 >>> 9) & 131071L); + final long block2 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block1 & 511L) << 8) | (block2 >>> 56)); + values[valuesOffset++] = (int) ((block2 >>> 39) & 131071L); + values[valuesOffset++] = (int) ((block2 >>> 22) & 131071L); + values[valuesOffset++] = (int) ((block2 >>> 5) & 131071L); + final long block3 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block2 & 31L) << 12) | (block3 >>> 52)); + values[valuesOffset++] = (int) ((block3 >>> 35) & 131071L); + values[valuesOffset++] = (int) ((block3 >>> 18) & 131071L); + values[valuesOffset++] = (int) ((block3 >>> 1) & 131071L); + final long block4 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block3 & 1L) << 16) | (block4 >>> 48)); + values[valuesOffset++] = (int) ((block4 >>> 31) & 131071L); + values[valuesOffset++] = (int) ((block4 >>> 14) & 131071L); + final long block5 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block4 & 16383L) << 3) | (block5 >>> 61)); + values[valuesOffset++] = (int) ((block5 >>> 44) & 131071L); + values[valuesOffset++] = (int) ((block5 >>> 27) & 131071L); + values[valuesOffset++] = (int) ((block5 >>> 10) & 131071L); + final long block6 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block5 & 1023L) << 7) | (block6 >>> 57)); + values[valuesOffset++] = (int) ((block6 >>> 40) & 131071L); + values[valuesOffset++] = (int) ((block6 >>> 23) & 131071L); + values[valuesOffset++] = (int) ((block6 >>> 6) & 131071L); + final long block7 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block6 & 63L) << 11) | (block7 >>> 53)); + values[valuesOffset++] = (int) ((block7 >>> 36) & 131071L); + values[valuesOffset++] = (int) ((block7 >>> 19) & 131071L); + values[valuesOffset++] = (int) ((block7 >>> 2) & 131071L); + final long block8 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block7 & 3L) << 15) | (block8 >>> 49)); + values[valuesOffset++] = (int) ((block8 >>> 32) & 131071L); + values[valuesOffset++] = (int) ((block8 >>> 15) & 131071L); + final long block9 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block8 & 32767L) << 2) | (block9 >>> 62)); + values[valuesOffset++] = (int) ((block9 >>> 45) & 131071L); + values[valuesOffset++] = (int) ((block9 >>> 28) & 131071L); + values[valuesOffset++] = (int) ((block9 >>> 11) & 131071L); + final long block10 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block9 & 2047L) << 6) | (block10 >>> 58)); + values[valuesOffset++] = (int) ((block10 >>> 41) & 131071L); + values[valuesOffset++] = (int) ((block10 >>> 24) & 131071L); + values[valuesOffset++] = (int) ((block10 >>> 7) & 131071L); + final long block11 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block10 & 127L) << 10) | (block11 >>> 54)); + values[valuesOffset++] = (int) ((block11 >>> 37) & 131071L); + values[valuesOffset++] = (int) ((block11 >>> 20) & 131071L); + values[valuesOffset++] = (int) ((block11 >>> 3) & 131071L); + final long block12 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block11 & 7L) << 14) | (block12 >>> 50)); + values[valuesOffset++] = (int) ((block12 >>> 33) & 131071L); + values[valuesOffset++] = (int) ((block12 >>> 16) & 131071L); + final long block13 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block12 & 65535L) << 1) | (block13 >>> 63)); + values[valuesOffset++] = (int) ((block13 >>> 46) & 131071L); + values[valuesOffset++] = (int) ((block13 >>> 29) & 131071L); + values[valuesOffset++] = (int) ((block13 >>> 12) & 131071L); + final long block14 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block13 & 4095L) << 5) | (block14 >>> 59)); + values[valuesOffset++] = (int) ((block14 >>> 42) & 131071L); + values[valuesOffset++] = (int) ((block14 >>> 25) & 131071L); + values[valuesOffset++] = (int) ((block14 >>> 8) & 131071L); + final long block15 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block14 & 255L) << 9) | (block15 >>> 55)); + values[valuesOffset++] = (int) ((block15 >>> 38) & 131071L); + values[valuesOffset++] = (int) ((block15 >>> 21) & 131071L); + values[valuesOffset++] = (int) ((block15 >>> 4) & 131071L); + final long block16 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block15 & 15L) << 13) | (block16 >>> 51)); + values[valuesOffset++] = (int) ((block16 >>> 34) & 131071L); + values[valuesOffset++] = (int) ((block16 >>> 17) & 131071L); + values[valuesOffset++] = (int) (block16 & 131071L); + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { for (int i = 0; i < iterations; ++i) { final int byte0 = blocks[blocksOffset++] & 0xFF; Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked7.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked7.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked7.java (working copy) @@ -106,6 +106,91 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations) { + // System.out.println("decode7 address=" + address + " iters=" + iterations); + for (int i = 0; i < iterations; ++i) { + final long block0 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (block0 >>> 57); + values[valuesOffset++] = (int) ((block0 >>> 50) & 127L); + values[valuesOffset++] = (int) ((block0 >>> 43) & 127L); + values[valuesOffset++] = (int) ((block0 >>> 36) & 127L); + values[valuesOffset++] = (int) ((block0 >>> 29) & 127L); + values[valuesOffset++] = (int) ((block0 >>> 22) & 127L); + values[valuesOffset++] = (int) ((block0 >>> 15) & 127L); + values[valuesOffset++] = (int) ((block0 >>> 8) & 127L); + values[valuesOffset++] = (int) ((block0 >>> 1) & 127L); + final long block1 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block0 & 1L) << 6) | (block1 >>> 58)); + values[valuesOffset++] = (int) ((block1 >>> 51) & 127L); + values[valuesOffset++] = (int) ((block1 >>> 44) & 127L); + values[valuesOffset++] = (int) ((block1 >>> 37) & 127L); + values[valuesOffset++] = (int) ((block1 >>> 30) & 127L); + values[valuesOffset++] = (int) ((block1 >>> 23) & 127L); + values[valuesOffset++] = (int) ((block1 >>> 16) & 127L); + values[valuesOffset++] = (int) ((block1 >>> 9) & 127L); + values[valuesOffset++] = (int) ((block1 >>> 2) & 127L); + final long block2 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block1 & 3L) << 5) | (block2 >>> 59)); + values[valuesOffset++] = (int) ((block2 >>> 52) & 127L); + values[valuesOffset++] = (int) ((block2 >>> 45) & 127L); + values[valuesOffset++] = (int) ((block2 >>> 38) & 127L); + values[valuesOffset++] = (int) ((block2 >>> 31) & 127L); + values[valuesOffset++] = (int) ((block2 >>> 24) & 127L); + values[valuesOffset++] = (int) ((block2 >>> 17) & 127L); + values[valuesOffset++] = (int) ((block2 >>> 10) & 127L); + values[valuesOffset++] = (int) ((block2 >>> 3) & 127L); + final long block3 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block2 & 7L) << 4) | (block3 >>> 60)); + values[valuesOffset++] = (int) ((block3 >>> 53) & 127L); + values[valuesOffset++] = (int) ((block3 >>> 46) & 127L); + values[valuesOffset++] = (int) ((block3 >>> 39) & 127L); + values[valuesOffset++] = (int) ((block3 >>> 32) & 127L); + values[valuesOffset++] = (int) ((block3 >>> 25) & 127L); + values[valuesOffset++] = (int) ((block3 >>> 18) & 127L); + values[valuesOffset++] = (int) ((block3 >>> 11) & 127L); + values[valuesOffset++] = (int) ((block3 >>> 4) & 127L); + final long block4 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block3 & 15L) << 3) | (block4 >>> 61)); + values[valuesOffset++] = (int) ((block4 >>> 54) & 127L); + values[valuesOffset++] = (int) ((block4 >>> 47) & 127L); + values[valuesOffset++] = (int) ((block4 >>> 40) & 127L); + values[valuesOffset++] = (int) ((block4 >>> 33) & 127L); + values[valuesOffset++] = (int) ((block4 >>> 26) & 127L); + values[valuesOffset++] = (int) ((block4 >>> 19) & 127L); + values[valuesOffset++] = (int) ((block4 >>> 12) & 127L); + values[valuesOffset++] = (int) ((block4 >>> 5) & 127L); + final long block5 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block4 & 31L) << 2) | (block5 >>> 62)); + values[valuesOffset++] = (int) ((block5 >>> 55) & 127L); + values[valuesOffset++] = (int) ((block5 >>> 48) & 127L); + values[valuesOffset++] = (int) ((block5 >>> 41) & 127L); + values[valuesOffset++] = (int) ((block5 >>> 34) & 127L); + values[valuesOffset++] = (int) ((block5 >>> 27) & 127L); + values[valuesOffset++] = (int) ((block5 >>> 20) & 127L); + values[valuesOffset++] = (int) ((block5 >>> 13) & 127L); + values[valuesOffset++] = (int) ((block5 >>> 6) & 127L); + final long block6 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block5 & 63L) << 1) | (block6 >>> 63)); + values[valuesOffset++] = (int) ((block6 >>> 56) & 127L); + values[valuesOffset++] = (int) ((block6 >>> 49) & 127L); + values[valuesOffset++] = (int) ((block6 >>> 42) & 127L); + values[valuesOffset++] = (int) ((block6 >>> 35) & 127L); + values[valuesOffset++] = (int) ((block6 >>> 28) & 127L); + values[valuesOffset++] = (int) ((block6 >>> 21) & 127L); + values[valuesOffset++] = (int) ((block6 >>> 14) & 127L); + values[valuesOffset++] = (int) ((block6 >>> 7) & 127L); + values[valuesOffset++] = (int) (block6 & 127L); + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { for (int i = 0; i < iterations; ++i) { final int byte0 = blocks[blocksOffset++] & 0xFF; Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked14.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked14.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked14.java (working copy) @@ -74,6 +74,58 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations) { + for (int i = 0; i < iterations; ++i) { + final long block0 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (block0 >>> 50); + values[valuesOffset++] = (int) ((block0 >>> 36) & 16383L); + values[valuesOffset++] = (int) ((block0 >>> 22) & 16383L); + values[valuesOffset++] = (int) ((block0 >>> 8) & 16383L); + final long block1 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block0 & 255L) << 6) | (block1 >>> 58)); + values[valuesOffset++] = (int) ((block1 >>> 44) & 16383L); + values[valuesOffset++] = (int) ((block1 >>> 30) & 16383L); + values[valuesOffset++] = (int) ((block1 >>> 16) & 16383L); + values[valuesOffset++] = (int) ((block1 >>> 2) & 16383L); + final long block2 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block1 & 3L) << 12) | (block2 >>> 52)); + values[valuesOffset++] = (int) ((block2 >>> 38) & 16383L); + values[valuesOffset++] = (int) ((block2 >>> 24) & 16383L); + values[valuesOffset++] = (int) ((block2 >>> 10) & 16383L); + final long block3 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block2 & 1023L) << 4) | (block3 >>> 60)); + values[valuesOffset++] = (int) ((block3 >>> 46) & 16383L); + values[valuesOffset++] = (int) ((block3 >>> 32) & 16383L); + values[valuesOffset++] = (int) ((block3 >>> 18) & 16383L); + values[valuesOffset++] = (int) ((block3 >>> 4) & 16383L); + final long block4 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block3 & 15L) << 10) | (block4 >>> 54)); + values[valuesOffset++] = (int) ((block4 >>> 40) & 16383L); + values[valuesOffset++] = (int) ((block4 >>> 26) & 16383L); + values[valuesOffset++] = (int) ((block4 >>> 12) & 16383L); + final long block5 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block4 & 4095L) << 2) | (block5 >>> 62)); + values[valuesOffset++] = (int) ((block5 >>> 48) & 16383L); + values[valuesOffset++] = (int) ((block5 >>> 34) & 16383L); + values[valuesOffset++] = (int) ((block5 >>> 20) & 16383L); + values[valuesOffset++] = (int) ((block5 >>> 6) & 16383L); + final long block6 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block5 & 63L) << 8) | (block6 >>> 56)); + values[valuesOffset++] = (int) ((block6 >>> 42) & 16383L); + values[valuesOffset++] = (int) ((block6 >>> 28) & 16383L); + values[valuesOffset++] = (int) ((block6 >>> 14) & 16383L); + values[valuesOffset++] = (int) (block6 & 16383L); + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { for (int i = 0; i < iterations; ++i) { final int byte0 = blocks[blocksOffset++] & 0xFF; Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked4.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked4.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked4.java (working copy) @@ -39,6 +39,17 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations) { + for (int i = 0; i < iterations; ++i) { + final long block = unsafe.getLong(address); + address += 8; + for (int shift = 60; shift >= 0; shift -= 4) { + values[valuesOffset++] = (int) ((block >>> shift) & 15); + } + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { for (int j = 0; j < iterations; ++j) { final byte block = blocks[blocksOffset++]; Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperation.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperation.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperation.java (working copy) @@ -23,8 +23,21 @@ /** * Efficient sequential read/write of packed integers. */ +import java.lang.reflect.*;import sun.misc.Unsafe; abstract class BulkOperation implements PackedInts.Decoder, PackedInts.Encoder { - private static final BulkOperation[] packedBulkOps = new BulkOperation[] { + + protected static final Unsafe unsafe; + + static { + try { + Field f = Unsafe.class.getDeclaredField("theUnsafe"); + f.setAccessible(true); + unsafe = (Unsafe) f.get(null); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + private static final BulkOperation[] packedBulkOps = new BulkOperation[] { new BulkOperationPacked1(), new BulkOperationPacked2(), new BulkOperationPacked3(), Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked11.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked11.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked11.java (working copy) @@ -110,6 +110,98 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations) { + for (int i = 0; i < iterations; ++i) { + final long block0 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (block0 >>> 53); + values[valuesOffset++] = (int) ((block0 >>> 42) & 2047L); + values[valuesOffset++] = (int) ((block0 >>> 31) & 2047L); + values[valuesOffset++] = (int) ((block0 >>> 20) & 2047L); + values[valuesOffset++] = (int) ((block0 >>> 9) & 2047L); + final long block1 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block0 & 511L) << 2) | (block1 >>> 62)); + values[valuesOffset++] = (int) ((block1 >>> 51) & 2047L); + values[valuesOffset++] = (int) ((block1 >>> 40) & 2047L); + values[valuesOffset++] = (int) ((block1 >>> 29) & 2047L); + values[valuesOffset++] = (int) ((block1 >>> 18) & 2047L); + values[valuesOffset++] = (int) ((block1 >>> 7) & 2047L); + final long block2 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block1 & 127L) << 4) | (block2 >>> 60)); + values[valuesOffset++] = (int) ((block2 >>> 49) & 2047L); + values[valuesOffset++] = (int) ((block2 >>> 38) & 2047L); + values[valuesOffset++] = (int) ((block2 >>> 27) & 2047L); + values[valuesOffset++] = (int) ((block2 >>> 16) & 2047L); + values[valuesOffset++] = (int) ((block2 >>> 5) & 2047L); + final long block3 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block2 & 31L) << 6) | (block3 >>> 58)); + values[valuesOffset++] = (int) ((block3 >>> 47) & 2047L); + values[valuesOffset++] = (int) ((block3 >>> 36) & 2047L); + values[valuesOffset++] = (int) ((block3 >>> 25) & 2047L); + values[valuesOffset++] = (int) ((block3 >>> 14) & 2047L); + values[valuesOffset++] = (int) ((block3 >>> 3) & 2047L); + final long block4 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block3 & 7L) << 8) | (block4 >>> 56)); + values[valuesOffset++] = (int) ((block4 >>> 45) & 2047L); + values[valuesOffset++] = (int) ((block4 >>> 34) & 2047L); + values[valuesOffset++] = (int) ((block4 >>> 23) & 2047L); + values[valuesOffset++] = (int) ((block4 >>> 12) & 2047L); + values[valuesOffset++] = (int) ((block4 >>> 1) & 2047L); + final long block5 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block4 & 1L) << 10) | (block5 >>> 54)); + values[valuesOffset++] = (int) ((block5 >>> 43) & 2047L); + values[valuesOffset++] = (int) ((block5 >>> 32) & 2047L); + values[valuesOffset++] = (int) ((block5 >>> 21) & 2047L); + values[valuesOffset++] = (int) ((block5 >>> 10) & 2047L); + final long block6 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block5 & 1023L) << 1) | (block6 >>> 63)); + values[valuesOffset++] = (int) ((block6 >>> 52) & 2047L); + values[valuesOffset++] = (int) ((block6 >>> 41) & 2047L); + values[valuesOffset++] = (int) ((block6 >>> 30) & 2047L); + values[valuesOffset++] = (int) ((block6 >>> 19) & 2047L); + values[valuesOffset++] = (int) ((block6 >>> 8) & 2047L); + final long block7 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block6 & 255L) << 3) | (block7 >>> 61)); + values[valuesOffset++] = (int) ((block7 >>> 50) & 2047L); + values[valuesOffset++] = (int) ((block7 >>> 39) & 2047L); + values[valuesOffset++] = (int) ((block7 >>> 28) & 2047L); + values[valuesOffset++] = (int) ((block7 >>> 17) & 2047L); + values[valuesOffset++] = (int) ((block7 >>> 6) & 2047L); + final long block8 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block7 & 63L) << 5) | (block8 >>> 59)); + values[valuesOffset++] = (int) ((block8 >>> 48) & 2047L); + values[valuesOffset++] = (int) ((block8 >>> 37) & 2047L); + values[valuesOffset++] = (int) ((block8 >>> 26) & 2047L); + values[valuesOffset++] = (int) ((block8 >>> 15) & 2047L); + values[valuesOffset++] = (int) ((block8 >>> 4) & 2047L); + final long block9 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block8 & 15L) << 7) | (block9 >>> 57)); + values[valuesOffset++] = (int) ((block9 >>> 46) & 2047L); + values[valuesOffset++] = (int) ((block9 >>> 35) & 2047L); + values[valuesOffset++] = (int) ((block9 >>> 24) & 2047L); + values[valuesOffset++] = (int) ((block9 >>> 13) & 2047L); + values[valuesOffset++] = (int) ((block9 >>> 2) & 2047L); + final long block10 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block9 & 3L) << 9) | (block10 >>> 55)); + values[valuesOffset++] = (int) ((block10 >>> 44) & 2047L); + values[valuesOffset++] = (int) ((block10 >>> 33) & 2047L); + values[valuesOffset++] = (int) ((block10 >>> 22) & 2047L); + values[valuesOffset++] = (int) ((block10 >>> 11) & 2047L); + values[valuesOffset++] = (int) (block10 & 2047L); + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { for (int i = 0; i < iterations; ++i) { final int byte0 = blocks[blocksOffset++] & 0xFF; Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked23.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked23.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked23.java (working copy) @@ -122,6 +122,122 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations) { + for (int i = 0; i < iterations; ++i) { + final long block0 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (block0 >>> 41); + values[valuesOffset++] = (int) ((block0 >>> 18) & 8388607L); + final long block1 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block0 & 262143L) << 5) | (block1 >>> 59)); + values[valuesOffset++] = (int) ((block1 >>> 36) & 8388607L); + values[valuesOffset++] = (int) ((block1 >>> 13) & 8388607L); + final long block2 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block1 & 8191L) << 10) | (block2 >>> 54)); + values[valuesOffset++] = (int) ((block2 >>> 31) & 8388607L); + values[valuesOffset++] = (int) ((block2 >>> 8) & 8388607L); + final long block3 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block2 & 255L) << 15) | (block3 >>> 49)); + values[valuesOffset++] = (int) ((block3 >>> 26) & 8388607L); + values[valuesOffset++] = (int) ((block3 >>> 3) & 8388607L); + final long block4 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block3 & 7L) << 20) | (block4 >>> 44)); + values[valuesOffset++] = (int) ((block4 >>> 21) & 8388607L); + final long block5 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block4 & 2097151L) << 2) | (block5 >>> 62)); + values[valuesOffset++] = (int) ((block5 >>> 39) & 8388607L); + values[valuesOffset++] = (int) ((block5 >>> 16) & 8388607L); + final long block6 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block5 & 65535L) << 7) | (block6 >>> 57)); + values[valuesOffset++] = (int) ((block6 >>> 34) & 8388607L); + values[valuesOffset++] = (int) ((block6 >>> 11) & 8388607L); + final long block7 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block6 & 2047L) << 12) | (block7 >>> 52)); + values[valuesOffset++] = (int) ((block7 >>> 29) & 8388607L); + values[valuesOffset++] = (int) ((block7 >>> 6) & 8388607L); + final long block8 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block7 & 63L) << 17) | (block8 >>> 47)); + values[valuesOffset++] = (int) ((block8 >>> 24) & 8388607L); + values[valuesOffset++] = (int) ((block8 >>> 1) & 8388607L); + final long block9 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block8 & 1L) << 22) | (block9 >>> 42)); + values[valuesOffset++] = (int) ((block9 >>> 19) & 8388607L); + final long block10 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block9 & 524287L) << 4) | (block10 >>> 60)); + values[valuesOffset++] = (int) ((block10 >>> 37) & 8388607L); + values[valuesOffset++] = (int) ((block10 >>> 14) & 8388607L); + final long block11 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block10 & 16383L) << 9) | (block11 >>> 55)); + values[valuesOffset++] = (int) ((block11 >>> 32) & 8388607L); + values[valuesOffset++] = (int) ((block11 >>> 9) & 8388607L); + final long block12 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block11 & 511L) << 14) | (block12 >>> 50)); + values[valuesOffset++] = (int) ((block12 >>> 27) & 8388607L); + values[valuesOffset++] = (int) ((block12 >>> 4) & 8388607L); + final long block13 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block12 & 15L) << 19) | (block13 >>> 45)); + values[valuesOffset++] = (int) ((block13 >>> 22) & 8388607L); + final long block14 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block13 & 4194303L) << 1) | (block14 >>> 63)); + values[valuesOffset++] = (int) ((block14 >>> 40) & 8388607L); + values[valuesOffset++] = (int) ((block14 >>> 17) & 8388607L); + final long block15 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block14 & 131071L) << 6) | (block15 >>> 58)); + values[valuesOffset++] = (int) ((block15 >>> 35) & 8388607L); + values[valuesOffset++] = (int) ((block15 >>> 12) & 8388607L); + final long block16 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block15 & 4095L) << 11) | (block16 >>> 53)); + values[valuesOffset++] = (int) ((block16 >>> 30) & 8388607L); + values[valuesOffset++] = (int) ((block16 >>> 7) & 8388607L); + final long block17 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block16 & 127L) << 16) | (block17 >>> 48)); + values[valuesOffset++] = (int) ((block17 >>> 25) & 8388607L); + values[valuesOffset++] = (int) ((block17 >>> 2) & 8388607L); + final long block18 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block17 & 3L) << 21) | (block18 >>> 43)); + values[valuesOffset++] = (int) ((block18 >>> 20) & 8388607L); + final long block19 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block18 & 1048575L) << 3) | (block19 >>> 61)); + values[valuesOffset++] = (int) ((block19 >>> 38) & 8388607L); + values[valuesOffset++] = (int) ((block19 >>> 15) & 8388607L); + final long block20 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block19 & 32767L) << 8) | (block20 >>> 56)); + values[valuesOffset++] = (int) ((block20 >>> 33) & 8388607L); + values[valuesOffset++] = (int) ((block20 >>> 10) & 8388607L); + final long block21 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block20 & 1023L) << 13) | (block21 >>> 51)); + values[valuesOffset++] = (int) ((block21 >>> 28) & 8388607L); + values[valuesOffset++] = (int) ((block21 >>> 5) & 8388607L); + final long block22 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block21 & 31L) << 18) | (block22 >>> 46)); + values[valuesOffset++] = (int) ((block22 >>> 23) & 8388607L); + values[valuesOffset++] = (int) (block22 & 8388607L); + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { for (int i = 0; i < iterations; ++i) { final int byte0 = blocks[blocksOffset++] & 0xFF; Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked19.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked19.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked19.java (working copy) @@ -118,6 +118,114 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations) { + for (int i = 0; i < iterations; ++i) { + final long block0 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (block0 >>> 45); + values[valuesOffset++] = (int) ((block0 >>> 26) & 524287L); + values[valuesOffset++] = (int) ((block0 >>> 7) & 524287L); + final long block1 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block0 & 127L) << 12) | (block1 >>> 52)); + values[valuesOffset++] = (int) ((block1 >>> 33) & 524287L); + values[valuesOffset++] = (int) ((block1 >>> 14) & 524287L); + final long block2 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block1 & 16383L) << 5) | (block2 >>> 59)); + values[valuesOffset++] = (int) ((block2 >>> 40) & 524287L); + values[valuesOffset++] = (int) ((block2 >>> 21) & 524287L); + values[valuesOffset++] = (int) ((block2 >>> 2) & 524287L); + final long block3 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block2 & 3L) << 17) | (block3 >>> 47)); + values[valuesOffset++] = (int) ((block3 >>> 28) & 524287L); + values[valuesOffset++] = (int) ((block3 >>> 9) & 524287L); + final long block4 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block3 & 511L) << 10) | (block4 >>> 54)); + values[valuesOffset++] = (int) ((block4 >>> 35) & 524287L); + values[valuesOffset++] = (int) ((block4 >>> 16) & 524287L); + final long block5 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block4 & 65535L) << 3) | (block5 >>> 61)); + values[valuesOffset++] = (int) ((block5 >>> 42) & 524287L); + values[valuesOffset++] = (int) ((block5 >>> 23) & 524287L); + values[valuesOffset++] = (int) ((block5 >>> 4) & 524287L); + final long block6 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block5 & 15L) << 15) | (block6 >>> 49)); + values[valuesOffset++] = (int) ((block6 >>> 30) & 524287L); + values[valuesOffset++] = (int) ((block6 >>> 11) & 524287L); + final long block7 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block6 & 2047L) << 8) | (block7 >>> 56)); + values[valuesOffset++] = (int) ((block7 >>> 37) & 524287L); + values[valuesOffset++] = (int) ((block7 >>> 18) & 524287L); + final long block8 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block7 & 262143L) << 1) | (block8 >>> 63)); + values[valuesOffset++] = (int) ((block8 >>> 44) & 524287L); + values[valuesOffset++] = (int) ((block8 >>> 25) & 524287L); + values[valuesOffset++] = (int) ((block8 >>> 6) & 524287L); + final long block9 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block8 & 63L) << 13) | (block9 >>> 51)); + values[valuesOffset++] = (int) ((block9 >>> 32) & 524287L); + values[valuesOffset++] = (int) ((block9 >>> 13) & 524287L); + final long block10 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block9 & 8191L) << 6) | (block10 >>> 58)); + values[valuesOffset++] = (int) ((block10 >>> 39) & 524287L); + values[valuesOffset++] = (int) ((block10 >>> 20) & 524287L); + values[valuesOffset++] = (int) ((block10 >>> 1) & 524287L); + final long block11 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block10 & 1L) << 18) | (block11 >>> 46)); + values[valuesOffset++] = (int) ((block11 >>> 27) & 524287L); + values[valuesOffset++] = (int) ((block11 >>> 8) & 524287L); + final long block12 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block11 & 255L) << 11) | (block12 >>> 53)); + values[valuesOffset++] = (int) ((block12 >>> 34) & 524287L); + values[valuesOffset++] = (int) ((block12 >>> 15) & 524287L); + final long block13 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block12 & 32767L) << 4) | (block13 >>> 60)); + values[valuesOffset++] = (int) ((block13 >>> 41) & 524287L); + values[valuesOffset++] = (int) ((block13 >>> 22) & 524287L); + values[valuesOffset++] = (int) ((block13 >>> 3) & 524287L); + final long block14 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block13 & 7L) << 16) | (block14 >>> 48)); + values[valuesOffset++] = (int) ((block14 >>> 29) & 524287L); + values[valuesOffset++] = (int) ((block14 >>> 10) & 524287L); + final long block15 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block14 & 1023L) << 9) | (block15 >>> 55)); + values[valuesOffset++] = (int) ((block15 >>> 36) & 524287L); + values[valuesOffset++] = (int) ((block15 >>> 17) & 524287L); + final long block16 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block15 & 131071L) << 2) | (block16 >>> 62)); + values[valuesOffset++] = (int) ((block16 >>> 43) & 524287L); + values[valuesOffset++] = (int) ((block16 >>> 24) & 524287L); + values[valuesOffset++] = (int) ((block16 >>> 5) & 524287L); + final long block17 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block16 & 31L) << 14) | (block17 >>> 50)); + values[valuesOffset++] = (int) ((block17 >>> 31) & 524287L); + values[valuesOffset++] = (int) ((block17 >>> 12) & 524287L); + final long block18 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block17 & 4095L) << 7) | (block18 >>> 57)); + values[valuesOffset++] = (int) ((block18 >>> 38) & 524287L); + values[valuesOffset++] = (int) ((block18 >>> 19) & 524287L); + values[valuesOffset++] = (int) (block18 & 524287L); + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { for (int i = 0; i < iterations; ++i) { final int byte0 = blocks[blocksOffset++] & 0xFF; Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked1.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked1.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked1.java (working copy) @@ -39,6 +39,17 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations) { + for (int i = 0; i < iterations; ++i) { + final long block = unsafe.getLong(address); + address += 8; + for (int shift = 63; shift >= 0; shift -= 1) { + values[valuesOffset++] = (int) ((block >>> shift) & 1); + } + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { for (int j = 0; j < iterations; ++j) { final byte block = blocks[blocksOffset++]; Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked9.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked9.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked9.java (working copy) @@ -108,6 +108,94 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations) { + for (int i = 0; i < iterations; ++i) { + final long block0 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (block0 >>> 55); + values[valuesOffset++] = (int) ((block0 >>> 46) & 511L); + values[valuesOffset++] = (int) ((block0 >>> 37) & 511L); + values[valuesOffset++] = (int) ((block0 >>> 28) & 511L); + values[valuesOffset++] = (int) ((block0 >>> 19) & 511L); + values[valuesOffset++] = (int) ((block0 >>> 10) & 511L); + values[valuesOffset++] = (int) ((block0 >>> 1) & 511L); + final long block1 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block0 & 1L) << 8) | (block1 >>> 56)); + values[valuesOffset++] = (int) ((block1 >>> 47) & 511L); + values[valuesOffset++] = (int) ((block1 >>> 38) & 511L); + values[valuesOffset++] = (int) ((block1 >>> 29) & 511L); + values[valuesOffset++] = (int) ((block1 >>> 20) & 511L); + values[valuesOffset++] = (int) ((block1 >>> 11) & 511L); + values[valuesOffset++] = (int) ((block1 >>> 2) & 511L); + final long block2 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block1 & 3L) << 7) | (block2 >>> 57)); + values[valuesOffset++] = (int) ((block2 >>> 48) & 511L); + values[valuesOffset++] = (int) ((block2 >>> 39) & 511L); + values[valuesOffset++] = (int) ((block2 >>> 30) & 511L); + values[valuesOffset++] = (int) ((block2 >>> 21) & 511L); + values[valuesOffset++] = (int) ((block2 >>> 12) & 511L); + values[valuesOffset++] = (int) ((block2 >>> 3) & 511L); + final long block3 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block2 & 7L) << 6) | (block3 >>> 58)); + values[valuesOffset++] = (int) ((block3 >>> 49) & 511L); + values[valuesOffset++] = (int) ((block3 >>> 40) & 511L); + values[valuesOffset++] = (int) ((block3 >>> 31) & 511L); + values[valuesOffset++] = (int) ((block3 >>> 22) & 511L); + values[valuesOffset++] = (int) ((block3 >>> 13) & 511L); + values[valuesOffset++] = (int) ((block3 >>> 4) & 511L); + final long block4 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block3 & 15L) << 5) | (block4 >>> 59)); + values[valuesOffset++] = (int) ((block4 >>> 50) & 511L); + values[valuesOffset++] = (int) ((block4 >>> 41) & 511L); + values[valuesOffset++] = (int) ((block4 >>> 32) & 511L); + values[valuesOffset++] = (int) ((block4 >>> 23) & 511L); + values[valuesOffset++] = (int) ((block4 >>> 14) & 511L); + values[valuesOffset++] = (int) ((block4 >>> 5) & 511L); + final long block5 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block4 & 31L) << 4) | (block5 >>> 60)); + values[valuesOffset++] = (int) ((block5 >>> 51) & 511L); + values[valuesOffset++] = (int) ((block5 >>> 42) & 511L); + values[valuesOffset++] = (int) ((block5 >>> 33) & 511L); + values[valuesOffset++] = (int) ((block5 >>> 24) & 511L); + values[valuesOffset++] = (int) ((block5 >>> 15) & 511L); + values[valuesOffset++] = (int) ((block5 >>> 6) & 511L); + final long block6 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block5 & 63L) << 3) | (block6 >>> 61)); + values[valuesOffset++] = (int) ((block6 >>> 52) & 511L); + values[valuesOffset++] = (int) ((block6 >>> 43) & 511L); + values[valuesOffset++] = (int) ((block6 >>> 34) & 511L); + values[valuesOffset++] = (int) ((block6 >>> 25) & 511L); + values[valuesOffset++] = (int) ((block6 >>> 16) & 511L); + values[valuesOffset++] = (int) ((block6 >>> 7) & 511L); + final long block7 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block6 & 127L) << 2) | (block7 >>> 62)); + values[valuesOffset++] = (int) ((block7 >>> 53) & 511L); + values[valuesOffset++] = (int) ((block7 >>> 44) & 511L); + values[valuesOffset++] = (int) ((block7 >>> 35) & 511L); + values[valuesOffset++] = (int) ((block7 >>> 26) & 511L); + values[valuesOffset++] = (int) ((block7 >>> 17) & 511L); + values[valuesOffset++] = (int) ((block7 >>> 8) & 511L); + final long block8 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block7 & 255L) << 1) | (block8 >>> 63)); + values[valuesOffset++] = (int) ((block8 >>> 54) & 511L); + values[valuesOffset++] = (int) ((block8 >>> 45) & 511L); + values[valuesOffset++] = (int) ((block8 >>> 36) & 511L); + values[valuesOffset++] = (int) ((block8 >>> 27) & 511L); + values[valuesOffset++] = (int) ((block8 >>> 18) & 511L); + values[valuesOffset++] = (int) ((block8 >>> 9) & 511L); + values[valuesOffset++] = (int) (block8 & 511L); + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { for (int i = 0; i < iterations; ++i) { final int byte0 = blocks[blocksOffset++] & 0xFF; Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked20.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked20.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked20.java (working copy) @@ -56,6 +56,38 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations) { + for (int i = 0; i < iterations; ++i) { + final long block0 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (block0 >>> 44); + values[valuesOffset++] = (int) ((block0 >>> 24) & 1048575L); + values[valuesOffset++] = (int) ((block0 >>> 4) & 1048575L); + final long block1 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block0 & 15L) << 16) | (block1 >>> 48)); + values[valuesOffset++] = (int) ((block1 >>> 28) & 1048575L); + values[valuesOffset++] = (int) ((block1 >>> 8) & 1048575L); + final long block2 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block1 & 255L) << 12) | (block2 >>> 52)); + values[valuesOffset++] = (int) ((block2 >>> 32) & 1048575L); + values[valuesOffset++] = (int) ((block2 >>> 12) & 1048575L); + final long block3 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block2 & 4095L) << 8) | (block3 >>> 56)); + values[valuesOffset++] = (int) ((block3 >>> 36) & 1048575L); + values[valuesOffset++] = (int) ((block3 >>> 16) & 1048575L); + final long block4 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block3 & 65535L) << 4) | (block4 >>> 60)); + values[valuesOffset++] = (int) ((block4 >>> 40) & 1048575L); + values[valuesOffset++] = (int) ((block4 >>> 20) & 1048575L); + values[valuesOffset++] = (int) (block4 & 1048575L); + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { for (int i = 0; i < iterations; ++i) { final int byte0 = blocks[blocksOffset++] & 0xFF; Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked16.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked16.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked16.java (working copy) @@ -39,6 +39,17 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations) { + for (int i = 0; i < iterations; ++i) { + final long block = unsafe.getLong(address); + address += 8; + for (int shift = 48; shift >= 0; shift -= 16) { + values[valuesOffset++] = (int) ((block >>> shift) & 65535); + } + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { for (int j = 0; j < iterations; ++j) { values[valuesOffset++] = ((blocks[blocksOffset++] & 0xFF) << 8) | (blocks[blocksOffset++] & 0xFF); Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked6.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked6.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked6.java (working copy) @@ -70,6 +70,51 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations) { + //System.out.println("decode6 address=" + address + " iters=" + iterations); + for (int i = 0; i < iterations; ++i) { + final long block0 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (block0 >>> 58); + values[valuesOffset++] = (int) ((block0 >>> 52) & 63L); + values[valuesOffset++] = (int) ((block0 >>> 46) & 63L); + values[valuesOffset++] = (int) ((block0 >>> 40) & 63L); + values[valuesOffset++] = (int) ((block0 >>> 34) & 63L); + values[valuesOffset++] = (int) ((block0 >>> 28) & 63L); + values[valuesOffset++] = (int) ((block0 >>> 22) & 63L); + values[valuesOffset++] = (int) ((block0 >>> 16) & 63L); + values[valuesOffset++] = (int) ((block0 >>> 10) & 63L); + values[valuesOffset++] = (int) ((block0 >>> 4) & 63L); + final long block1 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block0 & 15L) << 2) | (block1 >>> 62)); + values[valuesOffset++] = (int) ((block1 >>> 56) & 63L); + values[valuesOffset++] = (int) ((block1 >>> 50) & 63L); + values[valuesOffset++] = (int) ((block1 >>> 44) & 63L); + values[valuesOffset++] = (int) ((block1 >>> 38) & 63L); + values[valuesOffset++] = (int) ((block1 >>> 32) & 63L); + values[valuesOffset++] = (int) ((block1 >>> 26) & 63L); + values[valuesOffset++] = (int) ((block1 >>> 20) & 63L); + values[valuesOffset++] = (int) ((block1 >>> 14) & 63L); + values[valuesOffset++] = (int) ((block1 >>> 8) & 63L); + values[valuesOffset++] = (int) ((block1 >>> 2) & 63L); + final long block2 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block1 & 3L) << 4) | (block2 >>> 60)); + values[valuesOffset++] = (int) ((block2 >>> 54) & 63L); + values[valuesOffset++] = (int) ((block2 >>> 48) & 63L); + values[valuesOffset++] = (int) ((block2 >>> 42) & 63L); + values[valuesOffset++] = (int) ((block2 >>> 36) & 63L); + values[valuesOffset++] = (int) ((block2 >>> 30) & 63L); + values[valuesOffset++] = (int) ((block2 >>> 24) & 63L); + values[valuesOffset++] = (int) ((block2 >>> 18) & 63L); + values[valuesOffset++] = (int) ((block2 >>> 12) & 63L); + values[valuesOffset++] = (int) ((block2 >>> 6) & 63L); + values[valuesOffset++] = (int) (block2 & 63L); + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { for (int i = 0; i < iterations; ++i) { final int byte0 = blocks[blocksOffset++] & 0xFF; Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked.java (working copy) @@ -142,6 +142,31 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, + int valuesOffset, int iterations) { + if (bitsPerValue > 32) { + throw new UnsupportedOperationException("Cannot decode " + bitsPerValue + "-bits values into an int[]"); + } + int bitsLeft = 64; + long encoded = unsafe.getLong(address); + address += 8; + for (int i = 0; i < longValueCount * iterations; ++i) { + bitsLeft -= bitsPerValue; + if (bitsLeft < 0) { + long encodedNext = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) + (((encoded & ((1L << (bitsPerValue + bitsLeft)) - 1)) << -bitsLeft) + | (encodedNext >>> (64 + bitsLeft))); + bitsLeft += 64; + encoded = encodedNext; + } else { + values[valuesOffset++] = (int) ((encoded >>> bitsLeft) & mask); + } + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { int nextValue = 0; Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked13.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked13.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked13.java (working copy) @@ -112,6 +112,102 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations) { + for (int i = 0; i < iterations; ++i) { + final long block0 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (block0 >>> 51); + values[valuesOffset++] = (int) ((block0 >>> 38) & 8191L); + values[valuesOffset++] = (int) ((block0 >>> 25) & 8191L); + values[valuesOffset++] = (int) ((block0 >>> 12) & 8191L); + final long block1 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block0 & 4095L) << 1) | (block1 >>> 63)); + values[valuesOffset++] = (int) ((block1 >>> 50) & 8191L); + values[valuesOffset++] = (int) ((block1 >>> 37) & 8191L); + values[valuesOffset++] = (int) ((block1 >>> 24) & 8191L); + values[valuesOffset++] = (int) ((block1 >>> 11) & 8191L); + final long block2 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block1 & 2047L) << 2) | (block2 >>> 62)); + values[valuesOffset++] = (int) ((block2 >>> 49) & 8191L); + values[valuesOffset++] = (int) ((block2 >>> 36) & 8191L); + values[valuesOffset++] = (int) ((block2 >>> 23) & 8191L); + values[valuesOffset++] = (int) ((block2 >>> 10) & 8191L); + final long block3 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block2 & 1023L) << 3) | (block3 >>> 61)); + values[valuesOffset++] = (int) ((block3 >>> 48) & 8191L); + values[valuesOffset++] = (int) ((block3 >>> 35) & 8191L); + values[valuesOffset++] = (int) ((block3 >>> 22) & 8191L); + values[valuesOffset++] = (int) ((block3 >>> 9) & 8191L); + final long block4 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block3 & 511L) << 4) | (block4 >>> 60)); + values[valuesOffset++] = (int) ((block4 >>> 47) & 8191L); + values[valuesOffset++] = (int) ((block4 >>> 34) & 8191L); + values[valuesOffset++] = (int) ((block4 >>> 21) & 8191L); + values[valuesOffset++] = (int) ((block4 >>> 8) & 8191L); + final long block5 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block4 & 255L) << 5) | (block5 >>> 59)); + values[valuesOffset++] = (int) ((block5 >>> 46) & 8191L); + values[valuesOffset++] = (int) ((block5 >>> 33) & 8191L); + values[valuesOffset++] = (int) ((block5 >>> 20) & 8191L); + values[valuesOffset++] = (int) ((block5 >>> 7) & 8191L); + final long block6 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block5 & 127L) << 6) | (block6 >>> 58)); + values[valuesOffset++] = (int) ((block6 >>> 45) & 8191L); + values[valuesOffset++] = (int) ((block6 >>> 32) & 8191L); + values[valuesOffset++] = (int) ((block6 >>> 19) & 8191L); + values[valuesOffset++] = (int) ((block6 >>> 6) & 8191L); + final long block7 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block6 & 63L) << 7) | (block7 >>> 57)); + values[valuesOffset++] = (int) ((block7 >>> 44) & 8191L); + values[valuesOffset++] = (int) ((block7 >>> 31) & 8191L); + values[valuesOffset++] = (int) ((block7 >>> 18) & 8191L); + values[valuesOffset++] = (int) ((block7 >>> 5) & 8191L); + final long block8 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block7 & 31L) << 8) | (block8 >>> 56)); + values[valuesOffset++] = (int) ((block8 >>> 43) & 8191L); + values[valuesOffset++] = (int) ((block8 >>> 30) & 8191L); + values[valuesOffset++] = (int) ((block8 >>> 17) & 8191L); + values[valuesOffset++] = (int) ((block8 >>> 4) & 8191L); + final long block9 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block8 & 15L) << 9) | (block9 >>> 55)); + values[valuesOffset++] = (int) ((block9 >>> 42) & 8191L); + values[valuesOffset++] = (int) ((block9 >>> 29) & 8191L); + values[valuesOffset++] = (int) ((block9 >>> 16) & 8191L); + values[valuesOffset++] = (int) ((block9 >>> 3) & 8191L); + final long block10 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block9 & 7L) << 10) | (block10 >>> 54)); + values[valuesOffset++] = (int) ((block10 >>> 41) & 8191L); + values[valuesOffset++] = (int) ((block10 >>> 28) & 8191L); + values[valuesOffset++] = (int) ((block10 >>> 15) & 8191L); + values[valuesOffset++] = (int) ((block10 >>> 2) & 8191L); + final long block11 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block10 & 3L) << 11) | (block11 >>> 53)); + values[valuesOffset++] = (int) ((block11 >>> 40) & 8191L); + values[valuesOffset++] = (int) ((block11 >>> 27) & 8191L); + values[valuesOffset++] = (int) ((block11 >>> 14) & 8191L); + values[valuesOffset++] = (int) ((block11 >>> 1) & 8191L); + final long block12 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block11 & 1L) << 12) | (block12 >>> 52)); + values[valuesOffset++] = (int) ((block12 >>> 39) & 8191L); + values[valuesOffset++] = (int) ((block12 >>> 26) & 8191L); + values[valuesOffset++] = (int) ((block12 >>> 13) & 8191L); + values[valuesOffset++] = (int) (block12 & 8191L); + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { for (int i = 0; i < iterations; ++i) { final int byte0 = blocks[blocksOffset++] & 0xFF; Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked3.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked3.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked3.java (working copy) @@ -102,6 +102,82 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations) { + for (int i = 0; i < iterations; ++i) { + final long block0 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (block0 >>> 61); + values[valuesOffset++] = (int) ((block0 >>> 58) & 7L); + values[valuesOffset++] = (int) ((block0 >>> 55) & 7L); + values[valuesOffset++] = (int) ((block0 >>> 52) & 7L); + values[valuesOffset++] = (int) ((block0 >>> 49) & 7L); + values[valuesOffset++] = (int) ((block0 >>> 46) & 7L); + values[valuesOffset++] = (int) ((block0 >>> 43) & 7L); + values[valuesOffset++] = (int) ((block0 >>> 40) & 7L); + values[valuesOffset++] = (int) ((block0 >>> 37) & 7L); + values[valuesOffset++] = (int) ((block0 >>> 34) & 7L); + values[valuesOffset++] = (int) ((block0 >>> 31) & 7L); + values[valuesOffset++] = (int) ((block0 >>> 28) & 7L); + values[valuesOffset++] = (int) ((block0 >>> 25) & 7L); + values[valuesOffset++] = (int) ((block0 >>> 22) & 7L); + values[valuesOffset++] = (int) ((block0 >>> 19) & 7L); + values[valuesOffset++] = (int) ((block0 >>> 16) & 7L); + values[valuesOffset++] = (int) ((block0 >>> 13) & 7L); + values[valuesOffset++] = (int) ((block0 >>> 10) & 7L); + values[valuesOffset++] = (int) ((block0 >>> 7) & 7L); + values[valuesOffset++] = (int) ((block0 >>> 4) & 7L); + values[valuesOffset++] = (int) ((block0 >>> 1) & 7L); + final long block1 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block0 & 1L) << 2) | (block1 >>> 62)); + values[valuesOffset++] = (int) ((block1 >>> 59) & 7L); + values[valuesOffset++] = (int) ((block1 >>> 56) & 7L); + values[valuesOffset++] = (int) ((block1 >>> 53) & 7L); + values[valuesOffset++] = (int) ((block1 >>> 50) & 7L); + values[valuesOffset++] = (int) ((block1 >>> 47) & 7L); + values[valuesOffset++] = (int) ((block1 >>> 44) & 7L); + values[valuesOffset++] = (int) ((block1 >>> 41) & 7L); + values[valuesOffset++] = (int) ((block1 >>> 38) & 7L); + values[valuesOffset++] = (int) ((block1 >>> 35) & 7L); + values[valuesOffset++] = (int) ((block1 >>> 32) & 7L); + values[valuesOffset++] = (int) ((block1 >>> 29) & 7L); + values[valuesOffset++] = (int) ((block1 >>> 26) & 7L); + values[valuesOffset++] = (int) ((block1 >>> 23) & 7L); + values[valuesOffset++] = (int) ((block1 >>> 20) & 7L); + values[valuesOffset++] = (int) ((block1 >>> 17) & 7L); + values[valuesOffset++] = (int) ((block1 >>> 14) & 7L); + values[valuesOffset++] = (int) ((block1 >>> 11) & 7L); + values[valuesOffset++] = (int) ((block1 >>> 8) & 7L); + values[valuesOffset++] = (int) ((block1 >>> 5) & 7L); + values[valuesOffset++] = (int) ((block1 >>> 2) & 7L); + final long block2 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block1 & 3L) << 1) | (block2 >>> 63)); + values[valuesOffset++] = (int) ((block2 >>> 60) & 7L); + values[valuesOffset++] = (int) ((block2 >>> 57) & 7L); + values[valuesOffset++] = (int) ((block2 >>> 54) & 7L); + values[valuesOffset++] = (int) ((block2 >>> 51) & 7L); + values[valuesOffset++] = (int) ((block2 >>> 48) & 7L); + values[valuesOffset++] = (int) ((block2 >>> 45) & 7L); + values[valuesOffset++] = (int) ((block2 >>> 42) & 7L); + values[valuesOffset++] = (int) ((block2 >>> 39) & 7L); + values[valuesOffset++] = (int) ((block2 >>> 36) & 7L); + values[valuesOffset++] = (int) ((block2 >>> 33) & 7L); + values[valuesOffset++] = (int) ((block2 >>> 30) & 7L); + values[valuesOffset++] = (int) ((block2 >>> 27) & 7L); + values[valuesOffset++] = (int) ((block2 >>> 24) & 7L); + values[valuesOffset++] = (int) ((block2 >>> 21) & 7L); + values[valuesOffset++] = (int) ((block2 >>> 18) & 7L); + values[valuesOffset++] = (int) ((block2 >>> 15) & 7L); + values[valuesOffset++] = (int) ((block2 >>> 12) & 7L); + values[valuesOffset++] = (int) ((block2 >>> 9) & 7L); + values[valuesOffset++] = (int) ((block2 >>> 6) & 7L); + values[valuesOffset++] = (int) ((block2 >>> 3) & 7L); + values[valuesOffset++] = (int) (block2 & 7L); + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { for (int i = 0; i < iterations; ++i) { final int byte0 = blocks[blocksOffset++] & 0xFF; Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked10.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked10.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked10.java (working copy) @@ -72,6 +72,54 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations) { + for (int i = 0; i < iterations; ++i) { + final long block0 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (block0 >>> 54); + values[valuesOffset++] = (int) ((block0 >>> 44) & 1023L); + values[valuesOffset++] = (int) ((block0 >>> 34) & 1023L); + values[valuesOffset++] = (int) ((block0 >>> 24) & 1023L); + values[valuesOffset++] = (int) ((block0 >>> 14) & 1023L); + values[valuesOffset++] = (int) ((block0 >>> 4) & 1023L); + final long block1 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block0 & 15L) << 6) | (block1 >>> 58)); + values[valuesOffset++] = (int) ((block1 >>> 48) & 1023L); + values[valuesOffset++] = (int) ((block1 >>> 38) & 1023L); + values[valuesOffset++] = (int) ((block1 >>> 28) & 1023L); + values[valuesOffset++] = (int) ((block1 >>> 18) & 1023L); + values[valuesOffset++] = (int) ((block1 >>> 8) & 1023L); + final long block2 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block1 & 255L) << 2) | (block2 >>> 62)); + values[valuesOffset++] = (int) ((block2 >>> 52) & 1023L); + values[valuesOffset++] = (int) ((block2 >>> 42) & 1023L); + values[valuesOffset++] = (int) ((block2 >>> 32) & 1023L); + values[valuesOffset++] = (int) ((block2 >>> 22) & 1023L); + values[valuesOffset++] = (int) ((block2 >>> 12) & 1023L); + values[valuesOffset++] = (int) ((block2 >>> 2) & 1023L); + final long block3 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block2 & 3L) << 8) | (block3 >>> 56)); + values[valuesOffset++] = (int) ((block3 >>> 46) & 1023L); + values[valuesOffset++] = (int) ((block3 >>> 36) & 1023L); + values[valuesOffset++] = (int) ((block3 >>> 26) & 1023L); + values[valuesOffset++] = (int) ((block3 >>> 16) & 1023L); + values[valuesOffset++] = (int) ((block3 >>> 6) & 1023L); + final long block4 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block3 & 63L) << 4) | (block4 >>> 60)); + values[valuesOffset++] = (int) ((block4 >>> 50) & 1023L); + values[valuesOffset++] = (int) ((block4 >>> 40) & 1023L); + values[valuesOffset++] = (int) ((block4 >>> 30) & 1023L); + values[valuesOffset++] = (int) ((block4 >>> 20) & 1023L); + values[valuesOffset++] = (int) ((block4 >>> 10) & 1023L); + values[valuesOffset++] = (int) (block4 & 1023L); + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { for (int i = 0; i < iterations; ++i) { final int byte0 = blocks[blocksOffset++] & 0xFF; Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked22.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked22.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked22.java (working copy) @@ -78,6 +78,66 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations) { + for (int i = 0; i < iterations; ++i) { + final long block0 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (block0 >>> 42); + values[valuesOffset++] = (int) ((block0 >>> 20) & 4194303L); + final long block1 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block0 & 1048575L) << 2) | (block1 >>> 62)); + values[valuesOffset++] = (int) ((block1 >>> 40) & 4194303L); + values[valuesOffset++] = (int) ((block1 >>> 18) & 4194303L); + final long block2 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block1 & 262143L) << 4) | (block2 >>> 60)); + values[valuesOffset++] = (int) ((block2 >>> 38) & 4194303L); + values[valuesOffset++] = (int) ((block2 >>> 16) & 4194303L); + final long block3 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block2 & 65535L) << 6) | (block3 >>> 58)); + values[valuesOffset++] = (int) ((block3 >>> 36) & 4194303L); + values[valuesOffset++] = (int) ((block3 >>> 14) & 4194303L); + final long block4 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block3 & 16383L) << 8) | (block4 >>> 56)); + values[valuesOffset++] = (int) ((block4 >>> 34) & 4194303L); + values[valuesOffset++] = (int) ((block4 >>> 12) & 4194303L); + final long block5 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block4 & 4095L) << 10) | (block5 >>> 54)); + values[valuesOffset++] = (int) ((block5 >>> 32) & 4194303L); + values[valuesOffset++] = (int) ((block5 >>> 10) & 4194303L); + final long block6 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block5 & 1023L) << 12) | (block6 >>> 52)); + values[valuesOffset++] = (int) ((block6 >>> 30) & 4194303L); + values[valuesOffset++] = (int) ((block6 >>> 8) & 4194303L); + final long block7 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block6 & 255L) << 14) | (block7 >>> 50)); + values[valuesOffset++] = (int) ((block7 >>> 28) & 4194303L); + values[valuesOffset++] = (int) ((block7 >>> 6) & 4194303L); + final long block8 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block7 & 63L) << 16) | (block8 >>> 48)); + values[valuesOffset++] = (int) ((block8 >>> 26) & 4194303L); + values[valuesOffset++] = (int) ((block8 >>> 4) & 4194303L); + final long block9 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block8 & 15L) << 18) | (block9 >>> 46)); + values[valuesOffset++] = (int) ((block9 >>> 24) & 4194303L); + values[valuesOffset++] = (int) ((block9 >>> 2) & 4194303L); + final long block10 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block9 & 3L) << 20) | (block10 >>> 44)); + values[valuesOffset++] = (int) ((block10 >>> 22) & 4194303L); + values[valuesOffset++] = (int) (block10 & 4194303L); + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { for (int i = 0; i < iterations; ++i) { final int byte0 = blocks[blocksOffset++] & 0xFF; Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked18.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked18.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked18.java (working copy) @@ -76,6 +76,62 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations) { + for (int i = 0; i < iterations; ++i) { + final long block0 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (block0 >>> 46); + values[valuesOffset++] = (int) ((block0 >>> 28) & 262143L); + values[valuesOffset++] = (int) ((block0 >>> 10) & 262143L); + final long block1 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block0 & 1023L) << 8) | (block1 >>> 56)); + values[valuesOffset++] = (int) ((block1 >>> 38) & 262143L); + values[valuesOffset++] = (int) ((block1 >>> 20) & 262143L); + values[valuesOffset++] = (int) ((block1 >>> 2) & 262143L); + final long block2 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block1 & 3L) << 16) | (block2 >>> 48)); + values[valuesOffset++] = (int) ((block2 >>> 30) & 262143L); + values[valuesOffset++] = (int) ((block2 >>> 12) & 262143L); + final long block3 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block2 & 4095L) << 6) | (block3 >>> 58)); + values[valuesOffset++] = (int) ((block3 >>> 40) & 262143L); + values[valuesOffset++] = (int) ((block3 >>> 22) & 262143L); + values[valuesOffset++] = (int) ((block3 >>> 4) & 262143L); + final long block4 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block3 & 15L) << 14) | (block4 >>> 50)); + values[valuesOffset++] = (int) ((block4 >>> 32) & 262143L); + values[valuesOffset++] = (int) ((block4 >>> 14) & 262143L); + final long block5 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block4 & 16383L) << 4) | (block5 >>> 60)); + values[valuesOffset++] = (int) ((block5 >>> 42) & 262143L); + values[valuesOffset++] = (int) ((block5 >>> 24) & 262143L); + values[valuesOffset++] = (int) ((block5 >>> 6) & 262143L); + final long block6 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block5 & 63L) << 12) | (block6 >>> 52)); + values[valuesOffset++] = (int) ((block6 >>> 34) & 262143L); + values[valuesOffset++] = (int) ((block6 >>> 16) & 262143L); + final long block7 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block6 & 65535L) << 2) | (block7 >>> 62)); + values[valuesOffset++] = (int) ((block7 >>> 44) & 262143L); + values[valuesOffset++] = (int) ((block7 >>> 26) & 262143L); + values[valuesOffset++] = (int) ((block7 >>> 8) & 262143L); + final long block8 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block7 & 255L) << 10) | (block8 >>> 54)); + values[valuesOffset++] = (int) ((block8 >>> 36) & 262143L); + values[valuesOffset++] = (int) ((block8 >>> 18) & 262143L); + values[valuesOffset++] = (int) (block8 & 262143L); + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { for (int i = 0; i < iterations; ++i) { final int byte0 = blocks[blocksOffset++] & 0xFF; Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPackedSingleBlock.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPackedSingleBlock.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPackedSingleBlock.java (working copy) @@ -131,6 +131,18 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, + int valuesOffset, int iterations) { + //if (bitsPerValue > 32) { + // throw new UnsupportedOperationException("Cannot decode " + bitsPerValue + "-bits values into an int[]"); + //} + for (int i = 0; i < iterations; ++i) { + valuesOffset = decode(unsafe.getLong(address), values, valuesOffset); + address += 8; + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { if (bitsPerValue > 32) { Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked8.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked8.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked8.java (working copy) @@ -39,6 +39,17 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations) { + for (int i = 0; i < iterations; ++i) { + final long block = unsafe.getLong(address); + address += 8; + for (int shift = 56; shift >= 0; shift -= 8) { + values[valuesOffset++] = (int) ((block >>> shift) & 255); + } + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { for (int j = 0; j < iterations; ++j) { values[valuesOffset++] = blocks[blocksOffset++] & 0xFF; Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked15.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked15.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked15.java (working copy) @@ -114,6 +114,106 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations) { + for (int i = 0; i < iterations; ++i) { + final long block0 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (block0 >>> 49); + values[valuesOffset++] = (int) ((block0 >>> 34) & 32767L); + values[valuesOffset++] = (int) ((block0 >>> 19) & 32767L); + values[valuesOffset++] = (int) ((block0 >>> 4) & 32767L); + final long block1 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block0 & 15L) << 11) | (block1 >>> 53)); + values[valuesOffset++] = (int) ((block1 >>> 38) & 32767L); + values[valuesOffset++] = (int) ((block1 >>> 23) & 32767L); + values[valuesOffset++] = (int) ((block1 >>> 8) & 32767L); + final long block2 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block1 & 255L) << 7) | (block2 >>> 57)); + values[valuesOffset++] = (int) ((block2 >>> 42) & 32767L); + values[valuesOffset++] = (int) ((block2 >>> 27) & 32767L); + values[valuesOffset++] = (int) ((block2 >>> 12) & 32767L); + final long block3 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block2 & 4095L) << 3) | (block3 >>> 61)); + values[valuesOffset++] = (int) ((block3 >>> 46) & 32767L); + values[valuesOffset++] = (int) ((block3 >>> 31) & 32767L); + values[valuesOffset++] = (int) ((block3 >>> 16) & 32767L); + values[valuesOffset++] = (int) ((block3 >>> 1) & 32767L); + final long block4 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block3 & 1L) << 14) | (block4 >>> 50)); + values[valuesOffset++] = (int) ((block4 >>> 35) & 32767L); + values[valuesOffset++] = (int) ((block4 >>> 20) & 32767L); + values[valuesOffset++] = (int) ((block4 >>> 5) & 32767L); + final long block5 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block4 & 31L) << 10) | (block5 >>> 54)); + values[valuesOffset++] = (int) ((block5 >>> 39) & 32767L); + values[valuesOffset++] = (int) ((block5 >>> 24) & 32767L); + values[valuesOffset++] = (int) ((block5 >>> 9) & 32767L); + final long block6 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block5 & 511L) << 6) | (block6 >>> 58)); + values[valuesOffset++] = (int) ((block6 >>> 43) & 32767L); + values[valuesOffset++] = (int) ((block6 >>> 28) & 32767L); + values[valuesOffset++] = (int) ((block6 >>> 13) & 32767L); + final long block7 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block6 & 8191L) << 2) | (block7 >>> 62)); + values[valuesOffset++] = (int) ((block7 >>> 47) & 32767L); + values[valuesOffset++] = (int) ((block7 >>> 32) & 32767L); + values[valuesOffset++] = (int) ((block7 >>> 17) & 32767L); + values[valuesOffset++] = (int) ((block7 >>> 2) & 32767L); + final long block8 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block7 & 3L) << 13) | (block8 >>> 51)); + values[valuesOffset++] = (int) ((block8 >>> 36) & 32767L); + values[valuesOffset++] = (int) ((block8 >>> 21) & 32767L); + values[valuesOffset++] = (int) ((block8 >>> 6) & 32767L); + final long block9 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block8 & 63L) << 9) | (block9 >>> 55)); + values[valuesOffset++] = (int) ((block9 >>> 40) & 32767L); + values[valuesOffset++] = (int) ((block9 >>> 25) & 32767L); + values[valuesOffset++] = (int) ((block9 >>> 10) & 32767L); + final long block10 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block9 & 1023L) << 5) | (block10 >>> 59)); + values[valuesOffset++] = (int) ((block10 >>> 44) & 32767L); + values[valuesOffset++] = (int) ((block10 >>> 29) & 32767L); + values[valuesOffset++] = (int) ((block10 >>> 14) & 32767L); + final long block11 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block10 & 16383L) << 1) | (block11 >>> 63)); + values[valuesOffset++] = (int) ((block11 >>> 48) & 32767L); + values[valuesOffset++] = (int) ((block11 >>> 33) & 32767L); + values[valuesOffset++] = (int) ((block11 >>> 18) & 32767L); + values[valuesOffset++] = (int) ((block11 >>> 3) & 32767L); + final long block12 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block11 & 7L) << 12) | (block12 >>> 52)); + values[valuesOffset++] = (int) ((block12 >>> 37) & 32767L); + values[valuesOffset++] = (int) ((block12 >>> 22) & 32767L); + values[valuesOffset++] = (int) ((block12 >>> 7) & 32767L); + final long block13 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block12 & 127L) << 8) | (block13 >>> 56)); + values[valuesOffset++] = (int) ((block13 >>> 41) & 32767L); + values[valuesOffset++] = (int) ((block13 >>> 26) & 32767L); + values[valuesOffset++] = (int) ((block13 >>> 11) & 32767L); + final long block14 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block13 & 2047L) << 4) | (block14 >>> 60)); + values[valuesOffset++] = (int) ((block14 >>> 45) & 32767L); + values[valuesOffset++] = (int) ((block14 >>> 30) & 32767L); + values[valuesOffset++] = (int) ((block14 >>> 15) & 32767L); + values[valuesOffset++] = (int) (block14 & 32767L); + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { for (int i = 0; i < iterations; ++i) { final int byte0 = blocks[blocksOffset++] & 0xFF; Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked5.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked5.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked5.java (working copy) @@ -104,6 +104,86 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations) { + for (int i = 0; i < iterations; ++i) { + final long block0 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (block0 >>> 59); + values[valuesOffset++] = (int) ((block0 >>> 54) & 31L); + values[valuesOffset++] = (int) ((block0 >>> 49) & 31L); + values[valuesOffset++] = (int) ((block0 >>> 44) & 31L); + values[valuesOffset++] = (int) ((block0 >>> 39) & 31L); + values[valuesOffset++] = (int) ((block0 >>> 34) & 31L); + values[valuesOffset++] = (int) ((block0 >>> 29) & 31L); + values[valuesOffset++] = (int) ((block0 >>> 24) & 31L); + values[valuesOffset++] = (int) ((block0 >>> 19) & 31L); + values[valuesOffset++] = (int) ((block0 >>> 14) & 31L); + values[valuesOffset++] = (int) ((block0 >>> 9) & 31L); + values[valuesOffset++] = (int) ((block0 >>> 4) & 31L); + final long block1 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block0 & 15L) << 1) | (block1 >>> 63)); + values[valuesOffset++] = (int) ((block1 >>> 58) & 31L); + values[valuesOffset++] = (int) ((block1 >>> 53) & 31L); + values[valuesOffset++] = (int) ((block1 >>> 48) & 31L); + values[valuesOffset++] = (int) ((block1 >>> 43) & 31L); + values[valuesOffset++] = (int) ((block1 >>> 38) & 31L); + values[valuesOffset++] = (int) ((block1 >>> 33) & 31L); + values[valuesOffset++] = (int) ((block1 >>> 28) & 31L); + values[valuesOffset++] = (int) ((block1 >>> 23) & 31L); + values[valuesOffset++] = (int) ((block1 >>> 18) & 31L); + values[valuesOffset++] = (int) ((block1 >>> 13) & 31L); + values[valuesOffset++] = (int) ((block1 >>> 8) & 31L); + values[valuesOffset++] = (int) ((block1 >>> 3) & 31L); + final long block2 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block1 & 7L) << 2) | (block2 >>> 62)); + values[valuesOffset++] = (int) ((block2 >>> 57) & 31L); + values[valuesOffset++] = (int) ((block2 >>> 52) & 31L); + values[valuesOffset++] = (int) ((block2 >>> 47) & 31L); + values[valuesOffset++] = (int) ((block2 >>> 42) & 31L); + values[valuesOffset++] = (int) ((block2 >>> 37) & 31L); + values[valuesOffset++] = (int) ((block2 >>> 32) & 31L); + values[valuesOffset++] = (int) ((block2 >>> 27) & 31L); + values[valuesOffset++] = (int) ((block2 >>> 22) & 31L); + values[valuesOffset++] = (int) ((block2 >>> 17) & 31L); + values[valuesOffset++] = (int) ((block2 >>> 12) & 31L); + values[valuesOffset++] = (int) ((block2 >>> 7) & 31L); + values[valuesOffset++] = (int) ((block2 >>> 2) & 31L); + final long block3 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block2 & 3L) << 3) | (block3 >>> 61)); + values[valuesOffset++] = (int) ((block3 >>> 56) & 31L); + values[valuesOffset++] = (int) ((block3 >>> 51) & 31L); + values[valuesOffset++] = (int) ((block3 >>> 46) & 31L); + values[valuesOffset++] = (int) ((block3 >>> 41) & 31L); + values[valuesOffset++] = (int) ((block3 >>> 36) & 31L); + values[valuesOffset++] = (int) ((block3 >>> 31) & 31L); + values[valuesOffset++] = (int) ((block3 >>> 26) & 31L); + values[valuesOffset++] = (int) ((block3 >>> 21) & 31L); + values[valuesOffset++] = (int) ((block3 >>> 16) & 31L); + values[valuesOffset++] = (int) ((block3 >>> 11) & 31L); + values[valuesOffset++] = (int) ((block3 >>> 6) & 31L); + values[valuesOffset++] = (int) ((block3 >>> 1) & 31L); + final long block4 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block3 & 1L) << 4) | (block4 >>> 60)); + values[valuesOffset++] = (int) ((block4 >>> 55) & 31L); + values[valuesOffset++] = (int) ((block4 >>> 50) & 31L); + values[valuesOffset++] = (int) ((block4 >>> 45) & 31L); + values[valuesOffset++] = (int) ((block4 >>> 40) & 31L); + values[valuesOffset++] = (int) ((block4 >>> 35) & 31L); + values[valuesOffset++] = (int) ((block4 >>> 30) & 31L); + values[valuesOffset++] = (int) ((block4 >>> 25) & 31L); + values[valuesOffset++] = (int) ((block4 >>> 20) & 31L); + values[valuesOffset++] = (int) ((block4 >>> 15) & 31L); + values[valuesOffset++] = (int) ((block4 >>> 10) & 31L); + values[valuesOffset++] = (int) ((block4 >>> 5) & 31L); + values[valuesOffset++] = (int) (block4 & 31L); + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { for (int i = 0; i < iterations; ++i) { final int byte0 = blocks[blocksOffset++] & 0xFF; Index: lucene/core/src/java/org/apache/lucene/util/packed/PackedInts.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/PackedInts.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/PackedInts.java (working copy) @@ -350,6 +350,8 @@ */ void decode(long[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations); + void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations); + /** * Read 8 * iterations * blockCount() blocks from blocks, * decode them and write iterations * valueCount() values into Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked12.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked12.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked12.java (working copy) @@ -54,6 +54,34 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations) { + for (int i = 0; i < iterations; ++i) { + final long block0 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (block0 >>> 52); + values[valuesOffset++] = (int) ((block0 >>> 40) & 4095L); + values[valuesOffset++] = (int) ((block0 >>> 28) & 4095L); + values[valuesOffset++] = (int) ((block0 >>> 16) & 4095L); + values[valuesOffset++] = (int) ((block0 >>> 4) & 4095L); + final long block1 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block0 & 15L) << 8) | (block1 >>> 56)); + values[valuesOffset++] = (int) ((block1 >>> 44) & 4095L); + values[valuesOffset++] = (int) ((block1 >>> 32) & 4095L); + values[valuesOffset++] = (int) ((block1 >>> 20) & 4095L); + values[valuesOffset++] = (int) ((block1 >>> 8) & 4095L); + final long block2 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block1 & 255L) << 4) | (block2 >>> 60)); + values[valuesOffset++] = (int) ((block2 >>> 48) & 4095L); + values[valuesOffset++] = (int) ((block2 >>> 36) & 4095L); + values[valuesOffset++] = (int) ((block2 >>> 24) & 4095L); + values[valuesOffset++] = (int) ((block2 >>> 12) & 4095L); + values[valuesOffset++] = (int) (block2 & 4095L); + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { for (int i = 0; i < iterations; ++i) { final int byte0 = blocks[blocksOffset++] & 0xFF; Index: lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked24.java =================================================================== --- lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked24.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/util/packed/BulkOperationPacked24.java (working copy) @@ -46,6 +46,26 @@ } @Override + public void decode(long address, int blocksOffset, int[] values, int valuesOffset, int iterations) { + for (int i = 0; i < iterations; ++i) { + final long block0 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (block0 >>> 40); + values[valuesOffset++] = (int) ((block0 >>> 16) & 16777215L); + final long block1 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block0 & 65535L) << 8) | (block1 >>> 56)); + values[valuesOffset++] = (int) ((block1 >>> 32) & 16777215L); + values[valuesOffset++] = (int) ((block1 >>> 8) & 16777215L); + final long block2 = unsafe.getLong(address); + address += 8; + values[valuesOffset++] = (int) (((block1 & 255L) << 16) | (block2 >>> 48)); + values[valuesOffset++] = (int) ((block2 >>> 24) & 16777215L); + values[valuesOffset++] = (int) (block2 & 16777215L); + } + } + + @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { for (int i = 0; i < iterations; ++i) { final int byte0 = blocks[blocksOffset++] & 0xFF; Index: lucene/core/src/java/org/apache/lucene/store/FSDirectory.java =================================================================== --- lucene/core/src/java/org/apache/lucene/store/FSDirectory.java (revision 1575909) +++ lucene/core/src/java/org/apache/lucene/store/FSDirectory.java (working copy) @@ -401,6 +401,11 @@ public void setLength(long length) throws IOException { file.setLength(length); } + + @Override + public String toString() { + return "FSIndexOutput(" + name + ")"; + } } protected void fsync(String name) throws IOException { Index: lucene/core/src/java/org/apache/lucene/store/NativeMMapDirectory.cpp =================================================================== --- lucene/core/src/java/org/apache/lucene/store/NativeMMapDirectory.cpp (revision 0) +++ lucene/core/src/java/org/apache/lucene/store/NativeMMapDirectory.cpp (working copy) @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// To see assembly: +// +// g++ -fpermissive -S -O4 -o test.s -I/usr/local/src/jdk1.6.0_32/include -I/usr/local/src/jdk1.6.0_32/include/linux /l/nativebq/lucene/misc/src/java/org/apache/lucene/search/NativeSearch.cpp +// + +#include +#include +#include + +extern "C" JNIEXPORT jlong JNICALL +Java_org_apache_lucene_store_NativeMMapDirectory_map(JNIEnv *env, + jclass cl, + jint fd, jlong fileLength) { + long address = (long) mmap(0, fileLength, PROT_READ, MAP_SHARED, fd, 0); + if (address == -1) { + jclass exClass = env->FindClass("java/io/IOException"); + char buf[64]; + sprintf(buf, "errno=%d", errno); + return env->ThrowNew(exClass, buf); + } + //printf("map addr=%ld len=%ld\n", address, fileLength);fflush(stdout); + return address; +} + +extern "C" JNIEXPORT jlong JNICALL +Java_org_apache_lucene_store_NativeMMapDirectory_unmap(JNIEnv *env, + jclass cl, + jlong address, jlong fileLength) { + munmap((void *) address, fileLength); + //printf("unmap addr=%ld len=%ld\n", address, fileLength);fflush(stdout); +} Property changes on: lucene/core/src/java/org/apache/lucene/store/NativeMMapDirectory.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/core/src/java/org/apache/lucene/store/NativeMMapDirectory.java =================================================================== --- lucene/core/src/java/org/apache/lucene/store/NativeMMapDirectory.java (revision 0) +++ lucene/core/src/java/org/apache/lucene/store/NativeMMapDirectory.java (working copy) @@ -0,0 +1,196 @@ +package org.apache.lucene.store; + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.File; +import java.io.EOFException; +import java.io.RandomAccessFile; +import java.io.FileDescriptor; +import java.io.IOException; +import java.lang.reflect.*; +import java.nio.channels.FileChannel; +import java.nio.file.StandardOpenOption; + +import sun.misc.Unsafe; + +// nocommit fix build.xml: + +// export LD_LIBRARY_PATH=/l/nativemmap/lucene/core +// +// g++ -fPIC -O4 -shared -I/usr/local/src/jdk1.7.0_25/include -I/usr/local/src/jdk1.7.0_25/include/linux -o libNativeMMapDirectory.so src/java/org/apache/lucene/store/NativeMMapDirectory.cpp +// +// ant test -Dtests.directory=org.apache.lucene.store.NativeMMapDirectory -Dtests.postingsformat=NativeMMap -Dtestcase=TestDemo + +// pushd src/java/org/apache/lucene/util/packed; python -u gen_BulkOperation.py; popd + +public class NativeMMapDirectory extends FSDirectory { + + static { + System.loadLibrary("NativeMMapDirectory"); + } + + private final static native long map(int fd, long fileLength); + private final static native void unmap(long address, long fileLength); + + public NativeMMapDirectory(File path) throws IOException { + this(path, null); + } + + public NativeMMapDirectory(File path, LockFactory lockFactory) throws IOException { + super(path, lockFactory); + } + + @Override + public IndexInput openInput(String name, IOContext context) throws IOException { + ensureOpen(); + //System.out.println("openInput name=" + name + " len=" + fileLength(name)); + File file = new File(getDirectory(), name); + //try (RandomAccessFile raf = new RandomAccessFile(file, "r")) { + return new NativeMMapIndexInput("NativeMMapIndexInput(path=\"" + file.toString() + "\")", new RandomAccessFile(file, "r")); + } + + @Override + public IndexInputSlicer createSlicer(String name, IOContext context) throws IOException { + final NativeMMapIndexInput full = (NativeMMapIndexInput) openInput(name, context); + + return new IndexInputSlicer() { + @Override + public IndexInput openSlice(String sliceDescription, long offset, long length) throws IOException { + ensureOpen(); + return new NativeMMapIndexInput(full.toString() + "[slice=" + sliceDescription + "]", full.address + offset, length, full.address + offset); + } + + @Override + public void close() throws IOException { + full.close(); + } + }; + } + + int getFileDes(FileDescriptor fd) { + try { + Class x = Class.forName("java.io.FileDescriptor"); + Field f = x.getDeclaredField("fd"); + f.setAccessible(true); + return f.getInt(fd); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + static final Unsafe unsafe; + + static { + try { + Field f = Unsafe.class.getDeclaredField("theUnsafe"); + f.setAccessible(true); + unsafe = (Unsafe) f.get(null); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + static final long arrayBaseOffset = (long) unsafe.arrayBaseOffset(byte[].class); + + public final class NativeMMapIndexInput extends IndexInput { + + private final long address; + private final long length; + private final RandomAccessFile raf; + + private long pos; + + NativeMMapIndexInput(String resourceDescription, RandomAccessFile raf) throws IOException { + super(resourceDescription); + this.raf = raf; + length = raf.length(); + if (length == 0) { + // mmap gets angry if you map 0 length file: + address = 0; + } else { + int fd = getFileDes(raf.getFD()); + address = map(fd, length); + //System.out.println("map: " + resourceDescription + " fd=" + fd + " -> address=" + address + " length=" + length); + } + pos = address; + } + + NativeMMapIndexInput(String resourceDescription, long address, long length, long pos) { + super(resourceDescription); + raf = null; + this.address = address; + this.length = length; + this.pos = pos; + } + + public long getAddress() { + return pos; + } + + public void setAddress(long newPos) { + this.pos = newPos; + } + + @Override + public long getFilePointer() { + return pos - address; + } + + @Override + public void seek(long pos) { + this.pos = address + pos; + } + + @Override + public long length() { + return length; + } + + @Override + public void close() throws IOException { + // nocommit guard against double close + if (raf != null) { + unmap(address, length); + raf.close(); + } + } + + @Override + public byte readByte() throws IOException { + // Necessary for reading segments_N while IW is committing: + if (pos >= address + length) { + throw new EOFException(); + } + return unsafe.getByte(pos++); + } + + @Override + public void readBytes(byte[] b, int offset, int len) throws IOException { + // Necessary for reading segments_N while IW is committing: + if (pos + len > address + length) { + throw new EOFException(); + } + unsafe.copyMemory(null, pos, b, arrayBaseOffset + offset, len); + pos += len; + } + + @Override + public NativeMMapIndexInput clone() { + return new NativeMMapIndexInput(toString(), address, length, pos); + } + } +} Property changes on: lucene/core/src/java/org/apache/lucene/store/NativeMMapDirectory.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/core/src/java/org/apache/lucene/codecs/nativemmap/NativeMMapPostingsFormat.java =================================================================== --- lucene/core/src/java/org/apache/lucene/codecs/nativemmap/NativeMMapPostingsFormat.java (revision 0) +++ lucene/core/src/java/org/apache/lucene/codecs/nativemmap/NativeMMapPostingsFormat.java (working copy) @@ -0,0 +1,145 @@ +package org.apache.lucene.codecs.nativemmap; + + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.IOException; + +import org.apache.lucene.codecs.BlockTreeTermsReader; +import org.apache.lucene.codecs.BlockTreeTermsWriter; +import org.apache.lucene.codecs.CodecUtil; +import org.apache.lucene.codecs.FieldsConsumer; +import org.apache.lucene.codecs.FieldsProducer; +import org.apache.lucene.codecs.MultiLevelSkipListWriter; +import org.apache.lucene.codecs.PostingsFormat; +import org.apache.lucene.codecs.PostingsReaderBase; +import org.apache.lucene.codecs.PostingsWriterBase; +import org.apache.lucene.index.DocsEnum; +import org.apache.lucene.index.FieldInfo.IndexOptions; +import org.apache.lucene.index.SegmentReadState; +import org.apache.lucene.index.SegmentWriteState; +import org.apache.lucene.store.DataOutput; +import org.apache.lucene.util.IOUtils; +import org.apache.lucene.util.packed.PackedInts; + +// nocommit also test aligned reads + +/** + * Very similar to {@link NativeMMapPostingsFormat}, except + * requires that {@link NativeMMapDirectory} is used so that + * direct (Unsafe!) access to memory-mapped longs is + * possible. + * + * @lucene.experimental + */ + +public final class NativeMMapPostingsFormat extends PostingsFormat { + /** + * Filename extension for document number, frequencies, and skip data. + * See chapter: Frequencies and Skip Data + */ + public static final String DOC_EXTENSION = "doc"; + + /** + * Filename extension for positions. + * See chapter: Positions + */ + public static final String POS_EXTENSION = "pos"; + + /** + * Filename extension for payloads and offsets. + * See chapter: Payloads and Offsets + */ + public static final String PAY_EXTENSION = "pay"; + + private final int minTermBlockSize; + private final int maxTermBlockSize; + + /** + * Fixed packed block size, number of integers encoded in + * a single packed block. + */ + // NOTE: must be multiple of 64 because of PackedInts long-aligned encoding/decoding + public final static int BLOCK_SIZE = 128; + + /** Creates {@code NativeMMapPostingsFormat} with default + * settings. */ + public NativeMMapPostingsFormat() { + this(BlockTreeTermsWriter.DEFAULT_MIN_BLOCK_SIZE, BlockTreeTermsWriter.DEFAULT_MAX_BLOCK_SIZE); + } + + /** Creates {@code NativeMMapPostingsFormat} with custom + * values for {@code minBlockSize} and {@code + * maxBlockSize} passed to block terms dictionary. + * @see BlockTreeTermsWriter#BlockTreeTermsWriter(SegmentWriteState,PostingsWriterBase,int,int) */ + public NativeMMapPostingsFormat(int minTermBlockSize, int maxTermBlockSize) { + super("NativeMMap"); + this.minTermBlockSize = minTermBlockSize; + assert minTermBlockSize > 1; + this.maxTermBlockSize = maxTermBlockSize; + assert minTermBlockSize <= maxTermBlockSize; + } + + @Override + public String toString() { + return getName() + "(blocksize=" + BLOCK_SIZE + ")"; + } + + @Override + public FieldsConsumer fieldsConsumer(SegmentWriteState state) throws IOException { + PostingsWriterBase postingsWriter = new NativeMMapPostingsWriter(state); + + boolean success = false; + try { + FieldsConsumer ret = new BlockTreeTermsWriter(state, + postingsWriter, + minTermBlockSize, + maxTermBlockSize); + success = true; + return ret; + } finally { + if (!success) { + IOUtils.closeWhileHandlingException(postingsWriter); + } + } + } + + @Override + public FieldsProducer fieldsProducer(SegmentReadState state) throws IOException { + PostingsReaderBase postingsReader = new NativeMMapPostingsReader(state.directory, + state.fieldInfos, + state.segmentInfo, + state.context, + state.segmentSuffix); + boolean success = false; + try { + FieldsProducer ret = new BlockTreeTermsReader(state.directory, + state.fieldInfos, + state.segmentInfo, + postingsReader, + state.context, + state.segmentSuffix); + success = true; + return ret; + } finally { + if (!success) { + IOUtils.closeWhileHandlingException(postingsReader); + } + } + } +} Property changes on: lucene/core/src/java/org/apache/lucene/codecs/nativemmap/NativeMMapPostingsFormat.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lucene/core/src/java/org/apache/lucene/codecs/nativemmap/ForUtil.java =================================================================== --- lucene/core/src/java/org/apache/lucene/codecs/nativemmap/ForUtil.java (revision 0) +++ lucene/core/src/java/org/apache/lucene/codecs/nativemmap/ForUtil.java (working copy) @@ -0,0 +1,274 @@ +package org.apache.lucene.codecs.nativemmap; +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.IOException; +import java.util.Arrays; + +import org.apache.lucene.store.DataInput; +import org.apache.lucene.store.DataOutput; +import org.apache.lucene.store.IndexInput; +import org.apache.lucene.store.IndexOutput; +import org.apache.lucene.store.NativeMMapDirectory.NativeMMapIndexInput; +import org.apache.lucene.util.packed.PackedInts.Decoder; +import org.apache.lucene.util.packed.PackedInts.FormatAndBits; +import org.apache.lucene.util.packed.PackedInts; + +import static org.apache.lucene.codecs.lucene41.Lucene41PostingsFormat.BLOCK_SIZE; + +/** + * Encode all values in normal area with fixed bit width, + * which is determined by the max value in this block. + */ +final class ForUtil { + + /** + * Special number of bits per value used whenever all values to encode are equal. + */ + private static final int ALL_VALUES_EQUAL = 0; + + /** + * Upper limit of the number of bytes that might be required to stored + * BLOCK_SIZE encoded values. + */ + static final int MAX_ENCODED_SIZE = BLOCK_SIZE * 4; + + /** + * Upper limit of the number of values that might be decoded in a single call to + * {@link #readBlock(IndexInput, byte[], int[])}. Although values after + * BLOCK_SIZE are garbage, it is necessary to allocate value buffers + * whose size is >= MAX_DATA_SIZE to avoid {@link ArrayIndexOutOfBoundsException}s. + */ + static final int MAX_DATA_SIZE; + static { + int maxDataSize = 0; + for(int version=PackedInts.VERSION_START;version<=PackedInts.VERSION_CURRENT;version++) { + for (PackedInts.Format format : PackedInts.Format.values()) { + for (int bpv = 1; bpv <= 32; ++bpv) { + if (!format.isSupported(bpv)) { + continue; + } + final PackedInts.Decoder decoder = PackedInts.getDecoder(format, version, bpv); + final int iterations = computeIterations(decoder); + maxDataSize = Math.max(maxDataSize, iterations * decoder.byteValueCount()); + } + } + } + MAX_DATA_SIZE = maxDataSize; + } + + /** + * Compute the number of iterations required to decode BLOCK_SIZE + * values with the provided {@link Decoder}. + */ + private static int computeIterations(PackedInts.Decoder decoder) { + return (int) Math.ceil((float) BLOCK_SIZE / decoder.longValueCount()); + } + + /** + * Compute the number of longs required to encode a block of values that require + * bitsPerValue bits per value with format format. + */ + private static int encodedSize(PackedInts.Format format, int packedIntsVersion, int bitsPerValue) { + final long longCount = format.longCount(packedIntsVersion, BLOCK_SIZE, bitsPerValue); + assert longCount >= 0 && longCount <= Integer.MAX_VALUE : longCount; + return (int) longCount; + } + + private final int[] encodedSizes; + private final PackedInts.Encoder[] encoders; + private final PackedInts.Decoder[] decoders; + private final int[] iterations; + + /** + * Create a new {@link ForUtil} instance and save state into out. + */ + ForUtil(float acceptableOverheadRatio, DataOutput out) throws IOException { + out.writeVInt(PackedInts.VERSION_CURRENT); + encodedSizes = new int[33]; + encoders = new PackedInts.Encoder[33]; + decoders = new PackedInts.Decoder[33]; + iterations = new int[33]; + + for (int bpv = 1; bpv <= 32; ++bpv) { + final FormatAndBits formatAndBits = PackedInts.fastestFormatAndBits( + BLOCK_SIZE, bpv, acceptableOverheadRatio); + assert formatAndBits.format.isSupported(formatAndBits.bitsPerValue); + assert formatAndBits.bitsPerValue <= 32; + encodedSizes[bpv] = encodedSize(formatAndBits.format, PackedInts.VERSION_CURRENT, formatAndBits.bitsPerValue); + encoders[bpv] = PackedInts.getEncoder( + formatAndBits.format, PackedInts.VERSION_CURRENT, formatAndBits.bitsPerValue); + decoders[bpv] = PackedInts.getDecoder( + formatAndBits.format, PackedInts.VERSION_CURRENT, formatAndBits.bitsPerValue); + iterations[bpv] = computeIterations(decoders[bpv]); + + out.writeVInt(formatAndBits.format.getId() << 5 | (formatAndBits.bitsPerValue - 1)); + //System.out.println("bpv=" + bpv + " decoder=" + decoders[bpv]); + } + } + + /** + * Restore a {@link ForUtil} from a {@link DataInput}. + */ + ForUtil(DataInput in) throws IOException { + int packedIntsVersion = in.readVInt(); + PackedInts.checkVersion(packedIntsVersion); + encodedSizes = new int[33]; + encoders = new PackedInts.Encoder[33]; + decoders = new PackedInts.Decoder[33]; + iterations = new int[33]; + + for (int bpv = 1; bpv <= 32; ++bpv) { + final int code = in.readVInt(); + final int formatId = code >>> 5; + final int bitsPerValue = (code & 31) + 1; + + final PackedInts.Format format = PackedInts.Format.byId(formatId); + assert format.isSupported(bitsPerValue); + encodedSizes[bpv] = encodedSize(format, packedIntsVersion, bitsPerValue); + encoders[bpv] = PackedInts.getEncoder( + format, packedIntsVersion, bitsPerValue); + decoders[bpv] = PackedInts.getDecoder( + format, packedIntsVersion, bitsPerValue); + iterations[bpv] = computeIterations(decoders[bpv]); + //System.out.println("bpv=" + bpv + " iters=" + iterations[bpv] + " decoder=" + decoders[bpv] + " longValueCount=" + decoders[bpv].longValueCount()); + } + } + + /** + * Write a block of data (For format). + * + * @param data the data to write + * @param encoded a buffer to use to encode data + * @param out the destination output + * @throws IOException If there is a low-level I/O error + */ + void writeBlock(int[] data, long[] encoded, IndexOutput out) throws IOException { + //System.out.println("ForUtil.writeBlock out=" + out + " fp=" + out.getFilePointer()); + if (isAllEqual(data)) { + //System.out.println(" all equal " + data[0]); + out.writeByte((byte) ALL_VALUES_EQUAL); + out.writeVInt(data[0]); + return; + } + + final int numBits = bitsRequired(data); + //System.out.println(" bpv=" + numBits); + assert numBits > 0 && numBits <= 32 : numBits; + final PackedInts.Encoder encoder = encoders[numBits]; + final int iters = iterations[numBits]; + assert iters * encoder.longValueCount() >= BLOCK_SIZE; + final int encodedSize = encodedSizes[numBits]; + assert (iters * encoder.longBlockCount()) << 3 >= encodedSize; + + out.writeByte((byte) numBits); + + encoder.encode(data, 0, encoded, 0, iters); + + // nocommit: must write longs to match CPUs endian-ness; + // this is hack to match x86 (little endian), opposite + // of DataOutput.writeLong. To do this in general we'd + // need to know the endianness of the processor + for(int i=0;iPackedInts.COMPACT */ + public NativeMMapPostingsWriter(SegmentWriteState state) throws IOException { + this(state, PackedInts.COMPACT); + } + + final static class IntBlockTermState extends BlockTermState { + long docStartFP = 0; + long posStartFP = 0; + long payStartFP = 0; + long skipOffset = -1; + long lastPosBlockOffset = -1; + // docid when there is a single pulsed posting, otherwise -1 + // freq is always implicitly totalTermFreq in this case. + int singletonDocID = -1; + + @Override + public IntBlockTermState clone() { + IntBlockTermState other = new IntBlockTermState(); + other.copyFrom(this); + return other; + } + + @Override + public void copyFrom(TermState _other) { + super.copyFrom(_other); + IntBlockTermState other = (IntBlockTermState) _other; + docStartFP = other.docStartFP; + posStartFP = other.posStartFP; + payStartFP = other.payStartFP; + lastPosBlockOffset = other.lastPosBlockOffset; + skipOffset = other.skipOffset; + singletonDocID = other.singletonDocID; + } + + + @Override + public String toString() { + return super.toString() + " docStartFP=" + docStartFP + " posStartFP=" + posStartFP + " payStartFP=" + payStartFP + " lastPosBlockOffset=" + lastPosBlockOffset + " singletonDocID=" + singletonDocID; + } + } + + @Override + public IntBlockTermState newTermState() { + return new IntBlockTermState(); + } + + @Override + public void init(IndexOutput termsOut) throws IOException { + CodecUtil.writeHeader(termsOut, TERMS_CODEC, VERSION_CURRENT); + termsOut.writeVInt(BLOCK_SIZE); + } + + @Override + public int setField(FieldInfo fieldInfo) { + super.setField(fieldInfo); + skipWriter.setField(writePositions, writeOffsets, writePayloads); + lastState = emptyState; + if (writePositions) { + if (writePayloads || writeOffsets) { + return 3; // doc + pos + pay FP + } else { + return 2; // doc + pos FP + } + } else { + return 1; // doc FP + } + } + + @Override + public void startTerm() { + docStartFP = docOut.getFilePointer(); + if (writePositions) { + posStartFP = posOut.getFilePointer(); + if (writePayloads || writeOffsets) { + payStartFP = payOut.getFilePointer(); + } + } + lastDocID = 0; + lastBlockDocID = -1; + // if (DEBUG) { + // System.out.println("FPW.startTerm startFP=" + docStartFP); + // } + skipWriter.resetSkip(); + } + + @Override + public void startDoc(int docID, int termDocFreq) throws IOException { + // if (DEBUG) { + // System.out.println("FPW.startDoc docID["+docBufferUpto+"]=" + docID); + // } + // Have collected a block of docs, and get a new doc. + // Should write skip data as well as postings list for + // current block. + if (lastBlockDocID != -1 && docBufferUpto == 0) { + // if (DEBUG) { + // System.out.println(" bufferSkip at writeBlock: lastDocID=" + lastBlockDocID + " docCount=" + (docCount-1)); + // } + skipWriter.bufferSkip(lastBlockDocID, docCount, lastBlockPosFP, lastBlockPayFP, lastBlockPosBufferUpto, lastBlockPayloadByteUpto); + } + + final int docDelta = docID - lastDocID; + + if (docID < 0 || (docCount > 0 && docDelta <= 0)) { + throw new CorruptIndexException("docs out of order (" + docID + " <= " + lastDocID + " ) (docOut: " + docOut + ")"); + } + + docDeltaBuffer[docBufferUpto] = docDelta; + // if (DEBUG) { + // System.out.println(" docDeltaBuffer[" + docBufferUpto + "]=" + docDelta); + // } + if (writeFreqs) { + freqBuffer[docBufferUpto] = termDocFreq; + } + docBufferUpto++; + docCount++; + + if (docBufferUpto == BLOCK_SIZE) { + // if (DEBUG) { + // System.out.println(" write docDelta block @ fp=" + docOut.getFilePointer()); + // } + forUtil.writeBlock(docDeltaBuffer, encoded, docOut); + if (writeFreqs) { + // if (DEBUG) { + // System.out.println(" write freq block @ fp=" + docOut.getFilePointer()); + // } + forUtil.writeBlock(freqBuffer, encoded, docOut); + } + // NOTE: don't set docBufferUpto back to 0 here; + // finishDoc will do so (because it needs to see that + // the block was filled so it can save skip data) + } + + + lastDocID = docID; + lastPosition = 0; + lastStartOffset = 0; + } + + @Override + public void addPosition(int position, BytesRef payload, int startOffset, int endOffset) throws IOException { + // if (DEBUG) { + // System.out.println("FPW.addPosition pos=" + position + " posBufferUpto=" + posBufferUpto + (writePayloads ? " payloadByteUpto=" + payloadByteUpto: "")); + // } + posDeltaBuffer[posBufferUpto] = position - lastPosition; + if (writePayloads) { + if (payload == null || payload.length == 0) { + // no payload + payloadLengthBuffer[posBufferUpto] = 0; + } else { + payloadLengthBuffer[posBufferUpto] = payload.length; + if (payloadByteUpto + payload.length > payloadBytes.length) { + payloadBytes = ArrayUtil.grow(payloadBytes, payloadByteUpto + payload.length); + } + System.arraycopy(payload.bytes, payload.offset, payloadBytes, payloadByteUpto, payload.length); + payloadByteUpto += payload.length; + } + } + + if (writeOffsets) { + assert startOffset >= lastStartOffset; + assert endOffset >= startOffset; + offsetStartDeltaBuffer[posBufferUpto] = startOffset - lastStartOffset; + offsetLengthBuffer[posBufferUpto] = endOffset - startOffset; + lastStartOffset = startOffset; + } + + posBufferUpto++; + lastPosition = position; + if (posBufferUpto == BLOCK_SIZE) { + // if (DEBUG) { + // System.out.println(" write pos bulk block @ fp=" + posOut.getFilePointer()); + // } + forUtil.writeBlock(posDeltaBuffer, encoded, posOut); + + if (writePayloads) { + forUtil.writeBlock(payloadLengthBuffer, encoded, payOut); + payOut.writeVInt(payloadByteUpto); + payOut.writeBytes(payloadBytes, 0, payloadByteUpto); + payloadByteUpto = 0; + } + if (writeOffsets) { + forUtil.writeBlock(offsetStartDeltaBuffer, encoded, payOut); + forUtil.writeBlock(offsetLengthBuffer, encoded, payOut); + } + posBufferUpto = 0; + } + } + + @Override + public void finishDoc() throws IOException { + // Since we don't know df for current term, we had to buffer + // those skip data for each block, and when a new doc comes, + // write them to skip file. + if (docBufferUpto == BLOCK_SIZE) { + lastBlockDocID = lastDocID; + if (posOut != null) { + if (payOut != null) { + lastBlockPayFP = payOut.getFilePointer(); + } + lastBlockPosFP = posOut.getFilePointer(); + lastBlockPosBufferUpto = posBufferUpto; + lastBlockPayloadByteUpto = payloadByteUpto; + } + // if (DEBUG) { + // System.out.println(" docBufferUpto="+docBufferUpto+" now get lastBlockDocID="+lastBlockDocID+" lastBlockPosFP=" + lastBlockPosFP + " lastBlockPosBufferUpto=" + lastBlockPosBufferUpto + " lastBlockPayloadByteUpto=" + lastBlockPayloadByteUpto); + // } + docBufferUpto = 0; + } + } + + /** Called when we are done adding docs to this term */ + @Override + public void finishTerm(BlockTermState _state) throws IOException { + IntBlockTermState state = (IntBlockTermState) _state; + assert state.docFreq > 0; + + // TODO: wasteful we are counting this (counting # docs + // for this term) in two places? + assert state.docFreq == docCount: state.docFreq + " vs " + docCount; + + // if (DEBUG) { + // System.out.println("FPW.finishTerm docFreq=" + state.docFreq); + // } + + // if (DEBUG) { + // if (docBufferUpto > 0) { + // System.out.println(" write doc/freq vInt block (count=" + docBufferUpto + ") at fp=" + docOut.getFilePointer() + " docStartFP=" + docStartFP); + // } + // } + + // docFreq == 1, don't write the single docid/freq to a separate file along with a pointer to it. + final int singletonDocID; + if (state.docFreq == 1) { + // pulse the singleton docid into the term dictionary, freq is implicitly totalTermFreq + singletonDocID = docDeltaBuffer[0]; + } else { + singletonDocID = -1; + // vInt encode the remaining doc deltas and freqs: + for(int i=0;i 0) { + // System.out.println(" write pos vInt block (count=" + posBufferUpto + ") at fp=" + posOut.getFilePointer() + " posStartFP=" + posStartFP + " hasPayloads=" + writePayloads + " hasOffsets=" + writeOffsets); + // } + // } + + // totalTermFreq is just total number of positions(or payloads, or offsets) + // associated with current term. + assert state.totalTermFreq != -1; + if (state.totalTermFreq > BLOCK_SIZE) { + // record file offset for last pos in last block + lastPosBlockOffset = posOut.getFilePointer() - posStartFP; + } else { + lastPosBlockOffset = -1; + } + if (posBufferUpto > 0) { + // TODO: should we send offsets/payloads to + // .pay...? seems wasteful (have to store extra + // vLong for low (< BLOCK_SIZE) DF terms = vast vast + // majority) + + // vInt encode the remaining positions/payloads/offsets: + int lastPayloadLength = -1; // force first payload length to be written + int lastOffsetLength = -1; // force first offset length to be written + int payloadBytesReadUpto = 0; + for(int i=0;i>> 1; + if ((code & 1) != 0) { + freqBuffer[i] = 1; + } else { + freqBuffer[i] = docIn.readVInt(); + } + } + } else { + for(int i=0;i= 0; + final boolean fieldHasOffsets = fieldInfo.getIndexOptions().compareTo(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS) >= 0; + final boolean fieldHasPayloads = fieldInfo.hasPayloads(); + + if (absolute) { + termState.docStartFP = 0; + termState.posStartFP = 0; + termState.payStartFP = 0; + } + if (version < NativeMMapPostingsWriter.VERSION_META_ARRAY) { // backward compatibility + _decodeTerm(in, fieldInfo, termState); + return; + } + termState.docStartFP += longs[0]; + if (fieldHasPositions) { + termState.posStartFP += longs[1]; + if (fieldHasOffsets || fieldHasPayloads) { + termState.payStartFP += longs[2]; + } + } + if (termState.docFreq == 1) { + termState.singletonDocID = in.readVInt(); + } else { + termState.singletonDocID = -1; + } + if (fieldHasPositions) { + if (termState.totalTermFreq > BLOCK_SIZE) { + termState.lastPosBlockOffset = in.readVLong(); + } else { + termState.lastPosBlockOffset = -1; + } + } + if (termState.docFreq > BLOCK_SIZE) { + termState.skipOffset = in.readVLong(); + } else { + termState.skipOffset = -1; + } + } + private void _decodeTerm(DataInput in, FieldInfo fieldInfo, IntBlockTermState termState) throws IOException { + final boolean fieldHasPositions = fieldInfo.getIndexOptions().compareTo(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS) >= 0; + final boolean fieldHasOffsets = fieldInfo.getIndexOptions().compareTo(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS) >= 0; + final boolean fieldHasPayloads = fieldInfo.hasPayloads(); + if (termState.docFreq == 1) { + termState.singletonDocID = in.readVInt(); + } else { + termState.singletonDocID = -1; + termState.docStartFP += in.readVLong(); + } + if (fieldHasPositions) { + termState.posStartFP += in.readVLong(); + if (termState.totalTermFreq > BLOCK_SIZE) { + termState.lastPosBlockOffset = in.readVLong(); + } else { + termState.lastPosBlockOffset = -1; + } + if ((fieldHasPayloads || fieldHasOffsets) && termState.totalTermFreq >= BLOCK_SIZE) { + termState.payStartFP += in.readVLong(); + } + } + if (termState.docFreq > BLOCK_SIZE) { + termState.skipOffset = in.readVLong(); + } else { + termState.skipOffset = -1; + } + } + + @Override + public DocsEnum docs(FieldInfo fieldInfo, BlockTermState termState, Bits liveDocs, DocsEnum reuse, int flags) throws IOException { + BlockDocsEnum docsEnum; + if (reuse instanceof BlockDocsEnum) { + docsEnum = (BlockDocsEnum) reuse; + if (!docsEnum.canReuse(docIn, fieldInfo)) { + docsEnum = new BlockDocsEnum(fieldInfo); + } + } else { + docsEnum = new BlockDocsEnum(fieldInfo); + } + return docsEnum.reset(liveDocs, (IntBlockTermState) termState, flags); + } + + // TODO: specialize to liveDocs vs not + + @Override + public DocsAndPositionsEnum docsAndPositions(FieldInfo fieldInfo, BlockTermState termState, Bits liveDocs, + DocsAndPositionsEnum reuse, int flags) + throws IOException { + + boolean indexHasOffsets = fieldInfo.getIndexOptions().compareTo(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS) >= 0; + boolean indexHasPayloads = fieldInfo.hasPayloads(); + + if ((!indexHasOffsets || (flags & DocsAndPositionsEnum.FLAG_OFFSETS) == 0) && + (!indexHasPayloads || (flags & DocsAndPositionsEnum.FLAG_PAYLOADS) == 0)) { + BlockDocsAndPositionsEnum docsAndPositionsEnum; + if (reuse instanceof BlockDocsAndPositionsEnum) { + docsAndPositionsEnum = (BlockDocsAndPositionsEnum) reuse; + if (!docsAndPositionsEnum.canReuse(docIn, fieldInfo)) { + docsAndPositionsEnum = new BlockDocsAndPositionsEnum(fieldInfo); + } + } else { + docsAndPositionsEnum = new BlockDocsAndPositionsEnum(fieldInfo); + } + return docsAndPositionsEnum.reset(liveDocs, (IntBlockTermState) termState); + } else { + EverythingEnum everythingEnum; + if (reuse instanceof EverythingEnum) { + everythingEnum = (EverythingEnum) reuse; + if (!everythingEnum.canReuse(docIn, fieldInfo)) { + everythingEnum = new EverythingEnum(fieldInfo); + } + } else { + everythingEnum = new EverythingEnum(fieldInfo); + } + return everythingEnum.reset(liveDocs, (IntBlockTermState) termState, flags); + } + } + + final class BlockDocsEnum extends DocsEnum { + + private final int[] docDeltaBuffer = new int[MAX_DATA_SIZE]; + private final int[] freqBuffer = new int[MAX_DATA_SIZE]; + + private int docBufferUpto; + + private NativeMMapSkipReader skipper; + private boolean skipped; + + final IndexInput startDocIn; + + NativeMMapIndexInput docIn; + final boolean indexHasFreq; + final boolean indexHasPos; + final boolean indexHasOffsets; + final boolean indexHasPayloads; + + private int docFreq; // number of docs in this posting list + private long totalTermFreq; // sum of freqs in this posting list (or docFreq when omitted) + private int docUpto; // how many docs we've read + private int doc; // doc we last read + private int accum; // accumulator for doc deltas + private int freq; // freq we last read + + // Where this term's postings start in the .doc file: + private long docTermStartFP; + + // Where this term's skip data starts (after + // docTermStartFP) in the .doc file (or -1 if there is + // no skip data for this term): + private long skipOffset; + + // docID for next skip point, we won't use skipper if + // target docID is not larger than this + private int nextSkipDoc; + + private Bits liveDocs; + + private boolean needsFreq; // true if the caller actually needs frequencies + private int singletonDocID; // docid when there is a single pulsed posting, otherwise -1 + + public BlockDocsEnum(FieldInfo fieldInfo) throws IOException { + this.startDocIn = NativeMMapPostingsReader.this.docIn; + this.docIn = null; + indexHasFreq = fieldInfo.getIndexOptions().compareTo(IndexOptions.DOCS_AND_FREQS) >= 0; + indexHasPos = fieldInfo.getIndexOptions().compareTo(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS) >= 0; + indexHasOffsets = fieldInfo.getIndexOptions().compareTo(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS) >= 0; + indexHasPayloads = fieldInfo.hasPayloads(); + } + + public boolean canReuse(IndexInput docIn, FieldInfo fieldInfo) { + return docIn == startDocIn && + indexHasFreq == (fieldInfo.getIndexOptions().compareTo(IndexOptions.DOCS_AND_FREQS) >= 0) && + indexHasPos == (fieldInfo.getIndexOptions().compareTo(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS) >= 0) && + indexHasPayloads == fieldInfo.hasPayloads(); + } + + public DocsEnum reset(Bits liveDocs, IntBlockTermState termState, int flags) throws IOException { + this.liveDocs = liveDocs; + // if (DEBUG) { + // System.out.println(" FPR.reset: termState=" + termState); + // } + docFreq = termState.docFreq; + totalTermFreq = indexHasFreq ? termState.totalTermFreq : docFreq; + docTermStartFP = termState.docStartFP; + skipOffset = termState.skipOffset; + singletonDocID = termState.singletonDocID; + if (docFreq > 1) { + if (docIn == null) { + // lazy init + docIn = (NativeMMapIndexInput) startDocIn.clone(); + } + docIn.seek(docTermStartFP); + } + + doc = -1; + this.needsFreq = (flags & DocsEnum.FLAG_FREQS) != 0; + if (!indexHasFreq) { + Arrays.fill(freqBuffer, 1); + } + accum = 0; + docUpto = 0; + nextSkipDoc = BLOCK_SIZE - 1; // we won't skip if target is found in first block + docBufferUpto = BLOCK_SIZE; + skipped = false; + return this; + } + + @Override + public int freq() throws IOException { + return freq; + } + + @Override + public int docID() { + return doc; + } + + private void refillDocs() throws IOException { + final int left = docFreq - docUpto; + assert left > 0; + + if (left >= BLOCK_SIZE) { + // if (DEBUG) { + // System.out.println(" fill doc block from fp=" + docIn.getFilePointer()); + // } + forUtil.readBlock(docIn, docDeltaBuffer); + + if (indexHasFreq) { + // if (DEBUG) { + // System.out.println(" fill freq block from fp=" + docIn.getFilePointer()); + // } + if (needsFreq) { + forUtil.readBlock(docIn, freqBuffer); + } else { + forUtil.skipBlock(docIn); // skip over freqs + } + } + } else if (docFreq == 1) { + docDeltaBuffer[0] = singletonDocID; + freqBuffer[0] = (int) totalTermFreq; + } else { + // Read vInts: + // if (DEBUG) { + // System.out.println(" fill last vInt block from fp=" + docIn.getFilePointer()); + // } + readVIntBlock(docIn, docDeltaBuffer, freqBuffer, left, indexHasFreq); + } + docBufferUpto = 0; + } + + @Override + public int nextDoc() throws IOException { + // if (DEBUG) { + // System.out.println("\nFPR.nextDoc"); + // } + while (true) { + // if (DEBUG) { + // System.out.println(" docUpto=" + docUpto + " (of df=" + docFreq + ") docBufferUpto=" + docBufferUpto); + // } + + if (docUpto == docFreq) { + // if (DEBUG) { + // System.out.println(" return doc=END"); + // } + return doc = NO_MORE_DOCS; + } + if (docBufferUpto == BLOCK_SIZE) { + refillDocs(); + } + + // if (DEBUG) { + // System.out.println(" accum=" + accum + " docDeltaBuffer[" + docBufferUpto + "]=" + docDeltaBuffer[docBufferUpto]); + // } + accum += docDeltaBuffer[docBufferUpto]; + docUpto++; + + if (liveDocs == null || liveDocs.get(accum)) { + doc = accum; + freq = freqBuffer[docBufferUpto]; + docBufferUpto++; + // if (DEBUG) { + // System.out.println(" return doc=" + doc + " freq=" + freq); + // } + return doc; + } + // if (DEBUG) { + // System.out.println(" doc=" + accum + " is deleted; try next doc"); + // } + docBufferUpto++; + } + } + + @Override + public int advance(int target) throws IOException { + // TODO: make frq block load lazy/skippable + // if (DEBUG) { + // System.out.println(" FPR.advance target=" + target); + // } + + // current skip docID < docIDs generated from current buffer <= next skip docID + // we don't need to skip if target is buffered already + if (docFreq > BLOCK_SIZE && target > nextSkipDoc) { + + // if (DEBUG) { + // System.out.println("load skipper"); + // } + + if (skipper == null) { + // Lazy init: first time this enum has ever been used for skipping + skipper = new NativeMMapSkipReader(docIn.clone(), + NativeMMapPostingsWriter.maxSkipLevels, + BLOCK_SIZE, + indexHasPos, + indexHasOffsets, + indexHasPayloads); + } + + if (!skipped) { + assert skipOffset != -1; + // This is the first time this enum has skipped + // since reset() was called; load the skip data: + skipper.init(docTermStartFP+skipOffset, docTermStartFP, 0, 0, docFreq); + skipped = true; + } + + // always plus one to fix the result, since skip position in NativeMMapSkipReader + // is a little different from MultiLevelSkipListReader + final int newDocUpto = skipper.skipTo(target) + 1; + + if (newDocUpto > docUpto) { + // Skipper moved + // if (DEBUG) { + // System.out.println("skipper moved to docUpto=" + newDocUpto + " vs current=" + docUpto + "; docID=" + skipper.getDoc() + " fp=" + skipper.getDocPointer()); + // } + assert newDocUpto % BLOCK_SIZE == 0 : "got " + newDocUpto; + docUpto = newDocUpto; + + // Force to read next block + docBufferUpto = BLOCK_SIZE; + accum = skipper.getDoc(); // actually, this is just lastSkipEntry + docIn.seek(skipper.getDocPointer()); // now point to the block we want to search + } + // next time we call advance, this is used to + // foresee whether skipper is necessary. + nextSkipDoc = skipper.getNextSkipDoc(); + } + if (docUpto == docFreq) { + return doc = NO_MORE_DOCS; + } + if (docBufferUpto == BLOCK_SIZE) { + refillDocs(); + } + + // Now scan... this is an inlined/pared down version + // of nextDoc(): + while (true) { + // if (DEBUG) { + // System.out.println(" scan doc=" + accum + " docBufferUpto=" + docBufferUpto); + // } + accum += docDeltaBuffer[docBufferUpto]; + docUpto++; + + if (accum >= target) { + break; + } + docBufferUpto++; + if (docUpto == docFreq) { + return doc = NO_MORE_DOCS; + } + } + + if (liveDocs == null || liveDocs.get(accum)) { + // if (DEBUG) { + // System.out.println(" return doc=" + accum); + // } + freq = freqBuffer[docBufferUpto]; + docBufferUpto++; + return doc = accum; + } else { + // if (DEBUG) { + // System.out.println(" now do nextDoc()"); + // } + docBufferUpto++; + return nextDoc(); + } + } + + @Override + public long cost() { + return docFreq; + } + } + + + final class BlockDocsAndPositionsEnum extends DocsAndPositionsEnum { + + private final int[] docDeltaBuffer = new int[MAX_DATA_SIZE]; + private final int[] freqBuffer = new int[MAX_DATA_SIZE]; + private final int[] posDeltaBuffer = new int[MAX_DATA_SIZE]; + + private int docBufferUpto; + private int posBufferUpto; + + private NativeMMapSkipReader skipper; + private boolean skipped; + + final IndexInput startDocIn; + + NativeMMapIndexInput docIn; + final NativeMMapIndexInput posIn; + + final boolean indexHasOffsets; + final boolean indexHasPayloads; + + private int docFreq; // number of docs in this posting list + private long totalTermFreq; // number of positions in this posting list + private int docUpto; // how many docs we've read + private int doc; // doc we last read + private int accum; // accumulator for doc deltas + private int freq; // freq we last read + private int position; // current position + + // how many positions "behind" we are; nextPosition must + // skip these to "catch up": + private int posPendingCount; + + // Lazy pos seek: if != -1 then we must seek to this FP + // before reading positions: + private long posPendingFP; + + // Where this term's postings start in the .doc file: + private long docTermStartFP; + + // Where this term's postings start in the .pos file: + private long posTermStartFP; + + // Where this term's payloads/offsets start in the .pay + // file: + private long payTermStartFP; + + // File pointer where the last (vInt encoded) pos delta + // block is. We need this to know whether to bulk + // decode vs vInt decode the block: + private long lastPosBlockFP; + + // Where this term's skip data starts (after + // docTermStartFP) in the .doc file (or -1 if there is + // no skip data for this term): + private long skipOffset; + + private int nextSkipDoc; + + private Bits liveDocs; + private int singletonDocID; // docid when there is a single pulsed posting, otherwise -1 + + public BlockDocsAndPositionsEnum(FieldInfo fieldInfo) throws IOException { + this.startDocIn = NativeMMapPostingsReader.this.docIn; + this.docIn = null; + this.posIn = (NativeMMapIndexInput) NativeMMapPostingsReader.this.posIn.clone(); + indexHasOffsets = fieldInfo.getIndexOptions().compareTo(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS) >= 0; + indexHasPayloads = fieldInfo.hasPayloads(); + } + + public boolean canReuse(IndexInput docIn, FieldInfo fieldInfo) { + return docIn == startDocIn && + indexHasOffsets == (fieldInfo.getIndexOptions().compareTo(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS) >= 0) && + indexHasPayloads == fieldInfo.hasPayloads(); + } + + public DocsAndPositionsEnum reset(Bits liveDocs, IntBlockTermState termState) throws IOException { + this.liveDocs = liveDocs; + // if (DEBUG) { + // System.out.println(" FPR.reset: termState=" + termState); + // } + docFreq = termState.docFreq; + docTermStartFP = termState.docStartFP; + posTermStartFP = termState.posStartFP; + payTermStartFP = termState.payStartFP; + skipOffset = termState.skipOffset; + totalTermFreq = termState.totalTermFreq; + singletonDocID = termState.singletonDocID; + if (docFreq > 1) { + if (docIn == null) { + // lazy init + docIn = (NativeMMapIndexInput) startDocIn.clone(); + } + docIn.seek(docTermStartFP); + } + posPendingFP = posTermStartFP; + posPendingCount = 0; + if (termState.totalTermFreq < BLOCK_SIZE) { + lastPosBlockFP = posTermStartFP; + } else if (termState.totalTermFreq == BLOCK_SIZE) { + lastPosBlockFP = -1; + } else { + lastPosBlockFP = posTermStartFP + termState.lastPosBlockOffset; + } + + doc = -1; + accum = 0; + docUpto = 0; + nextSkipDoc = BLOCK_SIZE - 1; + docBufferUpto = BLOCK_SIZE; + skipped = false; + return this; + } + + @Override + public int freq() throws IOException { + return freq; + } + + @Override + public int docID() { + return doc; + } + + private void refillDocs() throws IOException { + final int left = docFreq - docUpto; + assert left > 0; + + if (left >= BLOCK_SIZE) { + // if (DEBUG) { + // System.out.println(" fill doc block from fp=" + docIn.getFilePointer()); + // } + forUtil.readBlock(docIn, docDeltaBuffer); + // if (DEBUG) { + // System.out.println(" fill freq block from fp=" + docIn.getFilePointer()); + // } + forUtil.readBlock(docIn, freqBuffer); + } else if (docFreq == 1) { + docDeltaBuffer[0] = singletonDocID; + freqBuffer[0] = (int) totalTermFreq; + } else { + // Read vInts: + // if (DEBUG) { + // System.out.println(" fill last vInt doc block from fp=" + docIn.getFilePointer()); + // } + readVIntBlock(docIn, docDeltaBuffer, freqBuffer, left, true); + } + docBufferUpto = 0; + } + + private void refillPositions() throws IOException { + // if (DEBUG) { + // System.out.println(" refillPositions"); + // } + if (posIn.getFilePointer() == lastPosBlockFP) { + // if (DEBUG) { + // System.out.println(" vInt pos block @ fp=" + posIn.getFilePointer() + " hasPayloads=" + indexHasPayloads + " hasOffsets=" + indexHasOffsets); + // } + final int count = (int) (totalTermFreq % BLOCK_SIZE); + int payloadLength = 0; + for(int i=0;i>> 1; + if (payloadLength != 0) { + posIn.seek(posIn.getFilePointer() + payloadLength); + } + } else { + posDeltaBuffer[i] = code; + } + if (indexHasOffsets) { + if ((posIn.readVInt() & 1) != 0) { + // offset length changed + posIn.readVInt(); + } + } + } + } else { + // if (DEBUG) { + // System.out.println(" bulk pos block @ fp=" + posIn.getFilePointer()); + // } + forUtil.readBlock(posIn, posDeltaBuffer); + } + } + + @Override + public int nextDoc() throws IOException { + // if (DEBUG) { + // System.out.println(" FPR.nextDoc"); + // } + while (true) { + // if (DEBUG) { + // System.out.println(" docUpto=" + docUpto + " (of df=" + docFreq + ") docBufferUpto=" + docBufferUpto); + // } + if (docUpto == docFreq) { + return doc = NO_MORE_DOCS; + } + if (docBufferUpto == BLOCK_SIZE) { + refillDocs(); + } + // if (DEBUG) { + // System.out.println(" accum=" + accum + " docDeltaBuffer[" + docBufferUpto + "]=" + docDeltaBuffer[docBufferUpto]); + // } + accum += docDeltaBuffer[docBufferUpto]; + freq = freqBuffer[docBufferUpto]; + posPendingCount += freq; + docBufferUpto++; + docUpto++; + + if (liveDocs == null || liveDocs.get(accum)) { + doc = accum; + position = 0; + // if (DEBUG) { + // System.out.println(" return doc=" + doc + " freq=" + freq + " posPendingCount=" + posPendingCount); + // } + return doc; + } + // if (DEBUG) { + // System.out.println(" doc=" + accum + " is deleted; try next doc"); + // } + } + } + + @Override + public int advance(int target) throws IOException { + // TODO: make frq block load lazy/skippable + // if (DEBUG) { + // System.out.println(" FPR.advance target=" + target); + // } + + if (docFreq > BLOCK_SIZE && target > nextSkipDoc) { + // if (DEBUG) { + // System.out.println(" try skipper"); + // } + if (skipper == null) { + // Lazy init: first time this enum has ever been used for skipping + // if (DEBUG) { + // System.out.println(" create skipper"); + // } + skipper = new NativeMMapSkipReader(docIn.clone(), + NativeMMapPostingsWriter.maxSkipLevels, + BLOCK_SIZE, + true, + indexHasOffsets, + indexHasPayloads); + } + + if (!skipped) { + assert skipOffset != -1; + // This is the first time this enum has skipped + // since reset() was called; load the skip data: + // if (DEBUG) { + // System.out.println(" init skipper"); + // } + skipper.init(docTermStartFP+skipOffset, docTermStartFP, posTermStartFP, payTermStartFP, docFreq); + skipped = true; + } + + final int newDocUpto = skipper.skipTo(target) + 1; + + if (newDocUpto > docUpto) { + // Skipper moved + // if (DEBUG) { + // System.out.println(" skipper moved to docUpto=" + newDocUpto + " vs current=" + docUpto + "; docID=" + skipper.getDoc() + " fp=" + skipper.getDocPointer() + " pos.fp=" + skipper.getPosPointer() + " pos.bufferUpto=" + skipper.getPosBufferUpto()); + // } + + assert newDocUpto % BLOCK_SIZE == 0 : "got " + newDocUpto; + docUpto = newDocUpto; + + // Force to read next block + docBufferUpto = BLOCK_SIZE; + accum = skipper.getDoc(); + docIn.seek(skipper.getDocPointer()); + posPendingFP = skipper.getPosPointer(); + posPendingCount = skipper.getPosBufferUpto(); + } + nextSkipDoc = skipper.getNextSkipDoc(); + } + if (docUpto == docFreq) { + return doc = NO_MORE_DOCS; + } + if (docBufferUpto == BLOCK_SIZE) { + refillDocs(); + } + + // Now scan... this is an inlined/pared down version + // of nextDoc(): + while (true) { + // if (DEBUG) { + // System.out.println(" scan doc=" + accum + " docBufferUpto=" + docBufferUpto); + // } + accum += docDeltaBuffer[docBufferUpto]; + freq = freqBuffer[docBufferUpto]; + posPendingCount += freq; + docBufferUpto++; + docUpto++; + + if (accum >= target) { + break; + } + if (docUpto == docFreq) { + return doc = NO_MORE_DOCS; + } + } + + if (liveDocs == null || liveDocs.get(accum)) { + // if (DEBUG) { + // System.out.println(" return doc=" + accum); + // } + position = 0; + return doc = accum; + } else { + // if (DEBUG) { + // System.out.println(" now do nextDoc()"); + // } + return nextDoc(); + } + } + + // TODO: in theory we could avoid loading frq block + // when not needed, ie, use skip data to load how far to + // seek the pos pointer ... instead of having to load frq + // blocks only to sum up how many positions to skip + private void skipPositions() throws IOException { + // Skip positions now: + int toSkip = posPendingCount - freq; + // if (DEBUG) { + // System.out.println(" FPR.skipPositions: toSkip=" + toSkip); + // } + + final int leftInBlock = BLOCK_SIZE - posBufferUpto; + if (toSkip < leftInBlock) { + posBufferUpto += toSkip; + // if (DEBUG) { + // System.out.println(" skip w/in block to posBufferUpto=" + posBufferUpto); + // } + } else { + toSkip -= leftInBlock; + while(toSkip >= BLOCK_SIZE) { + // if (DEBUG) { + // System.out.println(" skip whole block @ fp=" + posIn.getFilePointer()); + // } + assert posIn.getFilePointer() != lastPosBlockFP; + forUtil.skipBlock(posIn); + toSkip -= BLOCK_SIZE; + } + refillPositions(); + posBufferUpto = toSkip; + // if (DEBUG) { + // System.out.println(" skip w/in block to posBufferUpto=" + posBufferUpto); + // } + } + + position = 0; + } + + @Override + public int nextPosition() throws IOException { + // if (DEBUG) { + // System.out.println(" FPR.nextPosition posPendingCount=" + posPendingCount + " posBufferUpto=" + posBufferUpto); + // } + if (posPendingFP != -1) { + // if (DEBUG) { + // System.out.println(" seek to pendingFP=" + posPendingFP); + // } + posIn.seek(posPendingFP); + posPendingFP = -1; + + // Force buffer refill: + posBufferUpto = BLOCK_SIZE; + } + + if (posPendingCount > freq) { + skipPositions(); + posPendingCount = freq; + } + + if (posBufferUpto == BLOCK_SIZE) { + refillPositions(); + posBufferUpto = 0; + } + position += posDeltaBuffer[posBufferUpto++]; + posPendingCount--; + // if (DEBUG) { + // System.out.println(" return pos=" + position); + // } + return position; + } + + @Override + public int startOffset() { + return -1; + } + + @Override + public int endOffset() { + return -1; + } + + @Override + public BytesRef getPayload() { + return null; + } + + @Override + public long cost() { + return docFreq; + } + } + + // Also handles payloads + offsets + final class EverythingEnum extends DocsAndPositionsEnum { + + private final int[] docDeltaBuffer = new int[MAX_DATA_SIZE]; + private final int[] freqBuffer = new int[MAX_DATA_SIZE]; + private final int[] posDeltaBuffer = new int[MAX_DATA_SIZE]; + + private final int[] payloadLengthBuffer; + private final int[] offsetStartDeltaBuffer; + private final int[] offsetLengthBuffer; + + private byte[] payloadBytes; + private int payloadByteUpto; + private int payloadLength; + + private int lastStartOffset; + private int startOffset; + private int endOffset; + + private int docBufferUpto; + private int posBufferUpto; + + private NativeMMapSkipReader skipper; + private boolean skipped; + + final IndexInput startDocIn; + + NativeMMapIndexInput docIn; + final NativeMMapIndexInput posIn; + final NativeMMapIndexInput payIn; + final BytesRef payload; + + final boolean indexHasOffsets; + final boolean indexHasPayloads; + + private int docFreq; // number of docs in this posting list + private long totalTermFreq; // number of positions in this posting list + private int docUpto; // how many docs we've read + private int doc; // doc we last read + private int accum; // accumulator for doc deltas + private int freq; // freq we last read + private int position; // current position + + // how many positions "behind" we are; nextPosition must + // skip these to "catch up": + private int posPendingCount; + + // Lazy pos seek: if != -1 then we must seek to this FP + // before reading positions: + private long posPendingFP; + + // Lazy pay seek: if != -1 then we must seek to this FP + // before reading payloads/offsets: + private long payPendingFP; + + // Where this term's postings start in the .doc file: + private long docTermStartFP; + + // Where this term's postings start in the .pos file: + private long posTermStartFP; + + // Where this term's payloads/offsets start in the .pay + // file: + private long payTermStartFP; + + // File pointer where the last (vInt encoded) pos delta + // block is. We need this to know whether to bulk + // decode vs vInt decode the block: + private long lastPosBlockFP; + + // Where this term's skip data starts (after + // docTermStartFP) in the .doc file (or -1 if there is + // no skip data for this term): + private long skipOffset; + + private int nextSkipDoc; + + private Bits liveDocs; + + private boolean needsOffsets; // true if we actually need offsets + private boolean needsPayloads; // true if we actually need payloads + private int singletonDocID; // docid when there is a single pulsed posting, otherwise -1 + + public EverythingEnum(FieldInfo fieldInfo) throws IOException { + this.startDocIn = NativeMMapPostingsReader.this.docIn; + this.docIn = null; + this.posIn = (NativeMMapIndexInput) NativeMMapPostingsReader.this.posIn.clone(); + this.payIn = (NativeMMapIndexInput) NativeMMapPostingsReader.this.payIn.clone(); + indexHasOffsets = fieldInfo.getIndexOptions().compareTo(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS) >= 0; + if (indexHasOffsets) { + offsetStartDeltaBuffer = new int[MAX_DATA_SIZE]; + offsetLengthBuffer = new int[MAX_DATA_SIZE]; + } else { + offsetStartDeltaBuffer = null; + offsetLengthBuffer = null; + startOffset = -1; + endOffset = -1; + } + + indexHasPayloads = fieldInfo.hasPayloads(); + if (indexHasPayloads) { + payloadLengthBuffer = new int[MAX_DATA_SIZE]; + payloadBytes = new byte[128]; + payload = new BytesRef(); + } else { + payloadLengthBuffer = null; + payloadBytes = null; + payload = null; + } + } + + public boolean canReuse(IndexInput docIn, FieldInfo fieldInfo) { + return docIn == startDocIn && + indexHasOffsets == (fieldInfo.getIndexOptions().compareTo(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS) >= 0) && + indexHasPayloads == fieldInfo.hasPayloads(); + } + + public EverythingEnum reset(Bits liveDocs, IntBlockTermState termState, int flags) throws IOException { + this.liveDocs = liveDocs; + // if (DEBUG) { + // System.out.println(" FPR.reset: termState=" + termState); + // } + docFreq = termState.docFreq; + docTermStartFP = termState.docStartFP; + posTermStartFP = termState.posStartFP; + payTermStartFP = termState.payStartFP; + skipOffset = termState.skipOffset; + totalTermFreq = termState.totalTermFreq; + singletonDocID = termState.singletonDocID; + if (docFreq > 1) { + if (docIn == null) { + // lazy init + docIn = (NativeMMapIndexInput) startDocIn.clone(); + } + docIn.seek(docTermStartFP); + } + posPendingFP = posTermStartFP; + payPendingFP = payTermStartFP; + posPendingCount = 0; + if (termState.totalTermFreq < BLOCK_SIZE) { + lastPosBlockFP = posTermStartFP; + } else if (termState.totalTermFreq == BLOCK_SIZE) { + lastPosBlockFP = -1; + } else { + lastPosBlockFP = posTermStartFP + termState.lastPosBlockOffset; + } + + this.needsOffsets = (flags & DocsAndPositionsEnum.FLAG_OFFSETS) != 0; + this.needsPayloads = (flags & DocsAndPositionsEnum.FLAG_PAYLOADS) != 0; + + doc = -1; + accum = 0; + docUpto = 0; + nextSkipDoc = BLOCK_SIZE - 1; + docBufferUpto = BLOCK_SIZE; + skipped = false; + return this; + } + + @Override + public int freq() throws IOException { + return freq; + } + + @Override + public int docID() { + return doc; + } + + private void refillDocs() throws IOException { + final int left = docFreq - docUpto; + assert left > 0; + + if (left >= BLOCK_SIZE) { + // if (DEBUG) { + // System.out.println(" fill doc block from fp=" + docIn.getFilePointer()); + // } + forUtil.readBlock(docIn, docDeltaBuffer); + // if (DEBUG) { + // System.out.println(" fill freq block from fp=" + docIn.getFilePointer()); + // } + forUtil.readBlock(docIn, freqBuffer); + } else if (docFreq == 1) { + docDeltaBuffer[0] = singletonDocID; + freqBuffer[0] = (int) totalTermFreq; + } else { + // if (DEBUG) { + // System.out.println(" fill last vInt doc block from fp=" + docIn.getFilePointer()); + // } + readVIntBlock(docIn, docDeltaBuffer, freqBuffer, left, true); + } + docBufferUpto = 0; + } + + private void refillPositions() throws IOException { + // if (DEBUG) { + // System.out.println(" refillPositions"); + // } + if (posIn.getFilePointer() == lastPosBlockFP) { + // if (DEBUG) { + // System.out.println(" vInt pos block @ fp=" + posIn.getFilePointer() + " hasPayloads=" + indexHasPayloads + " hasOffsets=" + indexHasOffsets); + // } + final int count = (int) (totalTermFreq % BLOCK_SIZE); + int payloadLength = 0; + int offsetLength = 0; + payloadByteUpto = 0; + for(int i=0;i docUpto) { + // Skipper moved + // if (DEBUG) { + // System.out.println(" skipper moved to docUpto=" + newDocUpto + " vs current=" + docUpto + "; docID=" + skipper.getDoc() + " fp=" + skipper.getDocPointer() + " pos.fp=" + skipper.getPosPointer() + " pos.bufferUpto=" + skipper.getPosBufferUpto() + " pay.fp=" + skipper.getPayPointer() + " lastStartOffset=" + lastStartOffset); + // } + assert newDocUpto % BLOCK_SIZE == 0 : "got " + newDocUpto; + docUpto = newDocUpto; + + // Force to read next block + docBufferUpto = BLOCK_SIZE; + accum = skipper.getDoc(); + docIn.seek(skipper.getDocPointer()); + posPendingFP = skipper.getPosPointer(); + payPendingFP = skipper.getPayPointer(); + posPendingCount = skipper.getPosBufferUpto(); + lastStartOffset = 0; // new document + payloadByteUpto = skipper.getPayloadByteUpto(); + } + nextSkipDoc = skipper.getNextSkipDoc(); + } + if (docUpto == docFreq) { + return doc = NO_MORE_DOCS; + } + if (docBufferUpto == BLOCK_SIZE) { + refillDocs(); + } + + // Now scan: + while (true) { + // if (DEBUG) { + // System.out.println(" scan doc=" + accum + " docBufferUpto=" + docBufferUpto); + // } + accum += docDeltaBuffer[docBufferUpto]; + freq = freqBuffer[docBufferUpto]; + posPendingCount += freq; + docBufferUpto++; + docUpto++; + + if (accum >= target) { + break; + } + if (docUpto == docFreq) { + return doc = NO_MORE_DOCS; + } + } + + if (liveDocs == null || liveDocs.get(accum)) { + // if (DEBUG) { + // System.out.println(" return doc=" + accum); + // } + position = 0; + lastStartOffset = 0; + return doc = accum; + } else { + // if (DEBUG) { + // System.out.println(" now do nextDoc()"); + // } + return nextDoc(); + } + } + + // TODO: in theory we could avoid loading frq block + // when not needed, ie, use skip data to load how far to + // seek the pos pointer ... instead of having to load frq + // blocks only to sum up how many positions to skip + private void skipPositions() throws IOException { + // Skip positions now: + int toSkip = posPendingCount - freq; + // if (DEBUG) { + // System.out.println(" FPR.skipPositions: toSkip=" + toSkip); + // } + + final int leftInBlock = BLOCK_SIZE - posBufferUpto; + if (toSkip < leftInBlock) { + int end = posBufferUpto + toSkip; + while(posBufferUpto < end) { + if (indexHasPayloads) { + payloadByteUpto += payloadLengthBuffer[posBufferUpto]; + } + posBufferUpto++; + } + // if (DEBUG) { + // System.out.println(" skip w/in block to posBufferUpto=" + posBufferUpto); + // } + } else { + toSkip -= leftInBlock; + while(toSkip >= BLOCK_SIZE) { + // if (DEBUG) { + // System.out.println(" skip whole block @ fp=" + posIn.getFilePointer()); + // } + assert posIn.getFilePointer() != lastPosBlockFP; + forUtil.skipBlock(posIn); + + if (indexHasPayloads) { + // Skip payloadLength block: + forUtil.skipBlock(payIn); + + // Skip payloadBytes block: + int numBytes = payIn.readVInt(); + payIn.seek(payIn.getFilePointer() + numBytes); + } + + if (indexHasOffsets) { + forUtil.skipBlock(payIn); + forUtil.skipBlock(payIn); + } + toSkip -= BLOCK_SIZE; + } + refillPositions(); + payloadByteUpto = 0; + posBufferUpto = 0; + while(posBufferUpto < toSkip) { + if (indexHasPayloads) { + payloadByteUpto += payloadLengthBuffer[posBufferUpto]; + } + posBufferUpto++; + } + // if (DEBUG) { + // System.out.println(" skip w/in block to posBufferUpto=" + posBufferUpto); + // } + } + + position = 0; + lastStartOffset = 0; + } + + @Override + public int nextPosition() throws IOException { + // if (DEBUG) { + // System.out.println(" FPR.nextPosition posPendingCount=" + posPendingCount + " posBufferUpto=" + posBufferUpto + " payloadByteUpto=" + payloadByteUpto)// ; + // } + if (posPendingFP != -1) { + // if (DEBUG) { + // System.out.println(" seek pos to pendingFP=" + posPendingFP); + // } + posIn.seek(posPendingFP); + posPendingFP = -1; + + if (payPendingFP != -1) { + // if (DEBUG) { + // System.out.println(" seek pay to pendingFP=" + payPendingFP); + // } + payIn.seek(payPendingFP); + payPendingFP = -1; + } + + // Force buffer refill: + posBufferUpto = BLOCK_SIZE; + } + + if (posPendingCount > freq) { + skipPositions(); + posPendingCount = freq; + } + + if (posBufferUpto == BLOCK_SIZE) { + refillPositions(); + posBufferUpto = 0; + } + position += posDeltaBuffer[posBufferUpto]; + + if (indexHasPayloads) { + payloadLength = payloadLengthBuffer[posBufferUpto]; + payload.bytes = payloadBytes; + payload.offset = payloadByteUpto; + payload.length = payloadLength; + payloadByteUpto += payloadLength; + } + + if (indexHasOffsets) { + startOffset = lastStartOffset + offsetStartDeltaBuffer[posBufferUpto]; + endOffset = startOffset + offsetLengthBuffer[posBufferUpto]; + lastStartOffset = startOffset; + } + + posBufferUpto++; + posPendingCount--; + // if (DEBUG) { + // System.out.println(" return pos=" + position); + // } + return position; + } + + @Override + public int startOffset() { + return startOffset; + } + + @Override + public int endOffset() { + return endOffset; + } + + @Override + public BytesRef getPayload() { + // if (DEBUG) { + // System.out.println(" FPR.getPayload payloadLength=" + payloadLength + " payloadByteUpto=" + payloadByteUpto); + // } + if (payloadLength == 0) { + return null; + } else { + return payload; + } + } + + @Override + public long cost() { + return docFreq; + } + } + + @Override + public long ramBytesUsed() { + return 0; + } + +} Property changes on: lucene/core/src/java/org/apache/lucene/codecs/nativemmap/NativeMMapPostingsReader.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property