Skip to content

Commit cbf56ce

Browse files
nicolasstuckiodersky
authored andcommitted
Add pjwHash64 regression tests
1 parent 3c672e0 commit cbf56ce

File tree

3 files changed

+50
-19
lines changed

3 files changed

+50
-19
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package dotty.tools.dotc.core.tasty
2+
3+
object TastyHash {
4+
5+
/** Returns a non-cryptographic 64-bit hash of the array.
6+
*
7+
* from https://en.wikipedia.org/wiki/PJW_hash_function#Algorithm
8+
*/
9+
def pjwHash64(data: Array[Byte]): Long = {
10+
var h = 0L
11+
var i = 0
12+
while (i < data.length) {
13+
val d = data(i) & 0xFFL // Interpret byte as unsigned byte
14+
h = (h << 8) + d
15+
val high = h & 0xFF00000000000000L
16+
h ^= high >> 48L
17+
h &= ~high
18+
i += 1
19+
}
20+
h
21+
}
22+
23+
}

compiler/src/dotty/tools/dotc/core/tasty/TastyPickler.scala

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ class TastyPickler(val rootCls: ClassSymbol) {
2626
nameBuffer.assemble()
2727
sections.foreach(_._2.assemble())
2828

29-
val nameBufferHash = pjwHash64(nameBuffer.bytes)
30-
val treeSectionHash +: otherSectionHashes = sections.map(x => pjwHash64(x._2.bytes))
29+
val nameBufferHash = TastyHash.pjwHash64(nameBuffer.bytes)
30+
val treeSectionHash +: otherSectionHashes = sections.map(x => TastyHash.pjwHash64(x._2.bytes))
3131

3232
// Hash of name table and tree
3333
val uuidLow: Long = nameBufferHash ^ treeSectionHash
@@ -78,21 +78,4 @@ class TastyPickler(val rootCls: ClassSymbol) {
7878

7979
val treePkl = new TreePickler(this)
8080

81-
/** Returns a non-cryptographic 64-bit hash of the array.
82-
*
83-
* from https://en.wikipedia.org/wiki/PJW_hash_function#Algorithm
84-
*/
85-
private def pjwHash64(data: Array[Byte]): Long = {
86-
var h = 0L
87-
var i = 0
88-
while (i < data.length) {
89-
val d = data(i) & 0xFFL // Interpret byte as unsigned byte
90-
h = (h << 8) + d
91-
val high = h & 0xFF00000000000000L
92-
h ^= high >> 48L
93-
h &= ~high
94-
i += 1
95-
}
96-
h
97-
}
9881
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import dotty.tools.dotc.core.tasty.TastyHash.pjwHash64
2+
3+
object Test {
4+
def main(args: Array[String]): Unit = {
5+
testHash(0L, Array.empty)
6+
testHash(0L, Array(0))
7+
testHash(1L, Array(1))
8+
testHash(0x7fL, Array(Byte.MaxValue))
9+
testHash(0x80L, Array(Byte.MinValue))
10+
testHash(0x101L, Array(1, 1))
11+
testHash(0X10101L, Array(1, 1, 1))
12+
testHash(0X1010101L, Array(1, 1, 1, 1))
13+
testHash(0X101010101L, Array(1, 1, 1, 1, 1))
14+
testHash(0X202020202L, Array(2, 2, 2, 2, 2))
15+
testHash(0X1010101L, Array.fill(1024)(1))
16+
testHash(0X55aa01fe55ab54ffL, Array.tabulate(1024)(_.toByte))
17+
testHash(0x34545c16020230L, "abcdefghijklmnopqrstuvwxyz1234567890".getBytes)
18+
}
19+
20+
def testHash(expected: Long, arr: Array[Byte]): Unit = {
21+
val res = pjwHash64(arr)
22+
assert(res == expected, s"Exprected 0x${expected.toHexString}L but got 0X${res.toHexString}L")
23+
}
24+
25+
}

0 commit comments

Comments
 (0)