/** * Performs a binary search within a specified range. * @param begin The starting index of the search range. * @param end The ending index of the search range. * @param beforeHalf A list of predicates indicating conditions before the midpoint. * @returns A tuple containing the indices representing the binary search state: [begin, half, end]. */ export function binSearch(begin: number, end: number, beforeHalf: boolean[]): [number, number, number] { const gHalf = () => { return Math.floor((end - begin) / 2) + begin; }; for (const pred of beforeHalf) { const half = gHalf(); if (pred) { // Happens before "half" end = half; } else { begin = half; } } const half = gHalf(); console.log(`Checking range: [${begin}, ${end}), ${end - begin} objects, mid ${half}`); return [begin, half, end]; } export async function autoBisect( begin: number, end: number, check: ( begin: number, end: number, index: number ) => Promise) { // Try to find the first index where check() predicates to true. // Assume check() is true at first, for range [begin, end) let index = 0; while (end - begin > 1) { const mid = Math.floor((end - begin) / 2) + begin; if (await check(begin, mid, index)) { // Shrink half range. end = mid; } else { begin = mid; } index++; } return begin; }