mdarray_linalg/lib.rs
1#![doc(html_logo_url = "logo.png")]
2//! Linear algebra backends for [`mdarray`](https://crates.io/crates/mdarray)
3//!
4//! This crate defines traits for linear algebra operations on `mdarray` arrays. Whole-array
5//! operations including tensor contraction, matrix multiplication, decompositions and
6//! factorizations are exposed as trait methods. Crates such as [`mdarray_linalg_blas`] and
7//! [`mdarray_linalg_faer`] provide library-specific backends, i.e., Rust types that implement these
8//! traits.
9//!
10//! This backend-based approach is more than just a unified interface to multiple libraries.
11//! Backends are Rust values, so they can carry configuration such as threading settings or
12//! library-specific context.
13//!
14//! The operation traits are deliberately generic over the scalar type. This allows each backend to
15//! choose the scalar types it supports: BLAS/LAPACK backends naturally cover the classic BLAS
16//! scalar types, while other backends may be generic over broader families of scalars.
17//!
18//! User code can be generic over both the scalar type and the backend that provides whole-array
19//! operations. This allows user code to be written in any of the following ways:
20//!
21//! - tied to a concrete combination of backend and scalar type;
22//! - generic over the backend for a particular concrete scalar type;
23//! - generic over the scalar type for a concrete backend;
24//! - generic over both the backend and the scalar type.
25//!
26//! In the most general case, trait bounds for the scalar type and the backend are expressed independently:
27//! ```text
28//! T: ... // Require certain operations for the scalar type T.
29//! B: Contract<T> // Require a backend that can contract arrays of T.
30//! ```
31//!
32//! This separation also leaves room for backend implementations optimized for particular scalar
33//! types, e.g., matrix multiplication for double-double scalars. These can outperform
34//! implementations built from generic scalar operations of that type.
35//!
36//! Each backend (except `Naive`) lives in a separate crate with specific dependencies.
37//!
38//! # Backend crates
39//!
40//! - [`mdarray_linalg_blas`]: bindings to [BLAS](https://www.netlib.org/blas/)
41//! - [`mdarray_linalg_lapack`]: bindings to [LAPACK](https://www.netlib.org/lapack/)
42//! - [`mdarray_linalg_faer`]: bindings to [faer](https://faer.veganb.tw/)
43//! - [`mdarray_linalg_nalgebra`]: bindings to [nalgebra](https://nalgebra.rs/)
44//! - [`mdarray_linalg_tblis`]: bindings to [TBLIS](https://github.com/MatthewsResearchGroup/tblis)
45//! - `Naive`: simple demo backend, integrated into this crate
46//!
47//! # Backend functionality
48//!
49//! Backends support functionality based on the capabilities of the underlying libraries.
50//!
51//! | Functionality | BLAS | LAPACK | Naive | Faer | Nalgebra | TBLIS |
52//! |---------------------------------------------------|:----:|:------:|:-----:|:----:|:--------:|:-----:|
53//! | **▶︎ Basic vector/matrix operations** |||||||
54//! | [Matrix-vector multiplications](crate::matvec#matrix-vector-operations) | ✅ | ⬜ | ✅ | ✅ | ✅ | ⬜ |
55//! | [Operations on vectors](crate::matvec#vector-operations) | ✅ | ⬜ | ✅ | ✅ | ✅ | ⬜ |
56//! | [Matrix multiplication](mod@crate::contract) | ✅ | ⬜ | ✅ | ✅ | ✅ | ✅ |
57//! | [Argmax](crate::matvec#argmax) | ✅ | ⬜ | ✅ | ⬜ | ✅ | ⬜ |
58//! | **▶︎ Decomposition and solving** |||||||
59//! | [Eigen decomposition](crate::eig) | ⬜ | ✅ | ⬜ | ✅ | ✅ | ⬜ |
60//! | [SVD decomposition](crate::svd) | ⬜ | ✅ | ⬜ | ✅ | ✅ | ⬜ |
61//! | [LU decomposition and inverse](crate::lu) | ⬜ | ✅ | ⬜ | ✅ | ✅ | ⬜ |
62//! | [Solve](crate::solve) | ⬜ | ✅ | ⬜ | ✅ | ✅ | ⬜ |
63//! | [QR decomposition](crate::qr) | ⬜ | ✅ | ✅ | ✅ | ✅ | ⬜ |
64//! | [Cholesky decomposition](crate::lu)| ⬜ | ✅ | ⬜ | ✅ |✅ | ⬜ |
65//! | [Schur decomposition](crate::eig) | ⬜ | ✅ | ⬜ | ✅ | ✅ | ⬜ |
66//! | **▶︎ Advanced** |||||||
67//! | [Tensor contraction](mod@crate::contract) | ✅ | ⬜ | ✅ | ✅ | ✅ | ✅ |
68//!
69//! ✅ = implemented
70//! 🔧 = not implemented yet / partially implemented
71//! ⬜ = not applicable / not part of the backend’s scope
72//!
73// </details>
74//!
75//! # Example
76//!
77//! The following example demonstrates basic functionality:
78//!
79//! ```rust
80//! use mdarray::array;
81//!
82//! // The prelude does not expose any names. It only provides traits as _.
83//! use mdarray_linalg::prelude::*;
84//!
85//! // Backends are provided in partner crates (e.g. mdarray_linalg_blas or mdarray_linalg_faer),
86//! // the naive backend exists mostly as a demonstration.
87//! use mdarray_linalg::Naive;
88//!
89//! // Declare two vectors
90//! let x = array![1., 2.];
91//! let y = array![2., 4.];
92//!
93//! // Declare two matrices
94//! let a = array![[1., 2.], [3., 4.]];
95//! let b = array![[5., 6.], [7., 8.]];
96//!
97//! // ----- Scalar product -----
98//! let dot_result = Naive.dot(&x, &y);
99//! println!("dot(x, y) = {}", dot_result); // x · y
100//!
101//! // ----- Matrix multiplication -----
102//! let mut c = Naive.matmul(&a, &b).eval(); // C ← A ✕ B
103//! Naive.matmul(&b, &a).add_to(&mut c); // C ← B ✕ A + C
104//! println!("A * B + B * A = {:?}", c);
105//!
106//! let tmp = Naive.matmul(&b, &c).eval();
107//! let d = Naive.matmul(&a, &tmp).eval();
108//! ```
109//!
110//! # Dependencies on non-Rust libraries
111//!
112//! Backend crates that bind non-Rust libraries do not impose a concrete library to link against.
113//! This choice is left to the user. For example, users of [`mdarray_linalg_blas`] may add
114//! a provider crate such as `openblas-src`, users of [`mdarray_linalg_lapack`] may add
115//! `lapack-src`, and users of [`mdarray_linalg_tblis`] may add `tblis-src` or arrange
116//! to link TBLIS differently. The provider crate must be referenced from Rust code,
117//! e.g. by adding `extern crate openblas_src as _;`, so that appropriate link
118//! directives are used.
119//!
120//! See the documentation of the individual backend crates for further information.
121//!
122// Keep the doc-comment blank line above: these reference definitions must start
123// a separate Markdown block from the preceding paragraph.
124#![cfg_attr(docsrs, doc = concat!(
125 "[`mdarray_linalg_blas`]: https://docs.rs/mdarray-linalg-blas/", env!("CARGO_PKG_VERSION"), "/mdarray_linalg_blas/\n",
126 "[`mdarray_linalg_lapack`]: https://docs.rs/mdarray-linalg-lapack/", env!("CARGO_PKG_VERSION"), "/mdarray_linalg_lapack/\n",
127 "[`mdarray_linalg_faer`]: https://docs.rs/mdarray-linalg-faer/", env!("CARGO_PKG_VERSION"), "/mdarray_linalg_faer/\n",
128 "[`mdarray_linalg_nalgebra`]: https://docs.rs/mdarray-linalg-nalgebra/", env!("CARGO_PKG_VERSION"), "/mdarray_linalg_nalgebra/\n",
129 "[`mdarray_linalg_tblis`]: https://docs.rs/mdarray-linalg-tblis/", env!("CARGO_PKG_VERSION"), "/mdarray_linalg_tblis/",
130))]
131#![cfg_attr(not(docsrs), doc = "\
132[`mdarray_linalg_blas`]: ../mdarray_linalg_blas/index.html
133[`mdarray_linalg_lapack`]: ../mdarray_linalg_lapack/index.html
134[`mdarray_linalg_faer`]: ../mdarray_linalg_faer/index.html
135[`mdarray_linalg_nalgebra`]: ../mdarray_linalg_nalgebra/index.html
136[`mdarray_linalg_tblis`]: ../mdarray_linalg_tblis/index.html
137")]
138
139pub mod prelude;
140
141pub mod eig;
142pub mod lu;
143pub mod contract;
144pub mod matvec;
145pub mod qr;
146pub mod solve;
147pub mod svd;
148
149pub mod utils;
150
151pub use contract::Contract;
152pub use eig::Eig;
153pub use lu::LU;
154pub use matvec::{Argmax, MatVec, Outer, VecOps};
155pub use qr::QR;
156pub use solve::Solve;
157pub use svd::SVD;
158
159mod naive;
160pub use naive::Naive;
161
162#[doc(hidden)]
163pub mod testing;