numint/ode_state/smatrix.rs
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
use crate::ode_state::ode_state_trait::{OdeState, StateIndex};
use linalg_traits::Matrix;
#[cfg(feature = "nalgebra")]
use nalgebra::SMatrix;
/// Macro to implement the [`OdeState`] trait for statically-sized matrix types.
///
/// A type must implement the
/// [`linalg_traits::Matrix`](https://docs.rs/linalg-traits/latest/linalg_traits/trait.Matrix.html)
/// trait to be used with this macro.
///
/// # Arguments
///
/// * `$type:ident` - Type to implement the [`OdeState`] trait for. Do not include any type
/// parameters (e.g. use `SMatrix` instead of `SMatrix<f64, R, C>`).
///
/// # Warning
///
/// We use this macro to implement [`OdeState`] for `nalgebra::SMatrix<f64, R, C>`. However, this
/// also ends up implementing it for `nalgebra::SVector<f64, N>`, since both of them are type
/// aliases for `nalgebra::Matrix`.
///
/// # Example
///
/// This example demonstrates how we use the `impl_ode_state_for_smatrix` macro internally within
/// the `numint` crate to implement the [`crate::OdeState`] trait for `SMatrix<f64, R, C>`.
///
/// ```ignore
/// use linalg_traits::Matrix;
/// use nalgebra::SMatrix;
///
/// use numint::{impl_ode_state_for_smatrix, OdeState};
///
/// impl_ode_state_for_smatrix!(SMatrix);
/// ```
#[macro_export]
macro_rules! impl_ode_state_for_smatrix {
($($type:ident),*) => {
$(
impl<const R: usize, const C: usize> OdeState for $type<f64, R, C> {
fn add(&self, other: &Self) -> Self {
<Self as Matrix<f64>>::add(self, other)
}
fn add_assign(&mut self, other: &Self) {
<Self as Matrix<f64>>::add_assign(self, other);
}
fn sub(&self, other: &Self) -> Self {
<Self as Matrix<f64>>::sub(self, other)
}
fn sub_assign(&mut self, other: &Self) {
<Self as Matrix<f64>>::sub_assign(self, other);
}
fn mul(&self, scalar: f64) -> Self {
<Self as Matrix<f64>>::mul(self, scalar)
}
fn mul_assign(&mut self, scalar: f64) {
<Self as Matrix<f64>>::mul_assign(self, scalar);
}
fn get_state_variable(&self, index: StateIndex) -> f64 {
match index {
StateIndex::Scalar() => panic!("Cannot index a matrix ODE state with a StateIndex::Scalar."),
StateIndex::Vector(i) => self[i], // to support nalgebra::SVector
StateIndex::Matrix(i, j) => self[(i, j)]
}
}
}
)*
};
}
// Implementation of OdeState for nalgebra::SVector<f64, N> and nalgebra::SMatrix<f64, R, C>.
#[cfg(feature = "nalgebra")]
impl_ode_state_for_smatrix!(SMatrix);