Skip to content

Commit

Permalink
Merge pull request #244 from lorentey/unify-unsafe-bitsets
Browse files Browse the repository at this point in the history
Unify unsafe bit set implementations
  • Loading branch information
lorentey authored Nov 29, 2022
2 parents d1f1ab0 + a2f4b18 commit 8cc18a2
Show file tree
Hide file tree
Showing 29 changed files with 942 additions and 1,380 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
//
//===----------------------------------------------------------------------===//

import _CollectionsUtilities

internal struct _ChunkedBitsForwardIterator {
internal typealias _BitPosition = _UnsafeBitSet.Index

internal let words: UnsafeBufferPointer<_Word>
internal let end: _BitPosition
internal var position: _BitPosition
Expand Down Expand Up @@ -43,6 +47,8 @@ internal struct _ChunkedBitsForwardIterator {
}

internal struct _ChunkedBitsBackwardIterator {
internal typealias _BitPosition = _UnsafeBitSet.Index

internal let words: UnsafeBufferPointer<_Word>
internal let start: _BitPosition
internal var position: _BitPosition
Expand Down
5 changes: 5 additions & 0 deletions Sources/BitCollections/BitArray/BitArray._UnsafeHandle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,17 @@
//
//===----------------------------------------------------------------------===//

import _CollectionsUtilities

extension BitArray {
/// An unsafe-unowned bitarray view over `UInt` storage, providing bit array
/// primitives.
@usableFromInline
@frozen
internal struct _UnsafeHandle {
@usableFromInline
internal typealias _BitPosition = _UnsafeBitSet.Index

@usableFromInline
internal let _words: UnsafeBufferPointer<_Word>

Expand Down
5 changes: 5 additions & 0 deletions Sources/BitCollections/BitArray/BitArray.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
//
//===----------------------------------------------------------------------===//

import _CollectionsUtilities

/// An ordered, random-access collection of `Bool` values, implemented as an
/// uncompressed bitmap of as many bits as the count of the array.
///
Expand All @@ -19,6 +21,9 @@
/// structure, treating it as a set of nonnegative integers corresponding to
/// `true` bits.
public struct BitArray {
@usableFromInline
internal typealias _BitPosition = _UnsafeBitSet.Index

@usableFromInline
internal var _storage: [_Word]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ extension BitSet: Collection, BidirectionalCollection {
/// storage.)
public func index(after index: Index) -> Index {
_read { handle in
assert(handle.isReachable(index._position), "Invalid index")
assert(handle._isReachable(index._position), "Invalid index")
let pos = handle.index(after: index._position)
return Index(_position: pos)
}
Expand All @@ -178,7 +178,7 @@ extension BitSet: Collection, BidirectionalCollection {
/// storage.)
public func index(before index: Index) -> Index {
_read { handle in
assert(handle.isReachable(index._position), "Invalid index")
assert(handle._isReachable(index._position), "Invalid index")
let pos = handle.index(before: index._position)
return Index(_position: pos)
}
Expand All @@ -196,8 +196,8 @@ extension BitSet: Collection, BidirectionalCollection {
/// addressed by the two input indices.
public func distance(from start: Index, to end: Index) -> Int {
_read { handle in
assert(handle.isReachable(start._position), "Invalid start index")
assert(handle.isReachable(end._position), "Invalid end index")
assert(handle._isReachable(start._position), "Invalid start index")
assert(handle._isReachable(end._position), "Invalid end index")
return handle.distance(from: start._position, to: end._position)
}
}
Expand All @@ -220,7 +220,7 @@ extension BitSet: Collection, BidirectionalCollection {
/// addressed by `index` and the returned result.
public func index(_ index: Index, offsetBy distance: Int) -> Index {
_read { handle in
assert(handle.isReachable(index._position), "Invalid index")
assert(handle._isReachable(index._position), "Invalid index")
let pos = handle.index(index._position, offsetBy: distance)
return Index(_position: pos)
}
Expand Down Expand Up @@ -250,8 +250,8 @@ extension BitSet: Collection, BidirectionalCollection {
_ i: Index, offsetBy distance: Int, limitedBy limit: Index
) -> Index? {
_read { handle in
assert(handle.isReachable(i._position), "Invalid index")
assert(handle.isReachable(limit._position), "Invalid limit index")
assert(handle._isReachable(i._position), "Invalid index")
assert(handle._isReachable(limit._position), "Invalid limit index")
return handle.index(
i._position, offsetBy: distance, limitedBy: limit._position
).map { Index(_position: $0) }
Expand Down
4 changes: 2 additions & 2 deletions Sources/BitCollections/BitSet/BitSet+Extras.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,15 @@ extension BitSet {
public subscript(members bounds: Range<Int>) -> Slice<BitSet> {
let bounds: Range<Index> = _read { handle in
let bounds = bounds._clampedToUInt()
var lower = _BitPosition(bounds.lowerBound)
var lower = _UnsafeBitSet.Index(bounds.lowerBound)
if lower >= handle.endIndex {
lower = handle.endIndex
} else if !handle.contains(lower.value) {
lower = handle.index(after: lower)
}
assert(lower == handle.endIndex || handle.contains(lower.value))

var upper = _BitPosition(bounds.upperBound)
var upper = _UnsafeBitSet.Index(bounds.upperBound)
if upper <= lower {
upper = lower
} else if upper >= handle.endIndex {
Expand Down
2 changes: 1 addition & 1 deletion Sources/BitCollections/BitSet/BitSet+Random.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ extension BitSet {
) -> BitSet {
precondition(limit >= 0, "Invalid limit value")
guard limit > 0 else { return BitSet() }
let (w, b) = _BitPosition(limit).endSplit
let (w, b) = _UnsafeHandle.Index(limit).endSplit
var words = (0 ... w).map { _ in _Word(rng.next() as UInt) }
words[w].formIntersection(_Word(upTo: b))
return BitSet(_words: words)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ extension BitSet {
}

let selfCount = self.count
return _UnsafeHandle.withTemporaryBitset(
return _UnsafeHandle.withTemporaryBitSet(
wordCount: _storage.count
) { seen in
var strict = false
Expand All @@ -141,7 +141,7 @@ extension BitSet {
continue
}
if seen.insert(UInt(i)) {
c += 1
c &+= 1
if c == selfCount {
while !strict, let i = it.next() {
strict = !self.contains(i)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,12 @@ extension BitSet {
if S.self == Range<Int>.self {
return isStrictSuperset(of: other as! Range<Int>)
}
return _UnsafeHandle.withTemporaryBitset(
return _UnsafeHandle.withTemporaryBitSet(
wordCount: _storage.count
) { seen in
var c = 0
for i in other {
guard contains(i) else { return false }
if seen.insert(UInt(i)) { c += 1 }
seen.insert(UInt(i))
}
return !_storage.elementsEqual(seen._words)
}
Expand Down
Loading

0 comments on commit 8cc18a2

Please sign in to comment.