core/math/rand: Use core:crypto for the system RNG

This removes some code duplication and expands support for the system
RNG to all targets that `core:crypto` supports.
This commit is contained in:
Yawning Angel
2024-04-23 11:47:43 +09:00
parent a6eb64df6c
commit e2fa9be7e2
5 changed files with 21 additions and 96 deletions
+21 -18
View File
@@ -5,6 +5,7 @@ Package core:math/rand implements various random number generators
package rand
import "base:intrinsics"
import "core:crypto"
import "core:math"
import "core:mem"
@@ -104,27 +105,30 @@ init :: proc(r: ^Rand, seed: u64) {
}
/*
Initialises a random number generator to use the system random number generator.
The system random number generator is platform specific.
On `linux` refer to the `getrandom` syscall.
On `darwin` refer to `getentropy`.
On `windows` refer to `BCryptGenRandom`.
All other platforms are not supported
Initialises a random number generator to use the system random number generator.
The system random number generator is platform specific, and not supported
on all targets.
Inputs:
- r: The random number generator to use the system random number generator
WARNING: Panics if the system is not either `windows`, `darwin` or `linux`
WARNING: Panics if the system random number generator is not supported.
Support can be determined via the `core:crypto.HAS_RAND_BYTES` constant.
Example:
import "core:crypto"
import "core:math/rand"
import "core:fmt"
init_as_system_example :: proc() {
my_rand: rand.Rand
rand.init_as_system(&my_rand)
fmt.println(rand.uint64(&my_rand))
switch crypto.HAS_RAND_BYTES {
case true:
rand.init_as_system(&my_rand)
fmt.println(rand.uint64(&my_rand))
case false:
fmt.println("system random not supported!")
}
}
Possible Output:
@@ -133,7 +137,7 @@ Possible Output:
*/
init_as_system :: proc(r: ^Rand) {
if !#defined(_system_random) {
if !crypto.HAS_RAND_BYTES {
panic(#procedure + " is not supported on this platform yet")
}
r.state = 0
@@ -144,15 +148,14 @@ init_as_system :: proc(r: ^Rand) {
@(private)
_random_u64 :: proc(r: ^Rand) -> u64 {
r := r
if r == nil {
switch {
case r == nil:
r = &global_rand
case r.is_system:
value: u64
crypto.rand_bytes((cast([^]u8)&value)[:size_of(u64)])
return value
}
when #defined(_system_random) {
if r.is_system {
return _system_random()
}
}
old_state := r.state
r.state = old_state * 6364136223846793005 + (r.inc|1)