1use crate::error::*;
4use crate::layout::*;
5use crate::types::*;
6pub use lax::GeneralizedEigenvalue;
7use ndarray::*;
8
9#[cfg_attr(doc, katexit::katexit)]
10pub trait Eig {
12 type EigVal;
14 type EigVec;
15 fn eig(&self) -> Result<(Self::EigVal, Self::EigVec)>;
40}
41
42impl<A> Eig for ArrayRef<A, Ix2>
43where
44 A: Scalar + Lapack,
45{
46 type EigVal = Array1<A::Complex>;
47 type EigVec = Array2<A::Complex>;
48
49 fn eig(&self) -> Result<(Self::EigVal, Self::EigVec)> {
50 let mut a = self.to_owned();
51 let layout = a.square_layout()?;
52 let (s, t) = A::eig(true, layout, a.as_allocated_mut()?)?;
53 let n = layout.len() as usize;
54 Ok((
55 ArrayBase::from(s),
56 Array2::from_shape_vec((n, n).f(), t).unwrap(),
57 ))
58 }
59}
60
61pub trait EigVals {
63 type EigVal;
64 fn eigvals(&self) -> Result<Self::EigVal>;
65}
66
67impl<A> EigVals for ArrayRef<A, Ix2>
68where
69 A: Scalar + Lapack,
70{
71 type EigVal = Array1<A::Complex>;
72
73 fn eigvals(&self) -> Result<Self::EigVal> {
74 let mut a = self.to_owned();
75 let (s, _) = A::eig(false, a.square_layout()?, a.as_allocated_mut()?)?;
76 Ok(ArrayBase::from(s))
77 }
78}
79
80#[cfg_attr(doc, katexit::katexit)]
81pub trait EigGeneralized {
83 type EigVal;
85 type EigVec;
86 type Real;
87 fn eig_generalized(
128 self,
129 thresh_opt: Option<Self::Real>,
130 ) -> Result<(Self::EigVal, Self::EigVec)>;
131}
132
133pub trait MaybeOwnedMatrix {
135 type Elem;
136
137 fn into_owned(self) -> Array2<Self::Elem>;
139}
140
141impl<S> MaybeOwnedMatrix for ArrayBase<S, Ix2>
142where
143 S: Data,
144 S::Elem: Clone,
145{
146 type Elem = S::Elem;
147
148 fn into_owned(self) -> Array2<S::Elem> {
149 ArrayBase::into_owned(self)
150 }
151}
152
153impl<S> MaybeOwnedMatrix for &ArrayBase<S, Ix2>
154where
155 S: Data,
156 S::Elem: Clone,
157{
158 type Elem = S::Elem;
159
160 fn into_owned(self) -> Array2<S::Elem> {
161 self.to_owned()
162 }
163}
164
165impl<A> MaybeOwnedMatrix for &ArrayRef2<A>
166where
167 A: Clone,
168{
169 type Elem = A;
170
171 fn into_owned(self) -> Array2<A> {
172 self.to_owned()
173 }
174}
175
176impl<T1, T2> EigGeneralized for (T1, T2)
177where
178 T1: MaybeOwnedMatrix,
179 T1::Elem: Lapack + Scalar,
180 T2: MaybeOwnedMatrix<Elem = T1::Elem>,
181{
182 type EigVal = Array1<GeneralizedEigenvalue<<T1::Elem as Scalar>::Complex>>;
183 type EigVec = Array2<<T1::Elem as Scalar>::Complex>;
184 type Real = <T1::Elem as Scalar>::Real;
185
186 fn eig_generalized(
187 self,
188 thresh_opt: Option<Self::Real>,
189 ) -> Result<(Self::EigVal, Self::EigVec)> {
190 let (mut a, mut b) = (self.0.into_owned(), self.1.into_owned());
191 let layout = a.square_layout()?;
192 let (s, t) = T1::Elem::eig_generalized(
193 true,
194 layout,
195 a.as_allocated_mut()?,
196 b.as_allocated_mut()?,
197 thresh_opt,
198 )?;
199 let n = layout.len() as usize;
200 Ok((
201 ArrayBase::from(s),
202 Array2::from_shape_vec((n, n).f(), t).unwrap(),
203 ))
204 }
205}
206
207#[cfg(test)]
208mod tests {
209 use crate::MaybeOwnedMatrix;
210
211 #[test]
212 fn test_maybe_owned_matrix() {
213 let a = array![[1.0, 2.0], [3.0, 4.0]];
214 let a_ptr = a.as_ptr();
215 let a1 = MaybeOwnedMatrix::into_owned(a);
216 assert_eq!(a_ptr, a1.as_ptr());
217
218 let b = a1.clone();
219 let b1 = MaybeOwnedMatrix::into_owned(&b);
220 assert_eq!(b, b1);
221 assert_ne!(b.as_ptr(), b1.as_ptr());
222
223 let b2 = MaybeOwnedMatrix::into_owned(&*b);
224 assert_eq!(b, b2);
225 assert_ne!(b.as_ptr(), b2.as_ptr());
226 }
227}