linalg_traits/
lib.rs

1//! [![github]](https://github.com/tamaskis/linalg_traits) [![crates-io]](https://crates.io/crates/linalg-traits) [![docs-rs]](https://docs.rs/linalg-traits)
2//!
3//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
4//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
5//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
6//!
7//! Traits for generic linear algebra.
8//!
9//! # Purpose
10//!
11//! The purpose of this crate is to provide traits defining common interfaces for linear algebra
12//! types defined in various popular numerical computing crates in the Rust ecosystem. This is to
13//! facilitate the development of crates requiring some linear algebra features (e.g. ODE solvers,
14//! state estimation, etc.) without forcing users to use a specific numerical computing crate.
15//!
16//! _See [Additional notes on use cases](#additional-notes-on-use-cases)._
17//!
18//! #### Constraints
19//!
20//! 1. **Compatibility with [`Vec<f64>`], as well as types from [`nalgebra`], [`ndarray`], and [`faer`].**
21//!
22//!    As a result, this crate does not require any operator overloads to be implemented for linear
23//!    alegebra types. Different numerical computing crates may have different implementations for
24//!    operator overloads (e.g. [`ndarray`] overloads `*` for elementwise multiplication, while
25//!    [`nalgebra`] overloads `*` for matrix multiplication). This means that anyone writing
26//!    generic linear algebra code using `linalg-traits` should use the arithmetic methods defined
27//!    on the [`Vector`] and [`Matrix`] traits. <br><br>
28//!
29//! 1. **Compatibility with both statically-sized and dynamically-sized types.**
30//!
31//     Most linear algebra types implement the [`Clone`] trait. Statically-sized linear algebra
32//!    types (e.g. `nalgebra::SVector`) may also implement the [`Copy`] trait, which is often
33//!    preferable to use for those types. However, it can be unsafe to copy dynamically-sized
34//!    types, so to keep [`Vector`] and [`Matrix`] compatible with both statically and
35//!    dynamically-sized linear algebra types, they only require that [`Clone`] be implemented.
36//!
37//! # Linear Algebra Traits
38//!
39//! This crate provides the following traits along with their implementations for the following
40//! types:
41//!
42//! | Trait | Implementations on Foreign Types | Implementations on Local Types |
43//! | ----- | -------------------------------- | ------------------------------ |
44//! | [`Scalar`] | [`f64`] and all other types that satisfy its trait bounds. | N/A |
45//! | [`Vector`] | [`Vec<S>`] <BR> [`nalgebra::DVector<S>`] <BR> [`nalgebra::SVector<S, N>`] <BR> [`ndarray::Array1<T>`] <BR> [`faer::Mat<U>`] <BR><BR> Note:<BR>   • `S: Scalar` <BR>   • `T: Scalar + ndarray::ScalarOperand + ndarray::LinalgScalar` <BR>   • `U: Scalar + faer_traits::RealField` <BR> • `N: usize` | N/A |
46//! | [`Matrix`] | [`nalgebra::DMatrix<S>`] <BR> [`nalgebra::SMatrix<S, M, N>`] <BR> [`ndarray::Array2<T>`] <BR> [`faer::Mat<U>`] <BR><BR> Note:<BR>   • `S: Scalar` <BR>   • `T: Scalar + ndarray::ScalarOperand + ndarray::LinalgScalar` <BR>   • `U: Scalar + faer_traits::RealField` <BR>   • `M: usize` <BR>   • `N: usize` | [`Mat<S>`] <BR><BR> Note:<BR>   • `S: Scalar` |
47//!
48//! See the [Using with `nalgebra`, `ndarray`, and `faer`](#using-with-nalgebra-ndarray-and-faer)
49//! section further down on this page for information on using the `linalg-traits` crate with types
50//! defined in [`nalgebra`] and/or [`ndarray`].
51//!
52//! # Example
53//!
54//! Let's define a function that takes in a vector and returns a new vector with all the elements
55//! repeated twice. Using the [`Scalar`] and [`Vector`] traits, we can write it in a way that makes
56//! it independent of what types we use to represent scalars and vectors.
57//!
58//! ```
59//! use linalg_traits::{Scalar, Vector};
60//! use ndarray::{array, Array1};
61//! use numtest::*;
62//!
63//! // Define the function for repeating the elements.
64//! fn repeat_elements<S: Scalar, V: Vector<S>>(v: &V) -> V {
65//!     // Create a new vector of the same type but with twice the length.
66//!     let mut v_repeated = V::new_with_length(v.len() * 2);
67//!
68//!     // Populate the vector.
69//!     for i in 0..v.len() {
70//!         v_repeated.vset(2 * i, v.vget(i));
71//!         v_repeated.vset(2 * i + 1, v.vget(i));
72//!     }
73//!
74//!     v_repeated
75//! }
76//!
77//! // Define the vector to be repeated.
78//! let v: Array1<f64> = array![1.0, 2.0, 3.0];
79//!
80//! // Repeat the elements.
81//! let v_repeated: Array1<f64> = repeat_elements(&v);
82//!
83//! // Check that the elements were properly repeated.
84//! assert_arrays_equal!(v_repeated, [1.0, 1.0, 2.0, 2.0, 3.0, 3.0]);
85//! ```
86//!
87//! # Using with `nalgebra`, `ndarray`, and `faer`
88//!
89//! `linalg-traits` provides implementations of the [`Vector`] and [`Matrix`] traits for linear
90//! algebra types defined by [`nalgebra`], [`ndarray`], and [`faer`]. However, since you may not
91//! want to use some or any of these crates in your project, `linalg-traits` specifies [`nalgebra`],
92//! [`ndarray`], and [`faer`] as optional dependencies.
93//!
94//! If you _are_ using any of these crates in your project and want linear algebra types defined by
95//! these crates to be identified as either [`Vector`]s or [`Matrix`]es, you should specify these
96//! crates as features in the `linalg-traits` dependency in your `Cargo.toml`:
97//!
98//! ```toml
99//! [dependencies]
100//! linalg-traits = { version = "x.y.z", features = ["nalgebra", "ndarray", "faer", "faer-traits"] }
101//! ```
102//!
103//! Note that the `faer-traits` feature is also required when using [`faer`].
104//!
105//! # Additional notes on use cases
106//!
107//! Say I have an ODE solver crate `my-ode-solver`. I want this crate to be compatible with
108//! [`ndarray`], [`nalgebra`], and [`faer`]. In the backend, I implement everything requiring
109//! vectors/matrices in `my-ode-solver` using generic types with trait bounds on either [`Vector`]
110//! or [`Matrix`] (e.g. `T: Vector`, `T: Matrix`). Now, any downstream user of `my-ode-solver` can
111//! choose whether they want to use [`ndarray`], [`nalgebra`], [`faer`], or any combination of the
112//! three. Alternatively, if they have some custom linear algebra types, they could implement
113//! [`Vector`] and [`Matrix`] for those custom types and use them directly with `my-ode-solver`.
114//!
115//! This crate is _not_ trying to replace existing APIs in all situations. Continuing the example
116//! from above, `my-ode-solver` will use the methods defined by the traits in `linalg-traits`.
117//! However, if I'm a user of `my-ode-solver` and I'm using it with [`ndarray`], in my project I
118//! should still use the APIs defined by [`ndarray`] (and not those defined by `linalg-traits`).
119
120// Linter setup.
121#![warn(missing_docs)]
122
123// Module declarations.
124pub(crate) mod matrix;
125pub(crate) mod scalar;
126pub(crate) mod vector;
127
128// Re-exports.
129pub use crate::matrix::mat::Mat;
130pub use crate::matrix::matrix_trait::Matrix;
131pub use crate::scalar::Scalar;
132pub use crate::vector::vector_trait::Vector;