bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

add threshold search operation to 'oset' modules


From: Bruno Haible
Subject: add threshold search operation to 'oset' modules
Date: Wed, 4 Oct 2006 19:23:52 +0200
User-agent: KMail/1.9.1

Hi,

The ordered set datatype is missing an operation: search of the least
element >= a given threshold. I'm adding it, since the 'list' modules will
need it.

2006-10-03  Bruno Haible  <address@hidden>

        * 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.

*** gnulib-20060928/lib/gl_oset.h       2006-07-18 03:15:00.000000000 +0200
--- gnulib-20060928-modified/lib/gl_oset.h      2006-10-03 19:28:54.000000000 
+0200
***************
*** 59,64 ****
--- 59,65 ----
     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,74 ****
--- 70,79 ----
     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,95 ****
--- 95,110 ----
     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,148 ****
--- 158,166 ----
                             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,191 ****
--- 204,219 ----
    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)
*** gnulib-20060928/lib/gl_oset.c       2006-10-03 19:41:35.000000000 +0200
--- gnulib-20060928-modified/lib/gl_oset.c      2006-10-03 19:29:40.000000000 
+0200
***************
*** 47,52 ****
--- 47,61 ----
  }
  
  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);
*** gnulib-20060928/lib/gl_array_oset.c 2006-10-03 19:21:05.000000000 +0200
--- gnulib-20060928-modified/lib/gl_array_oset.c        2006-10-03 
19:33:52.000000000 +0200
***************
*** 105,110 ****
--- 105,160 ----
    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,278 ****
--- 323,329 ----
      gl_array_create_empty,
      gl_array_size,
      gl_array_search,
+     gl_array_search_atleast,
      gl_array_add,
      gl_array_remove,
      gl_array_free,
*** gnulib-20060928/lib/gl_anytree_oset.h       2006-09-29 01:08:24.000000000 
+0200
--- gnulib-20060928-modified/lib/gl_anytree_oset.h      2006-10-03 
19:35:41.000000000 +0200
***************
*** 73,78 ****
--- 73,113 ----
    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)
  {
*** gnulib-20060928/lib/gl_avltree_oset.c       2006-09-19 00:51:16.000000000 
+0200
--- gnulib-20060928-modified/lib/gl_avltree_oset.c      2006-10-03 
18:58:30.000000000 +0200
***************
*** 565,570 ****
--- 565,571 ----
      gl_tree_create_empty,
      gl_tree_size,
      gl_tree_search,
+     gl_tree_search_atleast,
      gl_tree_add,
      gl_tree_remove,
      gl_tree_oset_free,
*** gnulib-20060928/lib/gl_rbtree_oset.c        2006-09-19 00:51:16.000000000 
+0200
--- gnulib-20060928-modified/lib/gl_rbtree_oset.c       2006-10-03 
18:58:42.000000000 +0200
***************
*** 796,801 ****
--- 796,802 ----
      gl_tree_create_empty,
      gl_tree_size,
      gl_tree_search,
+     gl_tree_search_atleast,
      gl_tree_add,
      gl_tree_remove,
      gl_tree_oset_free,




reply via email to

[Prev in Thread] Current Thread [Next in Thread]