/* libmisc/rand.c - Non-crytpographic random-number utilities * * Copyright (C) 2024-2025 Luke T. Shumaker * SPDX-License-Identifier: AGPL-3.0-or-later */ #include #include #include uint32_t rand_uint32(void) { return __lm_rand_uint32(); } uint64_t rand_uint64(void) { return __lm_rand_uint64(); } uint32_t rand_uint31n(uint32_t cnt) { assert(cnt != 0 && ((cnt-1) & 0x80000000) == 0); uint32_t fair_cnt = ((UINT32_C(1)<<31) / cnt) * cnt; uint32_t rnd; do { rnd = __lm_rand_uint31(); } while (rnd >= fair_cnt); return rnd % cnt; } uint64_t rand_uint63n(uint64_t cnt) { assert(cnt != 0 && ((cnt-1) & 0x8000000000000000) == 0); if (cnt <= UINT64_C(1)<<31) { return rand_uint31n(cnt); } else if (cnt <= UINT64_C(1)<<32) { uint64_t fair_cnt = ((UINT64_C(1)<<32) / cnt) * cnt; uint64_t rnd; do { rnd = __lm_rand_uint32(); } while (rnd >= fair_cnt); return rnd % cnt; } else if (cnt <= UINT64_C(1)<<62) { uint64_t fair_cnt = ((UINT64_C(1)<<62) / cnt) * cnt; uint64_t rnd; do { rnd = __lm_rand_uint62(); } while (rnd >= fair_cnt); return rnd % cnt; } else { uint64_t fair_cnt = ((UINT64_C(1)<<63) / cnt) * cnt; uint64_t rnd; do { rnd = __lm_rand_uint63(); } while (rnd >= fair_cnt); return rnd % cnt; } }