@@ -271,7 +271,7 @@ public struct ChunkedByCount<Base: Collection> {
271
271
internal let chunkCount : Int
272
272
273
273
@usableFromInline
274
- internal var computedStartIndex : Index
274
+ internal var computedStartEnd : Base . Index
275
275
276
276
/// Creates a view instance that presents the elements of `base`
277
277
/// in `SubSequence` chunks of the given count.
@@ -284,13 +284,10 @@ public struct ChunkedByCount<Base: Collection> {
284
284
285
285
// Compute the start index upfront in order to make
286
286
// start index a O(1) lookup.
287
- let baseEnd = _base. index (
287
+ self . computedStartEnd = _base. index (
288
288
_base. startIndex, offsetBy: _chunkCount,
289
289
limitedBy: _base. endIndex
290
290
) ?? _base. endIndex
291
-
292
- self . computedStartIndex =
293
- Index ( _baseRange: _base. startIndex..< baseEnd)
294
291
}
295
292
}
296
293
@@ -307,7 +304,9 @@ extension ChunkedByCount: Collection {
307
304
308
305
/// - Complexity: O(1)
309
306
@inlinable
310
- public var startIndex : Index { computedStartIndex }
307
+ public var startIndex : Index {
308
+ Index ( _baseRange: base. startIndex..< computedStartEnd)
309
+ }
311
310
@inlinable
312
311
public var endIndex : Index {
313
312
Index ( _baseRange: base. endIndex..< base. endIndex)
@@ -331,6 +330,12 @@ extension ChunkedByCount: Collection {
331
330
}
332
331
333
332
extension ChunkedByCount . Index : Comparable {
333
+ @inlinable
334
+ public static func == ( lhs: ChunkedByCount . Index ,
335
+ rhs: ChunkedByCount . Index ) -> Bool {
336
+ lhs. baseRange. lowerBound == rhs. baseRange. lowerBound
337
+ }
338
+
334
339
@inlinable
335
340
public static func < ( lhs: ChunkedByCount . Index ,
336
341
rhs: ChunkedByCount . Index ) -> Bool {
@@ -391,47 +396,46 @@ where Base: RandomAccessCollection {
391
396
392
397
@usableFromInline
393
398
internal func offsetForward( _ i: Index , offsetBy distance: Int ) -> Index {
399
+ assert ( distance > 0 )
394
400
return makeOffsetIndex (
395
- from: i, baseBound: base. endIndex, distance : distance
401
+ from: i, baseBound: base. endIndex, baseDistance : distance * chunkCount
396
402
)
397
403
}
398
404
399
405
@usableFromInline
400
406
internal func offsetBackward( _ i: Index , offsetBy distance: Int ) -> Index {
401
- var idx = i
402
- var distance = distance
403
- // If we know that the last chunk is the only one that can possible
404
- // have a variadic count. So in order to simplify and avoid another
405
- // calculation of offsets(that is already done at `index(before:)`)
406
- // we just move one position already so the index can be calculated
407
- // since all remaining chunks have the same size.
407
+ assert ( distance < 0 )
408
+ // Distance "minus" one(at this point distance is negative) because we
409
+ // need to adjust for the last position that may have variadic(remainder)
410
+ // number of elements.
411
+ var baseDistance = ( distance + 1 ) * chunkCount
408
412
if i. baseRange. lowerBound == base. endIndex {
409
- formIndex ( before: & idx)
410
- distance += 1
411
- // If the offset was simply one, we are done.
412
- guard distance != 0 else {
413
- return idx
413
+ let remainder = base. count% chunkCount
414
+ // We have to take it into account when calculating offsets.
415
+ if remainder != 0 {
416
+ baseDistance -= remainder
417
+ return makeOffsetIndex (
418
+ from: i, baseBound: base. startIndex, baseDistance: baseDistance
419
+ )
414
420
}
415
421
}
416
-
417
422
return makeOffsetIndex (
418
- from: idx , baseBound: base. startIndex, distance : distance
423
+ from: i , baseBound: base. startIndex, baseDistance : baseDistance - chunkCount
419
424
)
420
425
}
421
426
422
427
// Helper to compute index(offsetBy:) index.
423
428
@inline ( __always)
424
429
private func makeOffsetIndex(
425
- from i: Index , baseBound: Base . Index , distance : Int
430
+ from i: Index , baseBound: Base . Index , baseDistance : Int
426
431
) -> Index {
427
432
let baseStartIdx = base. index (
428
- i. baseRange. lowerBound, offsetBy: distance * chunkCount ,
433
+ i. baseRange. lowerBound, offsetBy: baseDistance ,
429
434
limitedBy: baseBound
430
435
) ?? baseBound
431
436
432
437
let baseEndIdx = base. index (
433
- i. baseRange. lowerBound, offsetBy: ( distance + 1 ) * chunkCount,
434
- limitedBy: base. endIndex
438
+ baseStartIdx, offsetBy: chunkCount, limitedBy: base. endIndex
435
439
) ?? base. endIndex
436
440
437
441
return Index ( _baseRange: baseStartIdx..< baseEndIdx)
0 commit comments