mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 07:38:48 +00:00
Change algorithm to work on 64-bit integers rather than 32-bit integers internally
This commit is contained in:
+19
-122
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Package core:math/rand implements various random number generators
|
Package core:math/rand implements various random number generators
|
||||||
*/
|
*/
|
||||||
@@ -31,10 +32,6 @@ Example:
|
|||||||
fmt.println(rand.uint64())
|
fmt.println(rand.uint64())
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
|
||||||
|
|
||||||
10
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
set_global_seed :: proc(seed: u64) {
|
set_global_seed :: proc(seed: u64) {
|
||||||
init(&global_rand, seed)
|
init(&global_rand, seed)
|
||||||
@@ -58,10 +55,6 @@ Example:
|
|||||||
fmt.println(rand.uint64(&my_rand))
|
fmt.println(rand.uint64(&my_rand))
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
|
||||||
|
|
||||||
10
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
create :: proc(seed: u64) -> (res: Rand) {
|
create :: proc(seed: u64) -> (res: Rand) {
|
||||||
@@ -70,6 +63,7 @@ create :: proc(seed: u64) -> (res: Rand) {
|
|||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Initialises a random number generator.
|
Initialises a random number generator.
|
||||||
|
|
||||||
@@ -87,17 +81,13 @@ Example:
|
|||||||
fmt.println(rand.uint64(&my_rand))
|
fmt.println(rand.uint64(&my_rand))
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
|
||||||
|
|
||||||
10
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
init :: proc(r: ^Rand, seed: u64) {
|
init :: proc(r: ^Rand, seed: u64) {
|
||||||
r.state = 0
|
r.state = 0
|
||||||
r.inc = (seed << 1) | 1
|
r.inc = (seed << 1) | 1
|
||||||
_random(r)
|
_random_u64(r)
|
||||||
r.state += seed
|
r.state += seed
|
||||||
_random(r)
|
_random_u64(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -123,11 +113,6 @@ Example:
|
|||||||
rand.init_as_system(&my_rand)
|
rand.init_as_system(&my_rand)
|
||||||
fmt.println(rand.uint64(&my_rand))
|
fmt.println(rand.uint64(&my_rand))
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
|
||||||
|
|
||||||
10
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
init_as_system :: proc(r: ^Rand) {
|
init_as_system :: proc(r: ^Rand) {
|
||||||
if !#defined(_system_random) {
|
if !#defined(_system_random) {
|
||||||
@@ -139,11 +124,9 @@ init_as_system :: proc(r: ^Rand) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@(private)
|
@(private)
|
||||||
_random :: proc(r: ^Rand) -> u32 {
|
_random_u64 :: proc(r: ^Rand) -> u64 {
|
||||||
r := r
|
r := r
|
||||||
if r == nil {
|
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
|
r = &global_rand
|
||||||
}
|
}
|
||||||
when #defined(_system_random) {
|
when #defined(_system_random) {
|
||||||
@@ -154,9 +137,9 @@ _random :: proc(r: ^Rand) -> u32 {
|
|||||||
|
|
||||||
old_state := r.state
|
old_state := r.state
|
||||||
r.state = old_state * 6364136223846793005 + (r.inc|1)
|
r.state = old_state * 6364136223846793005 + (r.inc|1)
|
||||||
xor_shifted := u32(((old_state>>18) ~ old_state) >> 27)
|
word := (((old_state >> 59) + 5) ~ old_state) * 12605985483714917081
|
||||||
rot := u32(old_state >> 59)
|
rot := (word >> 43) ~ word
|
||||||
return (xor_shifted >> rot) | (xor_shifted << ((-rot) & 31))
|
return (word >> rot) | (word << ((-rot) & 63))
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -179,15 +162,9 @@ Example:
|
|||||||
my_rand := rand.create(1)
|
my_rand := rand.create(1)
|
||||||
fmt.println(rand.uint32(&my_rand))
|
fmt.println(rand.uint32(&my_rand))
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
|
||||||
|
|
||||||
10
|
|
||||||
389
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(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.
|
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)
|
my_rand := rand.create(1)
|
||||||
fmt.println(rand.uint64(&my_rand))
|
fmt.println(rand.uint64(&my_rand))
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
|
||||||
|
|
||||||
10
|
|
||||||
389
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
uint64 :: proc(r: ^Rand = nil) -> (val: u64) {
|
uint64 :: proc(r: ^Rand = nil) -> (val: u64) { return _random_u64(r) }
|
||||||
a := u64(_random(r))
|
|
||||||
b := u64(_random(r))
|
|
||||||
return (a<<32) | b
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
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.
|
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)
|
my_rand := rand.create(1)
|
||||||
fmt.println(rand.uint128(&my_rand))
|
fmt.println(rand.uint128(&my_rand))
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
|
||||||
|
|
||||||
10
|
|
||||||
389
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
uint128 :: proc(r: ^Rand = nil) -> (val: u128) {
|
uint128 :: proc(r: ^Rand = nil) -> (val: u128) {
|
||||||
a := u128(_random(r))
|
a := u128(_random_u64(r))
|
||||||
b := u128(_random(r))
|
b := u128(_random_u64(r))
|
||||||
c := u128(_random(r))
|
return (a<<64) | b
|
||||||
d := u128(_random(r))
|
|
||||||
return (a<<96) | (b<<64) | (c<<32) | d
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -280,14 +239,9 @@ Example:
|
|||||||
my_rand := rand.create(1)
|
my_rand := rand.create(1)
|
||||||
fmt.println(rand.int31(&my_rand))
|
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) }
|
@(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.
|
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.
|
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)
|
my_rand := rand.create(1)
|
||||||
fmt.println(rand.int63(&my_rand))
|
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) }
|
@(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.
|
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.
|
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)
|
my_rand := rand.create(1)
|
||||||
fmt.println(rand.int127(&my_rand))
|
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) }
|
@(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)
|
my_rand := rand.create(1)
|
||||||
fmt.println(rand.int31_max(1024, &my_rand))
|
fmt.println(rand.int31_max(1024, &my_rand))
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
|
||||||
|
|
||||||
6
|
|
||||||
500
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
int31_max :: proc(n: i32, r: ^Rand = nil) -> (val: i32) {
|
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
|
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.
|
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))
|
fmt.println(rand.int63_max(1024, &my_rand))
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
|
||||||
|
|
||||||
6
|
|
||||||
500
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
@@ -437,6 +371,7 @@ int63_max :: proc(n: i64, r: ^Rand = nil) -> (val: i64) {
|
|||||||
}
|
}
|
||||||
return v % n
|
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.
|
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))
|
fmt.println(rand.int127_max(1024, &my_rand))
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
|
||||||
|
|
||||||
6
|
|
||||||
500
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
@@ -482,6 +413,7 @@ int127_max :: proc(n: i128, r: ^Rand = nil) -> (val: i128) {
|
|||||||
}
|
}
|
||||||
return v % n
|
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.
|
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))
|
fmt.println(rand.int_max(1024, &my_rand))
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
|
||||||
|
|
||||||
6
|
|
||||||
500
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
@@ -545,10 +473,6 @@ Example:
|
|||||||
fmt.println(rand.float64(&my_rand))
|
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) }
|
@(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))
|
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)) }
|
@(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))
|
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 }
|
@(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.
|
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))
|
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 }
|
@(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)
|
fmt.println(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
|
||||||
|
|
||||||
8
|
|
||||||
[32, 4, 59, 7, 1, 2, 2, 119]
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
@@ -720,10 +629,6 @@ Example:
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Possible Output:
|
|
||||||
|
|
||||||
[7201011, 3, 9123, 231131]
|
|
||||||
[19578, 910081, 131, 7]
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
@@ -756,10 +661,6 @@ Example:
|
|||||||
fmt.println(data) // the contents have been shuffled
|
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) {
|
shuffle :: proc(array: $T/[]$E, r: ^Rand = nil) {
|
||||||
@@ -798,10 +699,6 @@ Example:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Possible Output:
|
|
||||||
|
|
||||||
3
|
|
||||||
2
|
|
||||||
2
|
2
|
||||||
4
|
4
|
||||||
|
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ package rand
|
|||||||
import "core:sys/darwin"
|
import "core:sys/darwin"
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
_system_random :: proc() -> u32 {
|
_system_random :: proc() -> u64 {
|
||||||
for {
|
for {
|
||||||
value: u32
|
value: u64
|
||||||
ret := darwin.syscall_getentropy(([^]u8)(&value), 4)
|
ret := darwin.syscall_getentropy(([^]u8)(&value), size_of(value))
|
||||||
if ret < 0 {
|
if ret < 0 {
|
||||||
switch ret {
|
switch ret {
|
||||||
case -4: // EINTR
|
case -4: // EINTR
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ package rand
|
|||||||
import "core:sys/unix"
|
import "core:sys/unix"
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
_system_random :: proc() -> u32 {
|
_system_random :: proc() -> u64 {
|
||||||
for {
|
for {
|
||||||
value: u32
|
value: u64
|
||||||
ret := unix.sys_getrandom(([^]u8)(&value), 4, 0)
|
ret := unix.sys_getrandom(([^]u8)(&value), size_of(value), 0)
|
||||||
if ret < 0 {
|
if ret < 0 {
|
||||||
switch ret {
|
switch ret {
|
||||||
case -4: // EINTR
|
case -4: // EINTR
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ package rand
|
|||||||
import win32 "core:sys/windows"
|
import win32 "core:sys/windows"
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
_system_random :: proc() -> u32 {
|
_system_random :: proc() -> u64 {
|
||||||
value: u32
|
value: u64
|
||||||
status := win32.BCryptGenRandom(nil, ([^]u8)(&value), 4, win32.BCRYPT_USE_SYSTEM_PREFERRED_RNG)
|
status := win32.BCryptGenRandom(nil, ([^]u8)(&value), size_of(value), win32.BCRYPT_USE_SYSTEM_PREFERRED_RNG)
|
||||||
if status < 0 {
|
if status < 0 {
|
||||||
panic("BCryptGenRandom failed")
|
panic("BCryptGenRandom failed")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user