File: BitArray%2BChunkedBitsIterators.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (100 lines) | stat: -rw-r--r-- 2,894 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift Collections open source project
//
// Copyright (c) 2021 - 2024 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
//
//===----------------------------------------------------------------------===//

#if !COLLECTIONS_SINGLE_MODULE
import InternalCollectionsUtilities
#endif

internal struct _ChunkedBitsForwardIterator {
  internal typealias _BitPosition = _UnsafeBitSet.Index

  internal let words: UnsafeBufferPointer<_Word>
  internal let end: _BitPosition
  internal var position: _BitPosition
  
  internal init(
    words: UnsafeBufferPointer<_Word>,
    range: Range<Int>
  ) {
    assert(range.lowerBound >= 0)
    assert(range.upperBound <= words.count * _Word.capacity)
    self.words = words
    self.end = _BitPosition(range.upperBound)
    self.position = _BitPosition(range.lowerBound)
  }
  
  mutating func next() -> (bits: _Word, count: UInt)? {
    guard position < end else { return nil }
    let (w, b) = position.split
    if w == end.word {
      position = end
      return (
        bits: words[w]
          .intersection(_Word(upTo: end.bit))
          .shiftedDown(by: b),
        count: end.bit - b)
    }
    let c = UInt(_Word.capacity) - b
    position.value += c
    return (bits: words[w].shiftedDown(by: b), count: c)
  }
}

internal struct _ChunkedBitsBackwardIterator {
  internal typealias _BitPosition = _UnsafeBitSet.Index

  internal let words: UnsafeBufferPointer<_Word>
  internal let start: _BitPosition
  internal var position: _BitPosition
  
  internal init(
    words: UnsafeBufferPointer<_Word>,
    range: Range<Int>
  ) {
    assert(range.lowerBound >= 0)
    assert(range.upperBound <= words.count * _Word.capacity)
    self.words = words
    self.start = _BitPosition(range.lowerBound)
    self.position = _BitPosition(range.upperBound)
  }
  
  internal mutating func next() -> (bits: _Word, count: UInt)? {
    guard position > start else { return nil }
    let (w, b) = position.endSplit
    if w == start.word {
      position = start
      return (
        bits: words[w]
          .intersection(_Word(upTo: b))
          .shiftedDown(by: start.bit),
        count: b - start.bit)
    }
    let c = b
    position.value -= c
    return (bits: words[w].intersection(_Word(upTo: b)), count: c)
  }
}

extension IteratorProtocol where Element == Bool {
  mutating func _nextChunk(
    maximumCount: UInt = UInt(_Word.capacity)
  ) -> (bits: _Word, count: UInt) {
    assert(maximumCount <= _Word.capacity)
    var bits = _Word.empty
    var c: UInt = 0
    while let v = next() {
      if v { bits.insert(c) }
      c += 1
      if c == maximumCount { break }
    }
    return (bits, c)
  }
}