Skip to content

Commit a295334

Browse files
committed
Implement bit shift operations in BitSet
1 parent 319f94d commit a295334

File tree

3 files changed

+111
-2
lines changed

3 files changed

+111
-2
lines changed

Bit Set/BitSet.playground/Contents.swift

+20
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,23 @@ z.all1() // false
8989

9090
//var bigBits = BitSet(size: 10000)
9191
//print(bigBits)
92+
93+
var smallBitSet = BitSet(size: 16)
94+
smallBitSet[5] = true
95+
smallBitSet[10] = true
96+
print( smallBitSet >> 3 )
97+
print( smallBitSet << 6 ) // one bit shifts off the end
98+
99+
var bigBitSet = BitSet( size: 120 )
100+
bigBitSet[1] = true
101+
bigBitSet[3] = true
102+
bigBitSet[7] = true
103+
bigBitSet[32] = true
104+
bigBitSet[55] = true
105+
bigBitSet[64] = true
106+
bigBitSet[80] = true
107+
print( bigBitSet )
108+
print( bigBitSet << 32 )
109+
print( bigBitSet << 64 )
110+
print( bigBitSet >> 32 )
111+
print( bigBitSet >> 64 )

Bit Set/BitSet.playground/Sources/BitSet.swift

+45-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public struct BitSet {
99
We store the bits in a list of unsigned 64-bit integers.
1010
The first entry, `words[0]`, is the least significant word.
1111
*/
12-
private let N = 64
12+
fileprivate let N = 64
1313
public typealias Word = UInt64
1414
fileprivate(set) public var words: [Word]
1515

@@ -221,6 +221,50 @@ prefix public func ~ (rhs: BitSet) -> BitSet {
221221
return out
222222
}
223223

224+
// MARK: - Bit shift operations
225+
226+
/*
227+
Note: For bitshift operations, the assumption is that any bits that are
228+
shifted off the end of the end of the declared size are not still set.
229+
In other words, we are maintaining the original number of bits.
230+
*/
231+
232+
public func << (lhs: BitSet, numBitsLeft: Int) -> BitSet {
233+
var out = lhs
234+
let offset = numBitsLeft / lhs.N
235+
let shift = numBitsLeft % lhs.N
236+
for i in 0..<lhs.words.count {
237+
out.words[i] = 0
238+
if( i - offset >= 0 ) {
239+
out.words[i] = lhs.words[i - offset] << shift
240+
}
241+
if( i - offset - 1 >= 0 ) {
242+
out.words[i] |= lhs.words[i - offset - 1] >> (lhs.N - shift)
243+
}
244+
}
245+
246+
out.clearUnusedBits()
247+
return out
248+
}
249+
250+
public func >> (lhs: BitSet, numBitsRight: Int) -> BitSet {
251+
var out = lhs
252+
let offset = numBitsRight / lhs.N
253+
let shift = numBitsRight % lhs.N
254+
for i in 0..<lhs.words.count {
255+
out.words[i] = 0
256+
if( i + offset < lhs.words.count ) {
257+
out.words[i] = lhs.words[i + offset] >> shift
258+
}
259+
if( i + offset + 1 < lhs.words.count ) {
260+
out.words[i] |= lhs.words[i + offset + 1] << (lhs.N - shift)
261+
}
262+
}
263+
264+
out.clearUnusedBits()
265+
return out
266+
}
267+
224268
// MARK: - Debugging
225269

226270
extension UInt64 {

Bit Set/BitSet.swift

+46-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public struct BitSet {
99
We store the bits in a list of unsigned 64-bit integers.
1010
The first entry, `words[0]`, is the least significant word.
1111
*/
12-
private let N = 64
12+
fileprivate let N = 64
1313
public typealias Word = UInt64
1414
fileprivate(set) public var words: [Word]
1515

@@ -221,6 +221,51 @@ prefix public func ~ (rhs: BitSet) -> BitSet {
221221
return out
222222
}
223223

224+
// MARK: - Bit shift operations
225+
226+
/*
227+
Note: For bitshift operations, the assumption is that any bits that are
228+
shifted off the end of the end of the declared size are not still set.
229+
In other words, we are maintaining the original number of bits.
230+
*/
231+
232+
public func << (lhs: BitSet, numBitsLeft: Int) -> BitSet {
233+
var out = lhs
234+
let offset = numBitsLeft / lhs.N
235+
let shift = numBitsLeft % lhs.N
236+
for i in 0..<lhs.words.count {
237+
out.words[i] = 0
238+
if( i - offset >= 0 ) {
239+
out.words[i] = lhs.words[i - offset] << shift
240+
}
241+
if( i - offset - 1 >= 0 ) {
242+
out.words[i] |= lhs.words[i - offset - 1] >> (lhs.N - shift)
243+
}
244+
}
245+
246+
out.clearUnusedBits()
247+
return out
248+
}
249+
250+
public func >> (lhs: BitSet, numBitsRight: Int) -> BitSet {
251+
var out = lhs
252+
let offset = numBitsRight / lhs.N
253+
let shift = numBitsRight % lhs.N
254+
for i in 0..<lhs.words.count {
255+
out.words[i] = 0
256+
if( i + offset < lhs.words.count ) {
257+
out.words[i] = lhs.words[i + offset] >> shift
258+
}
259+
if( i + offset + 1 < lhs.words.count ) {
260+
out.words[i] |= lhs.words[i + offset + 1] << (lhs.N - shift)
261+
}
262+
}
263+
264+
out.clearUnusedBits()
265+
return out
266+
}
267+
268+
224269
// MARK: - Debugging
225270

226271
extension UInt64 {

0 commit comments

Comments
 (0)