From 29a4ee4d888ccb049df9b50a57e3884ce2d4d0f3 Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Tue, 25 Aug 2020 10:59:26 +0100 Subject: [PATCH] feat(arrays): add non-recursive binary search fns - add fixed size binarySearch4/8/16/32() --- packages/arrays/src/binary-search.ts | 58 ++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/packages/arrays/src/binary-search.ts b/packages/arrays/src/binary-search.ts index 0846057c26..6e395b0783 100644 --- a/packages/arrays/src/binary-search.ts +++ b/packages/arrays/src/binary-search.ts @@ -86,6 +86,64 @@ export const binarySearchNumeric = ( return -low - 1; }; +/** + * Non-recursive, optimized binary search for fixed size numeric arrays of 4 + * values. Returns index of `x` or `-index-1` if not found. + * + * @param buf + * @param x + */ +export const binarySearch4 = (buf: ArrayLike, x: number) => { + let idx = buf[2] <= x ? 2 : 0; + idx |= buf[idx + 1] <= x ? 1 : 0; + return buf[idx] === x ? idx : -idx - 1; +}; + +/** + * Non-recursive, optimized binary search for fixed size numeric arrays of 8 + * values. Returns index of `x` or `-index-1` if not found. + * + * @param buf + * @param x + */ +export const binarySearch8 = (buf: ArrayLike, x: number) => { + let idx = buf[4] <= x ? 4 : 0; + idx |= buf[idx + 2] <= x ? 2 : 0; + idx |= buf[idx + 1] <= x ? 1 : 0; + return buf[idx] === x ? idx : -idx - 1; +}; + +/** + * Non-recursive, optimized binary search for fixed size numeric arrays of 16 + * values. Returns index of `x` or `-index-1` if not found. + * + * @param buf + * @param x + */ +export const binarySearch16 = (buf: ArrayLike, x: number) => { + let idx = buf[8] <= x ? 8 : 0; + idx |= buf[idx + 4] <= x ? 4 : 0; + idx |= buf[idx + 2] <= x ? 2 : 0; + idx |= buf[idx + 1] <= x ? 1 : 0; + return buf[idx] === x ? idx : -idx - 1; +}; + +/** + * Non-recursive, optimized binary search for fixed size numeric arrays of 32 + * values. Returns index of `x` or `-index-1` if not found. + * + * @param buf + * @param x + */ +export const binarySearch32 = (buf: ArrayLike, x: number) => { + let idx = buf[16] <= x ? 16 : 0; + idx |= buf[idx + 4] <= x ? 8 : 0; + idx |= buf[idx + 4] <= x ? 4 : 0; + idx |= buf[idx + 2] <= x ? 2 : 0; + idx |= buf[idx + 1] <= x ? 1 : 0; + return buf[idx] === x ? idx : -idx - 1; +}; + /** * {@link binarySearch} result index classifier for predecessor queries. * Returns index of last item less than search value or -1 if no such