nalgebra_lapack/lib.rs
1//! # nalgebra-lapack
2//!
3//! Rust library for linear algebra using nalgebra and LAPACK.
4//!
5//! ## Selecting a LAPACK Backend
6//!
7//! This crate uses [cargo features](https://doc.crates.io/manifest.html#the-[features]-section)
8//! to select which lapack provider (or implementation) is used.
9//!
10//! ### Default LAPACK Backend and Performance
11//!
12//! By default, the [`lapack-src`](https://crates.io/crates/lapack-src) crate
13//! is used as a LAPACK source, which bundles netlib and works out of the box,
14//! given an existing FORTRAN compiler on your system. That makes this choice
15//! practical, but it's typically not the best performing backend.
16//!
17//! ### LAPACK Backends
18//!
19//! LAPACK backends other than `lapack-netlib` typically assume the libraries or
20//! frameworks are present on your system. See the respective vendors how to
21//! install them. Backends are selected using one of the `lapack-*` feature flags:
22//!
23//! * `lapack-netlib`: use the bundled [Netlib](http://www.netlib.org/) reference
24//! implementation. This feature is enabled by default.
25//! * `lapack-openblas`: Use LAPACK provided via [OpenBLAS](http://www.openmathlib.org/OpenBLAS/).
26//! * `lapack-accelerate`: Use Apple's [Accelerate](https://developer.apple.com/documentation/accelerate)
27//! framework.
28//! * `lapack-mkl`: alias for `lapack-mkl-static-seq`. A useful default for [Intel MKL](https://www.intel.com/content/www/us/en/developer/tools/oneapi/onemkl.html).
29//! * `lapack-mkl-static-seq`: statically link the _sequential_ version of MKL.
30//! * `lapack-mkl-static-par`: statically link the _parallel_ version of MKL.
31//! * `lapack-mkl-dynamic-seq`: dynamically link the sequential version of MKL.
32//! * `lapack-mkl-dynamic-par`: dynamically link the parallel version of MKL.
33//! * `lapack-custom`: Use a custom LAPACK backend whose functions must be
34//! available at link time. It is your responsibility to make sure those are
35//! ABI compatible with the function signatures in the [lapack](https://crates.io/crates/lapack)
36//! crate.
37//!
38//! Note that **exactly one** of these features must be selected
39//! and that `lapack-netlib` is selected by default, which means **you have
40//! to disable default features** when explicitly specifying a LAPACK backend.
41//!
42//! ```toml
43//! nalgebra-lapack = { version = "*", default-features = false, features = ["lapack-*"] }
44//! ```
45//!
46//! [version-img]: https://img.shields.io/crates/v/nalgebra-lapack.svg
47//! [version-url]: https://crates.io/crates/nalgebra-lapack
48//! [doc-img]: https://docs.rs/nalgebra-lapack/badge.svg
49//! [doc-url]: https://docs.rs/nalgebra-lapack/
50//!
51//! ## Performance
52//!
53//! As always, there's only one way to find out if nalgebra-lapack brings
54//! a performance benefit to your project, which is _measuring_. The same
55//! goes for deciding which LAPACK backend to use, if you have multiple available
56//! options.
57//!
58//! ## License
59//!
60//! MIT
61//!
62//!
63//! ## Contributors
64//! This integration of LAPACK with nalgebra was
65//! [initiated](https://github.com/strawlab/nalgebra-lapack) by Andrew Straw. It
66//! then became officially supported and integrated into the main nalgebra
67//! repository.
68
69#![deny(non_camel_case_types)]
70#![deny(unused_parens)]
71#![deny(non_upper_case_globals)]
72#![deny(unused_qualifications)]
73#![deny(unused_results)]
74#![deny(missing_docs)]
75#![doc(
76 html_favicon_url = "https://nalgebra.rs/img/favicon.ico",
77 html_root_url = "https://nalgebra.rs/rustdoc"
78)]
79
80// A utility macro that makes sure that exactly one of the LAPACK backend
81// features is selected. It provides helpful error messages otherwise.
82macro_rules! enforce_exactly_one_feature_selected {
83 ($($feat:literal),+ $(,)?) => {
84 const _ENABLED_FEATURE_COUNT : usize = $(if cfg!(feature = $feat) {1} else {0} +)* 0;
85 const _ASSERT_EXACTLY_ONE : () = if _ENABLED_FEATURE_COUNT > 1 {
86 panic!("Multiple `lapack-*` features selected! Make sure to set `default-features = false` when including nalgebra-lapack with explicit `lapack-*` features.");
87 } else if _ENABLED_FEATURE_COUNT == 0 {
88 panic!("Select at least one `lapack-*` feature! To use a custom backend at link-time, specify `lapack-custom` without default features.");
89 } else {};
90 };
91}
92
93// If you hit a compile error here, make sure to specify exactly one of the
94// available `lapack-*` features in this crate.
95//
96// # Troubleshooting
97//
98// ## Multiple Features Selected!
99//
100// By default, the `lapack-netlib`
101// backend is specified, so to select another backend, you have to disable
102// the default features of this crate when including this crate.
103//
104// ## Select At Least One Feature!
105//
106// If you want to use a custom backend at link time, turn off default features
107// and use `lapack-custom`.
108enforce_exactly_one_feature_selected!(
109 "lapack-openblas",
110 "lapack-netlib",
111 "lapack-accelerate",
112 "lapack-mkl-static-seq",
113 "lapack-mkl-static-par",
114 "lapack-mkl-dynamic-seq",
115 "lapack-mkl-dynamic-par",
116 "lapack-custom"
117);
118
119extern crate lapack;
120#[cfg(not(feature = "lapack-custom"))]
121extern crate lapack_src;
122
123extern crate nalgebra as na;
124extern crate num_traits as num;
125
126mod lapack_check;
127
128mod cholesky;
129/// Column-pivoted QR decomposition of a rectangular (or square) matrix.
130pub mod colpiv_qr;
131mod eigen;
132mod generalized_eigenvalues;
133mod hessenberg;
134mod lu;
135/// QR decomposition of a rectangular (or square) matrix.
136pub mod qr;
137mod qz;
138mod schur;
139mod svd;
140mod symmetric_eigen;
141
142/// Internal utility module that contains functionality that is useful for
143/// both column-pivoted and non-pivoted QR decomposition.
144mod qr_util;
145
146use num_complex::Complex;
147
148/// Utility module that defines some common terms that LAPACK uses.
149mod lapack_terminology;
150
151/// Utility module for LAPACK error codes and error checking.
152mod lapack_error;
153
154pub use lapack_error::LapackErrorCode;
155pub use lapack_terminology::DiagonalKind;
156pub use lapack_terminology::Side;
157pub use lapack_terminology::Transposition;
158pub use lapack_terminology::TriangularStructure;
159
160pub use self::cholesky::{Cholesky, CholeskyScalar};
161pub use self::colpiv_qr::ColPivQR;
162pub use self::eigen::Eigen;
163pub use self::generalized_eigenvalues::GeneralizedEigen;
164pub use self::hessenberg::Hessenberg;
165pub use self::lu::{LU, LUScalar};
166pub use self::qr::QR;
167pub use self::qr::abstraction::QrDecomposition;
168pub use self::qz::QZ;
169pub use self::schur::Schur;
170pub use self::svd::SVD;
171pub use self::symmetric_eigen::SymmetricEigen;
172
173mod sealed;
174
175trait ComplexHelper {
176 type RealPart;
177
178 fn real_part(self) -> Self::RealPart;
179}
180
181impl ComplexHelper for f32 {
182 type RealPart = f32;
183
184 #[inline]
185 fn real_part(self) -> Self::RealPart {
186 self
187 }
188}
189
190impl ComplexHelper for f64 {
191 type RealPart = f64;
192
193 #[inline]
194 fn real_part(self) -> Self::RealPart {
195 self
196 }
197}
198
199impl ComplexHelper for Complex<f32> {
200 type RealPart = f32;
201
202 #[inline]
203 fn real_part(self) -> Self::RealPart {
204 self.re
205 }
206}
207
208impl ComplexHelper for Complex<f64> {
209 type RealPart = f64;
210
211 #[inline]
212 fn real_part(self) -> Self::RealPart {
213 self.re
214 }
215}