use crate::{EigenError, Eigenvalue, Eigenvector};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EigenSpace<T> {
value: Eigenvalue<T>,
basis: Vec<Eigenvector<T>>,
}
impl<T> EigenSpace<T> {
pub fn new(value: Eigenvalue<T>, basis: Vec<Eigenvector<T>>) -> Result<Self, EigenError> {
Self::try_new(value, basis)
}
pub fn try_new(value: Eigenvalue<T>, basis: Vec<Eigenvector<T>>) -> Result<Self, EigenError> {
if basis.is_empty() {
Err(EigenError::EmptyEigenspace)
} else {
Ok(Self { value, basis })
}
}
#[must_use]
pub const fn value(&self) -> &Eigenvalue<T> {
&self.value
}
#[must_use]
pub fn basis(&self) -> &[Eigenvector<T>] {
&self.basis
}
#[must_use]
pub fn into_inner(self) -> (Eigenvalue<T>, Vec<Eigenvector<T>>) {
(self.value, self.basis)
}
#[must_use]
pub const fn dimension(&self) -> usize {
self.basis.len()
}
}
#[cfg(test)]
mod tests {
use super::EigenSpace;
use crate::{EigenError, Eigenvalue, Eigenvector};
#[test]
fn stores_an_eigenspace_basis() {
let space = EigenSpace::new(
Eigenvalue::new(4_i32),
vec![Eigenvector::new(vec![1_i32, 1]).expect("valid eigenvector")],
)
.expect("valid eigenspace");
assert_eq!(*space.value().as_ref(), 4);
assert_eq!(space.dimension(), 1);
assert_eq!(space.basis()[0].coordinates(), &[1, 1]);
}
#[test]
fn rejects_an_empty_basis() {
assert_eq!(
EigenSpace::<i32>::new(Eigenvalue::new(1_i32), vec![]),
Err(EigenError::EmptyEigenspace)
);
}
}