blob: 2c2972987967f4c1cfd2c72a980731adb7aea9c8 [file] [log] [blame]
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.util.Arrays;
/**
* Utility class to buffer a list of signed longs in memory. This class only
* supports appending and is optimized for the case where values are close to
* each other.
* @lucene.internal
*/
public final class AppendingLongBuffer extends AbstractAppendingLongBuffer {
/** @param initialPageCount the initial number of pages
* @param pageSize the size of a single page */
public AppendingLongBuffer(int initialPageCount, int pageSize) {
super(initialPageCount, pageSize);
}
/** Create an {@link AppendingLongBuffer} with initialPageCount=16 and
* pageSize=1024. */
public AppendingLongBuffer() {
this(16, 1024);
}
@Override
long get(int block, int element) {
if (block == valuesOff) {
return pending[element];
} else if (deltas[block] == null) {
return minValues[block];
} else {
return minValues[block] + deltas[block].get(element);
}
}
@Override
void packPendingValues() {
assert pendingOff == pending.length;
// compute max delta
long minValue = pending[0];
long maxValue = pending[0];
for (int i = 1; i < pendingOff; ++i) {
minValue = Math.min(minValue, pending[i]);
maxValue = Math.max(maxValue, pending[i]);
}
final long delta = maxValue - minValue;
minValues[valuesOff] = minValue;
if (delta != 0) {
// build a new packed reader
final int bitsRequired = delta < 0 ? 64 : PackedInts.bitsRequired(delta);
for (int i = 0; i < pendingOff; ++i) {
pending[i] -= minValue;
}
final PackedInts.Mutable mutable = PackedInts.getMutable(pendingOff, bitsRequired, PackedInts.COMPACT);
for (int i = 0; i < pendingOff; ) {
i += mutable.set(i, pending, i, pendingOff - i);
}
deltas[valuesOff] = mutable;
}
}
/** Return an iterator over the values of this buffer. */
@Override
public Iterator iterator() {
return new Iterator();
}
/** A long iterator. */
public final class Iterator extends AbstractAppendingLongBuffer.Iterator {
Iterator() {
super();
}
@Override
void fillValues() {
if (vOff == valuesOff) {
currentValues = pending;
} else if (deltas[vOff] == null) {
Arrays.fill(currentValues, minValues[vOff]);
} else {
for (int k = 0; k < pending.length; ) {
k += deltas[vOff].get(k, currentValues, k, pending.length - k);
}
for (int k = 0; k < pending.length; ++k) {
currentValues[k] += minValues[vOff];
}
}
}
}
}