1
1
/*
2
- A fixed-size sequence of n bits. Bits have indices 0 to n-1.
3
- */
2
+ A fixed-size sequence of n bits. Bits have indices 0 to n-1.
3
+ */
4
4
public struct BitSet {
5
5
/* How many bits this object can hold. */
6
6
private( set) public var size : Int
7
-
7
+
8
8
/*
9
- We store the bits in a list of unsigned 64-bit integers.
10
- The first entry, `words[0]`, is the least significant word.
11
- */
9
+ We store the bits in a list of unsigned 64-bit integers.
10
+ The first entry, `words[0]`, is the least significant word.
11
+ */
12
12
private let N = 64
13
13
public typealias Word = UInt64
14
14
fileprivate( set) public var words : [ Word ]
15
-
15
+
16
16
private let allOnes = ~ Word( )
17
-
17
+
18
18
/* Creates a bit set that can hold `size` bits. All bits are initially 0. */
19
19
public init ( size: Int ) {
20
20
precondition ( size > 0 )
21
21
self . size = size
22
-
22
+
23
23
// Round up the count to the next multiple of 64.
24
24
let n = ( size + ( N- 1 ) ) / N
25
25
words = [ Word] ( repeating: 0 , count: n)
26
26
}
27
-
27
+
28
28
/* Converts a bit index into an array index and a mask inside the word. */
29
29
private func indexOf( _ i: Int ) -> ( Int , Word ) {
30
30
precondition ( i >= 0 )
@@ -33,79 +33,79 @@ public struct BitSet {
33
33
let m = Word ( i - o*N)
34
34
return ( o, 1 << m)
35
35
}
36
-
36
+
37
37
/* Returns a mask that has 1s for all bits that are in the last word. */
38
38
private func lastWordMask( ) -> Word {
39
39
let diff = words. count*N - size
40
40
if diff > 0 {
41
41
// Set the highest bit that's still valid.
42
42
let mask = 1 << Word ( 63 - diff)
43
43
// Subtract 1 to turn it into a mask, and add the high bit back in.
44
- return mask | ( mask - 1 )
44
+ return ( Word ) ( mask | ( mask - 1 ) )
45
45
} else {
46
46
return allOnes
47
47
}
48
48
}
49
-
49
+
50
50
/*
51
- If the size is not a multiple of N, then we have to clear out the bits
52
- that we're not using, or bitwise operations between two differently sized
53
- BitSets will go wrong.
54
- */
51
+ If the size is not a multiple of N, then we have to clear out the bits
52
+ that we're not using, or bitwise operations between two differently sized
53
+ BitSets will go wrong.
54
+ */
55
55
fileprivate mutating func clearUnusedBits( ) {
56
56
words [ words. count - 1 ] &= lastWordMask ( )
57
57
}
58
-
58
+
59
59
/* So you can write bitset[99] = ... */
60
60
public subscript( i: Int ) -> Bool {
61
61
get { return isSet ( i) }
62
62
set { if newValue { set ( i) } else { clear ( i) } }
63
63
}
64
-
64
+
65
65
/* Sets the bit at the specified index to 1. */
66
66
public mutating func set( _ i: Int ) {
67
67
let ( j, m) = indexOf ( i)
68
68
words [ j] |= m
69
69
}
70
-
70
+
71
71
/* Sets all the bits to 1. */
72
72
public mutating func setAll( ) {
73
73
for i in 0 ..< words. count {
74
74
words [ i] = allOnes
75
75
}
76
76
clearUnusedBits ( )
77
77
}
78
-
78
+
79
79
/* Sets the bit at the specified index to 0. */
80
80
public mutating func clear( _ i: Int ) {
81
81
let ( j, m) = indexOf ( i)
82
82
words [ j] &= ~ m
83
83
}
84
-
84
+
85
85
/* Sets all the bits to 0. */
86
86
public mutating func clearAll( ) {
87
87
for i in 0 ..< words. count {
88
88
words [ i] = 0
89
89
}
90
90
}
91
-
91
+
92
92
/* Changes 0 into 1 and 1 into 0. Returns the new value of the bit. */
93
93
public mutating func flip( _ i: Int ) -> Bool {
94
94
let ( j, m) = indexOf ( i)
95
95
words [ j] ^= m
96
96
return ( words [ j] & m) != 0
97
97
}
98
-
98
+
99
99
/* Determines whether the bit at the specific index is 1 (true) or 0 (false). */
100
100
public func isSet( _ i: Int ) -> Bool {
101
101
let ( j, m) = indexOf ( i)
102
102
return ( words [ j] & m) != 0
103
103
}
104
-
104
+
105
105
/*
106
- Returns the number of bits that are 1. Time complexity is O(s) where s is
107
- the number of 1-bits.
108
- */
106
+ Returns the number of bits that are 1. Time complexity is O(s) where s is
107
+ the number of 1-bits.
108
+ */
109
109
public var cardinality : Int {
110
110
var count = 0
111
111
for var x in words {
@@ -117,23 +117,23 @@ public struct BitSet {
117
117
}
118
118
return count
119
119
}
120
-
120
+
121
121
/* Checks if all the bits are set. */
122
122
public func all1( ) -> Bool {
123
123
for i in 0 ..< words. count - 1 {
124
124
if words [ i] != allOnes { return false }
125
125
}
126
126
return words [ words. count - 1 ] == lastWordMask ( )
127
127
}
128
-
128
+
129
129
/* Checks if any of the bits are set. */
130
130
public func any1( ) -> Bool {
131
131
for x in words {
132
132
if x != 0 { return true }
133
133
}
134
134
return false
135
135
}
136
-
136
+
137
137
/* Checks if none of the bits are set. */
138
138
public func all0( ) -> Bool {
139
139
for x in words {
@@ -167,7 +167,7 @@ extension BitSet: Hashable {
167
167
168
168
// MARK: - Bitwise operations
169
169
170
- extension BitSet : BitwiseOperations {
170
+ extension BitSet {
171
171
public static var allZeros : BitSet {
172
172
return BitSet ( size: 64 )
173
173
}
@@ -178,11 +178,11 @@ private func copyLargest(_ lhs: BitSet, _ rhs: BitSet) -> BitSet {
178
178
}
179
179
180
180
/*
181
- Note: In all of these bitwise operations, lhs and rhs are allowed to have a
182
- different number of bits. The new BitSet always has the larger size.
183
- The extra bits that get added to the smaller BitSet are considered to be 0.
184
- That will strip off the higher bits from the larger BitSet when doing &.
185
- */
181
+ Note: In all of these bitwise operations, lhs and rhs are allowed to have a
182
+ different number of bits. The new BitSet always has the larger size.
183
+ The extra bits that get added to the smaller BitSet are considered to be 0.
184
+ That will strip off the higher bits from the larger BitSet when doing &.
185
+ */
186
186
187
187
public func & ( lhs: BitSet , rhs: BitSet ) -> BitSet {
188
188
let m = max ( lhs. size, rhs. size)
@@ -245,3 +245,4 @@ extension BitSet: CustomStringConvertible {
245
245
return s
246
246
}
247
247
}
248
+
0 commit comments