Skip to content

Commit 07dd23a

Browse files
committed
WIP: EigWorkImpl for f64
1 parent 0a78593 commit 07dd23a

File tree

1 file changed

+126
-3
lines changed

1 file changed

+126
-3
lines changed

lax/src/eig.rs

Lines changed: 126 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ pub struct EigWork<T: Scalar> {
4040
pub jobvl: JobEv,
4141

4242
/// Eigenvalues used in complex routines
43-
pub eigs: Option<Vec<MaybeUninit<T>>>,
43+
pub eigs: Option<Vec<MaybeUninit<T::Complex>>>,
4444
/// Real part of eigenvalues used in real routines
45-
pub eigs_re: Option<Vec<MaybeUninit<T>>>,
45+
pub eigs_re: Option<Vec<MaybeUninit<T::Real>>>,
4646
/// Imaginary part of eigenvalues used in real routines
47-
pub eigs_im: Option<Vec<MaybeUninit<T>>>,
47+
pub eigs_im: Option<Vec<MaybeUninit<T::Real>>>,
4848

4949
/// Left eigenvectors
5050
pub vl: Option<Vec<MaybeUninit<T>>>,
@@ -71,6 +71,26 @@ pub struct EigRef<'work, T: Scalar> {
7171
pub vl: Option<&'work [T::Complex]>,
7272
}
7373

74+
impl<T: Scalar> EigWork<T> {
75+
/// Create complex eigenvalues from real and imaginary parts.
76+
unsafe fn reconstruct_eigs(&mut self) {
77+
let n = self.n as usize;
78+
if self.eigs.is_none() {
79+
self.eigs = Some(vec_uninit(n));
80+
}
81+
let eigs = self.eigs.as_mut().unwrap();
82+
if let (Some(re), Some(im)) = (self.eigs_re.as_ref(), self.eigs_im.as_ref()) {
83+
assert_eq!(re.len(), n);
84+
assert_eq!(im.len(), n);
85+
for i in 0..n {
86+
eigs[i].write(T::complex(re[i].assume_init(), im[i].assume_init()));
87+
}
88+
} else {
89+
panic!("Called without constructing eigs_re and eigs_im");
90+
}
91+
}
92+
}
93+
7494
pub trait EigWorkImpl: Sized {
7595
type Elem: Scalar;
7696
/// Create new working memory for eigenvalues compution.
@@ -227,6 +247,109 @@ impl EigWorkImpl for EigWork<c64> {
227247
}
228248
}
229249

250+
impl EigWorkImpl for EigWork<f64> {
251+
type Elem = f64;
252+
253+
fn new(calc_v: bool, l: MatrixLayout) -> Result<Self> {
254+
let (n, _) = l.size();
255+
let (jobvl, jobvr) = if calc_v {
256+
match l {
257+
MatrixLayout::C { .. } => (JobEv::All, JobEv::None),
258+
MatrixLayout::F { .. } => (JobEv::None, JobEv::All),
259+
}
260+
} else {
261+
(JobEv::None, JobEv::None)
262+
};
263+
let mut eigs_re: Vec<MaybeUninit<f64>> = vec_uninit(n as usize);
264+
let mut eigs_im: Vec<MaybeUninit<f64>> = vec_uninit(n as usize);
265+
266+
let mut vl: Option<Vec<MaybeUninit<f64>>> = jobvl.then(|| vec_uninit((n * n) as usize));
267+
let mut vr: Option<Vec<MaybeUninit<f64>>> = jobvr.then(|| vec_uninit((n * n) as usize));
268+
269+
// calc work size
270+
let mut info = 0;
271+
let mut work_size: [f64; 1] = [0.0];
272+
unsafe {
273+
lapack_sys::dgeev_(
274+
jobvl.as_ptr(),
275+
jobvr.as_ptr(),
276+
&n,
277+
std::ptr::null_mut(),
278+
&n,
279+
AsPtr::as_mut_ptr(&mut eigs_re),
280+
AsPtr::as_mut_ptr(&mut eigs_im),
281+
AsPtr::as_mut_ptr(vl.as_deref_mut().unwrap_or(&mut [])),
282+
&n,
283+
AsPtr::as_mut_ptr(vr.as_deref_mut().unwrap_or(&mut [])),
284+
&n,
285+
AsPtr::as_mut_ptr(&mut work_size),
286+
&(-1),
287+
&mut info,
288+
)
289+
};
290+
info.as_lapack_result()?;
291+
292+
// actual ev
293+
let lwork = work_size[0].to_usize().unwrap();
294+
let work: Vec<MaybeUninit<f64>> = vec_uninit(lwork);
295+
296+
Ok(Self {
297+
n,
298+
jobvr,
299+
jobvl,
300+
eigs: None,
301+
eigs_re: Some(eigs_re),
302+
eigs_im: Some(eigs_im),
303+
rwork: None,
304+
vl,
305+
vr,
306+
work,
307+
})
308+
}
309+
310+
fn calc<'work>(&'work mut self, _a: &mut [f64]) -> Result<EigRef<'work, f64>> {
311+
todo!()
312+
}
313+
314+
fn eval(mut self, a: &mut [f64]) -> Result<Eig<f64>> {
315+
let lwork = self.work.len().to_i32().unwrap();
316+
let mut info = 0;
317+
unsafe {
318+
lapack_sys::dgeev_(
319+
self.jobvl.as_ptr(),
320+
self.jobvr.as_ptr(),
321+
&self.n,
322+
AsPtr::as_mut_ptr(a),
323+
&self.n,
324+
AsPtr::as_mut_ptr(self.eigs_re.as_mut().unwrap()),
325+
AsPtr::as_mut_ptr(self.eigs_im.as_mut().unwrap()),
326+
AsPtr::as_mut_ptr(self.vl.as_deref_mut().unwrap_or(&mut [])),
327+
&self.n,
328+
AsPtr::as_mut_ptr(self.vr.as_deref_mut().unwrap_or(&mut [])),
329+
&self.n,
330+
AsPtr::as_mut_ptr(&mut self.work),
331+
&lwork,
332+
&mut info,
333+
)
334+
};
335+
info.as_lapack_result()?;
336+
337+
let eig_re = unsafe { self.eigs_re.unwrap().assume_init() };
338+
let eig_im = unsafe { self.eigs_im.unwrap().assume_init() };
339+
let vl = unsafe { self.vl.map(|v| v.assume_init()) };
340+
let vr = unsafe { self.vr.map(|v| v.assume_init()) };
341+
342+
// reconstruct eigenvalues
343+
let eigs: Vec<c64> = eig_re
344+
.iter()
345+
.zip(eig_im.iter())
346+
.map(|(&re, &im)| c64::new(re, im))
347+
.collect();
348+
349+
Ok(Eig { eigs, vl, vr })
350+
}
351+
}
352+
230353
macro_rules! impl_eig_complex {
231354
($scalar:ty, $ev:path) => {
232355
impl Eig_ for $scalar {

0 commit comments

Comments
 (0)