Skip to content

Commit

Permalink
# This is a combination of 2 commits.
Browse files Browse the repository at this point in the history
# This is the 1st commit message:

Optimize BitSet#min and max for case of Ordering.Int

# This is the commit message #2:

Fix buggy bitset min and max implementations
  • Loading branch information
joshlemer committed Dec 2, 2018
1 parent 837309f commit 9e4cec8
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 1 deletion.
56 changes: 56 additions & 0 deletions src/library/scala/collection/BitSet.scala
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,62 @@ trait BitSetOps[+C <: BitSet with BitSetOps[C]]

override def isEmpty: Boolean = 0 until nwords forall (i => word(i) == 0)

override def max[B >: Int](implicit ord: Ordering[B]): Int =
if (Ordering.Int eq ord) {
var i = nwords - 1
var currentWord = 0L
while(i >= 0) {
currentWord = word(i)
if (currentWord != 0L) {
return ((i + 1) * WordLength) - java.lang.Long.numberOfLeadingZeros(currentWord) - 1
}
i -= 1
}
throw new UnsupportedOperationException("empty.max")
} else if (Ordering.Int.reverse eq ord) {
val thisnwords = nwords
var i = 0
var currentWord = 0L
while(i < thisnwords) {
currentWord = word(i)
if (currentWord != 0L) {
return java.lang.Long.numberOfTrailingZeros(currentWord) + (i * WordLength)
}
i += 1
}
throw new UnsupportedOperationException("empty.max")
} else {
super.max(ord)
}

override def min[B >: Int](implicit ord: Ordering[B]): Int =
if (Ordering.Int eq ord) {
val thisnwords = nwords
var i = 0
var currentWord = 0L
while(i < thisnwords) {
currentWord = word(i)
if (currentWord != 0L) {
return java.lang.Long.numberOfTrailingZeros(currentWord) + (i * WordLength)
}
i += 1
}
throw new UnsupportedOperationException("empty.min")
} else if (Ordering.Int.reverse eq ord) {
var i = nwords - 1
var currentWord = 0L
while(i >= 0) {
currentWord = word(i)
if (currentWord != 0L) {
return ((i + 1) * WordLength) - java.lang.Long.numberOfLeadingZeros(currentWord) - 1
}
i -= 1
}
throw new UnsupportedOperationException("empty.min")
} else {
super.min(ord)
}

override def foreach[U](f: Int => U): Unit = {
/* NOTE: while loops are significantly faster as of 2.11 and
one major use case of bitsets is performance. Also, there
Expand Down
2 changes: 1 addition & 1 deletion src/library/scala/math/Ordering.scala
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ object Ordering extends LowPriorityOrderingImplicits {
override def hashCode(): Int = outer.hashCode() * reverseSeed
}

private final val IntReverse: Ordering[Int] = new Reverse(Ordering.Int)
final val IntReverse: Ordering[Int] = new Reverse(Ordering.Int)

private final class IterableOrdering[CC[X] <: Iterable[X], T](private val ord: Ordering[T]) extends Ordering[CC[T]] {
def compare(x: CC[T], y: CC[T]): Int = {
Expand Down
33 changes: 33 additions & 0 deletions test/scalacheck/scala/collection/immutable/BitSetProperties.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package scala.collection.immutable
import org.scalacheck._
import org.scalacheck.Prop._
import org.scalacheck.Prop.BooleanOperators
import Gen._
object BitSetProperties extends Properties("immutable.BitSet") {
override def overrideParameters(p: Test.Parameters): Test.Parameters =
p.withMinSuccessfulTests(500)
.withInitialSeed(42L)
// the top of the range shouldn't be too high, else we may not get enough overlap
implicit val arbitraryBitSet: Arbitrary[BitSet] = Arbitrary(
oneOf(
const(BitSet()),
oneOf(0 to 100).map(i => BitSet(i)),
listOfN(200, oneOf(0 to 10000)).map(_.to(BitSet))
)
)

property("min") = forAll { (bs: BitSet) =>
bs.nonEmpty ==> (bs.min ?= bs.toList.min)
}
property("min reverse") = forAll { (bs: BitSet) =>
bs.nonEmpty ==> (bs.min(Ordering.Int.reverse) ?= bs.toList.min(Ordering.Int.reverse))
}

property("max") = forAll { (bs: BitSet) =>
bs.nonEmpty ==> (bs.max ?= bs.toList.max)
}

property("max reverse") = forAll { (bs: BitSet) =>
bs.nonEmpty ==> (bs.max(Ordering.Int.reverse) ?= bs.toList.max(Ordering.Int.reverse))
}
}

0 comments on commit 9e4cec8

Please sign in to comment.