16#ifndef LLVM_ADT_EYTZINGER_H
17#define LLVM_ADT_EYTZINGER_H
37 : Data(Data), NumEntries(NumEntries) {}
40 [[nodiscard]]
iterator end()
const {
return Data + NumEntries; }
41 [[nodiscard]]
const T *
data()
const {
return Data; }
42 [[nodiscard]]
bool empty()
const {
return !Data || NumEntries == 0; }
43 [[nodiscard]]
size_t size()
const {
return NumEntries; }
45 assert(Idx < NumEntries &&
"Index out of bounds");
55 template <
typename KeyT = T>
58 while (
I < NumEntries) {
67 template <
typename KeyT = T>
78 auto Left = [](
size_t I) {
return 2 *
I + 1; };
79 auto Right = [](
size_t I) {
return 2 *
I + 2; };
80 auto Parent = [](
size_t I) {
return (
I - 1) / 2; };
81 auto IsRightChild = [](
size_t I) {
return I > 0 &&
I % 2 == 0; };
82 auto HasLeft = [&](
size_t I) {
return Left(
I) < NumEntries; };
83 auto HasRight = [&](
size_t I) {
return Right(
I) < NumEntries; };
90 const T *Prev =
nullptr;
91 while (Curr < NumEntries) {
92 if (Prev && !(*Prev < Data[Curr]))
100 while (HasLeft(Curr))
104 while (IsRightChild(Curr))
117 const T *
Data =
nullptr;
118 size_t NumEntries = 0;
123template <
typename T>
class EytzingerTable {
124 std::vector<T> Storage;
126 explicit EytzingerTable(std::vector<T> Buffer) : Storage(std::move(Buffer)) {}
129 using iterator =
typename std::vector<T>::const_iterator;
138 template <
typename KeyT = T>
139 static EytzingerTable<T>
create(std::vector<KeyT> Keys) {
143 std::vector<T> Eytzinger(Keys.size());
145 auto EytzingerInOrder = [&](
auto &Self,
size_t K) ->
void {
149 Eytzinger[K - 1] =
T(std::move(Keys[InIdx++]));
150 Self(Self, 2 * K + 1);
152 EytzingerInOrder(EytzingerInOrder, 1);
160 template <
typename KeyT = T>
165 template <
typename KeyT = T>
177 [[nodiscard]]
const T *
data()
const {
return Storage.data(); }
178 [[nodiscard]]
size_t size()
const {
return Storage.size(); }
179 [[nodiscard]]
bool empty()
const {
return Storage.empty(); }
181 assert(Idx < Storage.size() &&
"Index out of bounds");
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Non-owning view of a buffer formatted as a complete binary search tree in Eytzinger (breadth-first) o...
bool contains(const KeyT &Target) const
Check if this Eytzinger table contains Target.
EytzingerTableSpan(const T *Data, size_t NumEntries)
EytzingerTableSpan()=default
bool isSorted() const
Verify whether the buffer satisfies strictly ascending binary search tree order in Eytzinger layout.
std::optional< size_t > findIndex(const KeyT &Target) const
Search this Eytzinger table for Target.
const T & operator[](size_t Idx) const
const T & operator[](size_t Idx) const
typename std::vector< T >::const_iterator iterator
typename std::vector< T >::const_iterator const_iterator
const_iterator begin() const
static EytzingerTable< T > create(std::vector< KeyT > Keys)
Construct an Eytzinger search tree from a vector of keys by sorting, deduplicating,...
std::optional< size_t > findIndex(const KeyT &Target) const
EytzingerTableSpan< T > asSpan() const
bool contains(const KeyT &Target) const
const_iterator end() const
Target - Wrapper for Target specific information.
This is an optimization pass for GlobalISel generic memory operations.
auto unique(Range &&R, Predicate P)
void sort(IteratorTy Start, IteratorTy End)