skip to content
==> include/mesh/abi/pipe_hash.h <==
1/* @ajax/mesh-abi-pipe-hash: Pipe hashes: a record's position-mixed sum and an inbox type's FNV-1a 32.
2 *
3 * Part of alpha-c-mesh, a C port of alpha-rust-mesh (README.md says from where). */
4#ifndef MESH_ABI_PIPE_HASH_H
5#define MESH_ABI_PIPE_HASH_H
6
7#include <stdbool.h>
8#include <stddef.h>
9#include <stdint.h>
10
11/* Word i's part of a record sum (the sum: these, wrapping, over every word). */
12static inline uint32_t mesh_pipe_sum_part(uint32_t i, uint32_t w) {
13    return (w ^ i * 0x9e3779b9u) * (2 * i + 1) + i;
14}
15/* A record's sum (its little-endian u32 words; a trailing partial word is ignored). */
16static inline uint32_t mesh_pipe_rec_sum(const uint8_t *rec, size_t len) {
17    uint32_t s = 0;
18    for (size_t i = 0; 4 * i + 4 <= len; i++) {
19        const uint8_t *b = rec + 4 * i;
20        uint32_t w = (uint32_t)b[0] | (uint32_t)b[1] << 8 | (uint32_t)b[2] << 16 | (uint32_t)b[3] << 24;
21        s += mesh_pipe_sum_part((uint32_t)i, w);
22    }
23    return s;
24}
25/* Position p's part of its record's sum (murmur3's fmix32, a bijection: two
26 * positions never mix alike). */
27static inline uint32_t mesh_pipe_pos_mix(uint32_t p) {
28    uint32_t x = p ^ 0x6d2b79f5u;
29    x = (x ^ (x >> 16)) * 0x85ebca6bu;
30    x = (x ^ (x >> 13)) * 0xc2b2ae35u;
31    return x ^ (x >> 16);
32}
33/* The sum stored beside position p's record. */
34static inline uint32_t mesh_pipe_rec_sum_at(const uint8_t *rec, size_t len, uint32_t p) {
35    return mesh_pipe_rec_sum(rec, len) ^ mesh_pipe_pos_mix(p);
36}
37/* FNV-1a 32 of a type name (PP_IN_TYPE). */
38static inline uint32_t mesh_pipe_type_hash(const uint8_t *b, size_t n) {
39    uint32_t h = 0x811c9dc5u;
40    for (size_t i = 0; i < n; i++) {
41        h ^= b[i];
42        h *= 0x01000193u;
43    }
44    return h;
45}
46
47#endif