package core:hash/xxhash

⌘K
Ctrl+K
or
/

    Overview

    Yann Collet's xxhash.

    xxhash Fast Hash Algorithm

    Index

    Variables (1)
    Procedures (108)
    Procedure Groups (2)

    Types

    XXH128_canonical ¶

    XXH128_canonical :: struct {
    	digest: [16]u8,
    }

    XXH128_hash_t ¶

    XXH128_hash_t :: struct #raw_union {
    	using raw: struct {
    		low:  u64,
    		// !< `value & 0xFFFFFFFFFFFFFFFF` 
    		high: u64,
    	},
    	h:   u128,
    }

    XXH32_canonical ¶

    XXH32_canonical :: struct {
    	digest: [4]u8,
    }

    XXH32_state ¶

    XXH32_state :: struct {
    	total_len_32: u32,
    	// !< Total length hashed, modulo 2^32 
    	large_len:    u32,
    	// !< Whether the hash is >= 16 (handles @ref total_len_32 overflow) 
    	v1:           u32,
    	// !< First accumulator lane 
    	v2:           u32,
    	// !< Second accumulator lane 
    	v3:           u32,
    	// !< Third accumulator lane 
    	v4:           u32,
    	// !< Fourth accumulator lane 
    	mem32:        [4]u32,
    	// !< Internal buffer for partial reads. Treated as unsigned char[16]. 
    	memsize:      u32,
    	// !< Amount of data in @ref mem32 
    	reserved:     u32,
    }

    Related Procedures With Parameters

    XXH3_hashLong128_f ¶

    XXH3_hashLong128_f :: proc(input: []u8, seed: u64, secret: []u8) -> (res: u128)

    XXH3_hashLong64_f ¶

    XXH3_hashLong64_f :: proc(input: []u8, seed: u64, secret: []u8) -> (res: u64)

    XXH3_init_custom_secret_f ¶

    XXH3_init_custom_secret_f :: proc(custom_secret: []u8, seed64: u64)

    Related Procedures With Parameters

    XXH3_state ¶

    XXH3_state :: struct #align (64) {
    	acc:               [8]u64,
    	custom_secret:     [192]u8,
    	buffer:            [256]u8,
    	buffered_size:     u32,
    	reserved32:        u32,
    	stripes_so_far:    uint,
    	total_length:      u64,
    	stripes_per_block: uint,
    	secret_limit:      uint,
    	seed:              u64,
    	reserved64:        u64,
    	external_secret:   []u8,
    }
     

    Streaming state.

    IMPORTANT: This structure has a strict alignment requirement of 64 bytes!! ** Default allocators will align it correctly if created via new, as will placing this struct on the stack, but if using a custom allocator make sure that it handles the alignment correctly!

    Related Procedures With Parameters

    XXH64_canonical ¶

    XXH64_canonical :: struct {
    	digest: [8]u8,
    }

    XXH64_state ¶

    XXH64_state :: struct {
    	total_len:  u64,
    	// !< Total length hashed. This is always 64-bit. 
    	v1:         u64,
    	// !< First accumulator lane 
    	v2:         u64,
    	// !< Second accumulator lane 
    	v3:         u64,
    	// !< Third accumulator lane 
    	v4:         u64,
    	// !< Fourth accumulator lane 
    	mem64:      [4]u64,
    	// !< Internal buffer for partial reads. Treated as unsigned char[32]. 
    	memsize:    u32,
    	// !< Amount of data in @ref mem64 
    	reserved32: u32,
    	// !< Reserved field, needed for padding anyways
    	reserved64: u64,
    }

    Related Procedures With Parameters

    Constants

    XXH32_DEFAULT_SEED ¶

    XXH32_DEFAULT_SEED: u32 : XXH32_hash(0)

    XXH3_INIT_ACC ¶

    XXH3_INIT_ACC: [8]u64 : [XXH_ACC_NB]xxh_u64{XXH_PRIME32_3, XXH_PRIME64_1, XXH_PRIME64_2, XXH_PRIME64_3, XXH_PRIME64_4, XXH_PRIME32_2, XXH_PRIME64_5, XXH_PRIME32_1}

    XXH3_INTERNAL_BUFFER_SIZE ¶

    XXH3_INTERNAL_BUFFER_SIZE :: 256
     

    This is the optimal update size for incremental hashing.

    XXH3_SECRET_SIZE_MIN ¶

    XXH3_SECRET_SIZE_MIN :: 136
     

    Do not change this constant.

    XXH64_DEFAULT_SEED ¶

    XXH64_DEFAULT_SEED: u64 : XXH64_hash(0)

    XXH_ACC_ALIGN ¶

    XXH_ACC_ALIGN :: 8
     

    scalar

    XXH_ACC_NB ¶

    XXH_ACC_NB :: XXH_STRIPE_LEN / size_of(xxh_u64)

    XXH_DISABLE_PREFETCH ¶

    XXH_DISABLE_PREFETCH :: #config(XXH_DISABLE_PREFETCH, true)
    -define:XXH_DISABLE_PREFETCH=true

    XXH_FORCE_ALIGN_CHECK ¶

    XXH_FORCE_ALIGN_CHECK :: #config(XXH_FORCE_ALIGN_CHECK, false)
    -define:XXH_FORCE_ALIGN_CHECK=false
     

    false - Use this on platforms where unaligned reads are fast true - Use this on platforms where unaligned reads are slow

    XXH_FORCE_MEMORY_ACCESS ¶

    XXH_FORCE_MEMORY_ACCESS :: #config(XXH_FORCE_MEMORY_ACCESS, 2)
    -define:XXH_FORCE_MEMORY_ACCESS=2
     

    0 - Use memcopy, for platforms where unaligned reads are a problem 2 - Direct cast, for platforms where unaligned are allowed (default)

    XXH_MAX_WIDTH ¶

    XXH_MAX_WIDTH :: #config(XXH_MAX_WIDTH, 512) / 64

    XXH_NATIVE_WIDTH ¶

    XXH_NATIVE_WIDTH :: min(XXH_MAX_WIDTH, 8 when intrinsics.has_target_feature(AVX512_FEATURES) else 4 when intrinsics.has_target_feature(AVX2_FEATURES) else 2 when intrinsics.has_target_feature(SSE2_FEATURES) else 1)

    XXH_PRIME32_1 ¶

    XXH_PRIME32_1 :: 0x9E3779B1
     

    0b10011110001101110111100110110001

    XXH_PRIME32_2 ¶

    XXH_PRIME32_2 :: 0x85EBCA77
     

    0b10000101111010111100101001110111

    XXH_PRIME32_3 ¶

    XXH_PRIME32_3 :: 0xC2B2AE3D
     

    0b11000010101100101010111000111101

    XXH_PRIME32_4 ¶

    XXH_PRIME32_4 :: 0x27D4EB2F
     

    0b00100111110101001110101100101111

    XXH_PRIME32_5 ¶

    XXH_PRIME32_5 :: 0x165667B1
     

    0b00010110010101100110011110110001

    XXH_PRIME64_1 ¶

    XXH_PRIME64_1 :: 0x9E3779B185EBCA87
     

    0b1001111000110111011110011011000110000101111010111100101010000111

    XXH_PRIME64_2 ¶

    XXH_PRIME64_2 :: 0xC2B2AE3D27D4EB4F
     

    0b1100001010110010101011100011110100100111110101001110101101001111

    XXH_PRIME64_3 ¶

    XXH_PRIME64_3 :: 0x165667B19E3779F9
     

    0b0001011001010110011001111011000110011110001101110111100111111001

    XXH_PRIME64_4 ¶

    XXH_PRIME64_4 :: 0x85EBCA77C2B2AE63
     

    0b1000010111101011110010100111011111000010101100101010111001100011

    XXH_PRIME64_5 ¶

    XXH_PRIME64_5 :: 0x27D4EB2F165667C5
     

    0b0010011111010100111010110010111100010110010101100110011111000101

    XXH_SECRET_CONSUME_RATE ¶

    XXH_SECRET_CONSUME_RATE :: 8
     

    nb of secret bytes consumed at each accumulation

    XXH_SECRET_DEFAULT_SIZE ¶

    XXH_SECRET_DEFAULT_SIZE :: max(XXH3_SECRET_SIZE_MIN, #config(XXH_SECRET_DEFAULT_SIZE, 192))
     

    Custom secrets have a default length of 192, but can be set to a different size. The minimum secret size is 136 bytes. It must also be a multiple of 64.

    XXH_SECRET_LASTACC_START ¶

    XXH_SECRET_LASTACC_START :: 7
     

    not aligned on 8, last secret is different from acc & scrambler

    XXH_VERSION_MAJOR ¶

    XXH_VERSION_MAJOR :: 0
     

    Version definition

    XXH_VERSION_NUMBER ¶

    XXH_VERSION_NUMBER :: XXH_VERSION_MAJOR * 100 * 100 + XXH_VERSION_MINOR * 100 + XXH_VERSION_RELEASE

    Variables

    Procedures

    XXH128_mix32B ¶

    @(optimization_mode="favor_size")
    XXH128_mix32B :: proc(
    	acc:     u128, 
    	input_1: []u8, 
    	input_2: []u8, 
    	secret:  []u8, 
    	seed:    u64, 
    ) -> (res: u128) {…}
     

    A bit slower than XXH3_mix16B, but handles multiply by zero better.

    XXH32 ¶

    XXH32 :: proc(input: []u8, seed: u32 = XXH32_DEFAULT_SEED) -> (digest: u32) {…}

    XXH32_avalanche ¶

    @(optimization_mode="favor_size")
    XXH32_avalanche :: proc(h32: u32) -> (res: u32) {…}
     

    Mix all bits

    XXH32_canonical_from_hash ¶

    XXH32_canonical_from_hash :: proc(hash: u32) -> (canonical: XXH32_canonical) {…}
     

    ****** Canonical representation ******

    The default return values from XXH functions are unsigned 32 and 64 bit integers.

    The canonical representation uses big endian convention, the same convention as human-readable numbers (large digits first).

    This way, hash values can be written into a file or buffer, remaining comparable across different systems.

    The following functions allow transformation of hash values to and from their canonical format.

    XXH32_copy_state ¶

    XXH32_copy_state :: proc(dest, src: ^XXH32_state) {…}

    XXH32_create_state ¶

    XXH32_create_state :: proc(allocator := context.allocator) -> (res: ^XXH32_state, err: Error) {…}
     

    ****** Hash streaming ******

    XXH32_destroy_state ¶

    XXH32_destroy_state :: proc(
    	state:     ^XXH32_state, 
    	allocator := context.allocator, 
    ) -> (err: Error) {…}

    XXH32_digest ¶

    XXH32_digest :: proc(state: ^XXH32_state) -> (res: u32) {…}

    XXH32_endian_align ¶

    @(optimization_mode="favor_size")
    XXH32_endian_align :: proc(
    	input:     []u8, 
    	seed:      u32 = XXH32_DEFAULT_SEED, 
    	alignment: Alignment, 
    ) -> (res: u32) {…}

    XXH32_finalize ¶

    @(optimization_mode="favor_size")
    XXH32_finalize :: proc(h32: u32, buf: []u8, alignment: Alignment) -> (res: u32) {…}

    XXH32_hash_from_canonical ¶

    XXH32_hash_from_canonical :: proc(canonical: ^XXH32_canonical) -> (hash: u32) {…}

    XXH32_read32 ¶

    @(optimization_mode="favor_size")
    XXH32_read32 :: proc(buf: []u8, alignment: Alignment = Alignment.Unaligned) -> (res: u32) {…}

    XXH32_reset_state ¶

    XXH32_reset_state :: proc(
    	state_ptr: ^XXH32_state, 
    	seed:      u32 = XXH32_DEFAULT_SEED, 
    ) -> (err: Error) {…}

    XXH32_round ¶

    @(optimization_mode="favor_size")
    XXH32_round :: proc(seed, input: u32) -> (res: u32) {…}

    XXH32_update ¶

    XXH32_update :: proc(state: ^XXH32_state, input: []u8) -> (err: Error) {…}

    XXH3_128_canonical_from_hash ¶

    XXH3_128_canonical_from_hash :: proc(hash: XXH128_hash_t) -> (canonical: XXH128_canonical) {…}

    XXH3_128_default ¶

    @(optimization_mode="favor_size")
    XXH3_128_default :: proc(input: []u8) -> (hash: u128) {…}
     

    === Public XXH128 API ===

    XXH3_128_digest ¶

    XXH3_128_digest :: proc(state: ^XXH3_state) -> (hash: u128) {…}

    XXH3_128_hash_from_canonical ¶

    XXH3_128_hash_from_canonical :: proc(src: ^XXH128_canonical) -> (hash: u128) {…}

    XXH3_128_reset ¶

    XXH3_128_reset :: proc(state: ^XXH3_state) -> (err: Error) {…}
     

    === XXH3 128-bit streaming ===

    All the functions are actually the same as for 64-bit streaming variant. The only difference is the finalization routine.

    XXH3_128_reset_with_secret ¶

    XXH3_128_reset_with_secret :: proc(state: ^XXH3_state, secret: []u8) -> (err: Error) {…}

    XXH3_128_reset_with_seed ¶

    XXH3_128_reset_with_seed :: proc(state: ^XXH3_state, seed: u64) -> (err: Error) {…}

    XXH3_128_update ¶

    XXH3_128_update :: proc(state: ^XXH3_state, input: []u8) -> (err: Error) {…}

    XXH3_128_with_secret ¶

    @(optimization_mode="favor_size")
    XXH3_128_with_secret :: proc(input: []u8, secret: []u8) -> (hash: u128) {…}

    XXH3_128_with_seed ¶

    @(optimization_mode="favor_size")
    XXH3_128_with_seed :: proc(input: []u8, seed: u64) -> (hash: u128) {…}

    XXH3_128bits_internal ¶

    @(optimization_mode="favor_size")
    XXH3_128bits_internal :: proc(
    	input:   []u8, 
    	seed:    u64, 
    	secret:  []u8, 
    	f_hl128: XXH3_hashLong128_f, 
    ) -> (res: u128) {…}

    XXH3_64_default ¶

    @(optimization_mode="favor_size")
    XXH3_64_default :: proc(input: []u8) -> (hash: u64) {…}
     

    === Public entry point ===

    XXH3_64_digest ¶

    XXH3_64_digest :: proc(state: ^XXH3_state) -> (hash: u64) {…}

    XXH3_64_reset ¶

    XXH3_64_reset :: XXH3_128_reset
     

    === XXH3 128-bit streaming ===

    All the functions are actually the same as for 64-bit streaming variant. The only difference is the finalization routine.

    XXH3_64_with_secret ¶

    @(optimization_mode="favor_size")
    XXH3_64_with_secret :: proc(input: []u8, secret: []u8) -> (hash: u64) {…}

    XXH3_64_with_seed ¶

    @(optimization_mode="favor_size")
    XXH3_64_with_seed :: proc(input: []u8, seed: u64) -> (hash: u64) {…}

    XXH3_64bits_internal ¶

    @(optimization_mode="favor_size")
    XXH3_64bits_internal :: proc(
    	input:      []u8, 
    	seed:       u64, 
    	secret:     []u8, 
    	f_hashLong: XXH3_hashLong64_f, 
    ) -> (hash: u64) {…}

    XXH3_accumulate ¶

    @(optimization_mode="favor_size")
    XXH3_accumulate :: proc(
    	acc:       []u64, 
    	input:     []u8, 
    	secret:    []u8, 
    	nbStripes: uint, 
    	f_acc512:  XXH3_accumulate_512_f, 
    ) {…}
     

    XXH3_accumulate() Loops over XXH3_accumulate_512(). Assumption: nbStripes will not overflow the secret size

    XXH3_accumulate_512 ¶

    XXH3_accumulate_512 :: proc(acc: []u64, input: []u8, secret: []u8) {…}

    XXH3_accumulate_512_scalar ¶

    @(optimization_mode="favor_size")
    XXH3_accumulate_512_scalar :: proc(acc: []u64, input: []u8, secret: []u8) {…}
     

    scalar variants - universal

    XXH3_accumulate_512_simd_generic ¶

    XXH3_accumulate_512_simd_generic :: proc(acc: []u64, input: []u8, secret: []u8, $W: uint) {…}
     

    generalized SIMD variants

    XXH3_avalanche ¶

    @(optimization_mode="favor_size")
    XXH3_avalanche :: proc(h64: u64) -> (res: u64) {…}
     

    This is a fast avalanche stage, suitable when input bits are already partially mixed

    XXH3_consume_stripes ¶

    XXH3_consume_stripes :: proc(
    	acc:               []u64, 
    	stripes_so_far:    ^uint, 
    	stripes_per_block: uint, 
    	input:             []u8, 
    	number_of_stripes: uint, 
    	secret:            []u8, 
    	secret_limit:      uint, 
    	f_acc512:          XXH3_accumulate_512_f, 
    	f_scramble:        XXH3_scramble_accumulator_f, 
    ) {…}

    XXH3_copy_state ¶

    XXH3_copy_state :: proc(dest, src: ^XXH3_state) {…}

    XXH3_create_state ¶

    XXH3_create_state :: proc(allocator := context.allocator) -> (res: ^XXH3_state, err: Error) {…}

    XXH3_destroy_state ¶

    XXH3_destroy_state :: proc(state: ^XXH3_state, allocator := context.allocator) -> (err: Error) {…}

    XXH3_digest_long ¶

    XXH3_digest_long :: proc(acc: []u64, state: ^XXH3_state, secret: []u8) {…}

    XXH3_generate_secret ¶

    XXH3_generate_secret :: proc(secret_buffer: []u8, custom_seed: []u8) {…}

    XXH3_hashLong_128b_default ¶

    XXH3_hashLong_128b_default :: proc(input: []u8, seed: u64, secret: []u8) -> (res: u128) {…}
     

    It's important for performance that XXH3_hashLong is not inlined.

    XXH3_hashLong_128b_internal ¶

    XXH3_hashLong_128b_internal :: proc(
    	input:      []u8, 
    	secret:     []u8, 
    	f_acc512:   XXH3_accumulate_512_f, 
    	f_scramble: XXH3_scramble_accumulator_f, 
    ) -> (res: u128) {…}

    XXH3_hashLong_128b_withSecret ¶

    XXH3_hashLong_128b_withSecret :: proc(input: []u8, seed: u64, secret: []u8) -> (res: u128) {…}
     

    It's important for performance that XXH3_hashLong is not inlined.

    XXH3_hashLong_128b_withSeed ¶

    XXH3_hashLong_128b_withSeed :: proc(input: []u8, seed: u64, secret: []u8) -> (res: u128) {…}
     

    It's important for performance that XXH3_hashLong is not inlined.

    XXH3_hashLong_128b_withSeed_internal ¶

    XXH3_hashLong_128b_withSeed_internal :: proc(
    	input:      []u8, 
    	seed:       u64, 
    	secret:     []u8, 
    	f_acc512:   XXH3_accumulate_512_f, 
    	f_scramble: XXH3_scramble_accumulator_f, 
    	f_initSec:  XXH3_init_custom_secret_f, 
    ) -> (res: u128) {…}

    XXH3_hashLong_64b_default ¶

    XXH3_hashLong_64b_default :: proc(input: []u8, seed64: u64, secret: []u8) -> (hash: u64) {…}
     

    It's important for performance that XXH3_hashLong is not inlined. Since the function is not inlined, the compiler may not be able to understand that, in some scenarios, its secret argument is actually a compile time constant. This variant enforces that the compiler can detect that, and uses this opportunity to streamline the generated code for better performance.

    XXH3_hashLong_64b_internal ¶

    @(optimization_mode="favor_size")
    XXH3_hashLong_64b_internal :: proc(
    	input:      []u8, 
    	secret:     []u8, 
    	f_acc512:   XXH3_accumulate_512_f, 
    	f_scramble: XXH3_scramble_accumulator_f, 
    ) -> (hash: u64) {…}

    XXH3_hashLong_64b_withSecret ¶

    XXH3_hashLong_64b_withSecret :: proc(input: []u8, seed64: u64, secret: []u8) -> (hash: u64) {…}
     

    It's important for performance that XXH3_hashLong is not inlined.

    XXH3_hashLong_64b_withSeed ¶

    XXH3_hashLong_64b_withSeed :: proc(input: []u8, seed: u64, secret: []u8) -> (hash: u64) {…}
     

    XXH3_hashLong_64b_withSeed(): Generate a custom key based on alteration of default XXH3_kSecret with the seed, and then use this key for long mode hashing.

    This operation is decently fast but nonetheless costs a little bit of time. Try to avoid it whenever possible (typically when seed==0).

    It's important for performance that XXH3_hashLong is not inlined. Not sure why (uop cache maybe?), but the difference is large and easily measurable.

    XXH3_hashLong_64b_withSeed_internal ¶

    XXH3_hashLong_64b_withSeed_internal :: proc(
    	input:      []u8, 
    	seed:       u64, 
    	f_acc512:   XXH3_accumulate_512_f, 
    	f_scramble: XXH3_scramble_accumulator_f, 
    	f_init_sec: XXH3_init_custom_secret_f, 
    ) -> (hash: u64) {…}

    XXH3_hashLong_internal_loop ¶

    @(optimization_mode="favor_size")
    XXH3_hashLong_internal_loop :: proc(
    	acc:        []u64, 
    	input:      []u8, 
    	secret:     []u8, 
    	f_acc512:   XXH3_accumulate_512_f, 
    	f_scramble: XXH3_scramble_accumulator_f, 
    ) {…}

    XXH3_init_custom_secret ¶

    XXH3_init_custom_secret :: proc(custom_secret: []u8, seed64: u64) {…}

    XXH3_init_custom_secret_scalar ¶

    @(optimization_mode="favor_size")
    XXH3_init_custom_secret_scalar :: proc(custom_secret: []u8, seed64: u64) {…}

    XXH3_init_custom_secret_simd_generic ¶

    XXH3_init_custom_secret_simd_generic :: proc(custom_secret: []u8, seed64: u64, $W: uint) {…}

    XXH3_init_state ¶

    XXH3_init_state :: proc(state: ^XXH3_state) {…}

    XXH3_len_0to16_128b ¶

    @(optimization_mode="favor_size")
    XXH3_len_0to16_128b :: proc(input: []u8, secret: []u8, seed: u64) -> (res: u128) {…}
     

    Assumption: secret size is >= XXH3_SECRET_SIZE_MIN

    XXH3_len_0to16_64b ¶

    @(optimization_mode="favor_size")
    XXH3_len_0to16_64b :: proc(input: []u8, secret: []u8, seed: u64) -> (res: u64) {…}

    XXH3_len_129to240_128b ¶

    @(optimization_mode="favor_size")
    XXH3_len_129to240_128b :: proc(input: []u8, secret: []u8, seed: u64) -> (res: u128) {…}

    XXH3_len_129to240_64b ¶

    @(optimization_mode="favor_size")
    XXH3_len_129to240_64b :: proc(input: []u8, secret: []u8, seed: u64) -> (res: u64) {…}

    XXH3_len_17to128_128b ¶

    @(optimization_mode="favor_size")
    XXH3_len_17to128_128b :: proc(input: []u8, secret: []u8, seed: u64) -> (res: u128) {…}

    XXH3_len_17to128_64b ¶

    @(optimization_mode="favor_size")
    XXH3_len_17to128_64b :: proc(input: []u8, secret: []u8, seed: u64) -> (res: u64) {…}
     

    For mid range keys, XXH3 uses a Mum-hash variant.

    XXH3_len_1to3_128b ¶

    @(optimization_mode="favor_size")
    XXH3_len_1to3_128b :: proc(input: []u8, secret: []u8, seed: u64) -> (res: u128) {…}

    XXH3_len_1to3_64b ¶

    @(optimization_mode="favor_size")
    XXH3_len_1to3_64b :: proc(input: []u8, secret: []u8, seed: u64) -> (res: u64) {…}
     

    At very short lengths, there isn't enough input to fully hide secrets, or use the entire secret.

    There is also only a limited amount of mixing we can do before significantly impacting performance.

    Therefore, we use different sections of the secret and always mix two secret samples with an XOR. This should have no effect on performance on the seedless or withSeed variants because everything should be constant folded by modern compilers.

    The XOR mixing hides individual parts of the secret and increases entropy. This adds an extra layer of strength for custom secrets.

    XXH3_len_4to8_128b ¶

    @(optimization_mode="favor_size")
    XXH3_len_4to8_128b :: proc(input: []u8, secret: []u8, seed: u64) -> (res: u128) {…}

    XXH3_len_4to8_64b ¶

    @(optimization_mode="favor_size")
    XXH3_len_4to8_64b :: proc(input: []u8, secret: []u8, seed: u64) -> (res: u64) {…}

    XXH3_len_9to16_128b ¶

    @(optimization_mode="favor_size")
    XXH3_len_9to16_128b :: proc(input: []u8, secret: []u8, seed: u64) -> (res: u128) {…}

    XXH3_len_9to16_64b ¶

    @(optimization_mode="favor_size")
    XXH3_len_9to16_64b :: proc(input: []u8, secret: []u8, seed: u64) -> (res: u64) {…}

    XXH3_mergeAccs ¶

    @(optimization_mode="favor_size")
    XXH3_mergeAccs :: proc(acc: []u64, secret: []u8, start: u64) -> (res: u64) {…}

    XXH3_mix16B ¶

    @(optimization_mode="favor_size")
    XXH3_mix16B :: proc(input: []u8, secret: []u8, seed: u64) -> (res: u64) {…}
     

    DISCLAIMER: There are known seed-dependent multicollisions here due to multiplication by zero, affecting hashes of lengths 17 to 240.

    However, they are very unlikely.

    Keep this in mind when using the unseeded XXH3_64bits() variant: As with all unseeded non-cryptographic hashes, it does not attempt to defend itself against specially crafted inputs, only random inputs.

    Compared to classic UMAC where a 1 in 2^31 chance of 4 consecutive bytes cancelling out the secret is taken an arbitrary number of times (addressed in XXH3_accumulate_512), this collision is very unlikely with random inputs and/or proper seeding:

    This only has a 1 in 2^63 chance of 8 consecutive bytes cancelling out, in a function that is only called up to 16 times per hash with up to 240 bytes of input.

    This is not too bad for a non-cryptographic hash function, especially with only 64 bit outputs.

    The 128-bit variant (which trades some speed for strength) is NOT affected by this, although it is always a good idea to use a proper seed if you care about strength.

    XXH3_mix2Accs ¶

    @(optimization_mode="favor_size")
    XXH3_mix2Accs :: proc(acc: []u64, secret: []u8) -> (res: u64) {…}

    XXH3_reset_internal ¶

    XXH3_reset_internal :: proc(state: ^XXH3_state, seed: u64, secret: []u8, secret_size: uint) {…}

    XXH3_rrmxmx ¶

    @(optimization_mode="favor_size")
    XXH3_rrmxmx :: proc(h64, length: u64) -> (res: u64) {…}
     

    This is a stronger avalanche, inspired by Pelle Evensen's rrmxmx preferable when input has not been previously mixed

    XXH3_scramble_accumulator ¶

    XXH3_scramble_accumulator :: proc(acc: []u64, secret: []u8) {…}

    XXH3_scramble_accumulator_scalar ¶

    @(optimization_mode="favor_size")
    XXH3_scramble_accumulator_scalar :: proc(acc: []u64, secret: []u8) {…}

    XXH3_scramble_accumulator_simd_generic ¶

    XXH3_scramble_accumulator_simd_generic :: proc(acc: []u64, secret: []u8, $W: uint) {…}

    XXH3_update ¶

    XXH3_update :: proc(
    	state:      ^XXH3_state, 
    	input:      []u8, 
    	f_acc512:   XXH3_accumulate_512_f, 
    	f_scramble: XXH3_scramble_accumulator_f, 
    ) -> (err: Error) {…}
     

    Both XXH3_64bits_update and XXH3_128bits_update use this routine.

    XXH64 ¶

    XXH64 :: proc(input: []u8, seed: u64 = XXH64_DEFAULT_SEED) -> (digest: u64) {…}

    XXH64_avalanche ¶

    @(optimization_mode="favor_size")
    XXH64_avalanche :: proc(h64: u64) -> (res: u64) {…}

    XXH64_canonical_from_hash ¶

    XXH64_canonical_from_hash :: proc(hash: u64) -> (canonical: XXH64_canonical) {…}
     

    ****** Canonical representation ******

    The default return values from XXH functions are unsigned 32 and 64 bit integers.

    The canonical representation uses big endian convention, the same convention as human-readable numbers (large digits first).

    This way, hash values can be written into a file or buffer, remaining comparable across different systems.

    The following functions allow transformation of hash values to and from their canonical format.

    XXH64_copy_state ¶

    XXH64_copy_state :: proc(dest, src: ^XXH64_state) {…}

    XXH64_create_state ¶

    XXH64_create_state :: proc(allocator := context.allocator) -> (res: ^XXH64_state, err: Error) {…}
     

    ****** Hash Streaming ******

    XXH64_destroy_state ¶

    XXH64_destroy_state :: proc(
    	state:     ^XXH64_state, 
    	allocator := context.allocator, 
    ) -> (err: Error) {…}

    XXH64_digest ¶

    @(optimization_mode="favor_size")
    XXH64_digest :: proc(state: ^XXH64_state) -> (res: u64) {…}

    XXH64_endian_align ¶

    @(optimization_mode="favor_size")
    XXH64_endian_align :: proc(
    	input:     []u8, 
    	seed:      u64 = XXH64_DEFAULT_SEED, 
    	alignment: Alignment = Alignment.Unaligned, 
    ) -> (res: u64) {…}

    XXH64_finalize ¶

    @(optimization_mode="favor_size")
    XXH64_finalize :: proc(h64: u64, buf: []u8, alignment: Alignment) -> (res: u64) {…}

    XXH64_hash_from_canonical ¶

    XXH64_hash_from_canonical :: proc(canonical: ^XXH64_canonical) -> (hash: u64) {…}

    XXH64_mergeRound ¶

    @(optimization_mode="favor_size")
    XXH64_mergeRound :: proc(acc, val: u64) -> (res: u64) {…}

    XXH64_read64 ¶

    @(optimization_mode="favor_size")
    XXH64_read64 :: proc(buf: []u8, alignment: Alignment = Alignment.Unaligned) -> (res: u64) {…}

    XXH64_read64_simd ¶

    XXH64_read64_simd :: proc(
    	buf:       []$E, 
    	$W:         uint, 
    	alignment: Alignment = Alignment.Unaligned, 
    ) -> (res: [0]u64) {…}

    XXH64_reset_state ¶

    XXH64_reset_state :: proc(
    	state_ptr: ^XXH64_state, 
    	seed:      u64 = XXH64_DEFAULT_SEED, 
    ) -> (err: Error) {…}

    XXH64_round ¶

    @(optimization_mode="favor_size")
    XXH64_round :: proc(acc, input: u64) -> (res: u64) {…}

    XXH64_update ¶

    @(optimization_mode="favor_size")
    XXH64_update :: proc(state: ^XXH64_state, input: []u8) -> (err: Error) {…}

    XXH64_write64_simd ¶

    XXH64_write64_simd :: proc(
    	buf:       []$E, 
    	value:     $V/#simd[0]u64, 
    	alignment: Alignment = Alignment.Unaligned, 
    ) {…}

    XXH_mul_64_to_128_fold_64 ¶

    @(optimization_mode="favor_size")
    XXH_mul_64_to_128_fold_64 :: proc(lhs, rhs: u64) -> (res: u64) {…}
     

    The reason for the separate function is to prevent passing too many structs around by value. This will hopefully inline the multiply, but we don't force it.

    @param lhs, rhs The 64-bit integers to multiply @return The low 64 bits of the product XOR'd by the high 64 bits.

    XXH_rotl32 ¶

    @(optimization_mode="favor_size")
    XXH_rotl32 :: proc(x, r: u32) -> (res: u32) {…}

    XXH_rotl64 ¶

    @(optimization_mode="favor_size")
    XXH_rotl64 :: proc(x, r: u64) -> (res: u64) {…}

    XXH_writeLE64 ¶

    @(optimization_mode="favor_size")
    XXH_writeLE64 :: proc(dst: []u8, v64: u64le) {…}

    XXH_xorshift_64 ¶

    @(optimization_mode="favor_size")
    XXH_xorshift_64 :: proc(v: u64, #any_int shift: uint) -> (res: u64) {…}

    byte_swap ¶

    byte_swap :: intrinsics.byte_swap
    byte_swap :: proc(x: $T) -> T where type_is_integer(T) || type_is_float(T) {…}
     

    Reverses the bytes from ascending order to descending order e.g. 0xfe_ed_01_12 -> 0x12_01_ed_fe

    prefetch_address ¶

    prefetch_address :: proc(address: rawptr) {…}

    prefetch_offset ¶

    prefetch_offset :: proc(address: rawptr, #any_int offset: uintptr) {…}

    Procedure Groups

    `#config` values

    Source Files

    Generation Information

    Generated with odin version dev-2026-10 (vendor "odin") Windows_amd64 @ 2026-10-10 00:25:51.511820200 +0000 UTC