Skip to main content
Bumped by Community user
replaced http://codereview.stackexchange.com/ with https://codereview.stackexchange.com/
Source Link

Code review my binary search! It isn't supposed to be superfast or anything. It's optimized for clarity and only sorts arrays of pointers. Also in the same style is my quicksort code review question: Yet another quicksortYet another quicksort.

Code review my binary search! It isn't supposed to be superfast or anything. It's optimized for clarity and only sorts arrays of pointers. Also in the same style is my quicksort code review question: Yet another quicksort.

Code review my binary search! It isn't supposed to be superfast or anything. It's optimized for clarity and only sorts arrays of pointers. Also in the same style is my quicksort code review question: Yet another quicksort.

Source Link
Rosebud
  • 121
  • 2

Yet another binary search

Code review my binary search! It isn't supposed to be superfast or anything. It's optimized for clarity and only sorts arrays of pointers. Also in the same style is my quicksort code review question: Yet another quicksort.

/*
  used as the base case of bsearch.
*/
static void const* misc_bsearch_linear(void const** A, void const** Z, void const* K, bool (*cmp)(void const*, void const*))
{
  /*
    burn forward while *A < K. if there is anything left, it will have
    to be that *A >= K.
  */
  while ((A < Z) && cmp(*A, K)) A++;
  
  /*
    if there is nothing left, we're done.
  */
  if (!(A < Z)) return NULL;
  
  /*
    now we know *A >= K.
  */
  {
    if (cmp(K, *A)) {
      /* when K < *A */
      /* this means *A > K, so no dice */
      return NULL;
    } else {
      /* when K >= *A */
      /* this means *A == K, so return it */
      return *A;
    }
  }
}

static void const* misc_bsearch_internal(void const** A, void const** Z, void const* K, bool (*cmp)(void const*, void const*))
{
  /*
    must stop loop when there are 3 or fewer elements, otherwise it
    could go on forever in the bottom case.
  */
  while ((Z - A) > 3) {
    void const** M = (A + ((Z - A) >> 1));
    
    if (cmp(*M, K)) {
      /* when *M < K */
      A = M + 1;
    } else {
      /* when *M >= K */
      Z = M + 1;
    }
  }
  
  /*
    we're down to at most 3 elements, to downgrade to linear search to
    finish up.
  */
  return misc_bsearch_linear(A, Z, K, cmp);
}

/*
  cmp should return true iff [arg1] < [arg2] (strictly).
*/
static INLINE void const* misc_bsearch(void const** A, uintptr_t L, void const* K, bool (*cmp)(void const*, void const*))
{
  return misc_bsearch_internal(A, (A + L), K, cmp);
}

#define MISC_BSEARCH_VARIANT(s, t)                                   \
  static INLINE t* misc_bsearch_##s(t** A, uintptr_t L, t const* K, bool (*cmp)(t const*, t const*)) \
  {                                                                  \
    return ((t*)(misc_bsearch(((void const**)(A)), L, K, ((bool (*)(void const*, void const*))(cmp))))); \
  }