|
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