1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use impl_prelude::*;
use lapack::c::{spotrf, cpotrf, dpotrf, zpotrf};
use util::external::make_triangular_into;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum CholeskyError {
BadLayout,
NotSquare,
NotPositiveDefinite,
IllegalParameter(i32),
}
pub trait Cholesky: LinxalImplScalar {
fn compute_into<D>(a: ArrayBase<D, Ix2>, uplo: Symmetric)
-> Result<ArrayBase<D, Ix2>, CholeskyError>
where D: DataOwned<Elem=Self> + DataMut<Elem=Self>;
fn compute<D1: Data>(a: &ArrayBase<D1, Ix2>, uplo: Symmetric)
-> Result<Array<Self, Ix2>, CholeskyError>
where D1: Data<Elem = Self>
{
Self::compute_into(a.to_owned(), uplo)
}
}
macro_rules! impl_cholesky {
($chol_type:ty, $chol_func:ident) => (
impl Cholesky for $chol_type {
fn compute_into<D>(mut a: ArrayBase<D, Ix2>, uplo: Symmetric)
-> Result<ArrayBase<D, Ix2>, CholeskyError>
where D: DataOwned<Elem=Self> + DataMut<Elem=Self> {
let dim = a.dim();
if dim.0 != dim.1 {
return Err(CholeskyError::NotSquare);
}
let info = {
let (mut slice, layout, lda) = match slice_and_layout_mut(&mut a) {
None => return Err(CholeskyError::BadLayout),
Some(x) => x,
};
$chol_func(layout,
uplo as u8,
dim.0 as i32,
&mut slice,
lda as i32)
};
if info == 0 {
Ok(make_triangular_into(a, uplo))
} else if info < 0 {
Err(CholeskyError::IllegalParameter(-info))
} else {
Err(CholeskyError::NotPositiveDefinite)
}
}
}
)
}
impl_cholesky!(f32, spotrf);
impl_cholesky!(f64, dpotrf);
impl_cholesky!(c32, cpotrf);
impl_cholesky!(c64, zpotrf);