Browse Source

Add `Reset` mode

gingerBill 1 year ago
parent
commit
318d5e4a7e
4 changed files with 39 additions and 13 deletions
  1. 2 0
      base/runtime/core.odin
  2. 23 13
      base/runtime/random_generator.odin
  3. 2 0
      core/crypto/crypto.odin
  4. 12 0
      core/math/rand/rand.odin

+ 2 - 0
base/runtime/core.odin

@@ -400,6 +400,7 @@ Logger :: struct {
 
 
 Random_Generator_Mode :: enum {
 Random_Generator_Mode :: enum {
 	Read,
 	Read,
+	Reset,
 	Query_Info,
 	Query_Info,
 }
 }
 
 
@@ -407,6 +408,7 @@ Random_Generator_Query_Info_Flag :: enum u32 {
 	Cryptographic,
 	Cryptographic,
 	Uniform,
 	Uniform,
 	External_Entropy,
 	External_Entropy,
+	Resettable,
 }
 }
 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]
 
 

+ 23 - 13
base/runtime/random_generator.odin

@@ -29,7 +29,6 @@ random_generator_query_info :: proc(rg: Random_Generator) -> (info: Random_Gener
 }
 }
 
 
 
 
-@(private="file")
 Default_Random_State :: struct {
 Default_Random_State :: struct {
 	state: u64,
 	state: u64,
 	inc:   u64,
 	inc:   u64,
@@ -48,18 +47,24 @@ default_random_generator_proc :: proc(data: rawptr, mode: Random_Generator_Mode,
 	@(thread_local)
 	@(thread_local)
 	global_rand_seed: Default_Random_State
 	global_rand_seed: Default_Random_State
 
 
+	init :: proc "contextless" (r: ^Default_Random_State, seed: u64) {
+		seed := seed
+		if seed == 0 {
+			seed = u64(intrinsics.read_cycle_counter())
+		}
+		r.state = 0
+		r.inc = (seed << 1) | 1
+		_ = read_u64(r)
+		r.state += seed
+		_ = read_u64(r)
+	}
+
+	r := &global_rand_seed
+
 	switch mode {
 	switch mode {
 	case .Read:
 	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)
+		if r.state == 0 && r.inc == 0 {
+		   	init(r, 0)
 		}
 		}
 
 
 		pos := i8(0)
 		pos := i8(0)
@@ -73,13 +78,18 @@ default_random_generator_proc :: proc(data: rawptr, mode: Random_Generator_Mode,
 			val >>= 8
 			val >>= 8
 			pos -= 1
 			pos -= 1
 		}
 		}
-		return
+
+	case .Reset:
+		seed: u64
+		mem_copy_non_overlapping(&seed, raw_data(p), min(size_of(seed), len(p)))
+	   	init(r, seed)
+
 	case .Query_Info:
 	case .Query_Info:
 		if len(p) != size_of(Random_Generator_Query_Info) {
 		if len(p) != size_of(Random_Generator_Query_Info) {
 			return
 			return
 		}
 		}
 		info := (^Random_Generator_Query_Info)(raw_data(p))
 		info := (^Random_Generator_Query_Info)(raw_data(p))
-		info^ += {.Uniform}
+		info^ += {.Uniform, .Resettable}
 	}
 	}
 }
 }
 
 

+ 2 - 0
core/crypto/crypto.odin

@@ -67,6 +67,8 @@ to_random_generator :: proc() -> runtime.Random_Generator {
 			switch mode {
 			switch mode {
 			case .Read:
 			case .Read:
 				rand_bytes(p)
 				rand_bytes(p)
+			case .Reset:
+				// do nothing
 			case .Query_Info:
 			case .Query_Info:
 				if len(p) != size_of(runtime.Random_Generator_Query_Info) {
 				if len(p) != size_of(runtime.Random_Generator_Query_Info) {
 					return
 					return

+ 12 - 0
core/math/rand/rand.odin

@@ -23,6 +23,16 @@ to_random_generator :: proc(r: ^Rand) -> runtime.Random_Generator {
 			switch mode {
 			switch mode {
 			case .Read:
 			case .Read:
 				_ = read(p, r)
 				_ = 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:
 			case .Query_Info:
 				if len(p) != size_of(runtime.Random_Generator_Query_Info) {
 				if len(p) != size_of(runtime.Random_Generator_Query_Info) {
 					return
 					return
@@ -31,6 +41,8 @@ to_random_generator :: proc(r: ^Rand) -> runtime.Random_Generator {
 				info^ += {.Uniform}
 				info^ += {.Uniform}
 				if r.is_system {
 				if r.is_system {
 					info^ += {.External_Entropy}
 					info^ += {.External_Entropy}
+				} else {
+					info^ += {.Resettable}
 				}
 				}
 			}
 			}
 		},
 		},