Skip to content

Commit 6c6c900

Browse files
committed
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 <richard.yao@alumni.stonybrook.edu>
1 parent ff7c12a commit 6c6c900

File tree

1 file changed

+35
-0
lines changed

1 file changed

+35
-0
lines changed

binary_search.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
Copyright (C) 2014-2021 Igor van den Hoven ivdhoven@gmail.com
3+
Copyright (C) 2023 Zettabyte Software LLC.
34
*/
45

56
/*
@@ -523,6 +524,37 @@ int adaptive_binary_search(int *array, unsigned int array_size, int key)
523524
return -1;
524525
}
525526

527+
int shar_binary_search(int *array, unsigned int array_size, int key)
528+
{
529+
unsigned int i;
530+
531+
switch (array_size)
532+
{
533+
default:
534+
unsigned int u = sizeof (array_size) * 8 - __builtin_clz(2U*array_size-1U) - 2;
535+
unsigned int p = 1U << (u);
536+
i = (array[p] <= key) * (array_size - p);
537+
538+
++checks;
539+
540+
while (p >>= 1) {
541+
++checks;
542+
if (array[i + p] <= key)
543+
i += p;
544+
}
545+
break;
546+
case 1:
547+
i = 0;
548+
break;
549+
case 0:
550+
return -1;
551+
552+
}
553+
554+
++checks;
555+
return (array[i] == key) ? i : -1;
556+
}
557+
526558
// benchmark
527559

528560
long long utime()
@@ -683,6 +715,7 @@ int main(int argc, char **argv)
683715
run(monobound_quaternary_search);
684716
run(monobound_interpolated_search);
685717
run(adaptive_binary_search);
718+
run(shar_binary_search);
686719

687720
// uneven distribution
688721

@@ -701,6 +734,7 @@ int main(int argc, char **argv)
701734
run(monobound_binary_search);
702735
run(monobound_interpolated_search);
703736
run(adaptive_binary_search);
737+
run(shar_binary_search);
704738

705739
// sequential access, check stability while at it
706740

@@ -726,6 +760,7 @@ int main(int argc, char **argv)
726760
run(monobound_quaternary_search);
727761
run(monobound_interpolated_search);
728762
run(adaptive_binary_search);
763+
run(shar_binary_search);
729764

730765
free(o_array);
731766
free(r_array);

0 commit comments

Comments
 (0)