1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
//! Adapter trait for accessing different types of arrays.
//!
//! Includes adapters for `ndarray::Array2` and a serialized lower triangular matrix in a `Vec`.
/// Adapter trait for accessing different types of arrays
#[allow(clippy::len_without_is_empty)]
pub trait ArrayAdapter<N> {
/// Get the length of an array structure
fn len(&self) -> usize;
/// Verify that it is a square matrix
fn is_square(&self) -> bool;
/// Get the contents at cell x,y
fn get(&self, x: usize, y: usize) -> N;
}
/// Adapter trait for using `ndarray::Array2` and similar
#[cfg(feature = "ndarray")]
impl<A, N> ArrayAdapter<N> for ndarray::ArrayBase<A, ndarray::Ix2>
where
A: ndarray::Data<Elem = N>,
N: Copy,
{
#[inline]
fn len(&self) -> usize {
self.shape()[0]
}
#[inline]
fn is_square(&self) -> bool {
self.shape()[0] == self.shape()[1]
}
#[inline]
fn get(&self, x: usize, y: usize) -> N {
self[[x, y]]
}
}
/// Lower triangular matrix in serial form (without diagonal)
///
/// ## Example
/// ```
/// let data = kmedoids::arrayadapter::LowerTriangle { n: 4, data: vec![1, 2, 3, 4, 5, 6] };
/// let mut meds = vec![0, 1];
/// let (loss, numswap, numiter, assignment): (f64, _, _, _) = kmedoids::fasterpam(&data, &mut meds, 10);
/// println!("Loss is {}", loss);
/// ```
#[derive(Debug, Clone)]
pub struct LowerTriangle<N> {
/// Matrix size
pub n: usize,
// Matrix data, lower triangular form without diagonal
pub data: Vec<N>,
}
/// Adapter implementation for LowerTriangle
impl<N: Copy + num_traits::Zero> ArrayAdapter<N> for LowerTriangle<N> {
#[inline]
fn len(&self) -> usize {
self.n
}
#[inline]
fn is_square(&self) -> bool {
self.data.len() == (self.n * (self.n - 1)) >> 1
}
#[inline]
fn get(&self, x: usize, y: usize) -> N {
match x.cmp(&y) {
std::cmp::Ordering::Less => self.data[((y * (y - 1)) >> 1) + x],
std::cmp::Ordering::Greater => self.data[((x * (x - 1)) >> 1) + y],
std::cmp::Ordering::Equal => N::zero(),
}
}
}