[beast: 25/57] SFI: add Bse::binary_lookup() and related functions
- From: Tim Janik <timj src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [beast: 25/57] SFI: add Bse::binary_lookup() and related functions
- Date: Sun, 23 Jul 2017 09:59:53 +0000 (UTC)
commit f8557d77af27bfca215bd1fae6b03e2dacadf09e
Author: Tim Janik <timj gnu org>
Date: Sun Jul 16 19:50:58 2017 +0200
SFI: add Bse::binary_lookup() and related functions
Signed-off-by: Tim Janik <timj gnu org>
sfi/bcore.hh | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 82 insertions(+), 0 deletions(-)
---
diff --git a/sfi/bcore.hh b/sfi/bcore.hh
index c5db66c..a3a3508 100644
--- a/sfi/bcore.hh
+++ b/sfi/bcore.hh
@@ -44,6 +44,88 @@ inline bool debug_enabled (const char *conditiona
// == Development Aids ==
extern inline void breakpoint () BSE_ALWAYS_INLINE; ///< Cause a debugging breakpoint,
for development only.
+// == Binary Lookups ==
+template<typename RandIter, class Cmp, typename Arg, int case_lookup_or_sibling_or_insertion>
+extern inline std::pair<RandIter,bool>
+binary_lookup_fuzzy (RandIter begin, RandIter end, Cmp cmp_elements, const Arg &arg)
+{
+ RandIter current = end;
+ size_t n_elements = end - begin, offs = 0;
+ const bool want_lookup = case_lookup_or_sibling_or_insertion == 0;
+ // const bool want_sibling = case_lookup_or_sibling_or_insertion == 1;
+ const bool want_insertion_pos = case_lookup_or_sibling_or_insertion > 1;
+ ssize_t cmp = 0;
+ while (offs < n_elements)
+ {
+ size_t i = (offs + n_elements) >> 1;
+ current = begin + i;
+ cmp = cmp_elements (arg, *current);
+ if (cmp == 0)
+ return want_insertion_pos ? std::make_pair (current, true) : std::make_pair (current, /*ignored*/
false);
+ else if (cmp < 0)
+ n_elements = i;
+ else /* (cmp > 0) */
+ offs = i + 1;
+ }
+ /* check is last mismatch, cmp > 0 indicates greater key */
+ return (want_lookup
+ ? std::make_pair (end, /*ignored*/ false)
+ : (want_insertion_pos && cmp > 0)
+ ? std::make_pair (current + 1, false)
+ : std::make_pair (current, false));
+}
+
+/** Perform a binary lookup to find the insertion position for a new element.
+ * Return (end,false) for end-begin==0, or return (position,true) for exact match,
+ * otherwise return (position,false) where position indicates the location for
+ * the key to be inserted (and may equal end).
+ */
+template<typename RandIter, class Cmp, typename Arg>
+extern inline std::pair<RandIter,bool>
+binary_lookup_insertion_pos (RandIter begin, RandIter end, Cmp cmp_elements, const Arg &arg)
+{
+ return binary_lookup_fuzzy<RandIter,Cmp,Arg,2> (begin, end, cmp_elements, arg);
+}
+
+/** Perform a binary lookup to yield exact or nearest match.
+ * return end for end-begin==0, otherwise return the exact match element, or,
+ * if there's no such element, return the element last visited, which is pretty
+ * close to an exact match (will be one off into either direction).
+ */
+template<typename RandIter, class Cmp, typename Arg>
+extern inline RandIter
+binary_lookup_sibling (RandIter begin, RandIter end, Cmp cmp_elements, const Arg &arg)
+{
+ return binary_lookup_fuzzy<RandIter,Cmp,Arg,1> (begin, end, cmp_elements, arg).first;
+}
+
+/** Perform binary lookup and yield exact match or @a end.
+ * The arguments [ @a begin, @a end [ denote the range used for the lookup,
+ * @a arg is passed along with the current element to the @a cmp_elements
+ * function.
+ */
+template<typename RandIter, class Cmp, typename Arg>
+extern inline RandIter
+binary_lookup (RandIter begin, RandIter end, Cmp cmp_elements, const Arg &arg)
+{
+ /* return end or exact match */
+ return binary_lookup_fuzzy<RandIter,Cmp,Arg,0> (begin, end, cmp_elements, arg).first;
+}
+
+/// Comparison function useful to sort lesser items first.
+template<typename Value> static inline int
+compare_lesser (const Value &v1, const Value &v2)
+{
+ return -(v1 < v2) | (v2 < v1);
+}
+
+/// Comparison function useful to sort greater items first.
+template<typename Value> static inline int
+compare_greater (const Value &v1, const Value &v2)
+{
+ return (v1 < v2) | -(v2 < v1);
+}
+
// == Implementation Details ==
#if (defined __i386__ || defined __x86_64__)
inline void breakpoint() { __asm__ __volatile__ ("int $03"); }
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]