org.apache.mahout.math.BinarySearch Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mahout-math Show documentation
Show all versions of mahout-math Show documentation
High performance scientific and technical computing data structures and methods,
mostly based on CERN's
Colt Java API
/*
* 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.
*/
package org.apache.mahout.math;
import java.util.Comparator;
public final class BinarySearch {
private BinarySearch() {}
/**
* Performs a binary search for the specified element in the specified
* ascending sorted array. Searching in an unsorted array has an undefined
* result. It's also undefined which element is found if there are multiple
* occurrences of the same element.
*
* @param array
* the sorted {@code byte} array to search.
* @param value
* the {@code byte} element to find.
* @param from
* the first index to sort, inclusive.
* @param to
* the last index to sort, inclusive.
* @return the non-negative index of the element, or a negative index which is
* {@code -index - 1} where the element would be inserted.
*/
public static int binarySearchFromTo(byte[] array, byte value, int from, int to) {
int mid = -1;
while (from <= to) {
mid = (from + to) >>> 1;
if (value > array[mid]) {
from = mid + 1;
} else if (value == array[mid]) {
return mid;
} else {
to = mid - 1;
}
}
if (mid < 0) {
return -1;
}
return -mid - (value < array[mid] ? 1 : 2);
}
/**
* Performs a binary search for the specified element in the specified
* ascending sorted array. Searching in an unsorted array has an undefined
* result. It's also undefined which element is found if there are multiple
* occurrences of the same element.
*
* @param array
* the sorted {@code char} array to search.
* @param value
* the {@code char} element to find.
* @param from
* the first index to sort, inclusive.
* @param to
* the last index to sort, inclusive.
* @return the non-negative index of the element, or a negative index which is
* {@code -index - 1} where the element would be inserted.
*/
public static int binarySearchFromTo(char[] array, char value, int from, int to) {
int mid = -1;
while (from <= to) {
mid = (from + to) >>> 1;
if (value > array[mid]) {
from = mid + 1;
} else if (value == array[mid]) {
return mid;
} else {
to = mid - 1;
}
}
if (mid < 0) {
return -1;
}
return -mid - (value < array[mid] ? 1 : 2);
}
/**
* Performs a binary search for the specified element in the specified
* ascending sorted array. Searching in an unsorted array has an undefined
* result. It's also undefined which element is found if there are multiple
* occurrences of the same element.
*
* @param array
* the sorted {@code double} array to search.
* @param value
* the {@code double} element to find.
* @param from
* the first index to sort, inclusive.
* @param to
* the last index to sort, inclusive.
* @return the non-negative index of the element, or a negative index which is
* {@code -index - 1} where the element would be inserted.
*/
public static int binarySearchFromTo(double[] array, double value, int from, int to) {
long longBits = Double.doubleToLongBits(value);
int mid = -1;
while (from <= to) {
mid = (from + to) >>> 1;
if (lessThan(array[mid], value)) {
from = mid + 1;
} else if (longBits == Double.doubleToLongBits(array[mid])) {
return mid;
} else {
to = mid - 1;
}
}
if (mid < 0) {
return -1;
}
return -mid - (lessThan(value, array[mid]) ? 1 : 2);
}
/**
* Performs a binary search for the specified element in the specified
* ascending sorted array. Searching in an unsorted array has an undefined
* result. It's also undefined which element is found if there are multiple
* occurrences of the same element.
*
* @param array
* the sorted {@code float} array to search.
* @param value
* the {@code float} element to find.
* @param from
* the first index to sort, inclusive.
* @param to
* the last index to sort, inclusive.
* @return the non-negative index of the element, or a negative index which is
* {@code -index - 1} where the element would be inserted.
*/
public static int binarySearchFromTo(float[] array, float value, int from, int to) {
int intBits = Float.floatToIntBits(value);
int mid = -1;
while (from <= to) {
mid = (from + to) >>> 1;
if (lessThan(array[mid], value)) {
from = mid + 1;
} else if (intBits == Float.floatToIntBits(array[mid])) {
return mid;
} else {
to = mid - 1;
}
}
if (mid < 0) {
return -1;
}
return -mid - (lessThan(value, array[mid]) ? 1 : 2);
}
/**
* Performs a binary search for the specified element in the specified
* ascending sorted array. Searching in an unsorted array has an undefined
* result. It's also undefined which element is found if there are multiple
* occurrences of the same element.
*
* @param array
* the sorted {@code int} array to search.
* @param value
* the {@code int} element to find.
* @param from
* the first index to sort, inclusive.
* @param to
* the last index to sort, inclusive.
* @return the non-negative index of the element, or a negative index which is
* {@code -index - 1} where the element would be inserted.
*/
public static int binarySearchFromTo(int[] array, int value, int from, int to) {
int mid = -1;
while (from <= to) {
mid = (from + to) >>> 1;
if (value > array[mid]) {
from = mid + 1;
} else if (value == array[mid]) {
return mid;
} else {
to = mid - 1;
}
}
if (mid < 0) {
return -1;
}
return -mid - (value < array[mid] ? 1 : 2);
}
/**
* Performs a binary search for the specified element in the specified
* ascending sorted array. Searching in an unsorted array has an undefined
* result. It's also undefined which element is found if there are multiple
* occurrences of the same element.
*
* @param array
* the sorted {@code long} array to search.
* @param value
* the {@code long} element to find.
* @param from
* the first index to sort, inclusive.
* @param to
* the last index to sort, inclusive.
* @return the non-negative index of the element, or a negative index which is
* {@code -index - 1} where the element would be inserted.
*/
public static int binarySearchFromTo(long[] array, long value, int from, int to) {
int mid = -1;
while (from <= to) {
mid = (from + to) >>> 1;
if (value > array[mid]) {
from = mid + 1;
} else if (value == array[mid]) {
return mid;
} else {
to = mid - 1;
}
}
if (mid < 0) {
return -1;
}
return -mid - (value < array[mid] ? 1 : 2);
}
/**
* Performs a binary search for the specified element in the specified
* ascending sorted array. Searching in an unsorted array has an undefined
* result. It's also undefined which element is found if there are multiple
* occurrences of the same element.
*
* @param array
* the sorted {@code Object} array to search.
* @param object
* the {@code Object} element to find
* @param from
* the first index to sort, inclusive.
* @param to
* the last index to sort, inclusive.
* @return the non-negative index of the element, or a negative index which is
* {@code -index - 1} where the element would be inserted.
*
*/
public static > int binarySearchFromTo(T[] array, T object, int from, int to) {
if (array.length == 0) {
return -1;
}
int mid = 0;
int result = 0;
while (from <= to) {
mid = (from + to) >>> 1;
if ((result = array[mid].compareTo(object)) < 0) {
from = mid + 1;
} else if (result == 0) {
return mid;
} else {
to = mid - 1;
}
}
return -mid - (result >= 0 ? 1 : 2);
}
/**
* Performs a binary search for the specified element in the specified
* ascending sorted array using the {@code Comparator} to compare elements.
* Searching in an unsorted array has an undefined result. It's also undefined
* which element is found if there are multiple occurrences of the same
* element.
*
* @param array
* the sorted array to search
* @param object
* the element to find
* @param from
* the first index to sort, inclusive.
* @param to
* the last index to sort, inclusive.
* @param comparator
* the {@code Comparator} used to compare the elements.
* @return the non-negative index of the element, or a negative index which
*/
public static int binarySearchFromTo(T[] array, T object, int from, int to, Comparator super T> comparator) {
int mid = 0;
int result = 0;
while (from <= to) {
mid = (from + to) >>> 1;
if ((result = comparator.compare(array[mid], object)) < 0) {
from = mid + 1;
} else if (result == 0) {
return mid;
} else {
to = mid - 1;
}
}
return -mid - (result >= 0 ? 1 : 2);
}
/**
* Performs a binary search for the specified element in the specified
* ascending sorted array. Searching in an unsorted array has an undefined
* result. It's also undefined which element is found if there are multiple
* occurrences of the same element.
*
* @param array
* the sorted {@code short} array to search.
* @param value
* the {@code short} element to find.
* @param from
* the first index to sort, inclusive.
* @param to
* the last index to sort, inclusive.
* @return the non-negative index of the element, or a negative index which is
* {@code -index - 1} where the element would be inserted.
*/
public static int binarySearchFromTo(short[] array, short value, int from, int to) {
int mid = -1;
while (from <= to) {
mid = (from + to) >>> 1;
if (value > array[mid]) {
from = mid + 1;
} else if (value == array[mid]) {
return mid;
} else {
to = mid - 1;
}
}
if (mid < 0) {
return -1;
}
return -mid - (value < array[mid] ? 1 : 2);
}
private static boolean lessThan(double double1, double double2) {
// A slightly specialized version of
// Double.compare(double1, double2) < 0.
// Non-zero and non-NaN checking.
if (double1 < double2) {
return true;
}
if (double1 > double2) {
return false;
}
if (double1 == double2 && double1 != 0.0) {
return false;
}
// NaNs are equal to other NaNs and larger than any other double.
if (Double.isNaN(double1)) {
return false;
}
if (Double.isNaN(double2)) {
return true;
}
// Deal with +0.0 and -0.0.
long d1 = Double.doubleToRawLongBits(double1);
long d2 = Double.doubleToRawLongBits(double2);
return d1 < d2;
}
private static boolean lessThan(float float1, float float2) {
// A slightly specialized version of Float.compare(float1, float2) < 0.
// Non-zero and non-NaN checking.
if (float1 < float2) {
return true;
}
if (float1 > float2) {
return false;
}
if (float1 == float2 && float1 != 0.0f) {
return false;
}
// NaNs are equal to other NaNs and larger than any other float
if (Float.isNaN(float1)) {
return false;
}
if (Float.isNaN(float2)) {
return true;
}
// Deal with +0.0 and -0.0
int f1 = Float.floatToRawIntBits(float1);
int f2 = Float.floatToRawIntBits(float2);
return f1 < f2;
}
}