Given a matrix type in Rust using const generic parameters, something like this:
pub struct Mat<T, const R: usize, const C: usize>
{
m: [[T; C]; R],
}
I am aware that specializations are not available (yet, and not for this type of specialization it seems?), but it seems like it is possible to implement some 'specializations' for specific instances of this type, e.g.:
impl<T> Mat<T, 2, 2>
{
pub fn invert(self) -> Self
where T: From<f32> + Clone + std::ops::Neg<Output=T> + std::ops::Sub<T, Output = T> +
std::ops::Mul<T, Output = T> + std::ops::Div<T, Output = T>
{
let r = T::from(1.0) / self.clone().determinant();
Mat::new([[ self[1][1]*r.clone(), -self[0][1]*r.clone()],
[-self[1][0]*r.clone(), self[0][0]*r]])
}
pub fn determinant(self) -> T
where T: std::ops::Sub<T, Output = T> + std::ops::Mul<T, Output = T>
{
self[0][0]*self[1][1] - self[0][1]*self[1][0]
}
}
Similar 'specializations' can be implemented for 3x3 and 4x4 matrices.
However, at some point I would like to also implement a generalized determinant/inverse, something like this:
impl<T, const N: usize> Mat<T, N, N>
{
/// Generalized matrix inversion.
pub fn gen_invert(self) -> Self
{
// TODO: determinant(), matrix_minor(), cofactor(), adjugate()
Mat::default()
}
/// Generalized matrix determinant.
pub fn gen_det(self) -> T
{
match N
{
1 => self.determinant(), // <- Wrong type Mat<T, N, N>, not Mat<T, 1, 1>.
// 2 => // Same as above.
_ => general_fn(),
}
}
}
This turned out to be hard however, since there does not seem to be any way to
cast or even transmute a type of Mat<T, N, N> to Mat<T, 1, 1>, even though we
know that the sizes are correct, given that is done on a const variable under
an appropriate match case. Is there some way to accomplish the above without an
expensive from()
function that manually creates a Mat<T, 1, 1> from the Mat<T,
N, N>?
Additionally, is there some way to avoid renaming the generalized versions of these functions? I tried to do that using traits, similar to this question, but since all functions have the same name this does not appear to work for this case.
(There are even more complications with this though, since computing minor matrices requires arithmetic on const generics and that is only in nightly Rust right now, but that is beyond the scope of this question.)