/* See LICENSE file for copyright and license details. */ #include "common.h" #ifdef USE_INTERPOLATION_SEARCH # ifndef INTERPOLATION_SEARCH_FLOAT # define INTERPOLATION_SEARCH_FLOAT long double # endif /* convertion to unsigned is a modulo (unsigned maximum + 1) operation */ # define DIFF(TYPE, A, B) ((unsigned TYPE)(A) - (unsigned TYPE)(B)) # define INTERPOL_SEARCH(KEY, BASE, N, READ)\ do {\ INTERPOLATION_SEARCH_FLOAT guess_d;\ unsigned long long int guess;\ size_t h = (N);\ \ if (!h--)\ return NULL;\ \ if ((KEY) <= READ((BASE), 0))\ return (KEY) == READ((BASE), 0) ? &(BASE)[0] : NULL;\ if ((KEY) >= READ((BASE), h))\ return (KEY) == READ((BASE), h) ? &(BASE)[h] : NULL;\ if (READ((BASE), 0) == READ((BASE), h))\ return NULL;\ \ goto use_double;\ guess = DIFF(long long int, (KEY), READ((BASE), 0));\ if (h > ULLONG_MAX / guess)\ goto use_double;\ \ for (;;) {\ guess = DIFF(long long int, (KEY), READ((BASE), 0));\ guess *= (unsigned long long int)h;\ guess /= DIFF(long long int, READ((BASE), h), READ((BASE), 0));\ \ if (READ((BASE), guess) < (KEY)) {\ h -= guess += 1;\ (BASE) = &(BASE)[guess];\ } else if (READ((BASE), guess) > (KEY)) {\ h = guess -= 1;\ } else {\ return &(BASE)[guess];\ }\ \ if ((KEY) <= READ((BASE), 0))\ return (KEY) == READ((BASE), 0) ? &(BASE)[0] : NULL;\ if ((KEY) >= READ((BASE), h))\ return (KEY) == READ((BASE), h) ? &(BASE)[h] : NULL;\ if (READ((BASE), 0) == READ((BASE), h))\ return NULL;\ }\ \ use_double:\ for (;;) {\ guess = DIFF(long long int, (KEY), READ((BASE), 0));\ guess_d = (INTERPOLATION_SEARCH_FLOAT)guess * (INTERPOLATION_SEARCH_FLOAT)h;\ guess = DIFF(long long int, READ((BASE), h), READ((BASE), 0));\ guess_d /= (INTERPOLATION_SEARCH_FLOAT)guess;\ guess = (unsigned long long int)guess_d;\ \ if (READ((BASE), guess) < (KEY)) {\ h -= guess += 1;\ (BASE) = &(BASE)[guess];\ } else if (READ((BASE), guess) > (KEY)) {\ h = guess -= 1;\ } else {\ return &(BASE)[guess];\ }\ \ if ((KEY) <= READ((BASE), 0))\ return (KEY) == READ((BASE), 0) ? &(BASE)[0] : NULL;\ if ((KEY) >= READ((BASE), h))\ return (KEY) == READ((BASE), h) ? &(BASE)[h] : NULL;\ if (READ((BASE), 0) == READ((BASE), h))\ return NULL;\ }\ } while (0) #else PURE_FUNCTION static int signed_named_number_cmp(const void *a_, const void *b_) { const struct libsyscalls_named_number *a = a_, *b = b_; return a->number.s < b->number.s ? -1 : a->number.s > b->number.s; } PURE_FUNCTION static int unsigned_named_number_cmp(const void *a_, const void *b_) { const struct libsyscalls_named_number *a = a_, *b = b_; return a->number.u < b->number.u ? -1 : a->number.u > b->number.u; } #endif const struct libsyscalls_named_number * libsyscalls_find_signed_named_number(signed long long int key, const struct libsyscalls_named_number *base, size_t n) { #ifdef USE_INTERPOLATION_SEARCH # define X(ARR, I) ((ARR)[I].number.s) INTERPOL_SEARCH(key, base, n, X); # undef X #else struct libsyscalls_named_number struct_key = {.number.s = key}; return bsearch(&struct_key, base, n, sizeof(*base), &signed_named_number_cmp); #endif } const struct libsyscalls_named_number * libsyscalls_find_unsigned_named_number(unsigned long long int key, const struct libsyscalls_named_number *base, size_t n) { #ifdef USE_INTERPOLATION_SEARCH # define X(ARR, I) ((ARR)[I].number.u) INTERPOL_SEARCH(key, base, n, X); # undef X #else struct libsyscalls_named_number struct_key = {.number.u = key}; return bsearch(&struct_key, base, n, sizeof(*base), &unsigned_named_number_cmp); #endif } extern inline const struct libsyscalls_named_number * libsyscalls_find_named_number(unsigned long long int key, int is_signed, const struct libsyscalls_named_number *base, size_t n);