bsearch: simplify and optimize
authorFangrui Song <i@maskray.me>
Sun, 22 Jul 2018 00:34:00 +0000 (17:34 -0700)
committerRich Felker <dalias@aerifal.cx>
Mon, 23 Jul 2018 19:14:29 +0000 (15:14 -0400)
maintainer's note: the key observation here is that the compared
element is the first slot of the second ceil(half) of the array, and
thus can be removed for further comparison when it does not match, so
that we descend into the second ceil(half)-1 rather than ceil(half)
elements. this change ensures that nel strictly decreases with each
iteration, so that the case of != but nel==1 does not need to be
special-cased anymore.

src/stdlib/bsearch.c

index 61d89367e7b9140fa7dc067558427dc2aeed223c..fe050ea30a223f4dd45070adae43cd59ac8a2243 100644 (file)
@@ -7,13 +7,13 @@ void *bsearch(const void *key, const void *base, size_t nel, size_t width, int (
        while (nel > 0) {
                try = (char *)base + width*(nel/2);
                sign = cmp(key, try);
-               if (!sign) return try;
-               else if (nel == 1) break;
-               else if (sign < 0)
+               if (sign < 0) {
                        nel /= 2;
-               else {
-                       base = try;
-                       nel -= nel/2;
+               } else if (sign > 0) {
+                       base = (char *)try + width;
+                       nel -= nel/2+1;
+               } else {
+                       return try;
                }
        }
        return NULL;