#pragma once #include namespace fn::ds { // Estado RNG opaco (xoshiro256++). Periodo 2^256 - 1, paso muy rapido, // excelente calidad estadistica. No criptografico. struct Rng { std::uint64_t s[4] = {0, 0, 0, 0}; }; // Inicializa el state de una Rng a partir de una semilla maestra usando // SplitMix64. seed=0 se sustituye por la constante de Knuth para evitar // arranque degenerado. Funcion pura (modifica r in-place a partir de seed). void rng_seed(Rng& r, std::uint64_t seed); // Avanza el RNG y devuelve un uint64 uniformemente distribuido. std::uint64_t rng_u64(Rng& r); // Float [0, 1). 53 bits de mantisa. double rng_uniform(Rng& r); // N(0, 1) Box-Muller polar. double rng_normal(Rng& r); // Entero uniforme en [0, n). Rejection-sampling para evitar sesgo modular. std::uint64_t rng_below(Rng& r, std::uint64_t n); // Sample categorico: dado un array de probabilidades NO necesariamente // normalizadas (positivas), devuelve el indice [0, n) con probabilidad // proporcional. O(n). Si la suma es 0 devuelve n-1. int rng_categorical(Rng& r, const double* weights, int n); } // namespace fn::ds