use std::ops::{Index, IndexMut};
#[derive(Debug)]
pub struct CondensedMatrix<'a, T> {
data: &'a mut [T],
observations: usize,
}
impl<'a, T> CondensedMatrix<'a, T> {
pub fn new(
data: &'a mut [T],
observations: usize,
) -> CondensedMatrix<'a, T> {
if data.is_empty() {
assert!(observations <= 1);
CondensedMatrix { data: data, observations: 0 }
} else {
assert!(observations >= 2);
assert_eq!((observations * (observations - 1)) / 2, data.len());
CondensedMatrix { data: data, observations: observations }
}
}
pub fn observations(&self) -> usize {
self.observations
}
fn matrix_to_condensed_idx(&self, row: usize, column: usize) -> usize {
debug_assert!(row < column);
debug_assert!(column < self.observations());
((2 * self.observations() - row - 3) * row / 2) + column - 1
}
}
impl<'a, T> Index<[usize; 2]> for CondensedMatrix<'a, T> {
type Output = T;
fn index(&self, idx: [usize; 2]) -> &T {
&self.data[self.matrix_to_condensed_idx(idx[0], idx[1])]
}
}
impl<'a, T> IndexMut<[usize; 2]> for CondensedMatrix<'a, T> {
fn index_mut(&mut self, idx: [usize; 2]) -> &mut T {
let i = self.matrix_to_condensed_idx(idx[0], idx[1]);
&mut self.data[i]
}
}