rust_monster/ga/
ga_random.rs1use rand::{Rng, Rand, SeedableRng, XorShiftRng};
34use rand::distributions::range::SampleRange;
35
36use std::fmt;
37
38pub type GASeed = [u32; 4];
39pub struct GARandomCtx
40{
41 seed: GASeed,
42 rng: XorShiftRng,
43 name: String,
44 seeded: bool,
45 values_generated: u32
46}
47
48impl GARandomCtx
49{
50pub fn new_unseeded(name: String) -> GARandomCtx
52 {
53 let std_rng = XorShiftRng::new_unseeded();
54 GARandomCtx
55 {
56 seed: [0; 4],
57 rng: std_rng,
58 name: name,
59 seeded: false,
60 values_generated: 0
61 }
62 }
63
64 pub fn from_seed(seed: GASeed, name: String) -> GARandomCtx
65 {
66 let std_rng = SeedableRng::from_seed(seed);
67 GARandomCtx
68 {
69 seed: seed,
70 rng: std_rng,
71 name: name,
72 seeded: true,
73 values_generated: 0
74 }
75 }
76
77pub fn gen<T: Rand>(&mut self) -> T where Self: Sized
79 {
80 self.values_generated += 1;
81 self.rng.gen()
82 }
83
84 pub fn gen_range<T: PartialOrd + SampleRange>(&mut self, low: T, high: T) -> T
85 {
86 self.values_generated += 1;
87 self.rng.gen_range(low, high)
88 }
89
90 pub fn next_u32(&mut self) -> u32 { self.gen::<u32>() }
91 pub fn next_u64(&mut self) -> u64 { self.gen::<u64>() }
92 pub fn next_f32(&mut self) -> f32 { self.gen::<f32>() }
93 pub fn next_f64(&mut self) -> f64 { self.gen::<f64>() }
94
95pub fn test_value<T: PartialOrd + Rand>(&mut self, value: T) -> bool
97 {
98 self.gen::<T>() < value
99 }
100
101
102pub fn reseed(&mut self, seed: GASeed)
104 {
105 self.seed = seed;
106 self.seeded = true;
107 self.reset();
108 }
109
110 pub fn reset(&mut self)
111 {
112 self.values_generated = 0;
113 if self.seeded
114 {
115 self.rng.reseed(self.seed);
116 }
117 else
118 {
119 self.rng = XorShiftRng::new_unseeded();
120 }
121 }
122}
123
124impl fmt::Debug for GARandomCtx
125{
126 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
127 {
128 let seeded_str = if self.seeded
129 {
130 "Seeded"
131 }
132 else
133 {
134 "Not Seeded"
135 };
136
137 write!(f, "GARandomCtx {} - {} {{ seed: {:?}, values_generated: {:?} }}",
138 self.name,
139 seeded_str,
140 self.seed,
141 self.values_generated)
142 }
143}
144
145#[cfg(test)]
146mod test
147{
148 extern crate env_logger;
149 use super::{GASeed, GARandomCtx};
150
151 #[test]
152 fn same_seed()
153 {
154 let _ = env_logger::init();
155 let seed : GASeed = [1,2,3,4];
156 let mut ga_ctx = GARandomCtx::from_seed(seed, String::from("TestRandomCtx"));
157 let mut ga_ctx_2 = GARandomCtx::from_seed(seed, String::from("TestRandomCtx2"));
158 debug!("{:?}", ga_ctx);
159 debug!("{:?}", ga_ctx_2);
160
161 for _ in 0..100
162 {
163 assert_eq!(ga_ctx.gen::<f64>(), ga_ctx_2.gen::<f64>());
164 }
165 debug!("{:?}", ga_ctx);
166 debug!("{:?}", ga_ctx_2);
167
168 for _ in 0..100
169 {
170 assert_eq!(ga_ctx.gen::<u32>(), ga_ctx_2.gen::<u32>());
171 }
172 debug!("{:?}", ga_ctx);
173 debug!("{:?}", ga_ctx_2);
174 }
175
176 #[test]
177 fn diff_seed()
178 {
179 let _ = env_logger::init();
180 let seed_1 : GASeed = [1,2,3,4];
181 let seed_2 : GASeed = [4,3,2,1];
182 let mut ga_ctx = GARandomCtx::from_seed(seed_1, String::from("TestRandomCtx"));
183 let mut ga_ctx_2 = GARandomCtx::from_seed(seed_2, String::from("TestRandomCtx2"));
184 debug!("{:?}", ga_ctx);
185 debug!("{:?}", ga_ctx_2);
186
187 for _ in 0..100
188 {
189 assert!(ga_ctx.gen::<f32>() != ga_ctx_2.gen::<f32>());
190 }
191 debug!("{:?}", ga_ctx);
192 debug!("{:?}", ga_ctx_2);
193
194 for _ in 0..100
195 {
196 assert!(ga_ctx.gen::<u64>() != ga_ctx_2.gen::<u64>());
197 }
198 debug!("{:?}", ga_ctx);
199 debug!("{:?}", ga_ctx_2);
200 }
201
202 #[test]
203 fn same_seed_different_types()
204 {
205 let _ = env_logger::init();
206 let seed_1 = [1; 4];
207 let mut ga_ctx = GARandomCtx::from_seed(seed_1, String::from("TestRandomCtx"));
208 let mut ga_ctx_2 = GARandomCtx::from_seed(seed_1, String::from("TestRandomCtx"));
209 debug!("{:?}", ga_ctx.gen::<f32>());
210 debug!("{:?}", ga_ctx_2.gen::<i8>());
211 assert_eq!(ga_ctx.gen::<f32>(), ga_ctx_2.gen::<f32>());
212 }
213}