14 static A_INLINE
int int_factor(a_avl_node
*node
)
16 #if defined(A_SIZE_POINTER) && (A_SIZE_POINTER + 0 > 3)
17 return a_cast_s(int, node
->parent_
& 3) - 1;
18 #else /* !A_SIZE_POINTER */
20 #endif /* A_SIZE_POINTER */
23 static A_INLINE int_node
*int_entry(void const *node
)
25 return a_cast_r(int_node
*, a_cast_r(a_uptr
, node
) - a_offsetof(int_node
, node
)); // NOLINT
28 static int int_cmp(void const *lhs
, void const *rhs
)
30 int a
= int_entry(lhs
)->data
;
31 int b
= int_entry(rhs
)->data
;
32 return (a
> b
) - (a
< b
);
35 static int intcmp(void const *lhs
, void const *rhs
)
37 int a
= *a_int_(const *, lhs
);
38 int b
= *a_int_(const *, rhs
);
39 return (a
> b
) - (a
< b
);
42 #define int_max(a, b) ((a) > (b) ? (a) : (b))
43 #define int_height(node) ((node) ? int_entry(node)->height : 0)
44 static void set_height(a_avl_node
*node
) // NOLINT
48 TEST_BUG(node
->left
!= node
);
49 TEST_BUG(node
->right
!= node
);
50 set_height(node
->left
);
51 set_height(node
->right
);
52 int const hl
= int_height(node
->left
);
53 int const hr
= int_height(node
->right
);
54 int_entry(node
)->height
= int_max(hl
, hr
) + 1;
58 static void check_tree(a_avl_node
*node
) // NOLINT
62 int const e
= int_factor(node
);
63 TEST_BUG(-1 <= e
&& e
<= 1);
64 TEST_BUG(int_height(node
->right
) - int_height(node
->left
) == e
);
67 TEST_BUG(int_entry(node
->left
)->data
< int_entry(node
)->data
);
68 check_tree(node
->left
);
72 TEST_BUG(int_entry(node
->right
)->data
> int_entry(node
)->data
);
73 check_tree(node
->right
);
78 static int test(unsigned long n
)
80 a_str str
= A_STR_INIT
;
81 a_avl root
= A_AVL_ROOT
;
82 int *sorted
= a_new(int, A_NULL
, n
);
83 int_node
*vec
= a_new(int_node
, A_NULL
, n
);
84 for (unsigned int i
= 0; i
< n
; ++i
)
86 a_str_setf(&str
, "%u", i
);
87 vec
[i
].data
= sorted
[i
] = a_cast_s(int, a_hash_bkdr(a_str_ptr(&str
), 0));
88 a_avl_insert(&root
, &vec
[i
].node
, int_cmp
);
89 set_height(root
.node
);
90 check_tree(root
.node
);
93 debug("insert 0x%04X/0x%04lX\n", i
, n
);
98 for (unsigned int i
= 0; i
< n
; ++i
)
100 TEST_BUG(a_avl_search(&root
, &vec
[i
].node
, int_cmp
));
104 qsort(sorted
, n
, sizeof(int), intcmp
);
107 for (unsigned int i
= 0; i
< n
; ++i
)
111 a_avl_foreach(cur
, &root
)
113 int_node
*it
= int_entry(cur
);
114 TEST_BUG(it
->data
== sorted
[x
]);
118 for (unsigned int i
= 0; i
< n
; ++i
)
120 TEST_BUG(vec
[i
].reached
);
125 for (unsigned int i
= 0; i
< n
; ++i
)
129 a_avl_foreach_reverse(cur
, &root
)
131 int_node
*it
= int_entry(cur
);
132 TEST_BUG(it
->data
== sorted
[--x
]);
135 for (unsigned int i
= 0; i
< n
; ++i
)
137 TEST_BUG(vec
[i
].reached
);
141 for (unsigned int i
= 0; i
< n
; ++i
)
145 a_avl_pre_foreach(cur
, &root
)
147 int_node
*it
= int_entry(cur
);
150 for (unsigned int i
= 0; i
< n
; ++i
)
152 TEST_BUG(vec
[i
].reached
);
155 for (unsigned int i
= 0; i
< n
; ++i
)
159 a_avl_pre_foreach_reverse(cur
, &root
)
161 int_node
*it
= int_entry(cur
);
164 for (unsigned int i
= 0; i
< n
; ++i
)
166 TEST_BUG(vec
[i
].reached
);
169 for (unsigned int i
= 0; i
< n
; ++i
)
173 a_avl_post_foreach(cur
, &root
)
175 int_node
*it
= int_entry(cur
);
178 for (unsigned int i
= 0; i
< n
; ++i
)
180 TEST_BUG(vec
[i
].reached
);
183 for (unsigned int i
= 0; i
< n
; ++i
)
187 a_avl_post_foreach_reverse(cur
, &root
)
189 int_node
*it
= int_entry(cur
);
192 for (unsigned int i
= 0; i
< n
; ++i
)
194 TEST_BUG(vec
[i
].reached
);
197 for (unsigned int i
= 0; i
< n
; ++i
)
199 a_avl_remove(&root
, &vec
[i
].node
);
200 set_height(root
.node
);
201 check_tree(root
.node
);
204 debug("remove 0x%04X/0x%04lX\n", i
, n
);
208 TEST_BUG(!a_avl_search(&root
, &vec
->node
, int_cmp
));
210 for (unsigned int i
= 0; i
< n
; ++i
)
212 a_avl_insert(&root
, &vec
[i
].node
, int_cmp
);
215 a_avl_fortear(cur
, next
, &root
)
217 int_entry(cur
)->reached
= 1;
219 for (unsigned int i
= 0; i
< n
; ++i
)
221 TEST_BUG(vec
[i
].reached
);
229 int main(int argc
, char *argv
[]) // NOLINT(misc-definitions-in-headers)
231 printf("%s\n", A_FUNC
);
232 unsigned long n
= 0x1000;
233 if (argc
> 1) { n
= strtoul(argv
[1], A_NULL
, 0); }