in algebird-core/src/main/scala/com/twitter/algebird/BloomFilter.scala [267:329]
override def equiv(a: BF[A], b: BF[A]): Boolean = {
def toIntIt(b: BF[A]): IntIterator =
b match {
case BFItem(it, hashes, _) =>
new IntIterator {
// the hashes can have collisions so we need
// to remove duplicates
val hashvalues: Array[Int] = hashes(it)
java.util.Arrays.sort(hashvalues)
@annotation.tailrec
def uniq(src: Array[Int], dst: Array[Int], prev: Int, spos: Int, dpos: Int): Int =
if (spos >= src.length) dpos
else if (spos == 0) {
// first
val first = src(0)
dst(0) = first
uniq(src, dst, first, spos + 1, dpos + 1)
} else {
val cur = src(spos)
if (cur == prev) uniq(src, dst, prev, spos + 1, dpos)
else {
dst(dpos) = cur
uniq(src, dst, cur, spos + 1, dpos + 1)
}
}
val uniqVs = new Array[Int](hashvalues.length)
val len: Int = uniq(hashvalues, uniqVs, -1, 0, 0)
var pos = 0
override def hasNext: Boolean = pos < len
override def next: Int = {
val n = uniqVs(pos)
pos += 1
n
}
}
case BFSparse(_, cbitset, _) => cbitset.intIterator
case BFInstance(_, bitset, _) =>
new IntIterator {
val boxedIter: Iterator[Int] = bitset.iterator
override def hasNext: Boolean = boxedIter.hasNext
override def next: Int = boxedIter.next()
}
case BFZero(_, _) =>
new IntIterator {
override def hasNext = false
override def next: Nothing = sys.error("BFZero has no hashes set")
}
}
def eqIntIter(a: IntIterator, b: IntIterator): Boolean = {
while (a.hasNext && b.hasNext) {
if (!(a.next == b.next)) return false
}
a.hasNext == b.hasNext
}
(a eq b) || ((a.numHashes == b.numHashes) &&
(a.width == b.width) &&
eqIntIter(toIntIt(a), toIntIt(b)))
}