nros_platform_api/
xorshift32.rs1pub const DEFAULT_SEED: u32 = 0x12345678;
16
17#[inline]
19pub const fn step(state: u32) -> u32 {
20 let mut x = state;
21 x ^= x << 13;
22 x ^= x >> 17;
23 x ^= x << 5;
24 x
25}
26
27#[inline]
34pub unsafe fn next(state: *mut u32) -> u32 {
35 let next = step(unsafe { *state });
36 unsafe { *state = next };
37 next
38}
39
40#[inline]
46pub unsafe fn seed(state: *mut u32, value: u32) {
47 unsafe { *state = if value == 0 { DEFAULT_SEED } else { value } };
48}
49
50pub unsafe fn random_fill(state: *mut u32, buf: *mut u8, len: usize) {
57 if buf.is_null() {
58 return;
59 }
60 let mut offset = 0;
61 let mut remaining = len;
62 while remaining >= 4 {
63 let bytes = unsafe { next(state) }.to_ne_bytes();
64 unsafe { core::ptr::copy_nonoverlapping(bytes.as_ptr(), buf.add(offset), 4) };
65 offset += 4;
66 remaining -= 4;
67 }
68 if remaining > 0 {
69 let bytes = unsafe { next(state) }.to_ne_bytes();
70 unsafe { core::ptr::copy_nonoverlapping(bytes.as_ptr(), buf.add(offset), remaining) };
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 #[test]
79 fn step_is_deterministic() {
80 assert_eq!(step(DEFAULT_SEED), step(DEFAULT_SEED));
81 }
82
83 #[test]
84 fn step_changes_state() {
85 assert_ne!(step(DEFAULT_SEED), DEFAULT_SEED);
86 }
87
88 #[test]
89 fn seed_zero_falls_back_to_default() {
90 let mut s: u32 = 1;
91 unsafe { seed(&raw mut s, 0) };
92 assert_eq!(s, DEFAULT_SEED);
93 }
94
95 #[test]
96 fn seed_nonzero_takes_value() {
97 let mut s: u32 = 1;
98 unsafe { seed(&raw mut s, 0xDEADBEEF) };
99 assert_eq!(s, 0xDEADBEEF);
100 }
101
102 #[test]
103 fn next_advances_state() {
104 let mut s: u32 = DEFAULT_SEED;
105 let v = unsafe { next(&raw mut s) };
106 assert_eq!(v, step(DEFAULT_SEED));
107 assert_eq!(s, v);
108 }
109
110 #[test]
111 fn random_fill_null_buf_is_noop() {
112 let mut s: u32 = DEFAULT_SEED;
113 unsafe { random_fill(&raw mut s, core::ptr::null_mut(), 16) };
114 assert_eq!(s, DEFAULT_SEED);
115 }
116
117 #[test]
118 fn random_fill_writes_requested_length() {
119 let mut s: u32 = DEFAULT_SEED;
120 let mut buf = [0u8; 13];
121 unsafe { random_fill(&raw mut s, buf.as_mut_ptr(), buf.len()) };
122 assert!(buf.iter().any(|&b| b != 0));
123 }
124}