Files
fx/core/random.c

104 lines
2.1 KiB
C
Raw Normal View History

2024-10-24 21:33:05 +01:00
#include "random.h"
2026-03-16 10:35:43 +00:00
#include <fx/core/random.h>
2024-10-24 21:33:05 +01:00
#define GET_ALGORITHM_ID(flags) ((flags) & 0xFF)
2026-03-16 10:35:43 +00:00
FX_API struct fx_random_algorithm z__fx_gen_mt19937;
2024-10-24 21:33:05 +01:00
2026-03-16 10:35:43 +00:00
static struct fx_random_algorithm *generators[] = {
[FX_RANDOM_MT19937] = &z__fx_gen_mt19937,
2024-10-24 21:33:05 +01:00
};
static size_t nr_generators = sizeof generators / sizeof generators[0];
2026-03-16 10:35:43 +00:00
static struct fx_random_ctx g_global_ctx = {0};
2024-10-24 21:33:05 +01:00
static void init_global_ctx(void)
{
2026-03-16 10:35:43 +00:00
fx_random_init(&g_global_ctx, FX_RANDOM_MT19937);
2024-10-24 21:33:05 +01:00
}
2026-03-16 10:35:43 +00:00
struct fx_random_ctx *fx_random_global_ctx(void)
2024-10-24 21:33:05 +01:00
{
if (!g_global_ctx.__f) {
init_global_ctx();
}
return &g_global_ctx;
}
2026-03-16 10:35:43 +00:00
fx_status fx_random_init(struct fx_random_ctx *ctx, fx_random_flags flags)
2024-10-24 21:33:05 +01:00
{
unsigned int algorithm_id = GET_ALGORITHM_ID(flags);
if (algorithm_id >= nr_generators || !generators[algorithm_id]) {
2026-03-16 10:35:43 +00:00
return FX_ERR_INVALID_ARGUMENT;
2024-10-24 21:33:05 +01:00
}
2026-03-16 10:35:43 +00:00
struct fx_random_algorithm *algorithm = generators[algorithm_id];
2024-10-24 21:33:05 +01:00
ctx->__f = flags;
ctx->__a = algorithm;
unsigned long long seed;
2026-03-16 10:35:43 +00:00
if (flags & FX_RANDOM_SECURE) {
seed = z__fx_platform_random_seed_secure();
2024-10-24 21:33:05 +01:00
} else {
2026-03-16 10:35:43 +00:00
seed = z__fx_platform_random_seed();
2024-10-24 21:33:05 +01:00
}
algorithm->gen_init(ctx, seed);
2026-03-16 10:35:43 +00:00
return FX_SUCCESS;
2024-10-24 21:33:05 +01:00
}
2026-03-16 10:35:43 +00:00
unsigned long long fx_random_next_int64(struct fx_random_ctx *ctx)
2024-10-24 21:33:05 +01:00
{
if (!ctx->__a || !ctx->__a->gen_getrand) {
return 0;
}
return ctx->__a->gen_getrand(ctx);
}
2026-03-16 10:35:43 +00:00
double fx_random_next_double(struct fx_random_ctx *ctx)
2024-10-24 21:33:05 +01:00
{
2026-03-16 10:35:43 +00:00
unsigned long long v = fx_random_next_int64(ctx);
2024-10-24 21:33:05 +01:00
if (!v) {
return 0.0;
}
return (double)(v >> 11) * (1.0 / 9007199254740991.0);
}
2026-03-16 10:35:43 +00:00
void fx_random_next_bytes(struct fx_random_ctx *ctx, unsigned char *out, size_t nbytes)
2024-10-24 21:33:05 +01:00
{
size_t n_qwords = 0;
n_qwords = nbytes >> 3;
if ((n_qwords << 3) < nbytes) {
n_qwords++;
}
size_t bytes_written = 0;
for (size_t i = 0; i < n_qwords; i++) {
uint64_t *dest = (uint64_t *)&out[bytes_written];
2026-03-16 10:35:43 +00:00
*dest = fx_random_next_int64(ctx);
2024-10-24 21:33:05 +01:00
bytes_written += 8;
}
if (bytes_written == nbytes) {
return;
}
2026-03-16 10:35:43 +00:00
uint64_t padding = fx_random_next_int64(ctx);
2024-10-24 21:33:05 +01:00
unsigned char *padding_bytes = (unsigned char *)&padding;
for (size_t i = 0; i < 8; i++) {
out[bytes_written++] = padding_bytes[i];
if (bytes_written == nbytes) {
break;
}
}
}