@@ -21,6 +21,59 @@ pub type Q<A> = Array2<A>;
2121///
2222pub type R < A > = Array2 < A > ;
2323
24+ pub trait Orthogonalizer {
25+ type Elem : Scalar ;
26+
27+ /// Dimension of input array
28+ fn dim ( & self ) -> usize ;
29+
30+ /// Number of cached basis
31+ fn len ( & self ) -> usize ;
32+
33+ /// check if the basis spans entire space
34+ fn is_full ( & self ) -> bool {
35+ self . len ( ) == self . dim ( )
36+ }
37+
38+ fn is_empty ( & self ) -> bool {
39+ self . len ( ) == 0
40+ }
41+
42+ /// Orthogonalize given vector using current basis
43+ ///
44+ /// Panic
45+ /// -------
46+ /// - if the size of the input array mismatches to the dimension
47+ ///
48+ fn orthogonalize < S > ( & self , a : & mut ArrayBase < S , Ix1 > ) -> Array1 < Self :: Elem >
49+ where
50+ S : DataMut < Elem = Self :: Elem > ;
51+
52+ /// Add new vector if the residual is larger than relative tolerance
53+ ///
54+ /// Returns
55+ /// --------
56+ /// Coefficients to the `i`-th Q-vector
57+ ///
58+ /// - The size of array must be `self.len() + 1`
59+ /// - The last element is the residual norm of input vector
60+ ///
61+ /// Panic
62+ /// -------
63+ /// - if the size of the input array mismatches to the dimension
64+ ///
65+ fn append < S > (
66+ & mut self ,
67+ a : ArrayBase < S , Ix1 > ,
68+ rtol : <Self :: Elem as Scalar >:: Real ,
69+ ) -> Result < Array1 < Self :: Elem > , Array1 < Self :: Elem > >
70+ where
71+ S : DataMut < Elem = Self :: Elem > ;
72+
73+ /// Get Q-matrix of generated basis
74+ fn get_q ( & self ) -> Q < Self :: Elem > ;
75+ }
76+
2477/// Strategy for linearly dependent vectors appearing in iterative QR decomposition
2578#[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
2679pub enum Strategy {
@@ -41,3 +94,40 @@ pub enum Strategy {
4194 /// ```
4295 Full ,
4396}
97+
98+ /// Online QR decomposition using arbitrary orthogonalizer
99+ pub fn qr < A , S > (
100+ iter : impl Iterator < Item = ArrayBase < S , Ix1 > > ,
101+ mut ortho : impl Orthogonalizer < Elem = A > ,
102+ rtol : A :: Real ,
103+ strategy : Strategy ,
104+ ) -> ( Q < A > , R < A > )
105+ where
106+ A : Scalar + Lapack ,
107+ S : Data < Elem = A > ,
108+ {
109+ assert_eq ! ( ortho. len( ) , 0 ) ;
110+
111+ let mut coefs = Vec :: new ( ) ;
112+ for a in iter {
113+ match ortho. append ( a. into_owned ( ) , rtol) {
114+ Ok ( coef) => coefs. push ( coef) ,
115+ Err ( coef) => match strategy {
116+ Strategy :: Terminate => break ,
117+ Strategy :: Skip => continue ,
118+ Strategy :: Full => coefs. push ( coef) ,
119+ } ,
120+ }
121+ }
122+ let n = ortho. len ( ) ;
123+ let m = coefs. len ( ) ;
124+ let mut r = Array2 :: zeros ( ( n, m) . f ( ) ) ;
125+ for j in 0 ..m {
126+ for i in 0 ..n {
127+ if i < coefs[ j] . len ( ) {
128+ r[ ( i, j) ] = coefs[ j] [ i] ;
129+ }
130+ }
131+ }
132+ ( ortho. get_q ( ) , r)
133+ }
0 commit comments