cavl_test.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /**
  2. * @file cavl_test.c
  3. * @author Ambroz Bizjak <ambrop7@gmail.com>
  4. *
  5. * @section LICENSE
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the author nor the
  15. * names of its contributors may be used to endorse or promote products
  16. * derived from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. */
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <time.h>
  32. #include <stdint.h>
  33. #include <limits.h>
  34. #include <misc/balloc.h>
  35. #include <misc/compare.h>
  36. #include <misc/debug.h>
  37. #include <misc/print_macros.h>
  38. #include <structure/CAvl.h>
  39. #define USE_COUNTS 0
  40. typedef size_t entry_index;
  41. #define MAX_INDICES SIZE_MAX
  42. typedef uint32_t entry_key;
  43. struct entry {
  44. entry_index tree_child[2];
  45. entry_index tree_parent;
  46. int8_t tree_balance;
  47. #if USE_COUNTS
  48. size_t tree_count;
  49. #endif
  50. entry_key key;
  51. };
  52. typedef struct entry *entry_ptr;
  53. #include "cavl_test_tree.h"
  54. #include <structure/CAvl_decl.h>
  55. #include "cavl_test_tree.h"
  56. #include <structure/CAvl_impl.h>
  57. static void random_bytes (char *buf, size_t len)
  58. {
  59. while (len > 0) {
  60. *((unsigned char *)buf) = rand();
  61. buf++;
  62. len--;
  63. }
  64. }
  65. int main (int argc, char *argv[])
  66. {
  67. //srand(time(NULL));
  68. printf("sizeof(struct entry)=%" PRIsz "\n", sizeof(struct entry));
  69. if (argc != 6) {
  70. fprintf(stderr, "Usage: %s <num_keys> <num_lookups> <num_remove> <do_remove=1/0> <do_verify=1/0>\n", (argc > 0 ? argv[0] : ""));
  71. return 1;
  72. }
  73. size_t num_keys = atoi(argv[1]);
  74. size_t num_lookups = atoi(argv[2]);
  75. size_t num_remove = atoi(argv[3]);
  76. size_t do_remove = atoi(argv[4]);
  77. size_t do_verify = atoi(argv[5]);
  78. printf("Allocating keys...\n");
  79. entry_key *keys = (entry_key *)BAllocArray(num_keys, sizeof(keys[0]));
  80. ASSERT_FORCE(keys);
  81. printf("Generating random keys...\n");
  82. random_bytes((char *)keys, num_keys * sizeof(keys[0]));
  83. printf("Allocating lookup indices...\n");
  84. uint64_t *lookup_indices = (uint64_t *)BAllocArray(num_lookups, sizeof(lookup_indices[0]));
  85. ASSERT_FORCE(lookup_indices);
  86. printf("Generating random lookup indices...\n");
  87. random_bytes((char *)lookup_indices, num_lookups * sizeof(lookup_indices[0]));
  88. printf("Allocating remove indices...\n");
  89. uint64_t *remove_indices = (uint64_t *)BAllocArray(num_remove, sizeof(remove_indices[0]));
  90. ASSERT_FORCE(remove_indices);
  91. printf("Generating random remove indices...\n");
  92. random_bytes((char *)remove_indices, num_remove * sizeof(remove_indices[0]));
  93. printf("Allocating entries...\n");
  94. ASSERT_FORCE(num_keys <= MAX_INDICES);
  95. struct entry *entries = (struct entry *)BAllocArray(num_keys, sizeof(*entries));
  96. ASSERT_FORCE(entries);
  97. entry_index num_used_entries = 0;
  98. MyTree tree;
  99. MyTree_Init(&tree);
  100. struct entry *arg = entries;
  101. ASSERT_FORCE(MyTree_IsEmpty(&tree));
  102. #if USE_COUNTS
  103. ASSERT_FORCE(MyTree_Count(&tree, arg) == 0);
  104. #endif
  105. size_t num;
  106. #if USE_COUNTS
  107. size_t prevNum;
  108. #endif
  109. printf("Inserting random numbers...\n");
  110. num = 0;
  111. for (size_t i = 0; i < num_keys; i++) {
  112. entries[num_used_entries].key = keys[i];
  113. MyTreeRef ref = {&entries[num_used_entries], num_used_entries};
  114. if (!MyTree_Insert(&tree, arg, ref, NULL)) {
  115. //printf("Insert collision!\n");
  116. continue;
  117. }
  118. num_used_entries++;
  119. num++;
  120. }
  121. printf("Inserted %" PRIsz ".\n", num);
  122. #if USE_COUNTS
  123. ASSERT_FORCE(MyTree_Count(&tree, arg) == num);
  124. #endif
  125. if (do_verify) {
  126. printf("Verifying...\n");
  127. MyTree_Verify(&tree, arg);
  128. }
  129. printf("Looking up random inserted keys...\n");
  130. for (size_t i = 0; i < num_lookups; i++) {
  131. entry_index idx = lookup_indices[i] % num_keys;
  132. MyTreeRef entry = MyTree_LookupExact(&tree, arg, keys[idx]);
  133. ASSERT_FORCE(!MyTreeIsNullRef(entry));
  134. }
  135. #if USE_COUNTS
  136. prevNum = MyTree_Count(&tree, arg);
  137. #endif
  138. num = 0;
  139. printf("Looking up and removing random inserted keys...\n");
  140. for (size_t i = 0; i < num_remove; i++) {
  141. entry_index idx = remove_indices[i] % num_keys;
  142. MyTreeRef entry = MyTree_LookupExact(&tree, arg, keys[idx]);
  143. if (MyTreeIsNullRef(entry)) {
  144. //printf("Remove collision!\n");
  145. continue;
  146. }
  147. ASSERT_FORCE(entry.ptr->key == keys[idx]);
  148. MyTree_Remove(&tree, arg, entry);
  149. num++;
  150. }
  151. printf("Removed %" PRIsz ".\n", num);
  152. #if USE_COUNTS
  153. ASSERT_FORCE(MyTree_Count(&tree, arg) == prevNum - num);
  154. #endif
  155. if (do_verify) {
  156. printf("Verifying...\n");
  157. MyTree_Verify(&tree, arg);
  158. }
  159. if (do_remove) {
  160. #if USE_COUNTS
  161. prevNum = MyTree_Count(&tree, arg);
  162. #endif
  163. num = 0;
  164. printf("Removing remaining...\n");
  165. MyTreeRef cur = MyTree_GetFirst(&tree, arg);
  166. while (!MyTreeIsNullRef(cur)) {
  167. MyTreeRef prev = cur;
  168. cur = MyTree_GetNext(&tree, arg, cur);
  169. MyTree_Remove(&tree, arg, prev);
  170. num++;
  171. }
  172. printf("Removed %" PRIsz ".\n", num);
  173. ASSERT_FORCE(MyTree_IsEmpty(&tree));
  174. #if USE_COUNTS
  175. ASSERT_FORCE(MyTree_Count(&tree, arg) == 0);
  176. ASSERT_FORCE(num == prevNum);
  177. #endif
  178. if (do_verify) {
  179. printf("Verifying...\n");
  180. MyTree_Verify(&tree, arg);
  181. }
  182. }
  183. printf("Freeing...\n");
  184. BFree(keys);
  185. BFree(lookup_indices);
  186. BFree(remove_indices);
  187. BFree(entries);
  188. return 0;
  189. }