// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title Contract to be inherited by contracts that will sort an array using /// an unrolled implementation /// @notice The operation will be in-place, i.e., the array provided as the /// argument will be modified. contract Sort { uint256 internal constant MAX_SORT_LENGTH = 9; /// @notice Sorts the array /// @param array Array to be sorted function sort(int256[] memory array) internal pure { uint256 arrayLength = array.length; require(arrayLength <= MAX_SORT_LENGTH, "Array too long to sort"); // Do a binary search if (arrayLength < 6) { // Possible lengths: 1, 2, 3, 4, 5 if (arrayLength < 4) { // Possible lengths: 1, 2, 3 if (arrayLength == 3) { // Length: 3 swapIfFirstIsLarger(array, 0, 1); swapIfFirstIsLarger(array, 1, 2); swapIfFirstIsLarger(array, 0, 1); } else if (arrayLength == 2) { // Length: 2 swapIfFirstIsLarger(array, 0, 1); } // Do nothing for Length: 1 } else { // Possible lengths: 4, 5 if (arrayLength == 5) { // Length: 5 swapIfFirstIsLarger(array, 1, 2); swapIfFirstIsLarger(array, 3, 4); swapIfFirstIsLarger(array, 1, 3); swapIfFirstIsLarger(array, 0, 2); swapIfFirstIsLarger(array, 2, 4); swapIfFirstIsLarger(array, 0, 3); swapIfFirstIsLarger(array, 0, 1); swapIfFirstIsLarger(array, 2, 3); swapIfFirstIsLarger(array, 1, 2); } else { // Length: 4 swapIfFirstIsLarger(array, 0, 1); swapIfFirstIsLarger(array, 2, 3); swapIfFirstIsLarger(array, 1, 3); swapIfFirstIsLarger(array, 0, 2); swapIfFirstIsLarger(array, 1, 2); } } } else { // Possible lengths: 6, 7, 8, 9 if (arrayLength < 8) { // Possible lengths: 6, 7 if (arrayLength == 7) { // Length: 7 swapIfFirstIsLarger(array, 1, 2); swapIfFirstIsLarger(array, 3, 4); swapIfFirstIsLarger(array, 5, 6); swapIfFirstIsLarger(array, 0, 2); swapIfFirstIsLarger(array, 4, 6); swapIfFirstIsLarger(array, 3, 5); swapIfFirstIsLarger(array, 2, 6); swapIfFirstIsLarger(array, 1, 5); swapIfFirstIsLarger(array, 0, 4); swapIfFirstIsLarger(array, 2, 5); swapIfFirstIsLarger(array, 0, 3); swapIfFirstIsLarger(array, 2, 4); swapIfFirstIsLarger(array, 1, 3); swapIfFirstIsLarger(array, 0, 1); swapIfFirstIsLarger(array, 2, 3); swapIfFirstIsLarger(array, 4, 5); } else { // Length: 6 swapIfFirstIsLarger(array, 0, 1); swapIfFirstIsLarger(array, 2, 3); swapIfFirstIsLarger(array, 4, 5); swapIfFirstIsLarger(array, 1, 3); swapIfFirstIsLarger(array, 3, 5); swapIfFirstIsLarger(array, 1, 3); swapIfFirstIsLarger(array, 2, 4); swapIfFirstIsLarger(array, 0, 2); swapIfFirstIsLarger(array, 2, 4); swapIfFirstIsLarger(array, 3, 4); swapIfFirstIsLarger(array, 1, 2); swapIfFirstIsLarger(array, 2, 3); } } else { // Possible lengths: 8, 9 if (arrayLength == 9) { // Length: 9 swapIfFirstIsLarger(array, 1, 8); swapIfFirstIsLarger(array, 2, 7); swapIfFirstIsLarger(array, 3, 6); swapIfFirstIsLarger(array, 4, 5); swapIfFirstIsLarger(array, 1, 4); swapIfFirstIsLarger(array, 5, 8); swapIfFirstIsLarger(array, 0, 2); swapIfFirstIsLarger(array, 6, 7); swapIfFirstIsLarger(array, 2, 6); swapIfFirstIsLarger(array, 7, 8); swapIfFirstIsLarger(array, 0, 3); swapIfFirstIsLarger(array, 4, 5); swapIfFirstIsLarger(array, 0, 1); swapIfFirstIsLarger(array, 3, 5); swapIfFirstIsLarger(array, 6, 7); swapIfFirstIsLarger(array, 2, 4); swapIfFirstIsLarger(array, 1, 3); swapIfFirstIsLarger(array, 5, 7); swapIfFirstIsLarger(array, 4, 6); swapIfFirstIsLarger(array, 1, 2); swapIfFirstIsLarger(array, 3, 4); swapIfFirstIsLarger(array, 5, 6); swapIfFirstIsLarger(array, 7, 8); swapIfFirstIsLarger(array, 2, 3); swapIfFirstIsLarger(array, 4, 5); } else { // Length: 8 swapIfFirstIsLarger(array, 0, 7); swapIfFirstIsLarger(array, 1, 6); swapIfFirstIsLarger(array, 2, 5); swapIfFirstIsLarger(array, 3, 4); swapIfFirstIsLarger(array, 0, 3); swapIfFirstIsLarger(array, 4, 7); swapIfFirstIsLarger(array, 1, 2); swapIfFirstIsLarger(array, 5, 6); swapIfFirstIsLarger(array, 0, 1); swapIfFirstIsLarger(array, 2, 3); swapIfFirstIsLarger(array, 4, 5); swapIfFirstIsLarger(array, 6, 7); swapIfFirstIsLarger(array, 3, 5); swapIfFirstIsLarger(array, 2, 4); swapIfFirstIsLarger(array, 1, 2); swapIfFirstIsLarger(array, 3, 4); swapIfFirstIsLarger(array, 5, 6); swapIfFirstIsLarger(array, 2, 3); swapIfFirstIsLarger(array, 4, 5); swapIfFirstIsLarger(array, 3, 4); } } } } /// @notice Swaps two elements of an array if the first element is greater /// than the second /// @param array Array whose elements are to be swapped /// @param ind1 Index of the first element /// @param ind2 Index of the second element function swapIfFirstIsLarger( int256[] memory array, uint256 ind1, uint256 ind2 ) private pure { if (array[ind1] > array[ind2]) { (array[ind1], array[ind2]) = (array[ind2], array[ind1]); } } }