|
@@ -10,52 +10,18 @@ import "core:crypto"
|
|
|
import "core:math"
|
|
|
import "core:mem"
|
|
|
|
|
|
-Rand :: struct {
|
|
|
- state: u64,
|
|
|
- inc: u64,
|
|
|
- is_system: bool,
|
|
|
-}
|
|
|
+Default_Random_State :: runtime.Default_Random_State
|
|
|
+default_random_generator :: runtime.default_random_generator
|
|
|
|
|
|
-to_random_generator :: proc(r: ^Rand) -> runtime.Random_Generator {
|
|
|
- return {
|
|
|
- procedure = proc(data: rawptr, mode: runtime.Random_Generator_Mode, p: []byte) {
|
|
|
- r := (^Rand)(data)
|
|
|
- switch mode {
|
|
|
- case .Read:
|
|
|
- _ = read(p, r)
|
|
|
-
|
|
|
- case .Reset:
|
|
|
- if r.is_system {
|
|
|
- return
|
|
|
- }
|
|
|
- seed: u64
|
|
|
- runtime.mem_copy_non_overlapping(&seed, raw_data(p), min(size_of(seed), len(p)))
|
|
|
- init(r, seed)
|
|
|
-
|
|
|
-
|
|
|
- case .Query_Info:
|
|
|
- if len(p) != size_of(runtime.Random_Generator_Query_Info) {
|
|
|
- return
|
|
|
- }
|
|
|
- info := (^runtime.Random_Generator_Query_Info)(raw_data(p))
|
|
|
- info^ += {.Uniform}
|
|
|
- if r.is_system {
|
|
|
- info^ += {.External_Entropy}
|
|
|
- } else {
|
|
|
- info^ += {.Resettable}
|
|
|
- }
|
|
|
- }
|
|
|
- },
|
|
|
- data = r,
|
|
|
- }
|
|
|
+create :: proc(seed: u64) -> (state: Default_Random_State) {
|
|
|
+ seed := seed
|
|
|
+ runtime.default_random_generator(&state)
|
|
|
+ runtime.default_random_generator_proc(&state, .Reset, ([^]byte)(&seed)[:size_of(seed)])
|
|
|
+ return
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-@(private)
|
|
|
-global_rand := create(u64(intrinsics.read_cycle_counter()))
|
|
|
-
|
|
|
/*
|
|
|
-Sets the seed used by the global random number generator.
|
|
|
+Reset the seed used by the context.random_generator.
|
|
|
|
|
|
Inputs:
|
|
|
- seed: The seed value
|
|
@@ -72,143 +38,46 @@ Example:
|
|
|
Possible Output:
|
|
|
|
|
|
10
|
|
|
-
|
|
|
*/
|
|
|
+@(deprecated="Prefer `rand.reset`")
|
|
|
set_global_seed :: proc(seed: u64) {
|
|
|
- init(&global_rand, seed)
|
|
|
+ runtime.random_generator_reset_u64(context.random_generator, seed)
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
-Creates a new random number generator.
|
|
|
+Reset the seed used by the context.random_generator.
|
|
|
|
|
|
Inputs:
|
|
|
-- seed: The seed value to create the random number generator with
|
|
|
-
|
|
|
-Returns:
|
|
|
-- res: The created random number generator
|
|
|
-
|
|
|
-Example:
|
|
|
- import "core:math/rand"
|
|
|
- import "core:fmt"
|
|
|
-
|
|
|
- create_example :: proc() {
|
|
|
- my_rand := rand.create(1)
|
|
|
- fmt.println(rand.uint64(&my_rand))
|
|
|
- }
|
|
|
-
|
|
|
-Possible Output:
|
|
|
-
|
|
|
- 10
|
|
|
-
|
|
|
-*/
|
|
|
-@(require_results)
|
|
|
-create :: proc(seed: u64) -> (res: Rand) {
|
|
|
- r: Rand
|
|
|
- init(&r, seed)
|
|
|
- return r
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-/*
|
|
|
-Initialises a random number generator.
|
|
|
-
|
|
|
-Inputs:
|
|
|
-- r: The random number generator to initialise
|
|
|
-- seed: The seed value to initialise this random number generator
|
|
|
+- seed: The seed value
|
|
|
|
|
|
Example:
|
|
|
import "core:math/rand"
|
|
|
import "core:fmt"
|
|
|
|
|
|
- init_example :: proc() {
|
|
|
- my_rand: rand.Rand
|
|
|
- rand.init(&my_rand, 1)
|
|
|
- fmt.println(rand.uint64(&my_rand))
|
|
|
+ set_global_seed_example :: proc() {
|
|
|
+ rand.set_global_seed(1)
|
|
|
+ fmt.println(rand.uint64())
|
|
|
}
|
|
|
|
|
|
Possible Output:
|
|
|
|
|
|
10
|
|
|
-
|
|
|
*/
|
|
|
-init :: proc(r: ^Rand, seed: u64) {
|
|
|
- r.state = 0
|
|
|
- r.inc = (seed << 1) | 1
|
|
|
- _random_u64(r)
|
|
|
- r.state += seed
|
|
|
- _random_u64(r)
|
|
|
+reset :: proc(seed: u64) {
|
|
|
+ runtime.random_generator_reset_u64(context.random_generator, seed)
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
-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 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
|
|
|
- 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:
|
|
|
-
|
|
|
- 10
|
|
|
-
|
|
|
-*/
|
|
|
-init_as_system :: proc(r: ^Rand) {
|
|
|
- if !crypto.HAS_RAND_BYTES {
|
|
|
- panic(#procedure + " is not supported on this platform yet")
|
|
|
- }
|
|
|
- r.state = 0
|
|
|
- r.inc = 0
|
|
|
- r.is_system = true
|
|
|
-}
|
|
|
|
|
|
@(private)
|
|
|
-_random_u64 :: proc(r: ^Rand) -> u64 {
|
|
|
- r := r
|
|
|
- switch {
|
|
|
- case r == nil:
|
|
|
- if res: u64; runtime.random_generator_read_ptr(context.random_generator, &res, size_of(res)) {
|
|
|
- return res
|
|
|
- }
|
|
|
-
|
|
|
- r = &global_rand
|
|
|
- case r.is_system:
|
|
|
- value: u64
|
|
|
- crypto.rand_bytes((cast([^]u8)&value)[:size_of(u64)])
|
|
|
- return value
|
|
|
- }
|
|
|
-
|
|
|
- old_state := r.state
|
|
|
- r.state = old_state * 6364136223846793005 + (r.inc|1)
|
|
|
- xor_shifted := (((old_state >> 59) + 5) ~ old_state) * 12605985483714917081
|
|
|
- rot := (old_state >> 59)
|
|
|
- return (xor_shifted >> rot) | (xor_shifted << ((-rot) & 63))
|
|
|
+_random_u64 :: proc() -> (res: u64) {
|
|
|
+ ok := runtime.random_generator_read_ptr(context.random_generator, &res, size_of(res))
|
|
|
+ assert(ok, "uninitialized context.random_generator")
|
|
|
+ return
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
Generates a random 32 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
|
|
|
|
|
|
-Inputs:
|
|
|
-- r: The random number generator to use, or nil for the global generator
|
|
|
-
|
|
|
Returns:
|
|
|
- val: A random unsigned 32 bit value
|
|
|
|
|
@@ -217,11 +86,7 @@ Example:
|
|
|
import "core:fmt"
|
|
|
|
|
|
uint32_example :: proc() {
|
|
|
- // Using the global random number generator
|
|
|
fmt.println(rand.uint32())
|
|
|
- // Using local random number generator
|
|
|
- my_rand := rand.create(1)
|
|
|
- fmt.println(rand.uint32(&my_rand))
|
|
|
}
|
|
|
|
|
|
Possible Output:
|
|
@@ -231,14 +96,11 @@ Possible Output:
|
|
|
|
|
|
*/
|
|
|
@(require_results)
|
|
|
-uint32 :: proc(r: ^Rand = nil) -> (val: u32) { return u32(_random_u64(r)) }
|
|
|
+uint32 :: proc() -> (val: u32) { return u32(_random_u64()) }
|
|
|
|
|
|
/*
|
|
|
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.
|
|
|
|
|
|
-Inputs:
|
|
|
-- r: The random number generator to use, or nil for the global generator
|
|
|
-
|
|
|
Returns:
|
|
|
- val: A random unsigned 64 bit value
|
|
|
|
|
@@ -247,11 +109,7 @@ Example:
|
|
|
import "core:fmt"
|
|
|
|
|
|
uint64_example :: proc() {
|
|
|
- // Using the global random number generator
|
|
|
fmt.println(rand.uint64())
|
|
|
- // Using local random number generator
|
|
|
- my_rand := rand.create(1)
|
|
|
- fmt.println(rand.uint64(&my_rand))
|
|
|
}
|
|
|
|
|
|
Possible Output:
|
|
@@ -261,14 +119,11 @@ Possible Output:
|
|
|
|
|
|
*/
|
|
|
@(require_results)
|
|
|
-uint64 :: proc(r: ^Rand = nil) -> (val: u64) { return _random_u64(r) }
|
|
|
+uint64 :: proc() -> (val: u64) { return _random_u64() }
|
|
|
|
|
|
/*
|
|
|
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.
|
|
|
|
|
|
-Inputs:
|
|
|
-- r: The random number generator to use, or nil for the global generator
|
|
|
-
|
|
|
Returns:
|
|
|
- val: A random unsigned 128 bit value
|
|
|
|
|
@@ -277,11 +132,7 @@ Example:
|
|
|
import "core:fmt"
|
|
|
|
|
|
uint128_example :: proc() {
|
|
|
- // Using the global random number generator
|
|
|
fmt.println(rand.uint128())
|
|
|
- // Using local random number generator
|
|
|
- my_rand := rand.create(1)
|
|
|
- fmt.println(rand.uint128(&my_rand))
|
|
|
}
|
|
|
|
|
|
Possible Output:
|
|
@@ -291,9 +142,9 @@ Possible Output:
|
|
|
|
|
|
*/
|
|
|
@(require_results)
|
|
|
-uint128 :: proc(r: ^Rand = nil) -> (val: u128) {
|
|
|
- a := u128(_random_u64(r))
|
|
|
- b := u128(_random_u64(r))
|
|
|
+uint128 :: proc() -> (val: u128) {
|
|
|
+ a := u128(_random_u64())
|
|
|
+ b := u128(_random_u64())
|
|
|
return (a<<64) | b
|
|
|
}
|
|
|
|
|
@@ -301,9 +152,6 @@ uint128 :: proc(r: ^Rand = nil) -> (val: u128) {
|
|
|
Generates a random 31 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.
|
|
|
|
|
|
-Inputs:
|
|
|
-- r: The random number generator to use, or nil for the global generator
|
|
|
-
|
|
|
Returns:
|
|
|
- val: A random 31 bit value
|
|
|
|
|
@@ -312,11 +160,7 @@ Example:
|
|
|
import "core:fmt"
|
|
|
|
|
|
int31_example :: proc() {
|
|
|
- // Using the global random number generator
|
|
|
fmt.println(rand.int31())
|
|
|
- // Using local random number generator
|
|
|
- my_rand := rand.create(1)
|
|
|
- fmt.println(rand.int31(&my_rand))
|
|
|
}
|
|
|
|
|
|
Possible Output:
|
|
@@ -325,15 +169,12 @@ Possible Output:
|
|
|
389
|
|
|
|
|
|
*/
|
|
|
-@(require_results) int31 :: proc(r: ^Rand = nil) -> (val: i32) { return i32(uint32(r) << 1 >> 1) }
|
|
|
+@(require_results) int31 :: proc() -> (val: i32) { return i32(uint32() << 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.
|
|
|
|
|
|
-Inputs:
|
|
|
-- r: The random number generator to use, or nil for the global generator
|
|
|
-
|
|
|
Returns:
|
|
|
- val: A random 63 bit value
|
|
|
|
|
@@ -342,11 +183,7 @@ Example:
|
|
|
import "core:fmt"
|
|
|
|
|
|
int63_example :: proc() {
|
|
|
- // Using the global random number generator
|
|
|
fmt.println(rand.int63())
|
|
|
- // Using local random number generator
|
|
|
- my_rand := rand.create(1)
|
|
|
- fmt.println(rand.int63(&my_rand))
|
|
|
}
|
|
|
|
|
|
Possible Output:
|
|
@@ -355,15 +192,12 @@ Possible Output:
|
|
|
389
|
|
|
|
|
|
*/
|
|
|
-@(require_results) int63 :: proc(r: ^Rand = nil) -> (val: i64) { return i64(uint64(r) << 1 >> 1) }
|
|
|
+@(require_results) int63 :: proc() -> (val: i64) { return i64(uint64() << 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.
|
|
|
|
|
|
-Inputs:
|
|
|
-- r: The random number generator to use, or nil for the global generator
|
|
|
-
|
|
|
Returns:
|
|
|
- val: A random 127 bit value
|
|
|
|
|
@@ -372,11 +206,7 @@ Example:
|
|
|
import "core:fmt"
|
|
|
|
|
|
int127_example :: proc() {
|
|
|
- // Using the global random number generator
|
|
|
fmt.println(rand.int127())
|
|
|
- // Using local random number generator
|
|
|
- my_rand := rand.create(1)
|
|
|
- fmt.println(rand.int127(&my_rand))
|
|
|
}
|
|
|
|
|
|
Possible Output:
|
|
@@ -385,14 +215,13 @@ Possible Output:
|
|
|
389
|
|
|
|
|
|
*/
|
|
|
-@(require_results) int127 :: proc(r: ^Rand = nil) -> (val: i128) { return i128(uint128(r) << 1 >> 1) }
|
|
|
+@(require_results) int127 :: proc() -> (val: i128) { return i128(uint128() << 1 >> 1) }
|
|
|
|
|
|
/*
|
|
|
Generates a random 31 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.
|
|
|
|
|
|
Inputs:
|
|
|
- n: The upper bound of the generated number, this value is exclusive
|
|
|
-- r: The random number generator to use, or nil for the global generator
|
|
|
|
|
|
Returns:
|
|
|
- val: A random 31 bit value in the range `[0, n)`
|
|
@@ -404,11 +233,7 @@ Example:
|
|
|
import "core:fmt"
|
|
|
|
|
|
int31_max_example :: proc() {
|
|
|
- // Using the global random number generator
|
|
|
fmt.println(rand.int31_max(16))
|
|
|
- // Using local random number generator
|
|
|
- my_rand := rand.create(1)
|
|
|
- fmt.println(rand.int31_max(1024, &my_rand))
|
|
|
}
|
|
|
|
|
|
Possible Output:
|
|
@@ -418,17 +243,17 @@ Possible Output:
|
|
|
|
|
|
*/
|
|
|
@(require_results)
|
|
|
-int31_max :: proc(n: i32, r: ^Rand = nil) -> (val: i32) {
|
|
|
+int31_max :: proc(n: i32) -> (val: i32) {
|
|
|
if n <= 0 {
|
|
|
panic("Invalid argument to int31_max")
|
|
|
}
|
|
|
if n&(n-1) == 0 {
|
|
|
- return int31(r) & (n-1)
|
|
|
+ return int31() & (n-1)
|
|
|
}
|
|
|
max := i32((1<<31) - 1 - (1<<31)%u32(n))
|
|
|
- v := int31(r)
|
|
|
+ v := int31()
|
|
|
for v > max {
|
|
|
- v = int31(r)
|
|
|
+ v = int31()
|
|
|
}
|
|
|
return v % n
|
|
|
}
|
|
@@ -438,7 +263,6 @@ Generates a random 63 bit value in the range `[0, n)` using the provided random
|
|
|
|
|
|
Inputs:
|
|
|
- n: The upper bound of the generated number, this value is exclusive
|
|
|
-- r: The random number generator to use, or nil for the global generator
|
|
|
|
|
|
Returns:
|
|
|
- val: A random 63 bit value in the range `[0, n)`
|
|
@@ -450,11 +274,7 @@ Example:
|
|
|
import "core:fmt"
|
|
|
|
|
|
int63_max_example :: proc() {
|
|
|
- // Using the global random number generator
|
|
|
fmt.println(rand.int63_max(16))
|
|
|
- // Using local random number generator
|
|
|
- my_rand := rand.create(1)
|
|
|
- fmt.println(rand.int63_max(1024, &my_rand))
|
|
|
}
|
|
|
|
|
|
Possible Output:
|
|
@@ -464,17 +284,17 @@ Possible Output:
|
|
|
|
|
|
*/
|
|
|
@(require_results)
|
|
|
-int63_max :: proc(n: i64, r: ^Rand = nil) -> (val: i64) {
|
|
|
+int63_max :: proc(n: i64) -> (val: i64) {
|
|
|
if n <= 0 {
|
|
|
panic("Invalid argument to int63_max")
|
|
|
}
|
|
|
if n&(n-1) == 0 {
|
|
|
- return int63(r) & (n-1)
|
|
|
+ return int63() & (n-1)
|
|
|
}
|
|
|
max := i64((1<<63) - 1 - (1<<63)%u64(n))
|
|
|
- v := int63(r)
|
|
|
+ v := int63()
|
|
|
for v > max {
|
|
|
- v = int63(r)
|
|
|
+ v = int63()
|
|
|
}
|
|
|
return v % n
|
|
|
}
|
|
@@ -484,7 +304,6 @@ Generates a random 127 bit value in the range `[0, n)` using the provided random
|
|
|
|
|
|
Inputs:
|
|
|
- n: The upper bound of the generated number, this value is exclusive
|
|
|
-- r: The random number generator to use, or nil for the global generator
|
|
|
|
|
|
Returns:
|
|
|
- val: A random 127 bit value in the range `[0, n)`
|
|
@@ -496,11 +315,7 @@ Example:
|
|
|
import "core:fmt"
|
|
|
|
|
|
int127_max_example :: proc() {
|
|
|
- // Using the global random number generator
|
|
|
fmt.println(rand.int127_max(16))
|
|
|
- // Using local random number generator
|
|
|
- my_rand := rand.create(1)
|
|
|
- fmt.println(rand.int127_max(1024, &my_rand))
|
|
|
}
|
|
|
|
|
|
Possible Output:
|
|
@@ -510,17 +325,17 @@ Possible Output:
|
|
|
|
|
|
*/
|
|
|
@(require_results)
|
|
|
-int127_max :: proc(n: i128, r: ^Rand = nil) -> (val: i128) {
|
|
|
+int127_max :: proc(n: i128) -> (val: i128) {
|
|
|
if n <= 0 {
|
|
|
panic("Invalid argument to int127_max")
|
|
|
}
|
|
|
if n&(n-1) == 0 {
|
|
|
- return int127(r) & (n-1)
|
|
|
+ return int127() & (n-1)
|
|
|
}
|
|
|
max := i128((1<<127) - 1 - (1<<127)%u128(n))
|
|
|
- v := int127(r)
|
|
|
+ v := int127()
|
|
|
for v > max {
|
|
|
- v = int127(r)
|
|
|
+ v = int127()
|
|
|
}
|
|
|
return v % n
|
|
|
}
|
|
@@ -530,7 +345,6 @@ Generates a random integer value in the range `[0, n)` using the provided random
|
|
|
|
|
|
Inputs:
|
|
|
- n: The upper bound of the generated number, this value is exclusive
|
|
|
-- r: The random number generator to use, or nil for the global generator
|
|
|
|
|
|
Returns:
|
|
|
- val: A random integer value in the range `[0, n)`
|
|
@@ -542,11 +356,7 @@ Example:
|
|
|
import "core:fmt"
|
|
|
|
|
|
int_max_example :: proc() {
|
|
|
- // Using the global random number generator
|
|
|
fmt.println(rand.int_max(16))
|
|
|
- // Using local random number generator
|
|
|
- my_rand := rand.create(1)
|
|
|
- fmt.println(rand.int_max(1024, &my_rand))
|
|
|
}
|
|
|
|
|
|
Possible Output:
|
|
@@ -556,23 +366,20 @@ Possible Output:
|
|
|
|
|
|
*/
|
|
|
@(require_results)
|
|
|
-int_max :: proc(n: int, r: ^Rand = nil) -> (val: int) {
|
|
|
+int_max :: proc(n: int) -> (val: int) {
|
|
|
if n <= 0 {
|
|
|
panic("Invalid argument to int_max")
|
|
|
}
|
|
|
when size_of(int) == 4 {
|
|
|
- return int(int31_max(i32(n), r))
|
|
|
+ return int(int31_max(i32(n)))
|
|
|
} else {
|
|
|
- return int(int63_max(i64(n), r))
|
|
|
+ return int(int63_max(i64(n)))
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
Generates a random double floating point value in the range `[0, 1)` using the provided random number generator. If no generator is provided the global random number generator will be used.
|
|
|
|
|
|
-Inputs:
|
|
|
-- r: The random number generator to use, or nil for the global generator
|
|
|
-
|
|
|
Returns:
|
|
|
- val: A random double floating point value in the range `[0, 1)`
|
|
|
|
|
@@ -581,11 +388,7 @@ Example:
|
|
|
import "core:fmt"
|
|
|
|
|
|
float64_example :: proc() {
|
|
|
- // Using the global random number generator
|
|
|
fmt.println(rand.float64())
|
|
|
- // Using local random number generator
|
|
|
- my_rand := rand.create(1)
|
|
|
- fmt.println(rand.float64(&my_rand))
|
|
|
}
|
|
|
|
|
|
Possible Output:
|
|
@@ -594,14 +397,11 @@ Possible Output:
|
|
|
0.511
|
|
|
|
|
|
*/
|
|
|
-@(require_results) float64 :: proc(r: ^Rand = nil) -> (val: f64) { return f64(int63_max(1<<53, r)) / (1 << 53) }
|
|
|
+@(require_results) float64 :: proc() -> (val: f64) { return f64(int63_max(1<<53)) / (1 << 53) }
|
|
|
|
|
|
/*
|
|
|
Generates a random single floating point value in the range `[0, 1)` using the provided random number generator. If no generator is provided the global random number generator will be used.
|
|
|
|
|
|
-Inputs:
|
|
|
-- r: The random number generator to use, or nil for the global generator
|
|
|
-
|
|
|
Returns:
|
|
|
- val: A random single floating point value in the range `[0, 1)`
|
|
|
|
|
@@ -610,11 +410,7 @@ Example:
|
|
|
import "core:fmt"
|
|
|
|
|
|
float32_example :: proc() {
|
|
|
- // Using the global random number generator
|
|
|
fmt.println(rand.float32())
|
|
|
- // Using local random number generator
|
|
|
- my_rand := rand.create(1)
|
|
|
- fmt.println(rand.float32(&my_rand))
|
|
|
}
|
|
|
|
|
|
Possible Output:
|
|
@@ -623,7 +419,7 @@ Possible Output:
|
|
|
0.511
|
|
|
|
|
|
*/
|
|
|
-@(require_results) float32 :: proc(r: ^Rand = nil) -> (val: f32) { return f32(int31_max(1<<24, r)) / (1 << 24) }
|
|
|
+@(require_results) float32 :: proc() -> (val: f32) { return f32(int31_max(1<<24)) / (1 << 24) }
|
|
|
|
|
|
/*
|
|
|
Generates a random double 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.
|
|
@@ -633,7 +429,6 @@ WARNING: Panics if `high < low`
|
|
|
Inputs:
|
|
|
- low: The lower bounds of the value, this value is inclusive
|
|
|
- high: The upper bounds of the value, this value is exclusive
|
|
|
-- r: The random number generator to use, or nil for the global generator
|
|
|
|
|
|
Returns:
|
|
|
- val: A random double floating point value in the range [low, high)
|
|
@@ -643,11 +438,7 @@ Example:
|
|
|
import "core:fmt"
|
|
|
|
|
|
float64_range_example :: proc() {
|
|
|
- // Using the global random number generator
|
|
|
fmt.println(rand.float64_range(-10, 300))
|
|
|
- // Using local random number generator
|
|
|
- my_rand := rand.create(1)
|
|
|
- fmt.println(rand.float64_range(600, 900, &my_rand))
|
|
|
}
|
|
|
|
|
|
Possible Output:
|
|
@@ -656,9 +447,9 @@ Possible Output:
|
|
|
673.130
|
|
|
|
|
|
*/
|
|
|
-@(require_results) float64_range :: proc(low, high: f64, r: ^Rand = nil) -> (val: f64) {
|
|
|
+@(require_results) float64_range :: proc(low, high: f64) -> (val: f64) {
|
|
|
assert(low <= high, "low must be lower than or equal to high")
|
|
|
- val = (high-low)*float64(r) + low
|
|
|
+ val = (high-low)*float64() + low
|
|
|
if val >= high {
|
|
|
val = max(low, high * (1 - math.F64_EPSILON))
|
|
|
}
|
|
@@ -671,7 +462,6 @@ Generates a random single floating point value in the range `[low, high)` using
|
|
|
Inputs:
|
|
|
- low: The lower bounds of the value, this value is inclusive
|
|
|
- high: The upper bounds of the value, this value is exclusive
|
|
|
-- r: The random number generator to use, or nil for the global generator
|
|
|
|
|
|
Returns:
|
|
|
- val: A random single floating point value in the range [low, high)
|
|
@@ -683,11 +473,7 @@ Example:
|
|
|
import "core:fmt"
|
|
|
|
|
|
float32_range_example :: proc() {
|
|
|
- // Using the global random number generator
|
|
|
fmt.println(rand.float32_range(-10, 300))
|
|
|
- // Using local random number generator
|
|
|
- my_rand := rand.create(1)
|
|
|
- fmt.println(rand.float32_range(600, 900, &my_rand))
|
|
|
}
|
|
|
|
|
|
Possible Output:
|
|
@@ -696,9 +482,9 @@ Possible Output:
|
|
|
673.130
|
|
|
|
|
|
*/
|
|
|
-@(require_results) float32_range :: proc(low, high: f32, r: ^Rand = nil) -> (val: f32) {
|
|
|
+@(require_results) float32_range :: proc(low, high: f32) -> (val: f32) {
|
|
|
assert(low <= high, "low must be lower than or equal to high")
|
|
|
- val = (high-low)*float32(r) + low
|
|
|
+ val = (high-low)*float32() + low
|
|
|
if val >= high {
|
|
|
val = max(low, high * (1 - math.F32_EPSILON))
|
|
|
}
|
|
@@ -711,7 +497,6 @@ Due to floating point precision there is no guarantee if the upper and lower bou
|
|
|
|
|
|
Inputs:
|
|
|
- p: The byte slice to fill
|
|
|
-- r: The random number generator to use, or nil for the global generator
|
|
|
|
|
|
Returns:
|
|
|
- n: The number of bytes generated
|
|
@@ -721,7 +506,6 @@ Example:
|
|
|
import "core:fmt"
|
|
|
|
|
|
read_example :: proc() {
|
|
|
- // Using the global random number generator
|
|
|
data: [8]byte
|
|
|
n := rand.read(data[:])
|
|
|
fmt.println(n)
|
|
@@ -735,12 +519,12 @@ Possible Output:
|
|
|
|
|
|
*/
|
|
|
@(require_results)
|
|
|
-read :: proc(p: []byte, r: ^Rand = nil) -> (n: int) {
|
|
|
+read :: proc(p: []byte) -> (n: int) {
|
|
|
pos := i8(0)
|
|
|
val := i64(0)
|
|
|
for n = 0; n < len(p); n += 1 {
|
|
|
if pos == 0 {
|
|
|
- val = int63(r)
|
|
|
+ val = int63()
|
|
|
pos = 7
|
|
|
}
|
|
|
p[n] = byte(val)
|
|
@@ -757,7 +541,6 @@ Creates a slice of `int` filled with random values using the provided random num
|
|
|
|
|
|
Inputs:
|
|
|
- n: The size of the created slice
|
|
|
-- r: The random number generator to use, or nil for the global generator
|
|
|
- allocator: (default: context.allocator)
|
|
|
|
|
|
Returns:
|
|
@@ -770,16 +553,10 @@ Example:
|
|
|
import "core:fmt"
|
|
|
|
|
|
perm_example :: proc() -> (err: mem.Allocator_Error) {
|
|
|
- // Using the global random number generator and using the context allocator
|
|
|
data := rand.perm(4) or_return
|
|
|
fmt.println(data)
|
|
|
defer delete(data, context.allocator)
|
|
|
|
|
|
- // Using local random number generator and temp allocator
|
|
|
- my_rand := rand.create(1)
|
|
|
- data_tmp := rand.perm(4, &my_rand, context.temp_allocator) or_return
|
|
|
- fmt.println(data_tmp)
|
|
|
-
|
|
|
return
|
|
|
}
|
|
|
|
|
@@ -790,10 +567,10 @@ Possible Output:
|
|
|
|
|
|
*/
|
|
|
@(require_results)
|
|
|
-perm :: proc(n: int, r: ^Rand = nil, allocator := context.allocator) -> (res: []int, err: mem.Allocator_Error) #optional_allocator_error {
|
|
|
+perm :: proc(n: int, allocator := context.allocator) -> (res: []int, err: mem.Allocator_Error) #optional_allocator_error {
|
|
|
m := make([]int, n, allocator) or_return
|
|
|
for i := 0; i < n; i += 1 {
|
|
|
- j := int_max(i+1, r)
|
|
|
+ j := int_max(i+1)
|
|
|
m[i] = m[j]
|
|
|
m[j] = i
|
|
|
}
|
|
@@ -805,14 +582,12 @@ Randomizes the ordering of elements for the provided slice. If no generator is p
|
|
|
|
|
|
Inputs:
|
|
|
- array: The slice to randomize
|
|
|
-- r: The random number generator to use, or nil for the global generator
|
|
|
|
|
|
Example:
|
|
|
import "core:math/rand"
|
|
|
import "core:fmt"
|
|
|
|
|
|
shuffle_example :: proc() {
|
|
|
- // Using the global random number generator
|
|
|
data: [4]int = { 1, 2, 3, 4 }
|
|
|
fmt.println(data) // the contents are in order
|
|
|
rand.shuffle(data[:])
|
|
@@ -825,14 +600,14 @@ Possible Output:
|
|
|
[2, 4, 3, 1]
|
|
|
|
|
|
*/
|
|
|
-shuffle :: proc(array: $T/[]$E, r: ^Rand = nil) {
|
|
|
+shuffle :: proc(array: $T/[]$E) {
|
|
|
n := i64(len(array))
|
|
|
if n < 2 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
for i := i64(n - 1); i > 0; i -= 1 {
|
|
|
- j := int63_max(i + 1, r)
|
|
|
+ j := int63_max(i + 1)
|
|
|
array[i], array[j] = array[j], array[i]
|
|
|
}
|
|
|
}
|
|
@@ -842,7 +617,6 @@ Returns a random element from the provided slice. If no generator is provided th
|
|
|
|
|
|
Inputs:
|
|
|
- array: The slice to choose an element from
|
|
|
-- r: The random number generator to use, or nil for the global generator
|
|
|
|
|
|
Returns:
|
|
|
- res: A random element from `array`
|
|
@@ -852,7 +626,6 @@ Example:
|
|
|
import "core:fmt"
|
|
|
|
|
|
choice_example :: proc() {
|
|
|
- // Using the global random number generator
|
|
|
data: [4]int = { 1, 2, 3, 4 }
|
|
|
fmt.println(rand.choice(data[:]))
|
|
|
fmt.println(rand.choice(data[:]))
|
|
@@ -869,17 +642,17 @@ Possible Output:
|
|
|
|
|
|
*/
|
|
|
@(require_results)
|
|
|
-choice :: proc(array: $T/[]$E, r: ^Rand = nil) -> (res: E) {
|
|
|
+choice :: proc(array: $T/[]$E) -> (res: E) {
|
|
|
n := i64(len(array))
|
|
|
if n < 1 {
|
|
|
return E{}
|
|
|
}
|
|
|
- return array[int63_max(n, r)]
|
|
|
+ return array[int63_max(n)]
|
|
|
}
|
|
|
|
|
|
|
|
|
@(require_results)
|
|
|
-choice_enum :: proc($T: typeid, r: ^Rand = nil) -> T
|
|
|
+choice_enum :: proc($T: typeid) -> T
|
|
|
where
|
|
|
intrinsics.type_is_enum(T),
|
|
|
size_of(T) <= 8,
|
|
@@ -887,11 +660,11 @@ choice_enum :: proc($T: typeid, r: ^Rand = nil) -> T
|
|
|
{
|
|
|
when intrinsics.type_is_unsigned(intrinsics.type_core_type(T)) &&
|
|
|
u64(max(T)) > u64(max(i64)) {
|
|
|
- i := uint64(r) % u64(len(T))
|
|
|
+ i := uint64() % u64(len(T))
|
|
|
i += u64(min(T))
|
|
|
return T(i)
|
|
|
} else {
|
|
|
- i := int63_max(i64(len(T)), r)
|
|
|
+ i := int63_max(i64(len(T)))
|
|
|
i += i64(min(T))
|
|
|
return T(i)
|
|
|
}
|