/**
* diqube: Distributed Query Base.
*
* Copyright (C) 2015 Bastian Gloeckle
*
* This file is part of diqube.
*
* diqube is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.diqube.data.types.lng.array;
import java.util.Arrays;
/**
* Utility methods for {@link CompressedLongArray}.
*
* @author Bastian Gloeckle
*/
public class CompressedLongArrayUtil {
/**
* Execute a binary search on a sorted {@link CompressedLongArray}.
*
* <p>
* Searches the whole array for the given value.
*
* <p>
* Note that this method does only make sense to be executed on constant-access-time implementations of
* {@link CompressedLongArray} (i.e. not on {@link RunLengthLongArray}).
*
* @return Index >= 0 if found. If not found, the result is (-1-instertionpoint), means < 0 and it might be -(high+2).
* This is equal to the result of {@link Arrays#binarySearch(long[], long)}.
*/
public static int binarySearch(CompressedLongArray<?> sortedArray, long value) {
if (sortedArray.size() == 0)
return -1 - 0; // Insertion point 0
return binarySearch(sortedArray, value, 0, sortedArray.size() - 1);
}
/**
* Execute a binary search on a sub-array of a sorted {@link CompressedLongArray}.
*
* <p>
* Note that this method does only make sense to be executed on constant-access-time implementations of
* {@link CompressedLongArray} (i.e. not on {@link RunLengthLongArray}).
*
* @param lo
* lowest index to start search (inclusive).
* @param hi
* highest index to start search (inclusive).
* @return Index >= 0 if found. If not found, the result is (-1-instertionpoint), means < 0 and it might be -(high+2).
* This is equal to the result of {@link Arrays#binarySearch(long[], long)}.
*/
private static int binarySearch(CompressedLongArray<?> sortedArray, long value, int lo, int high) {
// TODO #5 instead of decompressing a lot of values here, we should compress the search value itself and then search
// for it in the compressed space. This should be implemented in CompressedLongArray.
long decompressed = sortedArray.get(lo);
if (decompressed == value)
return lo;
if (decompressed > value)
return -1;
decompressed = sortedArray.get(high);
if (decompressed == value)
return high;
if (decompressed < value)
return -2 - high;
while (true) {
if (high - lo <= 10) {
for (int i = lo + 1; i <= high - 1; i++) {
decompressed = sortedArray.get(i);
if (decompressed == value)
return i;
if (decompressed > value) {
return -1 - i;
}
}
return -1 - high;
}
int mid = lo + ((high - lo) / 2);
long midValue = sortedArray.get(mid);
if (midValue == value)
return mid;
if (midValue > value)
high = mid;
else
lo = mid;
}
}
}