Forráskód Böngészése

* modified (cosmetics) patch by Rika: replace DJB2 with MurmurHash3, resolves #39377

florian 3 éve
szülő
commit
177b38dfe9
1 módosított fájl, 49 hozzáadás és 23 törlés
  1. 49 23
      compiler/cclasses.pas

+ 49 - 23
compiler/cclasses.pas

@@ -1241,38 +1241,64 @@ end;
                             TFPHashList
                             TFPHashList
 *****************************************************************************}
 *****************************************************************************}
 
 
-
-    function FPHash(P: PChar; Len: Integer; Tag: LongWord): LongWord;
-    Var
-      pmax : pchar;
-    begin
+// MurmurHash3_32
+function FPHash(P: PChar; Len: Integer; Tag: LongWord): LongWord;
+const
+  C1 = uint32($cc9e2d51);
+  C2 = uint32($1b873593);
+var
+  h, tail: uint32;
+  e4: pChar;
+  len4, nTail: SizeUint;
+begin
 {$push}
 {$push}
 {$q-,r-}
 {$q-,r-}
-      result:=Tag;
-      pmax:=p+len;
-      while (p<pmax) do
-        begin
-          {DJBHash: result:=result*33 + next_char}
-          result:=LongWord(LongInt(result shl 5) + LongInt(result)) + LongWord(P^);
-          inc(p);
-        end;
-{$pop}
-    end;
+  h := tag;
 
 
-    function FPHash(P: PChar; Len: Integer): LongWord; inline;
+  len4 := len and not integer(sizeof(uint32) - 1); { len div sizeof(uint32) * sizeof(uint32) }
+  e4 := p + len4;
+  nTail := len - len4;
+  while p < e4 do
     begin
     begin
-      result:=fphash(P,Len, 5381);
+      { If independence on endianness is desired, unaligned(pUint32(p)^) can be replaced with LEtoN(unaligned(pUint32(p)^)). }
+      h := RolDWord(h xor (RolDWord(unaligned(pUint32(p)^) * C1, 15) * C2), 13) * 5 + $e6546b64;
+      p := p + sizeof(uint32);
     end;
     end;
 
 
-    function FPHash(const s: shortstring): LongWord; inline;
+  if nTail > 0 then
     begin
     begin
-      result:=fphash(pchar(@s[1]),length(s));
+      { tail is 1 to 3 bytes }
+      case nTail of
+        3: tail := unaligned(pUint16(p)^) or uint32(p[2]) shl 16; { unaligned(pUint16(p^)) can be LEtoNed for portability }
+        2: tail := unaligned(pUint16(p)^); { unaligned(pUint16(p^)) can be LEtoNed for portability }
+        {1:} else tail := uint32(p^);
+      end;
+      h := h xor (RolDWord(tail * C1, 15) * C2);
     end;
     end;
 
 
-    function FPHash(const a: ansistring): LongWord; inline;
-    begin
-      result:=fphash(pchar(a),length(a));
-    end;
+  h := h xor uint32(len);
+  h := (h xor (h shr 16)) * $85ebca6b;
+  h := (h xor (h shr 13)) * $c2b2ae35;
+  result := h xor (h shr 16);
+{$pop}
+end;
+
+function FPHash(P: PChar; Len: Integer): LongWord; inline;
+begin
+  result:=fphash(P,Len, 0);
+end;
+
+
+function FPHash(const s: shortstring): LongWord; inline;
+begin
+  result:=fphash(pchar(@s[1]),length(s));
+end;
+
+
+function FPHash(const a: ansistring): LongWord; inline;
+begin
+  result:=fphash(pchar(a),length(a));
+end;
 
 
 
 
 procedure TFPHashList.RaiseIndexError(Index : Integer);
 procedure TFPHashList.RaiseIndexError(Index : Integer);