Package xxhash implements the 64-bit variant of xxHash (XXH64) as described at http://cyan4973.github.io/xxHash/.
package xxhash

import (
	
	
	
)

const (
	prime1 uint64 = 11400714785074694791
	prime2 uint64 = 14029467366897019727
	prime3 uint64 = 1609587929392839161
	prime4 uint64 = 9650029242287828579
	prime5 uint64 = 2870177450012600261
)
NOTE(caleb): I'm using both consts and vars of the primes. Using consts where possible in the Go code is worth a small (but measurable) performance boost by avoiding some MOVQs. Vars are needed for the asm and also are useful for convenience in the Go code in a few places where we need to intentionally avoid constant arithmetic (e.g., v1 := prime1 + prime2 fails because the result overflows a uint64).
Digest implements hash.Hash64.
type Digest struct {
	v1    uint64
	v2    uint64
	v3    uint64
	v4    uint64
	total uint64
	mem   [32]byte
	n     int // how much of mem is used
}
New creates a new Digest that computes the 64-bit xxHash algorithm.
func () *Digest {
	var  Digest
	.Reset()
	return &
}
Reset clears the Digest's state so that it can be reused.
func ( *Digest) () {
	.v1 = prime1v + prime2
	.v2 = prime2
	.v3 = 0
	.v4 = -prime1v
	.total = 0
	.n = 0
}
Size always returns 8 bytes.
func ( *Digest) () int { return 8 }
BlockSize always returns 32 bytes.
func ( *Digest) () int { return 32 }
Write adds more data to d. It always returns len(b), nil.
func ( *Digest) ( []byte) ( int,  error) {
	 = len()
	.total += uint64()

This new data doesn't even fill the current block.
		copy(.mem[.n:], )
		.n += 
		return
	}

Finish off the partial block.
		copy(.mem[.n:], )
		.v1 = round(.v1, u64(.mem[0:8]))
		.v2 = round(.v2, u64(.mem[8:16]))
		.v3 = round(.v3, u64(.mem[16:24]))
		.v4 = round(.v4, u64(.mem[24:32]))
		 = [32-.n:]
		.n = 0
	}

One or more full blocks left.
		 := writeBlocks(, )
		 = [:]
	}
Store any remaining partial block.
	copy(.mem[:], )
	.n = len()

	return
}
Sum appends the current hash to b and returns the resulting slice.
func ( *Digest) ( []byte) []byte {
	 := .Sum64()
	return append(
		,
		byte(>>56),
		byte(>>48),
		byte(>>40),
		byte(>>32),
		byte(>>24),
		byte(>>16),
		byte(>>8),
		byte(),
	)
}
Sum64 returns the current hash.
func ( *Digest) () uint64 {
	var  uint64

	if .total >= 32 {
		, , ,  := .v1, .v2, .v3, .v4
		 = rol1() + rol7() + rol12() + rol18()
		 = mergeRound(, )
		 = mergeRound(, )
		 = mergeRound(, )
		 = mergeRound(, )
	} else {
		 = .v3 + prime5
	}

	 += .total

	,  := 0, .n
	for ; +8 <= ;  += 8 {
		 := round(0, u64(.mem[:+8]))
		 ^= 
		 = rol27()*prime1 + prime4
	}
	if +4 <=  {
		 ^= uint64(u32(.mem[:+4])) * prime1
		 = rol23()*prime2 + prime3
		 += 4
	}
	for  <  {
		 ^= uint64(.mem[]) * prime5
		 = rol11() * prime1
		++
	}

	 ^=  >> 33
	 *= prime2
	 ^=  >> 29
	 *= prime3
	 ^=  >> 32

	return 
}

const (
	magic         = "xxh\x06"
	marshaledSize = len(magic) + 8*5 + 32
)
MarshalBinary implements the encoding.BinaryMarshaler interface.
func ( *Digest) () ([]byte, error) {
	 := make([]byte, 0, marshaledSize)
	 = append(, magic...)
	 = appendUint64(, .v1)
	 = appendUint64(, .v2)
	 = appendUint64(, .v3)
	 = appendUint64(, .v4)
	 = appendUint64(, .total)
	 = append(, .mem[:.n]...)
	 = [:len()+len(.mem)-.n]
	return , nil
}
UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
func ( *Digest) ( []byte) error {
	if len() < len(magic) || string([:len(magic)]) != magic {
		return errors.New("xxhash: invalid hash state identifier")
	}
	if len() != marshaledSize {
		return errors.New("xxhash: invalid hash state size")
	}
	 = [len(magic):]
	, .v1 = consumeUint64()
	, .v2 = consumeUint64()
	, .v3 = consumeUint64()
	, .v4 = consumeUint64()
	, .total = consumeUint64()
	copy(.mem[:], )
	 = [len(.mem):]
	.n = int(.total % uint64(len(.mem)))
	return nil
}

func ( []byte,  uint64) []byte {
	var  [8]byte
	binary.LittleEndian.PutUint64([:], )
	return append(, [:]...)
}

func ( []byte) ([]byte, uint64) {
	 := u64()
	return [8:], 
}

func ( []byte) uint64 { return binary.LittleEndian.Uint64() }
func ( []byte) uint32 { return binary.LittleEndian.Uint32() }

func (,  uint64) uint64 {
	 +=  * prime2
	 = rol31()
	 *= prime1
	return 
}

func (,  uint64) uint64 {
	 = round(0, )
	 ^= 
	 = *prime1 + prime4
	return 
}

func ( uint64) uint64  { return bits.RotateLeft64(, 1) }
func ( uint64) uint64  { return bits.RotateLeft64(, 7) }
func ( uint64) uint64 { return bits.RotateLeft64(, 11) }
func ( uint64) uint64 { return bits.RotateLeft64(, 12) }
func ( uint64) uint64 { return bits.RotateLeft64(, 18) }
func ( uint64) uint64 { return bits.RotateLeft64(, 23) }
func ( uint64) uint64 { return bits.RotateLeft64(, 27) }