diff --git a/core/math/rand/rand.odin b/core/math/rand/rand.odin index b52522047..edcfb728f 100644 --- a/core/math/rand/rand.odin +++ b/core/math/rand/rand.odin @@ -1,3 +1,4 @@ + /* Package core:math/rand implements various random number generators */ @@ -31,10 +32,6 @@ Example: fmt.println(rand.uint64()) } -Possible Output: - - 10 - */ set_global_seed :: proc(seed: u64) { init(&global_rand, seed) @@ -58,10 +55,6 @@ Example: fmt.println(rand.uint64(&my_rand)) } -Possible Output: - - 10 - */ @(require_results) create :: proc(seed: u64) -> (res: Rand) { @@ -70,6 +63,7 @@ create :: proc(seed: u64) -> (res: Rand) { return r } + /* Initialises a random number generator. @@ -87,17 +81,13 @@ Example: fmt.println(rand.uint64(&my_rand)) } -Possible Output: - - 10 - */ init :: proc(r: ^Rand, seed: u64) { r.state = 0 r.inc = (seed << 1) | 1 - _random(r) + _random_u64(r) r.state += seed - _random(r) + _random_u64(r) } /* @@ -123,11 +113,6 @@ Example: rand.init_as_system(&my_rand) fmt.println(rand.uint64(&my_rand)) } - -Possible Output: - - 10 - */ init_as_system :: proc(r: ^Rand) { if !#defined(_system_random) { @@ -139,11 +124,9 @@ init_as_system :: proc(r: ^Rand) { } @(private) -_random :: proc(r: ^Rand) -> u32 { +_random_u64 :: proc(r: ^Rand) -> u64 { r := r if r == nil { - // NOTE(bill, 2020-09-07): Do this so that people can - // enforce the global random state if necessary with `nil` r = &global_rand } when #defined(_system_random) { @@ -154,9 +137,9 @@ _random :: proc(r: ^Rand) -> u32 { old_state := r.state r.state = old_state * 6364136223846793005 + (r.inc|1) - xor_shifted := u32(((old_state>>18) ~ old_state) >> 27) - rot := u32(old_state >> 59) - return (xor_shifted >> rot) | (xor_shifted << ((-rot) & 31)) + word := (((old_state >> 59) + 5) ~ old_state) * 12605985483714917081 + rot := (word >> 43) ~ word + return (word >> rot) | (word << ((-rot) & 63)) } /* @@ -179,15 +162,9 @@ Example: my_rand := rand.create(1) fmt.println(rand.uint32(&my_rand)) } - -Possible Output: - - 10 - 389 - */ @(require_results) -uint32 :: proc(r: ^Rand = nil) -> (val: u32) { return _random(r) } +uint32 :: proc(r: ^Rand = nil) -> (val: u32) { return u32(_random_u64(r)) } /* Generates a random 64 bit value using the provided random number generator. If no generator is provided the global random number generator will be used. @@ -209,19 +186,9 @@ Example: my_rand := rand.create(1) fmt.println(rand.uint64(&my_rand)) } - -Possible Output: - - 10 - 389 - */ @(require_results) -uint64 :: proc(r: ^Rand = nil) -> (val: u64) { - a := u64(_random(r)) - b := u64(_random(r)) - return (a<<32) | b -} +uint64 :: proc(r: ^Rand = nil) -> (val: u64) { return _random_u64(r) } /* Generates a random 128 bit value using the provided random number generator. If no generator is provided the global random number generator will be used. @@ -243,20 +210,12 @@ Example: my_rand := rand.create(1) fmt.println(rand.uint128(&my_rand)) } - -Possible Output: - - 10 - 389 - */ @(require_results) uint128 :: proc(r: ^Rand = nil) -> (val: u128) { - a := u128(_random(r)) - b := u128(_random(r)) - c := u128(_random(r)) - d := u128(_random(r)) - return (a<<96) | (b<<64) | (c<<32) | d + a := u128(_random_u64(r)) + b := u128(_random_u64(r)) + return (a<<64) | b } /* @@ -280,14 +239,9 @@ Example: my_rand := rand.create(1) fmt.println(rand.int31(&my_rand)) } - -Possible Output: - - 10 - 389 - */ @(require_results) int31 :: proc(r: ^Rand = nil) -> (val: i32) { return i32(uint32(r) << 1 >> 1) } + /* Generates a random 63 bit value using the provided random number generator. If no generator is provided the global random number generator will be used. The sign bit will always be set to 0, thus all generated numbers will be positive. @@ -309,14 +263,9 @@ Example: my_rand := rand.create(1) fmt.println(rand.int63(&my_rand)) } - -Possible Output: - - 10 - 389 - */ @(require_results) int63 :: proc(r: ^Rand = nil) -> (val: i64) { return i64(uint64(r) << 1 >> 1) } + /* Generates a random 127 bit value using the provided random number generator. If no generator is provided the global random number generator will be used. The sign bit will always be set to 0, thus all generated numbers will be positive. @@ -338,12 +287,6 @@ Example: my_rand := rand.create(1) fmt.println(rand.int127(&my_rand)) } - -Possible Output: - - 10 - 389 - */ @(require_results) int127 :: proc(r: ^Rand = nil) -> (val: i128) { return i128(uint128(r) << 1 >> 1) } @@ -370,12 +313,6 @@ Example: my_rand := rand.create(1) fmt.println(rand.int31_max(1024, &my_rand)) } - -Possible Output: - - 6 - 500 - */ @(require_results) int31_max :: proc(n: i32, r: ^Rand = nil) -> (val: i32) { @@ -392,6 +329,7 @@ int31_max :: proc(n: i32, r: ^Rand = nil) -> (val: i32) { } return v % n } + /* Generates a random 63 bit value in the range `[0, n)` using the provided random number generator. If no generator is provided the global random number generator will be used. @@ -416,10 +354,6 @@ Example: fmt.println(rand.int63_max(1024, &my_rand)) } -Possible Output: - - 6 - 500 */ @(require_results) @@ -437,6 +371,7 @@ int63_max :: proc(n: i64, r: ^Rand = nil) -> (val: i64) { } return v % n } + /* Generates a random 127 bit value in the range `[0, n)` using the provided random number generator. If no generator is provided the global random number generator will be used. @@ -461,10 +396,6 @@ Example: fmt.println(rand.int127_max(1024, &my_rand)) } -Possible Output: - - 6 - 500 */ @(require_results) @@ -482,6 +413,7 @@ int127_max :: proc(n: i128, r: ^Rand = nil) -> (val: i128) { } return v % n } + /* Generates a random integer value in the range `[0, n)` using the provided random number generator. If no generator is provided the global random number generator will be used. @@ -506,10 +438,6 @@ Example: fmt.println(rand.int_max(1024, &my_rand)) } -Possible Output: - - 6 - 500 */ @(require_results) @@ -545,10 +473,6 @@ Example: fmt.println(rand.float64(&my_rand)) } -Possible Output: - - 0.043 - 0.511 */ @(require_results) float64 :: proc(r: ^Rand = nil) -> (val: f64) { return f64(int63_max(1<<53, r)) / (1 << 53) } @@ -574,10 +498,6 @@ Example: fmt.println(rand.float32(&my_rand)) } -Possible Output: - - 0.043 - 0.511 */ @(require_results) float32 :: proc(r: ^Rand = nil) -> (val: f32) { return f32(float64(r)) } @@ -605,13 +525,10 @@ Example: fmt.println(rand.float64_range(600, 900, &my_rand)) } -Possible Output: - - 15.312 - 673.130 */ @(require_results) float64_range :: proc(low, high: f64, r: ^Rand = nil) -> (val: f64) { return (high-low)*float64(r) + low } + /* Generates a random single floating point value in the range `(low, high]` using the provided random number generator. If no generator is provided the global random number generator will be used. @@ -635,10 +552,6 @@ Example: fmt.println(rand.float32_range(600, 900, &my_rand)) } -Possible Output: - - 15.312 - 673.130 */ @(require_results) float32_range :: proc(low, high: f32, r: ^Rand = nil) -> (val: f32) { return (high-low)*float32(r) + low } @@ -665,10 +578,6 @@ Example: fmt.println(data) } -Possible Output: - - 8 - [32, 4, 59, 7, 1, 2, 2, 119] */ @(require_results) @@ -720,10 +629,6 @@ Example: return } -Possible Output: - - [7201011, 3, 9123, 231131] - [19578, 910081, 131, 7] */ @(require_results) @@ -756,10 +661,6 @@ Example: fmt.println(data) // the contents have been shuffled } -Possible Output: - - [1, 2, 3, 4] - [2, 4, 3, 1] */ shuffle :: proc(array: $T/[]$E, r: ^Rand = nil) { @@ -798,10 +699,6 @@ Example: } -Possible Output: - - 3 - 2 2 4 diff --git a/core/math/rand/system_darwin.odin b/core/math/rand/system_darwin.odin index a2890d1b4..756f7fcae 100644 --- a/core/math/rand/system_darwin.odin +++ b/core/math/rand/system_darwin.odin @@ -3,10 +3,10 @@ package rand import "core:sys/darwin" @(require_results) -_system_random :: proc() -> u32 { +_system_random :: proc() -> u64 { for { - value: u32 - ret := darwin.syscall_getentropy(([^]u8)(&value), 4) + value: u64 + ret := darwin.syscall_getentropy(([^]u8)(&value), size_of(value)) if ret < 0 { switch ret { case -4: // EINTR diff --git a/core/math/rand/system_linux.odin b/core/math/rand/system_linux.odin index 0e34228dc..2923b77be 100644 --- a/core/math/rand/system_linux.odin +++ b/core/math/rand/system_linux.odin @@ -3,10 +3,10 @@ package rand import "core:sys/unix" @(require_results) -_system_random :: proc() -> u32 { +_system_random :: proc() -> u64 { for { - value: u32 - ret := unix.sys_getrandom(([^]u8)(&value), 4, 0) + value: u64 + ret := unix.sys_getrandom(([^]u8)(&value), size_of(value), 0) if ret < 0 { switch ret { case -4: // EINTR diff --git a/core/math/rand/system_windows.odin b/core/math/rand/system_windows.odin index b6af9e6a4..c6d68816d 100644 --- a/core/math/rand/system_windows.odin +++ b/core/math/rand/system_windows.odin @@ -3,9 +3,9 @@ package rand import win32 "core:sys/windows" @(require_results) -_system_random :: proc() -> u32 { - value: u32 - status := win32.BCryptGenRandom(nil, ([^]u8)(&value), 4, win32.BCRYPT_USE_SYSTEM_PREFERRED_RNG) +_system_random :: proc() -> u64 { + value: u64 + status := win32.BCryptGenRandom(nil, ([^]u8)(&value), size_of(value), win32.BCRYPT_USE_SYSTEM_PREFERRED_RNG) if status < 0 { panic("BCryptGenRandom failed") }