11use super :: * ;
2+ use crate :: norm:: Norm ;
3+ use num_traits:: One ;
24use std:: iter:: Fuse ;
35
46pub struct Arnoldi < A , S , F , Ortho >
@@ -15,14 +17,25 @@ where
1517
1618impl < A , S , F , Ortho > Arnoldi < A , S , F , Ortho >
1719where
18- A : Scalar ,
20+ A : Scalar + Lapack ,
1921 S : DataMut < Elem = A > ,
2022 F : Fn ( & mut ArrayBase < S , Ix1 > ) ,
2123 Ortho : Orthogonalizer < Elem = A > ,
2224{
23- pub fn new ( a : F , v : ArrayBase < S , Ix1 > , ortho : Ortho ) -> Fuse < Self > {
25+ pub fn new ( a : F , mut v : ArrayBase < S , Ix1 > , mut ortho : Ortho ) -> Fuse < Self > {
26+ assert_eq ! ( ortho. len( ) , 0 ) ;
27+ assert ! ( ortho. tolerance( ) < One :: one( ) ) ;
28+ // normalize before append because |v| may be smaller than ortho.tolerance()
29+ let norm = v. norm_l2 ( ) ;
30+ azip ! ( mut v( & mut v) in { * v = v. div_real( norm) } ) ;
31+ ortho. append ( v. view ( ) ) ;
2432 Iterator :: fuse ( Arnoldi { a, v, ortho } )
2533 }
34+
35+ /// Dimension of Krylov subspace
36+ pub fn krylov_dimension ( & self ) -> usize {
37+ self . ortho . len ( )
38+ }
2639}
2740
2841impl < A , S , F , Ortho > Iterator for Arnoldi < A , S , F , Ortho >
@@ -36,13 +49,62 @@ where
3649
3750 fn next ( & mut self ) -> Option < Self :: Item > {
3851 ( self . a ) ( & mut self . v ) ;
39- match self . ortho . div_append ( & mut self . v ) {
40- AppendResult :: Added ( coef) => {
41- let norm = coef[ coef. len ( ) - 1 ] . abs ( ) ;
42- azip ! ( mut a( & mut self . v) in { * a = a. div_real( norm) } ) ;
43- Some ( coef)
44- }
45- AppendResult :: Dependent ( _) => None ,
52+ let result = self . ortho . div_append ( & mut self . v ) ;
53+ azip ! ( mut v( & mut self . v) in { * v = v. div_real( result. residual_norm( ) ) } ) ;
54+ if result. is_dependent ( ) {
55+ None
56+ } else {
57+ Some ( result. into_coeff ( ) )
4658 }
4759 }
4860}
61+
62+ pub fn arnoldi_householder < A , S1 , S2 > (
63+ a : ArrayBase < S1 , Ix2 > ,
64+ v : ArrayBase < S2 , Ix1 > ,
65+ tol : A :: Real ,
66+ ) -> impl Iterator < Item = Array1 < A > >
67+ where
68+ A : Scalar + Lapack ,
69+ S1 : Data < Elem = A > ,
70+ S2 : DataMut < Elem = A > ,
71+ {
72+ let ( n, m) = a. dim ( ) ;
73+ assert_eq ! ( n, m, "Input matrix must be square" ) ;
74+ assert_eq ! ( m, v. len( ) , "Input matrix and vector sizes mismach" ) ;
75+
76+ let householder = Householder :: new ( n, tol) ;
77+ Arnoldi :: new (
78+ move |x| {
79+ let ax = a. dot ( x) ;
80+ azip ! ( mut x( x) , ax in { * x = ax } ) ;
81+ } ,
82+ v,
83+ householder,
84+ )
85+ }
86+
87+ pub fn arnoldi_mgs < A , S1 , S2 > (
88+ a : ArrayBase < S1 , Ix2 > ,
89+ v : ArrayBase < S2 , Ix1 > ,
90+ tol : A :: Real ,
91+ ) -> impl Iterator < Item = Array1 < A > >
92+ where
93+ A : Scalar + Lapack ,
94+ S1 : Data < Elem = A > ,
95+ S2 : DataMut < Elem = A > ,
96+ {
97+ let ( n, m) = a. dim ( ) ;
98+ assert_eq ! ( n, m, "Input matrix must be square" ) ;
99+ assert_eq ! ( m, v. len( ) , "Input matrix and vector sizes mismach" ) ;
100+
101+ let mgs = MGS :: new ( n, tol) ;
102+ Arnoldi :: new (
103+ move |x| {
104+ let ax = a. dot ( x) ;
105+ azip ! ( mut x( x) , ax in { * x = ax } ) ;
106+ } ,
107+ v,
108+ mgs,
109+ )
110+ }
0 commit comments