optimize default insert_sorted implementation

Sun, 01 Sep 2024 16:14:34 +0200

author
Mike Becker <universe@uap-core.de>
date
Sun, 01 Sep 2024 16:14:34 +0200
changeset 877
608b14deea18
parent 876
f4ce7df9cff0
child 878
1c1ee61c01f9

optimize default insert_sorted implementation

resolves #418

src/list.c file | annotate | diff | comparison | revisions
--- a/src/list.c	Sun Sep 01 14:48:43 2024 +0200
+++ b/src/list.c	Sun Sep 01 16:14:34 2024 +0200
@@ -308,14 +308,62 @@
         void const *sorted_data,
         size_t n
 ) {
+    // corner case
+    if (n == 0) return 0;
+
     size_t elem_size = list->collection.elem_size;
     cx_compare_func cmp = list->collection.cmpfunc;
     char const *src = sorted_data;
 
-    size_t r = cx_list_default_insert_array(list, 0, src, n);
-    cx_list_default_sort(list);
+    // track indices and number of inserted items
+    size_t di = 0, si = 0, inserted = 0;
+
+    // search the list for insertion points
+    for (; di < list->collection.size; di++) {
+        void const *list_elm = invoke_list_func(at, list, di);
+
+        // compare current list element with first source element
+        // if less or equal, skip
+        if (cmp(list_elm, src) <= 0) {
+            continue;
+        }
 
-    return r;
+        // determine number of consecutive elements that can be inserted
+        size_t ins = 1;
+        char const *next = src;
+        while (++si < n) {
+            next += elem_size;
+            // once we become larger than the list elem, break
+            if (cmp(list_elm, next) <= 0) {
+                break;
+            }
+            // otherwise, we can insert one more
+            ins++;
+        }
+
+        // insert the elements at location si
+        if (ins == 1) {
+            if (0 != invoke_list_func(insert_element,
+                                      list, di, src))
+                return inserted;
+        } else {
+            size_t r = invoke_list_func(insert_array, list, di, src, ins);
+            if (r < ins) return inserted + r;
+        }
+        inserted += ins;
+        di += ins;
+
+        // everything inserted?
+        if (inserted == n) return inserted;
+        src = next;
+    }
+
+    // insert remaining items
+    if (si < n) {
+        inserted += invoke_list_func(insert_array, list, di, src, n - si);
+    }
+
+    return inserted;
 }
 
 void cx_list_default_sort(struct cx_list_s *list) {

mercurial