@@ -129,29 +129,27 @@ library PositionStatus {
129129 }
130130
131131 /**
132- * @dev Returns the next reserveId that is borrowing or using as collateral.
133- * @dev Returns NOT_FOUND if no such reserveId exists, starts searching from `startReserveId`.
134- * @dev Does not disregard potential dirty bits set after `reserveCount` in it's bucket.
132+ * @dev Finds the previous borrowing or collateralized reserve strictly before `fromReserveId`.
133+ * @dev The search starts at `fromReserveId` (exclusive) and scans backward across buckets.
134+ * @dev Returns `NOT_FOUND` if no borrowing or collateralized reserve exists before the bound.
135+ * @dev Ignores dirty bits beyond the configured `reserveCount` within the current bucket.
135136 * @param self The configuration object.
136- * @param startReserveId The reserveId to start searching from.
137- * @param reserveCount The current reserveCount, to avoid reading uninitialized buckets.
137+ * @param fromReserveId The reserveId to start searching from.
138138 * @return reserveId The next reserveId that is borrowing or using as collateral.
139139 * @return borrowing True if the next reserveId is borrowing, false otherwise.
140140 * @return collateral True if the next reserveId is using as collateral, false otherwise.
141141 */
142142 function next (
143143 DataTypes.PositionStatus storage self ,
144- uint256 startReserveId ,
145- uint256 reserveCount
144+ uint256 fromReserveId
146145 ) internal view returns (uint256 , bool , bool ) {
147146 unchecked {
148- uint256 endBucket = reserveCount.bucketId ();
149- uint256 bucket = startReserveId.bucketId ();
147+ uint256 bucket = fromReserveId.bucketId ();
150148 uint256 map = self.map[bucket];
151- uint256 setBitId = map.isolateFrom (startReserveId). ffs ();
152- while (setBitId == 256 && bucket != endBucket ) {
153- map = self.map[++ bucket];
154- setBitId = map.ffs ();
149+ uint256 setBitId = map.isolateUntil (fromReserveId). fls ();
150+ while (setBitId == 256 && bucket != 0 ) {
151+ map = self.map[-- bucket];
152+ setBitId = map.fls ();
155153 }
156154 if (setBitId == 256 ) {
157155 return (NOT_FOUND, false , false );
@@ -163,50 +161,46 @@ library PositionStatus {
163161 }
164162
165163 /**
166- * @dev Returns the next reserveId that is borrowing .
167- * @dev Returns NOT_FOUND if no such reserveId exists, starts searching from `startReserveId` .
168- * @dev Does not disregard potential dirty bits set after `reserveCount` in it's bucket .
169- * @param self The configuration object .
170- * @param startReserveId The reserveId to start searching from .
171- * @param reserveCount The current reserveCount, to avoid reading uninitialized buckets .
172- * @return reserveId The next reserveId that is borrowing .
164+ * @dev Finds the previous borrowing reserve strictly before `fromReserveId` .
165+ * @dev The search starts at `fromReserveId` (exclusive) and scans backward across buckets .
166+ * @dev Returns `NOT_FOUND` if no borrowing reserve exists before the bound .
167+ * @dev Ignores dirty bits beyond the configured `reserveCount` within the current bucket .
168+ * @param self The position status storing reserves bitmap .
169+ * @param fromReserveId The exclusive upper bound to start from (this reserveId is not considered) .
170+ * @return reserveId The previous borrowing reserveId, or `NOT_FOUND` if none is found .
173171 */
174172 function nextBorrowing (
175173 DataTypes.PositionStatus storage self ,
176- uint256 startReserveId ,
177- uint256 reserveCount
174+ uint256 fromReserveId
178175 ) internal view returns (uint256 reserveId ) {
179176 unchecked {
180- uint256 endBucket = reserveCount.bucketId ();
181- uint256 bucket = startReserveId.bucketId ();
182- uint256 setBitId = self.map[bucket].isolateBorrowingFrom (startReserveId).ffs ();
183- while (setBitId == 256 && bucket != endBucket) {
184- setBitId = self.map[++ bucket].isolateBorrowing ().ffs ();
177+ uint256 bucket = fromReserveId.bucketId ();
178+ uint256 setBitId = self.map[bucket].isolateBorrowingUntil (fromReserveId).fls ();
179+ while (setBitId == 256 && bucket != 0 ) {
180+ setBitId = self.map[-- bucket].isolateBorrowing ().fls ();
185181 }
186182 return setBitId == 256 ? NOT_FOUND : setBitId.fromBitId (bucket);
187183 }
188184 }
189185
190186 /**
191- * @dev Returns the next reserveId that is using as collateral .
192- * @dev Returns NOT_FOUND if no such reserveId exists, starts searching from `startReserveId` .
193- * @dev Does not disregard potential dirty bits set after `reserveCount` in it's bucket .
194- * @param self The configuration object .
195- * @param startReserveId The reserveId to start searching from .
196- * @param reserveCount The current reserveCount, to avoid reading uninitialized buckets .
197- * @return reserveId The next reserveId that is using as collateral .
187+ * @dev Finds the previous collateralized reserve strictly before `fromReserveId` .
188+ * @dev The search starts at `fromReserveId` (exclusive) and scans backward across buckets .
189+ * @dev Returns `NOT_FOUND` if no collateralized reserve exists before the bound .
190+ * @dev Ignores dirty bits beyond the configured `reserveCount` within the current bucket .
191+ * @param self The position status storing reserves bitmap .
192+ * @param fromReserveId The exclusive upper bound to start from (this reserveId is not considered) .
193+ * @return reserveId The previous collateralized reserveId, or `NOT_FOUND` if none is found .
198194 */
199195 function nextCollateral (
200196 DataTypes.PositionStatus storage self ,
201- uint256 startReserveId ,
202- uint256 reserveCount
197+ uint256 fromReserveId
203198 ) internal view returns (uint256 reserveId ) {
204199 unchecked {
205- uint256 endBucket = reserveCount.bucketId ();
206- uint256 bucket = startReserveId.bucketId ();
207- uint256 setBitId = self.map[bucket].isolateCollateralFrom (startReserveId).ffs ();
208- while (setBitId == 256 && bucket != endBucket) {
209- setBitId = self.map[++ bucket].isolateCollateral ().ffs ();
200+ uint256 bucket = fromReserveId.bucketId ();
201+ uint256 setBitId = self.map[bucket].isolateCollateralUntil (fromReserveId).fls ();
202+ while (setBitId == 256 && bucket != 0 ) {
203+ setBitId = self.map[-- bucket].isolateCollateral ().fls ();
210204 }
211205 return setBitId == 256 ? NOT_FOUND : setBitId.fromBitId (bucket);
212206 }
@@ -253,25 +247,31 @@ library PositionStatus {
253247 }
254248
255249 /**
256- * @dev Isolates the borrowing bits from word, disregarding bits before `reserveId`.
250+ * @dev Isolates borrowing bits up to the given `reserveCount`, clearing all later reserves.
251+ * @param word The 256-bit value encoding reserves configuration.
252+ * @param reserveCount The number of reserves (2 bits each) to include.
253+ * @return ret The portion of word containing borrowing bits from the first reserve up to `reserveCount`.
257254 */
258- function isolateBorrowingFrom (
255+ function isolateBorrowingUntil (
259256 uint256 word ,
260- uint256 reserveId
257+ uint256 reserveCount
261258 ) internal pure returns (uint256 ret ) {
262- // ret = word & (BORROWING_MASK << ((reserveId % 128) << 1));
259+ // ret = word & (BORROWING_MASK >> (256 - ((reserveCount % 128) << 1) ));
263260 assembly ('memory-safe ' ) {
264- ret := and (word, shl ( shl (1 , mod (reserveId , 128 )), BORROWING_MASK))
261+ ret := and (word, shr ( sub ( 256 , shl (1 , mod (reserveCount , 128 ) )), BORROWING_MASK))
265262 }
266263 }
267264
268265 /**
269- * @dev Isolates the bits from word, disregarding bits before `reserveId`.
266+ * @dev Isolates bits up to the given `reserveCount`, clearing all later reserves.
267+ * @param word The 256-bit value encoding reserves configuration.
268+ * @param reserveCount The number of reserves (2 bits each) to include.
269+ * @return ret The portion of word containing bits from the first reserve up to `reserveCount`.
270270 */
271- function isolateFrom (uint256 word , uint256 reserveId ) internal pure returns (uint256 ret ) {
272- // ret = word & (type(uint256).max << ((reserveId % 128) << 1));
271+ function isolateUntil (uint256 word , uint256 reserveCount ) internal pure returns (uint256 ret ) {
272+ // ret = word & (type(uint256).max >> (256 - ((reserveCount % 128) << 1) ));
273273 assembly ('memory-safe ' ) {
274- ret := and (word, shl ( shl (1 , mod (reserveId , 128 )), not (0 )))
274+ ret := and (word, shr ( sub ( 256 , shl (1 , mod (reserveCount , 128 ) )), not (0 )))
275275 }
276276 }
277277
@@ -285,20 +285,10 @@ library PositionStatus {
285285 }
286286
287287 /**
288- * @dev Isolates the bits from word, disregarding bits before `reserveId`.
289- */
290- function isolateCollateralFrom (
291- uint256 word ,
292- uint256 reserveId
293- ) internal pure returns (uint256 ret ) {
294- // ret = word & (COLLATERAL_MASK << ((reserveId % 128) << 1));
295- assembly ('memory-safe ' ) {
296- ret := and (word, shl (shl (1 , mod (reserveId, 128 )), COLLATERAL_MASK))
297- }
298- }
299-
300- /**
301- * @dev Isolates the bits from word, disregarding bits after `reserveCount`.
288+ * @dev Isolates collateral bits up to the given `reserveCount`, clearing all later reserves.
289+ * @param word The 256-bit value encoding reserves configuration.
290+ * @param reserveCount The number of reserves (2 bits each) to include.
291+ * @return ret The portion of word containing collateral bits from the first reserve up to `reserveCount`.
302292 */
303293 function isolateCollateralUntil (
304294 uint256 word ,
0 commit comments