Skip to content

Commit 8e496e1

Browse files
committed
Merge remote-tracking branch 'origin/master'
2 parents cd47c6a + 57fc75c commit 8e496e1

File tree

2 files changed

+163
-13
lines changed

2 files changed

+163
-13
lines changed

src/cholesky.rs

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,36 @@
1-
//! Cholesky decomposition
1+
//! Cholesky decomposition of Hermitian (or real symmetric) positive definite matrices
22
//!
3-
//! https://en.wikipedia.org/wiki/Cholesky_decomposition
3+
//! See the [Wikipedia page about Cholesky
4+
//! decomposition](https://en.wikipedia.org/wiki/Cholesky_decomposition) for
5+
//! more information.
6+
//!
7+
//! # Example
8+
//!
9+
//! Calculate `L` in the Cholesky decomposition `A = L * L^H`, where `A` is a
10+
//! Hermitian (or real symmetric) positive definite matrix:
11+
//!
12+
//! ```
13+
//! #[macro_use]
14+
//! extern crate ndarray;
15+
//! extern crate ndarray_linalg;
16+
//!
17+
//! use ndarray::prelude::*;
18+
//! use ndarray_linalg::{CholeskyInto, UPLO};
19+
//! # fn main() {
20+
//!
21+
//! let a: Array2<f64> = array![
22+
//! [ 4., 12., -16.],
23+
//! [ 12., 37., -43.],
24+
//! [-16., -43., 98.]
25+
//! ];
26+
//! let lower = a.cholesky_into(UPLO::Lower).unwrap();
27+
//! assert!(lower.all_close(&array![
28+
//! [ 2., 0., 0.],
29+
//! [ 6., 1., 0.],
30+
//! [-8., 5., 3.]
31+
//! ], 1e-9));
32+
//! # }
33+
//! ```
434
535
use ndarray::*;
636

@@ -12,19 +42,44 @@ use super::types::*;
1242

1343
pub use lapack_traits::UPLO;
1444

15-
/// Cholesky decomposition of matrix reference
45+
/// Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix reference
1646
pub trait Cholesky {
1747
type Output;
48+
/// Computes the Cholesky decomposition of the Hermitian (or real
49+
/// symmetric) positive definite matrix.
50+
///
51+
/// If the argument is `UPLO::Upper`, then computes the decomposition `A =
52+
/// U^H * U` using the upper triangular portion of `A` and returns `U`.
53+
/// Otherwise, if the argument is `UPLO::Lower`, computes the decomposition
54+
/// `A = L * L^H` using the lower triangular portion of `A` and returns
55+
/// `L`.
1856
fn cholesky(&self, UPLO) -> Result<Self::Output>;
1957
}
2058

21-
/// Cholesky decomposition
59+
/// Cholesky decomposition of Hermitian (or real symmetric) positive definite matrix
2260
pub trait CholeskyInto: Sized {
61+
/// Computes the Cholesky decomposition of the Hermitian (or real
62+
/// symmetric) positive definite matrix.
63+
///
64+
/// If the argument is `UPLO::Upper`, then computes the decomposition `A =
65+
/// U^H * U` using the upper triangular portion of `A` and returns `U`.
66+
/// Otherwise, if the argument is `UPLO::Lower`, computes the decomposition
67+
/// `A = L * L^H` using the lower triangular portion of `A` and returns
68+
/// `L`.
2369
fn cholesky_into(self, UPLO) -> Result<Self>;
2470
}
2571

26-
/// Cholesky decomposition of mutable reference of matrix
72+
/// Cholesky decomposition of Hermitian (or real symmetric) positive definite mutable reference of matrix
2773
pub trait CholeskyMut {
74+
/// Computes the Cholesky decomposition of the Hermitian (or real
75+
/// symmetric) positive definite matrix, storing the result in `self` and
76+
/// returning it.
77+
///
78+
/// If the argument is `UPLO::Upper`, then computes the decomposition `A =
79+
/// U^H * U` using the upper triangular portion of `A` and returns `U`.
80+
/// Otherwise, if the argument is `UPLO::Lower`, computes the decomposition
81+
/// `A = L * L^H` using the lower triangular portion of `A` and returns
82+
/// `L`.
2883
fn cholesky_mut(&mut self, UPLO) -> Result<&mut Self>;
2984
}
3085

src/solveh.rs

Lines changed: 103 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,53 @@
1-
//! Solve Hermite/Symmetric linear problems
1+
//! Solve Hermitian (or real symmetric) linear problems and invert Hermitian
2+
//! (or real symmetric) matrices
3+
//!
4+
//! **Note that only the upper triangular portion of the matrix is used.**
5+
//!
6+
//! # Examples
7+
//!
8+
//! Solve `A * x = b`, where `A` is a Hermitian (or real symmetric) matrix:
9+
//!
10+
//! ```
11+
//! #[macro_use]
12+
//! extern crate ndarray;
13+
//! extern crate ndarray_linalg;
14+
//!
15+
//! use ndarray::prelude::*;
16+
//! use ndarray_linalg::SolveH;
17+
//! # fn main() {
18+
//!
19+
//! let a: Array2<f64> = array![
20+
//! [3., 2., -1.],
21+
//! [2., -2., 4.],
22+
//! [-1., 4., 5.]
23+
//! ];
24+
//! let b: Array1<f64> = array![11., -12., 1.];
25+
//! let x = a.solveh_into(b).unwrap();
26+
//! assert!(x.all_close(&array![1., 3., -2.], 1e-9));
27+
//!
28+
//! # }
29+
//! ```
30+
//!
31+
//! If you are solving multiple systems of linear equations with the same
32+
//! Hermitian or real symmetric coefficient matrix `A`, it's faster to compute
33+
//! the factorization once at the beginning than solving directly using `A`:
34+
//!
35+
//! ```
36+
//! # extern crate ndarray;
37+
//! # extern crate ndarray_linalg;
38+
//! use ndarray::prelude::*;
39+
//! use ndarray_linalg::*;
40+
//! # fn main() {
41+
//!
42+
//! let a: Array2<f64> = random((3, 3));
43+
//! let f = a.factorizeh_into().unwrap(); // Factorize A (A is consumed)
44+
//! for _ in 0..10 {
45+
//! let b: Array1<f64> = random(3);
46+
//! let x = f.solveh_into(b).unwrap(); // Solve A * x = b using the factorization
47+
//! }
48+
//!
49+
//! # }
50+
//! ```
251
352
use ndarray::*;
453

@@ -9,19 +58,37 @@ use super::types::*;
958

1059
pub use lapack_traits::{Pivot, UPLO};
1160

61+
/// An interface for solving systems of Hermitian (or real symmetric) linear equations.
62+
///
63+
/// If you plan to solve many equations with the same Hermitian (or real
64+
/// symmetric) coefficient matrix `A` but different `b` vectors, it's faster to
65+
/// factor the `A` matrix once using the `FactorizeH` trait, and then solve
66+
/// using the `FactorizedH` struct.
1267
pub trait SolveH<A: Scalar> {
13-
fn solveh<S: Data<Elem = A>>(&self, a: &ArrayBase<S, Ix1>) -> Result<Array1<A>> {
14-
let mut a = replicate(a);
15-
self.solveh_mut(&mut a)?;
16-
Ok(a)
68+
/// Solves a system of linear equations `A * x = b` with Hermitian (or real
69+
/// symmetric) matrix `A`, where `A` is `self`, `b` is the argument, and
70+
/// `x` is the successful result.
71+
fn solveh<S: Data<Elem = A>>(&self, b: &ArrayBase<S, Ix1>) -> Result<Array1<A>> {
72+
let mut b = replicate(b);
73+
self.solveh_mut(&mut b)?;
74+
Ok(b)
1775
}
18-
fn solveh_into<S: DataMut<Elem = A>>(&self, mut a: ArrayBase<S, Ix1>) -> Result<ArrayBase<S, Ix1>> {
19-
self.solveh_mut(&mut a)?;
20-
Ok(a)
76+
/// Solves a system of linear equations `A * x = b` with Hermitian (or real
77+
/// symmetric) matrix `A`, where `A` is `self`, `b` is the argument, and
78+
/// `x` is the successful result.
79+
fn solveh_into<S: DataMut<Elem = A>>(&self, mut b: ArrayBase<S, Ix1>) -> Result<ArrayBase<S, Ix1>> {
80+
self.solveh_mut(&mut b)?;
81+
Ok(b)
2182
}
83+
/// Solves a system of linear equations `A * x = b` with Hermitian (or real
84+
/// symmetric) matrix `A`, where `A` is `self`, `b` is the argument, and
85+
/// `x` is the successful result. The value of `x` is also assigned to the
86+
/// argument.
2287
fn solveh_mut<'a, S: DataMut<Elem = A>>(&self, &'a mut ArrayBase<S, Ix1>) -> Result<&'a mut ArrayBase<S, Ix1>>;
2388
}
2489

90+
/// Represents the Bunch–Kaufman factorization of a Hermitian (or real
91+
/// symmetric) matrix as `A = P * U * D * U^H * P^T`.
2592
pub struct FactorizedH<S: Data> {
2693
pub a: ArrayBase<S, Ix2>,
2794
pub ipiv: Pivot,
@@ -69,6 +136,12 @@ where
69136
A: Scalar,
70137
S: DataMut<Elem = A>,
71138
{
139+
/// Computes the inverse of the factorized matrix.
140+
///
141+
/// **Warning: The inverse is stored only in the upper triangular portion
142+
/// of the result matrix!** If you want the lower triangular portion to be
143+
/// correct, you must fill it in according to the results in the upper
144+
/// triangular portion.
72145
pub fn into_inverseh(mut self) -> Result<ArrayBase<S, Ix2>> {
73146
unsafe {
74147
A::invh(
@@ -82,11 +155,19 @@ where
82155
}
83156
}
84157

158+
/// An interface for computing the Bunch–Kaufman factorization of Hermitian (or
159+
/// real symmetric) matrix refs.
85160
pub trait FactorizeH<S: Data> {
161+
/// Computes the Bunch–Kaufman factorization of a Hermitian (or real
162+
/// symmetric) matrix.
86163
fn factorizeh(&self) -> Result<FactorizedH<S>>;
87164
}
88165

166+
/// An interface for computing the Bunch–Kaufman factorization of Hermitian (or
167+
/// real symmetric) matrices.
89168
pub trait FactorizeHInto<S: Data> {
169+
/// Computes the Bunch–Kaufman factorization of a Hermitian (or real
170+
/// symmetric) matrix.
90171
fn factorizeh_into(self) -> Result<FactorizedH<S>>;
91172
}
92173

@@ -116,13 +197,27 @@ where
116197
}
117198
}
118199

200+
/// An interface for inverting Hermitian (or real symmetric) matrix refs.
119201
pub trait InverseH {
120202
type Output;
203+
/// Computes the inverse of the Hermitian (or real symmetric) matrix.
204+
///
205+
/// **Warning: The inverse is stored only in the upper triangular portion
206+
/// of the result matrix!** If you want the lower triangular portion to be
207+
/// correct, you must fill it in according to the results in the upper
208+
/// triangular portion.
121209
fn invh(&self) -> Result<Self::Output>;
122210
}
123211

212+
/// An interface for inverting Hermitian (or real symmetric) matrices.
124213
pub trait InverseHInto {
125214
type Output;
215+
/// Computes the inverse of the Hermitian (or real symmetric) matrix.
216+
///
217+
/// **Warning: The inverse is stored only in the upper triangular portion
218+
/// of the result matrix!** If you want the lower triangular portion to be
219+
/// correct, you must fill it in according to the results in the upper
220+
/// triangular portion.
126221
fn invh_into(self) -> Result<Self::Output>;
127222
}
128223

0 commit comments

Comments
 (0)