@@ -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 {
@@ -359,6 +364,25 @@ where Base: RandomAccessCollection {
359
364
) ?? base. startIndex
360
365
return Index ( _baseRange: baseIdx..< i. baseRange. lowerBound)
361
366
}
367
+ }
368
+
369
+ extension ChunkedByCount {
370
+ @inlinable
371
+ public func distance( from start: Index , to end: Index ) -> Int {
372
+ let distance =
373
+ base. distance ( from: start. baseRange. lowerBound,
374
+ to: end. baseRange. lowerBound)
375
+ let ( quotient, remainder) =
376
+ distance. quotientAndRemainder ( dividingBy: chunkCount)
377
+ return quotient + remainder. signum ( )
378
+ }
379
+
380
+ @inlinable
381
+ public var count : Int {
382
+ let ( quotient, remainder) =
383
+ base. count. quotientAndRemainder ( dividingBy: chunkCount)
384
+ return quotient + remainder. signum ( )
385
+ }
362
386
363
387
@inlinable
364
388
public func index(
@@ -391,72 +415,51 @@ where Base: RandomAccessCollection {
391
415
392
416
@usableFromInline
393
417
internal func offsetForward( _ i: Index , offsetBy distance: Int ) -> Index {
418
+ assert ( distance > 0 )
394
419
return makeOffsetIndex (
395
- from: i, baseBound: base. endIndex, distance : distance
420
+ from: i, baseBound: base. endIndex, baseDistance : distance * chunkCount
396
421
)
397
422
}
398
423
399
424
@usableFromInline
400
425
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.
426
+ assert ( distance < 0 )
408
427
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
428
+ let remainder = base. count% chunkCount
429
+ // We have to take it into account when calculating offsets.
430
+ if remainder != 0 {
431
+ // Distance "minus" one(at this point distance is negative) because we
432
+ // need to adjust for the last position that have a variadic(remainder)
433
+ // number of elements.
434
+ let baseDistance = ( ( distance + 1 ) * chunkCount) - remainder
435
+ return makeOffsetIndex (
436
+ from: i, baseBound: base. startIndex, baseDistance: baseDistance
437
+ )
414
438
}
415
439
}
416
-
417
440
return makeOffsetIndex (
418
- from: idx , baseBound: base. startIndex, distance : distance
441
+ from: i , baseBound: base. startIndex, baseDistance : distance * chunkCount
419
442
)
420
443
}
421
444
422
445
// Helper to compute index(offsetBy:) index.
423
446
@inline ( __always)
424
447
private func makeOffsetIndex(
425
- from i: Index , baseBound: Base . Index , distance : Int
448
+ from i: Index , baseBound: Base . Index , baseDistance : Int
426
449
) -> Index {
427
450
let baseStartIdx = base. index (
428
- i. baseRange. lowerBound, offsetBy: distance * chunkCount ,
451
+ i. baseRange. lowerBound, offsetBy: baseDistance ,
429
452
limitedBy: baseBound
430
453
) ?? baseBound
431
454
432
455
let baseEndIdx = base. index (
433
- i. baseRange. lowerBound, offsetBy: ( distance + 1 ) * chunkCount,
434
- limitedBy: base. endIndex
456
+ baseStartIdx, offsetBy: chunkCount, limitedBy: base. endIndex
435
457
) ?? base. endIndex
436
458
437
459
return Index ( _baseRange: baseStartIdx..< baseEndIdx)
438
460
}
439
461
}
440
462
441
- extension ChunkedByCount {
442
- @inlinable
443
- public func distance( from start: Index , to end: Index ) -> Int {
444
- let distance =
445
- base. distance ( from: start. baseRange. lowerBound,
446
- to: end. baseRange. lowerBound)
447
- let ( quotient, remainder) =
448
- distance. quotientAndRemainder ( dividingBy: chunkCount)
449
- return quotient + remainder. signum ( )
450
- }
451
-
452
- @inlinable
453
- public var count : Int {
454
- let ( quotient, remainder) =
455
- base. count. quotientAndRemainder ( dividingBy: chunkCount)
456
- return quotient + remainder. signum ( )
457
- }
458
- }
459
-
460
463
extension Collection {
461
464
/// Returns a `ChunkedCollection<Self>` view presenting the elements
462
465
/// in chunks with count of the given count parameter.
0 commit comments