@jcoreio/precise-bs
Version:
binary search and related utility functions
254 lines (243 loc) • 11.8 kB
JavaScript
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const DEFAULT_COMPARATOR = (a, b) => a < b ? -1 : a > b ? 1 : 0;
export function binarySearch(array, find, comparator = DEFAULT_COMPARATOR, low = 0, high = array.length - 1) {
let i, comparison;
while (low <= high) {
i = Math.floor((low + high) / 2);
comparison = comparator(array[i], find);
if (comparison < 0) {
low = i + 1;
continue;
}
if (comparison > 0) {
high = i - 1;
continue;
}
return i;
}
return low;
}
/**
* Finds the index of the greatest element less than a given search value in a sorted array
* using a binary search. If the given search value is less than or equal to all elements in the
* array, returns -1.
*
* @param {array} the array to search in.
* @param {find} the value to search for.
* @param {comparator} two-argument function that returns < 0 if
* the first argument is less than the second; > 0 if the first
* argument is greater; and 0 otherwise. (defaults to <code>a - b</code>)
* @param {low} the lower bound of the range in <code>array</code> to
* search in (defaults to 0)
* @param {high} the upper bound of the range in <code>array</code> to
* search in (defaults to <code>array.length - 1</code>)
*/
export function lowerIndex(array, find, comparator = DEFAULT_COMPARATOR, low, high) {
return binarySearch(array, find, comparator, low, high) - 1;
}
/**
* Finds the entry with the greatest element less than a given search value in a sorted array
* using a binary search. If the search value is less than or equal to all elements in the
* array, returns [-1, undefined].
*
* @param {array} the array to search in.
* @param {find} the value to search for.
* @param {comparator} two-argument function that returns < 0 if
* the first argument is less than the second; > 0 if the first
* argument is greater; and 0 otherwise. (defaults to <code>a - b</code>)
* @param {low} the lower bound of the range in <code>array</code> to
* search in (defaults to 0)
* @param {high} the upper bound of the range in <code>array</code> to
* search in (defaults to <code>array.length - 1</code>)
*/
export function lowerEntry(array, find, comparator = DEFAULT_COMPARATOR, low, high) {
const index = lowerIndex(array, find, comparator, low, high);
return [index, array[index]];
}
/**
* Finds the greatest element less than a given value in a sorted array
* using a binary search. If the given value is less than or equal to all elements in the
* array, returns undefined.
*
* @param {array} the array to search in.
* @param {find} the value to search for.
* @param {comparator} two-argument function that returns < 0 if
* the first argument is less than the second; > 0 if the first
* argument is greater; and 0 otherwise. (defaults to <code>a - b</code>)
* @param {low} the lower bound of the range in <code>array</code> to
* search in (defaults to 0)
* @param {high} the upper bound of the range in <code>array</code> to
* search in (defaults to <code>array.length - 1</code>)
*/
export function lowerValue(array, find, comparator = DEFAULT_COMPARATOR, low, high) {
const index = lowerIndex(array, find, comparator, low, high);
return array[index];
}
/**
* Finds the index of the greatest element less than or equal to a given search value in a sorted array
* using a binary search. If the given value is less than all elements in the
* array, returns -1.
*
* @param {array} the array to search in.
* @param {find} the value to search for.
* @param {comparator} two-argument function that returns < 0 if
* the first argument is less than the second; > 0 if the first
* argument is greater; and 0 otherwise. (defaults to <code>a - b</code>)
* @param {low} the lower bound of the range in <code>array</code> to
* search in (defaults to 0)
* @param {high} the upper bound of the range in <code>array</code> to
* search in (defaults to <code>array.length - 1</code>)
*/
export function floorIndex(array, find, comparator = DEFAULT_COMPARATOR, low, high) {
const i = binarySearch(array, find, comparator, low, high);
return i === array.length || comparator(array[i], find) > 0 ? i - 1 : i;
}
/**
* Finds the entry with the greatest element less than or equal to a given search value in a sorted array
* using a binary search. If the given value is less than all elements in the
* array, returns [-1, undefined].
*
* @param {array} the array to search in.
* @param {find} the value to search for.
* @param {comparator} two-argument function that returns < 0 if
* the first argument is less than the second; > 0 if the first
* argument is greater; and 0 otherwise. (defaults to <code>a - b</code>)
* @param {low} the lower bound of the range in <code>array</code> to
* search in (defaults to 0)
* @param {high} the upper bound of the range in <code>array</code> to
* search in (defaults to <code>array.length - 1</code>)
*/
export function floorEntry(array, find, comparator = DEFAULT_COMPARATOR, low, high) {
const index = floorIndex(array, find, comparator, low, high);
return [index, array[index]];
}
/**
* Finds the greatest element less than or equal to a given search value in a sorted array
* using a binary search. If the given value is less than all elements in the
* array, returns undefined.
*
* @param {array} the array to search in.
* @param {find} the value to search for.
* @param {comparator} two-argument function that returns < 0 if
* the first argument is less than the second; > 0 if the first
* argument is greater; and 0 otherwise. (defaults to <code>a - b</code>)
* @param {low} the lower bound of the range in <code>array</code> to
* search in (defaults to 0)
* @param {high} the upper bound of the range in <code>array</code> to
* search in (defaults to <code>array.length - 1</code>)
*/
export function floorValue(array, find, comparator = DEFAULT_COMPARATOR, low, high) {
const index = floorIndex(array, find, comparator, low, high);
return array[index];
}
/**
* Finds the index of the least element greater than or equal to a given search value in a sorted array
* using a binary search. If the given value is greater than all elements in the
* array, returns the length of the array.
*
* @param {array} the array to search in.
* @param {find} the value to search for.
* @param {comparator} two-argument function that returns < 0 if
* the first argument is less than the second; > 0 if the first
* argument is greater; and 0 otherwise. (defaults to <code>a - b</code>)
* @param {low} the lower bound of the range in <code>array</code> to
* search in (defaults to 0)
* @param {high} the upper bound of the range in <code>array</code> to
* search in (defaults to <code>array.length - 1</code>)
*/
export const ceilingIndex = binarySearch;
/**
* Finds the entry with the least element greater than or equal to a given search value in a sorted array
* using a binary search. If the given value is greater than all elements in the
* array, returns [array.length, undefined].
*
* @param {array} the array to search in.
* @param {find} the value to search for.
* @param {comparator} two-argument function that returns < 0 if
* the first argument is less than the second; > 0 if the first
* argument is greater; and 0 otherwise. (defaults to <code>a - b</code>)
* @param {low} the lower bound of the range in <code>array</code> to
* search in (defaults to 0)
* @param {high} the upper bound of the range in <code>array</code> to
* search in (defaults to <code>array.length - 1</code>)
*/
export function ceilingEntry(array, find, comparator = DEFAULT_COMPARATOR, low, high) {
const index = ceilingIndex(array, find, comparator, low, high);
return [index, array[index]];
}
/**
* Finds the least element greater than or equal to a given search value in a sorted array
* using a binary search. If the given value is greater than all elements in the
* array, returns undefined.
*
* @param {array} the array to search in.
* @param {find} the value to search for.
* @param {comparator} two-argument function that returns < 0 if
* the first argument is less than the second; > 0 if the first
* argument is greater; and 0 otherwise. (defaults to <code>a - b</code>)
* @param {low} the lower bound of the range in <code>array</code> to
* search in (defaults to 0)
* @param {high} the upper bound of the range in <code>array</code> to
* search in (defaults to <code>array.length - 1</code>)
*/
export function ceilingValue(array, find, comparator = DEFAULT_COMPARATOR, low, high) {
const index = ceilingIndex(array, find, comparator, low, high);
return array[index];
}
/**
* Finds the index of the least element greater than a given value in a sorted array
* using a binary search. If the given value is greater than or equal to all elements in the
* array, returns the length of the array.
*
* @param {array} the array to search in.
* @param {find} the value to search for.
* @param {comparator} two-argument function that returns < 0 if
* the first argument is less than the second; > 0 if the first
* argument is greater; and 0 otherwise. (defaults to <code>a - b</code>)
* @param {low} the lower bound of the range in <code>array</code> to
* search in (defaults to 0)
* @param {high} the upper bound of the range in <code>array</code> to
* search in (defaults to <code>array.length - 1</code>)
*/
export function higherIndex(array, find, comparator = DEFAULT_COMPARATOR, low, high) {
const i = binarySearch(array, find, comparator, low, high);
return i < array.length && comparator(array[i], find) <= 0 ? i + 1 : i;
}
/**
* Finds the entry with the least element greater than a given value in a sorted array
* using a binary search. If the given value is greater than or equal to all elements in the
* array, returns [array.length, undefined].
*
* @param {array} the array to search in.
* @param {find} the value to search for.
* @param {comparator} two-argument function that returns < 0 if
* the first argument is less than the second; > 0 if the first
* argument is greater; and 0 otherwise. (defaults to <code>a - b</code>)
* @param {low} the lower bound of the range in <code>array</code> to
* search in (defaults to 0)
* @param {high} the upper bound of the range in <code>array</code> to
* search in (defaults to <code>array.length - 1</code>)
*/
export function higherEntry(array, find, comparator = DEFAULT_COMPARATOR, low, high) {
const index = higherIndex(array, find, comparator, low, high);
return [index, array[index]];
}
/**
* Finds the least element greater than a given value in a sorted array
* using a binary search. If the given value is greater than or equal to all elements in the
* array, returns undefined.
*
* @param {array} the array to search in.
* @param {find} the value to search for.
* @param {comparator} two-argument function that returns < 0 if
* the first argument is less than the second; > 0 if the first
* argument is greater; and 0 otherwise. (defaults to <code>a - b</code>)
* @param {low} the lower bound of the range in <code>array</code> to
* search in (defaults to 0)
* @param {high} the upper bound of the range in <code>array</code> to
* search in (defaults to <code>array.length - 1</code>)
*/
export function higherValue(array, find, comparator = DEFAULT_COMPARATOR, low, high) {
const index = higherIndex(array, find, comparator, low, high);
return array[index];
}