1use num_traits::One;
25
26use crate::basenum::BaseFloat;
27use crate::vec::vec::{Vector2, Vector3, Vector4};
28
29use super::mat::*;
30use super::traits::{GenMat, GenSquareMat};
31
32impl<T: BaseFloat> One for Matrix2<T> {
33 #[inline]
34 fn one() -> Matrix2<T> {
35 let y = T::one();
36 let l = T::zero();
37 Matrix2::new(Vector2::new(y, l), Vector2::new(l, y))
38 }
39}
40
41impl<T: BaseFloat> GenSquareMat<T, Vector2<T>> for Matrix2<T> {
42 #[inline(always)]
43 fn determinant(&self) -> T {
44 self[0][0] * self[1][1] - self[0][1] * self[1][0]
45 }
46 #[inline]
47 fn inverse(&self) -> Option<Matrix2<T>> {
48 let det = self.determinant();
49 let ling = T::zero();
50 if det.is_approx_eq(&ling) {
51 None
52 } else {
53 let inv_det = det.recip();
54 let m = Matrix2::new(
55 Vector2::new(self[1][1] * inv_det, -self[0][1] * inv_det),
56 Vector2::new(-self[1][0] * inv_det, self[0][0] * inv_det),
57 );
58 Some(m)
59 }
60 }
61}
62
63impl<T: BaseFloat> One for Matrix3<T> {
64 #[inline]
65 fn one() -> Matrix3<T> {
66 let y = T::one();
67 let l = T::zero();
68 Matrix3::new(
69 Vector3::new(y, l, l),
70 Vector3::new(l, y, l),
71 Vector3::new(l, l, y),
72 )
73 }
74}
75
76impl<T: BaseFloat> GenSquareMat<T, Vector3<T>> for Matrix3<T> {
77 #[inline]
78 fn determinant(&self) -> T {
79 self[0][0] * (self[1][1] * self[2][2] - self[2][1] * self[1][2])
80 - self[1][0] * (self[0][1] * self[2][2] - self[2][1] * self[0][2])
81 + self[2][0] * (self[0][1] * self[1][2] - self[1][1] * self[0][2])
82 }
83 #[inline]
84 fn inverse(&self) -> Option<Matrix3<T>> {
85 let det = self.determinant();
86 let ling = T::zero();
87 if det.is_approx_eq(&ling) {
88 None
89 } else {
90 let inv_det = det.recip();
91 let r11 = self[1][1] * self[2][2] - self[2][1] * self[1][2];
92 let r12 = self[2][0] * self[1][2] - self[1][0] * self[2][2];
93 let r13 = self[1][0] * self[2][1] - self[2][0] * self[1][1];
94 let r21 = self[2][1] * self[0][2] - self[0][1] * self[2][2];
95 let r22 = self[0][0] * self[2][2] - self[2][0] * self[0][2];
96 let r23 = self[2][0] * self[0][1] - self[0][0] * self[2][1];
97 let r31 = self[0][1] * self[1][2] - self[1][1] * self[0][2];
98 let r32 = self[1][0] * self[0][2] - self[0][0] * self[1][2];
99 let r33 = self[0][0] * self[1][1] - self[1][0] * self[0][1];
100 let m = Matrix3::new(
101 Vector3::new(r11 * inv_det, r21 * inv_det, r31 * inv_det),
102 Vector3::new(r12 * inv_det, r22 * inv_det, r32 * inv_det),
103 Vector3::new(r13 * inv_det, r23 * inv_det, r33 * inv_det),
104 );
105 Some(m)
106 }
107 }
108}
109
110impl<T: BaseFloat> One for Matrix4<T> {
111 #[inline]
112 fn one() -> Matrix4<T> {
113 let y = T::one();
114 let l = T::zero();
115 Matrix4::new(
116 Vector4::new(y, l, l, l),
117 Vector4::new(l, y, l, l),
118 Vector4::new(l, l, y, l),
119 Vector4::new(l, l, l, y),
120 )
121 }
122}
123
124impl<T: BaseFloat> GenSquareMat<T, Vector4<T>> for Matrix4<T> {
125 #[inline]
126 #[rustfmt::skip]
127 fn determinant(&self) -> T {
128 self[0][0] * (
129 self[1][1] * self[2][2] * self[3][3] +
130 self[2][1] * self[3][2] * self[1][3] +
131 self[3][1] * self[1][2] * self[2][3] -
132 self[3][1] * self[2][2] * self[1][3] -
133 self[1][1] * self[3][2] * self[2][3] -
134 self[2][1] * self[1][2] * self[3][3]
135 ) -
136 self[1][0] * (
137 self[0][1] * self[2][2] * self[3][3] +
138 self[2][1] * self[3][2] * self[0][3] +
139 self[3][1] * self[0][2] * self[2][3] -
140 self[3][1] * self[2][2] * self[0][3] -
141 self[0][1] * self[3][2] * self[2][3] -
142 self[2][1] * self[0][2] * self[3][3]
143 ) +
144 self[2][0] * (
145 self[0][1] * self[1][2] * self[3][3] +
146 self[1][1] * self[3][2] * self[0][3] +
147 self[3][1] * self[0][2] * self[1][3] -
148 self[3][1] * self[1][2] * self[0][3] -
149 self[0][1] * self[3][2] * self[1][3] -
150 self[1][1] * self[0][2] * self[3][3]
151 ) -
152 self[3][0] * (
153 self[0][1] * self[1][2] * self[2][3] +
154 self[1][1] * self[2][2] * self[0][3] +
155 self[2][1] * self[0][2] * self[1][3] -
156 self[2][1] * self[1][2] * self[0][3] -
157 self[0][1] * self[2][2] * self[1][3] -
158 self[1][1] * self[0][2] * self[2][3]
159 )
160 }
161 #[inline]
162 fn inverse(&self) -> Option<Matrix4<T>> {
163 let det = self.determinant();
164 let ling = T::zero();
165 if det.is_approx_eq(&ling) {
166 None
167 } else {
168 let inv_det = det.recip();
169 let tr = self.transpose();
170 let cf = |i, j| -> T {
171 let mat = match i {
172 0 => Matrix3::new(tr.c1.truncate(j), tr.c2.truncate(j), tr.c3.truncate(j)),
173 1 => Matrix3::new(tr.c0.truncate(j), tr.c2.truncate(j), tr.c3.truncate(j)),
174 2 => Matrix3::new(tr.c0.truncate(j), tr.c1.truncate(j), tr.c3.truncate(j)),
175 3 => Matrix3::new(tr.c0.truncate(j), tr.c1.truncate(j), tr.c2.truncate(j)),
176 _ => unreachable!(),
177 };
178 let d = mat.determinant() * inv_det;
179 if (i + j) & 1 == 1 {
180 -d
181 } else {
182 d
183 }
184 };
185 let m = Matrix4::new(
186 Vector4::new(cf(0, 0), cf(0, 1), cf(0, 2), cf(0, 3)),
187 Vector4::new(cf(1, 0), cf(1, 1), cf(1, 2), cf(1, 3)),
188 Vector4::new(cf(2, 0), cf(2, 1), cf(2, 2), cf(2, 3)),
189 Vector4::new(cf(3, 0), cf(3, 1), cf(3, 2), cf(3, 3)),
190 );
191 Some(m)
192 }
193 }
194}
195
196#[cfg(test)]
197mod test {
198 use num_traits::{One, Zero};
199
200 use crate::*;
201
202 #[test]
203 fn test_determinant() {
204 let m2 = mat2(4., 5., 6., 7.);
205 assert_eq!(m2.determinant(), -2.);
206 assert_eq!(Mat3::one().determinant(), 1.);
207 let m4 = mat4(
208 1., 0., 4., 0., 2., 1., 2., 1., 3., 2., 3., 1., 4., 3., 0., 0.,
209 );
210 assert_eq!(m4.determinant(), -7.);
211 assert_eq!((m4 * m4).determinant(), 49.);
212 assert_eq!(Mat4::one().determinant(), 1.);
213 }
214
215 #[test]
216 fn test_inverse_mat2() {
217 let yi = Mat2::one();
218 assert!(yi.inverse().is_some());
219 assert!(DMat2::zero().inverse().is_none());
220 let mat = mat2(1., 3., 2., 4.);
221 let inv = mat.inverse().unwrap();
222 assert_close_to!(mat * inv, yi, 0.000001);
223 assert_close_to!(inv * mat, yi, 0.000001);
224 let m2 = mat2(1., 2., 2., 4.);
225 assert!(m2.inverse().is_none());
226 }
227
228 #[test]
229 fn test_inverse_mat3() {
230 let yi = Mat3::one();
231 assert!(yi.inverse().is_some());
232 assert_eq!(yi.inverse().unwrap(), yi);
233 assert!(DMat3::zero().inverse().is_none());
234 let mat = mat3(5., 7., 11., -6., 9., 2., 1., 13., 0.);
235 let inv = mat.inverse().unwrap();
236 assert_close_to!(mat * inv, yi, 0.000001);
237 assert_close_to!(inv * mat, yi, 0.000001);
238 }
239
240 #[test]
241 #[rustfmt::skip]
242 fn test_inverse_mat4() {
243 let mat = mat4(
244 1., 0., 4., 0.,
245 2., 1., 2., 1.,
246 3., 2., 3., 1.,
247 4., 3., 0., 0.,
248 );
249 let invm = mat4(
250 3./7., 12./7., -12./7., 4./7.,
251 -4./7., -16./7., 16./7., -3./7.,
252 1./7., -3./7., 3./7., -1./7.,
253 -4./7., 5./7., 2./7., -3./7.,
254 );
255 assert_approx_eq!(mat.inverse().unwrap(), invm);
256 assert_close_to!(mat.inverse().unwrap().inverse().unwrap(), mat, 0.000001);
257 assert!(Mat4::one().inverse().is_some());
258 }
259}