mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-28 18:30:06 +00:00
Add runtime.default_random_generator
This commit is contained in:
@@ -410,8 +410,10 @@ Random_Generator_Query_Info_Flag :: enum u32 {
|
|||||||
}
|
}
|
||||||
Random_Generator_Query_Info :: distinct bit_set[Random_Generator_Query_Info_Flag; u32]
|
Random_Generator_Query_Info :: distinct bit_set[Random_Generator_Query_Info_Flag; u32]
|
||||||
|
|
||||||
|
Random_Generator_Proc :: #type proc(data: rawptr, mode: Random_Generator_Mode, p: []byte)
|
||||||
|
|
||||||
Random_Generator :: struct {
|
Random_Generator :: struct {
|
||||||
procedure: proc(data: rawptr, mode: Random_Generator_Mode, p: []byte),
|
procedure: Random_Generator_Proc,
|
||||||
data: rawptr,
|
data: rawptr,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -727,6 +729,9 @@ __init_context :: proc "contextless" (c: ^Context) {
|
|||||||
|
|
||||||
c.logger.procedure = default_logger_proc
|
c.logger.procedure = default_logger_proc
|
||||||
c.logger.data = nil
|
c.logger.data = nil
|
||||||
|
|
||||||
|
c.random_generator.procedure = default_random_generator_proc
|
||||||
|
c.random_generator.data = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) -> ! {
|
default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) -> ! {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
|
import "base:intrinsics"
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
random_generator_read_bytes :: proc(rg: Random_Generator, p: []byte) -> bool {
|
random_generator_read_bytes :: proc(rg: Random_Generator, p: []byte) -> bool {
|
||||||
if rg.procedure != nil {
|
if rg.procedure != nil {
|
||||||
@@ -24,4 +26,66 @@ random_generator_query_info :: proc(rg: Random_Generator) -> (info: Random_Gener
|
|||||||
rg.procedure(rg.data, .Query_Info, ([^]byte)(&info)[:size_of(info)])
|
rg.procedure(rg.data, .Query_Info, ([^]byte)(&info)[:size_of(info)])
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@(private="file")
|
||||||
|
Default_Random_State :: struct {
|
||||||
|
state: u64,
|
||||||
|
inc: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
default_random_generator_proc :: proc(data: rawptr, mode: Random_Generator_Mode, p: []byte) {
|
||||||
|
@(require_results)
|
||||||
|
read_u64 :: proc "contextless" (r: ^Default_Random_State) -> u64 {
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
|
||||||
|
@(thread_local)
|
||||||
|
global_rand_seed: Default_Random_State
|
||||||
|
|
||||||
|
switch mode {
|
||||||
|
case .Read:
|
||||||
|
r := &global_rand_seed
|
||||||
|
|
||||||
|
if r.state == 0 &&
|
||||||
|
r.inc == 0 {
|
||||||
|
seed := u64(intrinsics.read_cycle_counter())
|
||||||
|
r.state = 0
|
||||||
|
r.inc = (seed << 1) | 1
|
||||||
|
_ = read_u64(r)
|
||||||
|
r.state += seed
|
||||||
|
_ = read_u64(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
pos := i8(0)
|
||||||
|
val := u64(0)
|
||||||
|
for &v in p {
|
||||||
|
if pos == 0 {
|
||||||
|
val = read_u64(r)
|
||||||
|
pos = 7
|
||||||
|
}
|
||||||
|
v = byte(val)
|
||||||
|
val >>= 8
|
||||||
|
pos -= 1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
case .Query_Info:
|
||||||
|
if len(p) != size_of(Random_Generator_Query_Info) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
info := (^Random_Generator_Query_Info)(raw_data(p))
|
||||||
|
info^ += {.Uniform}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default_random_generator :: proc "contextless" () -> Random_Generator {
|
||||||
|
return {
|
||||||
|
procedure = default_random_generator_proc,
|
||||||
|
data = nil,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user