Skip to content

Commit cc369fb

Browse files
committed
HouseholderWork and HouseholderWorkImpl
1 parent 0b133cf commit cc369fb

File tree

1 file changed

+110
-0
lines changed

1 file changed

+110
-0
lines changed

lax/src/qr.rs

+110
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,116 @@ pub trait QR_: Sized {
1818
fn qr(l: MatrixLayout, a: &mut [Self]) -> Result<Vec<Self>>;
1919
}
2020

21+
pub struct HouseholderWork<T: Scalar> {
22+
pub m: i32,
23+
pub n: i32,
24+
pub layout: MatrixLayout,
25+
pub tau: Vec<MaybeUninit<T>>,
26+
pub work: Vec<MaybeUninit<T>>,
27+
}
28+
29+
pub trait HouseholderWorkImpl: Sized {
30+
type Elem: Scalar;
31+
fn new(l: MatrixLayout) -> Result<Self>;
32+
fn calc(&mut self, a: &mut [Self::Elem]) -> Result<&[Self::Elem]>;
33+
fn eval(self, a: &mut [Self::Elem]) -> Result<Vec<Self::Elem>>;
34+
}
35+
36+
macro_rules! impl_householder_work {
37+
($s:ty, $qrf:path, $lqf: path) => {
38+
impl HouseholderWorkImpl for HouseholderWork<$s> {
39+
type Elem = $s;
40+
41+
fn new(layout: MatrixLayout) -> Result<Self> {
42+
let m = layout.lda();
43+
let n = layout.len();
44+
let k = m.min(n);
45+
let mut tau = vec_uninit(k as usize);
46+
let mut info = 0;
47+
let mut work_size = [Self::Elem::zero()];
48+
match layout {
49+
MatrixLayout::F { .. } => unsafe {
50+
$qrf(
51+
&m,
52+
&n,
53+
std::ptr::null_mut(),
54+
&m,
55+
AsPtr::as_mut_ptr(&mut tau),
56+
AsPtr::as_mut_ptr(&mut work_size),
57+
&(-1),
58+
&mut info,
59+
)
60+
},
61+
MatrixLayout::C { .. } => unsafe {
62+
$lqf(
63+
&m,
64+
&n,
65+
std::ptr::null_mut(),
66+
&m,
67+
AsPtr::as_mut_ptr(&mut tau),
68+
AsPtr::as_mut_ptr(&mut work_size),
69+
&(-1),
70+
&mut info,
71+
)
72+
},
73+
}
74+
info.as_lapack_result()?;
75+
let lwork = work_size[0].to_usize().unwrap();
76+
let work = vec_uninit(lwork);
77+
Ok(HouseholderWork {
78+
n,
79+
m,
80+
layout,
81+
tau,
82+
work,
83+
})
84+
}
85+
86+
fn calc(&mut self, a: &mut [Self::Elem]) -> Result<&[Self::Elem]> {
87+
let lwork = self.work.len().to_i32().unwrap();
88+
let mut info = 0;
89+
match self.layout {
90+
MatrixLayout::F { .. } => unsafe {
91+
$qrf(
92+
&self.m,
93+
&self.n,
94+
AsPtr::as_mut_ptr(a),
95+
&self.m,
96+
AsPtr::as_mut_ptr(&mut self.tau),
97+
AsPtr::as_mut_ptr(&mut self.work),
98+
&lwork,
99+
&mut info,
100+
);
101+
},
102+
MatrixLayout::C { .. } => unsafe {
103+
$lqf(
104+
&self.m,
105+
&self.n,
106+
AsPtr::as_mut_ptr(a),
107+
&self.m,
108+
AsPtr::as_mut_ptr(&mut self.tau),
109+
AsPtr::as_mut_ptr(&mut self.work),
110+
&lwork,
111+
&mut info,
112+
);
113+
},
114+
}
115+
info.as_lapack_result()?;
116+
Ok(unsafe { self.tau.slice_assume_init_ref() })
117+
}
118+
119+
fn eval(mut self, a: &mut [Self::Elem]) -> Result<Vec<Self::Elem>> {
120+
let _eig = self.calc(a)?;
121+
Ok(unsafe { self.tau.assume_init() })
122+
}
123+
}
124+
};
125+
}
126+
impl_householder_work!(c64, lapack_sys::zgeqrf_, lapack_sys::zgelqf_);
127+
impl_householder_work!(c32, lapack_sys::cgeqrf_, lapack_sys::cgelqf_);
128+
impl_householder_work!(f64, lapack_sys::dgeqrf_, lapack_sys::dgelqf_);
129+
impl_householder_work!(f32, lapack_sys::sgeqrf_, lapack_sys::sgelqf_);
130+
21131
macro_rules! impl_qr {
22132
($scalar:ty, $qrf:path, $lqf:path, $gqr:path, $glq:path) => {
23133
impl QR_ for $scalar {

0 commit comments

Comments
 (0)