|
1 | 1 | use super::*;
|
2 | 2 | use crate::{inner::*, norm::*};
|
3 |
| -use num_traits::{One, Zero}; |
| 3 | +use num_traits::One; |
4 | 4 |
|
5 | 5 | /// Calc a reflactor `w` from a vector `x`
|
6 |
| -pub fn calc_reflector<A, S>(x: &mut ArrayBase<S, Ix1>) |
| 6 | +pub fn calc_reflector<A, S>(x: &mut ArrayBase<S, Ix1>) -> A |
7 | 7 | where
|
8 | 8 | A: Scalar + Lapack,
|
9 | 9 | S: DataMut<Elem = A>,
|
|
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)});
|
| 16 | + alpha |
16 | 17 | }
|
17 | 18 |
|
18 | 19 | /// Take a reflection using `w`
|
@@ -121,35 +122,24 @@ impl<A: Scalar + Lapack> Orthogonalizer for Householder<A> {
|
121 | 122 | S: DataMut<Elem = A>,
|
122 | 123 | {
|
123 | 124 | assert_eq!(a.len(), self.dim);
|
124 |
| - |
125 |
| - self.forward_reflection(&mut a); |
126 |
| - |
127 | 125 | let k = self.len();
|
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 | 126 |
|
| 127 | + self.forward_reflection(&mut a); |
135 | 128 | let mut coef = Array::zeros(k + 1);
|
136 | 129 | for i in 0..k {
|
137 | 130 | coef[i] = a[i];
|
138 | 131 | }
|
| 132 | + if self.is_full() { |
| 133 | + return Err(coef); // coef[k] must be zero in this case |
| 134 | + } |
| 135 | + |
| 136 | + let alpha = calc_reflector(&mut a.slice_mut(s![k..])); |
139 | 137 | coef[k] = alpha;
|
140 | 138 |
|
141 | 139 | if alpha.abs() < rtol {
|
142 | 140 | // linearly dependent
|
143 | 141 | return Err(coef);
|
144 | 142 | }
|
145 |
| - |
146 |
| - assert!(k < a.len()); // this must hold because `alpha == 0` if k >= a.len() |
147 |
| - |
148 |
| - // Add reflector |
149 |
| - a[k] -= alpha; |
150 |
| - let norm = a.slice(s![k..]).norm_l2(); |
151 |
| - azip!(mut a (a.slice_mut(s![..k])) in { *a = A::zero() }); |
152 |
| - azip!(mut a (a.slice_mut(s![k..])) in { *a = a.div_real(norm) }); |
153 | 143 | self.v.push(a.into_owned());
|
154 | 144 | Ok(coef)
|
155 | 145 | }
|
@@ -184,6 +174,7 @@ where
|
184 | 174 | mod tests {
|
185 | 175 | use super::*;
|
186 | 176 | use crate::assert::*;
|
| 177 | + use num_traits::Zero; |
187 | 178 |
|
188 | 179 | #[test]
|
189 | 180 | fn check_reflector() {
|
|
0 commit comments