diff --git a/src/main/scala/scala/collection/decorators/BitSetDecorator.scala b/src/main/scala/scala/collection/decorators/BitSetDecorator.scala index f0838ec..0b5e294 100644 --- a/src/main/scala/scala/collection/decorators/BitSetDecorator.scala +++ b/src/main/scala/scala/collection/decorators/BitSetDecorator.scala @@ -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`) @@ -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 + } + if (bitOffset == 0) { - val newSize = bs.nwords + wordOffset + val newSize = significantWordCount + wordOffset require(newSize <= MaxSize) val newBits = Array.ofDim[Long](newSize) var i = wordOffset @@ -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 diff --git a/src/test/scala/scala/collection/decorators/BitSetDecoratorTest.scala b/src/test/scala/scala/collection/decorators/BitSetDecoratorTest.scala index 0fcf1c4..bee399f 100644 --- a/src/test/scala/scala/collection/decorators/BitSetDecoratorTest.scala +++ b/src/test/scala/scala/collection/decorators/BitSetDecoratorTest.scala @@ -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) {