Skip to content

Commit a88c984

Browse files
committed
remove duplicate source file, update README
1 parent 2f92aef commit a88c984

File tree

2 files changed

+84
-293
lines changed

2 files changed

+84
-293
lines changed

Bit Set/BitSet.swift

-293
This file was deleted.

Bit Set/README.markdown

+84
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,90 @@ This is the original value but with the lowest 1-bit removed.
329329

330330
We keep repeating this process until the value consists of all zeros. The time complexity is **O(s)** where **s** is the number of 1-bits.
331331

332+
## Bit Shift Operations
333+
334+
Bit shifts are a common and very useful mechanism when dealing with bitsets. Here is the right-shift function:
335+
336+
```
337+
public func >> (lhs: BitSet, numBitsRight: Int) -> BitSet {
338+
var out = lhs
339+
let offset = numBitsRight / lhs.N
340+
let shift = numBitsRight % lhs.N
341+
for i in 0..<lhs.words.count {
342+
out.words[i] = 0
343+
344+
if (i + offset < lhs.words.count) {
345+
out.words[i] = lhs.words[i + offset] >> shift
346+
}
347+
348+
if (i + offset + 1 < lhs.words.count) {
349+
out.words[i] |= lhs.words[i + offset + 1] << (lhs.N - shift)
350+
}
351+
}
352+
353+
out.clearUnusedBits()
354+
return out
355+
}
356+
```
357+
358+
Let's start with this line:
359+
360+
```swift
361+
for i in 0..<lhs.words.count {
362+
```
363+
364+
This indicates our strategy: we want to go through each word of the result and assign the correct bits.
365+
366+
The two internal if-statements inside this loop are assigning some bits from one place in the source number and bitwise OR-ing them with some bits from a second place in the source number. The key insight here is that the bits for any one word of the result comes from at most two source words in the input. So the only remaining trick is to calculate which ones. For this, we need these two numbers:
367+
368+
```swift
369+
let offset = numBitsRight / lhs.N
370+
let shift = numBitsRight % lhs.N
371+
```
372+
373+
Offset gives us how many words away from the source word we start getting our bits (with the remainder coming from it's neighbour). Shift gives us how many bits we need to shift within that word. Note that both of these are calcuated using the word size `lhs.N`.
374+
375+
All that's left if a little bit of protection against reading outside the bounds of the input. So these two if conditions protect against that:
376+
```swift
377+
if (i + offset < lhs.words.count) {
378+
```
379+
and
380+
```swift
381+
if (i + offset + 1 < lhs.words.count) {
382+
```
383+
384+
Let's work through an example. Suppose our word length has been reduced to 8 bits, and we'd like to right-shift the following number by 10 bits:
385+
386+
01000010 11000000 00011100 >> 10
387+
388+
I've grouped each part of the number by word to make it easier to see what happens. The for-loop goes from least significant word to most significant. So for index zero we're want to know what bits will make up our least significant word. Let's calculate our offset and shift values:
389+
390+
offset = 10 / 8 = 1 (remember this is integer division)
391+
shift = 10 % 8 = 2
392+
393+
So we consult the word at offset 1 to get some of our bits:
394+
395+
11000000 >> 2 = 00110000
396+
397+
And we get the rest of them from the word one further away:
398+
399+
01000010 << (8 - 2) = 10000000
400+
401+
And we bitwise OR these together to get our least significant term
402+
403+
00110000
404+
10000000
405+
-------- OR
406+
10110000
407+
408+
We repeat this for the 2nd least significant term and obtain:
409+
410+
00010000
411+
412+
The last term can't get any bits because they are past the end of our number so those are all zeros. Our result is:
413+
414+
00000000 00010000 10110000
415+
332416
## See also
333417

334418
[Bit Twiddling Hacks](http://graphics.stanford.edu/~seander/bithacks.html)

0 commit comments

Comments
 (0)