8000 [backport] Hash table getOrElseUpdate and indexing by adriaanm · Pull Request #5626 · scala/scala · GitHub
[go: up one dir, main page]

Skip to content

[backport] Hash table getOrElseUpdate and indexing #5626

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 7 commits into from
Jan 6, 2017
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Changed modulo to bitwise AND in hash calculation
(cherry picked from commit 7952525)
  • Loading branch information
l0rinc authored and adriaanm committed Jan 5, 2017
commit 26ad9cc73c88bad0140adb7cec583a4d05db498d
69 changes: 17 additions & 52 deletions src/library/scala/collection/mutable/HashTable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -411,58 +411,23 @@ private[collection] object HashTable {

protected def elemHashCode(key: KeyType) = key.##

protected final def improve(hcode: Int, seed: Int) = {
/* Murmur hash
* m = 0x5bd1e995
* r = 24
* note: h = seed = 0 in mmix
* mmix(h,k) = k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; */
// var k = hcode * 0x5bd1e995
// k ^= k >> 24
// k *= 0x5bd1e995
// k

/* Another fast multiplicative hash
* by Phil Bagwell
*
* Comment:
* Multiplication doesn't affect all the bits in the same way, so we want to
* multiply twice, "once from each side".
* It would be ideal to reverse all the bits after the first multiplication,
* however, this is more costly. We therefore restrict ourselves only to
* reversing the bytes before final multiplication. This yields a slightly
* worse entropy in the lower 8 bits, but that can be improved by adding:
*
* `i ^= i >> 6`
*
* For performance reasons, we avoid this improvement.
* */
val i= scala.util.hashing.byteswap32(hcode)

/* Jenkins hash
* for range 0-10000, output has the msb set to zero */
// var h = hcode + (hcode << 12)
// h ^= (h >> 22)
// h += (h << 4)
// h ^= (h >> 9)
// h += (h << 10)
// h ^= (h >> 2)
// h += (h << 7)
// h ^= (h >> 12)
// h

/* OLD VERSION
* quick, but bad for sequence 0-10000 - little entropy in higher bits
* since 2003 */
// var h: Int = hcode + ~(hcode << 9)
// h = h ^ (h >>> 14)
// h = h + (h << 4)
// h ^ (h >>> 10)

// the rest of the computation is due to SI-5293
val rotation = seed % 32
val rotated = (i >>> rotation) | (i << (32 - rotation))
rotated
/**
* Defer to a high-quality hash in [[scala.util.hashing]].
* The goal is to distribute across bins as well as possible even if a hash code has low entropy at some bits.
* <p/>
* OLD VERSION - quick, but bad for sequence 0-10000 - little entropy in higher bits - since 2003
* {{{
* var h: Int = hcode + ~(hcode << 9)
* h = h ^ (h >>> 14)
* h = h + (h << 4)
* h ^ (h >>> 10)
* }}}
* the rest of the computation is due to SI-5293
*/
protected final def improve(hcode: Int, seed: Int): Int = {
val hash = scala.util.hashing.byteswap32(hcode)
val shift = seed & ((1 << 5) - 1)
(hash >>> shift) | (hash << (32 - shift))
}
}

Expand Down
0