package xxh3

import (
	
	
)

// Uint128 is a 128 bit value.
// The actual value can be thought of as u.Hi<<64 | u.Lo.
type Uint128 struct {
	Hi, Lo uint64
}

// Bytes returns the uint128 as an array of bytes in canonical form (big-endian encoded).
func ( Uint128) () [16]byte {
	return [16]byte{
		byte(.Hi >> 0x38), byte(.Hi >> 0x30), byte(.Hi >> 0x28), byte(.Hi >> 0x20),
		byte(.Hi >> 0x18), byte(.Hi >> 0x10), byte(.Hi >> 0x08), byte(.Hi),
		byte(.Lo >> 0x38), byte(.Lo >> 0x30), byte(.Lo >> 0x28), byte(.Lo >> 0x20),
		byte(.Lo >> 0x18), byte(.Lo >> 0x10), byte(.Lo >> 0x08), byte(.Lo),
	}
}

type (
	ptr = unsafe.Pointer
	ui  = uintptr

	u8   = uint8
	u32  = uint32
	u64  = uint64
	u128 = Uint128
)

type str struct {
	p ptr
	l uint
}

func readU8( ptr,  ui) uint8 {
	return *(*uint8)(ptr(ui() + ))
}

func readU16( ptr,  ui) uint16 {
	 := (*[2]byte)(ptr(ui() + ))
	return uint16([0]) | uint16([1])<<8
}

func readU32( ptr,  ui) uint32 {
	 := (*[4]byte)(ptr(ui() + ))
	return uint32([0]) | uint32([1])<<8 | uint32([2])<<16 | uint32([3])<<24
}

func readU64( ptr,  ui) uint64 {
	 := (*[8]byte)(ptr(ui() + ))
	return uint64([0]) | uint64([1])<<8 | uint64([2])<<16 | uint64([3])<<24 |
		uint64([4])<<32 | uint64([5])<<40 | uint64([6])<<48 | uint64([7])<<56
}

func writeU64( ptr,  ui,  u64) {
	 := (*[8]byte)(ptr(ui() + ))
	[0] = byte()
	[1] = byte( >> 8)
	[2] = byte( >> 16)
	[3] = byte( >> 24)
	[4] = byte( >> 32)
	[5] = byte( >> 40)
	[6] = byte( >> 48)
	[7] = byte( >> 56)
}

const secretSize = 192

func initSecret( ptr,  u64) {
	for  := ui(0);  < secretSize/16; ++ {
		 := readU64(key, 16*) + 
		 := readU64(key, 16*+8) - 
		writeU64(, 16*, )
		writeU64(, 16*+8, )
	}
}

func xxh64AvalancheSmall( u64) u64 {
	// x ^= x >> 33                    // x must be < 32 bits
	// x ^= u64(key32_000 ^ key32_004) // caller must do this
	 *= prime64_2
	 ^=  >> 29
	 *= prime64_3
	 ^=  >> 32
	return 
}

func xxhAvalancheSmall( u64) u64 {
	 ^=  >> 33
	 *= prime64_2
	 ^=  >> 29
	 *= prime64_3
	 ^=  >> 32
	return 
}

func xxh64AvalancheFull( u64) u64 {
	 ^=  >> 33
	 *= prime64_2
	 ^=  >> 29
	 *= prime64_3
	 ^=  >> 32
	return 
}

func xxh3Avalanche( u64) u64 {
	 ^=  >> 37
	 *= 0x165667919e3779f9
	 ^=  >> 32
	return 
}

func rrmxmx( u64,  u64) u64 {
	 ^= bits.RotateLeft64(, 49) ^ bits.RotateLeft64(, 24)
	 *= 0x9fb21c651e98df25
	 ^= ( >> 35) + 
	 *= 0x9fb21c651e98df25
	 ^= ( >> 28)
	return 
}

func mulFold64(,  u64) u64 {
	,  := bits.Mul64(, )
	return  ^ 
}