Skip to content

BitSet shift left - skip zero words #50

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions src/main/scala/scala/collection/decorators/BitSetDecorator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class BitSetDecorator[+C <: BitSet with BitSetOps[C]](protected val bs: C) {
import BitSetOps._

/**
* Bitwise left shift of this BitSet by given the shift distance.
* Bitwise left shift of this BitSet by the given shift distance.
* The shift distance may be negative, in which case this method performs a right shift.
* @param shiftBy shift distance, in bits
* @return a new BitSet whose value is a bitwise shift left of this BitSet by given shift distance (`shiftBy`)
Expand Down Expand Up @@ -44,8 +44,13 @@ class BitSetDecorator[+C <: BitSet with BitSetOps[C]](protected val bs: C) {
val bitOffset = shiftBy & WordMask
val wordOffset = shiftBy >>> LogWL

var significantWordCount = bs.nwords
while (significantWordCount > 0 && bs.word(significantWordCount - 1) == 0) {
significantWordCount -= 1
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to compute the amount to subtract from significantWordCount in O(1) time?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really doubt this. AFAIK BitSet implementation does not keep track of its most significant word/bit. Or maybe you have some idea?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I haven’t thought about how to do this. This was just a question that popped up as I was quickly reading the diff.


if (bitOffset == 0) {
val newSize = bs.nwords + wordOffset
val newSize = significantWordCount + wordOffset
require(newSize <= MaxSize)
val newBits = Array.ofDim[Long](newSize)
var i = wordOffset
Expand All @@ -56,14 +61,14 @@ class BitSetDecorator[+C <: BitSet with BitSetOps[C]](protected val bs: C) {
newBits
} else {
val revBitOffset = WordLength - bitOffset
val extraBits = bs.word(bs.nwords - 1) >>> revBitOffset
val extraBits = bs.word(significantWordCount - 1) >>> revBitOffset
val extraWordCount = if (extraBits == 0) 0 else 1
val newSize = bs.nwords + wordOffset + extraWordCount
val newSize = significantWordCount + wordOffset + extraWordCount
require(newSize <= MaxSize)
val newBits = Array.ofDim[Long](newSize)
var previous = 0L
var i = 0
while (i < bs.nwords) {
while (i < significantWordCount) {
val current = bs.word(i)
newBits(i + wordOffset) = (previous >>> revBitOffset) | (current << bitOffset)
previous = current
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ class BitSetDecoratorTest {
}
}

@Test
def skipZeroWordsOnShiftLeft(): Unit = {
val result = BitSet(5 * 64 - 1) << 64
assertEquals(BitSet(6 * 64 - 1), result)
assertEquals(6, result.nwords)
}

@Test
def shiftEmptyRight(): Unit = {
for (shiftBy <- 0 to 128) {
Expand Down