Skip to content

Commit bcfee7b

Browse files
committed
Refactoring Householder
1 parent 2c4ed3d commit bcfee7b

File tree

2 files changed

+53
-16
lines changed

2 files changed

+53
-16
lines changed

src/krylov/householder.rs

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ pub struct Householder<A: Scalar> {
1414
v: Vec<Array1<A>>,
1515
}
1616

17-
impl<A: Scalar> Householder<A> {
17+
impl<A: Scalar + Lapack> Householder<A> {
1818
/// Create a new orthogonalizer
1919
pub fn new(dim: usize) -> Self {
2020
Householder { dim, v: Vec::new() }
2121
}
2222

2323
/// Take a Reflection `P = I - 2ww^T`
24-
fn reflect<S: DataMut<Elem = A>>(&self, k: usize, a: &mut ArrayBase<S, Ix1>) {
24+
fn fundamental_reflection<S: DataMut<Elem = A>>(&self, k: usize, a: &mut ArrayBase<S, Ix1>) {
2525
assert!(k < self.v.len());
2626
assert_eq!(a.len(), self.dim, "Input array size mismaches to the dimension");
2727

@@ -32,6 +32,42 @@ impl<A: Scalar> Householder<A> {
3232
a_slice[l] -= c * w[l];
3333
}
3434
}
35+
36+
/// Take forward reflection `P = P_l ... P_1`
37+
pub fn forward_reflection<S>(&self, a: &mut ArrayBase<S, Ix1>)
38+
where
39+
S: DataMut<Elem = A>,
40+
{
41+
assert!(a.len() == self.dim);
42+
let l = self.v.len();
43+
for k in 0..l {
44+
self.fundamental_reflection(k, a);
45+
}
46+
}
47+
48+
/// Take backward reflection `P = P_1 ... P_l`
49+
pub fn backward_reflection<S>(&self, a: &mut ArrayBase<S, Ix1>)
50+
where
51+
S: DataMut<Elem = A>,
52+
{
53+
assert!(a.len() == self.dim);
54+
let l = self.v.len();
55+
for k in (0..l).rev() {
56+
self.fundamental_reflection(k, a);
57+
}
58+
}
59+
60+
fn eval_residual<S>(&self, a: &ArrayBase<S, Ix1>) -> A::Real
61+
where
62+
S: Data<Elem = A>,
63+
{
64+
let l = self.v.len();
65+
if l == self.dim {
66+
Zero::zero()
67+
} else {
68+
a.slice(s![l..]).norm_l2()
69+
}
70+
}
3571
}
3672

3773
impl<A: Scalar + Lapack> Orthogonalizer for Householder<A> {
@@ -45,18 +81,18 @@ impl<A: Scalar + Lapack> Orthogonalizer for Householder<A> {
4581
self.v.len()
4682
}
4783

48-
fn orthogonalize<S>(&self, a: &mut ArrayBase<S, Ix1>) -> A::Real
84+
fn coeff<S>(&self, a: ArrayBase<S, Ix1>) -> Array1<A>
4985
where
50-
S: DataMut<Elem = A>,
86+
S: Data<Elem = A>,
5187
{
52-
for k in 0..self.len() {
53-
self.reflect(k, a);
54-
}
55-
if self.is_full() {
56-
return Zero::zero();
57-
}
58-
// residual norm
59-
a.slice(s![self.len()..]).norm_l2()
88+
let mut a = a.into_owned();
89+
self.forward_reflection(&mut a);
90+
let res = self.eval_residual(&a);
91+
let k = self.len();
92+
let mut c = Array1::zeros(k + 1);
93+
azip!(mut c(c.slice_mut(s![..k])), a(a.slice(s![..k])) in { *c = a });
94+
c[k] = A::from_real(res);
95+
c
6096
}
6197

6298
fn append<S>(&mut self, mut a: ArrayBase<S, Ix1>, rtol: A::Real) -> Result<Array1<A>, Array1<A>>
@@ -65,7 +101,8 @@ impl<A: Scalar + Lapack> Orthogonalizer for Householder<A> {
65101
{
66102
assert_eq!(a.len(), self.dim);
67103
let k = self.len();
68-
let alpha = self.orthogonalize(&mut a);
104+
self.forward_reflection(&mut a);
105+
let alpha = self.eval_residual(&a);
69106
let mut coef = Array::zeros(k + 1);
70107
for i in 0..k {
71108
coef[i] = a[i];
@@ -98,9 +135,7 @@ impl<A: Scalar + Lapack> Orthogonalizer for Householder<A> {
98135
let mut a = Array::zeros((self.dim(), self.len()));
99136
for (i, mut col) in a.axis_iter_mut(Axis(1)).enumerate() {
100137
col[i] = A::one();
101-
for l in (0..self.len()).rev() {
102-
self.reflect(l, &mut col);
103-
}
138+
self.backward_reflection(&mut col);
104139
}
105140
a
106141
}

src/krylov/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
use crate::types::*;
44
use ndarray::*;
55

6+
mod householder;
67
mod mgs;
78

9+
pub use householder::*;
810
pub use mgs::{mgs, MGS};
911

1012
/// Q-matrix

0 commit comments

Comments
 (0)