use std::cmp;
use std::collections::HashSet;
use Random;
pub struct Report {
cycle_length: u32,
collisions: u8,
dependency_matrix: [[u32; 64]; 64],
distribution: [u16; 4096],
}
impl Default for Report {
fn default() -> Report {
Report {
cycle_length: 0,
collisions: 0,
dependency_matrix: [[0; 64]; 64],
distribution: [0; 4096],
}
}
}
impl Report {
pub fn new<R: Random>(mut rand: R) -> Report {
let mut report = Report::default();
let mut set = HashSet::new();
let start = rand.get_random();
for n in 0..1 << 16 {
let r = rand.get_random();
for x in 0..64 {
for y in 0..64 {
report.dependency_matrix[x][y] += ((r & (1 << x) == 0) <= (r & (1 << y) == 0)) as u32;
}
}
report.distribution[r as usize % 4096] += 1;
if report.cycle_length == 0 && r == start {
report.cycle_length = n;
}
report.collisions += (!set.insert(r)) as u8;
}
report
}
pub fn get_score(&self) -> Score {
Score {
cycle: if self.cycle_length == 0 {
255
} else {
0
},
collision: match self.collisions {
0 => 255,
1 => 20,
_ => 0,
},
bit_dependency: {
let mut max = 0;
let mut min = !0;
for x in 0..64 {
for y in 0..64 {
max = cmp::max(self.dependency_matrix[x][y], max);
min = cmp::min(self.dependency_matrix[x][y], min);
}
}
let pmin = match 65536 - min as i32 {
0...4 => 127,
4...6 => 126,
6...16 => 120,
16...32 => 90,
32...64 => 50,
64...80 => 20,
_ => 0,
};
let pmax = match min as i32 - 65536 {
0...4 => 128,
4...6 => 126,
6...16 => 120,
16...32 => 90,
32...64 => 50,
64...80 => 20,
_ => 0,
};
pmin + pmax
},
distribution: {
let mut max = 0;
let mut min = !0;
for i in 0..4096 {
max = cmp::max(self.distribution[i], max);
min = cmp::min(self.distribution[i], min);
}
let pmin = match 32 - min as i32 {
0...4 => 127,
4...6 => 126,
6...10 => 110,
10...15 => 70,
15...18 => 50,
18...20 => 30,
20...32 => 20,
_ => 0,
};
let pmax = match min as i32 - 32 {
0...4 => 128,
4...6 => 126,
6...10 => 110,
10...15 => 70,
15...18 => 50,
18...20 => 30,
20...32 => 20,
_ => 0,
};
pmin + pmax
},
}
}
}
pub struct Score {
cycle: u8,
collision: u8,
bit_dependency: u8,
distribution: u8,
}
impl Score {
pub fn total(self) -> u16 {
self.cycle as u16
+ self.collision as u16
+ self.bit_dependency as u16
+ self.distribution as u16
}
}