FreeTensor
Loading...
Searching...
No Matches
shared_linked_list.h
Go to the documentation of this file.
1#ifndef FREE_TENSOR_SHARED_LINKED_LIST_H
2#define FREE_TENSOR_SHARED_LINKED_LIST_H
3
4#include <functional>
5
6#include <hash_combine.h>
7#include <ref.h>
8
9namespace freetensor {
10
20template <class T, class Hash = std::hash<T>, class Equal = std::equal_to<T>>
22 struct Node {
23 T data_;
24 size_t hash_; // Combined hash of all the nodes
25 Ref<Node> prev_;
26 };
27
28 Ref<Node> tail_;
29
30 public:
31 const T &top() const {
32 ASSERT(!empty());
33 return tail_->data_;
34 }
35
36 bool empty() const { return !tail_.isValid(); }
37
45 [[nodiscard]] SharedLinkedList push(const T &data) const {
46 auto node = Ref<Node>::make();
47 auto h = Hash()(data);
48 if (tail_.isValid()) {
49 h = hashCombine(tail_->hash_, h);
50 }
51 *node = {data, h, tail_};
52 auto ret = *this;
53 ret.tail_ = node;
54 return ret;
55 }
56
64 [[nodiscard]] SharedLinkedList pop() const {
65 auto ret = *this;
66 ret.tail_ = tail_->prev_;
67 return ret;
68 }
69
70 std::vector<T> asVector() const {
71 std::vector<T> revRet;
72 for (auto it = *this; !it.empty(); it = it.pop()) {
73 revRet.emplace_back(it.top());
74 }
75 return std::vector<T>(revRet.rbegin(), revRet.rend());
76 }
77
78 friend std::vector<T> asVector(const SharedLinkedList &bottom,
79 const SharedLinkedList &top) {
80 std::vector<T> revRet;
81 for (auto it = top; !it.empty() && it != bottom; it = it.pop()) {
82 revRet.emplace_back(it.top());
83 }
84 return std::vector<T>(revRet.rbegin(), revRet.rend());
85 }
86
87 size_t hash() const { return empty() ? 0 : tail_->hash_; }
88
89 friend bool operator==(const SharedLinkedList &lhs,
90 const SharedLinkedList &rhs) {
91 auto l = lhs, r = rhs;
92 while (!l.empty() && !r.empty()) {
93 if (l.tail_ == r.tail_) {
94 // Same object, which means two shared linked list form a tree,
95 // and this is their common ancestor, so no need to compare
96 return true;
97 }
98 if (l.hash() != r.hash()) {
99 return false;
100 }
101 if (!Equal()(l.top(), r.top())) {
102 return false;
103 }
104 l = l.pop(), r = r.pop();
105 }
106 return l.empty() && r.empty();
107 }
108};
109
110} // namespace freetensor
111
112namespace std {
113
114template <class T, class Hash, class Equal>
115class hash<freetensor::SharedLinkedList<T, Hash, Equal>> {
116 public:
119 return stack.hash();
120 }
121};
122
123} // namespace std
124
125#endif // FREE_TENSOR_SHARED_LINKED_LIST_H
Definition: ref.h:24
static Ref make()
Definition: ref.h:105
bool isValid() const
Definition: ref.h:89
Definition: shared_linked_list.h:21
std::vector< T > asVector() const
Definition: shared_linked_list.h:70
friend bool operator==(const SharedLinkedList &lhs, const SharedLinkedList &rhs)
Definition: shared_linked_list.h:89
friend std::vector< T > asVector(const SharedLinkedList &bottom, const SharedLinkedList &top)
Definition: shared_linked_list.h:78
size_t hash() const
Definition: shared_linked_list.h:87
SharedLinkedList push(const T &data) const
Definition: shared_linked_list.h:45
SharedLinkedList pop() const
Definition: shared_linked_list.h:64
const T & top() const
Definition: shared_linked_list.h:31
bool empty() const
Definition: shared_linked_list.h:36
size_t operator()(const freetensor::SharedLinkedList< T, Hash, Equal > &stack) const
Definition: shared_linked_list.h:117
#define ASSERT(expr)
Definition: except.h:152
Definition: allocator.h:9
auto && lhs
Definition: const_fold.cc:70
auto auto && rhs
Definition: const_fold.cc:70
size_t hashCombine(size_t seed, size_t other)
Definition: hash_combine.cc:5
STL namespace.