From 6b8617b5100a3b80b8dc69cb15d942a6c3a0e017 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Sat, 27 May 2023 17:45:00 -0400 Subject: [PATCH] Add shar's algorithm This is based on the D version by Alex Muscar, which was based on an implementation in Writing Efficient Programs by Jon L. Bentley. It was originally published by Knuth and is attributed to Shar. https://muscar.eu/shar-binary-search-meta.html Previously, I had mistaken the monobound binary search for a loop version of Shar's algorithm, but after looking at them more deeply, I realize that they are subtly different. On my Ryzen 7 5800X, this will outperform the monobound binary search on array sizes that are powers of 2 or near powers of 2. Signed-off-by: Richard Yao --- binary_search.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/binary_search.c b/binary_search.c index 68dfd32..48a6740 100644 --- a/binary_search.c +++ b/binary_search.c @@ -1,5 +1,6 @@ /* Copyright (C) 2014-2021 Igor van den Hoven ivdhoven@gmail.com + Copyright (C) 2023 Zettabyte Software LLC. */ /* @@ -523,6 +524,36 @@ int adaptive_binary_search(int *array, unsigned int array_size, int key) return -1; } +int shar_binary_search(int *array, unsigned int array_size, int key) +{ + unsigned int i; + + switch (array_size) + { + default: + unsigned int u = sizeof (array_size) * 8 - __builtin_clz(2U*array_size-1U) - 2; + unsigned int p = 1U << (u); + i = (array[p] <= key) * (array_size - p); + + ++checks; + + while (p >>= 1) { + ++checks; + if (array[i + p] <= key) + i += p; + } + break; + case 1: + i = 0; + break; + case 0: + return -1; + } + + ++checks; + return (array[i] == key) ? i : -1; +} + // benchmark long long utime() @@ -683,6 +714,7 @@ int main(int argc, char **argv) run(monobound_quaternary_search); run(monobound_interpolated_search); run(adaptive_binary_search); + run(shar_binary_search); // uneven distribution @@ -701,6 +733,7 @@ int main(int argc, char **argv) run(monobound_binary_search); run(monobound_interpolated_search); run(adaptive_binary_search); + run(shar_binary_search); // sequential access, check stability while at it @@ -726,6 +759,7 @@ int main(int argc, char **argv) run(monobound_quaternary_search); run(monobound_interpolated_search); run(adaptive_binary_search); + run(shar_binary_search); free(o_array); free(r_array);