use core_affinity::CoreId;
use std::iter::FromIterator;
#[derive(Debug, PartialEq)]
pub struct ProcessingUnitDistance {
distance_matrix: Box<[Box<[i32]>]>,
}
impl ProcessingUnitDistance {
pub fn new(distance_matrix: Box<[Box<[i32]>]>) -> Self {
let num_rows = distance_matrix.len();
for row in distance_matrix.iter() {
assert_eq!(num_rows, row.len(), "A PU distance matrix must be square!");
}
ProcessingUnitDistance { distance_matrix }
}
pub fn empty() -> Self {
ProcessingUnitDistance {
distance_matrix: Vec::new().into_boxed_slice(),
}
}
pub fn from_function<F>(size: usize, distance: F) -> Self
where
F: Fn(usize, usize) -> i32,
{
let mut matrix: Vec<Box<[i32]>> = Vec::with_capacity(size);
for row_index in 0..size {
let mut row: Vec<i32> = Vec::with_capacity(size);
for column_index in 0..size {
let d = distance(row_index, column_index);
row.push(d);
}
matrix.push(row.into_boxed_slice());
}
ProcessingUnitDistance {
distance_matrix: matrix.into_boxed_slice(),
}
}
pub fn distance(&self, pu1: CoreId, pu2: CoreId) -> i32 {
self.distance_matrix[pu1.id][pu2.id]
}
}
impl FromIterator<Vec<i32>> for ProcessingUnitDistance {
fn from_iter<I: IntoIterator<Item = Vec<i32>>>(iter: I) -> Self {
let mut v: Vec<Box<[i32]>> = Vec::new();
for i in iter {
v.push(i.into_boxed_slice());
}
ProcessingUnitDistance::new(v.into_boxed_slice())
}
}
impl FromIterator<Box<[i32]>> for ProcessingUnitDistance {
fn from_iter<I: IntoIterator<Item = Box<[i32]>>>(iter: I) -> Self {
let mut v: Vec<Box<[i32]>> = Vec::new();
for i in iter {
v.push(i);
}
ProcessingUnitDistance::new(v.into_boxed_slice())
}
}
pub fn equidistance(i: usize, j: usize) -> i32 {
if i == j {
0
} else {
1
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_pu_distance_creation() {
let mat = vec![vec![0, 1], vec![1, 0]];
let pud: ProcessingUnitDistance = mat.into_iter().collect();
let pud2 = ProcessingUnitDistance::from_function(2, equidistance);
assert_eq!(pud, pud2);
let core1 = CoreId { id: 0 };
let core2 = CoreId { id: 1 };
assert_eq!(0, pud.distance(core1, core1));
assert_eq!(0, pud.distance(core2, core2));
assert_eq!(1, pud.distance(core1, core2));
assert_eq!(1, pud.distance(core2, core1));
}
#[test]
fn test_empty_pu_distance() {
let mat: Vec<Vec<i32>> = Vec::new();
let pud: ProcessingUnitDistance = mat.into_iter().collect();
let pud2 = ProcessingUnitDistance::empty();
assert_eq!(pud, pud2);
}
}