move_to_front.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. // Copyright (c) 2018 Google Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "source/comp/move_to_front.h"
  15. #include <algorithm>
  16. #include <iomanip>
  17. #include <iostream>
  18. #include <ostream>
  19. #include <sstream>
  20. #include <unordered_set>
  21. #include <utility>
  22. namespace spvtools {
  23. namespace comp {
  24. bool MoveToFront::Insert(uint32_t value) {
  25. auto it = value_to_node_.find(value);
  26. if (it != value_to_node_.end() && IsInTree(it->second)) return false;
  27. const uint32_t old_size = GetSize();
  28. (void)old_size;
  29. InsertNode(CreateNode(next_timestamp_++, value));
  30. last_accessed_value_ = value;
  31. last_accessed_value_valid_ = true;
  32. assert(value_to_node_.count(value));
  33. assert(old_size + 1 == GetSize());
  34. return true;
  35. }
  36. bool MoveToFront::Remove(uint32_t value) {
  37. auto it = value_to_node_.find(value);
  38. if (it == value_to_node_.end()) return false;
  39. if (!IsInTree(it->second)) return false;
  40. if (last_accessed_value_ == value) last_accessed_value_valid_ = false;
  41. const uint32_t orphan = RemoveNode(it->second);
  42. (void)orphan;
  43. // The node of |value| is still alive but it's orphaned now. Can still be
  44. // reused later.
  45. assert(!IsInTree(orphan));
  46. assert(ValueOf(orphan) == value);
  47. return true;
  48. }
  49. bool MoveToFront::RankFromValue(uint32_t value, uint32_t* rank) {
  50. if (last_accessed_value_valid_ && last_accessed_value_ == value) {
  51. *rank = 1;
  52. return true;
  53. }
  54. const uint32_t old_size = GetSize();
  55. if (old_size == 1) {
  56. if (ValueOf(root_) == value) {
  57. *rank = 1;
  58. return true;
  59. } else {
  60. return false;
  61. }
  62. }
  63. const auto it = value_to_node_.find(value);
  64. if (it == value_to_node_.end()) {
  65. return false;
  66. }
  67. uint32_t target = it->second;
  68. if (!IsInTree(target)) {
  69. return false;
  70. }
  71. uint32_t node = target;
  72. *rank = 1 + SizeOf(LeftOf(node));
  73. while (node) {
  74. if (IsRightChild(node)) *rank += 1 + SizeOf(LeftOf(ParentOf(node)));
  75. node = ParentOf(node);
  76. }
  77. // Don't update timestamp if the node has rank 1.
  78. if (*rank != 1) {
  79. // Update timestamp and reposition the node.
  80. target = RemoveNode(target);
  81. assert(ValueOf(target) == value);
  82. assert(old_size == GetSize() + 1);
  83. MutableTimestampOf(target) = next_timestamp_++;
  84. InsertNode(target);
  85. assert(old_size == GetSize());
  86. }
  87. last_accessed_value_ = value;
  88. last_accessed_value_valid_ = true;
  89. return true;
  90. }
  91. bool MoveToFront::HasValue(uint32_t value) const {
  92. const auto it = value_to_node_.find(value);
  93. if (it == value_to_node_.end()) {
  94. return false;
  95. }
  96. return IsInTree(it->second);
  97. }
  98. bool MoveToFront::Promote(uint32_t value) {
  99. if (last_accessed_value_valid_ && last_accessed_value_ == value) {
  100. return true;
  101. }
  102. const uint32_t old_size = GetSize();
  103. if (old_size == 1) return ValueOf(root_) == value;
  104. const auto it = value_to_node_.find(value);
  105. if (it == value_to_node_.end()) {
  106. return false;
  107. }
  108. uint32_t target = it->second;
  109. if (!IsInTree(target)) {
  110. return false;
  111. }
  112. // Update timestamp and reposition the node.
  113. target = RemoveNode(target);
  114. assert(ValueOf(target) == value);
  115. assert(old_size == GetSize() + 1);
  116. MutableTimestampOf(target) = next_timestamp_++;
  117. InsertNode(target);
  118. assert(old_size == GetSize());
  119. last_accessed_value_ = value;
  120. last_accessed_value_valid_ = true;
  121. return true;
  122. }
  123. bool MoveToFront::ValueFromRank(uint32_t rank, uint32_t* value) {
  124. if (last_accessed_value_valid_ && rank == 1) {
  125. *value = last_accessed_value_;
  126. return true;
  127. }
  128. const uint32_t old_size = GetSize();
  129. if (rank <= 0 || rank > old_size) {
  130. return false;
  131. }
  132. if (old_size == 1) {
  133. *value = ValueOf(root_);
  134. return true;
  135. }
  136. const bool update_timestamp = (rank != 1);
  137. uint32_t node = root_;
  138. while (node) {
  139. const uint32_t left_subtree_num_nodes = SizeOf(LeftOf(node));
  140. if (rank == left_subtree_num_nodes + 1) {
  141. // This is the node we are looking for.
  142. // Don't update timestamp if the node has rank 1.
  143. if (update_timestamp) {
  144. node = RemoveNode(node);
  145. assert(old_size == GetSize() + 1);
  146. MutableTimestampOf(node) = next_timestamp_++;
  147. InsertNode(node);
  148. assert(old_size == GetSize());
  149. }
  150. *value = ValueOf(node);
  151. last_accessed_value_ = *value;
  152. last_accessed_value_valid_ = true;
  153. return true;
  154. }
  155. if (rank < left_subtree_num_nodes + 1) {
  156. // Descend into the left subtree. The rank is still valid.
  157. node = LeftOf(node);
  158. } else {
  159. // Descend into the right subtree. We leave behind the left subtree and
  160. // the current node, adjust the |rank| accordingly.
  161. rank -= left_subtree_num_nodes + 1;
  162. node = RightOf(node);
  163. }
  164. }
  165. assert(0);
  166. return false;
  167. }
  168. uint32_t MoveToFront::CreateNode(uint32_t timestamp, uint32_t value) {
  169. uint32_t handle = static_cast<uint32_t>(nodes_.size());
  170. const auto result = value_to_node_.emplace(value, handle);
  171. if (result.second) {
  172. // Create new node.
  173. nodes_.emplace_back(Node());
  174. Node& node = nodes_.back();
  175. node.timestamp = timestamp;
  176. node.value = value;
  177. node.size = 1;
  178. // Non-NIL nodes start with height 1 because their NIL children are
  179. // leaves.
  180. node.height = 1;
  181. } else {
  182. // Reuse old node.
  183. handle = result.first->second;
  184. assert(!IsInTree(handle));
  185. assert(ValueOf(handle) == value);
  186. assert(SizeOf(handle) == 1);
  187. assert(HeightOf(handle) == 1);
  188. MutableTimestampOf(handle) = timestamp;
  189. }
  190. return handle;
  191. }
  192. void MoveToFront::InsertNode(uint32_t node) {
  193. assert(!IsInTree(node));
  194. assert(SizeOf(node) == 1);
  195. assert(HeightOf(node) == 1);
  196. assert(TimestampOf(node));
  197. if (!root_) {
  198. root_ = node;
  199. return;
  200. }
  201. uint32_t iter = root_;
  202. uint32_t parent = 0;
  203. // Will determine if |node| will become the right or left child after
  204. // insertion (but before balancing).
  205. bool right_child = true;
  206. // Find the node which will become |node|'s parent after insertion
  207. // (but before balancing).
  208. while (iter) {
  209. parent = iter;
  210. assert(TimestampOf(iter) != TimestampOf(node));
  211. right_child = TimestampOf(iter) > TimestampOf(node);
  212. iter = right_child ? RightOf(iter) : LeftOf(iter);
  213. }
  214. assert(parent);
  215. // Connect node and parent.
  216. MutableParentOf(node) = parent;
  217. if (right_child)
  218. MutableRightOf(parent) = node;
  219. else
  220. MutableLeftOf(parent) = node;
  221. // Insertion is finished. Start the balancing process.
  222. bool needs_rebalancing = true;
  223. parent = ParentOf(node);
  224. while (parent) {
  225. UpdateNode(parent);
  226. if (needs_rebalancing) {
  227. const int parent_balance = BalanceOf(parent);
  228. if (RightOf(parent) == node) {
  229. // Added node to the right subtree.
  230. if (parent_balance > 1) {
  231. // Parent is right heavy, rotate left.
  232. if (BalanceOf(node) < 0) RotateRight(node);
  233. parent = RotateLeft(parent);
  234. } else if (parent_balance == 0 || parent_balance == -1) {
  235. // Parent is balanced or left heavy, no need to balance further.
  236. needs_rebalancing = false;
  237. }
  238. } else {
  239. // Added node to the left subtree.
  240. if (parent_balance < -1) {
  241. // Parent is left heavy, rotate right.
  242. if (BalanceOf(node) > 0) RotateLeft(node);
  243. parent = RotateRight(parent);
  244. } else if (parent_balance == 0 || parent_balance == 1) {
  245. // Parent is balanced or right heavy, no need to balance further.
  246. needs_rebalancing = false;
  247. }
  248. }
  249. }
  250. assert(BalanceOf(parent) >= -1 && (BalanceOf(parent) <= 1));
  251. node = parent;
  252. parent = ParentOf(parent);
  253. }
  254. }
  255. uint32_t MoveToFront::RemoveNode(uint32_t node) {
  256. if (LeftOf(node) && RightOf(node)) {
  257. // If |node| has two children, then use another node as scapegoat and swap
  258. // their contents. We pick the scapegoat on the side of the tree which has
  259. // more nodes.
  260. const uint32_t scapegoat = SizeOf(LeftOf(node)) >= SizeOf(RightOf(node))
  261. ? RightestDescendantOf(LeftOf(node))
  262. : LeftestDescendantOf(RightOf(node));
  263. assert(scapegoat);
  264. std::swap(MutableValueOf(node), MutableValueOf(scapegoat));
  265. std::swap(MutableTimestampOf(node), MutableTimestampOf(scapegoat));
  266. value_to_node_[ValueOf(node)] = node;
  267. value_to_node_[ValueOf(scapegoat)] = scapegoat;
  268. node = scapegoat;
  269. }
  270. // |node| may have only one child at this point.
  271. assert(!RightOf(node) || !LeftOf(node));
  272. uint32_t parent = ParentOf(node);
  273. uint32_t child = RightOf(node) ? RightOf(node) : LeftOf(node);
  274. // Orphan |node| and reconnect parent and child.
  275. if (child) MutableParentOf(child) = parent;
  276. if (parent) {
  277. if (LeftOf(parent) == node)
  278. MutableLeftOf(parent) = child;
  279. else
  280. MutableRightOf(parent) = child;
  281. }
  282. MutableParentOf(node) = 0;
  283. MutableLeftOf(node) = 0;
  284. MutableRightOf(node) = 0;
  285. UpdateNode(node);
  286. const uint32_t orphan = node;
  287. if (root_ == node) root_ = child;
  288. // Removal is finished. Start the balancing process.
  289. bool needs_rebalancing = true;
  290. node = child;
  291. while (parent) {
  292. UpdateNode(parent);
  293. if (needs_rebalancing) {
  294. const int parent_balance = BalanceOf(parent);
  295. if (parent_balance == 1 || parent_balance == -1) {
  296. // The height of the subtree was not changed.
  297. needs_rebalancing = false;
  298. } else {
  299. if (RightOf(parent) == node) {
  300. // Removed node from the right subtree.
  301. if (parent_balance < -1) {
  302. // Parent is left heavy, rotate right.
  303. const uint32_t sibling = LeftOf(parent);
  304. if (BalanceOf(sibling) > 0) RotateLeft(sibling);
  305. parent = RotateRight(parent);
  306. }
  307. } else {
  308. // Removed node from the left subtree.
  309. if (parent_balance > 1) {
  310. // Parent is right heavy, rotate left.
  311. const uint32_t sibling = RightOf(parent);
  312. if (BalanceOf(sibling) < 0) RotateRight(sibling);
  313. parent = RotateLeft(parent);
  314. }
  315. }
  316. }
  317. }
  318. assert(BalanceOf(parent) >= -1 && (BalanceOf(parent) <= 1));
  319. node = parent;
  320. parent = ParentOf(parent);
  321. }
  322. return orphan;
  323. }
  324. uint32_t MoveToFront::RotateLeft(const uint32_t node) {
  325. const uint32_t pivot = RightOf(node);
  326. assert(pivot);
  327. // LeftOf(pivot) gets attached to node in place of pivot.
  328. MutableRightOf(node) = LeftOf(pivot);
  329. if (RightOf(node)) MutableParentOf(RightOf(node)) = node;
  330. // Pivot gets attached to ParentOf(node) in place of node.
  331. MutableParentOf(pivot) = ParentOf(node);
  332. if (!ParentOf(node))
  333. root_ = pivot;
  334. else if (IsLeftChild(node))
  335. MutableLeftOf(ParentOf(node)) = pivot;
  336. else
  337. MutableRightOf(ParentOf(node)) = pivot;
  338. // Node is child of pivot.
  339. MutableLeftOf(pivot) = node;
  340. MutableParentOf(node) = pivot;
  341. // Update both node and pivot. Pivot is the new parent of node, so node should
  342. // be updated first.
  343. UpdateNode(node);
  344. UpdateNode(pivot);
  345. return pivot;
  346. }
  347. uint32_t MoveToFront::RotateRight(const uint32_t node) {
  348. const uint32_t pivot = LeftOf(node);
  349. assert(pivot);
  350. // RightOf(pivot) gets attached to node in place of pivot.
  351. MutableLeftOf(node) = RightOf(pivot);
  352. if (LeftOf(node)) MutableParentOf(LeftOf(node)) = node;
  353. // Pivot gets attached to ParentOf(node) in place of node.
  354. MutableParentOf(pivot) = ParentOf(node);
  355. if (!ParentOf(node))
  356. root_ = pivot;
  357. else if (IsLeftChild(node))
  358. MutableLeftOf(ParentOf(node)) = pivot;
  359. else
  360. MutableRightOf(ParentOf(node)) = pivot;
  361. // Node is child of pivot.
  362. MutableRightOf(pivot) = node;
  363. MutableParentOf(node) = pivot;
  364. // Update both node and pivot. Pivot is the new parent of node, so node should
  365. // be updated first.
  366. UpdateNode(node);
  367. UpdateNode(pivot);
  368. return pivot;
  369. }
  370. void MoveToFront::UpdateNode(uint32_t node) {
  371. MutableSizeOf(node) = 1 + SizeOf(LeftOf(node)) + SizeOf(RightOf(node));
  372. MutableHeightOf(node) =
  373. 1 + std::max(HeightOf(LeftOf(node)), HeightOf(RightOf(node)));
  374. }
  375. } // namespace comp
  376. } // namespace spvtools