use crate::types::*;
use ndarray::*;
mod mgs;
pub use mgs::{mgs, MGS};
pub type Q<A> = Array2<A>;
pub type R<A> = Array2<A>;
pub trait Orthogonalizer {
type Elem: Scalar;
fn dim(&self) -> usize;
fn len(&self) -> usize;
fn is_full(&self) -> bool {
self.len() == self.dim()
}
fn is_empty(&self) -> bool {
self.len() == 0
}
fn orthogonalize<S>(&self, a: &mut ArrayBase<S, Ix1>) -> Array1<Self::Elem>
where
S: DataMut<Elem = Self::Elem>;
fn append<S>(
&mut self,
a: ArrayBase<S, Ix1>,
rtol: <Self::Elem as Scalar>::Real,
) -> Result<Array1<Self::Elem>, Array1<Self::Elem>>
where
S: DataMut<Elem = Self::Elem>;
fn get_q(&self) -> Q<Self::Elem>;
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Strategy {
Terminate,
Skip,
Full,
}
pub fn qr<A, S>(
iter: impl Iterator<Item = ArrayBase<S, Ix1>>,
mut ortho: impl Orthogonalizer<Elem = A>,
rtol: A::Real,
strategy: Strategy,
) -> (Q<A>, R<A>)
where
A: Scalar + Lapack,
S: Data<Elem = A>,
{
assert_eq!(ortho.len(), 0);
let mut coefs = Vec::new();
for a in iter {
match ortho.append(a.into_owned(), rtol) {
Ok(coef) => coefs.push(coef),
Err(coef) => match strategy {
Strategy::Terminate => break,
Strategy::Skip => continue,
Strategy::Full => coefs.push(coef),
},
}
}
let n = ortho.len();
let m = coefs.len();
let mut r = Array2::zeros((n, m).f());
for j in 0..m {
for i in 0..n {
if i < coefs[j].len() {
r[(i, j)] = coefs[j][i];
}
}
}
(ortho.get_q(), r)
}