From b84c7e10dfb7212c79d5d63f68df904565747273 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Crozet?= Date: Sun, 13 Aug 2017 19:52:58 +0200 Subject: [PATCH] nalgebra-lapack: add doc + fix warnings. --- nalgebra-lapack/src/cholesky.rs | 23 ++++++++++ nalgebra-lapack/src/eigen.rs | 9 +++- nalgebra-lapack/src/hessenberg.rs | 3 ++ nalgebra-lapack/src/lib.rs | 61 +++++++++++++++++++++++++- nalgebra-lapack/src/lu.rs | 7 +++ nalgebra-lapack/src/qr.rs | 6 +++ nalgebra-lapack/src/schur.rs | 11 +++-- nalgebra-lapack/src/svd.rs | 20 +++++---- nalgebra-lapack/src/symmetric_eigen.rs | 15 +++++-- 9 files changed, 137 insertions(+), 18 deletions(-) diff --git a/nalgebra-lapack/src/cholesky.rs b/nalgebra-lapack/src/cholesky.rs index 1bddbc20..065a6bb4 100644 --- a/nalgebra-lapack/src/cholesky.rs +++ b/nalgebra-lapack/src/cholesky.rs @@ -36,17 +36,37 @@ impl Cholesky Some(Cholesky { l: m }) } + /// Retrieves the lower-triangular factor of the cholesky decomposition. pub fn unpack(mut self) -> MatrixN { self.l.fill_upper_triangle(Zero::zero(), 1); self.l } + /// Retrieves the lower-triangular factor of che cholesky decomposition, without zeroing-out + /// its strict upper-triangular part. + /// + /// This is an allocation-less version of `self.l()`. The values of the strict upper-triangular + /// part are garbage and should be ignored by further computations. + pub fn unpack_dirty(self) -> MatrixN { + self.l + } + + /// Retrieves the lower-triangular factor of the cholesky decomposition. pub fn l(&self) -> MatrixN { let mut res = self.l.clone(); res.fill_upper_triangle(Zero::zero(), 1); res } + /// Retrieves the lower-triangular factor of the cholesky decomposition, without zeroing-out + /// its strict upper-triangular part. + /// + /// This is an allocation-less version of `self.l()`. The values of the strict upper-triangular + /// part are garbage and should be ignored by further computations. + pub fn l_dirty(&self) -> &MatrixN { + &self.l + } + /// Solves the symmetric-definite-positive linear system `self * x = b`, where `x` is the /// unknown to be determined. pub fn solve(&self, b: &Matrix) -> Option> @@ -110,8 +130,11 @@ impl Cholesky /// Trait implemented by floats (`f32`, `f64`) and complex floats (`Complex`, `Complex`) /// supported by the cholesky decompotition. pub trait CholeskyScalar: Scalar { + #[allow(missing_docs)] fn xpotrf(uplo: u8, n: i32, a: &mut [Self], lda: i32, info: &mut i32); + #[allow(missing_docs)] fn xpotrs(uplo: u8, n: i32, nrhs: i32, a: &[Self], lda: i32, b: &mut [Self], ldb: i32, info: &mut i32); + #[allow(missing_docs)] fn xpotri(uplo: u8, n: i32, a: &mut [Self], lda: i32, info: &mut i32); } diff --git a/nalgebra-lapack/src/eigen.rs b/nalgebra-lapack/src/eigen.rs index 51812fb5..4121fbc3 100644 --- a/nalgebra-lapack/src/eigen.rs +++ b/nalgebra-lapack/src/eigen.rs @@ -15,8 +15,11 @@ use lapack::fortran as interface; pub struct Eigen where DefaultAllocator: Allocator + Allocator { + /// The eigenvalues of the decomposed matrix. pub eigenvalues: VectorN, + /// The (right) eigenvectors of the decomposed matrix. pub eigenvectors: Option>, + /// The left eigenvectors of the decomposed matrix. pub left_eigenvectors: Option> } @@ -125,7 +128,7 @@ impl Eigen where DefaultAllocator: Allocator, D> { assert!(m.is_square(), "Unable to compute the eigenvalue decomposition of a non-square matrix."); - let (nrows, ncols) = m.data.shape(); + let nrows = m.data.shape().0; let n = nrows.value(); let lda = n as i32; @@ -181,11 +184,15 @@ impl Eigen * Lapack functions dispatch. * */ +/// Trait implemented by scalar type for which Lapack funtion exist to compute the +/// eigendecomposition. pub trait EigenScalar: Scalar { + #[allow(missing_docs)] fn xgeev(jobvl: u8, jobvr: u8, n: i32, a: &mut [Self], lda: i32, wr: &mut [Self], wi: &mut [Self], vl: &mut [Self], ldvl: i32, vr: &mut [Self], ldvr: i32, work: &mut [Self], lwork: i32, info: &mut i32); + #[allow(missing_docs)] fn xgeev_work_size(jobvl: u8, jobvr: u8, n: i32, a: &mut [Self], lda: i32, wr: &mut [Self], wi: &mut [Self], vl: &mut [Self], ldvl: i32, vr: &mut [Self], ldvr: i32, info: &mut i32) -> i32; diff --git a/nalgebra-lapack/src/hessenberg.rs b/nalgebra-lapack/src/hessenberg.rs index 68a9c433..b7576022 100644 --- a/nalgebra-lapack/src/hessenberg.rs +++ b/nalgebra-lapack/src/hessenberg.rs @@ -94,9 +94,12 @@ pub trait HessenbergScalar: Scalar { tau: &mut [Self], info: &mut i32) -> i32; } +/// Trait implemented by scalars for which Lapack implements the hessenberg decomposition. pub trait HessenbergReal: HessenbergScalar { + #[allow(missing_docs)] fn xorghr(n: i32, ilo: i32, ihi: i32, a: &mut [Self], lda: i32, tau: &[Self], work: &mut [Self], lwork: i32, info: &mut i32); + #[allow(missing_docs)] fn xorghr_work_size(n: i32, ilo: i32, ihi: i32, a: &mut [Self], lda: i32, tau: &[Self], info: &mut i32) -> i32; } diff --git a/nalgebra-lapack/src/lib.rs b/nalgebra-lapack/src/lib.rs index 5afc3399..066c1cea 100644 --- a/nalgebra-lapack/src/lib.rs +++ b/nalgebra-lapack/src/lib.rs @@ -1,10 +1,69 @@ +//! # nalgebra-lapack +//! +//! Rust library for linear algebra using nalgebra and LAPACK. +//! +//! ## Documentation +//! +//! Documentation is available [here](https://docs.rs/nalgebra-lapack/). +//! +//! ## License +//! +//! MIT +//! +//! ## Cargo features to select lapack provider +//! +//! Like the [lapack crate](https://crates.io/crates/lapack) from which this +//! behavior is inherited, nalgebra-lapack uses [cargo +//! features](http://doc.crates.io/manifest.html#the-[features]-section) to select +//! which lapack provider (or implementation) is used. Command line arguments to +//! cargo are the easiest way to do this, and the best provider depends on your +//! particular system. In some cases, the providers can be further tuned with +//! environment variables. +//! +//! Below are given examples of how to invoke `cargo build` on two different systems +//! using two different providers. The `--no-default-features --features "provider"` +//! arguments will be consistent for other `cargo` commands. +//! +//! ### Ubuntu +//! +//! As tested on Ubuntu 12.04, do this to build the lapack package against +//! the system installation of netlib without LAPACKE (note the E) or +//! CBLAS: +//! +//! sudo apt-get install gfortran libblas3gf liblapack3gf +//! export CARGO_FEATURE_SYSTEM_NETLIB=1 +//! export CARGO_FEATURE_EXCLUDE_LAPACKE=1 +//! export CARGO_FEATURE_EXCLUDE_CBLAS=1 +//! +//! export CARGO_FEATURES='--no-default-features --features netlib' +//! cargo build ${CARGO_FEATURES} +//! +//! ### Mac OS X +//! +//! On Mac OS X, do this to use Apple's Accelerate framework: +//! +//! export CARGO_FEATURES='--no-default-features --features accelerate' +//! cargo build ${CARGO_FEATURES} +//! +//! [version-img]: https://img.shields.io/crates/v/nalgebra-lapack.svg +//! [version-url]: https://crates.io/crates/nalgebra-lapack +//! [status-img]: https://travis-ci.org/strawlab/nalgebra-lapack.svg?branch=master +//! [status-url]: https://travis-ci.org/strawlab/nalgebra-lapack +//! [doc-img]: https://docs.rs/nalgebra-lapack/badge.svg +//! [doc-url]: https://docs.rs/nalgebra-lapack/ +//! +//! ## Contributors +//! This integration of LAPACK on nalgebra was +//! [initiated](https://github.com/strawlab/nalgebra-lapack) by Andrew Straw. It +//! then became officially supported and integrated to the main nalgebra +//! repository. #![deny(non_camel_case_types)] #![deny(unused_parens)] #![deny(non_upper_case_globals)] #![deny(unused_qualifications)] #![deny(unused_results)] -#![warn(missing_docs)] +#![deny(missing_docs)] #![doc(html_root_url = "http://nalgebra.org/rustdoc")] extern crate num_traits as num; diff --git a/nalgebra-lapack/src/lu.rs b/nalgebra-lapack/src/lu.rs index b7655715..f3b5bdb0 100644 --- a/nalgebra-lapack/src/lu.rs +++ b/nalgebra-lapack/src/lu.rs @@ -33,6 +33,7 @@ impl LU Allocator, C> + Allocator> { + /// Computes the LU decomposition with partial (row) pivoting of `matrix`. pub fn new(mut m: MatrixMN) -> Self { let (nrows, ncols) = m.data.shape(); let min_nrows_ncols = nrows.min(ncols); @@ -238,13 +239,19 @@ impl LU * Lapack functions dispatch. * */ +/// Trait implemented by scalars for which Lapack implements the LU decomposition. pub trait LUScalar: Scalar { + #[allow(missing_docs)] fn xgetrf(m: i32, n: i32, a: &mut [Self], lda: i32, ipiv: &mut [i32], info: &mut i32); + #[allow(missing_docs)] fn xlaswp(n: i32, a: &mut [Self], lda: i32, k1: i32, k2: i32, ipiv: &[i32], incx: i32); + #[allow(missing_docs)] fn xgetrs(trans: u8, n: i32, nrhs: i32, a: &[Self], lda: i32, ipiv: &[i32], b: &mut [Self], ldb: i32, info: &mut i32); + #[allow(missing_docs)] fn xgetri(n: i32, a: &mut [Self], lda: i32, ipiv: &[i32], work: &mut [Self], lwork: i32, info: &mut i32); + #[allow(missing_docs)] fn xgetri_work_size(n: i32, a: &mut [Self], lda: i32, ipiv: &[i32], info: &mut i32) -> i32; } diff --git a/nalgebra-lapack/src/qr.rs b/nalgebra-lapack/src/qr.rs index 5a21babf..b69452f8 100644 --- a/nalgebra-lapack/src/qr.rs +++ b/nalgebra-lapack/src/qr.rs @@ -102,6 +102,8 @@ impl, C: Dim> QR * Lapack functions dispatch. * */ +/// Trait implemented by scalar types for which Lapack funtion exist to compute the +/// QR decomposition. pub trait QRScalar: Scalar { fn xgeqrf(m: i32, n: i32, a: &mut [Self], lda: i32, tau: &mut [Self], work: &mut [Self], lwork: i32, info: &mut i32); @@ -110,10 +112,14 @@ pub trait QRScalar: Scalar { tau: &mut [Self], info: &mut i32) -> i32; } +/// Trait implemented by reals for which Lapack funtion exist to compute the +/// QR decomposition. pub trait QRReal: QRScalar { + #[allow(missing_docs)] fn xorgqr(m: i32, n: i32, k: i32, a: &mut [Self], lda: i32, tau: &[Self], work: &mut [Self], lwork: i32, info: &mut i32); + #[allow(missing_docs)] fn xorgqr_work_size(m: i32, n: i32, k: i32, a: &mut [Self], lda: i32, tau: &[Self], info: &mut i32) -> i32; } diff --git a/nalgebra-lapack/src/schur.rs b/nalgebra-lapack/src/schur.rs index 82156803..225c3241 100644 --- a/nalgebra-lapack/src/schur.rs +++ b/nalgebra-lapack/src/schur.rs @@ -23,7 +23,7 @@ pub struct RealSchur } -impl RealSchur +impl RealSchur where DefaultAllocator: Allocator + Allocator { /// Computes the eigenvalues and real Schur foorm of the matrix `m`. @@ -106,7 +106,9 @@ impl RealSchur * Lapack functions dispatch. * */ -pub trait EigenScalar: Scalar { +/// Trait implemented by scalars for which Lapack implements the Real Schur decomposition. +pub trait RealSchurScalar: Scalar { + #[allow(missing_docs)] fn xgees(jobvs: u8, sort: u8, // select: ??? @@ -122,7 +124,8 @@ pub trait EigenScalar: Scalar { lwork: i32, bwork: &mut [i32], info: &mut i32); - + + #[allow(missing_docs)] fn xgees_work_size(jobvs: u8, sort: u8, // select: ??? @@ -141,7 +144,7 @@ pub trait EigenScalar: Scalar { macro_rules! real_eigensystem_scalar_impl ( ($N: ty, $xgees: path) => ( - impl EigenScalar for $N { + impl RealSchurScalar for $N { #[inline] fn xgees(jobvs: u8, sort: u8, diff --git a/nalgebra-lapack/src/svd.rs b/nalgebra-lapack/src/svd.rs index 932cb3ad..7f13c5f3 100644 --- a/nalgebra-lapack/src/svd.rs +++ b/nalgebra-lapack/src/svd.rs @@ -15,9 +15,12 @@ pub struct SVD, C: Dim> where DefaultAllocator: Allocator + Allocator> + Allocator { + /// The left-singular vectors `U` of this SVD. pub u: MatrixN, - pub s: VectorN>, - pub vt: MatrixN + /// The right-singular vectors `V^t` of this SVD. + pub vt: MatrixN, + /// The singular values of this SVD. + pub singular_values: VectorN> } @@ -37,6 +40,7 @@ impl, R: DimMin, C: Dim> SVD Allocator + Allocator> + Allocator { + /// Computes the Singular Value Decomposition of `matrix`. pub fn new(m: MatrixMN) -> Option { N::compute(m) } @@ -87,7 +91,7 @@ macro_rules! svd_impl( ldvt as i32, &mut work, lwork, &mut iwork, &mut info); lapack_check!(info); - Some(SVD { u: u, s: s, vt: vt }) + Some(SVD { u: u, singular_values: s, vt: vt }) } } @@ -108,7 +112,7 @@ macro_rules! svd_impl( /// Useful if some components (e.g. some singular values) of this decomposition have /// been manually changed by the user. #[inline] - pub fn matrix(&self) -> MatrixMN<$t, R, C> { + pub fn recompose(self) -> MatrixMN<$t, R, C> { let nrows = self.u.data.shape().0; let ncols = self.vt.data.shape().1; let min_nrows_ncols = nrows.min(ncols); @@ -120,13 +124,13 @@ macro_rules! svd_impl( sres.copy_from(&self.vt.rows_generic(0, min_nrows_ncols)); for i in 0 .. min_nrows_ncols.value() { - let eigval = self.s[i]; + let eigval = self.singular_values[i]; let mut row = sres.row_mut(i); row *= eigval; } } - &self.u * res + self.u * res } /// Computes the pseudo-inverse of the decomposed matrix. @@ -145,7 +149,7 @@ macro_rules! svd_impl( self.u.columns_generic(0, min_nrows_ncols).transpose_to(&mut sres); for i in 0 .. min_nrows_ncols.value() { - let eigval = self.s[i]; + let eigval = self.singular_values[i]; let mut row = sres.row_mut(i); if eigval.abs() > epsilon { @@ -168,7 +172,7 @@ macro_rules! svd_impl( pub fn rank(&self, epsilon: $t) -> usize { let mut i = 0; - for e in self.s.as_slice().iter() { + for e in self.singular_values.as_slice().iter() { if e.abs() > epsilon { i += 1; } diff --git a/nalgebra-lapack/src/symmetric_eigen.rs b/nalgebra-lapack/src/symmetric_eigen.rs index 4338118f..881fe2f5 100644 --- a/nalgebra-lapack/src/symmetric_eigen.rs +++ b/nalgebra-lapack/src/symmetric_eigen.rs @@ -15,8 +15,11 @@ use lapack::fortran as interface; pub struct SymmetricEigen where DefaultAllocator: Allocator + Allocator { - pub eigenvalues: VectorN, + /// The eigenvectors of the decomposed matrix. pub eigenvectors: MatrixN, + + /// The unsorted eigenvalues of the decomposed matrix. + pub eigenvalues: VectorN, } @@ -48,7 +51,7 @@ impl SymmetricEigen let jobz = if eigenvectors { b'V' } else { b'N' }; - let (nrows, ncols) = m.data.shape(); + let nrows = m.data.shape().0; let n = nrows.value(); let lda = n as i32; @@ -71,14 +74,14 @@ impl SymmetricEigen /// Computes only the eigenvalues of the input matrix. /// /// Panics if the method does not converge. - pub fn eigenvalues(mut m: MatrixN) -> VectorN { + pub fn eigenvalues(m: MatrixN) -> VectorN { Self::do_decompose(m, false).expect("SymmetricEigen eigenvalues: convergence failure.").0 } /// Computes only the eigenvalues of the input matrix. /// /// Returns `None` if the method does not converge. - pub fn try_eigenvalues(mut m: MatrixN) -> Option> { + pub fn try_eigenvalues(m: MatrixN) -> Option> { Self::do_decompose(m, false).map(|res| res.0) } @@ -113,9 +116,13 @@ impl SymmetricEigen * Lapack functions dispatch. * */ +/// Trait implemented by scalars for which Lapack implements the eigendecomposition of symmetric +/// real matrices. pub trait SymmetricEigenScalar: Scalar { + #[allow(missing_docs)] fn xsyev(jobz: u8, uplo: u8, n: i32, a: &mut [Self], lda: i32, w: &mut [Self], work: &mut [Self], lwork: i32, info: &mut i32); + #[allow(missing_docs)] fn xsyev_work_size(jobz: u8, uplo: u8, n: i32, a: &mut [Self], lda: i32, info: &mut i32) -> i32; }