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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
//! Linear algebra backends for [`mdarray`](https://crates.io/crates/mdarray)
//!
//! This crate defines traits for linear algebra operations on `mdarray` arrays. Whole-array
//! operations including tensor contraction, matrix multiplication, decompositions and
//! factorizations are exposed as trait methods. Crates such as [`mdarray_linalg_blas`] and
//! [`mdarray_linalg_faer`] provide library-specific backends, i.e., Rust types that implement these
//! traits.
//!
//! This backend-based approach is more than just a unified interface to multiple libraries.
//! Backends are Rust values, so they can carry configuration such as threading settings or
//! library-specific context.
//!
//! The operation traits are deliberately generic over the scalar type. This allows each backend to
//! choose the scalar types it supports: BLAS/LAPACK backends naturally cover the classic BLAS
//! scalar types, while other backends may be generic over broader families of scalars.
//!
//! User code can be generic over both the scalar type and the backend that provides whole-array
//! operations. This allows user code to be written in any of the following ways:
//!
//! - tied to a concrete combination of backend and scalar type;
//! - generic over the backend for a particular concrete scalar type;
//! - generic over the scalar type for a concrete backend;
//! - generic over both the backend and the scalar type.
//!
//! In the most general case, trait bounds for the scalar type and the backend are expressed independently:
//! ```text
//! T: ... // Require certain operations for the scalar type T.
//! B: Contract<T> // Require a backend that can contract arrays of T.
//! ```
//!
//! This separation also leaves room for backend implementations optimized for particular scalar
//! types, e.g., matrix multiplication for double-double scalars. These can outperform
//! implementations built from generic scalar operations of that type.
//!
//! Each backend (except `Naive`) lives in a separate crate with specific dependencies.
//!
//! # Backend crates
//!
//! - [`mdarray_linalg_blas`]: bindings to [BLAS](https://www.netlib.org/blas/)
//! - [`mdarray_linalg_lapack`]: bindings to [LAPACK](https://www.netlib.org/lapack/)
//! - [`mdarray_linalg_faer`]: bindings to [faer](https://faer.veganb.tw/)
//! - [`mdarray_linalg_nalgebra`]: bindings to [nalgebra](https://nalgebra.rs/)
//! - [`mdarray_linalg_tblis`]: bindings to [TBLIS](https://github.com/MatthewsResearchGroup/tblis)
//! - `Naive`: simple demo backend, integrated into this crate
//!
//! # Backend functionality
//!
//! Backends support functionality based on the capabilities of the underlying libraries.
//!
//! | Functionality | BLAS | LAPACK | Naive | Faer | Nalgebra | TBLIS |
//! |---------------------------------------------------|:----:|:------:|:-----:|:----:|:--------:|:-----:|
//! | **▶︎ Basic vector/matrix operations** |||||||
//! | [Matrix-vector multiplications](crate::matvec#matrix-vector-operations) | ✅ | ⬜ | ✅ | ✅ | ✅ | ⬜ |
//! | [Operations on vectors](crate::matvec#vector-operations) | ✅ | ⬜ | ✅ | ✅ | ✅ | ⬜ |
//! | [Matrix multiplication](mod@crate::contract) | ✅ | ⬜ | ✅ | ✅ | ✅ | ✅ |
//! | [Argmax](crate::matvec#argmax) | ✅ | ⬜ | ✅ | ⬜ | ✅ | ⬜ |
//! | **▶︎ Decomposition and solving** |||||||
//! | [Eigen decomposition](crate::eig) | ⬜ | ✅ | ⬜ | ✅ | ✅ | ⬜ |
//! | [SVD decomposition](crate::svd) | ⬜ | ✅ | ⬜ | ✅ | ✅ | ⬜ |
//! | [LU decomposition and inverse](crate::lu) | ⬜ | ✅ | ⬜ | ✅ | ✅ | ⬜ |
//! | [Solve](crate::solve) | ⬜ | ✅ | ⬜ | ✅ | ✅ | ⬜ |
//! | [QR decomposition](crate::qr) | ⬜ | ✅ | ✅ | ✅ | ✅ | ⬜ |
//! | [Cholesky decomposition](crate::lu)| ⬜ | ✅ | ⬜ | ✅ |✅ | ⬜ |
//! | [Schur decomposition](crate::eig) | ⬜ | ✅ | ⬜ | ✅ | ✅ | ⬜ |
//! | **▶︎ Advanced** |||||||
//! | [Tensor contraction](mod@crate::contract) | ✅ | ⬜ | ✅ | ✅ | ✅ | ✅ |
//!
//! ✅ = implemented
//! 🔧 = not implemented yet / partially implemented
//! ⬜ = not applicable / not part of the backend’s scope
//!
// </details>
//!
//! # Example
//!
//! The following example demonstrates basic functionality:
//!
//! ```rust
//! use mdarray::array;
//!
//! // The prelude does not expose any names. It only provides traits as _.
//! use mdarray_linalg::prelude::*;
//!
//! // Backends are provided in partner crates (e.g. mdarray_linalg_blas or mdarray_linalg_faer),
//! // the naive backend exists mostly as a demonstration.
//! use mdarray_linalg::Naive;
//!
//! // Declare two vectors
//! let x = array![1., 2.];
//! let y = array![2., 4.];
//!
//! // Declare two matrices
//! let a = array![[1., 2.], [3., 4.]];
//! let b = array![[5., 6.], [7., 8.]];
//!
//! // ----- Scalar product -----
//! let dot_result = Naive.dot(&x, &y);
//! println!("dot(x, y) = {}", dot_result); // x · y
//!
//! // ----- Matrix multiplication -----
//! let mut c = Naive.matmul(&a, &b).eval(); // C ← A ✕ B
//! Naive.matmul(&b, &a).add_to(&mut c); // C ← B ✕ A + C
//! println!("A * B + B * A = {:?}", c);
//!
//! let tmp = Naive.matmul(&b, &c).eval();
//! let d = Naive.matmul(&a, &tmp).eval();
//! ```
//!
//! # Dependencies on non-Rust libraries
//!
//! Backend crates that bind non-Rust libraries do not impose a concrete library to link against.
//! This choice is left to the user. For example, users of [`mdarray_linalg_blas`] may add
//! a provider crate such as `openblas-src`, users of [`mdarray_linalg_lapack`] may add
//! `lapack-src`, and users of [`mdarray_linalg_tblis`] may add `tblis-src` or arrange
//! to link TBLIS differently. The provider crate must be referenced from Rust code,
//! e.g. by adding `extern crate openblas_src as _;`, so that appropriate link
//! directives are used.
//!
//! See the documentation of the individual backend crates for further information.
//!
// Keep the doc-comment blank line above: these reference definitions must start
// a separate Markdown block from the preceding paragraph.
pub use Contract;
pub use Eig;
pub use LU;
pub use ;
pub use QR;
pub use Solve;
pub use SVD;
pub use Naive;