#OTHER by stefan
authorStefan Vogel <sv@exept.de>
Thu, 07 Apr 2016 14:43:12 +0200
changeset 19555 29a4c770f926
parent 19554 91ec8f105783
child 19556 debeaab902dd
#OTHER by stefan class: LargeInteger changed: #hash Make sure that SmallIntegers and (unnormalized) LargeIntegers hash to the same value, if equal.
LargeInteger.st
--- 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
     "
 !