1use std::time::{SystemTime, UNIX_EPOCH};
2
3#[cfg(feature = "serde")]
4use serde_crate::{Deserialize, Serialize};
5
6use crate::crypto::Crypto;
7
8#[cfg_attr(
10 feature = "serde",
11 derive(Serialize, Deserialize),
12 serde(crate = "serde_crate")
13)]
14#[derive(Copy, Clone)]
15pub struct State {
16 pub s0: u32,
17 pub s1: u32,
18 pub s2: u32,
19 pub s3: u32,
20}
21
22#[cfg_attr(
25 feature = "serde",
26 derive(Serialize, Deserialize),
27 serde(crate = "serde_crate")
28)]
29pub struct Random {
30 pub state: State,
32}
33
34impl Random {
35 pub fn new() -> Random {
37 let timestamp = Random::get_timestamp() as u32;
38
39 Random {
40 state: Crypto::init_state(timestamp),
41 }
42 }
43
44 pub fn init_state(&mut self, seed: i32) {
46 self.state = Crypto::init_state(seed as u32);
47 }
48
49 pub fn range_int(&mut self, mut min: i32, mut max: i32) -> i32 {
53 if min > max {
54 (min, max) = (max, min);
55 }
56
57 let diff = (max - min) as u32;
58
59 if diff > 0 {
60 min + (self.next_u32().rem_euclid(diff)) as i32
61 } else {
62 min
63 }
64 }
65
66 pub fn range_float(&mut self, min: f32, max: f32) -> f32 {
68 Crypto::precision_f32(self.range_float_intern(min, max), 7)
69 }
70
71 pub fn value(&mut self) -> f32 {
73 Crypto::precision_f32(self.next_f32(), 7)
74 }
75
76 pub fn inside_unit_circle(&mut self) -> (f32, f32) {
81 let theta = self.range_float_intern(0., std::f32::consts::TAU);
82 let radius = (self.range_float_intern(0., 1.)).sqrt();
83
84 let x = Crypto::precision_f32(radius * theta.cos(), 7);
85 let y = Crypto::precision_f32(radius * theta.sin(), 7);
86
87 (x, y)
88 }
89
90 pub fn on_unit_sphere(&mut self) -> (f32, f32, f32) {
92 let (mut x, mut y, mut z) = self.on_unit_sphere_intern();
93
94 x = Crypto::precision_f32(x, 7);
95 y = Crypto::precision_f32(y, 7);
96 z = Crypto::precision_f32(z, 7);
97
98 (x, y, z)
99 }
100
101 pub fn inside_unit_sphere(&mut self) -> (f32, f32, f32) {
106 let (mut x, mut y, mut z) = self.on_unit_sphere_intern();
107
108 let dist = self.next_f32().powf(1. / 3.);
109
110 x = Crypto::precision_f32(x * dist, 7);
111 y = Crypto::precision_f32(y * dist, 7);
112 z = Crypto::precision_f32(z * dist, 7);
113
114 (x, y, z)
115 }
116
117 pub fn rotation(&mut self) -> (f32, f32, f32, f32) {
124 let mut x = self.range_float_intern(-1., 1.);
125 let mut y = self.range_float_intern(-1., 1.);
126 let mut z = self.range_float_intern(-1., 1.);
127 let mut w = self.range_float_intern(-1., 1.);
128
129 let mut mag = (x.powi(2) + y.powi(2) + z.powi(2) + w.powi(2)).sqrt();
130
131 if w < 0. {
132 mag = -mag;
133 }
134
135 x = Crypto::precision_f32(x / mag, 7);
136 y = Crypto::precision_f32(y / mag, 7);
137 z = Crypto::precision_f32(z / mag, 7);
138 w = Crypto::precision_f32(w / mag, 7);
139
140 (x, y, z, w)
141 }
142
143 pub fn rotation_uniform(&mut self) -> (f32, f32, f32, f32) {
151 let u1 = self.range_float_intern(0., 1.);
152 let u2 = self.range_float_intern(0., std::f32::consts::TAU);
153 let u3 = self.range_float_intern(0., std::f32::consts::TAU);
154
155 let sqrt = (u1).sqrt();
156 let inv = (1. - u1).sqrt();
157
158 let mut x = inv * u2.sin();
159 let mut y = inv * u2.cos();
160 let mut z = sqrt * u3.sin();
161 let mut w = sqrt * u3.cos();
162
163 if w < 0. {
164 x = -x;
165 y = -y;
166 z = -z;
167 w = -w;
168 }
169
170 x = Crypto::precision_f32(x, 7);
171 y = Crypto::precision_f32(y, 7);
172 z = Crypto::precision_f32(z, 7);
173 w = Crypto::precision_f32(w, 7);
174
175 (x, y, z, w)
176 }
177
178 pub fn color(&mut self) -> (f32, f32, f32, f32) {
184 self.color_hsva(0., 1., 0., 1., 0., 1., 1., 1.)
185 }
186
187 pub fn color_h(&mut self, hue_min: f32, hue_max: f32) -> (f32, f32, f32, f32) {
193 self.color_hsva(hue_min, hue_max, 0., 1., 0., 1., 1., 1.)
194 }
195
196 pub fn color_hs(
202 &mut self,
203 hue_min: f32,
204 hue_max: f32,
205 saturation_min: f32,
206 saturation_max: f32,
207 ) -> (f32, f32, f32, f32) {
208 self.color_hsva(
209 hue_min,
210 hue_max,
211 saturation_min,
212 saturation_max,
213 0.,
214 1.,
215 1.,
216 1.,
217 )
218 }
219
220 pub fn color_hsv(
226 &mut self,
227 hue_min: f32,
228 hue_max: f32,
229 saturation_min: f32,
230 saturation_max: f32,
231 value_min: f32,
232 value_max: f32,
233 ) -> (f32, f32, f32, f32) {
234 self.color_hsva(
235 hue_min,
236 hue_max,
237 saturation_min,
238 saturation_max,
239 value_min,
240 value_max,
241 1.,
242 1.,
243 )
244 }
245
246 pub fn color_hsva(
252 &mut self,
253 hue_min: f32,
254 hue_max: f32,
255 saturation_min: f32,
256 saturation_max: f32,
257 value_min: f32,
258 value_max: f32,
259 alpha_min: f32,
260 alpha_max: f32,
261 ) -> (f32, f32, f32, f32) {
262 let hue = Crypto::lerp(hue_min, hue_max, self.next_f32());
263 let sat = Crypto::lerp(saturation_min, saturation_max, self.next_f32());
264 let val = Crypto::lerp(value_min, value_max, self.next_f32());
265
266 let (mut r, mut g, mut b, _) = Crypto::hsv_to_rbg(hue, sat, val, true);
267 let mut a = Crypto::lerp(alpha_min, alpha_max, self.next_f32());
268
269 r = Crypto::precision_f32(r, 7);
270 g = Crypto::precision_f32(g, 7);
271 b = Crypto::precision_f32(b, 7);
272 a = Crypto::precision_f32(a, 7);
273
274 (r, g, b, a)
275 }
276
277 fn next_u32(&mut self) -> u32 {
279 Crypto::next_u32(&mut self.state)
280 }
281
282 fn next_f32(&mut self) -> f32 {
284 Crypto::next_f32(&mut self.state)
285 }
286
287 fn range_float_intern(&mut self, min: f32, max: f32) -> f32 {
289 let next = self.next_f32();
290
291 (1. - next) * max + next * min
292 }
293
294 fn on_unit_sphere_intern(&mut self) -> (f32, f32, f32) {
296 let dist = self.range_float_intern(-1., 1.);
297 let rad = self.range_float_intern(0., std::f32::consts::TAU);
298 let radius_xy = (1. - dist.powi(2)).sqrt();
299
300 let x = rad.cos() * radius_xy;
301 let y = rad.sin() * radius_xy;
302 let z = dist;
303
304 (x, y, z)
305 }
306
307 fn get_timestamp() -> u64 {
309 SystemTime::now()
310 .duration_since(UNIX_EPOCH)
311 .expect("SystemTime before UNIX Epoch!")
312 .as_secs()
313 }
314}