Oregami
Repositories/oxedyne/fe2o3

oxedyne/fe2o3/fe2o3_test/src/data.rs

10.0 KiB, 16 runs

created by r1870400018:1075, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1use oxedyne_fe2o3_core::prelude::*;
2
3use rand::{
4 prelude::*,
5 distributions::Standard,
6 Rng,
7 seq::SliceRandom,
8};
9
10#[derive(Debug)]
11pub enum DataArrangement {
12 PlainFill(usize), // 12345 n=5
13 FillCopy{ n: usize, rep: usize }, // 111112222233333 n=5 rep=3
14 RepeatFill{ n: usize, rep: usize }, // 123451234512345 n=5 rep=3
15 RepeatFillShuffled{ n: usize, rep: usize }, // 351244315243125 n=5 rep=3, i.e. 5 values, repeated 3 times, but shuffled
16 RepeatFillAndSeq{ n: usize, rep: usize, specbox: Box<DataSpec> }, // 123ab456ab789ab n=3 rep=3 specbox.n=2
17}
18
19impl DataArrangement {
20 pub fn len(&self) -> Outcome<usize> {
21 match self {
22 Self::PlainFill(n) => Ok(*n),
23 Self::FillCopy{ n, rep } |
24 Self::RepeatFill{ n, rep } |
25 Self::RepeatFillShuffled{ n, rep } |
26 Self::RepeatFillAndSeq{ n, rep, ..} =>
27 match n.checked_mul(*rep) {
28 Some(prod) => Ok(prod),
29 None => Err(err!(
30 "Product of n = {} and rep = {} produces usize overflow.", n, rep;
31 Overflow, Integer)),
32 },
33 }
34 }
35}
36
37#[derive(Debug)]
38pub enum DataFill {
39 Const(u8),
40 Random,
41}
42
43#[derive(Debug)]
44pub enum DataSize {
45 Const(usize),
46 RandUniform{ lo: usize, hi: usize },
47 RandNorm{ lo: usize, hi: usize }, // assume 6 stdev in lo..hi
48}
49
50impl DataSize {
51 pub fn value(&self, fill: &DataFill) -> Vec<u8> {
52 let mut rng = rand::thread_rng();
53 let len = match self {
54 DataSize::Const(len) => {
55 *len
56 },
57 DataSize::RandUniform { lo, hi } => {
58 rng.gen_range(*lo..*hi)
59 },
60 DataSize::RandNorm { lo, hi } => {
61 let val: f32 = StdRng::from_entropy().sample(Standard);
62 ((((*hi as f32) - (*lo as f32)) * val) as usize) + *lo
63 },
64 };
65 let mut result = Vec::new();
66 for _ in 0..len {
67 result.push(match fill {
68 DataFill::Const(v) => *v,
69 DataFill::Random => rng.gen::<u8>(),
70 });
71 }
72 result
73 }
74}
75
76/// Create a collection of byte vectors for use in testing.
77#[derive(Debug)]
78pub struct DataSpec {
79 pub size: DataSize,
80 pub fill: DataFill,
81 pub arr: DataArrangement,
82}
83
84impl DataSpec {
85
86 pub fn len(&self) -> Outcome<usize> {
87 self.arr.len()
88 }
89
90 pub fn generate(&self) -> Outcome<Vec<Vec<u8>>> {
91 let mut vals = Vec::new();
92 match &self.arr {
93 DataArrangement::PlainFill(n) => {
94 for _ in 0..*n {
95 let v = self.size.value(&self.fill);
96 vals.push(v);
97 }
98 },
99 DataArrangement::FillCopy{ n, rep } => {
100 res!(self.common_checks(n, rep));
101 for _ in 0..*rep {
102 let v = self.size.value(&self.fill);
103 for _ in 0..*n {
104 vals.push(v.clone());
105 }
106 }
107 },
108 DataArrangement::RepeatFill{n, rep} => {
109 res!(self.common_checks(n, rep));
110 let mut vt = Vec::new();
111 for _ in 0..*n {
112 let v = self.size.value(&self.fill);
113 vt.push(v);
114 }
115 for _ in 0..*rep {
116 vals.extend_from_slice(&vt[..]);
117 }
118 },
119 DataArrangement::RepeatFillShuffled{n, rep} => {
120 res!(self.common_checks(n, rep));
121 let mut rng = thread_rng();
122 let mut vt = Vec::new();
123 for _ in 0..*n {
124 let v = self.size.value(&self.fill);
125 vt.push(v);
126 }
127 let mut ind: Vec<usize> = (0..*n).collect();
128 for _ in 0..*rep {
129 let _ = &ind.shuffle(&mut rng);
130 for i in &ind {
131 vals.push(vt[*i].clone());
132 }
133 }
134 },
135 DataArrangement::RepeatFillAndSeq{n, rep, specbox} => {
136 res!(self.common_checks(n, rep));
137 let seq = res!(specbox.generate());
138 let s = seq.len();
139 if s > *n {
140 return Err(err!(
141 "The given sequence length, {}, must not exceed n, {}.", s, n;
142 Invalid, Input));
143 }
144 for _ in 0..*rep {
145 for _ in 0..(n - s) {
146 let v = self.size.value(&self.fill);
147 vals.push(v);
148 }
149 for seqitem in &seq {
150 vals.push(seqitem.clone());
151 }
152 }
153 },
154 }
155 Ok(vals)
156 }
157
158 fn common_checks(&self, _n: &usize, rep: &usize) -> Outcome<()> {
159 if *rep == 0 {
160 return Err(err!(
161 "Given repetitions, {}, must be > 0.", rep;
162 Invalid, Input));
163 }
164 Ok(())
165 }
166}
167
168#[cfg(test)]
169mod tests {
170 use super::*;
171
172 #[test]
173 fn test_plain_fill_const() -> Outcome<()> {
174 let n0 = 5;
175 let len0 = 4;
176 let spec = DataSpec{
177 size: DataSize::Const(len0),
178 arr: DataArrangement::PlainFill(n0),
179 fill: DataFill::Const(42),
180 };
181 let data = res!(spec.generate());
182 assert_eq!(data.len(), n0);
183 let v_expected = vec![42u8; len0];
184 for v in data {
185 assert_eq!(v, v_expected);
186 }
187 Ok(())
188 }
189
190 #[test]
191 fn test_plain_fill_rand() -> Outcome<()> {
192 let n0 = 5;
193 let len0 = 4;
194 let spec = DataSpec{
195 size: DataSize::Const(len0),
196 arr: DataArrangement::PlainFill(n0),
197 fill: DataFill::Random,
198 };
199 let data = res!(spec.generate());
200 assert_eq!(data.len(), n0);
201 for v in data {
202 assert_eq!(v.len(), len0);
203 }
204 Ok(())
205 }
206
207 #[test]
208 fn test_fill_copy_rand() -> Outcome<()> {
209 let n0 = 5;
210 let rep0 = 3;
211 let len0 = 4;
212 let spec = DataSpec{
213 size: DataSize::Const(len0),
214 arr: DataArrangement::FillCopy{ n: n0, rep: rep0 },
215 fill: DataFill::Random,
216 };
217 let data = res!(spec.generate());
218 //msg!("FillCopy data:");
219 //for val in &data {
220 // msg!("{:02x?}", val);
221 //}
222 let total = n0 * rep0;
223 assert_eq!(data.len(), total);
224 let mut v0 = Vec::new();
225 for (i, v) in data.iter().enumerate() {
226 if i % n0 == 0 {
227 v0 = v.clone();
228 }
229 assert_eq!(v.len(), v0.len());
230 for (j, v1) in v.iter().enumerate() {
231 assert_eq!(*v1, v0[j]);
232 }
233 }
234 Ok(())
235 }
236
237 #[test]
238 fn test_repeat_fill_rand() -> Outcome<()> {
239 let n0 = 5;
240 let rep0 = 3;
241 let len0 = 4;
242 let spec = DataSpec{
243 size: DataSize::Const(len0),
244 arr: DataArrangement::RepeatFill{ n: n0, rep: rep0 },
245 fill: DataFill::Random,
246 };
247 let data = res!(spec.generate());
248 //msg!("RepeatFill data:");
249 //for val in &data {
250 // msg!("{:02x?}", val);
251 //}
252 let total = n0 * rep0;
253 assert_eq!(data.len(), total);
254 for (i, v) in data.iter().enumerate() {
255 if i < total - n0 {
256 assert_eq!(v.len(), data[i + n0].len());
257 for (j, v1) in v.iter().enumerate() {
258 assert_eq!(*v1, data[i + n0][j]);
259 }
260 }
261 }
262 Ok(())
263 }
264
265 #[test]
266 fn test_repeat_fill_shuffled_rand() -> Outcome<()> {
267 let n0 = 5;
268 let rep0 = 3;
269 let len0 = 4;
270 let spec = DataSpec{
271 size: DataSize::Const(len0),
272 arr: DataArrangement::RepeatFillShuffled{ n: n0, rep: rep0 },
273 fill: DataFill::Random,
274 };
275 let data = res!(spec.generate());
276 //msg!("RepeatFillShuffled data:");
277 //for val in &data {
278 // msg!("{:02x?}", val);
279 //}
280 let total = n0 * rep0;
281 assert_eq!(data.len(), total);
282 // Loop through the data to make total^2 comparisons ensuring that each repeats rep0
283 // times.
284 for v1 in &data {
285 let mut count = 0;
286 for v2 in &data {
287 if (*v1).len() == (*v2).len() {
288 let mut diff: bool = false;
289 for k in 0..(*v1).len() {
290 if (*v1)[k] != (*v2)[k] { diff = true; }
291 }
292 if !diff {
293 count += 1;
294 }
295 }
296 }
297 assert_eq!(count, rep0);
298 }
299 Ok(())
300 }
301
302 #[test]
303 fn test_repeat_fill_and_seq_rand() -> Outcome<()> {
304 let n0 = 5;
305 let n1 = 2;
306 let rep0 = 3;
307 let len0 = 4;
308 let spec0 = DataSpec{
309 size: DataSize::Const(len0),
310 arr: DataArrangement::PlainFill(n1),
311 fill: DataFill::Random,
312 };
313 let spec = DataSpec{
314 size: DataSize::Const(len0),
315 arr: DataArrangement::RepeatFillAndSeq{ n: n0, rep: rep0, specbox: Box::new(spec0) },
316 fill: DataFill::Random,
317 };
318 let data = res!(spec.generate());
319 msg!("RepeatFillAndSeq data:");
320 for val in &data {
321 msg!("{:02x?}", val);
322 }
323 let total = n0 * rep0;
324 assert_eq!(data.len(), total);
325 for (i, v) in data.iter().enumerate() {
326 if i < total - n0 && i % n0 > (n0 - n1) {
327 assert_eq!(v.len(), data[i + n0].len());
328 for (j, v1) in v.iter().enumerate() {
329 assert_eq!(*v1, data[i + n0][j]);
330 }
331 }
332 }
333 Ok(())
334 }
335
336}