Skip to content

Commit 4c1275a

Browse files
committed
Fix reflection bug
1 parent fb67133 commit 4c1275a

File tree

1 file changed

+16
-18
lines changed

1 file changed

+16
-18
lines changed

src/krylov/householder.rs

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ where
99
S: DataMut<Elem = A>,
1010
{
1111
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());
1313
x[0] -= alpha;
1414
let inv_rev_norm = A::Real::one() / x.norm_l2();
1515
azip!(mut a(x) in { *a = a.mul_real(inv_rev_norm)});
@@ -87,11 +87,7 @@ impl<A: Scalar + Lapack> Householder<A> {
8787
S: Data<Elem = A>,
8888
{
8989
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()
9591
}
9692
}
9793

@@ -125,32 +121,34 @@ impl<A: Scalar + Lapack> Orthogonalizer for Householder<A> {
125121
S: DataMut<Elem = A>,
126122
{
127123
assert_eq!(a.len(), self.dim);
128-
let k = self.len();
124+
129125
self.forward_reflection(&mut a);
126+
127+
let k = self.len();
130128
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+
131135
let mut coef = Array::zeros(k + 1);
132136
for i in 0..k {
133137
coef[i] = a[i];
134138
}
135-
coef[k] = A::from_real(alpha);
136-
if alpha < rtol {
139+
coef[k] = alpha;
140+
141+
if alpha.abs() < rtol {
137142
// linearly dependent
138143
return Err(coef);
139144
}
140145

141146
assert!(k < a.len()); // this must hold because `alpha == 0` if k >= a.len()
142147

143148
// 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-
151149
a[k] -= alpha;
152150
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() });
154152
azip!(mut a (a.slice_mut(s![k..])) in { *a = a.div_real(norm) });
155153
self.v.push(a.into_owned());
156154
Ok(coef)
@@ -195,7 +193,7 @@ mod tests {
195193
reflect(&w, &mut a);
196194
close_l2(
197195
&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()],
199197
1e-9,
200198
);
201199
}

0 commit comments

Comments
 (0)