private void WriteBlock() { Debug.Assert(BlockChunks > 0); FieldsIndexOut.WriteVInt(BlockChunks); // The trick here is that we only store the difference from the average start // pointer or doc base, this helps save bits per value. // And in order to prevent a few chunks that would be far from the average to // raise the number of bits per value for all of them, we only encode blocks // of 1024 chunks at once // See LUCENE-4512 // doc bases int avgChunkDocs; if (BlockChunks == 1) { avgChunkDocs = 0; } else { avgChunkDocs = (int)Math.Round((float)(BlockDocs - DocBaseDeltas[BlockChunks - 1]) / (BlockChunks - 1)); } FieldsIndexOut.WriteVInt(TotalDocs - BlockDocs); // docBase FieldsIndexOut.WriteVInt(avgChunkDocs); int docBase = 0; long maxDelta = 0; for (int i = 0; i < BlockChunks; ++i) { int delta = docBase - avgChunkDocs * i; maxDelta |= MoveSignToLowOrderBit(delta); docBase += DocBaseDeltas[i]; } int bitsPerDocBase = PackedInts.BitsRequired(maxDelta); FieldsIndexOut.WriteVInt(bitsPerDocBase); PackedInts.Writer writer = PackedInts.GetWriterNoHeader(FieldsIndexOut, PackedInts.Format.PACKED, BlockChunks, bitsPerDocBase, 1); docBase = 0; for (int i = 0; i < BlockChunks; ++i) { long delta = docBase - avgChunkDocs * i; Debug.Assert(PackedInts.BitsRequired(MoveSignToLowOrderBit(delta)) <= writer.BitsPerValue()); writer.Add(MoveSignToLowOrderBit(delta)); docBase += DocBaseDeltas[i]; } writer.Finish(); // start pointers FieldsIndexOut.WriteVLong(FirstStartPointer); long avgChunkSize; if (BlockChunks == 1) { avgChunkSize = 0; } else { avgChunkSize = (MaxStartPointer - FirstStartPointer) / (BlockChunks - 1); } FieldsIndexOut.WriteVLong(avgChunkSize); long startPointer = 0; maxDelta = 0; for (int i = 0; i < BlockChunks; ++i) { startPointer += StartPointerDeltas[i]; long delta = startPointer - avgChunkSize * i; maxDelta |= MoveSignToLowOrderBit(delta); } int bitsPerStartPointer = PackedInts.BitsRequired(maxDelta); FieldsIndexOut.WriteVInt(bitsPerStartPointer); writer = PackedInts.GetWriterNoHeader(FieldsIndexOut, PackedInts.Format.PACKED, BlockChunks, bitsPerStartPointer, 1); startPointer = 0; for (int i = 0; i < BlockChunks; ++i) { startPointer += StartPointerDeltas[i]; long delta = startPointer - avgChunkSize * i; Debug.Assert(PackedInts.BitsRequired(MoveSignToLowOrderBit(delta)) <= writer.BitsPerValue()); writer.Add(MoveSignToLowOrderBit(delta)); } writer.Finish(); }