LLVM 23.0.0git
Eytzinger.h
Go to the documentation of this file.
1//===- Eytzinger.h - Eytzinger Search Tree Span -----------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file defines the EytzingerTableSpan class, a non-owning view of a
11/// buffer formatted as a complete binary search tree in Eytzinger
12/// (breadth-first) order.
13///
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_ADT_EYTZINGER_H
17#define LLVM_ADT_EYTZINGER_H
18
19#include <cassert>
20#include <cstddef>
21#include <optional>
22
23namespace llvm {
24
25/// Non-owning view of a buffer formatted as a complete binary search tree in
26/// Eytzinger (breadth-first) order.
27template <typename T> class EytzingerTableSpan {
28public:
29 EytzingerTableSpan() = default;
30 EytzingerTableSpan(const T *Data, size_t NumEntries)
31 : Data(Data), NumEntries(NumEntries) {}
32
33 [[nodiscard]] const T *data() const { return Data; }
34 [[nodiscard]] bool empty() const { return !Data || NumEntries == 0; }
35 [[nodiscard]] size_t size() const { return NumEntries; }
36 [[nodiscard]] const T &operator[](size_t Idx) const {
37 assert(Idx < NumEntries && "Index out of bounds");
38 return Data[Idx];
39 }
40
41 /// Search this Eytzinger table for Target. Returns the 0-based array index if
42 /// found.
43 ///
44 /// KeyT enables heterogeneous lookups, allowing callers to search tables of
45 /// endian-specific wrappers (e.g., support::ulittle64_t) using native integer
46 /// keys without explicit conversions at the call site.
47 template <typename KeyT = T>
48 [[nodiscard]] std::optional<size_t> findIndex(const KeyT &Target) const {
49 size_t I = 0;
50 while (I < NumEntries) {
51 if (Data[I] == Target)
52 return I;
53 I = 2 * I + 1 + (Data[I] < Target);
54 }
55 return std::nullopt;
56 }
57
58 /// Check if this Eytzinger table contains Target.
59 template <typename KeyT = T>
60 [[nodiscard]] bool contains(const KeyT &Target) const {
61 return findIndex(Target).has_value();
62 }
63
64 /// Verify whether the buffer satisfies strictly ascending binary search tree
65 /// order in Eytzinger layout. Runs iteratively in O(N) time and O(1) space.
66 [[nodiscard]] bool isSorted() const {
67 if (empty())
68 return true;
69
70 auto Left = [](size_t I) { return 2 * I + 1; };
71 auto Right = [](size_t I) { return 2 * I + 2; };
72 auto Parent = [](size_t I) { return (I - 1) / 2; };
73 auto IsRightChild = [](size_t I) { return I > 0 && I % 2 == 0; };
74 auto HasLeft = [&](size_t I) { return Left(I) < NumEntries; };
75 auto HasRight = [&](size_t I) { return Right(I) < NumEntries; };
76
77 // Start at the leftmost leaf (in-order minimum).
78 size_t Curr = 0;
79 while (HasLeft(Curr))
80 Curr = Left(Curr);
81
82 const T *Prev = nullptr;
83 while (Curr < NumEntries) {
84 if (Prev && !(*Prev < Data[Curr]))
85 return false;
86 Prev = &Data[Curr];
87
88 // Step to the in-order successor of Curr.
89 if (HasRight(Curr)) {
90 // If Curr has a right subtree, successor is its leftmost leaf.
91 Curr = Right(Curr);
92 while (HasLeft(Curr))
93 Curr = Left(Curr);
94 } else {
95 // Otherwise, walk upward while we are in the right branch.
96 while (IsRightChild(Curr))
97 Curr = Parent(Curr);
98 // Traversed the entire tree; done.
99 if (Curr == 0)
100 break;
101 // Step up from left child to parent.
102 Curr = Parent(Curr);
103 }
104 }
105 return true;
106 }
107
108private:
109 const T *Data = nullptr;
110 size_t NumEntries = 0;
111};
112
113} // namespace llvm
114
115#endif // LLVM_ADT_EYTZINGER_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define I(x, y, z)
Definition MD5.cpp:57
#define T
bool contains(const KeyT &Target) const
Check if this Eytzinger table contains Target.
Definition Eytzinger.h:60
EytzingerTableSpan(const T *Data, size_t NumEntries)
Definition Eytzinger.h:30
bool isSorted() const
Verify whether the buffer satisfies strictly ascending binary search tree order in Eytzinger layout.
Definition Eytzinger.h:66
std::optional< size_t > findIndex(const KeyT &Target) const
Search this Eytzinger table for Target.
Definition Eytzinger.h:48
const T & operator[](size_t Idx) const
Definition Eytzinger.h:36
size_t size() const
Definition Eytzinger.h:35
const T * data() const
Definition Eytzinger.h:33
Target - Wrapper for Target specific information.
This is an optimization pass for GlobalISel generic memory operations.