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

This commit is contained in:
florian 2021-10-01 23:05:48 +02:00
parent 02745b0b83
commit 177b38dfe9

View File

@ -1241,38 +1241,64 @@ end;
TFPHashList TFPHashList
*****************************************************************************} *****************************************************************************}
// MurmurHash3_32
function FPHash(P: PChar; Len: Integer; Tag: LongWord): LongWord; function FPHash(P: PChar; Len: Integer; Tag: LongWord): LongWord;
Var const
pmax : pchar; C1 = uint32($cc9e2d51);
begin C2 = uint32($1b873593);
var
h, tail: uint32;
e4: pChar;
len4, nTail: SizeUint;
begin
{$push} {$push}
{$q-,r-} {$q-,r-}
result:=Tag; h := tag;
pmax:=p+len;
while (p<pmax) do len4 := len and not integer(sizeof(uint32) - 1); { len div sizeof(uint32) * sizeof(uint32) }
begin e4 := p + len4;
{DJBHash: result:=result*33 + next_char} nTail := len - len4;
result:=LongWord(LongInt(result shl 5) + LongInt(result)) + LongWord(P^); while p < e4 do
inc(p); begin
end; { 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;
if nTail > 0 then
begin
{ 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;
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} {$pop}
end; end;
function FPHash(P: PChar; Len: Integer): LongWord; inline; function FPHash(P: PChar; Len: Integer): LongWord; inline;
begin begin
result:=fphash(P,Len, 5381); result:=fphash(P,Len, 0);
end; end;
function FPHash(const s: shortstring): LongWord; inline;
begin
result:=fphash(pchar(@s[1]),length(s));
end;
function FPHash(const a: ansistring): LongWord; inline; function FPHash(const s: shortstring): LongWord; inline;
begin begin
result:=fphash(pchar(a),length(a)); result:=fphash(pchar(@s[1]),length(s));
end; 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);