Index: lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/JoinDocFreqValueSource.java
===================================================================
--- lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/JoinDocFreqValueSource.java	(révision 1340914)
+++ lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/JoinDocFreqValueSource.java	(copie de travail)
@@ -27,6 +27,7 @@
 import org.apache.lucene.search.FieldCache.DocTerms;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.ReaderUtil;
+import org.apache.lucene.util.packed.PackedInts;
 
 /**
  * Use a field value and find the Document Frequency within another field.
@@ -52,7 +53,7 @@
   @Override
   public FunctionValues getValues(Map context, AtomicReaderContext readerContext) throws IOException
   {
-    final DocTerms terms = cache.getTerms(readerContext.reader(), field, true );
+    final DocTerms terms = cache.getTerms(readerContext.reader(), field, PackedInts.FAST );
     final IndexReader top = ReaderUtil.getTopLevelContext(readerContext).reader();
     
     return new IntDocValues(this) {
Index: lucene/core/src/test/org/apache/lucene/codecs/lucene40/values/TestDocValues.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/codecs/lucene40/values/TestDocValues.java	(révision 1340914)
+++ lucene/core/src/test/org/apache/lucene/codecs/lucene40/values/TestDocValues.java	(copie de travail)
@@ -40,6 +40,7 @@
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.UnicodeUtil;
 import org.apache.lucene.util._TestUtil;
+import org.apache.lucene.util.packed.PackedInts;
 
 // TODO: some of this should be under lucene40 codec tests? is talking to codec directly?f
 public class TestDocValues extends LuceneTestCase {
@@ -71,7 +72,7 @@
     Directory dir = newDirectory();
     final Counter trackBytes = Counter.newCounter();
     DocValuesConsumer w = Bytes.getWriter(dir, "test", mode, fixedSize, COMP, trackBytes, newIOContext(random()),
-        random().nextBoolean());
+        random().nextFloat() * PackedInts.FAST);
     int maxDoc = 220;
     final String[] values = new String[maxDoc];
     final int fixedLength = 1 + atLeast(50);
Index: lucene/core/src/test/org/apache/lucene/index/TestIndexWriter.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/index/TestIndexWriter.java	(révision 1340914)
+++ lucene/core/src/test/org/apache/lucene/index/TestIndexWriter.java	(copie de travail)
@@ -64,6 +64,7 @@
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.ThreadInterruptedException;
 import org.apache.lucene.util._TestUtil;
+import org.apache.lucene.util.packed.PackedInts;
 
 public class TestIndexWriter extends LuceneTestCase {
 
@@ -1677,7 +1678,7 @@
     w.close();
     assertEquals(1, reader.docFreq(new Term("content", bigTerm)));
 
-    FieldCache.DocTermsIndex dti = FieldCache.DEFAULT.getTermsIndex(SlowCompositeReaderWrapper.wrap(reader), "content", random().nextBoolean());
+    FieldCache.DocTermsIndex dti = FieldCache.DEFAULT.getTermsIndex(SlowCompositeReaderWrapper.wrap(reader), "content", random().nextFloat() * PackedInts.FAST);
     assertEquals(5, dti.numOrd());                // +1 for null ord
     assertEquals(4, dti.size());
     assertEquals(bigTermBytesRef, dti.lookup(3, new BytesRef()));
Index: lucene/core/src/test/org/apache/lucene/util/packed/TestPackedInts.java
===================================================================
--- lucene/core/src/test/org/apache/lucene/util/packed/TestPackedInts.java	(révision 1340914)
+++ lucene/core/src/test/org/apache/lucene/util/packed/TestPackedInts.java	(copie de travail)
@@ -72,7 +72,7 @@
         out.close();
         {// test reader
           IndexInput in = d.openInput("out.bin", newIOContext(random()));
-          PackedInts.Reader r = PackedInts.getReader(in);
+          PackedInts.Reader r = PackedInts.getReader(in, PackedInts.DEFAULT);
           assertEquals(fp, in.getFilePointer());
           for(int i=0;i<valueCount;i++) {
             assertEquals("index=" + i + " ceil=" + ceil + " valueCount="
@@ -191,13 +191,22 @@
     if (bitsPerValue <= 31) {
       packedInts.add(new Packed32(valueCount, bitsPerValue));
     }
+    if (bitsPerValue <= 24 && valueCount <= Packed8ThreeBlocks.MAX_SIZE) {
+      packedInts.add(new Packed8ThreeBlocks(valueCount));
+    }
     if (bitsPerValue <= 32) {
       packedInts.add(new Direct32(valueCount));
     }
+    if (bitsPerValue <= 48 && valueCount <= Packed16ThreeBlocks.MAX_SIZE) {
+      packedInts.add(new Packed16ThreeBlocks(valueCount));
+    }
     if (bitsPerValue <= 63) {
       packedInts.add(new Packed64(valueCount, bitsPerValue));
     }
     packedInts.add(new Direct64(valueCount));
+    if (Packed64SingleBlock.isSupported(bitsPerValue)) {
+      packedInts.add(Packed64SingleBlock.create(valueCount, bitsPerValue));
+    }
     return packedInts;
   }
 
@@ -251,7 +260,7 @@
     out.close();
 
     IndexInput in = dir.openInput("out", newIOContext(random()));
-    PackedInts.getReader(in);
+    PackedInts.getReader(in, PackedInts.DEFAULT);
     assertEquals(end, in.getFilePointer());
     in.close();
 
@@ -286,5 +295,31 @@
     p64.set(INDEX-1, 1);
     assertEquals("The value at position " + (INDEX-1)
         + " should be correct for Packed64", 1, p64.get(INDEX-1));
+    p64 = null;
+
+    for (int bits = 1; bits <=64; ++bits) {
+      if (Packed64SingleBlock.isSupported(bits)) {
+        int index = Integer.MAX_VALUE / bits + (bits == 1 ? 0 : 1);
+        Packed64SingleBlock p64sb = Packed64SingleBlock.create(index, bits);
+        p64sb.set(index - 1, 1);
+        assertEquals("The value at position " + (index-1)
+            + " should be correct for " + p64sb.getClass().getSimpleName(),
+            1, p64sb.get(index-1));
+      }
+    }
+    
+    int index = Integer.MAX_VALUE / 24 + 1;
+    Packed8ThreeBlocks p8 = new Packed8ThreeBlocks(index);
+    p8.set(index - 1, 1);
+    assertEquals("The value at position " + (index-1)
+        + " should be correct for Packed8ThreeBlocks", 1, p8.get(index-1));
+    p8 = null;
+    
+    index = Integer.MAX_VALUE / 48 + 1;
+    Packed16ThreeBlocks p16 = new Packed16ThreeBlocks(index);
+    p16.set(index - 1, 1);
+    assertEquals("The value at position " + (index-1)
+        + " should be correct for Packed16ThreeBlocks", 1, p16.get(index-1));
+    p16 = null;
   }
 }
Index: lucene/core/src/java/org/apache/lucene/util/packed/Packed64SingleBlock.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/util/packed/Packed64SingleBlock.java	(révision 0)
+++ lucene/core/src/java/org/apache/lucene/util/packed/Packed64SingleBlock.java	(révision 0)
@@ -0,0 +1,362 @@
+package org.apache.lucene.util.packed;
+
+import java.util.Arrays;
+
+import org.apache.lucene.util.RamUsageEstimator;
+
+/**
+ * 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.
+ */
+
+/**
+ * This class is similar to {@link Packed64} except that it trades space for
+ * speed by ensuring that a single block needs to be read in order to read/write
+ * a value.
+ */
+abstract class Packed64SingleBlock extends PackedInts.ReaderImpl implements
+    PackedInts.Mutable {
+
+  private static final int[] SUPPORTED_BITS_PER_VALUE = new int[] {1, 2, 3, 4, 5, 6, 7, 9, 10, 12, 21};
+  private static final long[][] WRITE_MASKS = new long[22][];
+  private static final int[][] SHIFTS = new int[22][];
+  static {
+    for (int bpv : SUPPORTED_BITS_PER_VALUE) {
+      initMasks(bpv);
+    }
+  }
+
+  protected static void initMasks(int bpv) {
+    int valuesPerBlock = Long.SIZE / bpv;
+    long[] writeMasks = new long[valuesPerBlock];
+    int[] shifts = new int[valuesPerBlock];
+    long bits = (1L << bpv) - 1;
+    for (int i = 0; i < valuesPerBlock; ++i) {
+      shifts[i] = bpv * i;
+      writeMasks[i] = ~(bits << shifts[i]);
+    }
+    WRITE_MASKS[bpv] = writeMasks;
+    SHIFTS[bpv] = shifts;
+  }
+
+  public static Packed64SingleBlock create(int valueCount, int bitsPerValue) {
+    switch (bitsPerValue) {
+      case 1:
+        return new Packed64SingleBlock1(valueCount);
+      case 2:
+        return new Packed64SingleBlock2(valueCount);
+      case 3:
+        return new Packed64SingleBlock3(valueCount);
+      case 4:
+        return new Packed64SingleBlock4(valueCount);
+      case 5:
+        return new Packed64SingleBlock5(valueCount);
+      case 6:
+        return new Packed64SingleBlock6(valueCount);
+      case 7:
+        return new Packed64SingleBlock7(valueCount);
+      case 9:
+        return new Packed64SingleBlock9(valueCount);
+      case 10:
+        return new Packed64SingleBlock10(valueCount);
+      case 12:
+        return new Packed64SingleBlock12(valueCount);
+      case 21:
+        return new Packed64SingleBlock21(valueCount);
+      default:
+        throw new IllegalArgumentException("Unsupported bitsPerValue: " + bitsPerValue);
+    }
+  }
+  
+  public static boolean isSupported(int bitsPerValue) {
+    return Arrays.binarySearch(SUPPORTED_BITS_PER_VALUE, bitsPerValue) >= 0;
+  }
+
+  public static float overheadPerValue(int bitsPerValue) {
+    int valuesPerBlock = 64 / bitsPerValue;
+    int overhead = 64 % bitsPerValue;
+    return (float) overhead / valuesPerBlock;
+  }
+
+  private final long[] blocks;
+  protected final int valuesPerBlock;
+  private final int[] shifts;
+  private final long[] writeMasks;
+  private final long readMask;
+
+  Packed64SingleBlock(int valueCount, int bitsPerValue) {
+    super(valueCount, bitsPerValue);
+    valuesPerBlock = Long.SIZE / bitsPerValue;
+    blocks = new long[requiredCapacity(valueCount, valuesPerBlock)];
+    shifts = SHIFTS[bitsPerValue];
+    writeMasks = WRITE_MASKS[bitsPerValue];
+    readMask = ~writeMasks[0];
+  }
+
+  private static int requiredCapacity(int valueCount, int valuesPerBlock) {
+    return valueCount / valuesPerBlock + (valueCount % valuesPerBlock == 0 ? 0 : 1);
+  }
+
+  protected int blockOffset(int offset) {
+    return offset / valuesPerBlock;
+  }
+
+  protected int offsetInBlock(int offset) {
+    return offset % valuesPerBlock;
+  }
+
+  @Override
+  public long get(int index) {
+    final int o = blockOffset(index);
+    final int b = offsetInBlock(index);
+
+    return (blocks[o] >> shifts[b]) & readMask;
+  }
+
+  @Override
+  public void set(int index, long value) {
+    final int o = blockOffset(index);
+    final int b = offsetInBlock(index);
+
+    blocks[o] = (blocks[o] & writeMasks[b]) | (value << shifts[b]);
+  }
+
+  @Override
+  public void clear() {
+    Arrays.fill(blocks, 0L);
+  }
+
+  public long ramBytesUsed() {
+    return RamUsageEstimator.sizeOf(blocks);
+  }
+
+  @Override
+  public String toString() {
+    return "PackedSingleBlock64(bitsPerValue=" + bitsPerValue + ", size="
+        + size() + ", elements.length=" + blocks.length + ")";
+  }
+
+  //Specialisations that allow the JVM to optimize computation of the block
+  //offset as well as the offset in block
+  
+  static final class Packed64SingleBlock21 extends Packed64SingleBlock {
+  
+   Packed64SingleBlock21(int valueCount) {
+     super(valueCount, 21);
+     assert valuesPerBlock == 3;
+   }
+  
+   @Override
+   protected int blockOffset(int offset) {
+     return offset / 3;
+   }
+  
+   @Override
+   protected int offsetInBlock(int offset) {
+     return offset % 3;
+   }
+  
+  }
+  
+  static final class Packed64SingleBlock12 extends Packed64SingleBlock {
+  
+   Packed64SingleBlock12(int valueCount) {
+     super(valueCount, 12);
+     assert valuesPerBlock == 5;
+   }
+  
+   @Override
+   protected int blockOffset(int offset) {
+     return offset / 5;
+   }
+  
+   @Override
+   protected int offsetInBlock(int offset) {
+     return offset % 5;
+   }
+  
+  }
+  
+  static final class Packed64SingleBlock10 extends Packed64SingleBlock {
+  
+   Packed64SingleBlock10(int valueCount) {
+     super(valueCount, 10);
+     assert valuesPerBlock == 6;
+   }
+  
+   @Override
+   protected int blockOffset(int offset) {
+     return offset / 6;
+   }
+  
+   @Override
+   protected int offsetInBlock(int offset) {
+     return offset % 6;
+   }
+  
+  }
+  
+  static final class Packed64SingleBlock9 extends Packed64SingleBlock {
+  
+   Packed64SingleBlock9(int valueCount) {
+     super(valueCount, 9);
+     assert valuesPerBlock == 7;
+   }
+  
+   @Override
+   protected int blockOffset(int offset) {
+     return offset / 7;
+   }
+  
+   @Override
+   protected int offsetInBlock(int offset) {
+     return offset % 7;
+   }
+  
+  }
+  
+  static final class Packed64SingleBlock7 extends Packed64SingleBlock {
+  
+   Packed64SingleBlock7(int valueCount) {
+     super(valueCount, 7);
+     assert valuesPerBlock == 9;
+   }
+  
+   @Override
+   protected int blockOffset(int offset) {
+     return offset / 9;
+   }
+  
+   @Override
+   protected int offsetInBlock(int offset) {
+     return offset % 9;
+   }
+  
+  }
+  
+  static final class Packed64SingleBlock6 extends Packed64SingleBlock {
+  
+   Packed64SingleBlock6(int valueCount) {
+     super(valueCount, 6);
+     assert valuesPerBlock == 10;
+   }
+  
+   @Override
+   protected int blockOffset(int offset) {
+     return offset / 10;
+   }
+  
+   @Override
+   protected int offsetInBlock(int offset) {
+     return offset % 10;
+   }
+  
+  }
+  
+  static final class Packed64SingleBlock5 extends Packed64SingleBlock {
+  
+   Packed64SingleBlock5(int valueCount) {
+     super(valueCount, 5);
+     assert valuesPerBlock == 12;
+   }
+  
+   @Override
+   protected int blockOffset(int offset) {
+     return offset / 12;
+   }
+  
+   @Override
+   protected int offsetInBlock(int offset) {
+     return offset % 12;
+   }
+  
+  }
+  
+  static final class Packed64SingleBlock4 extends Packed64SingleBlock {
+  
+   Packed64SingleBlock4(int valueCount) {
+     super(valueCount, 4);
+     assert valuesPerBlock == 16;
+   }
+  
+   @Override
+   protected int blockOffset(int offset) {
+     return offset >> 4;
+   }
+  
+   @Override
+   protected int offsetInBlock(int offset) {
+     return offset & 15;
+   }
+  
+  }
+  
+  static final class Packed64SingleBlock3 extends Packed64SingleBlock {
+  
+   Packed64SingleBlock3(int valueCount) {
+     super(valueCount, 3);
+     assert valuesPerBlock == 21;
+   }
+  
+   @Override
+   protected int blockOffset(int offset) {
+     return offset / 21;
+   }
+  
+   @Override
+   protected int offsetInBlock(int offset) {
+     return offset % 21;
+   }
+  
+  }
+  
+  static final class Packed64SingleBlock2 extends Packed64SingleBlock {
+  
+   Packed64SingleBlock2(int valueCount) {
+     super(valueCount, 2);
+     assert valuesPerBlock == 32;
+   }
+  
+   @Override
+   protected int blockOffset(int offset) {
+     return offset >> 5;
+   }
+  
+   @Override
+   protected int offsetInBlock(int offset) {
+     return offset & 31;
+   }
+  
+  }
+  
+  static final class Packed64SingleBlock1 extends Packed64SingleBlock {
+  
+   Packed64SingleBlock1(int valueCount) {
+     super(valueCount, 1);
+     assert valuesPerBlock == 64;
+   }
+  
+   @Override
+   protected int blockOffset(int offset) {
+     return offset >> 6;
+   }
+  
+   @Override
+   protected int offsetInBlock(int offset) {
+     return offset & 63;
+   }
+  
+  }
+}
\ No newline at end of file
Index: lucene/core/src/java/org/apache/lucene/util/packed/SequentialPackedReaderIterator.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/util/packed/SequentialPackedReaderIterator.java	(révision 0)
+++ lucene/core/src/java/org/apache/lucene/util/packed/SequentialPackedReaderIterator.java	(révision 0)
@@ -0,0 +1,49 @@
+package org.apache.lucene.util.packed;
+
+import java.io.IOException;
+
+import org.apache.lucene.store.DataInput;
+
+/**
+ * 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.
+ */
+
+class SequentialPackedReaderIterator extends AbstractPackedReaderIterator {
+
+  private final DataInput in;
+  
+  public SequentialPackedReaderIterator(int bitsPerValue, int valueCount,
+      DataInput in) throws IOException {
+    super(bitsPerValue, valueCount);
+    this.in = in;
+  }
+
+  @Override
+  public long advance(int ord) throws IOException {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public void close() throws IOException {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  protected DataInput getDataInput() {
+    return in;
+  }
+
+}
Index: lucene/core/src/java/org/apache/lucene/util/packed/Packed16ThreeBlocks.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/util/packed/Packed16ThreeBlocks.java	(révision 0)
+++ lucene/core/src/java/org/apache/lucene/util/packed/Packed16ThreeBlocks.java	(révision 0)
@@ -0,0 +1,56 @@
+package org.apache.lucene.util.packed;
+
+import java.util.Arrays;
+
+/**
+ * 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.
+ */
+
+class Packed16ThreeBlocks extends PackedInts.ReaderImpl implements
+  PackedInts.Mutable {
+
+  public static final int MAX_SIZE = Integer.MAX_VALUE / 3;
+
+  private final short[] blocks;
+
+  Packed16ThreeBlocks(int valueCount) {
+    super(valueCount, 48);
+    if (valueCount > MAX_SIZE) {
+      throw new ArrayIndexOutOfBoundsException("MAX_SIZE exceeded");
+    }
+    this.blocks = new short[3 * valueCount];
+  }
+  
+  @Override
+  public long get(int index) {
+    final int o = index * 3;
+    return (blocks[o] & 0xffffL) << 32 | (blocks[o+1] & 0xffffL) << 16 | (blocks[o+2] & 0xffffL);
+  }
+
+  @Override
+  public void set(int index, long value) {
+    final int o = index * 3;
+    blocks[o] = (short) (value >> 32);
+    blocks[o+1] = (short) (value >> 16);
+    blocks[o+2] = (short) value;
+  }
+
+  @Override
+  public void clear() {
+    Arrays.fill(blocks, (short) 0);
+  }
+
+}
Index: lucene/core/src/java/org/apache/lucene/util/packed/PackedReaderIterator.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/util/packed/PackedReaderIterator.java	(révision 1340914)
+++ lucene/core/src/java/org/apache/lucene/util/packed/PackedReaderIterator.java	(copie de travail)
@@ -17,76 +17,30 @@
  * limitations under the License.
  */
 
+import org.apache.lucene.store.DataInput;
 import org.apache.lucene.store.IndexInput;
 
 import java.io.IOException;
 
-final class PackedReaderIterator implements PackedInts.ReaderIterator {
-  private long pending;
-  private int pendingBitsLeft;
+final class PackedReaderIterator extends AbstractPackedReaderIterator {
+
   private final IndexInput in;
-  private final int bitsPerValue;
-  private final int valueCount;
-  private int position = -1;
 
-  // masks[n-1] masks for bottom n bits
-  private final long[] masks;
-
   public PackedReaderIterator(int bitsPerValue, int valueCount, IndexInput in)
     throws IOException {
-
-    this.valueCount = valueCount;
-    this.bitsPerValue = bitsPerValue;
-    
+    super(bitsPerValue, valueCount);
     this.in = in;
-    masks = new long[bitsPerValue];
-
-    long v = 1;
-    for (int i = 0; i < bitsPerValue; i++) {
-      v *= 2;
-      masks[i] = v - 1;
-    }
   }
 
-  public int getBitsPerValue() {
-    return bitsPerValue;
+  @Override
+  protected DataInput getDataInput() {
+    return in;
   }
 
-  public int size() {
-    return valueCount;
-  }
-
-  public long next() throws IOException {
-    if (pendingBitsLeft == 0) {
-      pending = in.readLong();
-      pendingBitsLeft = 64;
-    }
-    
-    final long result;
-    if (pendingBitsLeft >= bitsPerValue) { // not split
-      result = (pending >> (pendingBitsLeft - bitsPerValue)) & masks[bitsPerValue-1];
-      pendingBitsLeft -= bitsPerValue;
-    } else { // split
-      final int bits1 = bitsPerValue - pendingBitsLeft;
-      final long result1 = (pending & masks[pendingBitsLeft-1]) << bits1;
-      pending = in.readLong();
-      final long result2 = (pending >> (64 - bits1)) & masks[bits1-1];
-      pendingBitsLeft = 64 + pendingBitsLeft - bitsPerValue;
-      result = result1 | result2;
-    }
-    
-    ++position;
-    return result;
-  }
-
   public void close() throws IOException {
     in.close();
   }
 
-  public int ord() {
-    return position;
-  }
-
   public long advance(final int ord) throws IOException{
     assert ord < valueCount : "ord must be less than valueCount";
     assert ord > position : "ord must be greater than the current position";
Index: lucene/core/src/java/org/apache/lucene/util/packed/PackedInts.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/util/packed/PackedInts.java	(révision 1340914)
+++ lucene/core/src/java/org/apache/lucene/util/packed/PackedInts.java	(copie de travail)
@@ -38,6 +38,10 @@
 
 public class PackedInts {
 
+  public static final float FAST = 1f;
+  public static final float COMPACT = 0f;
+  public static final float DEFAULT = 0.2f;
+  
   private final static String CODEC_NAME = "PackedInts";
   private final static int VERSION_START = 0;
   private final static int VERSION_CURRENT = VERSION_START;
@@ -136,7 +140,7 @@
       assert bitsPerValue > 0 && bitsPerValue <= 64 : "bitsPerValue=" + bitsPerValue;
       this.valueCount = valueCount;
     }
-
+    
     public int getBitsPerValue() {
       return bitsPerValue;
     }
@@ -145,10 +149,6 @@
       return valueCount;
     }
 
-    public long getMaxValue() { // Convenience method
-      return maxValue(bitsPerValue);
-    }
-
     public Object getArray() {
       return null;
     }
@@ -182,32 +182,70 @@
     public abstract void finish() throws IOException;
   }
 
+  private static Reader copyData(int bitsPerValue, int valueCount,
+      DataInput in, Mutable mutable) throws IOException {
+    SequentialPackedReaderIterator it = new SequentialPackedReaderIterator(bitsPerValue, valueCount, in);
+    for (int i = 0; i < valueCount; ++i) {
+      mutable.set(i, it.next());
+    }
+    return mutable;
+  }
+
   /**
    * Retrieve PackedInt data from the DataInput and return a packed int
    * structure based on it.
    * @param in positioned at the beginning of a stored packed int structure.
+   * @param acceptableOverheadRatio an acceptable overhead ratio per value
    * @return a read only random access capable array of positive integers.
    * @throws IOException if the structure could not be retrieved.
    * @lucene.internal
    */
-  public static Reader getReader(DataInput in) throws IOException {
+  public static Reader getReader(DataInput in, float acceptableOverheadRatio) throws IOException {
     CodecUtil.checkHeader(in, CODEC_NAME, VERSION_START, VERSION_START);
     final int bitsPerValue = in.readVInt();
     assert bitsPerValue > 0 && bitsPerValue <= 64: "bitsPerValue=" + bitsPerValue;
     final int valueCount = in.readVInt();
 
-    switch (bitsPerValue) {
-    case 8:
+    acceptableOverheadRatio = Math.max(COMPACT, acceptableOverheadRatio);
+    acceptableOverheadRatio = Math.min(FAST, acceptableOverheadRatio);
+    float acceptableOverheadPerValue = acceptableOverheadRatio * bitsPerValue; // in bits
+
+    int maxBitsPerValue = bitsPerValue + (int) acceptableOverheadPerValue;
+
+    if (bitsPerValue == Byte.SIZE) {
       return new Direct8(in, valueCount);
-    case 16:
+    } else if (bitsPerValue < Byte.SIZE && maxBitsPerValue >= Byte.SIZE) {
+      return copyData(bitsPerValue, valueCount, in, new Direct8(valueCount));
+    } else if (bitsPerValue == Short.SIZE) {
+      return copyData(bitsPerValue, valueCount, in, new Direct16(valueCount));
+    } else if (bitsPerValue < Short.SIZE && maxBitsPerValue >= Short.SIZE) {
       return new Direct16(in, valueCount);
-    case 32:
+    } else if (bitsPerValue == Integer.SIZE) {
+      return copyData(bitsPerValue, valueCount, in, new Direct32(valueCount));
+    } else if (bitsPerValue < Integer.SIZE && maxBitsPerValue >= Integer.SIZE) {
       return new Direct32(in, valueCount);
-    case 64:
+    } else if (bitsPerValue == Long.SIZE) {
       return new Direct64(in, valueCount);
-    default:
-      if (Constants.JRE_IS_64BIT || bitsPerValue >= 32) {
+    } else if (bitsPerValue < Long.SIZE && maxBitsPerValue >= Long.SIZE) {
+      return copyData(bitsPerValue, valueCount, in, new Direct64(valueCount));
+    } else if (valueCount <= Packed8ThreeBlocks.MAX_SIZE && bitsPerValue <= 24 && maxBitsPerValue >= 24) {
+      return copyData(bitsPerValue, valueCount, in, new Packed8ThreeBlocks(valueCount));
+    } else if (valueCount <= Packed16ThreeBlocks.MAX_SIZE && bitsPerValue <= 48 && maxBitsPerValue >= 48) {
+      return copyData(bitsPerValue, valueCount, in, new Packed16ThreeBlocks(valueCount));
+    } else {
+      if (bitsPerValue >= 32) {
         return new Packed64(in, valueCount, bitsPerValue);
+      } else if (Constants.JRE_IS_64BIT) {
+        for (int bpv = bitsPerValue; bpv <= maxBitsPerValue; ++bpv) {
+          if (Packed64SingleBlock.isSupported(bpv)) {
+            float overhead = Packed64SingleBlock.overheadPerValue(bpv);
+            float acceptableOverhead = acceptableOverheadPerValue + bitsPerValue - bpv;
+            if (overhead <= acceptableOverhead) {
+              return copyData(bitsPerValue, valueCount, in, Packed64SingleBlock.create(valueCount, bpv));
+            }
+          }
+        }
+        return new Packed64(in, valueCount, bitsPerValue);
       } else {
         return new Packed32(in, valueCount, bitsPerValue);
       }
@@ -250,28 +288,57 @@
    * Create a packed integer array with the given amount of values initialized
    * to 0. the valueCount and the bitsPerValue cannot be changed after creation.
    * All Mutables known by this factory are kept fully in RAM.
-   * @param valueCount   the number of elements.
-   * @param bitsPerValue the number of bits available for any given value.
-   * @return a mutable packed integer array.
+   * 
+   * Positive values of <code>acceptableOverheadRatio</code> will trade space
+   * for speed by selecting a faster but potentially less memory-efficient
+   * implementation. An <code>acceptableOverheadRatio</code> of
+   * {@link PackedInts#COMPACT} will make sure that the most memory-efficient
+   * implementation is selected whereas {@link PackedInts#FAST} will make sure
+   * that the fastest implementation is selected.
+   *
+   * @param valueCount   the number of elements
+   * @param bitsPerValue the number of bits available for any given value
+   * @param acceptableOverheadRatio an acceptable overhead ratio per value
+   * @return a mutable packed integer array
    * @throws java.io.IOException if the Mutable could not be created. With the
    *         current implementations, this never happens, but the method
    *         signature allows for future persistence-backed Mutables.
    * @lucene.internal
    */
-  public static Mutable getMutable(
-         int valueCount, int bitsPerValue) {
-    switch (bitsPerValue) {
-    case 8:
+  public static Mutable getMutable(int valueCount,
+      int bitsPerValue, float acceptableOverheadRatio) {
+    acceptableOverheadRatio = Math.max(COMPACT, acceptableOverheadRatio);
+    acceptableOverheadRatio = Math.min(FAST, acceptableOverheadRatio);
+    float acceptableOverheadPerValue = acceptableOverheadRatio * bitsPerValue; // in bits
+
+    int maxBitsPerValue = bitsPerValue + (int) acceptableOverheadPerValue;
+
+    if (bitsPerValue <= Byte.SIZE && maxBitsPerValue >= Byte.SIZE) {
       return new Direct8(valueCount);
-    case 16:
+    } else if (bitsPerValue <= Short.SIZE && maxBitsPerValue >= Short.SIZE) {
       return new Direct16(valueCount);
-    case 32:
+    } else if (bitsPerValue <= Integer.SIZE && maxBitsPerValue >= Integer.SIZE) {
       return new Direct32(valueCount);
-    case 64:
+    } else if (bitsPerValue <= Long.SIZE && maxBitsPerValue >= Long.SIZE) {
       return new Direct64(valueCount);
-    default:
-      if (Constants.JRE_IS_64BIT || bitsPerValue >= 32) {
+    } else if (valueCount <= Packed8ThreeBlocks.MAX_SIZE && bitsPerValue <= 24 && maxBitsPerValue >= 24) {
+      return new Packed8ThreeBlocks(valueCount);
+    } else if (valueCount <= Packed16ThreeBlocks.MAX_SIZE && bitsPerValue <= 48 && maxBitsPerValue >= 48) {
+      return new Packed16ThreeBlocks(valueCount);
+    } else {
+      if (bitsPerValue >= 32) {
         return new Packed64(valueCount, bitsPerValue);
+      } else if (Constants.JRE_IS_64BIT) {
+        for (int bpv = bitsPerValue; bpv <= maxBitsPerValue; ++bpv) {
+          if (Packed64SingleBlock.isSupported(bpv)) {
+            float overhead = Packed64SingleBlock.overheadPerValue(bpv);
+            float acceptableOverhead = acceptableOverheadPerValue + bitsPerValue - bpv;
+            if (overhead <= acceptableOverhead) {
+              return Packed64SingleBlock.create(valueCount, bpv);
+            }
+          }
+        }
+        return new Packed64(valueCount, bitsPerValue);
       } else {
         return new Packed32(valueCount, bitsPerValue);
       }
@@ -321,26 +388,4 @@
   public static long maxValue(int bitsPerValue) {
     return bitsPerValue == 64 ? Long.MAX_VALUE : ~(~0L << bitsPerValue);
   }
-
-  /** Rounds bitsPerValue up to 8, 16, 32 or 64. */
-  public static int getNextFixedSize(int bitsPerValue) {
-    if (bitsPerValue <= 8) {
-      return 8;
-    } else if (bitsPerValue <= 16) {
-      return 16;
-    } else if (bitsPerValue <= 32) {
-      return 32;
-    } else {
-      return 64;
-    }
-  }
-
-  /** Possibly wastes some storage in exchange for faster lookups */
-  public static int getRoundedFixedSize(int bitsPerValue) {
-    if (bitsPerValue > 58 || (bitsPerValue < 32 && bitsPerValue > 29)) { // 10% space-waste is ok
-      return getNextFixedSize(bitsPerValue);
-    } else {
-      return bitsPerValue;
-    }
-  }
 }
Index: lucene/core/src/java/org/apache/lucene/util/packed/GrowableWriter.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/util/packed/GrowableWriter.java	(révision 1340914)
+++ lucene/core/src/java/org/apache/lucene/util/packed/GrowableWriter.java	(copie de travail)
@@ -28,22 +28,14 @@
 
   private long currentMaxValue;
   private PackedInts.Mutable current;
-  private final boolean roundFixedSize;
+  private final float acceptableOverheadRatio;
 
-  public GrowableWriter(int startBitsPerValue, int valueCount, boolean roundFixedSize) {
-    this.roundFixedSize = roundFixedSize;
-    current = PackedInts.getMutable(valueCount, getSize(startBitsPerValue));
+  public GrowableWriter(int startBitsPerValue, int valueCount, float acceptableOverheadRatio) {
+    this.acceptableOverheadRatio = acceptableOverheadRatio;
+    current = PackedInts.getMutable(valueCount, startBitsPerValue, this.acceptableOverheadRatio);
     currentMaxValue = PackedInts.maxValue(current.getBitsPerValue());
   }
 
-  private final int getSize(int bpv) {
-    if (roundFixedSize) {
-      return PackedInts.getNextFixedSize(bpv);
-    } else {
-      return bpv;
-    }
-  }
-
   public long get(int index) {
     return current.get(index);
   }
@@ -78,7 +70,7 @@
         currentMaxValue *= 2;
       }
       final int valueCount = size();
-      PackedInts.Mutable next = PackedInts.getMutable(valueCount, getSize(bpv));
+      PackedInts.Mutable next = PackedInts.getMutable(valueCount, bpv, acceptableOverheadRatio);
       for(int i=0;i<valueCount;i++) {
         next.set(i, current.get(i));
       }
@@ -93,7 +85,7 @@
   }
 
   public GrowableWriter resize(int newSize) {
-    GrowableWriter next = new GrowableWriter(getBitsPerValue(), newSize, roundFixedSize);
+    GrowableWriter next = new GrowableWriter(getBitsPerValue(), newSize, acceptableOverheadRatio);
     final int limit = Math.min(size(), newSize);
     for(int i=0;i<limit;i++) {
       next.set(i, get(i));
Index: lucene/core/src/java/org/apache/lucene/util/packed/Packed8ThreeBlocks.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/util/packed/Packed8ThreeBlocks.java	(révision 0)
+++ lucene/core/src/java/org/apache/lucene/util/packed/Packed8ThreeBlocks.java	(révision 0)
@@ -0,0 +1,56 @@
+package org.apache.lucene.util.packed;
+
+import java.util.Arrays;
+
+/**
+ * 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.
+ */
+
+class Packed8ThreeBlocks extends PackedInts.ReaderImpl implements
+  PackedInts.Mutable {
+
+  public static final int MAX_SIZE = Integer.MAX_VALUE / 3;
+  
+  private final byte[] blocks;
+  
+  Packed8ThreeBlocks(int valueCount) {
+    super(valueCount, 24);
+    if (valueCount > MAX_SIZE) {
+      throw new ArrayIndexOutOfBoundsException("MAX_SIZE exceeded");
+    }
+    this.blocks = new byte[3 * valueCount];
+  }
+  
+  @Override
+  public long get(int index) {
+    final int o = index * 3;
+    return (blocks[o] & 0xffL) << 16 | (blocks[o+1] & 0xffL) << 8 | (blocks[o+2] & 0xffL);
+  }
+
+  @Override
+  public void set(int index, long value) {
+    final int o = index * 3;
+    blocks[o+2] = (byte) value;
+    blocks[o+1] = (byte) (value >> 8);
+    blocks[o] = (byte) (value >> 16);
+  }
+
+  @Override
+  public void clear() {
+    Arrays.fill(blocks, (byte) 0);
+  }
+  
+}
Index: lucene/core/src/java/org/apache/lucene/util/packed/AbstractPackedReaderIterator.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/util/packed/AbstractPackedReaderIterator.java	(révision 0)
+++ lucene/core/src/java/org/apache/lucene/util/packed/AbstractPackedReaderIterator.java	(révision 0)
@@ -0,0 +1,88 @@
+package org.apache.lucene.util.packed;
+
+/**
+ * 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.store.DataInput;
+
+abstract class AbstractPackedReaderIterator implements PackedInts.ReaderIterator {
+  protected long pending;
+  protected int pendingBitsLeft;
+  protected final int bitsPerValue;
+  protected final int valueCount;
+  protected int position = -1;
+
+  // masks[n-1] masks for bottom n bits
+  private final long[] masks;
+
+  public AbstractPackedReaderIterator(int bitsPerValue, int valueCount)
+    throws IOException {
+
+    this.valueCount = valueCount;
+    this.bitsPerValue = bitsPerValue;
+
+    masks = new long[bitsPerValue];
+
+    long v = 1;
+    for (int i = 0; i < bitsPerValue; i++) {
+      v *= 2;
+      masks[i] = v - 1;
+    }
+  }
+
+  protected abstract DataInput getDataInput();
+
+  public final int getBitsPerValue() {
+    return bitsPerValue;
+  }
+
+  public final int size() {
+    return valueCount;
+  }
+
+  public final long next() throws IOException {
+    final DataInput in = getDataInput();
+    
+    if (pendingBitsLeft == 0) {
+      pending = in.readLong();
+      pendingBitsLeft = 64;
+    }
+    
+    final long result;
+    if (pendingBitsLeft >= bitsPerValue) { // not split
+      result = (pending >> (pendingBitsLeft - bitsPerValue)) & masks[bitsPerValue-1];
+      pendingBitsLeft -= bitsPerValue;
+    } else { // split
+      final int bits1 = bitsPerValue - pendingBitsLeft;
+      final long result1 = (pending & masks[pendingBitsLeft-1]) << bits1;
+      pending = in.readLong();
+      final long result2 = (pending >> (64 - bits1)) & masks[bits1-1];
+      pendingBitsLeft = 64 + pendingBitsLeft - bitsPerValue;
+      result = result1 | result2;
+    }
+    
+    ++position;
+    return result;
+  }
+
+  public final int ord() {
+    return position;
+  }
+
+}
Index: lucene/core/src/java/org/apache/lucene/codecs/lucene3x/TermInfosReaderIndex.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/codecs/lucene3x/TermInfosReaderIndex.java	(révision 1340914)
+++ lucene/core/src/java/org/apache/lucene/codecs/lucene3x/TermInfosReaderIndex.java	(copie de travail)
@@ -74,7 +74,7 @@
     PagedBytesDataOutput dataOutput = dataPagedBytes.getDataOutput();
 
     final int bitEstimate = 1+MathUtil.log(tiiFileLength, 2);
-    GrowableWriter indexToTerms = new GrowableWriter(bitEstimate, indexSize, false);
+    GrowableWriter indexToTerms = new GrowableWriter(bitEstimate, indexSize, PackedInts.DEFAULT);
 
     String currentField = null;
     List<String> fieldStrs = new ArrayList<String>();
Index: lucene/core/src/java/org/apache/lucene/codecs/FixedGapTermsIndexReader.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/codecs/FixedGapTermsIndexReader.java	(révision 1340914)
+++ lucene/core/src/java/org/apache/lucene/codecs/FixedGapTermsIndexReader.java	(copie de travail)
@@ -301,11 +301,11 @@
             termBytes.copy(clone, numTermBytes);
 
             // records offsets into main terms dict file
-            termsDictOffsets = PackedInts.getReader(clone);
+            termsDictOffsets = PackedInts.getReader(clone, PackedInts.DEFAULT);
             assert termsDictOffsets.size() == numIndexTerms;
 
             // records offsets into byte[] term data
-            termOffsets = PackedInts.getReader(clone);
+            termOffsets = PackedInts.getReader(clone, PackedInts.DEFAULT);
             assert termOffsets.size() == 1+numIndexTerms;
           } finally {
             clone.close();
@@ -328,8 +328,8 @@
             // we'd have to try @ fewer bits and then grow
             // if we overflowed it.
 
-            PackedInts.Mutable termsDictOffsetsM = PackedInts.getMutable(this.numIndexTerms, termsDictOffsetsIter.getBitsPerValue());
-            PackedInts.Mutable termOffsetsM = PackedInts.getMutable(this.numIndexTerms+1, termOffsetsIter.getBitsPerValue());
+            PackedInts.Mutable termsDictOffsetsM = PackedInts.getMutable(this.numIndexTerms, termsDictOffsetsIter.getBitsPerValue(), PackedInts.DEFAULT);
+            PackedInts.Mutable termOffsetsM = PackedInts.getMutable(this.numIndexTerms+1, termOffsetsIter.getBitsPerValue(), PackedInts.DEFAULT);
 
             termsDictOffsets = termsDictOffsetsM;
             termOffsets = termOffsetsM;
Index: lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/FixedDerefBytesImpl.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/FixedDerefBytesImpl.java	(révision 1340914)
+++ lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/FixedDerefBytesImpl.java	(copie de travail)
@@ -102,7 +102,7 @@
       super(datIn, idxIn, new PagedBytes(PAGED_BYTES_BITS), size * numValues,
           Type.BYTES_FIXED_DEREF);
       this.size = size;
-      addresses = PackedInts.getReader(idxIn);
+      addresses = PackedInts.getReader(idxIn, PackedInts.DEFAULT);
     }
 
     @Override
Index: lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/PackedIntValues.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/PackedIntValues.java	(révision 1340914)
+++ lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/PackedIntValues.java	(copie de travail)
@@ -231,7 +231,7 @@
       super(Type.VAR_INTS);
       minValue = dataIn.readLong();
       defaultValue = dataIn.readLong();
-      values = direct ? PackedInts.getDirectReader(dataIn) : PackedInts.getReader(dataIn);
+      values = direct ? PackedInts.getDirectReader(dataIn) : PackedInts.getReader(dataIn, PackedInts.DEFAULT);
     }
     
     @Override
Index: lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/VarSortedBytesImpl.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/VarSortedBytesImpl.java	(révision 1340914)
+++ lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/VarSortedBytesImpl.java	(copie de travail)
@@ -58,8 +58,8 @@
     private final Comparator<BytesRef> comp;
 
     public Writer(Directory dir, String id, Comparator<BytesRef> comp,
-        Counter bytesUsed, IOContext context, boolean fasterButMoreRam) throws IOException {
-      super(dir, id, CODEC_NAME, VERSION_CURRENT, bytesUsed, context, fasterButMoreRam, Type.BYTES_VAR_SORTED);
+        Counter bytesUsed, IOContext context, float acceptableOverheadRatio) throws IOException {
+      super(dir, id, CODEC_NAME, VERSION_CURRENT, bytesUsed, context, acceptableOverheadRatio, Type.BYTES_VAR_SORTED);
       this.comp = comp;
       size = 0;
     }
@@ -125,7 +125,7 @@
       // total bytes of data
       idxOut.writeLong(maxBytes);
       PackedInts.Writer offsetWriter = PackedInts.getWriter(idxOut, count+1,
-          bitsRequired(maxBytes));
+          PackedInts.bitsRequired(maxBytes));
       // first dump bytes data, recording index & write offset as
       // we go
       final BytesRef spare = new BytesRef();
Index: lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/Bytes.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/Bytes.java	(révision 1340914)
+++ lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/Bytes.java	(copie de travail)
@@ -125,7 +125,7 @@
    */
   public static DocValuesConsumer getWriter(Directory dir, String id, Mode mode,
       boolean fixedSize, Comparator<BytesRef> sortComparator,
-      Counter bytesUsed, IOContext context, boolean fasterButMoreRam)
+      Counter bytesUsed, IOContext context, float acceptableOverheadRatio)
       throws IOException {
     // TODO -- i shouldn't have to specify fixed? can
     // track itself & do the write thing at write time?
@@ -139,7 +139,7 @@
       } else if (mode == Mode.DEREF) {
         return new FixedDerefBytesImpl.Writer(dir, id, bytesUsed, context);
       } else if (mode == Mode.SORTED) {
-        return new FixedSortedBytesImpl.Writer(dir, id, sortComparator, bytesUsed, context, fasterButMoreRam);
+        return new FixedSortedBytesImpl.Writer(dir, id, sortComparator, bytesUsed, context, acceptableOverheadRatio);
       }
     } else {
       if (mode == Mode.STRAIGHT) {
@@ -147,7 +147,7 @@
       } else if (mode == Mode.DEREF) {
         return new VarDerefBytesImpl.Writer(dir, id, bytesUsed, context);
       } else if (mode == Mode.SORTED) {
-        return new VarSortedBytesImpl.Writer(dir, id, sortComparator, bytesUsed, context, fasterButMoreRam);
+        return new VarSortedBytesImpl.Writer(dir, id, sortComparator, bytesUsed, context, acceptableOverheadRatio);
       }
     }
 
@@ -374,32 +374,32 @@
     protected int lastDocId = -1;
     protected int[] docToEntry;
     protected final BytesRefHash hash;
-    protected final boolean fasterButMoreRam;
+    protected final float acceptableOverheadRatio;
     protected long maxBytes = 0;
     
     protected DerefBytesWriterBase(Directory dir, String id, String codecName,
         int codecVersion, Counter bytesUsed, IOContext context, Type type)
         throws IOException {
       this(dir, id, codecName, codecVersion, new DirectTrackingAllocator(
-          ByteBlockPool.BYTE_BLOCK_SIZE, bytesUsed), bytesUsed, context, false, type);
+          ByteBlockPool.BYTE_BLOCK_SIZE, bytesUsed), bytesUsed, context, PackedInts.DEFAULT, type);
     }
 
     protected DerefBytesWriterBase(Directory dir, String id, String codecName,
-                                   int codecVersion, Counter bytesUsed, IOContext context, boolean fasterButMoreRam, Type type)
+                                   int codecVersion, Counter bytesUsed, IOContext context, float acceptableOverheadRatio, Type type)
         throws IOException {
       this(dir, id, codecName, codecVersion, new DirectTrackingAllocator(
-          ByteBlockPool.BYTE_BLOCK_SIZE, bytesUsed), bytesUsed, context, fasterButMoreRam,type);
+          ByteBlockPool.BYTE_BLOCK_SIZE, bytesUsed), bytesUsed, context, acceptableOverheadRatio,type);
     }
 
     protected DerefBytesWriterBase(Directory dir, String id, String codecName, int codecVersion, Allocator allocator,
-        Counter bytesUsed, IOContext context, boolean fasterButMoreRam, Type type) throws IOException {
+        Counter bytesUsed, IOContext context, float acceptableOverheadRatio, Type type) throws IOException {
       super(dir, id, codecName, codecVersion, bytesUsed, context, type);
       hash = new BytesRefHash(new ByteBlockPool(allocator),
           BytesRefHash.DEFAULT_CAPACITY, new TrackingDirectBytesStartArray(
               BytesRefHash.DEFAULT_CAPACITY, bytesUsed));
       docToEntry = new int[1];
       bytesUsed.addAndGet(RamUsageEstimator.NUM_BYTES_INT);
-      this.fasterButMoreRam = fasterButMoreRam;
+      this.acceptableOverheadRatio = acceptableOverheadRatio;
     }
     
     protected static int writePrefixLength(DataOutput datOut, BytesRef bytes)
@@ -498,7 +498,7 @@
     protected void writeIndex(IndexOutput idxOut, int docCount,
         long maxValue, int[] addresses, int[] toEntry) throws IOException {
       final PackedInts.Writer w = PackedInts.getWriter(idxOut, docCount,
-          bitsRequired(maxValue));
+          PackedInts.bitsRequired(maxValue));
       final int limit = docCount > docToEntry.length ? docToEntry.length
           : docCount;
       assert toEntry.length >= limit -1;
@@ -522,7 +522,7 @@
     protected void writeIndex(IndexOutput idxOut, int docCount,
         long maxValue, long[] addresses, int[] toEntry) throws IOException {
       final PackedInts.Writer w = PackedInts.getWriter(idxOut, docCount,
-          bitsRequired(maxValue));
+          PackedInts.bitsRequired(maxValue));
       final int limit = docCount > docToEntry.length ? docToEntry.length
           : docCount;
       assert toEntry.length >= limit -1;
@@ -542,11 +542,6 @@
       }
       w.finish();
     }
-
-    protected int bitsRequired(long maxValue){
-      return fasterButMoreRam ?
-          PackedInts.getNextFixedSize(PackedInts.bitsRequired(maxValue)) : PackedInts.bitsRequired(maxValue);
-    }
     
   }
   
@@ -578,8 +573,8 @@
       this.pagedBytes.copy(datIn, bytesToRead);
       data = pagedBytes.freeze(true);
       this.idxIn = idxIn;
-      ordToOffsetIndex = hasOffsets ? PackedInts.getReader(idxIn) : null; 
-      docToOrdIndex = PackedInts.getReader(idxIn);
+      ordToOffsetIndex = hasOffsets ? PackedInts.getReader(idxIn, PackedInts.DEFAULT) : null; 
+      docToOrdIndex = PackedInts.getReader(idxIn, PackedInts.DEFAULT);
     }
 
     @Override
Index: lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/VarDerefBytesImpl.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/VarDerefBytesImpl.java	(révision 1340914)
+++ lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/VarDerefBytesImpl.java	(copie de travail)
@@ -116,7 +116,7 @@
         throws IOException {
       super(datIn, idxIn, new PagedBytes(PAGED_BYTES_BITS), totalBytes,
           Type.BYTES_VAR_DEREF);
-      addresses = PackedInts.getReader(idxIn);
+      addresses = PackedInts.getReader(idxIn, PackedInts.DEFAULT);
     }
 
     @Override
Index: lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/VarStraightBytesImpl.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/VarStraightBytesImpl.java	(révision 1340914)
+++ lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/VarStraightBytesImpl.java	(copie de travail)
@@ -258,7 +258,7 @@
     public VarStraightSource(IndexInput datIn, IndexInput idxIn) throws IOException {
       super(datIn, idxIn, new PagedBytes(PAGED_BYTES_BITS), idxIn.readVLong(),
           Type.BYTES_VAR_STRAIGHT);
-      addresses = PackedInts.getReader(idxIn);
+      addresses = PackedInts.getReader(idxIn, PackedInts.DEFAULT);
     }
 
     @Override
Index: lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/FixedSortedBytesImpl.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/FixedSortedBytesImpl.java	(révision 1340914)
+++ lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/FixedSortedBytesImpl.java	(copie de travail)
@@ -57,8 +57,8 @@
     private final Comparator<BytesRef> comp;
 
     public Writer(Directory dir, String id, Comparator<BytesRef> comp,
-        Counter bytesUsed, IOContext context, boolean fasterButMoreRam) throws IOException {
-      super(dir, id, CODEC_NAME, VERSION_CURRENT, bytesUsed, context, fasterButMoreRam, Type.BYTES_FIXED_SORTED);
+        Counter bytesUsed, IOContext context, float acceptableOverheadRatio) throws IOException {
+      super(dir, id, CODEC_NAME, VERSION_CURRENT, bytesUsed, context, acceptableOverheadRatio, Type.BYTES_FIXED_SORTED);
       this.comp = comp;
     }
 
Index: lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/Writer.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/Writer.java	(révision 1340914)
+++ lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/Writer.java	(copie de travail)
@@ -84,7 +84,7 @@
    * @throws IOException
    */
   public static DocValuesConsumer create(Type type, String id, Directory directory,
-      Comparator<BytesRef> comp, Counter bytesUsed, IOContext context, boolean fasterButMoreRam) throws IOException {
+      Comparator<BytesRef> comp, Counter bytesUsed, IOContext context, float acceptableOverheadRatio) throws IOException {
     if (comp == null) {
       comp = BytesRef.getUTF8SortedAsUnicodeComparator();
     }
@@ -101,22 +101,22 @@
       return Floats.getWriter(directory, id, bytesUsed, context, type);
     case BYTES_FIXED_STRAIGHT:
       return Bytes.getWriter(directory, id, Bytes.Mode.STRAIGHT, true, comp,
-          bytesUsed, context, fasterButMoreRam);
+          bytesUsed, context, acceptableOverheadRatio);
     case BYTES_FIXED_DEREF:
       return Bytes.getWriter(directory, id, Bytes.Mode.DEREF, true, comp,
-          bytesUsed, context, fasterButMoreRam);
+          bytesUsed, context, acceptableOverheadRatio);
     case BYTES_FIXED_SORTED:
       return Bytes.getWriter(directory, id, Bytes.Mode.SORTED, true, comp,
-          bytesUsed, context, fasterButMoreRam);
+          bytesUsed, context, acceptableOverheadRatio);
     case BYTES_VAR_STRAIGHT:
       return Bytes.getWriter(directory, id, Bytes.Mode.STRAIGHT, false, comp,
-          bytesUsed, context, fasterButMoreRam);
+          bytesUsed, context, acceptableOverheadRatio);
     case BYTES_VAR_DEREF:
       return Bytes.getWriter(directory, id, Bytes.Mode.DEREF, false, comp,
-          bytesUsed, context, fasterButMoreRam);
+          bytesUsed, context, acceptableOverheadRatio);
     case BYTES_VAR_SORTED:
       return Bytes.getWriter(directory, id, Bytes.Mode.SORTED, false, comp,
-          bytesUsed, context, fasterButMoreRam);
+          bytesUsed, context, acceptableOverheadRatio);
     default:
       throw new IllegalArgumentException("Unknown Values: " + type);
     }
Index: lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/DocValuesWriterBase.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/DocValuesWriterBase.java	(révision 1340914)
+++ lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/DocValuesWriterBase.java	(copie de travail)
@@ -31,6 +31,7 @@
 import org.apache.lucene.store.IOContext;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.Counter;
+import org.apache.lucene.util.packed.PackedInts;
 
 /**
  * Abstract base class for PerDocConsumer implementations
@@ -41,7 +42,7 @@
   protected final String segmentName;
   private final Counter bytesUsed;
   protected final IOContext context;
-  private final boolean fasterButMoreRam;
+  private final float acceptableOverheadRatio;
 
   /**
    * Filename extension for index files
@@ -57,7 +58,7 @@
    * @param state The state to initiate a {@link PerDocConsumer} instance
    */
   protected DocValuesWriterBase(PerDocWriteState state) {
-    this(state, true);
+    this(state, PackedInts.FAST);
   }
 
   /**
@@ -66,11 +67,11 @@
    *                         used for a value to either 8, 16, 32 or 64 bytes. This option is only applicable for
    *                         docvalues of type {@link Type#BYTES_FIXED_SORTED} and {@link Type#BYTES_VAR_SORTED}.
    */
-  protected DocValuesWriterBase(PerDocWriteState state, boolean fasterButMoreRam) {
+  protected DocValuesWriterBase(PerDocWriteState state, float acceptableOverheadRatio) {
     this.segmentName = state.segmentName;
     this.bytesUsed = state.bytesUsed;
     this.context = state.context;
-    this.fasterButMoreRam = fasterButMoreRam;
+    this.acceptableOverheadRatio = acceptableOverheadRatio;
   }
 
   protected abstract Directory getDirectory() throws IOException;
@@ -83,7 +84,7 @@
   public DocValuesConsumer addValuesField(Type valueType, FieldInfo field) throws IOException {
     return Writer.create(valueType,
         PerDocProducerBase.docValuesId(segmentName, field.number), 
-        getDirectory(), getComparator(), bytesUsed, context, fasterButMoreRam);
+        getDirectory(), getComparator(), bytesUsed, context, acceptableOverheadRatio);
   }
 
   
Index: lucene/core/src/java/org/apache/lucene/search/FieldCacheImpl.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/search/FieldCacheImpl.java	(révision 1340914)
+++ lucene/core/src/java/org/apache/lucene/search/FieldCacheImpl.java	(copie de travail)
@@ -1071,14 +1071,12 @@
     }
   }
 
-  private static boolean DEFAULT_FASTER_BUT_MORE_RAM = true;
-
   public DocTermsIndex getTermsIndex(AtomicReader reader, String field) throws IOException {
-    return getTermsIndex(reader, field, DEFAULT_FASTER_BUT_MORE_RAM);
+    return getTermsIndex(reader, field, PackedInts.DEFAULT);
   }
 
-  public DocTermsIndex getTermsIndex(AtomicReader reader, String field, boolean fasterButMoreRAM) throws IOException {
-    return (DocTermsIndex) caches.get(DocTermsIndex.class).get(reader, new Entry(field, Boolean.valueOf(fasterButMoreRAM)), false);
+  public DocTermsIndex getTermsIndex(AtomicReader reader, String field, float acceptableOverheadRatio) throws IOException {
+    return (DocTermsIndex) caches.get(DocTermsIndex.class).get(reader, new Entry(field, acceptableOverheadRatio), false);
   }
 
   static class DocTermsIndexCache extends Cache {
@@ -1092,7 +1090,7 @@
 
       Terms terms = reader.terms(entryKey.field);
 
-      final boolean fasterButMoreRAM = ((Boolean) entryKey.custom).booleanValue();
+      final float acceptableOverheadRatio = ((Float) entryKey.custom).floatValue();
 
       final PagedBytes bytes = new PagedBytes(15);
 
@@ -1142,8 +1140,8 @@
         startNumUniqueTerms = 1;
       }
 
-      GrowableWriter termOrdToBytesOffset = new GrowableWriter(startBytesBPV, 1+startNumUniqueTerms, fasterButMoreRAM);
-      final GrowableWriter docToTermOrd = new GrowableWriter(startTermsBPV, maxDoc, fasterButMoreRAM);
+      GrowableWriter termOrdToBytesOffset = new GrowableWriter(startBytesBPV, 1+startNumUniqueTerms, acceptableOverheadRatio);
+      final GrowableWriter docToTermOrd = new GrowableWriter(startTermsBPV, maxDoc, acceptableOverheadRatio);
 
       // 0 is reserved for "unset"
       bytes.copyUsingLengthPrefix(new BytesRef());
@@ -1219,11 +1217,11 @@
   // TODO: this if DocTermsIndex was already created, we
   // should share it...
   public DocTerms getTerms(AtomicReader reader, String field) throws IOException {
-    return getTerms(reader, field, DEFAULT_FASTER_BUT_MORE_RAM);
+    return getTerms(reader, field, PackedInts.DEFAULT);
   }
 
-  public DocTerms getTerms(AtomicReader reader, String field, boolean fasterButMoreRAM) throws IOException {
-    return (DocTerms) caches.get(DocTerms.class).get(reader, new Entry(field, Boolean.valueOf(fasterButMoreRAM)), false);
+  public DocTerms getTerms(AtomicReader reader, String field, float acceptableOverheadRatio) throws IOException {
+    return (DocTerms) caches.get(DocTerms.class).get(reader, new Entry(field, acceptableOverheadRatio), false);
   }
 
   static final class DocTermsCache extends Cache {
@@ -1237,7 +1235,7 @@
 
       Terms terms = reader.terms(entryKey.field);
 
-      final boolean fasterButMoreRAM = ((Boolean) entryKey.custom).booleanValue();
+      final float acceptableOverheadRatio = ((Float) entryKey.custom).floatValue();
 
       final int termCountHardLimit = reader.maxDoc();
 
@@ -1268,7 +1266,7 @@
         startBPV = 1;
       }
 
-      final GrowableWriter docToOffset = new GrowableWriter(startBPV, reader.maxDoc(), fasterButMoreRAM);
+      final GrowableWriter docToOffset = new GrowableWriter(startBPV, reader.maxDoc(), acceptableOverheadRatio);
       
       // pointer==0 means not set
       bytes.copyUsingLengthPrefix(new BytesRef());
Index: lucene/core/src/java/org/apache/lucene/search/FieldCache.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/search/FieldCache.java	(révision 1340914)
+++ lucene/core/src/java/org/apache/lucene/search/FieldCache.java	(copie de travail)
@@ -494,7 +494,7 @@
    *  faster lookups (default is "true").  Note that the
    *  first call for a given reader and field "wins",
    *  subsequent calls will share the same cache entry. */
-  public DocTerms getTerms (AtomicReader reader, String field, boolean fasterButMoreRAM)
+  public DocTerms getTerms (AtomicReader reader, String field, float acceptableOverheadRatio)
   throws IOException;
 
   /** Returned by {@link #getTermsIndex} */
@@ -571,7 +571,7 @@
    *  faster lookups (default is "true").  Note that the
    *  first call for a given reader and field "wins",
    *  subsequent calls will share the same cache entry. */
-  public DocTermsIndex getTermsIndex (AtomicReader reader, String field, boolean fasterButMoreRAM)
+  public DocTermsIndex getTermsIndex (AtomicReader reader, String field, float acceptableOverheadRatio)
   throws IOException;
 
   /**
