1use crate::{EigenError, Eigenvalue, Eigenvector};
2
3#[derive(Debug, Clone, PartialEq, Eq)]
5pub struct EigenSpace<T> {
6 value: Eigenvalue<T>,
7 basis: Vec<Eigenvector<T>>,
8}
9
10impl<T> EigenSpace<T> {
11 pub fn new(value: Eigenvalue<T>, basis: Vec<Eigenvector<T>>) -> Result<Self, EigenError> {
17 Self::try_new(value, basis)
18 }
19
20 pub fn try_new(value: Eigenvalue<T>, basis: Vec<Eigenvector<T>>) -> Result<Self, EigenError> {
26 if basis.is_empty() {
27 Err(EigenError::EmptyEigenspace)
28 } else {
29 Ok(Self { value, basis })
30 }
31 }
32
33 #[must_use]
35 pub const fn value(&self) -> &Eigenvalue<T> {
36 &self.value
37 }
38
39 #[must_use]
41 pub fn basis(&self) -> &[Eigenvector<T>] {
42 &self.basis
43 }
44
45 #[must_use]
47 pub fn into_inner(self) -> (Eigenvalue<T>, Vec<Eigenvector<T>>) {
48 (self.value, self.basis)
49 }
50
51 #[must_use]
53 pub const fn dimension(&self) -> usize {
54 self.basis.len()
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use super::EigenSpace;
61 use crate::{EigenError, Eigenvalue, Eigenvector};
62
63 #[test]
64 fn stores_an_eigenspace_basis() {
65 let space = EigenSpace::new(
66 Eigenvalue::new(4_i32),
67 vec![Eigenvector::new(vec![1_i32, 1]).expect("valid eigenvector")],
68 )
69 .expect("valid eigenspace");
70
71 assert_eq!(*space.value().as_ref(), 4);
72 assert_eq!(space.dimension(), 1);
73 assert_eq!(space.basis()[0].coordinates(), &[1, 1]);
74 }
75
76 #[test]
77 fn rejects_an_empty_basis() {
78 assert_eq!(
79 EigenSpace::<i32>::new(Eigenvalue::new(1_i32), vec![]),
80 Err(EigenError::EmptyEigenspace)
81 );
82 }
83}