cgl_rs/math/
matrix.rs

1//! Matrix math module. Includes a 4x4 matrix struct and associated methods.
2//! NOTE: These matrix library is for graphics programming with OpenGL.
3//!       For linear algebra, check the cgl_rs::math::linalg module.
4
5use super::{Vector3, Vector4};
6
7
8/// A 3x3 matrix struct used for graphics programming with OpenGL.
9#[repr(C)]
10#[derive(Debug, Copy, Clone, PartialEq)]
11pub struct Matrix3x3 {
12    m: [f32; 9]
13}
14
15/// A 4x4 matrix struct used for graphics programming with OpenGL.
16#[repr(C)]
17#[derive(Debug, Copy, Clone, PartialEq)]
18pub struct Matrix4x4 {
19    m: [f32; 16]
20}
21
22
23extern {
24    fn CGL_mat3_det(m: &Matrix3x3) -> f32;
25    fn CGL_mat3_transpose(m: &Matrix3x3) -> Matrix3x3;
26    fn CGL_mat3_trace(m: &Matrix3x3) -> f32;
27
28    fn CGL_mat4_zero_MACRO() -> Matrix4x4;
29    fn CGL_mat4_identity_MACRO() -> Matrix4x4;
30    fn CGL_mat4_scale_MACRO(x: f32, y: f32, z: f32) -> Matrix4x4;
31    fn CGL_mat4_translate_MACRO(x: f32, y: f32, z: f32) -> Matrix4x4;
32    fn CGL_mat4_rotate_x_MACRO(angle: f32) -> Matrix4x4;
33    fn CGL_mat4_rotate_y_MACRO(angle: f32) -> Matrix4x4;
34    fn CGL_mat4_rotate_z_MACRO(angle: f32) -> Matrix4x4;
35    fn CGL_mat4_perspective_MACRO(fov: f32, aspect: f32, near: f32, far: f32) -> Matrix4x4;
36    fn CGL_mat4_orthographic_MACRO(left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32) -> Matrix4x4;
37
38    fn CGL_mat4_mul(a: &Matrix4x4, b: &Matrix4x4) -> Matrix4x4;
39    fn CGL_mat4_det(m: &Matrix4x4) -> f32;
40    fn CGL_mat4_det_by_lu(m: &Matrix4x4) -> f32;
41    fn CGL_mat4_det_by_gauss(m: &Matrix4x4) -> f32;
42    fn CGL_mat4_mul_vec4(m: &Matrix4x4, v: &Vector4) -> Vector4;
43    fn CGL_mat4_inverse(m: &Matrix4x4) -> Matrix4x4;
44    fn CGL_mat4_transpose(m: &Matrix4x4) -> Matrix4x4;
45    fn CGL_mat4_adjoint(m: &Matrix4x4) -> Matrix4x4;
46    fn CGL_mat4_gauss_elim(m: &Matrix4x4) -> Matrix4x4;
47    fn CGL_mat4_rank(m: &Matrix4x4) -> i32;
48    fn CGL_mat4_trace(m: &Matrix4x4) -> f32;
49    fn CGL_mat4_to_mat3(m: &Matrix4x4) -> Matrix3x3;
50    fn CGL_mat4_from_mat3(m: &Matrix3x3) -> Matrix4x4;
51    fn CGL_mat4_rotate_about_axis(axis: &Vector3, angle: f32) -> Matrix4x4;
52    fn CGL_mat4_look_at(eye: Vector3, target: Vector3, up: Vector3) -> Matrix4x4;
53    fn CGL_mat4_lerp(a: &Matrix4x4, b: &Matrix4x4, t: f32) -> Matrix4x4;
54    fn CGL_mat4_decompose_lu(m: &Matrix4x4, l: *mut Matrix4x4, u: *mut Matrix4x4) -> std::ffi::c_void;
55}
56
57
58impl std::ops::Add<Matrix3x3> for Matrix3x3 {
59    type Output = Matrix3x3;
60
61    fn add(self, rhs: Matrix3x3) -> Matrix3x3 {
62        Matrix3x3 {
63            m: [
64                self.m[0] + rhs.m[0], self.m[1] + rhs.m[1], self.m[2] + rhs.m[2],
65                self.m[3] + rhs.m[3], self.m[4] + rhs.m[4], self.m[5] + rhs.m[5],
66                self.m[6] + rhs.m[6], self.m[7] + rhs.m[7], self.m[8] + rhs.m[8]
67            ]
68        }
69    }
70}
71
72impl std::ops::Sub<Matrix3x3> for Matrix3x3 {
73    type Output = Matrix3x3;
74
75    fn sub(self, rhs: Matrix3x3) -> Matrix3x3 {
76        Matrix3x3 {
77            m: [
78                self.m[0] - rhs.m[0], self.m[1] - rhs.m[1], self.m[2] - rhs.m[2],
79                self.m[3] - rhs.m[3], self.m[4] - rhs.m[4], self.m[5] - rhs.m[5],
80                self.m[6] - rhs.m[6], self.m[7] - rhs.m[7], self.m[8] - rhs.m[8]
81            ]
82        }
83    }
84}
85
86impl std::ops::Mul<f32> for Matrix3x3 {
87    type Output = Matrix3x3;
88
89    fn mul(self, rhs: f32) -> Matrix3x3 {
90        Matrix3x3 {
91            m: [
92                self.m[0] * rhs, self.m[1] * rhs, self.m[2] * rhs,
93                self.m[3] * rhs, self.m[4] * rhs, self.m[5] * rhs,
94                self.m[6] * rhs, self.m[7] * rhs, self.m[8] * rhs
95            ]
96        }
97    }
98}
99
100impl std::fmt::Display for Matrix3x3 {
101    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
102        write!(f, "{{\n\t[{}, {}, {}]\n\t[{}, {}, {}]\n\t[{}, {}, {}]\n}}",
103            self.m[0], self.m[3], self.m[6],
104            self.m[1], self.m[4], self.m[7],
105            self.m[2], self.m[5], self.m[8]
106        )
107    }
108}
109
110impl Matrix3x3 {
111    /// Creates a new 3x3 matrix.
112    /// 
113    /// # Arguments
114    /// 
115    /// m0 ... m8: The values of the matrix.
116    /// 
117    /// # Returns
118    /// 
119    /// A new 3x3 matrix.
120    /// 
121    /// # Example
122    /// 
123    /// ```
124    /// use cgl_rs::math::Matrix3x3;
125    /// 
126    /// let m = Matrix3x3::new(
127    ///    1.0, 0.0, 0.0,
128    ///    0.0, 1.0, 0.0,
129    ///    0.0, 0.0, 1.0
130    /// );
131    /// ```
132    pub fn new(
133        m0: f32, m1: f32, m2: f32,
134        m3: f32, m4: f32, m5: f32,
135        m6: f32, m7: f32, m8: f32
136    ) -> Matrix3x3 {
137        Matrix3x3 {
138            m: [
139                m0, m3, m6,
140                m1, m4, m7,
141                m2, m5, m8
142            ]
143        }
144    }
145
146
147    /// Creates a new 3x3 matrix with all elements set to zero.
148    ///
149    /// # Returns
150    ///
151    /// A new 3x3 matrix with all elements set to zero.
152    ///
153    /// # Example
154    ///
155    /// ```
156    /// use cgl_rs::math::Matrix3x3;
157    ///
158    /// let m = Matrix3x3::zero();
159    /// ```
160    pub fn zero() -> Matrix3x3 {
161        Matrix3x3 {
162            m: [0.0; 9]
163        }
164    }
165
166
167
168    /// Creates a new 3x3 identity matrix.
169    ///
170    /// # Returns
171    ///
172    /// A new 3x3 identity matrix.
173    ///
174    /// # Example
175    ///
176    /// ```
177    /// use cgl_rs::math::Matrix3x3;
178    ///
179    /// let m = Matrix3x3::identity();
180    /// ```
181    pub fn identity() -> Matrix3x3 {
182        Matrix3x3::new(
183            1.0, 0.0, 0.0,
184            0.0, 1.0, 0.0, 
185            0.0, 0.0, 1.0
186        )
187    }
188
189
190    /// Transposes the matrix.
191    ///
192    /// # Returns
193    ///
194    /// A new 3x3 matrix that is the transpose of the original matrix.
195    ///
196    /// # Example
197    ///
198    /// ```
199    /// use cgl_rs::math::Matrix3x3;
200    ///
201    /// let m = Matrix3x3::new(
202    ///     1.0, 2.0, 3.0,
203    ///     4.0, 5.0, 6.0,
204    ///     7.0, 8.0, 9.0
205    /// );
206    ///
207    /// let m_transpose = m.transpose();
208    /// ```
209    pub fn transpose(&self) -> Matrix3x3 {
210        unsafe {
211            CGL_mat3_transpose(self)
212        }
213    }
214
215    /// Calculates the trace of the matrix.
216    ///
217    /// # Returns
218    ///
219    /// The sum of the diagonal elements of the matrix.
220    ///
221    /// # Example
222    ///
223    /// ```
224    /// use cgl_rs::math::Matrix3x3;
225    ///
226    /// let m = Matrix3x3::new(
227    ///     1.0, 2.0, 3.0,
228    ///     4.0, 5.0, 6.0,
229    ///     7.0, 8.0, 9.0
230    /// );
231    ///
232    /// let trace = m.trace();
233    /// ```
234    pub fn trace(&self) -> f32 {
235        unsafe {
236            CGL_mat3_trace(self) as f32
237        }
238    }
239
240    /// Calculates the determinant of the matrix.
241    ///
242    /// # Returns
243    ///
244    /// The determinant of the matrix.
245    ///
246    /// # Example
247    ///
248    /// ```
249    /// use cgl_rs::math::Matrix3x3;
250    ///
251    /// let m = Matrix3x3::new(
252    ///     1.0, 2.0, 3.0,
253    ///     4.0, 5.0, 6.0,
254    ///     7.0, 8.0, 9.0
255    /// );
256    ///
257    /// let det = m.determinant();
258    /// ```
259    pub fn determinant(&self) -> f32 {
260        unsafe {
261            CGL_mat3_det(self) as f32
262        }
263    }
264
265}
266
267
268impl std::ops::Add<Matrix4x4> for Matrix4x4 {
269    type Output = Matrix4x4;
270
271    fn add(self, rhs: Matrix4x4) -> Matrix4x4 {
272        Matrix4x4 {
273            m: [
274                self.m[0] + rhs.m[0], self.m[1] + rhs.m[1], self.m[2] + rhs.m[2], self.m[3] + rhs.m[3],
275                self.m[4] + rhs.m[4], self.m[5] + rhs.m[5], self.m[6] + rhs.m[6], self.m[7] + rhs.m[7],
276                self.m[8] + rhs.m[8], self.m[9] + rhs.m[9], self.m[10] + rhs.m[10], self.m[11] + rhs.m[11],
277                self.m[12] + rhs.m[12], self.m[13] + rhs.m[13], self.m[14] + rhs.m[14], self.m[15] + rhs.m[15]
278            ]
279        }
280    }
281}
282
283impl std::ops::Sub<Matrix4x4> for Matrix4x4 {
284    type Output = Matrix4x4;
285
286    fn sub(self, rhs: Matrix4x4) -> Matrix4x4 {
287        Matrix4x4 {
288            m: [
289                self.m[0] - rhs.m[0], self.m[1] - rhs.m[1], self.m[2] - rhs.m[2], self.m[3] - rhs.m[3],
290                self.m[4] - rhs.m[4], self.m[5] - rhs.m[5], self.m[6] - rhs.m[6], self.m[7] - rhs.m[7],
291                self.m[8] - rhs.m[8], self.m[9] - rhs.m[9], self.m[10] - rhs.m[10], self.m[11] - rhs.m[11],
292                self.m[12] - rhs.m[12], self.m[13] - rhs.m[13], self.m[14] - rhs.m[14], self.m[15] - rhs.m[15]
293            ]
294        }
295    }
296}
297
298impl std::ops::Mul<f32> for Matrix4x4 {
299    type Output = Matrix4x4;
300
301    fn mul(self, rhs: f32) -> Matrix4x4 {
302        Matrix4x4 {
303            m: [
304                self.m[0] * rhs, self.m[1] * rhs, self.m[2] * rhs, self.m[3] * rhs,
305                self.m[4] * rhs, self.m[5] * rhs, self.m[6] * rhs, self.m[7] * rhs,
306                self.m[8] * rhs, self.m[9] * rhs, self.m[10] * rhs, self.m[11] * rhs,
307                self.m[12] * rhs, self.m[13] * rhs, self.m[14] * rhs, self.m[15] * rhs
308            ]
309        }
310    }
311}
312
313impl std::fmt::Display for Matrix4x4 {
314    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
315        write!(f, "{{\n\t[{}, {}, {}, {}]\n\t[{}, {}, {}, {}]\n\t[{}, {}, {}, {}]\n\t[{}, {}, {}, {}]\n}}",
316            self.m[0], self.m[1], self.m[2], self.m[3],
317            self.m[4], self.m[5], self.m[6], self.m[7],
318            self.m[8], self.m[9], self.m[10], self.m[11],
319            self.m[12], self.m[13], self.m[14], self.m[15]
320        )
321    }
322}
323
324impl Matrix4x4 {
325
326    /// Creates a new matrix with the given values.
327    /// 
328    /// # Arguments
329    /// 
330    /// * `m00 .. m33` - The values of the matrix.
331    /// 
332    /// # Returns
333    /// 
334    /// A new identity matrix.
335    /// 
336    /// # Example
337    /// 
338    /// ```
339    /// use cgl_rs::math::Matrix4x4;
340    /// 
341    /// let m = Matrix4x4::new(
342    ///    1.0, 0.0, 0.0, 0.0,
343    ///    0.0, 1.0, 0.0, 0.0,
344    ///    0.0, 0.0, 1.0, 0.0,
345    ///    0.0, 0.0, 0.0, 1.0
346    /// );
347    /// 
348    /// println!("{}", m);
349    /// ```
350    pub fn new(
351        m00: f32, m01: f32, m02: f32, m03: f32,
352        m10: f32, m11: f32, m12: f32, m13: f32,
353        m20: f32, m21: f32, m22: f32, m23: f32,
354        m30: f32, m31: f32, m32: f32, m33: f32 
355    ) -> Matrix4x4 {
356        Matrix4x4 {
357            m: [
358                m00, m10, m20, m30,
359                m01, m11, m21, m31,
360                m02, m12, m22, m32,
361                m03, m13, m23, m33
362            ]
363        }
364    }
365
366    /// Creates a new 4x4 matrix from a 3x3 matrix.
367    ///
368    /// # Arguments
369    ///
370    /// * `m` - The 3x3 matrix to convert to a 4x4 matrix.
371    ///
372    /// # Returns
373    ///
374    /// A new 4x4 matrix with the same values as the input 3x3 matrix, with the fourth row and column set to zero.
375    ///
376    /// # Example
377    ///
378    /// ```
379    /// use cgl_rs::math::{Matrix3x3, Matrix4x4};
380    ///
381    /// let m3 = Matrix3x3::new(
382    ///     1.0, 2.0, 3.0,
383    ///     4.0, 5.0, 6.0,
384    ///     7.0, 8.0, 9.0
385    /// );
386    ///
387    /// let m4 = Matrix4x4::from_mat3(&m3);
388    /// ```
389    pub fn from_mat3(m: &Matrix3x3) -> Matrix4x4 {
390        unsafe {
391            CGL_mat4_from_mat3(&m) as Matrix4x4
392        }
393    }
394
395    /// Returns a new matrix with all elements set to zero.
396    ///
397    /// # Returns
398    ///
399    /// A new matrix with all elements set to zero.
400    ///
401    /// # Example
402    ///
403    /// ```
404    /// use cgl_rs::math::Matrix4x4;
405    ///
406    /// let m = Matrix4x4::zero();
407    /// ```
408    pub fn zero() -> Matrix4x4 {
409        unsafe {
410            CGL_mat4_zero_MACRO() as Matrix4x4
411        }
412    }
413
414
415    /// Returns a new identity matrix.
416    ///
417    /// # Returns
418    ///
419    /// A new identity matrix.
420    ///
421    /// # Example
422    ///
423    /// ```
424    /// use cgl_rs::math::Matrix4x4;
425    ///
426    /// let m = Matrix4x4::identity();
427    /// ```
428    pub fn identity() -> Matrix4x4 {
429        unsafe {
430            CGL_mat4_identity_MACRO() as Matrix4x4
431        }
432    }
433
434
435    /// Returns a new scaling matrix.
436    ///
437    /// # Arguments
438    ///
439    /// * `x` - The scaling factor along the x-axis.
440    /// * `y` - The scaling factor along the y-axis.
441    /// * `z` - The scaling factor along the z-axis.
442    ///
443    /// # Returns
444    ///
445    /// A new scaling matrix.
446    ///
447    /// # Example
448    ///
449    /// ```
450    /// use cgl_rs::math::Matrix4x4;
451    ///
452    /// let m = Matrix4x4::scale(2.0, 3.0, 4.0);
453    /// ```
454    pub fn scale(x: f32, y: f32, z: f32) -> Matrix4x4 {
455        unsafe {
456            CGL_mat4_scale_MACRO(x, y, z) as Matrix4x4
457        }
458    }
459
460
461    /// Returns a new translation matrix.
462    ///
463    /// # Arguments
464    ///
465    /// * `x` - The translation along the x-axis.
466    /// * `y` - The translation along the y-axis.
467    /// * `z` - The translation along the z-axis.
468    ///
469    /// # Returns
470    ///
471    /// A new translation matrix.
472    /// 
473    /// # Example
474    ///
475    /// ```
476    /// use cgl_rs::math::Matrix4x4;
477    ///
478    /// let m = Matrix4x4::translate(1.0, 2.0, 3.0);
479    /// ```
480    pub fn translate(x: f32, y: f32, z: f32) -> Matrix4x4 {
481        unsafe {
482            CGL_mat4_translate_MACRO(x, y, z) as Matrix4x4
483        }
484    }
485
486
487    /// Returns a new rotation matrix around the x-axis.
488    ///
489    /// # Arguments
490    ///
491    /// * `angle` - The angle of rotation in radians.
492    ///
493    /// # Returns
494    ///
495    /// A new rotation matrix around the x-axis.
496    ///
497    /// # Example
498    ///
499    /// ```
500    /// use cgl_rs::math::Matrix4x4;
501    ///
502    /// let m = Matrix4x4::rotate_x(0.5);
503    /// ```
504    pub fn rotate_x(angle: f32) -> Matrix4x4 {
505        unsafe {
506            CGL_mat4_rotate_x_MACRO(angle) as Matrix4x4
507        }
508    }
509
510    /// Returns a new rotation matrix around the y-axis.
511    ///
512    /// # Arguments
513    ///
514    /// * `angle` - The angle of rotation in radians.
515    ///
516    /// # Returns
517    ///
518    /// A new rotation matrix around the y-axis.
519    ///
520    /// # Example
521    ///
522    /// ```
523    /// use cgl_rs::math::Matrix4x4;
524    ///
525    /// let m = Matrix4x4::rotate_y(0.5);
526    /// ```
527    pub fn rotate_y(angle: f32) -> Matrix4x4 {
528        unsafe {
529            CGL_mat4_rotate_y_MACRO(angle) as Matrix4x4
530        }
531    }
532
533
534    /// Returns a new rotation matrix around the z-axis.
535    ///
536    /// # Arguments
537    ///
538    /// * `angle` - The angle of rotation in radians.
539    ///
540    /// # Returns
541    ///
542    /// A new rotation matrix around the z-axis.
543    ///
544    /// # Example
545    ///
546    /// ```
547    /// use cgl_rs::math::Matrix4x4;
548    ///
549    /// let m = Matrix4x4::rotate_z(0.5);
550    /// ```
551    pub fn rotate_z(angle: f32) -> Matrix4x4 {
552        unsafe {
553            CGL_mat4_rotate_z_MACRO(angle) as Matrix4x4
554        }
555    }
556
557
558    /// Returns a new rotation matrix that rotates around the given axis by the specified angle.
559    ///
560    /// # Arguments
561    ///
562    /// * `axis` - The axis to rotate around.
563    /// * `angle` - The angle of rotation in radians.
564    ///
565    /// # Returns
566    ///
567    /// A new rotation matrix that rotates around the given axis by the specified angle.
568    /// 
569    /// # Example
570    ///
571    /// ```
572    /// use cgl_rs::math::{Matrix4x4, Vector3};
573    ///
574    /// let axis = Vector3::new(1.0, 0.0, 0.0);
575    /// let m = Matrix4x4::rotate_about_axis(&axis, 0.5);
576    /// ```
577    pub fn rotate_about_axis(axis: &Vector3, angle: f32) -> Matrix4x4 {
578        unsafe {
579            CGL_mat4_rotate_about_axis(axis, angle) as Matrix4x4
580        }
581    }
582
583
584
585
586
587    /// Returns a new perspective projection matrix.
588    ///
589    /// # Arguments
590    ///
591    /// * `fov` - The field of view angle in radians.
592    /// * `aspect` - The aspect ratio of the projection.
593    /// * `near` - The distance to the near clipping plane.
594    /// * `far` - The distance to the far clipping plane.
595    ///
596    /// # Returns
597    ///
598    /// A new perspective projection matrix.
599    ///
600    /// # Example
601    ///
602    /// ```
603    /// use cgl_rs::math::Matrix4x4;
604    /// 
605    /// let m = Matrix4x4::perspective(cgl_rs::math::constants::PI_2, 16.0/9.0, 0.1, 100.0);
606    /// ```
607    pub fn perspective(fov: f32, aspect: f32, near: f32, far: f32) -> Matrix4x4 {
608        unsafe {
609            CGL_mat4_perspective_MACRO(fov, aspect, near, far) as Matrix4x4
610        }
611    }
612
613
614    /// Returns a new orthographic projection matrix.
615    ///
616    /// # Arguments
617    ///
618    /// * `left` - The coordinate for the left vertical clipping plane.
619    /// * `right` - The coordinate for the right vertical clipping plane.
620    /// * `bottom` - The coordinate for the bottom horizontal clipping plane.
621    /// * `top` - The coordinate for the top horizontal clipping plane.
622    /// * `near` - The distance to the near clipping plane.
623    /// * `far` - The distance to the far clipping plane.
624    ///
625    /// # Returns
626    ///
627    /// A new orthographic projection matrix.
628    ///
629    /// # Example
630    ///
631    /// ```
632    /// use cgl_rs::math::Matrix4x4;
633    ///
634    /// let m = Matrix4x4::orthographic(-1.0, 1.0, -1.0, 1.0, 0.1, 100.0);
635    /// ```
636    pub fn orthographic(left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32) -> Matrix4x4 {
637        unsafe {
638            CGL_mat4_orthographic_MACRO(left, right, bottom, top, near, far) as Matrix4x4
639        }
640    }
641
642
643    /// Returns a new view matrix that looks from the eye position towards the target position.
644    ///
645    /// # Arguments
646    ///
647    /// * `eye` - The position of the camera.
648    /// * `target` - The position to look at.
649    /// * `up` - The up direction of the camera.
650    ///
651    /// # Returns
652    ///
653    /// A new view matrix.
654    ///
655    /// # Example
656    ///
657    /// ```
658    /// use cgl_rs::math::{Matrix4x4, Vector3};
659    ///
660    /// let mat = Matrix4x4::look_at(
661    ///    Vector3::new(0.0, 0.0, 0.0),
662    ///    Vector3::new(0.0, 0.0, -1.0),
663    ///    Vector3::new(0.0, 1.0, 0.0)
664    /// );
665    /// ```
666    pub fn look_at(eye: Vector3, target: Vector3, up: Vector3) -> Matrix4x4 {
667        unsafe {
668            CGL_mat4_look_at(eye, target, up) as Matrix4x4
669        }
670    }
671
672    /// Multiplies this matrix by another matrix and returns the result.
673    ///
674    /// # Arguments
675    ///
676    /// * `other` - The matrix to multiply by.
677    ///
678    /// # Returns
679    ///
680    /// The resulting matrix of the multiplication.
681    ///
682    /// # Example
683    ///
684    /// ```
685    /// use cgl_rs::math::Matrix4x4;
686    ///
687    /// let m1 = Matrix4x4::identity();
688    /// let m2 = Matrix4x4::rotate_z(0.5);
689    /// let m3 = m1.mul(&m2);
690    /// ```
691    pub fn mul(&self, other: &Matrix4x4) -> Matrix4x4 {
692        unsafe {
693            CGL_mat4_mul(self, other) as Matrix4x4
694        }
695    }
696
697    /// Calculates the determinant of this matrix.
698    ///
699    /// # Returns
700    ///
701    /// The determinant of this matrix.
702    ///
703    /// # Example
704    ///
705    /// ```
706    /// use cgl_rs::math::Matrix4x4;
707    ///
708    /// let m = Matrix4x4::identity();
709    /// let det = m.determinant();
710    /// ```
711    pub fn determinant(&self) -> f32 {
712        unsafe {
713            CGL_mat4_det(self)
714        }
715    }
716
717    /// Multiplies this matrix by a vector and returns the result.
718    ///
719    /// # Arguments
720    ///
721    /// * `other` - The vector to multiply by.
722    ///
723    /// # Returns
724    ///
725    /// The resulting vector of the multiplication.
726    ///
727    /// # Example
728    ///
729    /// ```
730    /// use cgl_rs::math::{Matrix4x4, Vector4};
731    ///
732    /// let m = Matrix4x4::identity();
733    /// let v = Vector4::new(1.0, 2.0, 3.0, 1.0);
734    /// let result = m.mul_vec4(&v);
735    /// ```
736    pub fn mul_vec4(&self, other: &Vector4) -> Vector4 {
737        unsafe {
738            CGL_mat4_mul_vec4(self, other) as Vector4
739        }
740    }
741
742    /// Calculates the inverse of this matrix.
743    ///
744    /// # Returns
745    ///
746    /// The inverse of this matrix.
747    ///
748    /// # Example
749    ///
750    /// ```
751    /// use cgl_rs::math::Matrix4x4;
752    ///
753    /// let m = Matrix4x4::identity();
754    /// let inv = m.inverse();
755    /// ```
756    pub fn inverse(&self) -> Matrix4x4 {
757        unsafe {
758            CGL_mat4_inverse(self) as Matrix4x4
759        }
760    }
761
762    /// Transposes this matrix.
763    ///
764    /// # Returns
765    ///
766    /// The transposed matrix.
767    ///
768    /// # Example
769    ///
770    /// ```
771    /// use cgl_rs::math::Matrix4x4;
772    ///
773    /// let m = Matrix4x4::identity();
774    /// let transposed = m.transpose();
775    /// ```
776    pub fn transpose(&self) -> Matrix4x4 {
777        unsafe {
778            CGL_mat4_transpose(self) as Matrix4x4
779        }
780    }
781
782    /// Calculates the adjoint of this matrix.
783    ///
784    /// # Returns
785    ///
786    /// The adjoint of this matrix.
787    ///
788    /// # Example
789    ///
790    /// ```
791    /// use cgl_rs::math::Matrix4x4;
792    ///
793    /// let m = Matrix4x4::identity();
794    /// let adj = m.adjoint();
795    /// ```
796    pub fn adjoint(&self) -> Matrix4x4 {
797        unsafe {
798            CGL_mat4_adjoint(self) as Matrix4x4
799        }
800    }
801
802
803    /// Performs Gaussian elimination on this matrix.
804    ///
805    /// # Returns
806    ///
807    /// The matrix in row echelon form.
808    ///
809    /// # Example
810    ///
811    /// ```
812    /// use cgl_rs::math::Matrix4x4;
813    ///
814    /// let m = Matrix4x4::identity();
815    /// let row_echelon = m.gaussian_elimination();
816    /// ```
817    pub fn gaussian_elimination(&self) -> Matrix4x4 {
818        unsafe {
819            CGL_mat4_gauss_elim(self) as Matrix4x4
820        }
821    }
822
823    /// Calculates the rank of this matrix.
824    ///
825    /// # Returns
826    ///
827    /// The rank of this matrix.
828    ///
829    /// # Example
830    ///
831    /// ```
832    /// use cgl_rs::math::Matrix4x4;
833    ///
834    /// let m = Matrix4x4::identity();
835    /// let rank = m.rank();
836    /// ```
837    pub fn rank(&self) -> i32 {
838        unsafe {
839            CGL_mat4_rank(self)
840        }
841    }
842
843    /// Calculates the trace of this matrix.
844    ///
845    /// # Returns
846    ///
847    /// The trace of this matrix.
848    ///
849    /// # Example
850    ///
851    /// ```
852    /// use cgl_rs::math::Matrix4x4;
853    ///
854    /// let m = Matrix4x4::identity();
855    /// let trace = m.trace();
856    /// ```
857    pub fn trace(&self) -> f32 {
858        unsafe {
859            CGL_mat4_trace(self)
860        }
861    }
862
863    /// Converts this Matrix4x4 to a Matrix3x3 by discarding the last row and column.
864    ///
865    /// # Example
866    ///
867    /// ```
868    /// use cgl_rs::math::{Matrix3x3, Matrix4x4};
869    ///
870    /// let m = Matrix4x4::identity();
871    /// let m3 = m.to_mat3();
872    /// ```
873    pub fn to_mat3(&self) -> Matrix3x3 {
874        unsafe {
875            CGL_mat4_to_mat3(self) as Matrix3x3
876        }
877    }
878
879    /// Decomposes this matrix into lower and upper triangular matrices using LU decomposition.
880    ///
881    /// # Returns
882    ///
883    /// A tuple containing the lower and upper triangular matrices.
884    ///
885    /// # Example
886    ///
887    /// ```
888    /// use cgl_rs::math::Matrix4x4;
889    ///
890    /// let m = Matrix4x4::identity();
891    /// let (l, u) = m.decompose_lu();
892    /// ```
893    pub fn decompose_lu(&self) -> (Matrix4x4, Matrix4x4) {
894        unsafe {
895            let mut l = Matrix4x4::identity();
896            let mut u = Matrix4x4::identity();
897            CGL_mat4_decompose_lu(self, &mut l, &mut u);
898            (l, u)
899        }
900    }
901
902    /// Performs a linear interpolation between this matrix and another matrix.
903    ///
904    /// # Arguments
905    ///
906    /// * `other` - The other matrix to interpolate with.
907    /// * `t` - The interpolation factor. Should be between 0.0 and 1.0.
908    ///
909    /// # Returns
910    ///
911    /// The interpolated matrix.
912    ///
913    /// # Example
914    ///
915    /// ```
916    /// use cgl_rs::math::Matrix4x4;
917    ///
918    /// let m1 = Matrix4x4::identity();
919    /// let m2 = Matrix4x4::scale(1.0, 2.0, 3.0);
920    /// let m3 = m1.lerp(&m2, 0.5);
921    /// ```
922    pub fn lerp(&self, other: &Matrix4x4, t: f32) -> Matrix4x4 {
923        unsafe {
924            CGL_mat4_lerp(self, other, t) as Matrix4x4
925        }
926    }
927
928
929}