@@ -21,6 +21,59 @@ pub type Q<A> = Array2<A>;
21
21
///
22
22
pub type R < A > = Array2 < A > ;
23
23
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
+
24
77
/// Strategy for linearly dependent vectors appearing in iterative QR decomposition
25
78
#[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
26
79
pub enum Strategy {
@@ -41,3 +94,40 @@ pub enum Strategy {
41
94
/// ```
42
95
Full ,
43
96
}
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