@@ -13,13 +13,13 @@ import {StorageSlot} from "../StorageSlot.sol";
13
13
* @dev Library for managing https://en.wikipedia.org/wiki/Binary_heap[binary heap] that can be used as
14
14
* https://en.wikipedia.org/wiki/Priority_queue[priority queue].
15
15
*
16
- * Heaps are represented as an tree of values where the first element (index 0) is the root, and where the node at
17
- * index i is the child of the node at index (i-1)/2 and the father of nodes at index 2*i+1 and 2*i+2. Each node
16
+ * Heaps are represented as a tree of values where the first element (index 0) is the root, and where the node at
17
+ * index i is the child of the node at index (i-1)/2 and the parent of nodes at index 2*i+1 and 2*i+2. Each node
18
18
* stores an element of the heap.
19
19
*
20
20
* The structure is ordered so that each node is bigger than its parent. An immediate consequence is that the
21
21
* highest priority value is the one at the root. This value can be looked up in constant time (O(1)) at
22
- * `heap.tree[0].value `
22
+ * `heap.tree[0]`
23
23
*
24
24
* The structure is designed to perform the following operations with the corresponding complexities:
25
25
*
@@ -42,7 +42,7 @@ library Heap {
42
42
/**
43
43
* @dev Binary heap that supports values of type uint256.
44
44
*
45
- * Each element of that structure uses 2 storage slots .
45
+ * Each element of that structure uses one storage slot .
46
46
*/
47
47
struct Uint256Heap {
48
48
uint256 [] tree;
@@ -184,7 +184,7 @@ library Heap {
184
184
* @dev Perform heap maintenance on `self`, starting at `index` (with the `value`), using `comp` as a
185
185
* comparator, and moving toward the leaves of the underlying tree.
186
186
*
187
- * NOTE: This is a private function that is called in a trusted context with already cached parameters. `length `
187
+ * NOTE: This is a private function that is called in a trusted context with already cached parameters. `size `
188
188
* and `value` could be extracted from `self` and `index`, but that would require redundant storage read. These
189
189
* parameters are not verified. It is the caller role to make sure the parameters are correct.
190
190
*/
@@ -195,31 +195,33 @@ library Heap {
195
195
uint256 value ,
196
196
function (uint256 , uint256 ) view returns (bool ) comp
197
197
) private {
198
- // Check if there is a risk of overflow when computing the indices of the child nodes. If that is the case,
199
- // there cannot be child nodes in the tree, so sifting is done.
200
- if (index >= type (uint256 ).max / 2 ) return ;
201
-
202
- // Compute the indices of the potential child nodes
203
- uint256 lIndex = 2 * index + 1 ;
204
- uint256 rIndex = 2 * index + 2 ;
205
-
206
- // Three cases:
207
- // 1. Both children exist: sifting may continue on one of the branch (selection required)
208
- // 2. Only left child exist: sifting may contineu on the left branch (no selection required)
209
- // 3. Neither child exist: sifting is done
210
- if (rIndex < size) {
211
- uint256 lValue = self.tree.unsafeAccess (lIndex).value;
212
- uint256 rValue = self.tree.unsafeAccess (rIndex).value;
213
- if (comp (lValue, value) || comp (rValue, value)) {
214
- uint256 cIndex = comp (lValue, rValue).ternary (lIndex, rIndex);
215
- _swap (self, index, cIndex);
216
- _siftDown (self, size, cIndex, value, comp);
217
- }
218
- } else if (lIndex < size) {
219
- uint256 lValue = self.tree.unsafeAccess (lIndex).value;
220
- if (comp (lValue, value)) {
221
- _swap (self, index, lIndex);
222
- _siftDown (self, size, lIndex, value, comp);
198
+ unchecked {
199
+ // Check if there is a risk of overflow when computing the indices of the child nodes. If that is the case,
200
+ // there cannot be child nodes in the tree, so sifting is done.
201
+ if (index >= type (uint256 ).max / 2 ) return ;
202
+
203
+ // Compute the indices of the potential child nodes
204
+ uint256 lIndex = 2 * index + 1 ;
205
+ uint256 rIndex = 2 * index + 2 ;
206
+
207
+ // Three cases:
208
+ // 1. Both children exist: sifting may continue on one of the branch (selection required)
209
+ // 2. Only left child exist: sifting may continue on the left branch (no selection required)
210
+ // 3. Neither child exist: sifting is done
211
+ if (rIndex < size) {
212
+ uint256 lValue = self.tree.unsafeAccess (lIndex).value;
213
+ uint256 rValue = self.tree.unsafeAccess (rIndex).value;
214
+ if (comp (lValue, value) || comp (rValue, value)) {
215
+ uint256 cIndex = comp (lValue, rValue).ternary (lIndex, rIndex);
216
+ _swap (self, index, cIndex);
217
+ _siftDown (self, size, cIndex, value, comp);
218
+ }
219
+ } else if (lIndex < size) {
220
+ uint256 lValue = self.tree.unsafeAccess (lIndex).value;
221
+ if (comp (lValue, value)) {
222
+ _swap (self, index, lIndex);
223
+ _siftDown (self, size, lIndex, value, comp);
224
+ }
223
225
}
224
226
}
225
227
}
0 commit comments