#OTHER by stefan
class: LargeInteger
changed: #hash
Make sure that SmallIntegers and (unnormalized) LargeIntegers hash to the
same value, if equal.
--- a/LargeInteger.st Thu Apr 07 14:36:35 2016 +0200
+++ b/LargeInteger.st Thu Apr 07 14:43:12 2016 +0200
@@ -2200,31 +2200,30 @@
hash
"return an integer useful for hashing on large numbers"
- |l h m|
-
- h := self bitAnd:16r3FFFFFFF.
-
- l := digitByteArray size.
- l >= 8 ifTrue:[
- h := h bitXor:(digitByteArray at:l).
- h := h bitXor:((digitByteArray at:l-1) bitShift:8).
- h := h bitXor:((digitByteArray at:l-2) bitShift:16).
- h := h bitXor:((digitByteArray at:l-3) bitShift:22).
- l >= 12 ifTrue:[
- m := l // 2.
- h := h bitXor:(digitByteArray at:m-1).
- h := h bitXor:((digitByteArray at:m) bitShift:8).
- h := h bitXor:((digitByteArray at:m+1) bitShift:16).
- h := h bitXor:((digitByteArray at:m+2) bitShift:22).
- ].
- ^ h
+ |sz h|
+
+ sz := digitByteArray size.
+ (sz <= SmallInteger maxBytes and:[self absLess:SmallInteger maxVal]) ifTrue:[
+ "I am really an unnormalized SmallInteger, answer the same hash as for the SmallInteger"
+ ^ self bitAnd:SmallInteger maxVal.
].
- ^ (h bitShift:3) + l
+
+ h := digitByteArray computeXorHashFrom:1 to:8. "/ the low 8 bytes
+ sz > 8 ifTrue:[ "/ the high 8 bytes
+ h := h bitXor:(digitByteArray computeXorHashFrom:sz-8 to:sz).
+ ].
+ ^ h
"
16r80000000 hash
+ 16r-80000000 asLargeInteger hash
16r80000008 hash
16r8000000000008 hash
+
+ 16r8000000000000000 hash
+ 16r8000000000000008 hash
+ 16r800000000000000000008 hash
+ 16r-800000000000000000008 hash
"
!