Skip to content

Commit

Permalink
up
Browse files Browse the repository at this point in the history
  • Loading branch information
Amxx committed Jun 21, 2024
1 parent a46cc63 commit b2fda31
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 112 deletions.
2 changes: 1 addition & 1 deletion .githooks/pre-push
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
set -euo pipefail

if [ "${CI:-"false"}" != "true" ]; then
npm run generate
npm run test:generation
npm run lint
fi
154 changes: 78 additions & 76 deletions contracts/utils/structs/Heap.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ library Heap {
* @dev Lookup the root element of the heap.
*/
function peek(Uint256Heap storage self) internal view returns (uint256) {
// self.data[0] will `ARRAY_ACCESS_OUT_OF_BOUNDS` panic if heap is empty.
return _unsafeNodeAccess(self, self.data[0].index).value;
}

Expand All @@ -69,45 +70,46 @@ library Heap {
Uint256Heap storage self,
function(uint256, uint256) view returns (bool) comp
) internal returns (uint256) {
uint32 size = length(self);

if (size == 0) Panic.panic(Panic.EMPTY_ARRAY_POP);

uint32 last = size - 1; // could be unchecked (check above)

// get root location (in the data array) and value
Uint256HeapNode storage rootNode = _unsafeNodeAccess(self, 0);
uint32 rootIdx = rootNode.index;
Uint256HeapNode storage rootData = _unsafeNodeAccess(self, rootIdx);
Uint256HeapNode storage lastNode = _unsafeNodeAccess(self, last);
uint256 rootDataValue = rootData.value;

// if root is not the last element of the data array (that will get pop-ed), reorder the data array.
if (rootIdx != last) {
// get details about the value stored in the last element of the array (that will get pop-ed)
uint32 lastDataIdx = lastNode.lookup;
uint256 lastDataValue = lastNode.value;
// copy these values to the location of the root (that is safe, and that we no longer use)
rootData.value = lastDataValue;
rootData.lookup = lastDataIdx;
// update the tree node that used to point to that last element (value now located where the root was)
_unsafeNodeAccess(self, lastDataIdx).index = rootIdx;
}
unchecked {
uint32 size = length(self);
if (size == 0) Panic.panic(Panic.EMPTY_ARRAY_POP);

uint32 last = size - 1;

// get root location (in the data array) and value
Uint256HeapNode storage rootNode = _unsafeNodeAccess(self, 0);
uint32 rootIdx = rootNode.index;
Uint256HeapNode storage rootData = _unsafeNodeAccess(self, rootIdx);
Uint256HeapNode storage lastNode = _unsafeNodeAccess(self, last);
uint256 rootDataValue = rootData.value;

// if root is not the last element of the data array (that will get pop-ed), reorder the data array.
if (rootIdx != last) {
// get details about the value stored in the last element of the array (that will get pop-ed)
uint32 lastDataIdx = lastNode.lookup;
uint256 lastDataValue = lastNode.value;
// copy these values to the location of the root (that is safe, and that we no longer use)
rootData.value = lastDataValue;
rootData.lookup = lastDataIdx;
// update the tree node that used to point to that last element (value now located where the root was)
_unsafeNodeAccess(self, lastDataIdx).index = rootIdx;
}

// get last leaf location (in the data array) and value
uint32 lastIdx = lastNode.index;
uint256 lastValue = _unsafeNodeAccess(self, lastIdx).value;
// get last leaf location (in the data array) and value
uint32 lastIdx = lastNode.index;
uint256 lastValue = _unsafeNodeAccess(self, lastIdx).value;

// move the last leaf to the root, pop last leaf ...
rootNode.index = lastIdx;
_unsafeNodeAccess(self, lastIdx).lookup = 0;
self.data.pop();
// move the last leaf to the root, pop last leaf ...
rootNode.index = lastIdx;
_unsafeNodeAccess(self, lastIdx).lookup = 0;
self.data.pop();

// ... and heapify
_siftDown(self, last, 0, lastValue, comp);
// ... and heapify
_siftDown(self, last, 0, lastValue, comp);

// return root value
return rootDataValue;
// return root value
return rootDataValue;
}
}

/**
Expand All @@ -132,9 +134,8 @@ library Heap {
function(uint256, uint256) view returns (bool) comp
) internal {
uint32 size = length(self);
if (size == type(uint32).max) {
Panic.panic(Panic.RESOURCE_ERROR);
}
if (size == type(uint32).max) Panic.panic(Panic.RESOURCE_ERROR);

self.data.push(Uint256HeapNode({index: size, lookup: size, value: value}));
_siftUp(self, size, value, comp);
}
Expand Down Expand Up @@ -327,6 +328,7 @@ library Heap {
* @dev Lookup the root element of the heap.
*/
function peek(Uint208Heap storage self) internal view returns (uint208) {
// self.data[0] will `ARRAY_ACCESS_OUT_OF_BOUNDS` panic if heap is empty.
return _unsafeNodeAccess(self, self.data[0].index).value;
}

Expand All @@ -350,45 +352,46 @@ library Heap {
Uint208Heap storage self,
function(uint256, uint256) view returns (bool) comp
) internal returns (uint208) {
uint24 size = length(self);

if (size == 0) Panic.panic(Panic.EMPTY_ARRAY_POP);

uint24 last = size - 1; // could be unchecked (check above)

// get root location (in the data array) and value
Uint208HeapNode storage rootNode = _unsafeNodeAccess(self, 0);
uint24 rootIdx = rootNode.index;
Uint208HeapNode storage rootData = _unsafeNodeAccess(self, rootIdx);
Uint208HeapNode storage lastNode = _unsafeNodeAccess(self, last);
uint208 rootDataValue = rootData.value;

// if root is not the last element of the data array (that will get pop-ed), reorder the data array.
if (rootIdx != last) {
// get details about the value stored in the last element of the array (that will get pop-ed)
uint24 lastDataIdx = lastNode.lookup;
uint208 lastDataValue = lastNode.value;
// copy these values to the location of the root (that is safe, and that we no longer use)
rootData.value = lastDataValue;
rootData.lookup = lastDataIdx;
// update the tree node that used to point to that last element (value now located where the root was)
_unsafeNodeAccess(self, lastDataIdx).index = rootIdx;
}
unchecked {
uint24 size = length(self);
if (size == 0) Panic.panic(Panic.EMPTY_ARRAY_POP);

uint24 last = size - 1;

// get root location (in the data array) and value
Uint208HeapNode storage rootNode = _unsafeNodeAccess(self, 0);
uint24 rootIdx = rootNode.index;
Uint208HeapNode storage rootData = _unsafeNodeAccess(self, rootIdx);
Uint208HeapNode storage lastNode = _unsafeNodeAccess(self, last);
uint208 rootDataValue = rootData.value;

// if root is not the last element of the data array (that will get pop-ed), reorder the data array.
if (rootIdx != last) {
// get details about the value stored in the last element of the array (that will get pop-ed)
uint24 lastDataIdx = lastNode.lookup;
uint208 lastDataValue = lastNode.value;
// copy these values to the location of the root (that is safe, and that we no longer use)
rootData.value = lastDataValue;
rootData.lookup = lastDataIdx;
// update the tree node that used to point to that last element (value now located where the root was)
_unsafeNodeAccess(self, lastDataIdx).index = rootIdx;
}

// get last leaf location (in the data array) and value
uint24 lastIdx = lastNode.index;
uint208 lastValue = _unsafeNodeAccess(self, lastIdx).value;
// get last leaf location (in the data array) and value
uint24 lastIdx = lastNode.index;
uint208 lastValue = _unsafeNodeAccess(self, lastIdx).value;

// move the last leaf to the root, pop last leaf ...
rootNode.index = lastIdx;
_unsafeNodeAccess(self, lastIdx).lookup = 0;
self.data.pop();
// move the last leaf to the root, pop last leaf ...
rootNode.index = lastIdx;
_unsafeNodeAccess(self, lastIdx).lookup = 0;
self.data.pop();

// ... and heapify
_siftDown(self, last, 0, lastValue, comp);
// ... and heapify
_siftDown(self, last, 0, lastValue, comp);

// return root value
return rootDataValue;
// return root value
return rootDataValue;
}
}

/**
Expand All @@ -413,9 +416,8 @@ library Heap {
function(uint256, uint256) view returns (bool) comp
) internal {
uint24 size = length(self);
if (size == type(uint24).max) {
Panic.panic(Panic.RESOURCE_ERROR);
}
if (size == type(uint24).max) Panic.panic(Panic.RESOURCE_ERROR);

self.data.push(Uint208HeapNode({index: size, lookup: size, value: value}));
_siftUp(self, size, value, comp);
}
Expand Down
71 changes: 36 additions & 35 deletions scripts/generate/templates/Heap.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ struct ${node} {
* @dev Lookup the root element of the heap.
*/
function peek(${struct} storage self) internal view returns (${valueType}) {
// self.data[0] will \`ARRAY_ACCESS_OUT_OF_BOUNDS\` panic if heap is empty.
return _unsafeNodeAccess(self, self.data[0].index).value;
}
Expand All @@ -71,45 +72,46 @@ function pop(
${struct} storage self,
function(uint256, uint256) view returns (bool) comp
) internal returns (${valueType}) {
${indexType} size = length(self);
if (size == 0) Panic.panic(Panic.EMPTY_ARRAY_POP);
unchecked {
${indexType} size = length(self);
if (size == 0) Panic.panic(Panic.EMPTY_ARRAY_POP);
${indexType} last = size - 1; // could be unchecked (check above)
${indexType} last = size - 1;
// get root location (in the data array) and value
${node} storage rootNode = _unsafeNodeAccess(self, 0);
${indexType} rootIdx = rootNode.index;
${node} storage rootData = _unsafeNodeAccess(self, rootIdx);
${node} storage lastNode = _unsafeNodeAccess(self, last);
${valueType} rootDataValue = rootData.value;
// get root location (in the data array) and value
${node} storage rootNode = _unsafeNodeAccess(self, 0);
${indexType} rootIdx = rootNode.index;
${node} storage rootData = _unsafeNodeAccess(self, rootIdx);
${node} storage lastNode = _unsafeNodeAccess(self, last);
${valueType} rootDataValue = rootData.value;
// if root is not the last element of the data array (that will get pop-ed), reorder the data array.
if (rootIdx != last) {
// get details about the value stored in the last element of the array (that will get pop-ed)
${indexType} lastDataIdx = lastNode.lookup;
${valueType} lastDataValue = lastNode.value;
// copy these values to the location of the root (that is safe, and that we no longer use)
rootData.value = lastDataValue;
rootData.lookup = lastDataIdx;
// update the tree node that used to point to that last element (value now located where the root was)
_unsafeNodeAccess(self, lastDataIdx).index = rootIdx;
}
// if root is not the last element of the data array (that will get pop-ed), reorder the data array.
if (rootIdx != last) {
// get details about the value stored in the last element of the array (that will get pop-ed)
${indexType} lastDataIdx = lastNode.lookup;
${valueType} lastDataValue = lastNode.value;
// copy these values to the location of the root (that is safe, and that we no longer use)
rootData.value = lastDataValue;
rootData.lookup = lastDataIdx;
// update the tree node that used to point to that last element (value now located where the root was)
_unsafeNodeAccess(self, lastDataIdx).index = rootIdx;
}
// get last leaf location (in the data array) and value
${indexType} lastIdx = lastNode.index;
${valueType} lastValue = _unsafeNodeAccess(self, lastIdx).value;
// get last leaf location (in the data array) and value
${indexType} lastIdx = lastNode.index;
${valueType} lastValue = _unsafeNodeAccess(self, lastIdx).value;
// move the last leaf to the root, pop last leaf ...
rootNode.index = lastIdx;
_unsafeNodeAccess(self, lastIdx).lookup = 0;
self.data.pop();
// move the last leaf to the root, pop last leaf ...
rootNode.index = lastIdx;
_unsafeNodeAccess(self, lastIdx).lookup = 0;
self.data.pop();
// ... and heapify
_siftDown(self, last, 0, lastValue, comp);
// ... and heapify
_siftDown(self, last, 0, lastValue, comp);
// return root value
return rootDataValue;
// return root value
return rootDataValue;
}
}
/**
Expand All @@ -134,9 +136,8 @@ function insert(
function(uint256, uint256) view returns (bool) comp
) internal {
${indexType} size = length(self);
if (size == type(${indexType}).max) {
Panic.panic(Panic.RESOURCE_ERROR);
}
if (size == type(${indexType}).max) Panic.panic(Panic.RESOURCE_ERROR);
self.data.push(${struct}Node({index: size, lookup: size, value: value}));
_siftUp(self, size, value, comp);
}
Expand Down

0 comments on commit b2fda31

Please sign in to comment.