// Copyright © 2014 Lawrence E. Bakst. All rights reserved.

// This package contains various transliteration of Jenkins hash funcions.
// This includes lookup3.c and some other Jenkins functions that appear to be based on lookup2.c.
// See http://burtleburtle.net/bob/c/lookup3.c and http://burtleburtle.net/bob/hash/evahash.html

package jenkins

import (
	"fmt"
	"hash"
	"leb.io/hashland/nhash"
	"unsafe"
)

// Make sure interfaces are correctly implemented. Stolen from another implementation.
// I did something similar in another package to verify the interface but didn't know you could elide the variable in a var.
// What a cute wart it is.
var (
	//_ hash.Hash   = new(Digest)
	_ hash.Hash32   = new(State332c)
	_ nhash.HashF32 = new(State332c)
)

/*
uint32_t jenkins_one_at_a_time_hash(char *key, size_t len)
{
    uint32_t hash, i;
    for(hash = i = 0; i < len; ++i)
    {
        hash += key[i];
        hash += (hash << 10);
        hash ^= (hash >> 6);
    }
    hash += (hash << 3);
    hash ^= (hash >> 11);
    hash += (hash << 15);
    return hash;
}
*/

// This function mixes the state
func mix32(a, b, c uint32) (uint32, uint32, uint32) {
	a = a - b
	a = a - c
	a = a ^ (c >> 13)
	b = b - c
	b = b - a
	b = b ^ (a << 8)
	c = c - a
	c = c - b
	c = c ^ (b >> 13)
	a = a - b
	a = a - c
	a = a ^ (c >> 12)
	b = b - c
	b = b - a
	b = b ^ (a << 16)
	c = c - a
	c = c - b
	c = c ^ (b >> 5)
	a = a - b
	a = a - c
	a = a ^ (c >> 3)
	b = b - c
	b = b - a
	b = b ^ (a << 10)
	c = c - a
	c = c - b
	c = c ^ (b >> 15)
	return a, b, c
}

func mix32a(a, b, c uint32) (uint32, uint32, uint32) {
	a = a - b - c ^ (c >> 13)
	b = b - c - a ^ (a << 8)
	c = c - a - b ^ (b >> 13)
	a = a - b - c ^ (c >> 12)
	b = b - c - a ^ (a << 16)
	c = c - a - b ^ (b >> 5)
	a = a - b - c ^ (c >> 3)
	b = b - c - a ^ (a << 10)
	c = c - a - b ^ (b >> 15)
	return a, b, c
}

func Check() {
	var a, b, c uint32
	var init = func() {
		a, b, c = 0x12345678, 0x87654321, 0xdeadbeef
	}

	init()
	a = a - b
	a = a - c
	fmt.Printf("a=0x%08x\n", a)
	a = a ^ (c >> 13)
	fmt.Printf("a=0x%08x\n", a)
	fmt.Printf("a=0x%08x, b=0x%08x, c=0x%08x\n", a, b, c)
	init()
	a = ((a - b) - c)
	fmt.Printf("a=0x%08x\n", a)
	a = a ^ (c >> 13)
	fmt.Printf("a=0x%08x\n", a)
	fmt.Printf("a=0x%08x, b=0x%08x, c=0x%08x\n", a, b, c)
}

// This makes a new slice of uint64 that points to the same slice passed in as []byte.
// We should check alignment for architectures that don't handle unaligned reads.
// Fallback to a copy or maybe use encoding/binary?
// Not sure what the right thing to do is for little vs big endian?
// What are the right test vevtors for big-endian machines.
func sliceUI32(in []byte) []uint32 {
	return (*(*[]uint32)(unsafe.Pointer(&in)))[:len(in)/4]
}

// Jenkin's second generation 32 bit hash.
// Benchmarked with 4 byte key, inlining, and no store of hash at:
// benchmark32: 55 Mhashes/sec
// benchmark32: 219 MB/sec
func Hash232(k []byte, seed uint32) uint32 {
	var fast = true // fast is really much faster
	l := uint32(len(k))
	a := uint32(0x9e3779b9) // the golden ratio; an arbitrary value
	b := a
	c := seed // variable initialization of internal state

	if fast {
		k32 := sliceUI32(k)
		cnt := 0
		for ; l >= 12; l -= 12 {
			a += k32[0+cnt]
			b += k32[1+cnt]
			c += k32[2+cnt]
			a, b, c = mix32(a, b, c)
			k = k[12:]
			cnt += 3
		}
	} else {
		for ; l >= 12; l -= 12 {
			a += uint32(k[0]) + uint32(k[1])<<8 + uint32(k[2])<<16 + uint32(k[3])<<24
			b += uint32(k[4]) + uint32(k[5])<<8 + uint32(k[6])<<16 + uint32(k[7])<<24
			c += uint32(k[8]) + uint32(k[9])<<8 + uint32(k[10])<<16 + uint32(k[11])<<24
			a, b, c = mix32(a, b, c)
			k = k[12:]
		}
	}

	c += l
	switch l {
	case 11:
		c += uint32(k[10]) << 24
		fallthrough
	case 10:
		c += uint32(k[9]) << 16
		fallthrough
	case 9:
		c += uint32(k[8]) << 8
		fallthrough
	case 8:
		b += uint32(k[7]) << 24 // the first byte of c is reserved for the length
		fallthrough
	case 7:
		b += uint32(k[6]) << 16
		fallthrough
	case 6:
		b += uint32(k[5]) << 8
		fallthrough
	case 5:
		b += uint32(k[4])
		fallthrough
	case 4:
		a += uint32(k[3]) << 24
		fallthrough
	case 3:
		a += uint32(k[2]) << 16
		fallthrough
	case 2:
		a += uint32(k[1]) << 8
		fallthrough
	case 1:
		c += uint32(k[0])
		fallthrough
	case 0:
		break
	default:
		panic("HashWords32")
	}
	a, b, c = mix32(a, b, c)
	return c
}

// original mix function
func mix64(a, b, c uint64) (uint64, uint64, uint64) {
	a = a - b
	a = a - c
	a = a ^ (c >> 43)
	b = b - c
	b = b - a
	b = b ^ (a << 9)
	c = c - a
	c = c - b
	c = c ^ (b >> 8)
	a = a - b
	a = a - c
	a = a ^ (c >> 38)
	b = b - c
	b = b - a
	b = b ^ (a << 23)
	c = c - a
	c = c - b
	c = c ^ (b >> 5)
	a = a - b
	a = a - c
	a = a ^ (c >> 35)
	b = b - c
	b = b - a
	b = b ^ (a << 49)
	c = c - a
	c = c - b
	c = c ^ (b >> 11)
	a = a - b
	a = a - c
	a = a ^ (c >> 12)
	b = b - c
	b = b - a
	b = b ^ (a << 18)
	c = c - a
	c = c - b
	c = c ^ (b >> 22)
	return a, b, c
}

// restated mix function better for gofmt
func mix64alt(a, b, c uint64) (uint64, uint64, uint64) {
	a -= b - c ^ (c >> 43)
	b -= c - a ^ (a << 9)
	c -= a - b ^ (b >> 8)
	a -= b - c ^ (c >> 38)
	b -= c - a ^ (a << 23)
	c -= a - b ^ (b >> 5)
	a -= b - c ^ (c >> 35)
	b -= c - a ^ (a << 49)
	c -= a - b ^ (b >> 11)
	a -= b - c ^ (c >> 12)
	b -= c - a ^ (a << 18)
	c -= a - b ^ (b >> 22)
	return a, b, c
}

// the following functions can be inlined
func mix64a(a, b, c uint64) (uint64, uint64, uint64) {
	a -= b - c ^ (c >> 43)
	b -= c - a ^ (a << 9)
	return a, b, c
}

func mix64b(a, b, c uint64) (uint64, uint64, uint64) {
	c -= a - b ^ (b >> 8)
	a -= b - c ^ (c >> 38)
	return a, b, c
}

func mix64c(a, b, c uint64) (uint64, uint64, uint64) {
	b -= c - a ^ (a << 23)
	c -= a - b ^ (b >> 5)
	return a, b, c
}

func mix64d(a, b, c uint64) (uint64, uint64, uint64) {
	a -= b - c ^ (c >> 35)
	b -= c - a ^ (a << 49)
	return a, b, c
}

func mix64e(a, b, c uint64) (uint64, uint64, uint64) {
	c -= a - b ^ (b >> 11)
	a -= b - c ^ (c >> 12)
	return a, b, c
}

func mix64f(a, b, c uint64) (uint64, uint64, uint64) {
	b -= c - a ^ (a << 18)
	c -= a - b ^ (b >> 22)
	return a, b, c
}

// This makes a new slice of uint64 that points to the same slice passed in as []byte.
// We should check alignment for architectures that don't handle unaligned reads.
// Fallback to a copy or maybe use encoding/binary?
// Not sure what the right thing to do is for little vs big endian?
// What are the right test vevtors for big-endian machines.
func sliceUI64(in []byte) []uint64 {
	return (*(*[]uint64)(unsafe.Pointer(&in)))[:len(in)/8]
}

// Jenkin's second generation 64 bit hash.
// Benchmarked with 24 byte key, inlining, store of hash in memory (cache miss every 4 hashes) and fast=true at:
// benchmark64: 26 Mhashes/sec
// benchmark64: 623 MB/sec
func Hash264(k []byte, seed uint64) uint64 {
	var fast = true // fast is really much faster
	//fmt.Printf("k=%v\n", k)
	//fmt.Printf("length=%d, len(k)=%d\n", length, len(k))

	//The 64-bit golden ratio is 0x9e3779b97f4a7c13LL
	length := uint64(len(k))
	a := uint64(0x9e3779b97f4a7c13)
	b := a
	c := seed
	if fast {
		k64 := sliceUI64(k)
		cnt := 0
		for i := length; i >= 24; i -= 24 {
			a += k64[0+cnt]
			b += k64[1+cnt]
			c += k64[2+cnt]
			// inlining is slightly faster
			a, b, c = mix64a(a, b, c)
			a, b, c = mix64b(a, b, c)
			a, b, c = mix64c(a, b, c)
			a, b, c = mix64d(a, b, c)
			a, b, c = mix64e(a, b, c)
			a, b, c = mix64f(a, b, c)
			k = k[24:]
			cnt += 3
			length -= 24
		}
	} else {
		for i := length; i >= 24; i -= 24 {
			a += uint64(k[0]) | uint64(k[1])<<8 | uint64(k[2])<<16 | uint64(k[3])<<24 | uint64(k[4])<<32 | uint64(k[5])<<40 | uint64(k[6])<<48 | uint64(k[7])<<56
			b += uint64(k[8]) | uint64(k[9])<<8 | uint64(k[10])<<16 | uint64(k[11])<<24 | uint64(k[12])<<32 | uint64(k[13])<<40 | uint64(k[14])<<48 | uint64(k[15])<<56
			c += uint64(k[16]) | uint64(k[17])<<8 | uint64(k[18])<<16 | uint64(k[19])<<24 | uint64(k[20])<<32 | uint64(k[21])<<40 | uint64(k[22])<<48 | uint64(k[23])<<56
			a, b, c = mix64alt(a, b, c)
			k = k[24:]
			length -= 24
		}
	}
	c += length
	if len(k) > 23 {
		panic("Hash264")
	}
	switch length {
	case 23:
		c += uint64(k[22]) << 56
		fallthrough
	case 22:
		c += uint64(k[21]) << 48
		fallthrough
	case 21:
		c += uint64(k[20]) << 40
		fallthrough
	case 20:
		c += uint64(k[19]) << 32
		fallthrough
	case 19:
		c += uint64(k[18]) << 24
		fallthrough
	case 18:
		c += uint64(k[17]) << 16
		fallthrough
	case 17:
		c += uint64(k[16]) << 8
		fallthrough
	case 16:
		b += uint64(k[15]) << 56 // the first byte of c is reserved for the length
		fallthrough
	case 15:
		b += uint64(k[14]) << 48
		fallthrough
	case 14:
		b += uint64(k[13]) << 40
		fallthrough
	case 13:
		b += uint64(k[12]) << 32
		fallthrough
	case 12:
		b += uint64(k[11]) << 24
		fallthrough
	case 11:
		b += uint64(k[10]) << 16
		fallthrough
	case 10:
		b += uint64(k[9]) << 8
		fallthrough
	case 9:
		b += uint64(k[8])
		fallthrough
	case 8:
		a += uint64(k[7]) << 56
		fallthrough
	case 7:
		a += uint64(k[6]) << 48
		fallthrough
	case 6:
		a += uint64(k[5]) << 40
		fallthrough
	case 5:
		a += uint64(k[4]) << 32
		fallthrough
	case 4:
		a += uint64(k[3]) << 24
		fallthrough
	case 3:
		a += uint64(k[2]) << 16
		fallthrough
	case 2:
		a += uint64(k[1]) << 8
		fallthrough
	case 1:
		a += uint64(k[0])
	case 0:
		break
	default:
		panic("HashWords64")
	}
	a, b, c = mix64alt(a, b, c)
	return c
}

/*
func omix(a, b, c uint32) (uint32, uint32, uint32) {
	a -= c;  a ^= rot(c, 4);  c += b;
	b -= a;  b ^= rot(a, 6);  a += c;
	c -= b;  c ^= rot(b, 8);  b += a;
	a -= c;  a ^= rot(c,16);  c += b;
	b -= a;  b ^= rot(a,19);  a += c;
	c -= b;  c ^= rot(b, 4);  b += a;
	return a, b, c
}

func ofinal(a, b, c uint32) (uint32, uint32, uint32) {
	c ^= b; c -= rot(b,14);
	a ^= c; a -= rot(c,11);
	b ^= a; b -= rot(a,25);
	c ^= b; c -= rot(b,16);
	a ^= c; a -= rot(c,4);
	b ^= a; b -= rot(a,14);
	c ^= b; c -= rot(b,24);
	return a, b, c
}


func mix(a, b, c uint32) (uint32, uint32, uint32) {
	a -= c;  a ^= c << 4 | c >> (32 - 4);  c += b;
	b -= a;  b ^= a << 6 | a >> (32 - 6);  a += c;
	c -= b;  c ^= b << 8 | b >> (32 - 8);  b += a;
	a -= c;  a ^= c << 16 | c >> (32 - 16);  c += b;
	b -= a;  b ^= a << 19 | a >> (32 - 19);  a += c;
	c -= b;  c ^= b << 4 | b >> (32 - 4);  b += a;
	return a, b, c
}


func final(a, b, c uint32) (uint32, uint32, uint32) {
	c ^= b; c -= b << 14 | b >> (32 - 14);
	a ^= c; a -= c << 11 | c >> (32 - 11);
	b ^= a; b -= a << 25 | a >> (32 - 25);
	c ^= b; c -= b << 16 | b >> (32 - 16);
	a ^= c; a -= c << 4 | c >> (32 - 4);
	b ^= a; b -= a << 14 | a >> (32 - 14);
	c ^= b; c -= b << 24 | b >> (32 - 24);
	return a, b, c
}
*/

//var a, b, c uint32

func rot(x, k uint32) uint32 {
	return x<<k | x>>(32-k)
}

// current gc compilers can't inline long functions so we have to split mix into 2
func mix1(a, b, c uint32) (uint32, uint32, uint32) {
	a -= c
	a ^= rot(c, 4)
	c += b
	b -= a
	b ^= rot(a, 6)
	a += c
	c -= b
	c ^= rot(b, 8)
	b += a
	//a -= c;  a ^= c << 4 | c >> (32 - 4);  c += b;
	//b -= a;  b ^= a << 6 | a >> (32 - 6);  a += c;
	return a, b, c
}

func mix2(a, b, c uint32) (uint32, uint32, uint32) {
	a -= c
	a ^= rot(c, 16)
	c += b
	b -= a
	b ^= rot(a, 19)
	a += c
	c -= b
	c ^= rot(b, 4)
	b += a
	//	c -= b;  c ^= b << 8 | b >> (32 - 8);  b += a;
	//	a -= c;  a ^= c << 16 | c >> (32 - 16);  c += b;
	return a, b, c
}

/*
func mix3(a, b, c uint32) (uint32, uint32, uint32) {
	b -= a;  b ^= a << 19 | a >> (32 - 19);  a += c;
	c -= b;  c ^= b << 4 | b >> (32 - 4);  b += a;
	return a, b, c
}
*/

func final1(a, b, c uint32) (uint32, uint32, uint32) {
	c ^= b
	c -= rot(b, 14)
	a ^= c
	a -= rot(c, 11)
	b ^= a
	b -= rot(a, 25)
	c ^= b
	c -= rot(b, 16)
	//c ^= b; c -= b << 14 | b >> (32 - 14);
	//a ^= c; a -= c << 11 | c >> (32 - 11);
	//b ^= a; b -= a << 25 | a >> (32 - 25);
	//c ^= b; c -= b << 16 | b >> (32 - 16);
	return a, b, c
}

func final2(a, b, c uint32) (uint32, uint32, uint32) {
	a ^= c
	a -= rot(c, 4)
	b ^= a
	b -= rot(a, 14)
	c ^= b
	c -= rot(b, 24)
	//a ^= c; a -= c << 4 | c >> (32 - 4);
	//b ^= a; b -= a << 14 | a >> (32 - 14);
	//c ^= b; c -= b << 24 | b >> (32 - 24);
	return a, b, c
}

func HashWords332(k []uint32, seed uint32) uint32 {
	var a, b, c uint32

	length := uint32(len(k))
	a = 0xdeadbeef + length<<2 + seed
	b, c = a, a

	i := 0
	for ; length > 3; length -= 3 {
		a += k[i+0]
		b += k[i+1]
		c += k[i+2]
		a, b, c = mix1(a, b, c)
		a, b, c = mix2(a, b, c)
		i += 3
	}

	switch length {
	case 3:
		c += k[i+2]
		fallthrough
	case 2:
		b += k[i+1]
		fallthrough
	case 1:
		a += k[i+0]
		a, b, c = final1(a, b, c)
		a, b, c = final2(a, b, c)
	case 0:
		break
	}
	return c
}

func HashWordsLen(k []uint32, length int, seed uint32) uint32 {
	var a, b, c uint32

	//fmt.Printf("k=%v\n", k)
	//fmt.Printf("length=%d, len(k)=%d\n", length, len(k))
	if length > len(k)*4 {
		fmt.Printf("length=%d, len(k)=%d\n", length, len(k))
		panic("HashWords")
	}

	ul := uint32(len(k))
	a = 0xdeadbeef + ul<<2 + seed
	b, c = a, a

	i := 0
	//length := 0
	for ; length > 3; length -= 3 {
		a += k[i+0]
		b += k[i+1]
		c += k[i+2]
		a, b, c = mix1(a, b, c)
		a, b, c = mix2(a, b, c)
		//a, b, c = mix3(a, b, c)
		i += 3
	}

	//fmt.Printf("remaining length=%d, len(k)=%d, i=%d, k[i + 2]=%d, k[i + 1]=%d, k[i + 0]=%d\n", length, len(k), i, k[i + 2], k[i + 1], k[i + 0])
	switch length {
	case 3:
		c += k[i+2]
		fallthrough
	case 2:
		b += k[i+1]
		fallthrough
	case 1:
		a += k[i+0]
		a, b, c = final1(a, b, c)
		a, b, c = final2(a, b, c)
	case 0:
		break
	}
	//fmt.Printf("end\n")
	return c
}

// This is an example of how I could like to code hash functions like this.
// Using closures over the state and expecting thme to be inlined
func XHashWords(k []uint32, length int, seed uint32) uint32 {
	var a, b, c uint32
	var rot = func(x, k uint32) uint32 {
		return x<<k | x>>(32-k)
	}
	var mix = func() {
		a -= c
		a ^= rot(c, 4)
		c += b
		b -= a
		b ^= rot(a, 6)
		a += c
		c -= b
		c ^= rot(b, 8)
		b += a
		a -= c
		a ^= rot(c, 16)
		c += b
		b -= a
		b ^= rot(a, 19)
		a += c
		c -= b
		c ^= rot(b, 4)
		b += a
	}
	var final = func() {
		c ^= b
		c -= rot(b, 14)
		a ^= c
		a -= rot(c, 11)
		b ^= a
		b -= rot(a, 25)
		c ^= b
		c -= rot(b, 16)
		a ^= c
		a -= rot(c, 4)
		b ^= a
		b -= rot(a, 14)
		c ^= b
		c -= rot(b, 24)
	}
	ul := uint32(len(k))
	a = 0xdeadbeef + ul<<2 + seed
	b, c = a, a

	i := 0
	//length := 0
	for length = len(k); length > 3; length -= 3 {
		a += k[i+0]
		b += k[i+1]
		c += k[i+2]
		mix()
		i += 3
	}

	switch length {
	case 3:
		c += k[i+2]
		fallthrough
	case 2:
		b += k[i+1]
		fallthrough
	case 1:
		a += k[i+0]
		final()
	case 0:
		break
	}
	return c
}

// jenkins364: return 2 32-bit hash values.
// Returns two 32-bit hash values instead of just one.
// This is good enough for hash table lookup with 2^^64 buckets,
// or if you want a second hash if you're not happy with the first,
// or if you want a probably-unique 64-bit ID for the key.
// *pc is better mixed than *pb, so use *pc first.
// If you want a 64-bit value do something like "*pc + (((uint64_t)*pb)<<32)"
func Jenkins364(k []byte, length int, pc, pb uint32) (rpc, rpb uint32) {
	var a, b, c uint32

	//fmt.Printf("Jenkins364: k=%v, len(k)=%d\n", k, len(k))
	if length == 0 {
		length = len(k)
	}
	/*
		var rot = func(x, k uint32) uint32 {
			return x << k | x >> (32 - k)
		}

		var mix = func() {
			a -= c;  a ^= rot(c, 4); c += b;
			b -= a;  b ^= rot(a, 6);  a += c;
			c -= b;  c ^= rot(b, 8);  b += a;
			a -= c;  a ^= rot(c,16);  c += b;
			b -= a;  b ^= rot(a,19);  a += c;
			c -= b;  c ^= rot(b, 4);  b += a;
		}
		var final = func() {
			c ^= b; c -= rot(b,14);
			a ^= c; a -= rot(c,11);
			b ^= a; b -= rot(a,25);
			c ^= b; c -= rot(b,16);
			a ^= c; a -= rot(c,4);
			b ^= a; b -= rot(a,14);
			c ^= b; c -= rot(b,24);
		}
	*/
	ul := uint32(len(k))

	/* Set up the internal state */
	a = 0xdeadbeef + ul + pc
	b, c = a, a
	c += pb

	for ; length > 12; length -= 12 {
		//fmt.Printf("k=%q, length=%d\n", k, length)
		a += *(*uint32)(unsafe.Pointer(&k[0]))
		b += *(*uint32)(unsafe.Pointer(&k[4]))
		c += *(*uint32)(unsafe.Pointer(&k[8]))
		a, b, c = mix1(a, b, c)
		a, b, c = mix2(a, b, c)
		k = k[12:]
	}
	//fmt.Printf("k=%q, length=%d\n", k, length)

	/* handle the last (probably partial) block */
	/*
	 * "k[2]&0xffffff" actually reads beyond the end of the string, but
	 * then masks off the part it's not allowed to read.  Because the
	 * string is aligned, the masked-off tail is in the same word as the
	 * rest of the string.  Every machine with memory protection I've seen
	 * does it on word boundaries, so is OK with this.  But VALGRIND will
	 * still catch it and complain.  The masking trick does make the hash
	 * noticably faster for short strings (like English words).
	 */

	//fmt.Printf("length now=%d\n", length)
	switch length {
	case 12:
		a += *(*uint32)(unsafe.Pointer(&k[0]))
		b += *(*uint32)(unsafe.Pointer(&k[4]))
		c += *(*uint32)(unsafe.Pointer(&k[8]))
	case 11:
		c += uint32(k[10]) << 16
		fallthrough
	case 10:
		c += uint32(k[9]) << 8
		fallthrough
	case 9:
		c += uint32(k[8])
		fallthrough
	case 8:
		a += *(*uint32)(unsafe.Pointer(&k[0]))
		b += *(*uint32)(unsafe.Pointer(&k[4]))
		break
	case 7:
		b += uint32(k[6]) << 16
		fallthrough
	case 6:
		b += uint32(k[5]) << 8
		fallthrough
	case 5:
		b += uint32(k[4])
		fallthrough
	case 4:
		a += *(*uint32)(unsafe.Pointer(&k[0]))
		break
	case 3:
		a += uint32(k[2]) << 16
		fallthrough
	case 2:
		a += uint32(k[1]) << 8
		fallthrough
	case 1:
		a += uint32(k[0])
		break
	case 0:
		//fmt.Printf("case 0\n")
		return c, b /* zero length strings require no mixing */
	}
	a, b, c = final1(a, b, c)
	a, b, c = final2(a, b, c)
	return c, b
}

func HashString(s string, pc, pb uint32) (rpc, rpb uint32) {
	k := ([]byte)(s)
	rpc, rpb = Jenkins364(k, len(k), pc, pb)
	return
}

func HashBytesLength(k []byte, length int, seed uint32) uint32 {
	if length > len(k) {
		fmt.Printf("len(k)=%d, length=%d\n", len(k), length)
		panic("HashBytesLength")
	}
	ret, _ := Jenkins364(k, length, seed, 0)
	return ret
}

//
// Streaming interface and new interface

type State332 struct {
	hash uint32
	seed uint32
	pc   uint32
	pb   uint32
	clen int
	tail []byte
}

type State332c struct {
	State332
}

type State332b struct {
	State332
}

type State364 struct {
	hash uint64
	seed uint64
	pc   uint32
	pb   uint32
	clen int
	tail []byte
}

type State264 struct {
	hash uint64
	seed uint64
}

type State232 struct {
	hash uint32
	seed uint32
	clen int
	tail []byte
}

// const Size = 4

// Sum32 returns the 32 bit hash of data given the seed.
// This is code is what I started with before I added the hash.Hash and hash.Hash32 interfaces.
func Sum32(data []byte, seed uint32) uint32 {
	rpc, _ := Jenkins364(data, len(data), seed, seed)
	return rpc
}

// New returns a new hash.Hash32 interface that computes a 32 bit jenkins lookup3 hash.
func New(seed uint32) hash.Hash32 {
	s := new(State332c)
	s.seed = seed
	s.Reset()
	return s
}

// New returns a new nhash.HashF32 interface that computes a 32 bit jenkins lookup3 hash.
func New332c(seed uint32) nhash.HashF32 {
	s := new(State332c)
	s.seed = seed
	s.Reset()
	return s
}

/*
func New332b(seed uint32) nhash.HashF32 {
	s := new(State332b)
	s.seed = seed
	s.Reset()
	return s
}
*/

// Return the size of the resulting hash.
func (d *State332c) Size() int { return 4 }

// Return the blocksize of the hash which in this case is 1 byte.
func (d *State332c) BlockSize() int { return 1 }

// Return the maximum number of seed bypes required. In this case 2 x 32
func (d *State332c) NumSeedBytes() int {
	return 8
}

// Return the number of bits the hash function outputs.
func (d *State332c) HashSizeInBits() int {
	return 32
}

// Reset the hash state.
func (d *State332c) Reset() {
	d.pc = d.seed
	d.pb = d.seed
	d.clen = 0
	d.tail = nil
}

// Accept a byte stream p used for calculating the hash. For now this call is lazy and the actual hash calculations take place in Sum() and Sum32().
func (d *State332c) Write(p []byte) (nn int, err error) {
	l := len(p)
	d.clen += l
	d.tail = append(d.tail, p...)
	return l, nil
}

// Return the current hash as a byte slice.
func (d *State332c) Sum(b []byte) []byte {
	d.pc, d.pb = Jenkins364(d.tail, len(d.tail), d.pc, d.pb)
	d.hash = d.pc
	h := d.hash
	return append(b, byte(h>>24), byte(h>>16), byte(h>>8), byte(h))
}

// Return the current hash as a 32 bit unsigned type.
func (d *State332c) Sum32() uint32 {
	d.pc, d.pb = Jenkins364(d.tail, len(d.tail), d.pc, d.pb)
	d.hash = d.pc
	return d.hash
}

// Given b as input and an optional 32 bit seed return the Jenkins lookup3 hash c bits.
func (d *State332c) Hash32(b []byte, seeds ...uint32) uint32 {
	//fmt.Printf("len(b)=%d, b=%x\n", len(b), b)
	/*
		switch len(seeds) {
		case 2:
			d.pb = seeds[1]
			fallthrough
		case 1:
			d.pc = seeds[0]
		default:
			d.pc, d.pb = 0, 0
		}
	*/
	d.pc, d.pb = 0, 0

	d.pc, d.pb = Jenkins364(b, len(b), d.pc, d.pb)
	d.hash = d.pc
	return d.hash
}

// ----

// changed this from HashF64 to Hash64 to get streaming functions, what did I break? 7-22-15
func New364(seed uint64) nhash.Hash64 {
	s := new(State364)
	s.seed = seed
	s.Reset()
	return s
}

// Return the size of the resulting hash.
func (d *State364) Size() int { return 8 }

// Return the blocksize of the hash which in this case is 1 byte.
func (d *State364) BlockSize() int { return 1 }

// Return the maximum number of seed bypes required. In this case 2 x 32
func (d *State364) NumSeedBytes() int {
	return 8
}

// Return the number of bits the hash function outputs.
func (d *State364) HashSizeInBits() int {
	return 64
}

// Reset the hash state.
func (d *State364) Reset() {
	d.pc = uint32(d.seed)
	d.pb = uint32(d.seed >> 32)
	d.clen = 0
	d.tail = nil
}

// Accept a byte stream p used for calculating the hash. For now this call is lazy and the actual hash calculations take place in Sum() and Sum32().
func (d *State364) Write(p []byte) (nn int, err error) {
	l := len(p)
	d.clen += l
	d.tail = append(d.tail, p...)
	return l, nil
}

// Return the current hash as a byte slice.
func (d *State364) Sum(b []byte) []byte {
	d.pc, d.pb = Jenkins364(d.tail, len(d.tail), d.pc, d.pb)
	d.hash = uint64(d.pb<<32) | uint64(d.pc)
	h := d.hash
	return append(b, byte(h>>56), byte(h>>48), byte(h>>40), byte(h>>32), byte(h>>24), byte(h>>16), byte(h>>8), byte(h))
}

func (d *State364) Write64(h uint64) (err error) {
	d.clen += 8
	d.tail = append(d.tail, byte(h>>56), byte(h>>48), byte(h>>40), byte(h>>32), byte(h>>24), byte(h>>16), byte(h>>8), byte(h))
	return nil
}

// Return the current hash as a 64 bit unsigned type.
func (d *State364) Sum64() uint64 {
	d.pc, d.pb = Jenkins364(d.tail, len(d.tail), d.pc, d.pb)
	d.hash = uint64(d.pb)<<32 | uint64(d.pc)
	return d.hash
}

func (d *State364) Hash64(b []byte, seeds ...uint64) uint64 {
	switch len(seeds) {
	case 2:
		d.pc = uint32(seeds[0])
		d.pb = uint32(seeds[1])
	case 1:
		d.pc = uint32(seeds[0])
		d.pb = uint32(seeds[0] >> 32)
	}
	d.pc, d.pb = Jenkins364(b, len(b), d.pc, d.pb)
	//fmt.Printf("pc=0x%08x, pb=0x%08x\n", d.pc, d.pb)

	// pc is better mixed than pb so pc goes in the low order bits
	d.hash = uint64(d.pb)<<32 | uint64(d.pc)
	return d.hash
}

func (d *State364) Hash64S(b []byte, seed uint64) uint64 {
	d.pc, d.pb = uint32(seed), uint32(seed>>32)
	d.pc, d.pb = Jenkins364(b, len(b), d.pc, d.pb)
	//fmt.Printf("pc=0x%08x, pb=0x%08x\n", d.pc, d.pb)

	// pc is better mixed than pb so pc goes in the low order bits
	d.hash = uint64(d.pb)<<32 | uint64(d.pc)
	return d.hash
}

// ----

// New returns a new nhash.HashF32 interface that computes a 32 bit jenkins lookup3 hash.
func New232(seed uint32) nhash.HashF32 {
	s := new(State232)
	s.seed = seed
	s.Reset()
	return s
}

// Return the size of the resulting hash.
func (s *State232) Size() int { return 4 }

// Return the blocksize of the hash which in this case is 12 bytes at a time.
func (s *State232) BlockSize() int { return 12 }

// Return the maximum number of seed bypes required.
func (s *State232) NumSeedBytes() int {
	return 4
}

// Return the number of bits the hash function outputs.
func (s *State232) HashSizeInBits() int {
	return 32
}

// Reset the hash state.
func (s *State232) Reset() {
	s.seed = 0
	s.clen = 0
	s.tail = nil
}

// Accept a byte stream p used for calculating the hash. For now this call is lazy and the actual hash calculations take place in Sum() and Sum32().
func (s *State232) Write(p []byte) (nn int, err error) {
	l := len(p)
	s.clen += l
	s.tail = append(s.tail, p...)
	return l, nil
}

// Return the current hash as a byte slice.
func (s *State232) Sum(b []byte) []byte {
	s.hash = Hash232(s.tail, s.seed)
	h := s.hash
	return append(b, byte(h>>24), byte(h>>16), byte(h>>8), byte(h))
}

// Return the current hash as a 64 bit unsigned type.
func (s *State232) Sum32() uint32 {
	s.hash = Hash232(s.tail, s.seed)
	return s.hash
}

func (s *State232) Hash32(b []byte, seeds ...uint32) uint32 {
	//	fmt.Printf("Hash32: len(b)=%d, b=%x\n", len(b), b)
	if len(seeds) > 0 {
		s.seed = 0
	}
	s.hash = Hash232(b, s.seed)
	return s.hash
}

/*
	var mix = func() {
		a -= c;  a ^= c << 4 | c >> (32 - 4);  c += b;
		b -= a;  b ^= a << 6 | a >> (32 - 6);  a += c;
		c -= b;  c ^= b << 8 | b >> (32 - 8);  b += a;
		a -= c;  a ^= c << 16 | c >> (32 - 16);  c += b;
		b -= a;  b ^= a << 19 | a >> (32 - 19);  a += c;
		c -= b;  c ^= b << 4 | b >> (32 - 4);  b += a;
	}

	var final = func() {
		c ^= b; c -= b << 14 | b >> (32 - 14);
		a ^= c; a -= c << 11 | c >> (32 - 11);
		b ^= a; b -= a << 25 | a >> (32 - 25);
		c ^= b; c -= b << 16 | b >> (32 - 16);
		a ^= c; a -= c << 4 | c >> (32 - 4);
		b ^= a; b -= a << 14 | a >> (32 - 14);
		c ^= b; c -= b << 24 | b >> (32 - 24);
	}
*/