瀏覽代碼

examples/cavl_test: add testing of associative operation feature

ambrop7 13 年之前
父節點
當前提交
dbcb258a7f
共有 2 個文件被更改,包括 70 次插入0 次删除
  1. 64 0
      examples/cavl_test.c
  2. 6 0
      examples/cavl_test_tree.h

+ 64 - 0
examples/cavl_test.c

@@ -32,6 +32,7 @@
 #include <time.h>
 #include <stdint.h>
 #include <limits.h>
+#include <inttypes.h>
 
 #include <misc/balloc.h>
 #include <misc/compare.h>
@@ -40,18 +41,26 @@
 #include <structure/CAvl.h>
 
 #define USE_COUNTS 0
+#define USE_ASSOC 1
 
 typedef size_t entry_index;
 #define MAX_INDICES SIZE_MAX
 
 typedef uint32_t entry_key;
 
+typedef uint8_t assoc_value;
+typedef uint64_t assoc_sum;
+
 struct entry {
     entry_index tree_child[2];
     entry_index tree_parent;
     int8_t tree_balance;
 #if USE_COUNTS
     size_t tree_count;
+#endif
+#if USE_ASSOC
+    assoc_value assoc_value;
+    assoc_sum assoc_sum;
 #endif
     entry_key key;
 };
@@ -73,6 +82,43 @@ static void random_bytes (char *buf, size_t len)
     }
 }
 
+static int uint64_less (void *user, uint64_t a, uint64_t b)
+{
+    return (a < b);
+}
+
+#if USE_ASSOC
+static MyTreeRef assoc_continue_last_lesser_equal (MyTree *tree, struct entry *arg, MyTreeRef ref, assoc_sum target_sum)
+{
+    assoc_sum cur_sum = MyTree_ExclusiveAssocPrefixSum(tree, arg, ref);
+    ASSERT(target_sum >= cur_sum)
+    while (cur_sum + ref.ptr->assoc_value <= target_sum) {
+        MyTreeRef next_ref = MyTree_GetNext(tree, arg, ref);
+        if (next_ref.link == -1) {
+            break;
+        }
+        cur_sum += ref.ptr->assoc_value;
+        ref = next_ref;
+    }
+    return ref;
+}
+#endif
+
+static void test_assoc (MyTree *tree, struct entry *arg)
+{
+#if USE_ASSOC
+    assoc_sum sum = 0;
+    for (MyTreeRef ref = MyTree_GetFirst(tree, arg); ref.link != -1; ref = MyTree_GetNext(tree, arg, ref)) {
+        assoc_sum tree_sum = MyTree_ExclusiveAssocPrefixSum(tree, arg, ref);
+        ASSERT_FORCE(tree_sum == sum);
+        ASSERT_FORCE(MyTree_FindLastExclusiveAssocPrefixSumLesserEqual(tree, arg, sum, uint64_less, NULL).link == assoc_continue_last_lesser_equal(tree, arg, ref, sum).link);
+        ASSERT_FORCE(MyTree_FindLastExclusiveAssocPrefixSumLesserEqual(tree, arg, sum + 1, uint64_less, NULL).link == assoc_continue_last_lesser_equal(tree, arg, ref, sum + 1).link);
+        sum += ref.ptr->assoc_value;
+    }
+    ASSERT_FORCE(sum == MyTree_AssocSum(tree, arg));
+#endif
+}
+
 int main (int argc, char *argv[])
 {
     //srand(time(NULL));
@@ -111,6 +157,15 @@ int main (int argc, char *argv[])
     printf("Generating random remove indices...\n");
     random_bytes((char *)remove_indices, num_remove * sizeof(remove_indices[0]));
     
+#if USE_ASSOC
+    printf("Allocating assoc values...\n");
+    assoc_value *assoc_values = (assoc_value *)BAllocArray(num_keys, sizeof(assoc_values[0]));
+    ASSERT_FORCE(assoc_values);
+
+    printf("Generating random assoc values...\n");
+    random_bytes((char *)assoc_values, num_keys * sizeof(assoc_values[0]));
+#endif
+    
     printf("Allocating entries...\n");
     ASSERT_FORCE(num_keys <= MAX_INDICES);
     struct entry *entries = (struct entry *)BAllocArray(num_keys, sizeof(*entries));
@@ -126,6 +181,7 @@ int main (int argc, char *argv[])
 #if USE_COUNTS
     ASSERT_FORCE(MyTree_Count(&tree, arg) == 0);
 #endif
+    test_assoc(&tree, arg);
     
     size_t num;
 #if USE_COUNTS
@@ -136,6 +192,9 @@ int main (int argc, char *argv[])
     num = 0;
     for (size_t i = 0; i < num_keys; i++) {
         entries[num_used_entries].key = keys[i];
+#if USE_ASSOC
+        entries[num_used_entries].assoc_value = assoc_values[i];
+#endif
         MyTreeRef ref = {&entries[num_used_entries], num_used_entries};
         if (!MyTree_Insert(&tree, arg, ref, NULL)) {
             //printf("Insert collision!\n");
@@ -151,6 +210,7 @@ int main (int argc, char *argv[])
     if (do_verify) {
         printf("Verifying...\n");
         MyTree_Verify(&tree, arg);
+        test_assoc(&tree, arg);
     }
     
     printf("Looking up random inserted keys...\n");
@@ -183,6 +243,7 @@ int main (int argc, char *argv[])
     if (do_verify) {
         printf("Verifying...\n");
         MyTree_Verify(&tree, arg);
+        test_assoc(&tree, arg);
     }
     
     if (do_remove) {
@@ -216,6 +277,9 @@ int main (int argc, char *argv[])
     BFree(keys);
     BFree(lookup_indices);
     BFree(remove_indices);
+#if USE_ASSOC
+    BFree(assoc_values);
+#endif
     BFree(entries);
     
     return 0;

+ 6 - 0
examples/cavl_test_tree.h

@@ -1,17 +1,23 @@
 #define CAVL_PARAM_NAME MyTree
 #define CAVL_PARAM_FEATURE_COUNTS USE_COUNTS
 #define CAVL_PARAM_FEATURE_KEYS_ARE_INDICES 0
+#define CAVL_PARAM_FEATURE_ASSOC USE_ASSOC
 #define CAVL_PARAM_TYPE_ENTRY struct entry
 #define CAVL_PARAM_TYPE_LINK entry_index
 #define CAVL_PARAM_TYPE_KEY entry_key
 #define CAVL_PARAM_TYPE_ARG entry_ptr
 #define CAVL_PARAM_TYPE_COUNT size_t
+#define CAVL_PARAM_TYPE_ASSOC assoc_sum
 #define CAVL_PARAM_VALUE_COUNT_MAX SIZE_MAX
 #define CAVL_PARAM_VALUE_NULL ((entry_index)-1)
+#define CAVL_PARAM_VALUE_ASSOC_ZERO 0
 #define CAVL_PARAM_FUN_DEREF(arg, link) (&(arg)[(link)])
 #define CAVL_PARAM_FUN_COMPARE_ENTRIES(arg, entry1, entry2) B_COMPARE((entry1).ptr->key, (entry2).ptr->key)
 #define CAVL_PARAM_FUN_COMPARE_KEY_ENTRY(arg, key1, entry2) B_COMPARE((key1), (entry2).ptr->key)
+#define CAVL_PARAM_FUN_ASSOC_VALUE(arg, entry) ((entry).ptr->assoc_value)
+#define CAVL_PARAM_FUN_ASSOC_OPER(arg, value1, value2) ((value1) + (value2))
 #define CAVL_PARAM_MEMBER_CHILD tree_child
 #define CAVL_PARAM_MEMBER_BALANCE tree_balance
 #define CAVL_PARAM_MEMBER_PARENT tree_parent
 #define CAVL_PARAM_MEMBER_COUNT tree_count
+#define CAVL_PARAM_MEMBER_ASSOC assoc_sum