@@ -43,18 +43,18 @@ pub type Coefficients<A> = Array1<A>;
4343/// ```rust
4444/// # use ndarray::*;
4545/// # use ndarray_linalg::{krylov::*, *};
46- /// let mut mgs = MGS::new(3);
47- /// let coef = mgs.append(array![0.0, 1.0, 0.0], 1e-9).unwrap ();
46+ /// let mut mgs = MGS::new(3, 1e-9 );
47+ /// let coef = mgs.append(array![0.0, 1.0, 0.0]).into_coeff ();
4848/// close_l2(&coef, &array![1.0], 1e-9);
4949///
50- /// let coef = mgs.append(array![1.0, 1.0, 0.0], 1e-9).unwrap ();
50+ /// let coef = mgs.append(array![1.0, 1.0, 0.0]).into_coeff ();
5151/// close_l2(&coef, &array![1.0, 1.0], 1e-9);
5252///
5353/// // Fail if the vector is linearly dependent
54- /// assert!(mgs.append(array![1.0, 2.0, 0.0], 1e-9).is_err ());
54+ /// assert!(mgs.append(array![1.0, 2.0, 0.0]).is_dependent ());
5555///
5656/// // You can get coefficients of dependent vector
57- /// if let Err (coef) = mgs.append(array![1.0, 2.0, 0.0], 1e-9 ) {
57+ /// if let AppendResult::Dependent (coef) = mgs.append(array![1.0, 2.0, 0.0]) {
5858/// close_l2(&coef, &array![2.0, 1.0, 0.0], 1e-9);
5959/// }
6060/// ```
@@ -76,6 +76,8 @@ pub trait Orthogonalizer {
7676 self . len ( ) == 0
7777 }
7878
79+ fn tolerance ( & self ) -> <Self :: Elem as Scalar >:: Real ;
80+
7981 /// Decompose given vector into the span of current basis and
8082 /// its tangent space
8183 ///
@@ -96,18 +98,47 @@ pub trait Orthogonalizer {
9698 S : Data < Elem = Self :: Elem > ;
9799
98100 /// Add new vector if the residual is larger than relative tolerance
99- fn append < S > (
100- & mut self ,
101- a : ArrayBase < S , Ix1 > ,
102- rtol : <Self :: Elem as Scalar >:: Real ,
103- ) -> Result < Coefficients < Self :: Elem > , Coefficients < Self :: Elem > >
101+ fn append < S > ( & mut self , a : ArrayBase < S , Ix1 > ) -> AppendResult < Self :: Elem >
104102 where
105103 S : DataMut < Elem = Self :: Elem > ;
106104
107105 /// Get Q-matrix of generated basis
108106 fn get_q ( & self ) -> Q < Self :: Elem > ;
109107}
110108
109+ pub enum AppendResult < A > {
110+ Added ( Coefficients < A > ) ,
111+ Dependent ( Coefficients < A > ) ,
112+ }
113+
114+ impl < A : Scalar > AppendResult < A > {
115+ pub fn into_coeff ( self ) -> Coefficients < A > {
116+ match self {
117+ AppendResult :: Added ( c) => c,
118+ AppendResult :: Dependent ( c) => c,
119+ }
120+ }
121+
122+ pub fn is_dependent ( & self ) -> bool {
123+ match self {
124+ AppendResult :: Added ( _) => false ,
125+ AppendResult :: Dependent ( _) => true ,
126+ }
127+ }
128+
129+ pub fn coeff ( & self ) -> & Coefficients < A > {
130+ match self {
131+ AppendResult :: Added ( c) => c,
132+ AppendResult :: Dependent ( c) => c,
133+ }
134+ }
135+
136+ pub fn residual_norm ( & self ) -> A :: Real {
137+ let c = self . coeff ( ) ;
138+ c[ c. len ( ) - 1 ] . abs ( )
139+ }
140+ }
141+
111142/// Strategy for linearly dependent vectors appearing in iterative QR decomposition
112143#[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
113144pub enum Strategy {
@@ -133,7 +164,6 @@ pub enum Strategy {
133164pub fn qr < A , S > (
134165 iter : impl Iterator < Item = ArrayBase < S , Ix1 > > ,
135166 mut ortho : impl Orthogonalizer < Elem = A > ,
136- rtol : A :: Real ,
137167 strategy : Strategy ,
138168) -> ( Q < A > , R < A > )
139169where
@@ -144,9 +174,9 @@ where
144174
145175 let mut coefs = Vec :: new ( ) ;
146176 for a in iter {
147- match ortho. append ( a. into_owned ( ) , rtol ) {
148- Ok ( coef) => coefs. push ( coef) ,
149- Err ( coef) => match strategy {
177+ match ortho. append ( a. into_owned ( ) ) {
178+ AppendResult :: Added ( coef) => coefs. push ( coef) ,
179+ AppendResult :: Dependent ( coef) => match strategy {
150180 Strategy :: Terminate => break ,
151181 Strategy :: Skip => continue ,
152182 Strategy :: Full => coefs. push ( coef) ,
0 commit comments