4 #include <linux/bitops.h>
5 #include <linux/log2.h>
10 * Traversal for trees in eytzinger layout - a full binary tree layed out in an
13 * We used one based indexing, not zero based: with one based indexing, each
14 * level of the tree starts at a power of two - leading to better alignment -
15 * and it's what you want for implementing next/prev and to/from inorder.
17 * To/from inorder also uses 1 based indexing.
19 * Size parameter is treated as if we were using 0 based indexing, however:
20 * valid nodes, and inorder indices, are in the range [1..size)
23 static inline unsigned eytzinger_child(unsigned j, unsigned child)
27 return (j << 1) + child;
30 static inline unsigned eytzinger_left_child(unsigned j)
32 return eytzinger_child(j, 0);
35 static inline unsigned eytzinger_right_child(unsigned j)
37 return eytzinger_child(j, 1);
40 static inline unsigned eytzinger_first(unsigned size)
42 return rounddown_pow_of_two(size - 1);
45 static inline unsigned eytzinger_last(unsigned size)
47 return rounddown_pow_of_two(size) - 1;
51 * eytzinger_next() and eytzinger_prev() have the nice properties that
53 * eytzinger_next(0) == eytzinger_first())
54 * eytzinger_prev(0) == eytzinger_last())
56 * eytzinger_prev(eytzinger_first()) == 0
57 * eytzinger_next(eytzinger_last()) == 0
60 static inline unsigned eytzinger_next(unsigned j, unsigned size)
64 if (eytzinger_right_child(j) < size) {
65 j = eytzinger_right_child(j);
67 j <<= __fls(size) - __fls(j);
76 static inline unsigned eytzinger_prev(unsigned j, unsigned size)
80 if (eytzinger_left_child(j) < size) {
81 j = eytzinger_left_child(j);
83 j <<= __fls(size) - __fls(j);
93 static inline unsigned eytzinger_extra(unsigned size)
95 return (size - rounddown_pow_of_two(size - 1)) << 1;
98 static inline unsigned __eytzinger_to_inorder(unsigned j, unsigned size,
101 unsigned b = __fls(j);
102 unsigned shift = __fls(size - 1) - b;
105 EBUG_ON(!j || j >= size);
116 * j -= (j - extra) >> 1;
119 j += (s >> 1) & (s >> 31);
124 static inline unsigned __inorder_to_eytzinger(unsigned j, unsigned size,
130 EBUG_ON(!j || j >= size);
144 j |= 1U << (__fls(size - 1) - shift);
149 static inline unsigned eytzinger_to_inorder(unsigned j, unsigned size)
151 return __eytzinger_to_inorder(j, size, eytzinger_extra(size));
154 static inline unsigned inorder_to_eytzinger(unsigned j, unsigned size)
156 return __inorder_to_eytzinger(j, size, eytzinger_extra(size));
159 #define eytzinger_for_each(_i, _size) \
160 for ((_i) = eytzinger_first((_size)); \
162 (_i) = eytzinger_next((_i), (_size)))
165 void eytzinger_test(void)
173 printk(KERN_INFO "tree size %u\n", size);
175 assert(eytzinger_prev(0, size) == eytzinger_last(size));
176 assert(eytzinger_next(0, size) == eytzinger_first(size));
178 assert(eytzinger_prev(eytzinger_first(size), size) == 0);
179 assert(eytzinger_next(eytzinger_last(size), size) == 0);
181 eytzinger_for_each(j, size) {
182 assert(from_inorder(i, size) == j);
183 assert(to_inorder(j, size) == i);
185 if (j != eytzinger_last(size)) {
186 unsigned next = eytzinger_next(j, size);
188 assert(eytzinger_prev(next, size) == j);
196 #endif /* _EYTZINGER_H */