// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; import './BitMath.sol'; library TickBitmap { function position(int24 tick) private pure returns (int16 wordPos, uint8 bitPos) { wordPos = int16(tick >> 8); bitPos = uint8(tick % 256); } function flipTick( mapping(int16 => uint256) storage self, int24 tick, int24 tickSpacing ) internal { require(tick % tickSpacing == 0); // ensure that the tick is spaced (int16 wordPos, uint8 bitPos) = position(tick / tickSpacing); uint256 mask = 1 << bitPos; self[wordPos] ^= mask; } function nextInitializedTickWithinOneWord( mapping(int16 => uint256) storage self, int24 tick, int24 tickSpacing, bool lte ) internal view returns (int24 next, bool initialized) { int24 compressed = tick / tickSpacing; if (tick < 0 && tick % tickSpacing != 0) compressed--; // round towards negative infinity if (lte) { (int16 wordPos, uint8 bitPos) = position(compressed); // all the 1s at or to the right of the current bitPos uint256 mask = (1 << bitPos) - 1 + (1 << bitPos); uint256 masked = self[wordPos] & mask; // if there are no initialized ticks to the right of or at the current tick, return rightmost in the word initialized = masked != 0; // overflow/underflow is possible, but prevented externally by limiting both tickSpacing and tick next = initialized ? (compressed - int24(bitPos - BitMath.mostSignificantBit(masked))) * tickSpacing : (compressed - int24(bitPos)) * tickSpacing; } else { // start from the word of the next tick, since the current tick state doesn't matter (int16 wordPos, uint8 bitPos) = position(compressed + 1); // all the 1s at or to the left of the bitPos uint256 mask = ~((1 << bitPos) - 1); uint256 masked = self[wordPos] & mask; // if there are no initialized ticks to the left of the current tick, return leftmost in the word initialized = masked != 0; // overflow/underflow is possible, but prevented externally by limiting both tickSpacing and tick next = initialized ? (compressed + 1 + int24(BitMath.leastSignificantBit(masked) - bitPos)) * tickSpacing : (compressed + 1 + int24(type(uint8).max - bitPos)) * tickSpacing; } } }