#include "random.h" #include #define GET_ALGORITHM_ID(flags) ((flags) & 0xFF) BLUE_API struct b_random_algorithm z__b_gen_mt19937; static struct b_random_algorithm *generators[] = { [B_RANDOM_MT19937] = &z__b_gen_mt19937, }; static size_t nr_generators = sizeof generators / sizeof generators[0]; static struct b_random_ctx g_global_ctx = {0}; static void init_global_ctx(void) { b_random_init(&g_global_ctx, B_RANDOM_MT19937); } struct b_random_ctx *b_random_global_ctx(void) { if (!g_global_ctx.__f) { init_global_ctx(); } return &g_global_ctx; } b_status b_random_init(struct b_random_ctx *ctx, b_random_flags flags) { unsigned int algorithm_id = GET_ALGORITHM_ID(flags); if (algorithm_id >= nr_generators || !generators[algorithm_id]) { return B_ERR_INVALID_ARGUMENT; } struct b_random_algorithm *algorithm = generators[algorithm_id]; ctx->__f = flags; ctx->__a = algorithm; unsigned long long seed; if (flags & B_RANDOM_SECURE) { seed = z__b_platform_random_seed_secure(); } else { seed = z__b_platform_random_seed(); } algorithm->gen_init(ctx, seed); return B_SUCCESS; } unsigned long long b_random_next_int64(struct b_random_ctx *ctx) { if (!ctx->__a || !ctx->__a->gen_getrand) { return 0; } return ctx->__a->gen_getrand(ctx); } double b_random_next_double(struct b_random_ctx *ctx) { unsigned long long v = b_random_next_int64(ctx); if (!v) { return 0.0; } return (double)(v >> 11) * (1.0 / 9007199254740991.0); } void b_random_next_bytes(struct b_random_ctx *ctx, unsigned char *out, size_t nbytes) { 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]; *dest = b_random_next_int64(ctx); bytes_written += 8; } if (bytes_written == nbytes) { return; } uint64_t padding = b_random_next_int64(ctx); 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; } } }