From: Bruno Haible Date: Wed, 4 Oct 2006 17:28:15 +0000 (+0000) Subject: Add a search_atleast operation. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5c90f29795d4e8d9a66268d5dc61d02b82cf7db8;p=pspp Add a search_atleast operation. --- diff --git a/lib/ChangeLog b/lib/ChangeLog index 6f39cdb6b2..e8ab808144 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,3 +1,16 @@ +2006-10-03 Bruno Haible + + * gl_oset.h (gl_setelement_threshold_fn): New type. + (gl_oset_search_atleast): New declaration. + (struct gl_oset_implementation): Add field 'search_atleast'. + (gl_oset_search_atleast): New inline function. + * gl_oset.c (gl_oset_search_atleast): New function. + * gl_array_oset.c (gl_array_search_atleast): New function. + (gl_array_oset_implementation): Update. + * gl_anytree_oset.h (gl_tree_search_atleast): New function. + * gl_avltree_oset.c (gl_avltree_oset_implementation): Update. + * gl_rbtree_oset.c (gl_rbtree_oset_implementation): Update. + 2006-10-04 Jim Meyering * fts.c (fts_open): Tiny comment change. diff --git a/lib/gl_anytree_oset.h b/lib/gl_anytree_oset.h index 6ac07e4625..53c877505a 100644 --- a/lib/gl_anytree_oset.h +++ b/lib/gl_anytree_oset.h @@ -73,6 +73,41 @@ gl_tree_search (gl_oset_t set, const void *elt) return false; } +static bool +gl_tree_search_atleast (gl_oset_t set, + gl_setelement_threshold_fn threshold_fn, + const void *threshold, + const void **eltp) +{ + gl_oset_node_t node; + + for (node = set->root; node != NULL; ) + { + if (! threshold_fn (node->value, threshold)) + node = node->right; + else + { + /* We have an element >= VALUE. But we need the leftmost such + element. */ + gl_oset_node_t found = node; + node = node->left; + for (; node != NULL; ) + { + if (! threshold_fn (node->value, threshold)) + node = node->right; + else + { + found = node; + node = node->left; + } + } + *eltp = found; + return true; + } + } + return false; +} + static gl_oset_node_t gl_tree_search_node (gl_oset_t set, const void *elt) { diff --git a/lib/gl_array_oset.c b/lib/gl_array_oset.c index 6a227b0bfe..a6fdb06e9e 100644 --- a/lib/gl_array_oset.c +++ b/lib/gl_array_oset.c @@ -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) @@ -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, diff --git a/lib/gl_avltree_oset.c b/lib/gl_avltree_oset.c index ac1185cb4c..db02ab8950 100644 --- a/lib/gl_avltree_oset.c +++ b/lib/gl_avltree_oset.c @@ -565,6 +565,7 @@ const struct gl_oset_implementation gl_avltree_oset_implementation = gl_tree_create_empty, gl_tree_size, gl_tree_search, + gl_tree_search_atleast, gl_tree_add, gl_tree_remove, gl_tree_oset_free, diff --git a/lib/gl_oset.c b/lib/gl_oset.c index 69ae2b6ce7..83f964e0ce 100644 --- a/lib/gl_oset.c +++ b/lib/gl_oset.c @@ -46,6 +46,15 @@ gl_oset_search (gl_oset_t set, const void *elt) return ((const struct gl_oset_impl_base *) set)->vtable->search (set, elt); } +bool +gl_oset_search_atleast (gl_oset_t set, + gl_setelement_threshold_fn threshold_fn, + const void *threshold, const void **eltp) +{ + return ((const struct gl_oset_impl_base *) set)->vtable + ->search_atleast (set, threshold_fn, threshold, eltp); +} + bool gl_oset_add (gl_oset_t set, const void *elt) { diff --git a/lib/gl_oset.h b/lib/gl_oset.h index 6c5d5eb420..2a67994a86 100644 --- a/lib/gl_oset.h +++ b/lib/gl_oset.h @@ -59,6 +59,7 @@ extern "C" { gl_oset_add O(n) O(log n) gl_oset_remove O(n) O(log n) gl_oset_search O(log n) O(log n) + gl_oset_search_atleast O(log n) O(log n) gl_oset_iterator O(1) O(log n) gl_oset_iterator_next O(1) O(log n) */ @@ -69,6 +70,10 @@ extern "C" { NULL denotes pointer comparison. */ typedef int (*gl_setelement_compar_fn) (const void *elt1, const void *elt2); +/* Type of function used to compare an element with a threshold. + Return true if the element is greater or equal than the threshold. */ +typedef bool (*gl_setelement_threshold_fn) (const void *elt, const void *threshold); + struct gl_oset_impl; /* Type representing an entire ordered set. */ typedef struct gl_oset_impl * gl_oset_t; @@ -90,6 +95,16 @@ extern size_t gl_oset_size (gl_oset_t set); Return true if found, or false if not present in the set. */ extern bool gl_oset_search (gl_oset_t set, const void *elt); +/* Search the least element in the ordered set that compares greater or equal + to the given THRESHOLD. The representation of the THRESHOLD is defined + by the THRESHOLD_FN. + Return true and store the found element in *ELTP if found, otherwise return + false. */ +extern bool gl_oset_search_atleast (gl_oset_t set, + gl_setelement_threshold_fn threshold_fn, + const void *threshold, + const void **eltp); + /* Add an element to an ordered set. Return true if it was not already in the set and added. */ extern bool gl_oset_add (gl_oset_t set, const void *elt); @@ -143,6 +158,9 @@ struct gl_oset_implementation gl_setelement_compar_fn compar_fn); size_t (*size) (gl_oset_t set); bool (*search) (gl_oset_t set, const void *elt); + bool (*search_atleast) (gl_oset_t set, + gl_setelement_threshold_fn threshold_fn, + const void *threshold, const void **eltp); bool (*add) (gl_oset_t set, const void *elt); bool (*remove) (gl_oset_t set, const void *elt); void (*oset_free) (gl_oset_t set); @@ -186,6 +204,16 @@ gl_oset_search (gl_oset_t set, const void *elt) return ((const struct gl_oset_impl_base *) set)->vtable->search (set, elt); } +# define gl_oset_search_atleast gl_oset_search_atleast_inline +static inline bool +gl_oset_search_atleast (gl_oset_t set, + gl_setelement_threshold_fn threshold_fn, + const void *threshold, const void **eltp) +{ + return ((const struct gl_oset_impl_base *) set)->vtable + ->search_atleast (set, threshold_fn, threshold, eltp); +} + # define gl_oset_add gl_oset_add_inline static inline bool gl_oset_add (gl_oset_t set, const void *elt) diff --git a/lib/gl_rbtree_oset.c b/lib/gl_rbtree_oset.c index 12c86325ea..78636d6156 100644 --- a/lib/gl_rbtree_oset.c +++ b/lib/gl_rbtree_oset.c @@ -796,6 +796,7 @@ const struct gl_oset_implementation gl_rbtree_oset_implementation = gl_tree_create_empty, gl_tree_size, gl_tree_search, + gl_tree_search_atleast, gl_tree_add, gl_tree_remove, gl_tree_oset_free,