summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2006-10-04 17:28:15 +0000
committerBruno Haible <bruno@clisp.org>2006-10-04 17:28:15 +0000
commit5c90f29795d4e8d9a66268d5dc61d02b82cf7db8 (patch)
tree52e242d232da3963405ca7643a8b31e0417139be /lib
parenta7cc0db9f5f6c63936c6914d4bb6448789774e5f (diff)
downloadgnulib-5c90f29795d4e8d9a66268d5dc61d02b82cf7db8.tar.gz
Add a search_atleast operation.
Diffstat (limited to 'lib')
-rw-r--r--lib/ChangeLog13
-rw-r--r--lib/gl_anytree_oset.h35
-rw-r--r--lib/gl_array_oset.c51
-rw-r--r--lib/gl_avltree_oset.c1
-rw-r--r--lib/gl_oset.c9
-rw-r--r--lib/gl_oset.h28
-rw-r--r--lib/gl_rbtree_oset.c1
7 files changed, 138 insertions, 0 deletions
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 <bruno@clisp.org>
+
+ * 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 <jim@meyering.net>
* 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
@@ -47,6 +47,15 @@ gl_oset_search (gl_oset_t set, const void *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)
{
return ((const struct gl_oset_impl_base *) set)->vtable->add (set, 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,