// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Hashing algorithm inspired by
//   xxhash: https://code.google.com/p/xxhash/
// cityhash: https://code.google.com/p/cityhash/

// +build amd64 arm64 mips64 mips64le ppc64 ppc64le riscv64 s390x wasm

package runtime

import 

const (
	// Constants for multiplication: four random odd 64-bit numbers.
	m1 = 16877499708836156737
	m2 = 2820277070424839065
	m3 = 9497967016996688599
	m4 = 15839092249703872147
)

func ( unsafe.Pointer, ,  uintptr) uintptr {
	 := uint64( + *hashkey[0])
:
	switch {
	case  == 0:
	case  < 4:
		 ^= uint64(*(*byte)())
		 ^= uint64(*(*byte)(add(, >>1))) << 8
		 ^= uint64(*(*byte)(add(, -1))) << 16
		 = rotl_31(*m1) * m2
	case  <= 8:
		 ^= uint64(readUnaligned32())
		 ^= uint64(readUnaligned32(add(, -4))) << 32
		 = rotl_31(*m1) * m2
	case  <= 16:
		 ^= readUnaligned64()
		 = rotl_31(*m1) * m2
		 ^= readUnaligned64(add(, -8))
		 = rotl_31(*m1) * m2
	case  <= 32:
		 ^= readUnaligned64()
		 = rotl_31(*m1) * m2
		 ^= readUnaligned64(add(, 8))
		 = rotl_31(*m1) * m2
		 ^= readUnaligned64(add(, -16))
		 = rotl_31(*m1) * m2
		 ^= readUnaligned64(add(, -8))
		 = rotl_31(*m1) * m2
	default:
		 := 
		 := uint64( * hashkey[1])
		 := uint64( * hashkey[2])
		 := uint64( * hashkey[3])
		for  >= 32 {
			 ^= readUnaligned64()
			 = rotl_31(*m1) * m2
			 = add(, 8)
			 ^= readUnaligned64()
			 = rotl_31(*m2) * m3
			 = add(, 8)
			 ^= readUnaligned64()
			 = rotl_31(*m3) * m4
			 = add(, 8)
			 ^= readUnaligned64()
			 = rotl_31(*m4) * m1
			 = add(, 8)
			 -= 32
		}
		 =  ^  ^  ^ 
		goto 
	}

	 ^=  >> 29
	 *= m3
	 ^=  >> 32
	return uintptr()
}

func ( unsafe.Pointer,  uintptr) uintptr {
	 := uint64( + 4*hashkey[0])
	 := uint64(readUnaligned32())
	 ^= 
	 ^=  << 32
	 = rotl_31(*m1) * m2
	 ^=  >> 29
	 *= m3
	 ^=  >> 32
	return uintptr()
}

func ( unsafe.Pointer,  uintptr) uintptr {
	 := uint64( + 8*hashkey[0])
	 ^= uint64(readUnaligned32()) | uint64(readUnaligned32(add(, 4)))<<32
	 = rotl_31(*m1) * m2
	 ^=  >> 29
	 *= m3
	 ^=  >> 32
	return uintptr()
}

// Note: in order to get the compiler to issue rotl instructions, we
// need to constant fold the shift amount by hand.
// TODO: convince the compiler to issue rotl instructions after inlining.
func ( uint64) uint64 {
	return ( << 31) | ( >> (64 - 31))
}