Skip to content

Instantly share code, notes, and snippets.

@OneOfOne
Last active August 29, 2015 14:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save OneOfOne/fdab6439ea89871e0769 to your computer and use it in GitHub Desktop.
Save OneOfOne/fdab6439ea89871e0769 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"unsafe"
)
//#include "xxhash_9p.c"
//import "C" //uncomment this and comment the next line for the cgo version
func XXH32_test(in unsafe.Pointer, l uint32, seed uint32) uint32
const (
prime32_1 = 2654435761
prime32_2 = 2246822519
prime32_3 = 3266489917
prime32_4 = 668265263
prime32_5 = 374761393
)
func readU32(b []byte) uint32 {
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
}
func rotl32(x, r uint32) uint32 {
return ((x << r) | (x >> (32 - r)))
}
func GoXXH32(in []byte, seed uint32) (h uint32) {
var i int
if len(in) >= 16 {
var (
limit = len(in) - 16
v1 = seed + prime32_1 + prime32_2
v2 = seed + prime32_2
v3 = seed + 0
v4 = seed - prime32_1
)
for i = 0; i <= limit; {
v1 += readU32(in[i:]) * prime32_2
v1 = rotl32(v1, 13)
v1 *= prime32_1
i += 4
v2 += readU32(in[i:]) * prime32_2
v2 = rotl32(v2, 13)
v2 *= prime32_1
i += 4
v3 += readU32(in[i:]) * prime32_2
v3 = rotl32(v3, 13)
v3 *= prime32_1
i += 4
v4 += readU32(in[i:]) * prime32_2
v4 = rotl32(v4, 13)
v4 *= prime32_1
i += 4
}
h = rotl32(v1, 1) + rotl32(v2, 7) + rotl32(v3, 12) + rotl32(v4, 18)
} else {
h = seed + prime32_5
}
h += uint32(len(in))
for ; i <= len(in)-4; i += 4 {
h += readU32(in[i:]) * prime32_3
h = rotl32(h, 17) * prime32_4
//this might blow without i += 4
}
for ; i < len(in); i++ {
h += uint32(in[i]) * prime32_5
h = rotl32(h, 11) * prime32_1
}
h ^= h >> 15
h *= prime32_2
h ^= h >> 13
h *= prime32_3
h ^= h >> 16
return
}
func main() {
b := []byte("ABCDEFGLAALSDLSD:LSDL:DL:DL:SDL:SL:DSL:DL:DSL:DL:{W{EOQWExzghp[[p")
fmt.Println(XXH32_test(unsafe.Pointer(&b[0]), uint32(len(b)), 0)) //uncomment this and comment the next line for the cgo version
//fmt.Println(C.XXH32_test(unsafe.Pointer(&b[0]), C.uint(len(b)), 0))
fmt.Println(GoXXH32(b, 0)) //this is tested against the C implementation and it's the right hash.
}
/*
xxHash - Fast Hash algorithm
Copyright (C) 2012-2014, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
attempt to port to native 9p C by OneOfOne
*/
#define PRIME32_1 2654435761U
#define PRIME32_2 2246822519U
#define PRIME32_3 3266489917U
#define PRIME32_4 668265263U
#define PRIME32_5 374761393U
#define U32 unsigned int
typedef struct _U32_S { U32 v; } U32_S;
#define A32(x) (((U32_S *)(x))->v)
U32 ·XXH32_test(const void* input, U32 len, U32 seed) {
//static U32 XXH32_test(const void* input, U32 len, U32 seed) {
const char* p = (const char*)input;
const char* bEnd = p + len;
U32 h32;
#define XXH_get32bits(p) A32(p)
#define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))
if (len>=16) {
const char* const limit = bEnd - 16;
U32 v1 = seed + PRIME32_1 + PRIME32_2;
U32 v2 = seed + PRIME32_2;
U32 v3 = seed + 0;
U32 v4 = seed - PRIME32_1;
do
{
v1 += XXH_get32bits(p) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4;
v2 += XXH_get32bits(p) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4;
v3 += XXH_get32bits(p) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4;
v4 += XXH_get32bits(p) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4;
} while (p<=limit);
h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
}
else
{
h32 = seed + PRIME32_5;
}
h32 += (unsigned long) len;
while (p<=bEnd-4) {
h32 += XXH_get32bits(p) * PRIME32_3;
h32 = XXH_rotl32(h32, 17) * PRIME32_4 ;
p+=4;
}
while (p<bEnd) {
h32 += (*p) * PRIME32_5;
h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
p++;
}
h32 ^= h32 >> 15;
h32 *= PRIME32_2;
h32 ^= h32 >> 13;
h32 *= PRIME32_3;
h32 ^= h32 >> 16;
return h32;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment