Skip to content

Commit c953001

Browse files
committed
Split generalized eigenvalue routine
1 parent 33e2dc3 commit c953001

File tree

3 files changed

+118
-90
lines changed

3 files changed

+118
-90
lines changed

lax/src/eigh.rs

Lines changed: 9 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -21,33 +21,16 @@ pub trait Eigh_: Scalar {
2121
uplo: UPLO,
2222
a: &mut [Self],
2323
) -> Result<Vec<Self::Real>>;
24-
25-
/// Compute generalized right eigenvalue and eigenvectors $Ax = \lambda B x$
26-
///
27-
/// LAPACK correspondance
28-
/// ----------------------
29-
///
30-
/// | f32 | f64 | c32 | c64 |
31-
/// |:------|:------|:------|:------|
32-
/// | ssygv | dsygv | chegv | zhegv |
33-
///
34-
fn eigh_generalized(
35-
calc_eigenvec: bool,
36-
layout: MatrixLayout,
37-
uplo: UPLO,
38-
a: &mut [Self],
39-
b: &mut [Self],
40-
) -> Result<Vec<Self::Real>>;
4124
}
4225

4326
macro_rules! impl_eigh {
44-
(@real, $scalar:ty, $ev:path, $evg:path) => {
45-
impl_eigh!(@body, $scalar, $ev, $evg, );
27+
(@real, $scalar:ty, $ev:path) => {
28+
impl_eigh!(@body, $scalar, $ev, );
4629
};
47-
(@complex, $scalar:ty, $ev:path, $evg:path) => {
48-
impl_eigh!(@body, $scalar, $ev, $evg, rwork);
30+
(@complex, $scalar:ty, $ev:path) => {
31+
impl_eigh!(@body, $scalar, $ev, rwork);
4932
};
50-
(@body, $scalar:ty, $ev:path, $evg:path, $($rwork_ident:ident),*) => {
33+
(@body, $scalar:ty, $ev:path, $($rwork_ident:ident),*) => {
5134
impl Eigh_ for $scalar {
5235
fn eigh(
5336
calc_v: bool,
@@ -106,75 +89,11 @@ macro_rules! impl_eigh {
10689
let eigs = unsafe { eigs.assume_init() };
10790
Ok(eigs)
10891
}
109-
110-
fn eigh_generalized(
111-
calc_v: bool,
112-
layout: MatrixLayout,
113-
uplo: UPLO,
114-
a: &mut [Self],
115-
b: &mut [Self],
116-
) -> Result<Vec<Self::Real>> {
117-
assert_eq!(layout.len(), layout.lda());
118-
let n = layout.len();
119-
let jobz = if calc_v { JobEv::All } else { JobEv::None };
120-
let mut eigs: Vec<MaybeUninit<Self::Real>> = vec_uninit(n as usize);
121-
122-
$(
123-
let mut $rwork_ident: Vec<MaybeUninit<Self::Real>> = vec_uninit(3 * n as usize - 2);
124-
)*
125-
126-
// calc work size
127-
let mut info = 0;
128-
let mut work_size = [Self::zero()];
129-
unsafe {
130-
$evg(
131-
&1, // ITYPE A*x = (lambda)*B*x
132-
jobz.as_ptr(),
133-
uplo.as_ptr(),
134-
&n,
135-
AsPtr::as_mut_ptr(a),
136-
&n,
137-
AsPtr::as_mut_ptr(b),
138-
&n,
139-
AsPtr::as_mut_ptr(&mut eigs),
140-
AsPtr::as_mut_ptr(&mut work_size),
141-
&(-1),
142-
$(AsPtr::as_mut_ptr(&mut $rwork_ident),)*
143-
&mut info,
144-
);
145-
}
146-
info.as_lapack_result()?;
147-
148-
// actual evg
149-
let lwork = work_size[0].to_usize().unwrap();
150-
let mut work: Vec<MaybeUninit<Self>> = vec_uninit(lwork);
151-
let lwork = lwork as i32;
152-
unsafe {
153-
$evg(
154-
&1, // ITYPE A*x = (lambda)*B*x
155-
jobz.as_ptr(),
156-
uplo.as_ptr(),
157-
&n,
158-
AsPtr::as_mut_ptr(a),
159-
&n,
160-
AsPtr::as_mut_ptr(b),
161-
&n,
162-
AsPtr::as_mut_ptr(&mut eigs),
163-
AsPtr::as_mut_ptr(&mut work),
164-
&lwork,
165-
$(AsPtr::as_mut_ptr(&mut $rwork_ident),)*
166-
&mut info,
167-
);
168-
}
169-
info.as_lapack_result()?;
170-
let eigs = unsafe { eigs.assume_init() };
171-
Ok(eigs)
172-
}
17392
}
17493
};
17594
} // impl_eigh!
17695

177-
impl_eigh!(@real, f64, lapack_sys::dsyev_, lapack_sys::dsygv_);
178-
impl_eigh!(@real, f32, lapack_sys::ssyev_, lapack_sys::ssygv_);
179-
impl_eigh!(@complex, c64, lapack_sys::zheev_, lapack_sys::zhegv_);
180-
impl_eigh!(@complex, c32, lapack_sys::cheev_, lapack_sys::chegv_);
96+
impl_eigh!(@real, f64, lapack_sys::dsyev_);
97+
impl_eigh!(@real, f32, lapack_sys::ssyev_);
98+
impl_eigh!(@complex, c64, lapack_sys::zheev_);
99+
impl_eigh!(@complex, c32, lapack_sys::cheev_);

lax/src/eigh_generalized.rs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
use super::*;
2+
use crate::{error::*, layout::MatrixLayout};
3+
use cauchy::*;
4+
use num_traits::{ToPrimitive, Zero};
5+
6+
#[cfg_attr(doc, katexit::katexit)]
7+
/// Eigenvalue problem for symmetric/hermite matrix
8+
pub trait EighGeneralized_: Scalar {
9+
/// Compute generalized right eigenvalue and eigenvectors $Ax = \lambda B x$
10+
///
11+
/// LAPACK correspondance
12+
/// ----------------------
13+
///
14+
/// | f32 | f64 | c32 | c64 |
15+
/// |:------|:------|:------|:------|
16+
/// | ssygv | dsygv | chegv | zhegv |
17+
///
18+
fn eigh_generalized(
19+
calc_eigenvec: bool,
20+
layout: MatrixLayout,
21+
uplo: UPLO,
22+
a: &mut [Self],
23+
b: &mut [Self],
24+
) -> Result<Vec<Self::Real>>;
25+
}
26+
27+
macro_rules! impl_eigh {
28+
(@real, $scalar:ty, $evg:path) => {
29+
impl_eigh!(@body, $scalar, $evg, );
30+
};
31+
(@complex, $scalar:ty, $evg:path) => {
32+
impl_eigh!(@body, $scalar, $evg, rwork);
33+
};
34+
(@body, $scalar:ty, $evg:path, $($rwork_ident:ident),*) => {
35+
impl EighGeneralized_ for $scalar {
36+
fn eigh_generalized(
37+
calc_v: bool,
38+
layout: MatrixLayout,
39+
uplo: UPLO,
40+
a: &mut [Self],
41+
b: &mut [Self],
42+
) -> Result<Vec<Self::Real>> {
43+
assert_eq!(layout.len(), layout.lda());
44+
let n = layout.len();
45+
let jobz = if calc_v { JobEv::All } else { JobEv::None };
46+
let mut eigs: Vec<MaybeUninit<Self::Real>> = vec_uninit(n as usize);
47+
48+
$(
49+
let mut $rwork_ident: Vec<MaybeUninit<Self::Real>> = vec_uninit(3 * n as usize - 2);
50+
)*
51+
52+
// calc work size
53+
let mut info = 0;
54+
let mut work_size = [Self::zero()];
55+
unsafe {
56+
$evg(
57+
&1, // ITYPE A*x = (lambda)*B*x
58+
jobz.as_ptr(),
59+
uplo.as_ptr(),
60+
&n,
61+
AsPtr::as_mut_ptr(a),
62+
&n,
63+
AsPtr::as_mut_ptr(b),
64+
&n,
65+
AsPtr::as_mut_ptr(&mut eigs),
66+
AsPtr::as_mut_ptr(&mut work_size),
67+
&(-1),
68+
$(AsPtr::as_mut_ptr(&mut $rwork_ident),)*
69+
&mut info,
70+
);
71+
}
72+
info.as_lapack_result()?;
73+
74+
// actual evg
75+
let lwork = work_size[0].to_usize().unwrap();
76+
let mut work: Vec<MaybeUninit<Self>> = vec_uninit(lwork);
77+
let lwork = lwork as i32;
78+
unsafe {
79+
$evg(
80+
&1, // ITYPE A*x = (lambda)*B*x
81+
jobz.as_ptr(),
82+
uplo.as_ptr(),
83+
&n,
84+
AsPtr::as_mut_ptr(a),
85+
&n,
86+
AsPtr::as_mut_ptr(b),
87+
&n,
88+
AsPtr::as_mut_ptr(&mut eigs),
89+
AsPtr::as_mut_ptr(&mut work),
90+
&lwork,
91+
$(AsPtr::as_mut_ptr(&mut $rwork_ident),)*
92+
&mut info,
93+
);
94+
}
95+
info.as_lapack_result()?;
96+
let eigs = unsafe { eigs.assume_init() };
97+
Ok(eigs)
98+
}
99+
}
100+
};
101+
} // impl_eigh!
102+
103+
impl_eigh!(@real, f64, lapack_sys::dsygv_);
104+
impl_eigh!(@real, f32, lapack_sys::ssygv_);
105+
impl_eigh!(@complex, c64, lapack_sys::zhegv_);
106+
impl_eigh!(@complex, c32, lapack_sys::chegv_);

lax/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ pub mod eig;
8989
mod alloc;
9090
mod cholesky;
9191
mod eigh;
92+
mod eigh_generalized;
9293
mod least_squares;
9394
mod opnorm;
9495
mod qr;
@@ -102,6 +103,7 @@ mod tridiagonal;
102103

103104
pub use self::cholesky::*;
104105
pub use self::eigh::*;
106+
pub use self::eigh_generalized::*;
105107
pub use self::flags::*;
106108
pub use self::least_squares::*;
107109
pub use self::opnorm::*;
@@ -130,6 +132,7 @@ pub trait Lapack:
130132
+ Solveh_
131133
+ Cholesky_
132134
+ Eigh_
135+
+ EighGeneralized_
133136
+ Triangular_
134137
+ Tridiagonal_
135138
+ Rcond_

0 commit comments

Comments
 (0)