@@ -4,7 +4,7 @@ use num_traits::Zero;
4
4
5
5
/// Iterative orthogonalizer using Householder reflection
6
6
#[ derive( Debug , Clone ) ]
7
- pub struct Householder < A > {
7
+ pub struct Householder < A : Scalar > {
8
8
dim : usize ,
9
9
v : Vec < Array1 < A > > ,
10
10
}
@@ -18,21 +18,19 @@ impl<A: Scalar> Householder<A> {
18
18
fn reflect < S : DataMut < Elem = A > > ( & self , k : usize , a : & mut ArrayBase < S , Ix1 > ) {
19
19
assert ! ( k < self . v. len( ) ) ;
20
20
assert_eq ! ( a. len( ) , self . dim) ;
21
+
21
22
let w = self . v [ k] . slice ( s ! [ k..] ) ;
22
- let c = A :: from ( 2.0 ) . unwrap ( ) * w. inner ( & a. slice ( s ! [ k..] ) ) ;
23
- for l in k..self . dim {
24
- a[ l] -= c * w[ l - k] ;
23
+ let mut a_slice = a. slice_mut ( s ! [ k..] ) ;
24
+ let c = A :: from ( 2.0 ) . unwrap ( ) * w. inner ( & a_slice) ;
25
+ for l in 0 ..self . dim - k {
26
+ a_slice[ l] -= c * w[ l] ;
25
27
}
26
28
}
27
29
}
28
30
29
31
impl < A : Scalar + Lapack > Orthogonalizer for Householder < A > {
30
32
type Elem = A ;
31
33
32
- fn new ( dim : usize ) -> Self {
33
- Self { dim, v : Vec :: new ( ) }
34
- }
35
-
36
34
fn dim ( & self ) -> usize {
37
35
self . dim
38
36
}
@@ -48,8 +46,7 @@ impl<A: Scalar + Lapack> Orthogonalizer for Householder<A> {
48
46
for k in 0 ..self . len ( ) {
49
47
self . reflect ( k, a) ;
50
48
}
51
- if a. len ( ) >= self . len ( ) {
52
- // full rank
49
+ if self . is_full ( ) {
53
50
return Zero :: zero ( ) ;
54
51
}
55
52
// residual norm
@@ -60,12 +57,30 @@ impl<A: Scalar + Lapack> Orthogonalizer for Householder<A> {
60
57
where
61
58
S : DataMut < Elem = A > ,
62
59
{
63
- let residual = self . orthogonalize ( & mut a) ;
64
- let coef = a. slice ( s ! [ ..self . len( ) ] ) . into_owned ( ) ;
65
- if residual < rtol {
60
+ assert_eq ! ( a. len( ) , self . dim) ;
61
+ let alpha = self . orthogonalize ( & mut a) ;
62
+
63
+ // Generate coefficient vector
64
+ let mut coef = Array :: zeros ( self . len ( ) + 1 ) ;
65
+ for i in 0 ..self . len ( ) {
66
+ coef[ i] = a[ i] ;
67
+ }
68
+ coef[ self . len ( ) ] = A :: from_real ( alpha) ;
69
+
70
+ if alpha < rtol {
66
71
return Err ( coef) ;
67
72
}
73
+
74
+ // Add reflector
75
+ let k = self . len ( ) ;
76
+ let xi = a[ k] . re ( ) ;
77
+ a[ k] = A :: from ( if xi > Zero :: zero ( ) { xi + alpha } else { xi - alpha } ) . unwrap ( ) ;
78
+ let norm = a. slice ( s ! [ k..] ) . norm_l2 ( ) ;
79
+ dbg ! ( alpha) ;
80
+ dbg ! ( norm) ;
81
+ azip ! ( mut a ( a. slice_mut( s![ k..] ) ) in { * a = a. div_real( norm) } ) ;
68
82
self . v . push ( a. into_owned ( ) ) ;
83
+ dbg ! ( & self . v) ;
69
84
Ok ( coef)
70
85
}
71
86
@@ -98,6 +113,7 @@ mod tests {
98
113
assert ! ( householder. append( array![ 1.0 , 2.0 , 0.0 ] , 1e-9 ) . is_err( ) ) ;
99
114
100
115
if let Err ( coef) = householder. append ( array ! [ 1.0 , 2.0 , 0.0 ] , 1e-9 ) {
116
+ dbg ! ( & coef) ;
101
117
close_l2 ( & coef, & array ! [ 2.0 , 1.0 , 0.0 ] , 1e-9 ) . unwrap ( ) ;
102
118
}
103
119
}
0 commit comments