Skip to content

Commit ee0788d

Browse files
committed
Orthogonalizer::div_append
1 parent 6c40611 commit ee0788d

File tree

3 files changed

+46
-20
lines changed

3 files changed

+46
-20
lines changed

src/krylov/householder.rs

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,17 @@ use crate::{inner::*, norm::*};
88
use num_traits::One;
99

1010
/// Calc a reflactor `w` from a vector `x`
11-
pub fn calc_reflector<A, S>(x: &mut ArrayBase<S, Ix1>) -> A
11+
pub fn calc_reflector<A, S>(x: &mut ArrayBase<S, Ix1>)
1212
where
1313
A: Scalar + Lapack,
1414
S: DataMut<Elem = A>,
1515
{
16+
assert!(x.len() > 0);
1617
let norm = x.norm_l2();
1718
let alpha = -x[0].mul_real(norm / x[0].abs());
1819
x[0] -= alpha;
1920
let inv_rev_norm = A::Real::one() / x.norm_l2();
2021
azip!(mut a(x) in { *a = a.mul_real(inv_rev_norm)});
21-
alpha
2222
}
2323

2424
/// Take a reflection `P = I - 2ww^T`
@@ -108,7 +108,12 @@ impl<A: Scalar + Lapack> Householder<A> {
108108
let res = a.slice(s![k..]).norm_l2();
109109
let mut c = Array1::zeros(k + 1);
110110
azip!(mut c(c.slice_mut(s![..k])), a(a.slice(s![..k])) in { *c = a });
111-
c[k] = A::from_real(res);
111+
if k < a.len() {
112+
let ak = a[k];
113+
c[k] = -ak.mul_real(res / ak.abs());
114+
} else {
115+
c[k] = A::from_real(res);
116+
}
112117
c
113118
}
114119

@@ -157,30 +162,37 @@ impl<A: Scalar + Lapack> Orthogonalizer for Householder<A> {
157162
self.compose_coefficients(&a)
158163
}
159164

160-
fn append<S>(&mut self, mut a: ArrayBase<S, Ix1>) -> AppendResult<A>
165+
fn div_append<S>(&mut self, a: &mut ArrayBase<S, Ix1>) -> AppendResult<A>
161166
where
162167
S: DataMut<Elem = A>,
163168
{
164169
assert_eq!(a.len(), self.dim);
165170
let k = self.len();
166-
167-
self.forward_reflection(&mut a);
168-
let mut coef = Array::zeros(k + 1);
169-
for i in 0..k {
170-
coef[i] = a[i];
171-
}
172-
if self.is_full() {
173-
return AppendResult::Dependent(coef); // coef[k] must be zero in this case
171+
self.forward_reflection(a);
172+
let coef = self.compose_coefficients(a);
173+
if coef[k].abs() < self.tol {
174+
return AppendResult::Dependent(coef);
174175
}
176+
calc_reflector(&mut a.slice_mut(s![k..]));
177+
self.v.push(a.to_owned());
178+
self.construct_residual(a);
179+
AppendResult::Added(coef)
180+
}
175181

176-
let alpha = calc_reflector(&mut a.slice_mut(s![k..]));
177-
coef[k] = alpha;
178-
179-
if alpha.abs() < self.tol {
180-
// linearly dependent
182+
fn append<S>(&mut self, a: ArrayBase<S, Ix1>) -> AppendResult<A>
183+
where
184+
S: Data<Elem = A>,
185+
{
186+
assert_eq!(a.len(), self.dim);
187+
let mut a = a.into_owned();
188+
let k = self.len();
189+
self.forward_reflection(&mut a);
190+
let coef = self.compose_coefficients(&a);
191+
if coef[k].abs() < self.tol {
181192
return AppendResult::Dependent(coef);
182193
}
183-
self.v.push(a.into_owned());
194+
calc_reflector(&mut a.slice_mut(s![k..]));
195+
self.v.push(a.to_owned());
184196
AppendResult::Added(coef)
185197
}
186198

src/krylov/mgs.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,22 @@ impl<A: Scalar + Lapack> Orthogonalizer for MGS<A> {
7474
S: Data<Elem = A>,
7575
{
7676
let mut a = a.into_owned();
77+
self.div_append(&mut a)
78+
}
79+
80+
fn div_append<S>(&mut self, mut a: &mut ArrayBase<S, Ix1>) -> AppendResult<A>
81+
where
82+
A: Lapack,
83+
S: DataMut<Elem = A>,
84+
{
7785
let coef = self.decompose(&mut a);
7886
let nrm = coef[coef.len() - 1].re();
7987
if nrm < self.tol {
8088
// Linearly dependent
8189
return AppendResult::Dependent(coef);
8290
}
83-
azip!(mut a in { *a = *a / A::from_real(nrm) });
84-
self.q.push(a);
91+
azip!(mut a(&mut *a) in { *a = *a / A::from_real(nrm) });
92+
self.q.push(a.to_owned());
8593
AppendResult::Added(coef)
8694
}
8795

src/krylov/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ pub trait Orthogonalizer {
9999

100100
/// Add new vector if the residual is larger than relative tolerance
101101
fn append<S>(&mut self, a: ArrayBase<S, Ix1>) -> AppendResult<Self::Elem>
102+
where
103+
S: Data<Elem = Self::Elem>;
104+
105+
/// Add new vector if the residual is larger than relative tolerance,
106+
/// and return the residual vector
107+
fn div_append<S>(&mut self, a: &mut ArrayBase<S, Ix1>) -> AppendResult<Self::Elem>
102108
where
103109
S: DataMut<Elem = Self::Elem>;
104110

0 commit comments

Comments
 (0)