diff --git a/lib/pure/hashes.nim b/lib/pure/hashes.nim index 667f27e95d2ef..da72f2fab01d0 100644 --- a/lib/pure/hashes.nim +++ b/lib/pure/hashes.nim @@ -195,10 +195,29 @@ else: ## Efficient hashing of integers. hashWangYi1(uint64(ord(x))) +when defined(js): + proc asBigInt(x: float): int64 = + # result is a `BigInt` type in js, but we cheat the type system + # and say it is a `int64` type. + # TODO refactor it using bigInt once jsBigInt is ready, pending pr #1640 + asm """ + const buffer = new ArrayBuffer(8); + const floatBuffer = new Float64Array(buffer); + const uintBuffer = new BigUint64Array(buffer); + floatBuffer[0] = `x`; + `result` = uintBuffer[0];""" + proc hash*(x: float): Hash {.inline.} = ## Efficient hashing of floats. - var y = x + 0.0 # for denormalization - result = hash(cast[ptr Hash](addr(y))[]) + let y = x + 0.0 # for denormalization + when nimvm: + # workaround a JS VM bug: bug #16547 + result = hashWangYi1(cast[int64](float64(y))) + else: + when not defined(js): + result = hashWangYi1(cast[Hash](y)) + else: + result = hashWangYi1(asBigInt(y)) # Forward declarations before methods that hash containers. This allows # containers to contain other containers diff --git a/tests/stdlib/thashes.nim b/tests/stdlib/thashes.nim index 520b27e263186..9c928778489b9 100644 --- a/tests/stdlib/thashes.nim +++ b/tests/stdlib/thashes.nim @@ -2,7 +2,7 @@ discard """ targets: "c cpp js" """ -import hashes +import std/hashes block hashes: block hashing: @@ -75,3 +75,32 @@ block largeSize: # longer than 4 characters doAssert hash(xx) == hash(ssl, 0, 4) doAssert hash(xx, 0, 3) == hash(xxl, 0, 3) doAssert hash(xx, 0, 3) == hash(ssl, 0, 3) + +proc main() = + doAssert hash(0.0) == hash(0) + when sizeof(int) == 8: + block: + var s: seq[Hash] + for a in [0.0, 1.0, -1.0, 1000.0, -1000.0]: + let b = hash(a) + doAssert b notin s + s.add b + when defined(js): + doAssert hash(0.345602) == 2035867618 + doAssert hash(234567.45) == -20468103 + doAssert hash(-9999.283456) == -43247422 + doAssert hash(84375674.0) == 707542256 + else: + doAssert hash(0.345602) == 387936373221941218 + doAssert hash(234567.45) == -8179139172229468551 + doAssert hash(-9999.283456) == 5876943921626224834 + doAssert hash(84375674.0) == 1964453089107524848 + else: + doAssert hash(0.345602) != 0 + doAssert hash(234567.45) != 0 + doAssert hash(-9999.283456) != 0 + doAssert hash(84375674.0) != 0 + + +static: main() +main()