Skip to content

Commit 2e1d571

Browse files
committed
[BitCollections] Move shared utilities to _CollectionsUtilities
1 parent 49ea8cd commit 2e1d571

15 files changed

+227
-162
lines changed

Sources/BitCollections/BitArray/BitArray+Copy.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
//
1010
//===----------------------------------------------------------------------===//
1111

12+
import _CollectionsUtilities
13+
1214
extension BitArray {
1315
internal mutating func _copy(
1416
from range: Range<Int>,

Sources/BitCollections/BitArray/BitArray+CustomStringConvertible.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ extension BitArray: CustomStringConvertible {
2323
let b1: UInt8 = 49 // ASCII 1
2424
var i = 0
2525
for v in self {
26-
target._initialize(at: i, to: v ? b1 : b0)
26+
target.initializeElement(at: i, to: v ? b1 : b0)
2727
i &+= 1
2828
}
2929
return i

Sources/BitCollections/BitSet/BitSet+Initializers.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,16 +172,16 @@ extension BitSet {
172172
_storage = Array(unsafeUninitializedCapacity: capacity) { buffer, count in
173173
let sharedCount = Swift.min(w1.count, w2.count)
174174
for w in 0 ..< sharedCount {
175-
buffer._initialize(at: w, to: function(w1[w], w2[w]))
175+
buffer.initializeElement(at: w, to: function(w1[w], w2[w]))
176176
}
177177
if includingTail {
178178
if w1.count < w2.count {
179179
for w in w1.count ..< w2.count {
180-
buffer._initialize(at: w, to: function(_Word.empty, w2[w]))
180+
buffer.initializeElement(at: w, to: function(_Word.empty, w2[w]))
181181
}
182182
} else {
183183
for w in w2.count ..< w1.count {
184-
buffer._initialize(at: w, to: function(w1[w], _Word.empty))
184+
buffer.initializeElement(at: w, to: function(w1[w], _Word.empty))
185185
}
186186
}
187187
}

Sources/BitCollections/BitSet/BitSet._UnsafeHandle.swift

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
//
1010
//===----------------------------------------------------------------------===//
1111

12+
import _CollectionsUtilities
13+
1214
extension BitSet {
1315
/// An unsafe-unowned bitset view over `UInt` storage, providing bit set
1416
/// primitives.
@@ -273,7 +275,7 @@ extension BitSet._UnsafeHandle: BidirectionalCollection {
273275
internal var startIndex: Index {
274276
let word = _words.firstIndex { !$0.isEmpty }
275277
guard let word = word else { return endIndex }
276-
return Index(word: word, bit: _words[word].firstMember)
278+
return Index(word: word, bit: _words[word].firstMember!)
277279
}
278280

279281
@inlinable
@@ -299,7 +301,7 @@ extension BitSet._UnsafeHandle: BidirectionalCollection {
299301
}
300302
w = _words[word]
301303
}
302-
return Index(word: word, bit: w.firstMember)
304+
return Index(word: word, bit: w.firstMember!)
303305
}
304306

305307
@usableFromInline
@@ -318,7 +320,7 @@ extension BitSet._UnsafeHandle: BidirectionalCollection {
318320
precondition(word >= 0, "Can't advance below startIndex")
319321
w = _words[word]
320322
}
321-
return Index(word: word, bit: w.lastMember)
323+
return Index(word: word, bit: w.lastMember!)
322324
}
323325

324326
@usableFromInline
@@ -501,9 +503,7 @@ extension BitSet._UnsafeHandle {
501503
_mutableWords[l.word].formIntersection(_Word(upTo: l.bit).complement())
502504
if u.word < wordCount {
503505
_mutableWords[u.word].formIntersection(_Word(upTo: u.bit))
504-
_mutableWords[(u.word + 1)...]
505-
._rebased()
506-
.assign(repeating: .empty)
506+
_mutableWords[(u.word + 1)...].update(repeating: .empty)
507507
}
508508
}
509509

@@ -542,9 +542,7 @@ extension BitSet._UnsafeHandle {
542542
}
543543

544544
_mutableWords[l.word].subtract(_Word(upTo: l.bit).complement())
545-
_mutableWords[(l.word + 1) ..< u.word]
546-
._rebased()
547-
.assign(repeating: .empty)
545+
_mutableWords[(l.word + 1) ..< u.word].update(repeating: .empty)
548546
if u.word < wordCount {
549547
_mutableWords[u.word].subtract(_Word(upTo: u.bit))
550548
}

Sources/BitCollections/Shared/UInt+Tricks.swift

Lines changed: 8 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -9,36 +9,9 @@
99
//
1010
//===----------------------------------------------------------------------===//
1111

12-
extension UInt {
13-
@inlinable @inline(__always)
14-
internal var _nonzeroBitCount: UInt {
15-
Self(truncatingIfNeeded: nonzeroBitCount)
16-
}
17-
18-
internal var _reversed: UInt {
19-
// https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel
20-
var shift: UInt = UInt(UInt.bitWidth)
21-
var mask: UInt = ~0;
22-
var result = self
23-
while true {
24-
shift &>>= 1
25-
guard shift > 0 else { break }
26-
mask ^= mask &<< shift
27-
result = ((result &>> shift) & mask) | ((result &<< shift) & ~mask)
28-
}
29-
return result
30-
}
31-
32-
@inlinable @inline(__always)
33-
internal var _lastSetBit: UInt {
34-
UInt(truncatingIfNeeded: self.trailingZeroBitCount)
35-
}
36-
37-
@inlinable @inline(__always)
38-
internal var _firstSetBit: UInt {
39-
UInt(truncatingIfNeeded: UInt.bitWidth &- 1 &- self.leadingZeroBitCount)
40-
}
12+
import _CollectionsUtilities
4113

14+
extension UInt {
4215
/// Returns the position of the `n`th set bit in `self`.
4316
///
4417
/// - Parameter n: The to retrieve. This value is
@@ -48,52 +21,14 @@ extension UInt {
4821
/// - Returns: If this integer contains enough set bits to satisfy the
4922
/// request, then this function returns the position of the bit found.
5023
/// Otherwise it returns nil.
51-
internal func _nthSetBit(_ n: inout UInt) -> UInt? {
52-
// FIXME: Use bit deposit instruction when available (PDEP on Intel).
53-
assert(UInt.bitWidth == 64 || UInt.bitWidth == 32, "Unsupported UInt bitWidth")
54-
55-
var shift: UInt = 0
56-
57-
let c = self._nonzeroBitCount
24+
internal func _rank(ofBit n: inout UInt) -> UInt? {
25+
let c = self.nonzeroBitCount
5826
guard n < c else {
59-
n &-= c
27+
n &-= UInt(bitPattern: c)
6028
return nil
6129
}
62-
63-
if UInt.bitWidth == 64 {
64-
let c32 = (self & 0xFFFFFFFF)._nonzeroBitCount
65-
if n >= c32 {
66-
shift &+= 32
67-
n &-= c32
68-
}
69-
}
70-
let c16 = ((self &>> shift) & 0xFFFF)._nonzeroBitCount
71-
if n >= c16 {
72-
shift &+= 16
73-
n &-= c16
74-
}
75-
let c8 = ((self &>> shift) & 0xFF)._nonzeroBitCount
76-
if n >= c8 {
77-
shift &+= 8
78-
n &-= c8
79-
}
80-
let c4 = ((self &>> shift) & 0xF)._nonzeroBitCount
81-
if n >= c4 {
82-
shift &+= 4
83-
n &-= c4
84-
}
85-
let c2 = ((self &>> shift) & 0x3)._nonzeroBitCount
86-
if n >= c2 {
87-
shift &+= 2
88-
n &-= c2
89-
}
90-
let c1 = (self &>> shift) & 0x1
91-
if n >= c1 {
92-
shift &+= 1
93-
n &-= c1
94-
}
95-
precondition(n == 0 && (self &>> shift) & 0x1 == 1)
96-
return shift
30+
let m = Int(bitPattern: n)
31+
n = 0
32+
return _bit(ranked: m)!
9733
}
9834
}
99-

Sources/BitCollections/Shared/UnsafeMutableBufferPointer+Utilities.swift

Lines changed: 0 additions & 36 deletions
This file was deleted.

Sources/BitCollections/Shared/_Word.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
//
1010
//===----------------------------------------------------------------------===//
1111

12+
import _CollectionsUtilities
13+
1214
@usableFromInline
1315
@frozen
1416
internal struct _Word {
@@ -52,12 +54,12 @@ extension _Word {
5254
/// then this function returns the member found. Otherwise it returns nil.
5355
@inline(never)
5456
internal func nthElement(_ n: inout UInt) -> UInt? {
55-
value._nthSetBit(&n)
57+
value._rank(ofBit: &n)
5658
}
5759

5860
@inline(never)
5961
internal func nthElementFromEnd(_ n: inout UInt) -> UInt? {
60-
guard let i = value._reversed._nthSetBit(&n) else { return nil }
62+
guard let i = value._reversed._rank(ofBit: &n) else { return nil }
6163
return UInt(UInt.bitWidth) &- 1 &- i
6264
}
6365
}
@@ -102,13 +104,13 @@ extension _Word {
102104

103105
@inlinable
104106
@inline(__always)
105-
internal var firstMember: UInt {
107+
internal var firstMember: UInt? {
106108
value._lastSetBit
107109
}
108110

109111
@inlinable
110112
@inline(__always)
111-
internal var lastMember: UInt {
113+
internal var lastMember: UInt? {
112114
value._firstSetBit
113115
}
114116

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift Collections open source project
4+
//
5+
// Copyright (c) 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
//
10+
//===----------------------------------------------------------------------===//
11+
12+
extension FixedWidthInteger {
13+
/// Round up `self` to the nearest power of two, assuming it's representable.
14+
/// Returns 0 if `self` isn't positive.
15+
@inlinable
16+
public func _roundUpToPowerOfTwo() -> Self {
17+
guard self > 0 else { return 0 }
18+
let l = Self.bitWidth - (self &- 1).leadingZeroBitCount
19+
return 1 << l
20+
}
21+
}

0 commit comments

Comments
 (0)