X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fgl_array_oset.c;h=a6fdb06e9e93bae80dda045b159b4290631669e5;hb=7b9878d56ceb1a8ed1255ea1e6010638af7252c6;hp=b73d69031fcb6331f7b23bb6be6ae5578f9289da;hpb=a42a50dc6f5c48c557920c21c8f05d31f26fea73;p=gnulib.git diff --git a/lib/gl_array_oset.c b/lib/gl_array_oset.c index b73d69031..a6fdb06e9 100644 --- a/lib/gl_array_oset.c +++ b/lib/gl_array_oset.c @@ -76,7 +76,7 @@ gl_array_indexof (gl_oset_t set, const void *elt) /* At each loop iteration, low < high; for indices < low the values are smaller than ELT; for indices >= high the values are greater - than ELT. So, if the element occurs in the list, is at + than ELT. So, if the element occurs in the list, it is at low <= position < high. */ do { @@ -84,7 +84,7 @@ gl_array_indexof (gl_oset_t set, const void *elt) int cmp = (compar != NULL ? compar (set->elements[mid], elt) : (set->elements[mid] > elt ? 1 : - set->elements[mid] < elt ? -1 : 0)); + set->elements[mid] < elt ? -1 : 0)); if (cmp < 0) low = mid + 1; @@ -105,6 +105,56 @@ gl_array_search (gl_oset_t set, const void *elt) return gl_array_indexof (set, elt) != (size_t)(-1); } +static bool +gl_array_search_atleast (gl_oset_t set, + gl_setelement_threshold_fn threshold_fn, + const void *threshold, + const void **eltp) +{ + size_t count = set->count; + + if (count > 0) + { + size_t low = 0; + size_t high = count; + + /* At each loop iteration, low < high; for indices < low the values are + smaller than THRESHOLD; for indices >= high the values are nonexistent. + So, if an element >= THRESHOLD occurs in the list, it is at + low <= position < high. */ + do + { + size_t mid = low + (high - low) / 2; /* low <= mid < high */ + + if (! threshold_fn (set->elements[mid], threshold)) + low = mid + 1; + else + { + /* We have an element >= THRESHOLD at index MID. But we need the + minimal such index. */ + high = mid; + /* At each loop iteration, low <= high and + compar (list->elements[high], value) >= 0, + and we know that the first occurrence of the element is at + low <= position <= high. */ + while (low < high) + { + size_t mid2 = low + (high - low) / 2; /* low <= mid2 < high */ + + if (! threshold_fn (set->elements[mid2], threshold)) + low = mid2 + 1; + else + high = mid2; + } + *eltp = set->elements[low]; + return true; + } + } + while (low < high); + } + return false; +} + /* Ensure that set->allocated > set->count. */ static void grow (gl_oset_t set) @@ -173,7 +223,7 @@ gl_array_add (gl_oset_t set, const void *elt) /* At each loop iteration, low < high; for indices < low the values are smaller than ELT; for indices >= high the values are greater - than ELT. So, if the element occurs in the list, is at + than ELT. So, if the element occurs in the list, it is at low <= position < high. */ do { @@ -273,6 +323,7 @@ const struct gl_oset_implementation gl_array_oset_implementation = gl_array_create_empty, gl_array_size, gl_array_search, + gl_array_search_atleast, gl_array_add, gl_array_remove, gl_array_free,