common: tree: Various updates.
This commit is contained in:
		| @@ -43,246 +43,445 @@ | |||||||
|  * The maximum height of a red-black tree is 2lg (n+1). |  * The maximum height of a red-black tree is 2lg (n+1). | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include "common/assert.h" | namespace Common::freebsd { | ||||||
|  |  | ||||||
| namespace Common { | enum class RBColor { | ||||||
| template <typename T> |     RB_BLACK = 0, | ||||||
| class RBHead { |     RB_RED = 1, | ||||||
| public: |  | ||||||
|     [[nodiscard]] T* Root() { |  | ||||||
|         return rbh_root; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     [[nodiscard]] const T* Root() const { |  | ||||||
|         return rbh_root; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void SetRoot(T* root) { |  | ||||||
|         rbh_root = root; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     [[nodiscard]] bool IsEmpty() const { |  | ||||||
|         return Root() == nullptr; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| private: |  | ||||||
|     T* rbh_root = nullptr; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| enum class EntryColor { |  | ||||||
|     Black, |  | ||||||
|     Red, |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | #pragma pack(push, 4) | ||||||
| template <typename T> | template <typename T> | ||||||
| class RBEntry { | class RBEntry { | ||||||
| public: | public: | ||||||
|     [[nodiscard]] T* Left() { |     constexpr RBEntry() = default; | ||||||
|         return rbe_left; |  | ||||||
|  |     [[nodiscard]] constexpr T* Left() { | ||||||
|  |         return m_rbe_left; | ||||||
|  |     } | ||||||
|  |     [[nodiscard]] constexpr const T* Left() const { | ||||||
|  |         return m_rbe_left; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     [[nodiscard]] const T* Left() const { |     constexpr void SetLeft(T* e) { | ||||||
|         return rbe_left; |         m_rbe_left = e; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void SetLeft(T* left) { |     [[nodiscard]] constexpr T* Right() { | ||||||
|         rbe_left = left; |         return m_rbe_right; | ||||||
|  |     } | ||||||
|  |     [[nodiscard]] constexpr const T* Right() const { | ||||||
|  |         return m_rbe_right; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     [[nodiscard]] T* Right() { |     constexpr void SetRight(T* e) { | ||||||
|         return rbe_right; |         m_rbe_right = e; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     [[nodiscard]] const T* Right() const { |     [[nodiscard]] constexpr T* Parent() { | ||||||
|         return rbe_right; |         return m_rbe_parent; | ||||||
|  |     } | ||||||
|  |     [[nodiscard]] constexpr const T* Parent() const { | ||||||
|  |         return m_rbe_parent; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void SetRight(T* right) { |     constexpr void SetParent(T* e) { | ||||||
|         rbe_right = right; |         m_rbe_parent = e; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     [[nodiscard]] T* Parent() { |     [[nodiscard]] constexpr bool IsBlack() const { | ||||||
|         return rbe_parent; |         return m_rbe_color == RBColor::RB_BLACK; | ||||||
|  |     } | ||||||
|  |     [[nodiscard]] constexpr bool IsRed() const { | ||||||
|  |         return m_rbe_color == RBColor::RB_RED; | ||||||
|  |     } | ||||||
|  |     [[nodiscard]] constexpr RBColor Color() const { | ||||||
|  |         return m_rbe_color; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     [[nodiscard]] const T* Parent() const { |     constexpr void SetColor(RBColor c) { | ||||||
|         return rbe_parent; |         m_rbe_color = c; | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void SetParent(T* parent) { |  | ||||||
|         rbe_parent = parent; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     [[nodiscard]] bool IsBlack() const { |  | ||||||
|         return rbe_color == EntryColor::Black; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     [[nodiscard]] bool IsRed() const { |  | ||||||
|         return rbe_color == EntryColor::Red; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     [[nodiscard]] EntryColor Color() const { |  | ||||||
|         return rbe_color; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void SetColor(EntryColor color) { |  | ||||||
|         rbe_color = color; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
| private: | private: | ||||||
|     T* rbe_left = nullptr; |     T* m_rbe_left{}; | ||||||
|     T* rbe_right = nullptr; |     T* m_rbe_right{}; | ||||||
|     T* rbe_parent = nullptr; |     T* m_rbe_parent{}; | ||||||
|     EntryColor rbe_color{}; |     RBColor m_rbe_color{RBColor::RB_BLACK}; | ||||||
|  | }; | ||||||
|  | #pragma pack(pop) | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | struct CheckRBEntry { | ||||||
|  |     static constexpr bool value = false; | ||||||
|  | }; | ||||||
|  | template <typename T> | ||||||
|  | struct CheckRBEntry<RBEntry<T>> { | ||||||
|  |     static constexpr bool value = true; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| template <typename Node> | template <typename T> | ||||||
| [[nodiscard]] RBEntry<Node>& RB_ENTRY(Node* node) { | concept IsRBEntry = CheckRBEntry<T>::value; | ||||||
|     return node->GetEntry(); |  | ||||||
|  | template <typename T> | ||||||
|  | concept HasRBEntry = requires(T& t, const T& ct) { | ||||||
|  |     { t.GetRBEntry() } -> std::same_as<RBEntry<T>&>; | ||||||
|  |     { ct.GetRBEntry() } -> std::same_as<const RBEntry<T>&>; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | requires HasRBEntry<T> | ||||||
|  | class RBHead { | ||||||
|  | private: | ||||||
|  |     T* m_rbh_root = nullptr; | ||||||
|  |  | ||||||
|  | public: | ||||||
|  |     [[nodiscard]] constexpr T* Root() { | ||||||
|  |         return m_rbh_root; | ||||||
|  |     } | ||||||
|  |     [[nodiscard]] constexpr const T* Root() const { | ||||||
|  |         return m_rbh_root; | ||||||
|  |     } | ||||||
|  |     constexpr void SetRoot(T* root) { | ||||||
|  |         m_rbh_root = root; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     [[nodiscard]] constexpr bool IsEmpty() const { | ||||||
|  |         return this->Root() == nullptr; | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | requires HasRBEntry<T> | ||||||
|  | [[nodiscard]] constexpr RBEntry<T>& RB_ENTRY(T* t) { | ||||||
|  |     return t->GetRBEntry(); | ||||||
|  | } | ||||||
|  | template <typename T> | ||||||
|  | requires HasRBEntry<T> | ||||||
|  | [[nodiscard]] constexpr const RBEntry<T>& RB_ENTRY(const T* t) { | ||||||
|  |     return t->GetRBEntry(); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename Node> | template <typename T> | ||||||
| [[nodiscard]] const RBEntry<Node>& RB_ENTRY(const Node* node) { | requires HasRBEntry<T> | ||||||
|     return node->GetEntry(); | [[nodiscard]] constexpr T* RB_LEFT(T* t) { | ||||||
|  |     return RB_ENTRY(t).Left(); | ||||||
|  | } | ||||||
|  | template <typename T> | ||||||
|  | requires HasRBEntry<T> | ||||||
|  | [[nodiscard]] constexpr const T* RB_LEFT(const T* t) { | ||||||
|  |     return RB_ENTRY(t).Left(); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename Node> | template <typename T> | ||||||
| [[nodiscard]] Node* RB_PARENT(Node* node) { | requires HasRBEntry<T> | ||||||
|     return RB_ENTRY(node).Parent(); | [[nodiscard]] constexpr T* RB_RIGHT(T* t) { | ||||||
|  |     return RB_ENTRY(t).Right(); | ||||||
|  | } | ||||||
|  | template <typename T> | ||||||
|  | requires HasRBEntry<T> | ||||||
|  | [[nodiscard]] constexpr const T* RB_RIGHT(const T* t) { | ||||||
|  |     return RB_ENTRY(t).Right(); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename Node> | template <typename T> | ||||||
| [[nodiscard]] const Node* RB_PARENT(const Node* node) { | requires HasRBEntry<T> | ||||||
|     return RB_ENTRY(node).Parent(); | [[nodiscard]] constexpr T* RB_PARENT(T* t) { | ||||||
|  |     return RB_ENTRY(t).Parent(); | ||||||
|  | } | ||||||
|  | template <typename T> | ||||||
|  | requires HasRBEntry<T> | ||||||
|  | [[nodiscard]] constexpr const T* RB_PARENT(const T* t) { | ||||||
|  |     return RB_ENTRY(t).Parent(); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename Node> | template <typename T> | ||||||
| void RB_SET_PARENT(Node* node, Node* parent) { | requires HasRBEntry<T> | ||||||
|     return RB_ENTRY(node).SetParent(parent); | constexpr void RB_SET_LEFT(T* t, T* e) { | ||||||
|  |     RB_ENTRY(t).SetLeft(e); | ||||||
|  | } | ||||||
|  | template <typename T> | ||||||
|  | requires HasRBEntry<T> | ||||||
|  | constexpr void RB_SET_RIGHT(T* t, T* e) { | ||||||
|  |     RB_ENTRY(t).SetRight(e); | ||||||
|  | } | ||||||
|  | template <typename T> | ||||||
|  | requires HasRBEntry<T> | ||||||
|  | constexpr void RB_SET_PARENT(T* t, T* e) { | ||||||
|  |     RB_ENTRY(t).SetParent(e); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename Node> | template <typename T> | ||||||
| [[nodiscard]] Node* RB_LEFT(Node* node) { | requires HasRBEntry<T> | ||||||
|     return RB_ENTRY(node).Left(); | [[nodiscard]] constexpr bool RB_IS_BLACK(const T* t) { | ||||||
|  |     return RB_ENTRY(t).IsBlack(); | ||||||
|  | } | ||||||
|  | template <typename T> | ||||||
|  | requires HasRBEntry<T> | ||||||
|  | [[nodiscard]] constexpr bool RB_IS_RED(const T* t) { | ||||||
|  |     return RB_ENTRY(t).IsRed(); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename Node> | template <typename T> | ||||||
| [[nodiscard]] const Node* RB_LEFT(const Node* node) { | requires HasRBEntry<T> | ||||||
|     return RB_ENTRY(node).Left(); | [[nodiscard]] constexpr RBColor RB_COLOR(const T* t) { | ||||||
|  |     return RB_ENTRY(t).Color(); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename Node> | template <typename T> | ||||||
| void RB_SET_LEFT(Node* node, Node* left) { | requires HasRBEntry<T> | ||||||
|     return RB_ENTRY(node).SetLeft(left); | constexpr void RB_SET_COLOR(T* t, RBColor c) { | ||||||
|  |     RB_ENTRY(t).SetColor(c); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename Node> | template <typename T> | ||||||
| [[nodiscard]] Node* RB_RIGHT(Node* node) { | requires HasRBEntry<T> | ||||||
|     return RB_ENTRY(node).Right(); | constexpr void RB_SET(T* elm, T* parent) { | ||||||
|  |     auto& rb_entry = RB_ENTRY(elm); | ||||||
|  |     rb_entry.SetParent(parent); | ||||||
|  |     rb_entry.SetLeft(nullptr); | ||||||
|  |     rb_entry.SetRight(nullptr); | ||||||
|  |     rb_entry.SetColor(RBColor::RB_RED); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename Node> | template <typename T> | ||||||
| [[nodiscard]] const Node* RB_RIGHT(const Node* node) { | requires HasRBEntry<T> | ||||||
|     return RB_ENTRY(node).Right(); | constexpr void RB_SET_BLACKRED(T* black, T* red) { | ||||||
|  |     RB_SET_COLOR(black, RBColor::RB_BLACK); | ||||||
|  |     RB_SET_COLOR(red, RBColor::RB_RED); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename Node> | template <typename T> | ||||||
| void RB_SET_RIGHT(Node* node, Node* right) { | requires HasRBEntry<T> | ||||||
|     return RB_ENTRY(node).SetRight(right); | constexpr void RB_ROTATE_LEFT(RBHead<T>& head, T* elm, T*& tmp) { | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename Node> |  | ||||||
| [[nodiscard]] bool RB_IS_BLACK(const Node* node) { |  | ||||||
|     return RB_ENTRY(node).IsBlack(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename Node> |  | ||||||
| [[nodiscard]] bool RB_IS_RED(const Node* node) { |  | ||||||
|     return RB_ENTRY(node).IsRed(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename Node> |  | ||||||
| [[nodiscard]] EntryColor RB_COLOR(const Node* node) { |  | ||||||
|     return RB_ENTRY(node).Color(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename Node> |  | ||||||
| void RB_SET_COLOR(Node* node, EntryColor color) { |  | ||||||
|     return RB_ENTRY(node).SetColor(color); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename Node> |  | ||||||
| void RB_SET(Node* node, Node* parent) { |  | ||||||
|     auto& entry = RB_ENTRY(node); |  | ||||||
|     entry.SetParent(parent); |  | ||||||
|     entry.SetLeft(nullptr); |  | ||||||
|     entry.SetRight(nullptr); |  | ||||||
|     entry.SetColor(EntryColor::Red); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename Node> |  | ||||||
| void RB_SET_BLACKRED(Node* black, Node* red) { |  | ||||||
|     RB_SET_COLOR(black, EntryColor::Black); |  | ||||||
|     RB_SET_COLOR(red, EntryColor::Red); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename Node> |  | ||||||
| void RB_ROTATE_LEFT(RBHead<Node>* head, Node* elm, Node*& tmp) { |  | ||||||
|     tmp = RB_RIGHT(elm); |     tmp = RB_RIGHT(elm); | ||||||
|     RB_SET_RIGHT(elm, RB_LEFT(tmp)); |     if (RB_SET_RIGHT(elm, RB_LEFT(tmp)); RB_RIGHT(elm) != nullptr) { | ||||||
|     if (RB_RIGHT(elm) != nullptr) { |  | ||||||
|         RB_SET_PARENT(RB_LEFT(tmp), elm); |         RB_SET_PARENT(RB_LEFT(tmp), elm); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     RB_SET_PARENT(tmp, RB_PARENT(elm)); |     if (RB_SET_PARENT(tmp, RB_PARENT(elm)); RB_PARENT(tmp) != nullptr) { | ||||||
|     if (RB_PARENT(tmp) != nullptr) { |  | ||||||
|         if (elm == RB_LEFT(RB_PARENT(elm))) { |         if (elm == RB_LEFT(RB_PARENT(elm))) { | ||||||
|             RB_SET_LEFT(RB_PARENT(elm), tmp); |             RB_SET_LEFT(RB_PARENT(elm), tmp); | ||||||
|         } else { |         } else { | ||||||
|             RB_SET_RIGHT(RB_PARENT(elm), tmp); |             RB_SET_RIGHT(RB_PARENT(elm), tmp); | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         head->SetRoot(tmp); |         head.SetRoot(tmp); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     RB_SET_LEFT(tmp, elm); |     RB_SET_LEFT(tmp, elm); | ||||||
|     RB_SET_PARENT(elm, tmp); |     RB_SET_PARENT(elm, tmp); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename Node> | template <typename T> | ||||||
| void RB_ROTATE_RIGHT(RBHead<Node>* head, Node* elm, Node*& tmp) { | requires HasRBEntry<T> | ||||||
|  | constexpr void RB_ROTATE_RIGHT(RBHead<T>& head, T* elm, T*& tmp) { | ||||||
|     tmp = RB_LEFT(elm); |     tmp = RB_LEFT(elm); | ||||||
|     RB_SET_LEFT(elm, RB_RIGHT(tmp)); |     if (RB_SET_LEFT(elm, RB_RIGHT(tmp)); RB_LEFT(elm) != nullptr) { | ||||||
|     if (RB_LEFT(elm) != nullptr) { |  | ||||||
|         RB_SET_PARENT(RB_RIGHT(tmp), elm); |         RB_SET_PARENT(RB_RIGHT(tmp), elm); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     RB_SET_PARENT(tmp, RB_PARENT(elm)); |     if (RB_SET_PARENT(tmp, RB_PARENT(elm)); RB_PARENT(tmp) != nullptr) { | ||||||
|     if (RB_PARENT(tmp) != nullptr) { |  | ||||||
|         if (elm == RB_LEFT(RB_PARENT(elm))) { |         if (elm == RB_LEFT(RB_PARENT(elm))) { | ||||||
|             RB_SET_LEFT(RB_PARENT(elm), tmp); |             RB_SET_LEFT(RB_PARENT(elm), tmp); | ||||||
|         } else { |         } else { | ||||||
|             RB_SET_RIGHT(RB_PARENT(elm), tmp); |             RB_SET_RIGHT(RB_PARENT(elm), tmp); | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         head->SetRoot(tmp); |         head.SetRoot(tmp); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     RB_SET_RIGHT(tmp, elm); |     RB_SET_RIGHT(tmp, elm); | ||||||
|     RB_SET_PARENT(elm, tmp); |     RB_SET_PARENT(elm, tmp); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename Node> | template <typename T> | ||||||
| void RB_INSERT_COLOR(RBHead<Node>* head, Node* elm) { | requires HasRBEntry<T> | ||||||
|     Node* parent = nullptr; | constexpr void RB_REMOVE_COLOR(RBHead<T>& head, T* parent, T* elm) { | ||||||
|     Node* tmp = nullptr; |     T* tmp; | ||||||
|  |     while ((elm == nullptr || RB_IS_BLACK(elm)) && elm != head.Root()) { | ||||||
|  |         if (RB_LEFT(parent) == elm) { | ||||||
|  |             tmp = RB_RIGHT(parent); | ||||||
|  |             if (RB_IS_RED(tmp)) { | ||||||
|  |                 RB_SET_BLACKRED(tmp, parent); | ||||||
|  |                 RB_ROTATE_LEFT(head, parent, tmp); | ||||||
|  |                 tmp = RB_RIGHT(parent); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if ((RB_LEFT(tmp) == nullptr || RB_IS_BLACK(RB_LEFT(tmp))) && | ||||||
|  |                 (RB_RIGHT(tmp) == nullptr || RB_IS_BLACK(RB_RIGHT(tmp)))) { | ||||||
|  |                 RB_SET_COLOR(tmp, RBColor::RB_RED); | ||||||
|  |                 elm = parent; | ||||||
|  |                 parent = RB_PARENT(elm); | ||||||
|  |             } else { | ||||||
|  |                 if (RB_RIGHT(tmp) == nullptr || RB_IS_BLACK(RB_RIGHT(tmp))) { | ||||||
|  |                     T* oleft; | ||||||
|  |                     if ((oleft = RB_LEFT(tmp)) != nullptr) { | ||||||
|  |                         RB_SET_COLOR(oleft, RBColor::RB_BLACK); | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                     RB_SET_COLOR(tmp, RBColor::RB_RED); | ||||||
|  |                     RB_ROTATE_RIGHT(head, tmp, oleft); | ||||||
|  |                     tmp = RB_RIGHT(parent); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 RB_SET_COLOR(tmp, RB_COLOR(parent)); | ||||||
|  |                 RB_SET_COLOR(parent, RBColor::RB_BLACK); | ||||||
|  |                 if (RB_RIGHT(tmp)) { | ||||||
|  |                     RB_SET_COLOR(RB_RIGHT(tmp), RBColor::RB_BLACK); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 RB_ROTATE_LEFT(head, parent, tmp); | ||||||
|  |                 elm = head.Root(); | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             tmp = RB_LEFT(parent); | ||||||
|  |             if (RB_IS_RED(tmp)) { | ||||||
|  |                 RB_SET_BLACKRED(tmp, parent); | ||||||
|  |                 RB_ROTATE_RIGHT(head, parent, tmp); | ||||||
|  |                 tmp = RB_LEFT(parent); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if ((RB_LEFT(tmp) == nullptr || RB_IS_BLACK(RB_LEFT(tmp))) && | ||||||
|  |                 (RB_RIGHT(tmp) == nullptr || RB_IS_BLACK(RB_RIGHT(tmp)))) { | ||||||
|  |                 RB_SET_COLOR(tmp, RBColor::RB_RED); | ||||||
|  |                 elm = parent; | ||||||
|  |                 parent = RB_PARENT(elm); | ||||||
|  |             } else { | ||||||
|  |                 if (RB_LEFT(tmp) == nullptr || RB_IS_BLACK(RB_LEFT(tmp))) { | ||||||
|  |                     T* oright; | ||||||
|  |                     if ((oright = RB_RIGHT(tmp)) != nullptr) { | ||||||
|  |                         RB_SET_COLOR(oright, RBColor::RB_BLACK); | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                     RB_SET_COLOR(tmp, RBColor::RB_RED); | ||||||
|  |                     RB_ROTATE_LEFT(head, tmp, oright); | ||||||
|  |                     tmp = RB_LEFT(parent); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 RB_SET_COLOR(tmp, RB_COLOR(parent)); | ||||||
|  |                 RB_SET_COLOR(parent, RBColor::RB_BLACK); | ||||||
|  |  | ||||||
|  |                 if (RB_LEFT(tmp)) { | ||||||
|  |                     RB_SET_COLOR(RB_LEFT(tmp), RBColor::RB_BLACK); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 RB_ROTATE_RIGHT(head, parent, tmp); | ||||||
|  |                 elm = head.Root(); | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (elm) { | ||||||
|  |         RB_SET_COLOR(elm, RBColor::RB_BLACK); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | requires HasRBEntry<T> | ||||||
|  | constexpr T* RB_REMOVE(RBHead<T>& head, T* elm) { | ||||||
|  |     T* child = nullptr; | ||||||
|  |     T* parent = nullptr; | ||||||
|  |     T* old = elm; | ||||||
|  |     RBColor color = RBColor::RB_BLACK; | ||||||
|  |  | ||||||
|  |     if (RB_LEFT(elm) == nullptr) { | ||||||
|  |         child = RB_RIGHT(elm); | ||||||
|  |     } else if (RB_RIGHT(elm) == nullptr) { | ||||||
|  |         child = RB_LEFT(elm); | ||||||
|  |     } else { | ||||||
|  |         T* left; | ||||||
|  |         elm = RB_RIGHT(elm); | ||||||
|  |         while ((left = RB_LEFT(elm)) != nullptr) { | ||||||
|  |             elm = left; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         child = RB_RIGHT(elm); | ||||||
|  |         parent = RB_PARENT(elm); | ||||||
|  |         color = RB_COLOR(elm); | ||||||
|  |  | ||||||
|  |         if (child) { | ||||||
|  |             RB_SET_PARENT(child, parent); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (parent) { | ||||||
|  |             if (RB_LEFT(parent) == elm) { | ||||||
|  |                 RB_SET_LEFT(parent, child); | ||||||
|  |             } else { | ||||||
|  |                 RB_SET_RIGHT(parent, child); | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             head.SetRoot(child); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (RB_PARENT(elm) == old) { | ||||||
|  |             parent = elm; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         elm->SetRBEntry(old->GetRBEntry()); | ||||||
|  |  | ||||||
|  |         if (RB_PARENT(old)) { | ||||||
|  |             if (RB_LEFT(RB_PARENT(old)) == old) { | ||||||
|  |                 RB_SET_LEFT(RB_PARENT(old), elm); | ||||||
|  |             } else { | ||||||
|  |                 RB_SET_RIGHT(RB_PARENT(old), elm); | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             head.SetRoot(elm); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         RB_SET_PARENT(RB_LEFT(old), elm); | ||||||
|  |  | ||||||
|  |         if (RB_RIGHT(old)) { | ||||||
|  |             RB_SET_PARENT(RB_RIGHT(old), elm); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (parent) { | ||||||
|  |             left = parent; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (color == RBColor::RB_BLACK) { | ||||||
|  |             RB_REMOVE_COLOR(head, parent, child); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return old; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     parent = RB_PARENT(elm); | ||||||
|  |     color = RB_COLOR(elm); | ||||||
|  |  | ||||||
|  |     if (child) { | ||||||
|  |         RB_SET_PARENT(child, parent); | ||||||
|  |     } | ||||||
|  |     if (parent) { | ||||||
|  |         if (RB_LEFT(parent) == elm) { | ||||||
|  |             RB_SET_LEFT(parent, child); | ||||||
|  |         } else { | ||||||
|  |             RB_SET_RIGHT(parent, child); | ||||||
|  |         } | ||||||
|  |     } else { | ||||||
|  |         head.SetRoot(child); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (color == RBColor::RB_BLACK) { | ||||||
|  |         RB_REMOVE_COLOR(head, parent, child); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return old; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | requires HasRBEntry<T> | ||||||
|  | constexpr void RB_INSERT_COLOR(RBHead<T>& head, T* elm) { | ||||||
|  |     T *parent = nullptr, *tmp = nullptr; | ||||||
|     while ((parent = RB_PARENT(elm)) != nullptr && RB_IS_RED(parent)) { |     while ((parent = RB_PARENT(elm)) != nullptr && RB_IS_RED(parent)) { | ||||||
|         Node* gparent = RB_PARENT(parent); |         T* gparent = RB_PARENT(parent); | ||||||
|         if (parent == RB_LEFT(gparent)) { |         if (parent == RB_LEFT(gparent)) { | ||||||
|             tmp = RB_RIGHT(gparent); |             tmp = RB_RIGHT(gparent); | ||||||
|             if (tmp && RB_IS_RED(tmp)) { |             if (tmp && RB_IS_RED(tmp)) { | ||||||
|                 RB_SET_COLOR(tmp, EntryColor::Black); |                 RB_SET_COLOR(tmp, RBColor::RB_BLACK); | ||||||
|                 RB_SET_BLACKRED(parent, gparent); |                 RB_SET_BLACKRED(parent, gparent); | ||||||
|                 elm = gparent; |                 elm = gparent; | ||||||
|                 continue; |                 continue; | ||||||
| @@ -300,7 +499,7 @@ void RB_INSERT_COLOR(RBHead<Node>* head, Node* elm) { | |||||||
|         } else { |         } else { | ||||||
|             tmp = RB_LEFT(gparent); |             tmp = RB_LEFT(gparent); | ||||||
|             if (tmp && RB_IS_RED(tmp)) { |             if (tmp && RB_IS_RED(tmp)) { | ||||||
|                 RB_SET_COLOR(tmp, EntryColor::Black); |                 RB_SET_COLOR(tmp, RBColor::RB_BLACK); | ||||||
|                 RB_SET_BLACKRED(parent, gparent); |                 RB_SET_BLACKRED(parent, gparent); | ||||||
|                 elm = gparent; |                 elm = gparent; | ||||||
|                 continue; |                 continue; | ||||||
| @@ -318,194 +517,14 @@ void RB_INSERT_COLOR(RBHead<Node>* head, Node* elm) { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     RB_SET_COLOR(head->Root(), EntryColor::Black); |     RB_SET_COLOR(head.Root(), RBColor::RB_BLACK); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename Node> | template <typename T, typename Compare> | ||||||
| void RB_REMOVE_COLOR(RBHead<Node>* head, Node* parent, Node* elm) { | requires HasRBEntry<T> | ||||||
|     Node* tmp; | constexpr T* RB_INSERT(RBHead<T>& head, T* elm, Compare cmp) { | ||||||
|     while ((elm == nullptr || RB_IS_BLACK(elm)) && elm != head->Root() && parent != nullptr) { |     T* parent = nullptr; | ||||||
|         if (RB_LEFT(parent) == elm) { |     T* tmp = head.Root(); | ||||||
|             tmp = RB_RIGHT(parent); |  | ||||||
|             if (!tmp) { |  | ||||||
|                 ASSERT_MSG(false, "tmp is invalid!"); |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
|             if (RB_IS_RED(tmp)) { |  | ||||||
|                 RB_SET_BLACKRED(tmp, parent); |  | ||||||
|                 RB_ROTATE_LEFT(head, parent, tmp); |  | ||||||
|                 tmp = RB_RIGHT(parent); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if ((RB_LEFT(tmp) == nullptr || RB_IS_BLACK(RB_LEFT(tmp))) && |  | ||||||
|                 (RB_RIGHT(tmp) == nullptr || RB_IS_BLACK(RB_RIGHT(tmp)))) { |  | ||||||
|                 RB_SET_COLOR(tmp, EntryColor::Red); |  | ||||||
|                 elm = parent; |  | ||||||
|                 parent = RB_PARENT(elm); |  | ||||||
|             } else { |  | ||||||
|                 if (RB_RIGHT(tmp) == nullptr || RB_IS_BLACK(RB_RIGHT(tmp))) { |  | ||||||
|                     Node* oleft; |  | ||||||
|                     if ((oleft = RB_LEFT(tmp)) != nullptr) { |  | ||||||
|                         RB_SET_COLOR(oleft, EntryColor::Black); |  | ||||||
|                     } |  | ||||||
|  |  | ||||||
|                     RB_SET_COLOR(tmp, EntryColor::Red); |  | ||||||
|                     RB_ROTATE_RIGHT(head, tmp, oleft); |  | ||||||
|                     tmp = RB_RIGHT(parent); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 RB_SET_COLOR(tmp, RB_COLOR(parent)); |  | ||||||
|                 RB_SET_COLOR(parent, EntryColor::Black); |  | ||||||
|                 if (RB_RIGHT(tmp)) { |  | ||||||
|                     RB_SET_COLOR(RB_RIGHT(tmp), EntryColor::Black); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 RB_ROTATE_LEFT(head, parent, tmp); |  | ||||||
|                 elm = head->Root(); |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
|         } else { |  | ||||||
|             tmp = RB_LEFT(parent); |  | ||||||
|             if (RB_IS_RED(tmp)) { |  | ||||||
|                 RB_SET_BLACKRED(tmp, parent); |  | ||||||
|                 RB_ROTATE_RIGHT(head, parent, tmp); |  | ||||||
|                 tmp = RB_LEFT(parent); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if (!tmp) { |  | ||||||
|                 ASSERT_MSG(false, "tmp is invalid!"); |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if ((RB_LEFT(tmp) == nullptr || RB_IS_BLACK(RB_LEFT(tmp))) && |  | ||||||
|                 (RB_RIGHT(tmp) == nullptr || RB_IS_BLACK(RB_RIGHT(tmp)))) { |  | ||||||
|                 RB_SET_COLOR(tmp, EntryColor::Red); |  | ||||||
|                 elm = parent; |  | ||||||
|                 parent = RB_PARENT(elm); |  | ||||||
|             } else { |  | ||||||
|                 if (RB_LEFT(tmp) == nullptr || RB_IS_BLACK(RB_LEFT(tmp))) { |  | ||||||
|                     Node* oright; |  | ||||||
|                     if ((oright = RB_RIGHT(tmp)) != nullptr) { |  | ||||||
|                         RB_SET_COLOR(oright, EntryColor::Black); |  | ||||||
|                     } |  | ||||||
|  |  | ||||||
|                     RB_SET_COLOR(tmp, EntryColor::Red); |  | ||||||
|                     RB_ROTATE_LEFT(head, tmp, oright); |  | ||||||
|                     tmp = RB_LEFT(parent); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 RB_SET_COLOR(tmp, RB_COLOR(parent)); |  | ||||||
|                 RB_SET_COLOR(parent, EntryColor::Black); |  | ||||||
|  |  | ||||||
|                 if (RB_LEFT(tmp)) { |  | ||||||
|                     RB_SET_COLOR(RB_LEFT(tmp), EntryColor::Black); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 RB_ROTATE_RIGHT(head, parent, tmp); |  | ||||||
|                 elm = head->Root(); |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (elm) { |  | ||||||
|         RB_SET_COLOR(elm, EntryColor::Black); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename Node> |  | ||||||
| Node* RB_REMOVE(RBHead<Node>* head, Node* elm) { |  | ||||||
|     Node* child = nullptr; |  | ||||||
|     Node* parent = nullptr; |  | ||||||
|     Node* old = elm; |  | ||||||
|     EntryColor color{}; |  | ||||||
|  |  | ||||||
|     const auto finalize = [&] { |  | ||||||
|         if (color == EntryColor::Black) { |  | ||||||
|             RB_REMOVE_COLOR(head, parent, child); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         return old; |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     if (RB_LEFT(elm) == nullptr) { |  | ||||||
|         child = RB_RIGHT(elm); |  | ||||||
|     } else if (RB_RIGHT(elm) == nullptr) { |  | ||||||
|         child = RB_LEFT(elm); |  | ||||||
|     } else { |  | ||||||
|         Node* left; |  | ||||||
|         elm = RB_RIGHT(elm); |  | ||||||
|         while ((left = RB_LEFT(elm)) != nullptr) { |  | ||||||
|             elm = left; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         child = RB_RIGHT(elm); |  | ||||||
|         parent = RB_PARENT(elm); |  | ||||||
|         color = RB_COLOR(elm); |  | ||||||
|  |  | ||||||
|         if (child) { |  | ||||||
|             RB_SET_PARENT(child, parent); |  | ||||||
|         } |  | ||||||
|         if (parent) { |  | ||||||
|             if (RB_LEFT(parent) == elm) { |  | ||||||
|                 RB_SET_LEFT(parent, child); |  | ||||||
|             } else { |  | ||||||
|                 RB_SET_RIGHT(parent, child); |  | ||||||
|             } |  | ||||||
|         } else { |  | ||||||
|             head->SetRoot(child); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (RB_PARENT(elm) == old) { |  | ||||||
|             parent = elm; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         elm->SetEntry(old->GetEntry()); |  | ||||||
|  |  | ||||||
|         if (RB_PARENT(old)) { |  | ||||||
|             if (RB_LEFT(RB_PARENT(old)) == old) { |  | ||||||
|                 RB_SET_LEFT(RB_PARENT(old), elm); |  | ||||||
|             } else { |  | ||||||
|                 RB_SET_RIGHT(RB_PARENT(old), elm); |  | ||||||
|             } |  | ||||||
|         } else { |  | ||||||
|             head->SetRoot(elm); |  | ||||||
|         } |  | ||||||
|         RB_SET_PARENT(RB_LEFT(old), elm); |  | ||||||
|         if (RB_RIGHT(old)) { |  | ||||||
|             RB_SET_PARENT(RB_RIGHT(old), elm); |  | ||||||
|         } |  | ||||||
|         if (parent) { |  | ||||||
|             left = parent; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         return finalize(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     parent = RB_PARENT(elm); |  | ||||||
|     color = RB_COLOR(elm); |  | ||||||
|  |  | ||||||
|     if (child) { |  | ||||||
|         RB_SET_PARENT(child, parent); |  | ||||||
|     } |  | ||||||
|     if (parent) { |  | ||||||
|         if (RB_LEFT(parent) == elm) { |  | ||||||
|             RB_SET_LEFT(parent, child); |  | ||||||
|         } else { |  | ||||||
|             RB_SET_RIGHT(parent, child); |  | ||||||
|         } |  | ||||||
|     } else { |  | ||||||
|         head->SetRoot(child); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return finalize(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Inserts a node into the RB tree |  | ||||||
| template <typename Node, typename CompareFunction> |  | ||||||
| Node* RB_INSERT(RBHead<Node>* head, Node* elm, CompareFunction cmp) { |  | ||||||
|     Node* parent = nullptr; |  | ||||||
|     Node* tmp = head->Root(); |  | ||||||
|     int comp = 0; |     int comp = 0; | ||||||
|  |  | ||||||
|     while (tmp) { |     while (tmp) { | ||||||
| @@ -529,17 +548,17 @@ Node* RB_INSERT(RBHead<Node>* head, Node* elm, CompareFunction cmp) { | |||||||
|             RB_SET_RIGHT(parent, elm); |             RB_SET_RIGHT(parent, elm); | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         head->SetRoot(elm); |         head.SetRoot(elm); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     RB_INSERT_COLOR(head, elm); |     RB_INSERT_COLOR(head, elm); | ||||||
|     return nullptr; |     return nullptr; | ||||||
| } | } | ||||||
|  |  | ||||||
| // Finds the node with the same key as elm | template <typename T, typename Compare> | ||||||
| template <typename Node, typename CompareFunction> | requires HasRBEntry<T> | ||||||
| Node* RB_FIND(RBHead<Node>* head, Node* elm, CompareFunction cmp) { | constexpr T* RB_FIND(RBHead<T>& head, T* elm, Compare cmp) { | ||||||
|     Node* tmp = head->Root(); |     T* tmp = head.Root(); | ||||||
|  |  | ||||||
|     while (tmp) { |     while (tmp) { | ||||||
|         const int comp = cmp(elm, tmp); |         const int comp = cmp(elm, tmp); | ||||||
| @@ -555,11 +574,11 @@ Node* RB_FIND(RBHead<Node>* head, Node* elm, CompareFunction cmp) { | |||||||
|     return nullptr; |     return nullptr; | ||||||
| } | } | ||||||
|  |  | ||||||
| // Finds the first node greater than or equal to the search key | template <typename T, typename Compare> | ||||||
| template <typename Node, typename CompareFunction> | requires HasRBEntry<T> | ||||||
| Node* RB_NFIND(RBHead<Node>* head, Node* elm, CompareFunction cmp) { | constexpr T* RB_NFIND(RBHead<T>& head, T* elm, Compare cmp) { | ||||||
|     Node* tmp = head->Root(); |     T* tmp = head.Root(); | ||||||
|     Node* res = nullptr; |     T* res = nullptr; | ||||||
|  |  | ||||||
|     while (tmp) { |     while (tmp) { | ||||||
|         const int comp = cmp(elm, tmp); |         const int comp = cmp(elm, tmp); | ||||||
| @@ -576,13 +595,13 @@ Node* RB_NFIND(RBHead<Node>* head, Node* elm, CompareFunction cmp) { | |||||||
|     return res; |     return res; | ||||||
| } | } | ||||||
|  |  | ||||||
| // Finds the node with the same key as lelm | template <typename T, typename U, typename Compare> | ||||||
| template <typename Node, typename CompareFunction> | requires HasRBEntry<T> | ||||||
| Node* RB_FIND_LIGHT(RBHead<Node>* head, const void* lelm, CompareFunction lcmp) { | constexpr T* RB_FIND_KEY(RBHead<T>& head, const U& key, Compare cmp) { | ||||||
|     Node* tmp = head->Root(); |     T* tmp = head.Root(); | ||||||
|  |  | ||||||
|     while (tmp) { |     while (tmp) { | ||||||
|         const int comp = lcmp(lelm, tmp); |         const int comp = cmp(key, tmp); | ||||||
|         if (comp < 0) { |         if (comp < 0) { | ||||||
|             tmp = RB_LEFT(tmp); |             tmp = RB_LEFT(tmp); | ||||||
|         } else if (comp > 0) { |         } else if (comp > 0) { | ||||||
| @@ -595,14 +614,14 @@ Node* RB_FIND_LIGHT(RBHead<Node>* head, const void* lelm, CompareFunction lcmp) | |||||||
|     return nullptr; |     return nullptr; | ||||||
| } | } | ||||||
|  |  | ||||||
| // Finds the first node greater than or equal to the search key | template <typename T, typename U, typename Compare> | ||||||
| template <typename Node, typename CompareFunction> | requires HasRBEntry<T> | ||||||
| Node* RB_NFIND_LIGHT(RBHead<Node>* head, const void* lelm, CompareFunction lcmp) { | constexpr T* RB_NFIND_KEY(RBHead<T>& head, const U& key, Compare cmp) { | ||||||
|     Node* tmp = head->Root(); |     T* tmp = head.Root(); | ||||||
|     Node* res = nullptr; |     T* res = nullptr; | ||||||
|  |  | ||||||
|     while (tmp) { |     while (tmp) { | ||||||
|         const int comp = lcmp(lelm, tmp); |         const int comp = cmp(key, tmp); | ||||||
|         if (comp < 0) { |         if (comp < 0) { | ||||||
|             res = tmp; |             res = tmp; | ||||||
|             tmp = RB_LEFT(tmp); |             tmp = RB_LEFT(tmp); | ||||||
| @@ -616,8 +635,43 @@ Node* RB_NFIND_LIGHT(RBHead<Node>* head, const void* lelm, CompareFunction lcmp) | |||||||
|     return res; |     return res; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename Node> | template <typename T, typename Compare> | ||||||
| Node* RB_NEXT(Node* elm) { | requires HasRBEntry<T> | ||||||
|  | constexpr T* RB_FIND_EXISTING(RBHead<T>& head, T* elm, Compare cmp) { | ||||||
|  |     T* tmp = head.Root(); | ||||||
|  |  | ||||||
|  |     while (true) { | ||||||
|  |         const int comp = cmp(elm, tmp); | ||||||
|  |         if (comp < 0) { | ||||||
|  |             tmp = RB_LEFT(tmp); | ||||||
|  |         } else if (comp > 0) { | ||||||
|  |             tmp = RB_RIGHT(tmp); | ||||||
|  |         } else { | ||||||
|  |             return tmp; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename T, typename U, typename Compare> | ||||||
|  | requires HasRBEntry<T> | ||||||
|  | constexpr T* RB_FIND_EXISTING_KEY(RBHead<T>& head, const U& key, Compare cmp) { | ||||||
|  |     T* tmp = head.Root(); | ||||||
|  |  | ||||||
|  |     while (true) { | ||||||
|  |         const int comp = cmp(key, tmp); | ||||||
|  |         if (comp < 0) { | ||||||
|  |             tmp = RB_LEFT(tmp); | ||||||
|  |         } else if (comp > 0) { | ||||||
|  |             tmp = RB_RIGHT(tmp); | ||||||
|  |         } else { | ||||||
|  |             return tmp; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | requires HasRBEntry<T> | ||||||
|  | constexpr T* RB_NEXT(T* elm) { | ||||||
|     if (RB_RIGHT(elm)) { |     if (RB_RIGHT(elm)) { | ||||||
|         elm = RB_RIGHT(elm); |         elm = RB_RIGHT(elm); | ||||||
|         while (RB_LEFT(elm)) { |         while (RB_LEFT(elm)) { | ||||||
| @@ -636,8 +690,9 @@ Node* RB_NEXT(Node* elm) { | |||||||
|     return elm; |     return elm; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename Node> | template <typename T> | ||||||
| Node* RB_PREV(Node* elm) { | requires HasRBEntry<T> | ||||||
|  | constexpr T* RB_PREV(T* elm) { | ||||||
|     if (RB_LEFT(elm)) { |     if (RB_LEFT(elm)) { | ||||||
|         elm = RB_LEFT(elm); |         elm = RB_LEFT(elm); | ||||||
|         while (RB_RIGHT(elm)) { |         while (RB_RIGHT(elm)) { | ||||||
| @@ -656,30 +711,32 @@ Node* RB_PREV(Node* elm) { | |||||||
|     return elm; |     return elm; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename Node> | template <typename T> | ||||||
| Node* RB_MINMAX(RBHead<Node>* head, bool is_min) { | requires HasRBEntry<T> | ||||||
|     Node* tmp = head->Root(); | constexpr T* RB_MIN(RBHead<T>& head) { | ||||||
|     Node* parent = nullptr; |     T* tmp = head.Root(); | ||||||
|  |     T* parent = nullptr; | ||||||
|  |  | ||||||
|     while (tmp) { |     while (tmp) { | ||||||
|         parent = tmp; |         parent = tmp; | ||||||
|         if (is_min) { |         tmp = RB_LEFT(tmp); | ||||||
|             tmp = RB_LEFT(tmp); |  | ||||||
|         } else { |  | ||||||
|             tmp = RB_RIGHT(tmp); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return parent; |     return parent; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename Node> | template <typename T> | ||||||
| Node* RB_MIN(RBHead<Node>* head) { | requires HasRBEntry<T> | ||||||
|     return RB_MINMAX(head, true); | constexpr T* RB_MAX(RBHead<T>& head) { | ||||||
|  |     T* tmp = head.Root(); | ||||||
|  |     T* parent = nullptr; | ||||||
|  |  | ||||||
|  |     while (tmp) { | ||||||
|  |         parent = tmp; | ||||||
|  |         tmp = RB_RIGHT(tmp); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return parent; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename Node> | } // namespace Common::freebsd | ||||||
| Node* RB_MAX(RBHead<Node>* head) { |  | ||||||
|     return RB_MINMAX(head, false); |  | ||||||
| } |  | ||||||
| } // namespace Common |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 bunnei
					bunnei