@@ -73,15 +73,19 @@ impl<A: Scalar> MGS<A> {
7373 /// # use ndarray::*;
7474 /// # use ndarray_linalg::*;
7575 /// let mut mgs = arnoldi::MGS::new(3);
76- /// let coef = mgs.append(array![1 .0, 0 .0, 0.0], 1e-9).unwrap();
76+ /// let coef = mgs.append(array![0 .0, 1 .0, 0.0], 1e-9).unwrap();
7777 /// close_l2(&coef, &array![1.0], 1e-9).unwrap();
7878 ///
7979 /// let coef = mgs.append(array![1.0, 1.0, 0.0], 1e-9).unwrap();
8080 /// close_l2(&coef, &array![1.0, 1.0], 1e-9).unwrap();
8181 ///
82- /// assert!(mgs.append(array![1.0, 2.0, 0.0], 1e-9).is_none()); // Cannot append dependent vector
82+ /// assert!(mgs.append(array![1.0, 2.0, 0.0], 1e-9).is_err()); // Fail if the vector is linearly dependend
83+ ///
84+ /// if let Err(coef) = mgs.append(array![1.0, 2.0, 0.0], 1e-9) {
85+ /// close_l2(&coef, &array![2.0, 1.0, 0.0], 1e-9).unwrap(); // You can get coefficients of dependent vector
86+ /// }
8387 /// ```
84- pub fn append < S > ( & mut self , a : ArrayBase < S , Ix1 > , rtol : A :: Real ) -> Option < Array1 < A > >
88+ pub fn append < S > ( & mut self , a : ArrayBase < S , Ix1 > , rtol : A :: Real ) -> Result < Array1 < A > , Array1 < A > >
8589 where
8690 A : Lapack ,
8791 S : Data < Elem = A > ,
@@ -91,11 +95,11 @@ impl<A: Scalar> MGS<A> {
9195 let nrm = coef[ coef. len ( ) - 1 ] . re ( ) ;
9296 if nrm < rtol {
9397 // Linearly dependent
94- return None ;
98+ return Err ( coef ) ;
9599 }
96100 azip ! ( mut a in { * a = * a / A :: from_real( nrm) } ) ;
97101 self . q . push ( a) ;
98- Some ( coef)
102+ Ok ( coef)
99103 }
100104
101105 /// Get orthogonal basis as Q matrix
@@ -104,7 +108,34 @@ impl<A: Scalar> MGS<A> {
104108 }
105109}
106110
107- pub fn mgs < A , S > ( iter : impl Iterator < Item = ArrayBase < S , Ix1 > > , dim : usize , rtol : A :: Real ) -> ( Q < A > , R < A > )
111+ /// Strategy for linearly dependent vectors appearing in iterative QR decomposition
112+ #[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
113+ pub enum Strategy {
114+ /// Terminate iteration if dependent vector comes
115+ Terminate ,
116+
117+ /// Skip dependent vector
118+ Skip ,
119+
120+ /// Orghotonalize dependent vector without adding to Q,
121+ /// thus R must be non-regular like following:
122+ ///
123+ /// ```ignore
124+ /// x x x x x
125+ /// 0 x x x x
126+ /// 0 0 0 x x
127+ /// 0 0 0 0 x
128+ /// 0 0 0 0 0 // 0-filled to be square matrix
129+ /// ```
130+ Full ,
131+ }
132+
133+ pub fn mgs < A , S > (
134+ iter : impl Iterator < Item = ArrayBase < S , Ix1 > > ,
135+ dim : usize ,
136+ rtol : A :: Real ,
137+ strategy : Strategy ,
138+ ) -> ( Q < A > , R < A > )
108139where
109140 A : Scalar + Lapack ,
110141 S : Data < Elem = A > ,
@@ -113,8 +144,12 @@ where
113144 let mut coefs = Vec :: new ( ) ;
114145 for a in iter {
115146 match ortho. append ( a, rtol) {
116- Some ( coef) => coefs. push ( coef) ,
117- None => break ,
147+ Ok ( coef) => coefs. push ( coef) ,
148+ Err ( coef) => match strategy {
149+ Strategy :: Terminate => break ,
150+ Strategy :: Skip => continue ,
151+ Strategy :: Full => coefs. push ( coef) ,
152+ } ,
118153 }
119154 }
120155 let m = coefs. len ( ) ;
0 commit comments