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. */ /** * Non-specialized {@link BulkOperation} for {@link PackedInts.Format#PACKED}. */ class BulkOperationPacked extends BulkOperation { private final int bitsPerValue; private final int blockCount; private final int valueCount; private final long mask; public BulkOperationPacked(int bitsPerValue) { this.bitsPerValue = bitsPerValue; assert bitsPerValue > 0 && bitsPerValue <= 64; int blocks = bitsPerValue; while ((blocks & 1) == 0) { blocks >>>= 1; } this.blockCount = blocks; this.valueCount = 64 * blockCount / bitsPerValue; if (bitsPerValue == 64) { this.mask = ~0L; } else { this.mask = (1L << bitsPerValue) - 1; } assert valueCount * bitsPerValue == 64 * blockCount; } @Override public int blockCount() { return blockCount; } @Override public int valueCount() { return valueCount; } @Override public void decode(long[] blocks, int blocksOffset, long[] values, int valuesOffset, int iterations) { int bitsLeft = 64; for (int i = 0; i < valueCount * iterations; ++i) { bitsLeft -= bitsPerValue; if (bitsLeft < 0) { values[valuesOffset++] = ((blocks[blocksOffset++] & ((1L << (bitsPerValue + bitsLeft)) - 1)) << -bitsLeft) | (blocks[blocksOffset] >>> (64 + bitsLeft)); bitsLeft += 64; } else { values[valuesOffset++] = (blocks[blocksOffset] >>> bitsLeft) & mask; } } } @Override public void decode(byte[] blocks, int blocksOffset, long[] values, int valuesOffset, int iterations) { int blockBitsLeft = 8; int valueBitsLeft = bitsPerValue; long nextValue = 0; for (int end = valuesOffset + iterations * valueCount; valuesOffset < end; ) { if (valueBitsLeft > blockBitsLeft) { nextValue |= (blocks[blocksOffset++] & ((1L << blockBitsLeft) - 1)) << (valueBitsLeft - blockBitsLeft); valueBitsLeft -= blockBitsLeft; blockBitsLeft = 8; } else { nextValue |= ((blocks[blocksOffset] & 0xFFL) >>> (blockBitsLeft - valueBitsLeft)) & ((1L << valueBitsLeft) - 1); values[valuesOffset++] = nextValue; nextValue = 0; blockBitsLeft -= valueBitsLeft; valueBitsLeft = bitsPerValue; } } } @Override public void decode(long[] blocks, 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; for (int i = 0; i < valueCount * iterations; ++i) { bitsLeft -= bitsPerValue; if (bitsLeft < 0) { values[valuesOffset++] = (int) (((blocks[blocksOffset++] & ((1L << (bitsPerValue + bitsLeft)) - 1)) << -bitsLeft) | (blocks[blocksOffset] >>> (64 + bitsLeft))); bitsLeft += 64; } else { values[valuesOffset++] = (int) ((blocks[blocksOffset] >>> bitsLeft) & mask); } } } @Override public void decode(byte[] blocks, int blocksOffset, int[] values, int valuesOffset, int iterations) { if (bitsPerValue > 32) { throw new UnsupportedOperationException("Cannot decode " + bitsPerValue + "-bits values into an int[]"); } int blockBitsLeft = 8; int valueBitsLeft = bitsPerValue; int nextValue = 0; for (int end = valuesOffset + iterations * valueCount; valuesOffset < end; ) { if (valueBitsLeft > blockBitsLeft) { nextValue |= (blocks[blocksOffset++] & ((1L << blockBitsLeft) - 1)) << (valueBitsLeft - blockBitsLeft); valueBitsLeft -= blockBitsLeft; blockBitsLeft = 8; } else { nextValue |= ((blocks[blocksOffset] & 0xFFL) >>> (blockBitsLeft - valueBitsLeft)) & ((1L << valueBitsLeft) - 1); values[valuesOffset++] = nextValue; nextValue = 0; blockBitsLeft -= valueBitsLeft; valueBitsLeft = bitsPerValue; } } } @Override public void encode(long[] values, int valuesOffset, long[] blocks, int blocksOffset, int iterations) { long nextBlock = 0; int bitsLeft = 64; for (int i = 0; i < valueCount * iterations; ++i) { bitsLeft -= bitsPerValue; if (bitsLeft > 0) { nextBlock |= values[valuesOffset++] << bitsLeft; } else if (bitsLeft == 0) { nextBlock |= values[valuesOffset++]; blocks[blocksOffset++] = nextBlock; nextBlock = 0; bitsLeft = 64; } else { // bitsLeft < 0 nextBlock |= values[valuesOffset] >>> -bitsLeft; blocks[blocksOffset++] = nextBlock; nextBlock = (values[valuesOffset++] & ((1L << -bitsLeft) - 1)) << (64 + bitsLeft); bitsLeft += 64; } } } @Override public void encode(int[] values, int valuesOffset, long[] blocks, int blocksOffset, int iterations) { long nextBlock = 0; int bitsLeft = 64; for (int i = 0; i < valueCount * iterations; ++i) { bitsLeft -= bitsPerValue; if (bitsLeft > 0) { nextBlock |= (values[valuesOffset++] & 0xFFFFFFFFL) << bitsLeft; } else if (bitsLeft == 0) { nextBlock |= (values[valuesOffset++] & 0xFFFFFFFFL); blocks[blocksOffset++] = nextBlock; nextBlock = 0; bitsLeft = 64; } else { // bitsLeft < 0 nextBlock |= (values[valuesOffset] & 0xFFFFFFFFL) >>> -bitsLeft; blocks[blocksOffset++] = nextBlock; nextBlock = (values[valuesOffset++] & ((1L << -bitsLeft) - 1)) << (64 + bitsLeft); bitsLeft += 64; } } } @Override public void encode(long[] values, int valuesOffset, byte[] blocks, int blocksOffset, int iterations) { long nextBlock = 0; int bitsLeft = 64; for (int i = 0; i < valueCount * iterations; ++i) { bitsLeft -= bitsPerValue; if (bitsLeft > 0) { nextBlock |= values[valuesOffset++] << bitsLeft; } else if (bitsLeft == 0) { nextBlock |= values[valuesOffset++]; blocksOffset = writeLong(nextBlock, blocks, blocksOffset); nextBlock = 0; bitsLeft = 64; } else { // bitsLeft < 0 nextBlock |= values[valuesOffset] >>> -bitsLeft; blocksOffset = writeLong(nextBlock, blocks, blocksOffset); nextBlock = (values[valuesOffset++] & ((1L << -bitsLeft) - 1)) << (64 + bitsLeft); bitsLeft += 64; } } } @Override public void encode(int[] values, int valuesOffset, byte[] blocks, int blocksOffset, int iterations) { long nextBlock = 0; int bitsLeft = 64; for (int i = 0; i < valueCount * iterations; ++i) { bitsLeft -= bitsPerValue; if (bitsLeft > 0) { nextBlock |= (values[valuesOffset++] & 0xFFFFFFFFL) << bitsLeft; } else if (bitsLeft == 0) { nextBlock |= (values[valuesOffset++] & 0xFFFFFFFFL); blocksOffset = writeLong(nextBlock, blocks, blocksOffset); nextBlock = 0; bitsLeft = 64; } else { // bitsLeft < 0 nextBlock |= (values[valuesOffset] & 0xFFFFFFFFL) >>> -bitsLeft; blocksOffset = writeLong(nextBlock, blocks, blocksOffset); nextBlock = (values[valuesOffset++] & ((1L << -bitsLeft) - 1)) << (64 + bitsLeft); bitsLeft += 64; } } } }