hexga_math/geometry/
matrix.rs

1use super::*;
2
3
4/// 1x1 matrix
5pub type Matrix1<T> = SquareMatrix<T,1>;
6/// 2x2 matrix
7pub type Matrix2<T> = SquareMatrix<T,2>;
8/// 3x3 matrix
9pub type Matrix3<T> = SquareMatrix<T,3>;
10/// 4x4 matrix
11pub type Matrix4<T> = SquareMatrix<T,4>;
12
13pub type Mat<const ROW : usize, const COL : usize> = Matrix<float,ROW,COL>;
14/// 1x1 matrix
15pub type Mat1 = Mat<1,1>;
16/// 2x2 matrix
17pub type Mat2 = Mat<2,2>;
18/// 3x3 matrix
19pub type Mat3 = Mat<3,3>;
20/// 4x4 matrix
21pub type Mat4 = Mat<4,4>;
22
23pub type MatP<const COL : usize> = SquareMatrix<int,COL>;
24/// 1x1 matrix
25pub type Mat1P = MatP<1>;
26/// 2x2 matrix
27pub type Mat2P = MatP<2>;
28/// 3x3 matrix
29pub type Mat3P = MatP<3>;
30/// 4x4 matrix
31pub type Mat4P = MatP<4>;
32
33
34
35
36/// NxN matrix
37pub type SquareMatrix<T, const N : usize> = Matrix<T, N, N>;
38
39/// ROW rows, COL columns.
40///
41/// Can be indexed `matrix[row][col]`
42///
43/// The [(0,0)] index is in the top left corner
44#[repr(C)]
45#[derive(PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
46#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(transparent))]
47#[cfg_attr(feature = "hexga_io", derive(Save, Load))]
48pub struct Matrix<T, const ROW : usize, const COL : usize>
49{
50    columns : Vector<Vector<T, ROW>,COL>,
51}
52
53
54impl<T, const ROW : usize, const COL : usize> Deref for Matrix<T, ROW, COL>
55{
56    type Target=Vector<Vector<T, ROW>,COL>;
57    fn deref(&self) -> &Self::Target { &self.columns }
58}
59
60impl<T, const ROW : usize, const COL : usize> DerefMut for Matrix<T, ROW, COL>
61{
62    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.columns }
63}
64
65impl<T, const ROW : usize, const COL : usize>  Matrix<T, ROW, COL>
66{
67    fn _fmt(&self, f: &mut Formatter<'_>, d : impl Fn(&T, &mut Formatter<'_>) -> FmtResult) -> FmtResult
68    {
69        const SEP :&'static str = " ";
70
71        let mut strings: Vec<String> = Vec::with_capacity(ROW * COL);
72
73        let mut width = 0;
74
75        for c in 0..COL
76        {
77            for r in 0..ROW
78            {
79                strings.push(___());
80                let mut tmp_f = std::fmt::Formatter::new(strings.last_mut().unwrap(), ___());
81                d(&self[c][r], &mut tmp_f)?;
82                width = max(width, strings.last().unwrap().len());
83            }
84        }
85
86        for c in 0..COL
87        {
88            for r in 0..ROW
89            {
90                let idx = r * COL + c;
91                write!(f, "{:>width$}{}", strings[idx], SEP, width = width)?;
92            }
93            writeln!(f)?;
94        }
95        Ok(())
96    }
97}
98
99use std::fmt;
100impl<T, const ROW : usize, const COL : usize> fmt::Display  for Matrix<T, ROW, COL> where T: fmt::Display  { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult  { self._fmt(f, T::fmt) } }
101impl<T, const ROW : usize, const COL : usize> fmt::Debug    for Matrix<T, ROW, COL> where T: fmt::Debug    { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult  { self._fmt(f, T::fmt) } }
102impl<T, const ROW : usize, const COL : usize> fmt::Octal    for Matrix<T, ROW, COL> where T: fmt::Octal    { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult  { self._fmt(f, T::fmt) } }
103impl<T, const ROW : usize, const COL : usize> fmt::Binary   for Matrix<T, ROW, COL> where T: fmt::Binary   { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult  { self._fmt(f, T::fmt) } }
104impl<T, const ROW : usize, const COL : usize> fmt::LowerHex for Matrix<T, ROW, COL> where T: fmt::LowerHex { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult  { self._fmt(f, T::fmt) } }
105impl<T, const ROW : usize, const COL : usize> fmt::UpperHex for Matrix<T, ROW, COL> where T: fmt::UpperHex { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult  { self._fmt(f, T::fmt) } }
106impl<T, const ROW : usize, const COL : usize> fmt::LowerExp for Matrix<T, ROW, COL> where T: fmt::LowerExp { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult  { self._fmt(f, T::fmt) } }
107impl<T, const ROW : usize, const COL : usize> fmt::UpperExp for Matrix<T, ROW, COL> where T: fmt::UpperExp { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult  { self._fmt(f, T::fmt) } }
108impl<T, const ROW : usize, const COL : usize> fmt::Pointer  for Matrix<T, ROW, COL> where T: fmt::Pointer  { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult  { self._fmt(f, T::fmt) } }
109
110impl<T, const ROW : usize, const COL : usize> Default for Matrix<T,ROW,COL> where Vector<Vector<T, ROW>,COL> : Default
111{
112    fn default() -> Self {
113        Self { columns: ___() }
114    }
115}
116
117impl<T, const ROW : usize> Matrix<T,ROW,1>
118{
119    /// From a `Mx1` vector
120    pub const fn from_vector(vector : Vector<T, ROW>) -> Self
121    {
122        Self::from_col(Vector::from_array([vector]))
123    }
124}
125
126impl<T, const ROW : usize> From<Vector<T, ROW>> for Matrix<T,ROW,1>
127{
128    fn from(value: Vector<T, ROW>) -> Self {
129        Self::from_vector(value)
130    }
131}
132impl<T, const ROW : usize> From<Matrix<T,ROW,1>> for Vector<T, ROW> where Vector<T,ROW> : Default
133{
134    fn from(mut value: Matrix<T,ROW,1>) -> Self
135    {
136        std::mem::take(&mut value.columns[0])
137    }
138}
139
140impl<T, const ROW : usize, const COL : usize> Matrix<T,ROW,COL>
141{
142    /// Create a matrix from a `fn((columns,row))`
143    pub fn from_fn<F>(mut column_then_row : F) -> Self where F : FnMut(Point2) -> T
144    {
145        Self::from_col_array(std::array::from_fn(|column| std::array::from_fn(|row| column_then_row(point2(column as _,row as _)))))
146    }
147
148    pub fn from_col_fn<F>(mut column_then_row : F) -> Self where F : FnMut(usize, usize) -> T
149    {
150        Self::from_col_array(std::array::from_fn(|column| std::array::from_fn(|row| column_then_row(column,row))))
151    }
152
153    pub fn from_row_fn<F>(mut row_then_column : F) -> Self where F : FnMut(usize, usize) -> T
154    {
155        Self::from_col_array(std::array::from_fn(|column| std::array::from_fn(|row| row_then_column(row,column))))
156    }
157
158    pub const fn from_col(columns : Vector<Vector<T, ROW>,COL>) -> Self { Self { columns }}
159    pub fn from_col_array(columns : [[T;ROW];COL]) -> Self
160    {
161        Self
162        {
163            columns :  Vector::from_array(columns.map(|array| Vector::from_array(array)))
164        }
165    }
166
167    pub fn from_row(rows : Vector<Vector<T, COL>,ROW>) -> Self where T: Copy
168    {
169        Matrix::from_col(rows).transpose()
170    }
171    pub fn from_row_array(rows : [[T;COL];ROW]) -> Self where T: Copy
172    {
173        Self::from_row(Vector::from_array(rows.map(|array| Vector::from_array(array))))
174    }
175
176    pub fn col(&self) -> Vector<Vector<T, ROW>,COL> where T: Copy { self.columns }
177    pub fn row(&self) -> Vector<Vector<T, COL>,ROW> where T: Copy { self.transpose().columns }
178
179    pub fn iter_col(&self) -> impl Iterator<Item = Vector<T, ROW>> where Vector<Vector<T, ROW>,COL> : Copy, T : Copy { self.columns.into_iter()}
180    pub fn iter_row(&self) -> impl Iterator<Item = Vector<T, COL>> where Vector<Vector<T, ROW>,COL> : Copy, T : Copy { self.transpose().into_iter()}
181
182    /// Transpose the matrix
183    ///
184    /// ```rust
185    /// use hexga_math::prelude::*;
186    ///
187    /// assert_eq!(
188    ///     Mat2::from_col(vector2(vec2(1., 2.), vec2(3., 4.))).transpose(),
189    ///     Mat2::from_col(vector2(vec2(1., 3.), vec2(2., 4.)))
190    /// );
191    ///
192    /// assert_eq!(
193    ///     Mat::<3,2>::from_col(vector2(vec3(1., 2., 3.), vec3(4., 5., 6.))).transpose(),
194    ///     Mat::<2,3>::from_col(vector3(vec2(1., 4.), vec2(2., 5.), vec2(3., 6.)))
195    /// );
196    /// ```
197    pub fn transpose(&self) -> Matrix<T,COL,ROW> where T: Copy
198    {
199        Matrix::from_col(Vector::from_fn(|x| Vector::from_fn(|y| self[y][x])))
200    }
201}
202
203
204impl<T, const ROW : usize, const COL : usize> GetMatrix<T,ROW,COL> for Matrix<T,ROW,COL> where Self: Copy
205{
206    fn matrix(&self) -> Matrix<T,ROW,COL> {
207        *self
208    }
209}
210
211impl<T, const ROW : usize, const COL : usize> SetMatrix<T,ROW,COL> for Matrix<T,ROW,COL> where Self: Copy
212{
213    fn set_matrix(&mut self, matrix : Matrix<T,ROW,COL>) -> &mut Self {
214        *self = matrix; self
215    }
216}
217
218
219// 2D
220impl<T> SquareMatrix<T,2>
221    where
222    Self : Copy,
223    SquareMatrix<T, 2> : Mul<Vector<T, 2>, Output = Vector<T, 2>>,
224    Vector<T, 2> : Into< Vector<T, 1>>
225{
226    pub fn transform_relative(self, relative : Vector<T, 1>) -> Vector<T, 1> where T: Zero
227    {
228        self.transform(relative.with_y(T::ZERO)).into()
229    }
230
231    pub fn transform_position(self, position : Vector<T, 1>) -> Vector<T, 1> where T: One
232    {
233        self.transform(position.with_y(T::ONE)).into()
234    }
235}
236
237// 3D
238impl<T> SquareMatrix<T,3>
239    where
240    Self : Copy,
241    SquareMatrix<T, 3> : Mul<Vector<T, 3>, Output = Vector<T, 3>>,
242    Vector<T, 3> : Into< Vector<T, 2>>
243{
244    pub fn transform_relative(self, relative : Vector<T, 2>) -> Vector<T, 2> where T: Zero
245    {
246        self.transform(relative.with_z(T::ZERO)).into()
247    }
248
249    pub fn transform_position(self, position : Vector<T, 2>) -> Vector<T, 2> where T: One
250    {
251        self.transform(position.with_z(T::ONE)).into()
252    }
253}
254
255// 4D
256impl<T> SquareMatrix<T,4>
257    where
258    Self : Copy,
259    SquareMatrix<T, 4> : Mul<Vector<T, 4>, Output = Vector<T, 4>>,
260    Vector<T, 4> : Into< Vector<T, 3>>
261{
262    pub fn transform_relative(self, relative : Vector<T, 3>) -> Vector<T, 3> where T: Zero
263    {
264        self.transform(relative.with_w(T::ZERO)).into()
265    }
266
267    pub fn transform_position(self, position : Vector<T, 3>) -> Vector<T, 3> where T: One
268    {
269        self.transform(position.with_w(T::ONE)).into()
270    }
271}
272
273
274impl<T, const N : usize> SquareMatrix<T,N>
275    where
276    Self : Copy,
277    SquareMatrix<T, N>: Mul<Vector<T, N>, Output = Vector<T, N>>
278{
279    /*
280    /// The last value/component will be replaced by 0 because it is relative/a vector in math terms.
281    pub fn transform_relative(self, relative : Vector<T, N>) -> Vector<T, N> where T: Zero
282    {
283        self.transform(relative.with(N-1, T::ZERO))
284    }
285
286    /// The last value/component will be replaced by 1 because it is fixed/point in math terms.
287    pub fn transform_fixed(self, fixed : Vector<T, N>) -> Vector<T, N> where T: Zero
288    {
289        self.transform(fixed.with(N-1, T::ZERO))
290    }
291    */
292    /// The last value/component is 0 if it is a relative/vector/delta, 1 if it is fixed/point/position in math terms.
293    pub fn transform(self, value : Vector<T, N>) -> Vector<T, N>
294    {
295        self * value
296    }
297}
298
299
300
301
302impl<T, const ROW : usize, const COL : usize> Zero for Matrix<T,ROW,COL> where Vector<Vector<T,ROW>,COL> : Zero
303{
304    const ZERO : Self = Self::from_col(Vector::<Vector::<T, ROW>, COL>::ZERO);
305}
306
307impl<T, const N : usize> SquareMatrix<T,N> where T: One + Zero + Copy
308{
309    /// Same as [One]
310    pub const IDENTITY : Self = Self::ONE;
311}
312
313
314impl<T, const N : usize> One for SquareMatrix<T,N> where T: One + Zero + Copy
315{
316    const ONE : Self =
317    {
318        let mut col = [[T::ZERO; N]; N];
319        let mut i = 0;
320        while i < N
321        {
322            col[i][i] = T::ONE;
323            i+=1;
324        }
325        Self::from_col(unsafe { std::mem::transmute_copy(&col) })
326    };
327}
328
329impl<T, const N : usize> MinusOne for SquareMatrix<T,N> where T: MinusOne + Zero + Copy
330{
331    const MINUS_ONE : Self =
332    {
333        let mut col = [[T::ZERO; N]; N];
334        let mut i = 0;
335        while i < N
336        {
337            col[i][i] = T::MINUS_ONE;
338            i+=1;
339        }
340        Self::from_col(unsafe { std::mem::transmute_copy(&col) })
341    };
342}
343
344impl<T, const N : usize> Half for SquareMatrix<T,N> where T: Half + Zero + Copy
345{
346    const HALF : Self =
347    {
348        let mut col = [[T::ZERO; N]; N];
349        let mut i = 0;
350        while i < N
351        {
352            col[i][i] = T::HALF;
353            i+=1;
354        }
355        Self::from_col(unsafe { std::mem::transmute_copy(&col) })
356    };
357}
358
359
360impl<T, const N : usize> SquareMatrix<T,N> where T: Copy
361{
362    /// Return the diagonal
363    pub fn diag(&self) -> Vector<T,N> { Vector::from_fn(|i| self[i][i]) }
364    /// Set the value on the diagonal
365    pub fn set_diag(&mut self, diag: Vector<T,N>)
366    {
367        for i in 0..N
368        {
369            self[i][i] = diag[i];
370        }
371    }
372}
373
374map_on!(
375    (
376        (MinValue, MIN),
377        (MaxValue, MAX),
378        (NaNValue, NAN)
379    ),
380    (($trait_name : ident, $constant_name : ident)) =>
381    {
382        impl<T, const ROW : usize, const COL : usize> $trait_name for Matrix<T,ROW,COL> where T: $trait_name + Copy
383        {
384            const $constant_name : Self = Self::from_col(Vector::from_array([Vector::from_array([T::$constant_name; ROW]); COL]));
385        }
386    }
387);
388
389impl<T, const ROW : usize, const COL : usize> Add<Self> for Matrix<T,ROW,COL>
390    where
391    Vector<Vector<T, ROW>, COL> : Add<Vector<Vector<T, ROW>, COL>,Output = Vector<Vector<T, ROW>, COL>>
392{
393    type Output = Self;
394
395    fn add(self, rhs: Self) -> Self::Output
396    {
397        Self::from_col(self.columns.add(rhs.columns))
398    }
399}
400
401impl<T, const ROW : usize, const COL : usize> AddAssign<Self> for Matrix<T,ROW,COL>
402    where
403    Self : Add<Self,Output = Self> + Copy
404{
405    fn add_assign(&mut self, rhs: Self) {
406        *self = (*self).add(rhs);
407    }
408}
409
410
411impl<T, const ROW : usize, const COL : usize> Sub<Self> for Matrix<T,ROW,COL>
412    where
413    Vector<Vector<T, ROW>, COL> : Sub<Vector<Vector<T, ROW>, COL>,Output = Vector<Vector<T, ROW>, COL>>
414{
415    type Output = Self;
416
417    fn sub(self, rhs: Self) -> Self::Output
418    {
419        Self::from_col(self.columns.sub(rhs.columns))
420    }
421}
422
423impl<T, const ROW : usize, const COL : usize> SubAssign<Self> for Matrix<T,ROW,COL>
424    where
425    Self : Sub<Self,Output = Self> + Copy
426{
427    fn sub_assign(&mut self, rhs: Self) {
428        *self = (*self).sub(rhs);
429    }
430}
431
432
433impl<T, const ROW : usize, const COL : usize> Sum for Matrix<T,ROW,COL> where Self : Zero + Add<Self,Output = Self>
434{
435    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
436        iter.fold(Self::ZERO, Self::add)
437    }
438}
439
440impl<T, const COL : usize> Product for SquareMatrix<T,COL> where Self : One + Mul<Self,Output = Self>
441{
442    fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
443        iter.fold(Self::ONE, Self::mul)
444    }
445}
446
447/// ```
448/// use hexga_math::prelude::*;
449///
450/// let m1  = Mat2P::from_col((point2(7, 6), point2(5, 3)).into());
451/// let m2  = Mat2P::from_col((point2(2, 5), point2(1, 1)).into());
452/// let m3  = Mat2P::from_col((point2(39, 27), point2(12, 9)).into());
453///
454/// assert_eq!(m1 * m2, m3);
455///
456///
457/// let m1 = Matrix::<i32,2,3>::from_col(vector3(vector2(1, 4), vector2(2, 5), vector2(3, 6)));
458/// let m2 = Matrix::<i32,3,2>::from_col(vector2(vector3(7, 9, 11), vector3(8, 10, 12)));
459/// let m3 = Matrix::<i32,2,2>::from_col(vector2(vector2(1*7+2*9+3*11, 4*7+5*9+6*11), vector2(1*8+2*10+3*12, 4*8+5*10+6*12)));
460///
461/// assert_eq!(m1 * m2, m3);
462/// ```
463impl<T, const ROW : usize, const COL : usize, const COL2 : usize> Mul<Matrix<T,COL,COL2>> for Matrix<T,ROW,COL>
464    where
465    T : Numeric,
466{
467    type Output = Matrix<T, ROW, COL2>;
468
469    fn mul(self, rhs: Matrix<T,COL,COL2>) -> Self::Output
470    {
471        // Todo : match on ROW / COL, COL2
472        // and specialize it for 1x1, 2x2, 3x3 and 4x4 matrix
473        Matrix::from_col(Vector::from_fn(|c| Vector::from_fn(|r| (0..COL).map(|k| self[k][r] * rhs[c][k]).sum())))
474    }
475}
476
477
478impl<T, const ROW : usize, const COL : usize> Mul<Vector<T,COL>> for Matrix<T,ROW,COL>
479    where
480    T : Numeric,
481    //Matrix<T,ROW,COL> : Mul<Matrix<T,ROW,1>>,
482    Self : Mul<Matrix<T,COL,1>, Output = Matrix<T,ROW,1>>,
483    Vector<T,COL> : From<Matrix::<T,ROW,1>>
484{
485    type Output = Vector<T,COL>;
486
487    fn mul(self, rhs: Vector<T,COL>) -> Self::Output
488    {
489        let m : Matrix::<T,COL,1> = rhs.into();
490        let r = self * m;
491        r.into()
492    }
493}
494
495impl<T, const COL : usize> MulAssign<Self> for SquareMatrix<T,COL>
496    where
497    Self : Mul<Self,Output = Self> + Copy
498{
499    fn mul_assign(&mut self, rhs: Self) {
500        *self = *self * rhs;
501    }
502}
503
504impl<T, const ROW : usize, const COL : usize> Mul<T> for Matrix<T,ROW,COL> where T: Copy + Mul<T>
505{
506    type Output = Matrix<T::Output,ROW,COL>;
507
508    fn mul(self, rhs: T) -> Self::Output
509    {
510        Matrix::from_col(self.columns.map(|v| v.map(|i| i.mul(rhs))))
511    }
512}
513
514impl<T, const ROW : usize, const COL : usize> MulAssign<T> for Matrix<T,ROW,COL> where T: Copy + Mul<T,Output = T>
515{
516    fn mul_assign(&mut self, rhs: T) {
517        *self = (*self).mul(rhs);
518    }
519}
520
521impl<T, const ROW : usize, const COL : usize> Div<T> for Matrix<T,ROW,COL> where T: Copy + Div<T>
522{
523    type Output = Matrix<T::Output,ROW,COL>;
524
525    fn div(self, rhs: T) -> Self::Output
526    {
527        Matrix::from_col(self.columns.map(|v| v.map(|i| i.div(rhs))))
528    }
529}
530
531impl<T, const ROW : usize, const COL : usize> DivAssign<T> for Matrix<T,ROW,COL> where T: Copy + Div<T,Output = T>
532{
533    fn div_assign(&mut self, rhs: T) {
534        *self = (*self).div(rhs);
535    }
536}
537
538
539impl<T, const ROW : usize, const COL : usize> Map for Matrix<T,ROW,COL>
540{
541    type Item=T;
542    fn map_intern<F>(self, f: F) -> Self where F: FnMut(Self::Item) -> Self::Item
543    {
544        self.map(f)
545    }
546
547    fn map_with_intern<F>(self, other: Self, f: F) -> Self where F: FnMut(Self::Item, Self::Item) -> Self::Item {
548        self.map_with(other, f)
549    }
550}
551impl<T, const ROW : usize, const COL : usize> MapGeneric for Matrix<T,ROW,COL>
552{
553    type WithType<R> = Matrix<R,ROW,COL>;
554
555    fn map<R,F>(self, mut f: F) -> Self::WithType<R> where F: FnMut(Self::Item) -> R {
556        let mut it = self.columns.into_iter();
557        let cols = std::array::from_fn(|_| MapGeneric::map(it.next().unwrap(), &mut f));
558        Self::WithType::<R>::from_col(Vector::from_array(cols))
559    }
560
561    fn map_with<R, Item2, F>(self, other: Self::WithType<Item2>, mut f : F) -> Self::WithType<R> where F: FnMut(Self::Item, Item2) -> R {
562        let mut it1 = self.columns.into_iter();
563        let mut it2 = other.columns.into_iter();
564        let cols = std::array::from_fn(|_| MapGeneric::map_with(it1.next().unwrap(), it2.next().unwrap(), &mut f));
565        Self::WithType::<R>::from_col(Vector::from_array(cols))
566    }
567}
568
569
570
571impl<T, const N: usize> SquareMatrix<T, N>
572where
573    T: Float,
574{
575    /// Inverse the matrix, or return `None` if the matrix is singular.
576    ///
577    /// ```
578    /// use hexga_math::prelude::*;
579    ///
580    /// assert_eq!(Mat2::IDENTITY.inverse(), Some(Mat2::IDENTITY));
581    ///
582    /// // Non inversible matrix
583    /// let mut m2 = Mat2::IDENTITY;
584    /// m2.set_y(vec2(0., 0.));
585    /// assert_eq!(m2.inverse(), None);
586    ///
587    /// let m2 = Mat2::from_col(vector2(vec2(1., 3.), vec2(2., 4.)));
588    /// let m2_inv = m2.inverse().unwrap();
589    ///
590    /// assert_eq!(m2 * m2_inv, Mat2::IDENTITY);
591    /// ```
592    pub fn inverse(mut self) -> Option<Self>
593    {
594        let mut augmented = Self::IDENTITY;
595
596        for i in 0..N
597        {
598            if self[i][i] == T::ZERO { return None; }
599
600            let pivot = self[i][i];
601
602            for j in 0..N
603            {
604                self[i][j] /= pivot;
605                augmented[i][j] /=  pivot;
606            }
607
608            for k in (i + 1)..N
609            {
610                let factor = self[k][i];
611                for j in 0..N
612                {
613                    self[k][j] = self[k][j] - factor * self[i][j];
614                    let a = augmented[i][j];
615                    augmented[k][j] -= factor * a;
616                }
617            }
618        }
619
620        for i in (0..N).rev()
621        {
622            for k in 0..i
623            {
624                let factor = self[k][i];
625                for j in 0..N
626                {
627                    let a = self[i][j];
628                    self[k][j] -= factor * a;
629                    let a = augmented[i][j];
630                    augmented[k][j] -= factor * a;
631                }
632            }
633        }
634
635        Some(augmented)
636    }
637}
638
639
640// Todo : impl det in a generic way once const generic will be here.
641// Do a match on N, and hardcode the case for N in 0..=4
642
643// There is no generic way to compute the determinant of a matrix, because it required calculaing the submatrix, but at the moment const generic operation are not possible
644// I also don't want any heap allocation when computing the determinant
645impl<T> SquareMatrix<T, 0> where T: Numeric + One,
646{
647    pub fn det(&self) -> T
648    {
649        T::ONE
650    }
651}
652
653impl<T> SquareMatrix<T, 1> where T: Numeric + One,
654{
655    pub fn det(&self) -> T
656    {
657        self[0][0]
658    }
659}
660
661impl<T> SquareMatrix<T, 2> where T: Numeric + One,
662{
663    pub fn det(&self) -> T
664    {
665        self[0][0] * self[1][1] - self[0][1] * self[1][0]
666    }
667}
668
669impl<T> SquareMatrix<T, 3> where T: Numeric + One,
670{
671    pub fn det(&self) -> T
672    {
673          self[0][0] * (self[1][1] * self[2][2] - self[1][2] * self[2][1])
674        - self[0][1] * (self[1][0] * self[2][2] - self[1][2] * self[2][0])
675        + self[0][2] * (self[1][0] * self[2][1] - self[1][1] * self[2][0])
676    }
677}
678
679impl<T> SquareMatrix<T, 4> where T: Numeric + One,
680{
681    pub fn det(&self) -> T
682    {
683        let a = self[2][2] * self[3][3] - self[2][3] * self[3][2];
684        let b = self[2][1] * self[3][3] - self[2][3] * self[3][1];
685        let c = self[2][1] * self[3][2] - self[2][2] * self[3][1];
686        let d = self[2][0] * self[3][3] - self[2][3] * self[3][0];
687        let e = self[2][0] * self[3][2] - self[2][2] * self[3][0];
688        let f = self[2][0] * self[3][1] - self[2][1] * self[3][0];
689
690        self[0][0] *
691        (
692              self[1][1] * a
693            - self[1][2] * b
694            + self[1][3] * c
695        )
696
697        - self[0][1] *
698        (
699            self[1][0] * a
700          - self[1][2] * d
701          + self[1][3] * e
702        )
703
704        + self[0][2] *
705        (
706            self[1][0] * b
707          - self[1][1] * d
708          + self[1][3] * f
709        )
710
711        - self[0][3] *
712        (
713            self[1][0] * c
714          - self[1][1] * e
715          + self[1][2] * f
716        )
717    }
718}
719
720
721macro_rules! matrix_have_x {
722    ($dim : expr) =>
723    {
724        impl<T> HaveX<Vector<T,$dim>> for SquareMatrix<T,$dim>
725        {
726            fn iter_x<'a>(&'a self) -> impl Iterator<Item=&'a Vector<T,$dim>> where Vector<T,$dim>: 'a {
727                self.columns.as_array().as_slice()[0..=Self::X_INDEX].iter()
728            }
729
730            fn iter_x_mut<'a>(&'a mut self) -> impl Iterator<Item=&'a mut Vector<T,$dim>> where Vector<T,$dim>: 'a {
731                self.columns.as_array_mut().as_mut_slice()[0..=Self::X_INDEX].iter_mut()
732            }
733        }
734    };
735}
736
737matrix_have_x!(1);
738matrix_have_x!(2);
739matrix_have_x!(3);
740matrix_have_x!(4);
741
742macro_rules! matrix_have_y {
743    ($dim : expr) =>
744    {
745        impl<T> HaveY<Vector<T,$dim>> for SquareMatrix<T,$dim>
746        {
747            fn iter_xy<'a>(&'a self) -> impl Iterator<Item=&'a Vector<T,$dim>> where Vector<T,$dim>: 'a {
748                self.columns.as_array().as_slice()[0..=Self::Y_INDEX].iter()
749            }
750
751            fn iter_xy_mut<'a>(&'a mut self) -> impl Iterator<Item=&'a mut Vector<T,$dim>> where Vector<T,$dim>: 'a {
752                self.columns.as_array_mut().as_mut_slice()[0..=Self::Y_INDEX].iter_mut()
753            }
754        }
755    };
756}
757
758matrix_have_y!(2);
759matrix_have_y!(3);
760matrix_have_y!(4);
761
762macro_rules! matrix_have_z {
763    ($dim : expr) =>
764    {
765        impl<T> HaveZ<Vector<T,$dim>> for SquareMatrix<T,$dim>
766        {
767            fn iter_xyz<'a>(&'a self) -> impl Iterator<Item=&'a Vector<T,$dim>> where Vector<T,$dim>: 'a {
768                self.columns.as_array().as_slice()[0..=Self::Z_INDEX].iter()
769            }
770
771            fn iter_xyz_mut<'a>(&'a mut self) -> impl Iterator<Item=&'a mut Vector<T,$dim>> where Vector<T,$dim>: 'a {
772                self.columns.as_array_mut().as_mut_slice()[0..=Self::Z_INDEX].iter_mut()
773            }
774        }
775    };
776}
777
778matrix_have_z!(3);
779matrix_have_z!(4);
780
781macro_rules! matrix_have_w {
782    ($dim : expr) =>
783    {
784        impl<T> HaveW<Vector<T,$dim>> for SquareMatrix<T,$dim>
785        {
786            fn iter_xyzw<'a>(&'a self) -> impl Iterator<Item=&'a Vector<T,$dim>> where Vector<T,$dim>: 'a {
787                self.columns.as_array().as_slice()[0..=Self::W_INDEX].iter()
788            }
789
790            fn iter_xyzw_mut<'a>(&'a mut self) -> impl Iterator<Item=&'a mut Vector<T,$dim>> where Vector<T,$dim>: 'a {
791                self.columns.as_array_mut().as_mut_slice()[0..=Self::W_INDEX].iter_mut()
792            }
793        }
794    };
795}
796
797matrix_have_w!(4);
798
799impl<T, const N : usize> RotateX<T> for SquareMatrix<T,N>
800    where
801        Self : HaveZ<Vector<T,N>> + Zero + Mul<Self, Output = Self>,
802        T : Float
803{
804    fn rotate_x(&mut self, angle : AngleOf<T>) -> &mut Self
805    {
806        *self = Self::from_rotation_x(angle) * (*self);
807        self
808    }
809}
810
811impl<T, const N : usize> RotateY<T> for SquareMatrix<T,N>
812    where
813        Self : HaveZ<Vector<T,N>> + Zero + Mul<Self, Output = Self>,
814        T : Float
815{
816    fn rotate_y(&mut self, angle : AngleOf<T>) -> &mut Self
817    {
818        *self = Self::from_rotation_y(angle) * (*self);
819        self
820    }
821}
822
823impl<T, const N : usize> RotateZ<T> for SquareMatrix<T,N>
824    where
825        Self : HaveY<Vector<T,N>> + Zero + Mul<Self, Output = Self>,
826        T : Float
827{
828    fn rotate_z(&mut self, angle : AngleOf<T>) -> &mut Self
829    {
830        *self = Self::from_rotation_z(angle) * (*self);
831        self
832    }
833}
834
835/*
836impl<T, const N : usize> GetPosition<Vector<T,N>,N> for SquareMatrix<T,N> where T: Copy
837{
838    fn pos(&self) -> Vector<Vector<T,N>,N> {
839        self.col()
840    }
841}
842impl<T, const N : usize> SetPosition<Vector<T,N>,N> for SquareMatrix<T,N> where T: Copy
843{
844    fn set_pos(&mut self, pos : Vector<Vector<T,N>,N>) -> &mut Self {
845        *self = Self::from_col(pos);
846        self
847    }
848}
849*/
850
851impl<T> GetPosition<T,2> for SquareMatrix<T,3> where T: Copy
852{
853    fn pos(&self) -> Vector<T,2> { self.columns[2].into() }
854}
855impl<T> SetPosition<T,2> for SquareMatrix<T,3> where T: Copy
856{
857    fn set_pos(&mut self, pos : Vector<T,2>) -> &mut Self { self.columns[2] = pos.with_z(self[2][2]); self }
858}
859impl<T> GetPosition<T,3> for SquareMatrix<T,4> where T: Copy
860{
861    fn pos(&self) -> Vector<T,3> { self.columns[3].into() }
862}
863impl<T> SetPosition<T,3> for SquareMatrix<T,4> where T: Copy
864{
865    fn set_pos(&mut self, pos : Vector<T,3>) -> &mut Self { self.columns[3] = pos.with_w(self[3][3]); self }
866}
867
868impl<T> GetScale<T,2> for SquareMatrix<T,3> where T: Float
869{
870    fn scale(&self) -> Vector<T,2> { Vector::from_fn(|i| Vector::<T,2>::from(self[i]).length() ) }
871}
872impl<T> SetScale<T,2> for SquareMatrix<T,3> where T: Float
873{
874    fn set_scale(&mut self, scale : Vector<T,2>) -> &mut Self {
875        for i in 0..2
876        {
877            let len = Vector::<T, 2>::from(self[i]).length();
878            if len.is_non_zero()
879            {
880                let factor = scale[i] / len;
881                for j in 0..2
882                {
883                    self[i][j] = self[i][j] * factor;
884                }
885            }
886        }
887        self
888    }
889}
890impl<T> GetScale<T,3> for SquareMatrix<T,4> where T: Float
891{
892    fn scale(&self) -> Vector<T,3> { Vector::from_fn(|i| Vector::<T,3>::from(self[i]).length() ) }
893}
894impl<T> SetScale<T,3> for SquareMatrix<T,4> where T: Float
895{
896    fn set_scale(&mut self, scale : Vector<T,3>) -> &mut Self {
897        for i in 0..3
898        {
899            let len = Vector::<T, 3>::from(self[i]).length();
900            if len.is_non_zero()
901            {
902                let factor = scale[i] / len;
903                for j in 0..3
904                {
905                    self[i][j] = self[i][j] * factor;
906                }
907            }
908        }
909        self
910    }
911}
912
913/// the rotation code is mainly based on glam code
914impl<T, const N : usize> SquareMatrix<T,N> where Self : HaveZ<Vector<T,N>> + Zero, T : Float
915{
916    pub fn from_rotation_axis(axis: Vector3<T>, angle : AngleOf<T>) -> Self
917    {
918        let (sin, cos) = angle.sin_cos();
919        let axis = axis.normalized();
920        let axis_sin = axis * sin;
921        let axis_sq = axis * axis;
922        let omc = T::ONE - cos;
923
924        let xyomc = axis.x * axis.y * omc;
925        let xzomc = axis.x * axis.z * omc;
926        let yzomc = axis.y * axis.z * omc;
927
928        let mut r = Self::ZERO;
929        r[0][0] = axis_sq.x * omc + cos;
930        r[0][1] = xyomc + axis_sin.z;
931        r[0][2] = xzomc - axis_sin.y;
932
933        r[1][0] = xyomc - axis_sin.z;
934        r[1][1] = axis_sq.y * omc + cos;
935        r[1][2] = yzomc + axis_sin.x;
936
937        r[2][0] = xzomc + axis_sin.y;
938        r[2][1] = yzomc - axis_sin.x;
939        r[2][2] = axis_sq.z * omc + cos;
940
941        r
942    }
943
944    pub fn from_rotation_x(angle : AngleOf<T>) -> Self
945    {
946        let (sina, cosa) = angle.sin_cos();
947        let mut r = Self::IDENTITY;
948
949        r[Self::Y_INDEX][Self::Y_INDEX] =  cosa;
950        r[Self::Y_INDEX][Self::Z_INDEX] =  sina;
951        r[Self::Z_INDEX][Self::Y_INDEX] = -sina;
952        r[Self::Z_INDEX][Self::Z_INDEX] =  cosa;
953        r
954    }
955
956    pub fn from_rotation_y(angle : AngleOf<T>) -> Self
957    {
958        let (sina, cosa) = angle.sin_cos();
959        let mut r = Self::IDENTITY;
960
961        r[Self::X_INDEX][Self::X_INDEX] =  cosa;
962        r[Self::X_INDEX][Self::Z_INDEX] = -sina;
963        r[Self::Z_INDEX][Self::X_INDEX] =  sina;
964        r[Self::Z_INDEX][Self::Z_INDEX] =  cosa;
965        r
966    }
967}
968
969impl<T, const N : usize> SquareMatrix<T,N> where Self : HaveY<Vector<T,N>> + Zero, T : Float
970{
971    pub fn from_rotation_z(angle : AngleOf<T>) -> Self
972    {
973        let (sina, cosa) = angle.sin_cos();
974        let mut r = Self::IDENTITY;
975
976        r[Self::X_INDEX][Self::X_INDEX] =  cosa;
977        r[Self::X_INDEX][Self::Y_INDEX] =  sina;
978        r[Self::Y_INDEX][Self::X_INDEX] = -sina;
979        r[Self::Y_INDEX][Self::Y_INDEX] =  cosa;
980        r
981    }
982}
983
984impl<T, const N : usize> SquareMatrix<T,N> where Self : HaveZ<Vector<T,N>> + One, T : Copy + Zero + One
985{
986    /// Put an [One] for the last component
987    pub fn from_scale(scale : Vector<T,N>) -> Self
988    {
989        //let scale = scale.to_vector_filled(T::ONE);
990
991        let mut r = Self::IDENTITY;
992        for i in 0..N
993        {
994            r[i][i] = scale[i];
995        }
996        r
997    }
998    /// Put an [Zero] for the last component
999    pub fn from_translation(translation: Vector<T,N>) -> Self where T: Zero + AddAssign<T>
1000    {
1001        //let translation = translation.to_vector_filled(T::ZERO);
1002        let mut r = Self::IDENTITY;
1003        for i in 0..N
1004        {
1005            r[N-1][i] += translation[i];
1006        }
1007        r
1008    }
1009}
1010
1011
1012// Impl based on the glam crate
1013impl<T> Matrix4<T>
1014{
1015    /// Creates a right-handed view matrix.
1016    ///
1017    /// View space: +X = right, +Y = up, +Z = back (camera looks toward -Z).
1018    #[inline]
1019    #[must_use]
1020    pub fn look_at_rh(position: Vector3<T>, center: Vector3<T>, up: Vector3<T>) -> Self where T: Float
1021    {
1022        Self::look_to_rh(position, center - position, up)
1023    }
1024
1025    /// Creates a right-handed view matrix from a direction vector.
1026    ///
1027    /// View space: +X = right, +Y = up, +Z = back (camera looks toward -Z).
1028    #[inline]
1029    #[must_use]
1030    pub fn look_to_rh(position: Vector3<T>, dir: Vector3<T>, up: Vector3<T>) -> Self where T: Float
1031    {
1032        let f = dir.normalized();
1033        let s = f.cross(up).normalized();
1034        let u = s.cross(f);
1035
1036        Self::from_col(
1037            vector4
1038            (
1039                vector4(s.x, u.x, -f.x, zero()),
1040                vector4(s.y, u.y, -f.y, zero()),
1041                vector4(s.z, u.z, -f.z, zero()),
1042                vector4(-position.dot(s), position.dot(u), position.dot(f), one())
1043            )
1044        )
1045    }
1046
1047
1048    /// Creates a left-handed view matrix.
1049    ///
1050    /// View space: +X = right, +Y = up, +Z = forward (camera looks toward +Z).
1051    #[inline]
1052    #[must_use]
1053    pub fn look_at_lh(position: Vector3<T>, center: Vector3<T>, up: Vector3<T>) -> Self where T: Float,
1054    {
1055        Self::look_to_lh(position, center - position, up)
1056    }
1057
1058    /// Creates a left-handed view matrix from a direction vector.
1059    ///
1060    /// View space: +X = right, +Y = up, +Z = forward (camera looks toward +Z).
1061    #[inline]
1062    #[must_use]
1063    pub fn look_to_lh(position: Vector3<T>, dir: Vector3<T>, up: Vector3<T>) -> Self where T: Float,
1064    {
1065        let f = dir.normalized();
1066        let s = up.cross(f).normalized();
1067        let u = f.cross(s);
1068
1069        Self::from_col(
1070            vector4(
1071                vector4(s.x, u.x, f.x, zero()),
1072                vector4(s.y, u.y, f.y, zero()),
1073                vector4(s.z, u.z, f.z, zero()),
1074                vector4(-position.dot(s), -position.dot(u), -position.dot(f), one()),
1075            )
1076        )
1077    }
1078}
1079
1080
1081#[cfg(test)]
1082mod test_matrix
1083{
1084    use super::*;
1085
1086    #[test]
1087    fn rotation_zero_on_z()
1088    {
1089        let m = Mat2::from_col_array([[1.,2.], [3.,4.]]);
1090        assert_eq!(m.rotated_z(0.degree()), m);
1091    }
1092}