37 lines
1.6 KiB
C
37 lines
1.6 KiB
C
|
|
#pragma once
|
|||
|
|
// -----------------------------------------------------------------------------
|
|||
|
|
// Чистые хеш-функции без состояния. Значение зависит ТОЛЬКО от аргументов.
|
|||
|
|
//
|
|||
|
|
// Это не генератор случайных чисел: общего состояния нет, «посеять» нечего,
|
|||
|
|
// последовательность вызовов ни на что не влияет. Поэтому такой хеш можно
|
|||
|
|
// звать и из симуляции, не ломая детерминизм: --headless по-прежнему выдаёт
|
|||
|
|
// один и тот же прогон, а разброс выстрела воспроизводится по номеру выстрела
|
|||
|
|
// и индексу стрелка (см. sim/loadout.h и docs/08-decisions.md).
|
|||
|
|
//
|
|||
|
|
// Рендер использует те же функции через render/noise.h.
|
|||
|
|
// -----------------------------------------------------------------------------
|
|||
|
|
#include <cstdint>
|
|||
|
|
|
|||
|
|
inline uint32_t HashU32(uint32_t x)
|
|||
|
|
{
|
|||
|
|
x ^= x >> 16;
|
|||
|
|
x *= 0x7FEB352Du;
|
|||
|
|
x ^= x >> 15;
|
|||
|
|
x *= 0x846CA68Bu;
|
|||
|
|
x ^= x >> 16;
|
|||
|
|
return x;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
inline uint32_t Hash2(uint32_t x, uint32_t y) { return HashU32(x * 0x27D4EB2Du ^ (y + 0x165667B1u)); }
|
|||
|
|
|
|||
|
|
inline uint32_t Hash3(uint32_t x, uint32_t y, uint32_t z)
|
|||
|
|
{
|
|||
|
|
return HashU32(Hash2(x, y) ^ (z * 0x9E3779B9u));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// [0, 1)
|
|||
|
|
inline float Hash01(uint32_t h) { return float(h & 0x00FFFFFFu) * (1.0f / 16777216.0f); }
|
|||
|
|
|
|||
|
|
// [-1, 1)
|
|||
|
|
inline float HashSigned(uint32_t h) { return Hash01(h) * 2.0f - 1.0f; }
|