Skip to content

Commit 83a6eb1

Browse files
authored
Merge pull request #36 from termoshtt/hermite
Re-implementation of Eigh and Cholesky
2 parents dc1a71c + 4d65780 commit 83a6eb1

File tree

19 files changed

+334
-263
lines changed

19 files changed

+334
-263
lines changed

src/bin/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use ndarray_linalg::prelude::*;
77

88
fn main() {
99
let a = arr2(&[[3.0, 1.0, 1.0], [1.0, 3.0, 1.0], [1.0, 1.0, 3.0]]);
10-
let (e, vecs) = a.clone().eigh().unwrap();
10+
let (e, vecs): (Array1<_>, Array2<_>) = a.clone().eigh(UPLO::Upper).unwrap();
1111
println!("eigenvalues = \n{:?}", e);
1212
println!("V = \n{:?}", vecs);
1313
let av = a.dot(&vecs);

src/cholesky.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
2+
use ndarray::*;
3+
use num_traits::Zero;
4+
5+
use super::error::*;
6+
use super::layout::*;
7+
use super::triangular::IntoTriangular;
8+
9+
use impl2::LapackScalar;
10+
pub use impl2::UPLO;
11+
12+
pub trait Cholesky<K> {
13+
fn cholesky(self, UPLO) -> Result<K>;
14+
}
15+
16+
impl<A, S> Cholesky<ArrayBase<S, Ix2>> for ArrayBase<S, Ix2>
17+
where A: LapackScalar + Zero,
18+
S: DataMut<Elem = A>
19+
{
20+
fn cholesky(mut self, uplo: UPLO) -> Result<ArrayBase<S, Ix2>> {
21+
A::cholesky(self.square_layout()?, uplo, self.as_allocated_mut()?)?;
22+
Ok(self.into_triangular(uplo))
23+
}
24+
}
25+
26+
impl<'a, A, S> Cholesky<&'a mut ArrayBase<S, Ix2>> for &'a mut ArrayBase<S, Ix2>
27+
where A: LapackScalar + Zero,
28+
S: DataMut<Elem = A>
29+
{
30+
fn cholesky(mut self, uplo: UPLO) -> Result<&'a mut ArrayBase<S, Ix2>> {
31+
A::cholesky(self.square_layout()?, uplo, self.as_allocated_mut()?)?;
32+
Ok(self.into_triangular(uplo))
33+
}
34+
}
35+
36+
impl<'a, A, Si, So> Cholesky<ArrayBase<So, Ix2>> for &'a ArrayBase<Si, Ix2>
37+
where A: LapackScalar + Copy + Zero,
38+
Si: Data<Elem = A>,
39+
So: DataMut<Elem = A> + DataOwned
40+
{
41+
fn cholesky(self, uplo: UPLO) -> Result<ArrayBase<So, Ix2>> {
42+
let mut a = replicate(self);
43+
A::cholesky(a.square_layout()?, uplo, a.as_allocated_mut()?)?;
44+
Ok(a.into_triangular(uplo))
45+
}
46+
}

src/eigh.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
2+
use ndarray::*;
3+
4+
use super::error::*;
5+
use super::layout::*;
6+
7+
use impl2::LapackScalar;
8+
pub use impl2::UPLO;
9+
10+
pub trait Eigh<EigVal, EigVec> {
11+
fn eigh(self, UPLO) -> Result<(EigVal, EigVec)>;
12+
}
13+
14+
impl<A, S, Se> Eigh<ArrayBase<Se, Ix1>, ArrayBase<S, Ix2>> for ArrayBase<S, Ix2>
15+
where A: LapackScalar,
16+
S: DataMut<Elem = A>,
17+
Se: DataOwned<Elem = A::Real>
18+
{
19+
fn eigh(mut self, uplo: UPLO) -> Result<(ArrayBase<Se, Ix1>, ArrayBase<S, Ix2>)> {
20+
let s = A::eigh(true, self.square_layout()?, uplo, self.as_allocated_mut()?)?;
21+
Ok((ArrayBase::from_vec(s), self))
22+
}
23+
}
24+
25+
impl<'a, A, S, Se, So> Eigh<ArrayBase<Se, Ix1>, ArrayBase<So, Ix2>> for &'a ArrayBase<S, Ix2>
26+
where A: LapackScalar + Copy,
27+
S: Data<Elem = A>,
28+
Se: DataOwned<Elem = A::Real>,
29+
So: DataOwned<Elem = A> + DataMut
30+
{
31+
fn eigh(self, uplo: UPLO) -> Result<(ArrayBase<Se, Ix1>, ArrayBase<So, Ix2>)> {
32+
let mut a = replicate(self);
33+
let s = A::eigh(true, a.square_layout()?, uplo, a.as_allocated_mut()?)?;
34+
Ok((ArrayBase::from_vec(s), a))
35+
}
36+
}
37+
38+
impl<'a, A, S, Se> Eigh<ArrayBase<Se, Ix1>, &'a mut ArrayBase<S, Ix2>> for &'a mut ArrayBase<S, Ix2>
39+
where A: LapackScalar,
40+
S: DataMut<Elem = A>,
41+
Se: DataOwned<Elem = A::Real>
42+
{
43+
fn eigh(mut self, uplo: UPLO) -> Result<(ArrayBase<Se, Ix1>, &'a mut ArrayBase<S, Ix2>)> {
44+
let s = A::eigh(true, self.square_layout()?, uplo, self.as_allocated_mut()?)?;
45+
Ok((ArrayBase::from_vec(s), self))
46+
}
47+
}
48+
49+
pub trait EigValsh<EigVal> {
50+
fn eigvalsh(self, UPLO) -> Result<EigVal>;
51+
}
52+
53+
impl<A, S, Se> EigValsh<ArrayBase<Se, Ix1>> for ArrayBase<S, Ix2>
54+
where A: LapackScalar,
55+
S: DataMut<Elem = A>,
56+
Se: DataOwned<Elem = A::Real>
57+
{
58+
fn eigvalsh(mut self, uplo: UPLO) -> Result<ArrayBase<Se, Ix1>> {
59+
let s = A::eigh(false, self.square_layout()?, uplo, self.as_allocated_mut()?)?;
60+
Ok(ArrayBase::from_vec(s))
61+
}
62+
}
63+
64+
impl<'a, A, S, Se> EigValsh<ArrayBase<Se, Ix1>> for &'a ArrayBase<S, Ix2>
65+
where A: LapackScalar + Copy,
66+
S: Data<Elem = A>,
67+
Se: DataOwned<Elem = A::Real>
68+
{
69+
fn eigvalsh(self, uplo: UPLO) -> Result<ArrayBase<Se, Ix1>> {
70+
let mut a = self.to_owned();
71+
let s = A::eigh(false, a.square_layout()?, uplo, a.as_allocated_mut()?)?;
72+
Ok(ArrayBase::from_vec(s))
73+
}
74+
}
75+
76+
impl<'a, A, S, Se> EigValsh<ArrayBase<Se, Ix1>> for &'a mut ArrayBase<S, Ix2>
77+
where A: LapackScalar,
78+
S: DataMut<Elem = A>,
79+
Se: DataOwned<Elem = A::Real>
80+
{
81+
fn eigvalsh(mut self, uplo: UPLO) -> Result<ArrayBase<Se, Ix1>> {
82+
let s = A::eigh(true, self.square_layout()?, uplo, self.as_allocated_mut()?)?;
83+
Ok(ArrayBase::from_vec(s))
84+
}
85+
}

src/hermite.rs

Lines changed: 0 additions & 91 deletions
This file was deleted.

src/impl2/cholesky.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//! implement Cholesky decomposition
2+
3+
use lapack::c;
4+
5+
use types::*;
6+
use error::*;
7+
use layout::Layout;
8+
9+
use super::{into_result, UPLO};
10+
11+
pub trait Cholesky_: Sized {
12+
fn cholesky(Layout, UPLO, a: &mut [Self]) -> Result<()>;
13+
}
14+
15+
macro_rules! impl_cholesky {
16+
($scalar:ty, $potrf:path) => {
17+
impl Cholesky_ for $scalar {
18+
fn cholesky(l: Layout, uplo: UPLO, mut a: &mut [Self]) -> Result<()> {
19+
let (n, _) = l.size();
20+
let info = $potrf(l.lapacke_layout(), uplo as u8, n, &mut a, n);
21+
into_result(info, ())
22+
}
23+
}
24+
}} // end macro_rules
25+
26+
impl_cholesky!(f64, c::dpotrf);
27+
impl_cholesky!(f32, c::spotrf);
28+
impl_cholesky!(c64, c::zpotrf);
29+
impl_cholesky!(c32, c::cpotrf);

src/impl2/eigh.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
use lapack::c;
3+
use num_traits::Zero;
4+
5+
use types::*;
6+
use error::*;
7+
use layout::Layout;
8+
9+
use super::{into_result, UPLO};
10+
11+
pub trait Eigh_: AssociatedReal {
12+
fn eigh(calc_eigenvec: bool, Layout, UPLO, a: &mut [Self]) -> Result<Vec<Self::Real>>;
13+
}
14+
15+
macro_rules! impl_eigh {
16+
($scalar:ty, $ev:path) => {
17+
impl Eigh_ for $scalar {
18+
fn eigh(calc_v: bool, l: Layout, uplo: UPLO, mut a: &mut [Self]) -> Result<Vec<Self::Real>> {
19+
let (n, _) = l.size();
20+
let jobz = if calc_v { b'V' } else { b'N' };
21+
let mut w = vec![Self::Real::zero(); n as usize];
22+
let info = $ev(l.lapacke_layout(), jobz, uplo as u8, n, &mut a, n, &mut w);
23+
into_result(info, w)
24+
}
25+
}
26+
}} // impl_eigh!
27+
28+
impl_eigh!(f64, c::dsyev);
29+
impl_eigh!(f32, c::ssyev);
30+
impl_eigh!(c64, c::zheev);
31+
impl_eigh!(c32, c::cheev);

src/impl2/mod.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,20 @@ pub mod opnorm;
33
pub mod qr;
44
pub mod svd;
55
pub mod solve;
6+
pub mod cholesky;
7+
pub mod eigh;
68

79
pub use self::opnorm::*;
810
pub use self::qr::*;
911
pub use self::svd::*;
1012
pub use self::solve::*;
13+
pub use self::cholesky::*;
14+
pub use self::eigh::*;
1115

1216
use super::error::*;
1317

14-
pub trait LapackScalar: OperatorNorm_ + QR_ + SVD_ + Solve_ {}
15-
impl<A> LapackScalar for A where A: OperatorNorm_ + QR_ + SVD_ + Solve_ {}
18+
pub trait LapackScalar: OperatorNorm_ + QR_ + SVD_ + Solve_ + Cholesky_ + Eigh_ {}
19+
impl<A> LapackScalar for A where A: OperatorNorm_ + QR_ + SVD_ + Solve_ + Cholesky_ + Eigh_ {}
1620

1721
pub fn into_result<T>(info: i32, val: T) -> Result<T> {
1822
if info == 0 {
@@ -21,3 +25,10 @@ pub fn into_result<T>(info: i32, val: T) -> Result<T> {
2125
Err(LapackError::new(info).into())
2226
}
2327
}
28+
29+
#[derive(Debug, Clone, Copy)]
30+
#[repr(u8)]
31+
pub enum UPLO {
32+
Upper = b'U',
33+
Lower = b'L',
34+
}

src/impls/cholesky.rs

Lines changed: 0 additions & 25 deletions
This file was deleted.

src/impls/eigh.rs

Lines changed: 0 additions & 28 deletions
This file was deleted.

src/impls/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
11
//! Implement trait bindings of LAPACK
22
pub mod outer;
3-
pub mod eigh;
43
pub mod solve;
5-
pub mod cholesky;

0 commit comments

Comments
 (0)