|
9 | 9 | S: DataMut<Elem = A>, |
10 | 10 | { |
11 | 11 | let norm = x.norm_l2(); |
12 | | - let alpha = x[0].mul_real(norm / x[0].abs()); |
| 12 | + let alpha = -x[0].mul_real(norm / x[0].abs()); |
13 | 13 | x[0] -= alpha; |
14 | 14 | let inv_rev_norm = A::Real::one() / x.norm_l2(); |
15 | 15 | azip!(mut a(x) in { *a = a.mul_real(inv_rev_norm)}); |
@@ -87,11 +87,7 @@ impl<A: Scalar + Lapack> Householder<A> { |
87 | 87 | S: Data<Elem = A>, |
88 | 88 | { |
89 | 89 | let l = self.v.len(); |
90 | | - if l == self.dim { |
91 | | - Zero::zero() |
92 | | - } else { |
93 | | - a.slice(s![l..]).norm_l2() |
94 | | - } |
| 90 | + a.slice(s![l..]).norm_l2() |
95 | 91 | } |
96 | 92 | } |
97 | 93 |
|
@@ -125,32 +121,34 @@ impl<A: Scalar + Lapack> Orthogonalizer for Householder<A> { |
125 | 121 | S: DataMut<Elem = A>, |
126 | 122 | { |
127 | 123 | assert_eq!(a.len(), self.dim); |
128 | | - let k = self.len(); |
| 124 | + |
129 | 125 | self.forward_reflection(&mut a); |
| 126 | + |
| 127 | + let k = self.len(); |
130 | 128 | let alpha = self.eval_residual(&a); |
| 129 | + let alpha = if k < a.len() && a[k].abs() > Zero::zero() { |
| 130 | + -a[k].mul_real(alpha / a[k].abs()) |
| 131 | + } else { |
| 132 | + A::from_real(alpha) |
| 133 | + }; |
| 134 | + |
131 | 135 | let mut coef = Array::zeros(k + 1); |
132 | 136 | for i in 0..k { |
133 | 137 | coef[i] = a[i]; |
134 | 138 | } |
135 | | - coef[k] = A::from_real(alpha); |
136 | | - if alpha < rtol { |
| 139 | + coef[k] = alpha; |
| 140 | + |
| 141 | + if alpha.abs() < rtol { |
137 | 142 | // linearly dependent |
138 | 143 | return Err(coef); |
139 | 144 | } |
140 | 145 |
|
141 | 146 | assert!(k < a.len()); // this must hold because `alpha == 0` if k >= a.len() |
142 | 147 |
|
143 | 148 | // Add reflector |
144 | | - let alpha = if a[k].abs() > Zero::zero() { |
145 | | - a[k].mul_real(alpha / a[k].abs()) |
146 | | - } else { |
147 | | - A::from_real(alpha) |
148 | | - }; |
149 | | - coef[k] = alpha; |
150 | | - |
151 | 149 | a[k] -= alpha; |
152 | 150 | let norm = a.slice(s![k..]).norm_l2(); |
153 | | - azip!(mut a (a.slice_mut(s![..k])) in { *a = Zero::zero() }); // this can be omitted |
| 151 | + azip!(mut a (a.slice_mut(s![..k])) in { *a = A::zero() }); |
154 | 152 | azip!(mut a (a.slice_mut(s![k..])) in { *a = a.div_real(norm) }); |
155 | 153 | self.v.push(a.into_owned()); |
156 | 154 | Ok(coef) |
@@ -195,7 +193,7 @@ mod tests { |
195 | 193 | reflect(&w, &mut a); |
196 | 194 | close_l2( |
197 | 195 | &a, |
198 | | - &array![c64::new(2.0.sqrt(), 2.0.sqrt()), c64::zero(), c64::zero()], |
| 196 | + &array![-c64::new(2.0.sqrt(), 2.0.sqrt()), c64::zero(), c64::zero()], |
199 | 197 | 1e-9, |
200 | 198 | ); |
201 | 199 | } |
|
0 commit comments