|
| 1 | +unit UHashes; |
| 2 | + |
| 3 | +{$I SCL.inc} |
| 4 | + |
| 5 | +interface |
| 6 | + |
| 7 | +uses |
| 8 | + UNumber, UString, UxxHash, UxxHashLibraryStatic; |
| 9 | + |
| 10 | +function xxHash32C(P: PChar; L: NChar): U32; inline; |
| 11 | +function FNV1a32(P: PChar; L: NChar): U32; inline; |
| 12 | +function FNV1a32Custom(P: PChar; L: NChar): U32; inline; |
| 13 | +function crc32csse42(crc: cardinal; buf: PAnsiChar; len: cardinal): cardinal; |
| 14 | +function crc32c(P: PChar; L: U32): U32; |
| 15 | +function crc32c2(P: PChar; L: U32): U32; |
| 16 | +function xxHash(P: PByte; L: U32): U32; inline; |
| 17 | + |
| 18 | +implementation |
| 19 | + |
| 20 | +function xxHash32C(P: PChar; L: NChar): U32; |
| 21 | +begin |
| 22 | + Result := XXH3_64bits(P, L) shr 32; |
| 23 | +end; |
| 24 | + |
| 25 | +function FNV1a32(P: PChar; L: NChar): U32; |
| 26 | +var |
| 27 | + C: Ind; |
| 28 | +begin |
| 29 | + Result := 2166136261; |
| 30 | + for C := 0 to L - 1 do |
| 31 | + Result := (Result xor U8(P[C])) * 16777619; |
| 32 | +end; |
| 33 | + |
| 34 | +function FNV1a32Custom(P: PChar; L: NChar): U32; |
| 35 | +begin |
| 36 | + Result := 2166136261; |
| 37 | + while L >= 4 do |
| 38 | + begin |
| 39 | + Result := (Result xor PU32(P)^) * 16777619; |
| 40 | + P += 3; |
| 41 | + L -= 3; |
| 42 | + end; |
| 43 | + while L >= 2 do |
| 44 | + begin |
| 45 | + Result := (Result xor PU16(P)^) * 16777619; |
| 46 | + P += 2; |
| 47 | + L -= 2; |
| 48 | + end; |
| 49 | + if L = 1 then |
| 50 | + Result := (Result xor PU8(P)^) * 16777619; |
| 51 | +end; |
| 52 | + |
| 53 | +//From the great tiny mORMot |
| 54 | +function crc32csse42(crc: cardinal; buf: PAnsiChar; len: cardinal): cardinal; nostackframe; assembler; |
| 55 | +asm |
| 56 | + mov eax, crc |
| 57 | + test len, len |
| 58 | + jz @z |
| 59 | + test buf, buf |
| 60 | + jz @z |
| 61 | + not eax |
| 62 | + mov ecx, len |
| 63 | + shr len, 3 |
| 64 | + jnz @by8 // no read alignment care here - but in crypto.core |
| 65 | + @0: |
| 66 | + test cl, 4 |
| 67 | + jz @4 |
| 68 | + crc32 eax, dword ptr [buf] |
| 69 | + add buf, 4 |
| 70 | + @4: |
| 71 | + test cl, 2 |
| 72 | + jz @2 |
| 73 | + crc32 eax, word ptr [buf] |
| 74 | + add buf, 2 |
| 75 | + @2: |
| 76 | + test cl, 1 |
| 77 | + jz @1 |
| 78 | + crc32 eax, byte ptr [buf] |
| 79 | + @1: |
| 80 | + not eax |
| 81 | + @z: |
| 82 | + ret |
| 83 | + align 16 |
| 84 | + @by8: |
| 85 | + crc32 rax, qword ptr [buf] // hash 8 bytes per loop |
| 86 | + add buf, 8 |
| 87 | + sub len, 1 |
| 88 | + jnz @by8 |
| 89 | + jmp @0 |
| 90 | +end; |
| 91 | + |
| 92 | +function crc32c(P: PChar; L: U32): U32; nostackframe; assembler; |
| 93 | +asm |
| 94 | + MOV EDX, EDX |
| 95 | + LEA R9, [RCX + 8] |
| 96 | + LEA R8, [RCX+RDX] |
| 97 | + CMP R8, R9 |
| 98 | + JB @L7 |
| 99 | + MOV RCX, R9 |
| 100 | + XOR EAX, EAX |
| 101 | + @L3: |
| 102 | + CRC32 RAX, QWORD PTR [RCX - 8] |
| 103 | + ADD RCX, 8 |
| 104 | + CMP R8, RCX |
| 105 | + JNB @L3 |
| 106 | + SUB RDX, 8 |
| 107 | + AND RDX, -8 |
| 108 | + LEA RCX, [R9+RDX] |
| 109 | + @L2: |
| 110 | + LEA RDX, [RCX + 4] |
| 111 | + CMP R8, RDX |
| 112 | + JB @L4 |
| 113 | + CRC32 EAX, DWORD PTR [RCX] |
| 114 | + MOV RCX, RDX |
| 115 | + @L4: |
| 116 | + CMP RCX, R8 |
| 117 | + JNB @L1 |
| 118 | + @L6: |
| 119 | + CRC32 EAX, BYTE PTR [RCX] |
| 120 | + INC RCX |
| 121 | + CMP R8, RCX |
| 122 | + JNE @L6 |
| 123 | + @L1: |
| 124 | + RET |
| 125 | + @L7: |
| 126 | + XOR EAX, EAX |
| 127 | + JMP @L2 |
| 128 | +end; |
| 129 | + |
| 130 | +function crc32c2(P: PChar; L: U32): U32; nostackframe; assembler; |
| 131 | +asm |
| 132 | + mov r8d, edx |
| 133 | + and r8d, 3 |
| 134 | + xor eax, eax |
| 135 | + cmp r8d, 1 |
| 136 | + je @LBB0_5 |
| 137 | + cmp r8d, 2 |
| 138 | + je @LBB0_4 |
| 139 | + cmp r8d, 3 |
| 140 | + jne @LBB0_6 |
| 141 | + xor eax, eax |
| 142 | + crc32 eax, word ptr [rcx] |
| 143 | + crc32 eax, byte ptr [rcx + 2] |
| 144 | + add rcx, 3 |
| 145 | + cmp edx, 4 |
| 146 | + jae @LBB0_7 |
| 147 | + jmp @LBB0_13 |
| 148 | + @LBB0_5: |
| 149 | + crc32 eax, byte ptr [rcx] |
| 150 | + inc rcx |
| 151 | + @LBB0_6: |
| 152 | + cmp edx, 4 |
| 153 | + jae @LBB0_7 |
| 154 | + jmp @LBB0_13 |
| 155 | + @LBB0_4: |
| 156 | + crc32 eax, word ptr [rcx] |
| 157 | + add rcx, 2 |
| 158 | + cmp edx, 4 |
| 159 | + jb @LBB0_13 |
| 160 | + @LBB0_7: |
| 161 | + shr edx, 2 |
| 162 | + lea r8d, [rdx - 1] |
| 163 | + cmp r8d, 7 |
| 164 | + jb @LBB0_10 |
| 165 | + mov r8d, edx |
| 166 | + and r8d, -8 |
| 167 | + @LBB0_9: |
| 168 | + crc32 eax, dword ptr [rcx] |
| 169 | + crc32 eax, dword ptr [rcx + 4] |
| 170 | + crc32 eax, dword ptr [rcx + 8] |
| 171 | + crc32 eax, dword ptr [rcx + 12] |
| 172 | + crc32 eax, dword ptr [rcx + 16] |
| 173 | + crc32 eax, dword ptr [rcx + 20] |
| 174 | + crc32 eax, dword ptr [rcx + 24] |
| 175 | + crc32 eax, dword ptr [rcx + 28] |
| 176 | + add rcx, 32 |
| 177 | + add r8d, -8 |
| 178 | + jne @LBB0_9 |
| 179 | + @LBB0_10: |
| 180 | + test dl, 7 |
| 181 | + je @LBB0_13 |
| 182 | + and edx, 7 |
| 183 | + xor r8d, r8d |
| 184 | + @LBB0_12: |
| 185 | + crc32 eax, dword ptr [rcx + 4*r8] |
| 186 | + inc r8 |
| 187 | + cmp edx, r8d |
| 188 | + jne @LBB0_12 |
| 189 | + @LBB0_13: |
| 190 | + ret |
| 191 | +end; |
| 192 | + |
| 193 | +const |
| 194 | + Prime1 = 2654435761; |
| 195 | + Prime2 = 2246822519; |
| 196 | + Prime3 = 3266489917; |
| 197 | + Prime4 = 668265263; |
| 198 | + Prime5 = 374761393; |
| 199 | + |
| 200 | +function xxHashStep(V, D: U32): U32; inline; |
| 201 | +begin |
| 202 | + V := V + (D * Prime2); |
| 203 | + V := (V shl 13) or (V shr (32 - 13)); |
| 204 | + V := V * Prime1; |
| 205 | + Result := V; |
| 206 | +end; |
| 207 | + |
| 208 | +function xxHash(P: PByte; L: U32): U32; |
| 209 | +var |
| 210 | + I, J: Ind; |
| 211 | + V1, V2, V3, V4: U32; |
| 212 | +begin |
| 213 | + if L >= 16 then |
| 214 | + begin |
| 215 | + V1 := Prime1 + Prime2; |
| 216 | + V2 := Prime2; |
| 217 | + V3 := 0; |
| 218 | + V4 := Prime1; |
| 219 | + |
| 220 | + for I := 0 to (L shr 4) - 1 do |
| 221 | + begin |
| 222 | + V1 := xxHashStep(V1, PU32(P)[0]); |
| 223 | + V2 := xxHashStep(V2, PU32(P)[1]); |
| 224 | + V3 := xxHashStep(V3, PU32(P)[2]); |
| 225 | + V4 := xxHashStep(V4, PU32(P)[3]); |
| 226 | + P += 16; |
| 227 | + end; |
| 228 | + |
| 229 | + Result := ((V1 shl 1) or (V1 shr (32 - 1))) + ((V2 shl 7) or (V2 shr (32 - 7))) + |
| 230 | + ((V3 shl 12) or (V3 shr (32 - 12))) + ((V4 shl 18) or (V4 shr (32 - 18))); |
| 231 | + L := L and 15; |
| 232 | + end |
| 233 | + else |
| 234 | + Result := Prime5; |
| 235 | + |
| 236 | + Result += L; |
| 237 | + |
| 238 | + while L >= 4 do |
| 239 | + begin |
| 240 | + Result += PU32(P)^ * Prime3; |
| 241 | + Result := ((Result shl 17) or (Result shr (32 - 17))) * Prime4; |
| 242 | + P += 4; |
| 243 | + L -= 4; |
| 244 | + end; |
| 245 | + |
| 246 | + while L > 0 do |
| 247 | + begin |
| 248 | + Result += P^ * Prime5; |
| 249 | + Result := ((Result shl 11) or (Result shr (32 - 11))) * Prime1; |
| 250 | + P += 1; |
| 251 | + L -= 1; |
| 252 | + end; |
| 253 | + |
| 254 | + Result := Result xor (Result shr 15); |
| 255 | + Result := Result * Prime2; |
| 256 | + Result := Result xor (Result shr 13); |
| 257 | + Result := Result * Prime3; |
| 258 | + Result := Result xor (Result shr 16); |
| 259 | +end; |
| 260 | + |
| 261 | +end. |
0 commit comments