Skip to main content

cvmath/mat/
mat3.rs

1/*!
2Mat3 transformation matrix.
3*/
4
5use super::*;
6
7/// 3D transformation matrix.
8///
9/// Each field _a_<sub>i</sub><sub>j</sub> represents the _i_-th row and _j_-th column of the matrix.
10///
11/// Row-major storage with column-major semantics.
12///
13/// Stored in row-major order (fields appear in reading order),
14/// but interpreted as column-major: each column is a transformed basis vector,
15/// and matrices are applied to column vectors via `mat * vec`.
16#[derive(Copy, Clone, Default, PartialEq)]
17#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
18#[repr(C)]
19pub struct Mat3<T> {
20	pub a11: T, pub a12: T, pub a13: T,
21	pub a21: T, pub a22: T, pub a23: T,
22	pub a31: T, pub a32: T, pub a33: T,
23}
24
25/// Mat3 constructor.
26#[allow(non_snake_case)]
27#[inline]
28pub const fn Mat3<T>(
29	a11: T, a12: T, a13: T,
30	a21: T, a22: T, a23: T,
31	a31: T, a32: T, a33: T,
32) -> Mat3<T> {
33	Mat3 { a11, a12, a13, a21, a22, a23, a31, a32, a33 }
34}
35
36#[cfg(feature = "dataview")]
37unsafe impl<T: dataview::Pod> dataview::Pod for Mat3<T> {}
38
39//----------------------------------------------------------------
40// Constructors
41
42impl<T> Mat3<T> {
43	/// Constructs a new matrix from components.
44	#[inline]
45	pub const fn new(
46		a11: T, a12: T, a13: T,
47		a21: T, a22: T, a23: T,
48		a31: T, a32: T, a33: T,
49	) -> Mat3<T> {
50		Mat3 {
51			a11, a12, a13,
52			a21, a22, a23,
53			a31, a32, a33,
54		}
55	}
56}
57
58impl<T: Zero> Mat3<T> {
59	/// Zero matrix.
60	pub const ZERO: Mat3<T> = Mat3 {
61		a11: T::ZERO, a12: T::ZERO, a13: T::ZERO,
62		a21: T::ZERO, a22: T::ZERO, a23: T::ZERO,
63		a31: T::ZERO, a32: T::ZERO, a33: T::ZERO,
64	};
65}
66
67impl<T: Zero + One> Mat3<T> {
68	/// Identity matrix.
69	pub const IDENTITY: Mat3<T> = Mat3 {
70		a11: T::ONE,  a12: T::ZERO, a13: T::ZERO,
71		a21: T::ZERO, a22: T::ONE,  a23: T::ZERO,
72		a31: T::ZERO, a32: T::ZERO, a33: T::ONE,
73	};
74}
75
76impl<T: Float> Mat3<T> {
77	/// Scaling matrix.
78	///
79	/// ```
80	/// let mat = cvmath::Mat3::scaling(cvmath::Vec3(2.0, 3.0, 4.0));
81	/// let value = mat * cvmath::Vec3(4.0, 5.0, 6.0);
82	/// let expected = cvmath::Vec3(8.0, 15.0, 24.0);
83	/// assert_eq!(expected, value);
84	/// ```
85	#[inline]
86	pub fn scaling(scale: Vec3<T>) -> Mat3<T> {
87		let Vec3 { x: a11, y: a22, z: a33 } = scale;
88		Mat3 { a11, a22, a33, ..Mat3::IDENTITY }
89	}
90
91	/// Rotation matrix around an axis.
92	///
93	/// ```
94	/// let mat = cvmath::Mat3::rotation(cvmath::Vec3::Z, cvmath::Angle::deg(90.0));
95	/// let value = (mat * cvmath::Vec3(1.0f64, 1.0, 1.0)).cast::<f32>();
96	/// let expected = cvmath::Vec3(-1.0f32, 1.0, 1.0);
97	/// assert_eq!(expected, value);
98	/// ```
99	#[inline]
100	pub fn rotation(axis: Vec3<T>, angle: Angle<T>) -> Mat3<T> {
101		let (s, c) = angle.sin_cos();
102		let Vec3 { x, y, z } = axis;
103		let t = T::ONE - c;
104		Mat3 {
105			a11: t * x * x + c,     a12: t * x * y - s * z, a13: t * x * z + s * y,
106			a21: t * x * y + s * z, a22: t * y * y + c,     a23: t * y * z - s * x,
107			a31: t * x * z - s * y, a32: t * y * z + s * x, a33: t * z * z + c,
108		}
109	}
110
111	/// Returns the shortest rotation that aligns vector `from` with vector `to`.
112	///
113	/// The resulting matrix `R` satisfies:
114	///
115	/// ```text
116	/// R * from = to
117	/// ```
118	///
119	/// Both vectors are expected to be normalized.
120	/// The implementation avoids trigonometric functions.
121	///
122	/// This produces the minimal rotation between the two directions.
123	/// The behavior is undefined if `from` and `to` are opposite (180° apart), or if either vector is zero-length,
124	/// since the rotation axis is not uniquely defined.
125	///
126	/// This is useful for constructing an orientation matrix that points one direction vector toward another.
127	///
128	/// ```
129	/// let from = cvmath::Vec3(1.0, 0.0, 0.0);
130	/// let to = cvmath::Vec3(0.0, 1.0, 0.0);
131	/// let mat = cvmath::Mat3::rotation_between(from, to);
132	/// let value = (mat * from).cast::<f32>();
133	/// let expected = to.cast::<f32>();
134	/// assert_eq!(expected, value);
135	/// ```
136	#[inline]
137	pub fn rotation_between(from: Vec3<T>, to: Vec3<T>) -> Mat3<T> {
138		let Vec3 { x, y, z } = from.cross(to);
139		let c = from.dot(to);
140		let k = T::ONE / (T::ONE + c);
141		Mat3 {
142			a11: x * x * k + c, a12: x * y * k - z, a13: x * z * k + y,
143			a21: y * x * k + z, a22: y * y * k + c, a23: y * z * k - x,
144			a31: z * x * k - y, a32: z * y * k + x, a33: z * z * k + c,
145		}
146	}
147}
148
149impl<T: Zero + One> From<Transform2<T>> for Mat3<T> {
150	#[inline]
151	fn from(mat: Transform2<T>) -> Mat3<T> {
152		Mat3 {
153			a11: mat.a11, a12: mat.a12, a13: mat.a13,
154			a21: mat.a21, a22: mat.a22, a23: mat.a23,
155			..Mat3::IDENTITY
156		}
157	}
158}
159
160//----------------------------------------------------------------
161// Conversions
162
163impl<T> Mat3<T> {
164	/// Converts to a Mat2 matrix.
165	///
166	/// ```
167	/// let value = cvmath::Mat3(1, 2, 3, 4, 5, 6, 7, 8, 9).mat2();
168	/// let expected = cvmath::Mat2(1, 2, 4, 5);
169	/// assert_eq!(expected, value);
170	/// ```
171	#[inline]
172	pub fn mat2(self) -> Mat2<T> {
173		Mat2 {
174			a11: self.a11, a12: self.a12,
175			a21: self.a21, a22: self.a22,
176		}
177	}
178	/// Converts to a Transform3 matrix.
179	///
180	/// ```
181	/// let mat = cvmath::Mat3(1, 2, 3, 4, 5, 6, 7, 8, 9).transform3();
182	/// let value = mat.into_row_major();
183	/// let expected = [[1, 2, 3, 0], [4, 5, 6, 0], [7, 8, 9, 0]];
184	/// assert_eq!(expected, value);
185	/// ```
186	#[inline]
187	pub fn transform3(self) -> Transform3<T> where T: Zero {
188		Transform3 {
189			a11: self.a11, a12: self.a12, a13: self.a13, a14: T::ZERO,
190			a21: self.a21, a22: self.a22, a23: self.a23, a24: T::ZERO,
191			a31: self.a31, a32: self.a32, a33: self.a33, a34: T::ZERO,
192		}
193	}
194	/// Adds a translation to the matrix.
195	///
196	/// ```
197	/// let mat = cvmath::Mat3::IDENTITY.translate(cvmath::Vec3(5, 6, 7));
198	/// let value = mat.into_row_major();
199	/// let expected = [[1, 0, 0, 5], [0, 1, 0, 6], [0, 0, 1, 7]];
200	/// assert_eq!(expected, value);
201	/// ```
202	#[inline]
203	pub fn translate(self, trans: Vec3<T>) -> Transform3<T> {
204		let Vec3 { x: a14, y: a24, z: a34 } = trans;
205		Transform3 {
206			a11: self.a11, a12: self.a12, a13: self.a13, a14,
207			a21: self.a21, a22: self.a22, a23: self.a23, a24,
208			a31: self.a31, a32: self.a32, a33: self.a33, a34,
209		}
210	}
211}
212
213impl<T> Mat3<T> {
214	#[inline]
215	fn as_array(&self) -> &[T; 9] {
216		unsafe { mem::transmute(self) }
217	}
218	/// Imports the matrix from a row-major layout.
219	///
220	/// ```
221	/// let mat = cvmath::Mat3::from_row_major([[1, 2, 3], [4, 5, 6], [7, 8, 9]]);
222	/// let expected = cvmath::Mat3(1, 2, 3, 4, 5, 6, 7, 8, 9);
223	/// assert_eq!(expected, mat);
224	/// ```
225	#[inline]
226	pub fn from_row_major(mat: [[T; 3]; 3]) -> Mat3<T> {
227		let [[a11, a12, a13], [a21, a22, a23], [a31, a32, a33]] = mat;
228		Mat3 {
229			a11, a12, a13,
230			a21, a22, a23,
231			a31, a32, a33,
232		}
233	}
234	/// Imports the matrix from a column-major layout.
235	///
236	/// ```
237	/// let mat = cvmath::Mat3::from_column_major([[1, 4, 7], [2, 5, 8], [3, 6, 9]]);
238	/// let expected = cvmath::Mat3(1, 2, 3, 4, 5, 6, 7, 8, 9);
239	/// assert_eq!(expected, mat);
240	/// ```
241	#[inline]
242	pub fn from_column_major(mat: [[T; 3]; 3]) -> Mat3<T> {
243		let [[a11, a21, a31], [a12, a22, a32], [a13, a23, a33]] = mat;
244		Mat3 {
245			a11, a12, a13,
246			a21, a22, a23,
247			a31, a32, a33,
248		}
249	}
250	/// Exports the matrix as a row-major array.
251	///
252	/// ```
253	/// let value = cvmath::Mat3(1, 2, 3, 4, 5, 6, 7, 8, 9).into_row_major();
254	/// let expected = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
255	/// assert_eq!(expected, value);
256	/// ```
257	#[inline]
258	pub fn into_row_major(self) -> [[T; 3]; 3] {
259		[
260			[self.a11, self.a12, self.a13],
261			[self.a21, self.a22, self.a23],
262			[self.a31, self.a32, self.a33],
263		]
264	}
265	/// Exports the matrix as a column-major array.
266	///
267	/// ```
268	/// let value = cvmath::Mat3(1, 2, 3, 4, 5, 6, 7, 8, 9).into_column_major();
269	/// let expected = [[1, 4, 7], [2, 5, 8], [3, 6, 9]];
270	/// assert_eq!(expected, value);
271	/// ```
272	#[inline]
273	pub fn into_column_major(self) -> [[T; 3]; 3] {
274		[
275			[self.a11, self.a21, self.a31],
276			[self.a12, self.a22, self.a32],
277			[self.a13, self.a23, self.a33],
278		]
279	}
280}
281
282//----------------------------------------------------------------
283// Decomposition
284
285impl<T> Mat3<T> {
286	/// Composes the matrix from basis vectors.
287	///
288	/// ```
289	/// let mat = cvmath::Mat3::compose(cvmath::Vec3(1, 2, 3), cvmath::Vec3(4, 5, 6), cvmath::Vec3(7, 8, 9));
290	/// let value = mat.into_row_major();
291	/// let expected = [[1, 4, 7], [2, 5, 8], [3, 6, 9]];
292	/// assert_eq!(expected, value);
293	/// ```
294	#[inline]
295	pub fn compose(x: Vec3<T>, y: Vec3<T>, z: Vec3<T>) -> Mat3<T> {
296		Mat3 {
297			a11: x.x, a12: y.x, a13: z.x,
298			a21: x.y, a22: y.y, a23: z.y,
299			a31: x.z, a32: y.z, a33: z.z,
300		}
301	}
302	/// Gets the transformed X basis vector.
303	///
304	/// ```
305	/// let value = cvmath::Mat3(1, 2, 3, 4, 5, 6, 7, 8, 9).x();
306	/// let expected = cvmath::Vec3(1, 4, 7);
307	/// assert_eq!(expected, value);
308	/// ```
309	#[inline]
310	pub fn x(self) -> Vec3<T> {
311		Vec3 { x: self.a11, y: self.a21, z: self.a31 }
312	}
313	/// Gets the transformed Y basis vector.
314	///
315	/// ```
316	/// let value = cvmath::Mat3(1, 2, 3, 4, 5, 6, 7, 8, 9).y();
317	/// let expected = cvmath::Vec3(2, 5, 8);
318	/// assert_eq!(expected, value);
319	/// ```
320	#[inline]
321	pub fn y(self) -> Vec3<T> {
322		Vec3 { x: self.a12, y: self.a22, z: self.a32 }
323	}
324	/// Gets the transformed Z basis vector.
325	///
326	/// ```
327	/// let value = cvmath::Mat3(1, 2, 3, 4, 5, 6, 7, 8, 9).z();
328	/// let expected = cvmath::Vec3(3, 6, 9);
329	/// assert_eq!(expected, value);
330	/// ```
331	#[inline]
332	pub fn z(self) -> Vec3<T> {
333		Vec3 { x: self.a13, y: self.a23, z: self.a33 }
334	}
335}
336
337//----------------------------------------------------------------
338// Operations
339
340impl<T: Scalar> Mat3<T> {
341	/// Computes the determinant.
342	///
343	/// ```
344	/// let value = cvmath::Mat3::scaling(cvmath::Vec3(2.0, 3.0, 4.0)).det();
345	/// assert_eq!(24.0, value);
346	/// ```
347	#[inline]
348	pub fn det(self) -> T {
349		self.a11 * (self.a22 * self.a33 - self.a23 * self.a32) +
350		self.a12 * (self.a23 * self.a31 - self.a21 * self.a33) +
351		self.a13 * (self.a21 * self.a32 - self.a22 * self.a31)
352	}
353	/// Computes the trace.
354	///
355	/// ```
356	/// let value = cvmath::Mat3::scaling(cvmath::Vec3(2.0, 3.0, 4.0)).trace();
357	/// assert_eq!(9.0, value);
358	/// ```
359	#[inline]
360	pub fn trace(self) -> T {
361		self.a11 + self.a22 + self.a33
362	}
363	/// Computes the squared Frobenius norm (sum of squares of all matrix elements).
364	///
365	/// This measure is useful for quickly checking matrix magnitude or comparing matrices without the cost of a square root operation.
366	///
367	/// To check if a matrix is effectively zero, test if `flat_norm_sqr()` is below a small epsilon threshold.
368	///
369	/// ```
370	/// let value = cvmath::Mat3::scaling(cvmath::Vec3(2.0, 3.0, 4.0)).flat_norm_sqr();
371	/// assert_eq!(29.0, value);
372	/// ```
373	#[inline]
374	pub fn flat_norm_sqr(self) -> T {
375		self.a11 * self.a11 + self.a12 * self.a12 + self.a13 * self.a13 +
376		self.a21 * self.a21 + self.a22 * self.a22 + self.a23 * self.a23 +
377		self.a31 * self.a31 + self.a32 * self.a32 + self.a33 * self.a33
378	}
379	/// Attempts to invert the matrix.
380	///
381	/// ```
382	/// let value = cvmath::Mat3::scaling(cvmath::Vec3(2.0, 4.0, 8.0)).try_invert();
383	/// let expected = Some(cvmath::Mat3::scaling(cvmath::Vec3(0.5, 0.25, 0.125)));
384	/// assert_eq!(expected, value);
385	/// ```
386	#[inline]
387	pub fn try_invert(self) -> Option<Mat3<T>> where T: Float {
388		let det = self.det();
389		if det == T::ZERO {
390			return None;
391		}
392		Some(self.adjugate() * (T::ONE / det))
393	}
394	/// Computes the inverse matrix.
395	///
396	/// Returns the zero matrix if the determinant is exactly zero.
397	///
398	/// ```
399	/// let value = cvmath::Mat3::scaling(cvmath::Vec3(2.0, 4.0, 8.0)).inverse();
400	/// let expected = cvmath::Mat3::scaling(cvmath::Vec3(0.5, 0.25, 0.125));
401	/// assert_eq!(expected, value);
402	/// ```
403	#[inline]
404	pub fn inverse(self) -> Mat3<T> where T: Float {
405		self.try_invert().unwrap_or(Mat3::ZERO)
406	}
407	/// Returns the transposed matrix.
408	///
409	/// ```
410	/// let mat = cvmath::Mat3(1, 2, 3, 4, 5, 6, 7, 8, 9);
411	/// let value = mat.transpose();
412	/// let expected = cvmath::Mat3(1, 4, 7, 2, 5, 8, 3, 6, 9);
413	/// assert_eq!(expected, value);
414	/// ```
415	#[inline]
416	pub fn transpose(self) -> Mat3<T> {
417		Mat3 {
418			a11: self.a11, a12: self.a21, a13: self.a31,
419			a21: self.a12, a22: self.a22, a23: self.a32,
420			a31: self.a13, a32: self.a23, a33: self.a33,
421		}
422	}
423	/// Computes the adjugate matrix.
424	///
425	/// ```
426	/// let value = cvmath::Mat3::scaling(cvmath::Vec3(2.0, 3.0, 4.0)).adjugate();
427	/// let expected = cvmath::Mat3::scaling(cvmath::Vec3(12.0, 8.0, 6.0));
428	/// assert_eq!(expected, value);
429	/// ```
430	#[inline]
431	pub fn adjugate(self) -> Mat3<T> {
432		Mat3 {
433			a11: self.a22 * self.a33 - self.a23 * self.a32,
434			a12: self.a13 * self.a32 - self.a12 * self.a33,
435			a13: self.a12 * self.a23 - self.a13 * self.a22,
436
437			a21: self.a23 * self.a31 - self.a21 * self.a33,
438			a22: self.a11 * self.a33 - self.a13 * self.a31,
439			a23: self.a13 * self.a21 - self.a11 * self.a23,
440
441			a31: self.a21 * self.a32 - self.a22 * self.a31,
442			a32: self.a12 * self.a31 - self.a11 * self.a32,
443			a33: self.a11 * self.a22 - self.a12 * self.a21,
444		}
445	}
446	/// Linear interpolation between the matrix elements.
447	///
448	/// ```
449	/// let source = cvmath::Mat3::IDENTITY;
450	/// let target = cvmath::Mat3::scaling(cvmath::Vec3(3.0, 5.0, 9.0));
451	/// let value = source.lerp(target, 0.5);
452	/// let expected = cvmath::Mat3(2.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 5.0);
453	/// assert_eq!(expected, value);
454	/// ```
455	#[inline]
456	pub fn lerp(self, rhs: Mat3<T>, t: T) -> Mat3<T> where T: Float {
457		Mat3 {
458			a11: self.a11 + (rhs.a11 - self.a11) * t,
459			a12: self.a12 + (rhs.a12 - self.a12) * t,
460			a13: self.a13 + (rhs.a13 - self.a13) * t,
461			a21: self.a21 + (rhs.a21 - self.a21) * t,
462			a22: self.a22 + (rhs.a22 - self.a22) * t,
463			a23: self.a23 + (rhs.a23 - self.a23) * t,
464			a31: self.a31 + (rhs.a31 - self.a31) * t,
465			a32: self.a32 + (rhs.a32 - self.a32) * t,
466			a33: self.a33 + (rhs.a33 - self.a33) * t,
467		}
468	}
469	/// Applies the transformation around a given origin.
470	///
471	/// ```
472	/// let rotation = cvmath::Mat3::rotation(cvmath::Vec3::Z, cvmath::Angle::deg(90.0));
473	/// let mat = rotation.around(cvmath::Vec3(2.0f64, 3.0, 4.0));
474	/// let value = (mat * cvmath::Vec3(3.0, 3.0, 4.0)).cast::<f32>();
475	/// let expected = cvmath::Vec3(2.0f32, 4.0, 4.0);
476	/// assert_eq!(expected, value);
477	/// ```
478	#[inline]
479	pub fn around(self, origin: Vec3<T>) -> Transform3<T> where T: Float {
480		let to_origin = Transform3::translation(-origin);
481		let from_origin = Transform3::translation(origin);
482		from_origin * self * to_origin
483	}
484}
485
486//----------------------------------------------------------------
487// Operators
488
489impl<T: Copy + ops::Mul<Output = T>> ops::Mul<T> for Mat3<T> {
490	type Output = Mat3<T>;
491	#[inline]
492	fn mul(self, rhs: T) -> Mat3<T> {
493		Mat3 {
494			a11: self.a11 * rhs, a12: self.a12 * rhs, a13: self.a13 * rhs,
495			a21: self.a21 * rhs, a22: self.a22 * rhs, a23: self.a23 * rhs,
496			a31: self.a31 * rhs, a32: self.a32 * rhs, a33: self.a33 * rhs,
497		}
498	}
499}
500impl<T: Copy + ops::MulAssign> ops::MulAssign<T> for Mat3<T> {
501	#[inline]
502	fn mul_assign(&mut self, rhs: T) {
503		self.a11 *= rhs; self.a12 *= rhs; self.a13 *= rhs;
504		self.a21 *= rhs; self.a22 *= rhs; self.a23 *= rhs;
505		self.a31 *= rhs; self.a32 *= rhs; self.a33 *= rhs;
506	}
507}
508
509impl<T: ops::Neg<Output = T>> ops::Neg for Mat3<T> {
510	type Output = Mat3<T>;
511	#[inline]
512	fn neg(self) -> Mat3<T> {
513		Mat3 {
514			a11: -self.a11, a12: -self.a12, a13: -self.a13,
515			a21: -self.a21, a22: -self.a22, a23: -self.a23,
516			a31: -self.a31, a32: -self.a32, a33: -self.a33,
517		}
518	}
519}
520
521impl<T: Copy + ops::Add<Output = T>> ops::Add<Mat3<T>> for Mat3<T> {
522	type Output = Mat3<T>;
523	#[inline]
524	fn add(self, rhs: Mat3<T>) -> Mat3<T> {
525		Mat3 {
526			a11: self.a11 + rhs.a11, a12: self.a12 + rhs.a12, a13: self.a13 + rhs.a13,
527			a21: self.a21 + rhs.a21, a22: self.a22 + rhs.a22, a23: self.a23 + rhs.a23,
528			a31: self.a31 + rhs.a31, a32: self.a32 + rhs.a32, a33: self.a33 + rhs.a33,
529		}
530	}
531}
532impl<T: Copy + ops::AddAssign> ops::AddAssign<Mat3<T>> for Mat3<T> {
533	#[inline]
534	fn add_assign(&mut self, rhs: Mat3<T>) {
535		self.a11 += rhs.a11; self.a12 += rhs.a12; self.a13 += rhs.a13;
536		self.a21 += rhs.a21; self.a22 += rhs.a22; self.a23 += rhs.a23;
537		self.a31 += rhs.a31; self.a32 += rhs.a32; self.a33 += rhs.a33;
538	}
539}
540impl<T: Copy + ops::Sub<Output = T>> ops::Sub<Mat3<T>> for Mat3<T> {
541	type Output = Mat3<T>;
542	#[inline]
543	fn sub(self, rhs: Mat3<T>) -> Mat3<T> {
544		Mat3 {
545			a11: self.a11 - rhs.a11, a12: self.a12 - rhs.a12, a13: self.a13 - rhs.a13,
546			a21: self.a21 - rhs.a21, a22: self.a22 - rhs.a22, a23: self.a23 - rhs.a23,
547			a31: self.a31 - rhs.a31, a32: self.a32 - rhs.a32, a33: self.a33 - rhs.a33,
548		}
549	}
550}
551impl<T: Copy + ops::SubAssign> ops::SubAssign<Mat3<T>> for Mat3<T> {
552	#[inline]
553	fn sub_assign(&mut self, rhs: Mat3<T>) {
554		self.a11 -= rhs.a11; self.a12 -= rhs.a12; self.a13 -= rhs.a13;
555		self.a21 -= rhs.a21; self.a22 -= rhs.a22; self.a23 -= rhs.a23;
556		self.a31 -= rhs.a31; self.a32 -= rhs.a32; self.a33 -= rhs.a33;
557	}
558}
559
560impl<T: Copy + ops::Add<Output = T> + ops::Mul<Output = T>> ops::Mul<Vec3<T>> for Mat3<T> {
561	type Output = Vec3<T>;
562	#[inline]
563	fn mul(self, rhs: Vec3<T>) -> Vec3<T> {
564		Vec3 {
565			x: self.a11 * rhs.x + self.a12 * rhs.y + self.a13 * rhs.z,
566			y: self.a21 * rhs.x + self.a22 * rhs.y + self.a23 * rhs.z,
567			z: self.a31 * rhs.x + self.a32 * rhs.y + self.a33 * rhs.z,
568		}
569	}
570}
571
572impl<T: Copy + ops::Add<Output = T> + ops::Mul<Output = T>> ops::Mul<Mat3<T>> for Mat3<T> {
573	type Output = Mat3<T>;
574	#[inline]
575	fn mul(self, rhs: Mat3<T>) -> Mat3<T> {
576		Mat3 {
577			a11: self.a11 * rhs.a11 + self.a12 * rhs.a21 + self.a13 * rhs.a31,
578			a12: self.a11 * rhs.a12 + self.a12 * rhs.a22 + self.a13 * rhs.a32,
579			a13: self.a11 * rhs.a13 + self.a12 * rhs.a23 + self.a13 * rhs.a33,
580
581			a21: self.a21 * rhs.a11 + self.a22 * rhs.a21 + self.a23 * rhs.a31,
582			a22: self.a21 * rhs.a12 + self.a22 * rhs.a22 + self.a23 * rhs.a32,
583			a23: self.a21 * rhs.a13 + self.a22 * rhs.a23 + self.a23 * rhs.a33,
584
585			a31: self.a31 * rhs.a11 + self.a32 * rhs.a21 + self.a33 * rhs.a31,
586			a32: self.a31 * rhs.a12 + self.a32 * rhs.a22 + self.a33 * rhs.a32,
587			a33: self.a31 * rhs.a13 + self.a32 * rhs.a23 + self.a33 * rhs.a33,
588		}
589	}
590}
591impl<T: Copy + ops::Add<Output = T> + ops::Mul<Output = T>> ops::MulAssign<Mat3<T>> for Mat3<T> {
592	#[inline]
593	fn mul_assign(&mut self, rhs: Mat3<T>) {
594		*self = *self * rhs;
595	}
596}
597
598impl<T: Copy + ops::Add<Output = T> + ops::Mul<Output = T>> ops::Mul<Transform2<T>> for Mat3<T> {
599	type Output = Mat3<T>;
600	#[inline]
601	fn mul(self, rhs: Transform2<T>) -> Mat3<T> {
602		Mat3 {
603			a11: self.a11 * rhs.a11 + self.a12 * rhs.a21,
604			a12: self.a11 * rhs.a12 + self.a12 * rhs.a22,
605			a13: self.a11 * rhs.a13 + self.a12 * rhs.a23 + self.a13,
606
607			a21: self.a21 * rhs.a11 + self.a22 * rhs.a21,
608			a22: self.a21 * rhs.a12 + self.a22 * rhs.a22,
609			a23: self.a21 * rhs.a13 + self.a22 * rhs.a23 + self.a23,
610
611			a31: self.a31 * rhs.a11 + self.a32 * rhs.a21,
612			a32: self.a31 * rhs.a12 + self.a32 * rhs.a22,
613			a33: self.a31 * rhs.a13 + self.a32 * rhs.a23 + self.a33,
614		}
615	}
616}
617impl<T: Copy + ops::Add<Output = T> + ops::Mul<Output = T>> ops::MulAssign<Transform2<T>> for Mat3<T> {
618	#[inline]
619	fn mul_assign(&mut self, rhs: Transform2<T>) {
620		*self = *self * rhs;
621	}
622}
623
624impl_mat_neg!(Mat3);
625impl_mat_add_mat!(Mat3);
626impl_mat_sub_mat!(Mat3);
627impl_mat_mul_scalar!(Mat3);
628impl_mat_mul_vec!(Mat3, Vec3);
629impl_mat_mul_mat!(Mat3);
630
631//----------------------------------------------------------------
632// Formatting
633
634impl<T: fmt::Display> fmt::Display for Mat3<T> {
635	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
636		f.write_str("Mat3(")?;
637		print::print(&move |i| &self.as_array()[i], 0x33, f)?;
638		f.write_str(")")
639	}
640}
641impl<T: fmt::Debug> fmt::Debug for Mat3<T> {
642	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
643		f.write_str("Mat3(")?;
644		print::print(&move |i| print::Debug(&self.as_array()[i]), 0x33, f)?;
645		f.write_str(")")
646	}
647}
648
649//----------------------------------------------------------------
650// Tests
651
652#[test]
653fn test_inverse() {
654	let mut rng = urandom::seeded(42);
655
656	for _ in 0..1000 {
657		let a11 = rng.range(-10.0..10.0);
658		let a12 = rng.range(-10.0..10.0);
659		let a13 = rng.range(-10.0..10.0);
660		let a21 = rng.range(-10.0..10.0);
661		let a22 = rng.range(-10.0..10.0);
662		let a23 = rng.range(-10.0..10.0);
663		let a31 = rng.range(-10.0..10.0);
664		let a32 = rng.range(-10.0..10.0);
665		let a33 = rng.range(-10.0..10.0);
666
667		let mat = Mat3(a11, a12, a13, a21, a22, a23, a31, a32, a33);
668		let inv = mat.inverse();
669		let _identity = mat * inv;
670
671		let p = Vec3(
672			rng.range(-10.0..10.0),
673			rng.range(-10.0..10.0),
674			rng.range(-10.0..10.0),
675		);
676
677		let projected = mat * p;
678		let unprojected = inv * projected;
679
680		let error = (unprojected - p).len();
681		assert!(error < 1e-6, "Failed for mat: {mat:?}, p: {p:?}, error: {error}");
682	}
683}
684
685#[test]
686fn test_add() {
687	let lhs = Mat3(1, 2, 3, 4, 5, 6, 7, 8, 9);
688	let rhs = Mat3(10, 20, 30, 40, 50, 60, 70, 80, 90);
689	let expected = Mat3(11, 22, 33, 44, 55, 66, 77, 88, 99);
690
691	assert_eq!(lhs + rhs, expected);
692	assert_eq!(lhs + &rhs, expected);
693	assert_eq!(&lhs + rhs, expected);
694	assert_eq!(&lhs + &rhs, expected);
695
696	let mut value = lhs;
697	value += rhs;
698	assert_eq!(value, expected);
699
700	let mut value = lhs;
701	value += &rhs;
702	assert_eq!(value, expected);
703}
704
705#[test]
706fn test_sub() {
707	let lhs = Mat3(11, 22, 33, 44, 55, 66, 77, 88, 99);
708	let rhs = Mat3(10, 20, 30, 40, 50, 60, 70, 80, 90);
709	let expected = Mat3(1, 2, 3, 4, 5, 6, 7, 8, 9);
710
711	assert_eq!(lhs - rhs, expected);
712	assert_eq!(lhs - &rhs, expected);
713	assert_eq!(&lhs - rhs, expected);
714	assert_eq!(&lhs - &rhs, expected);
715
716	let mut value = lhs;
717	value -= rhs;
718	assert_eq!(value, expected);
719
720	let mut value = lhs;
721	value -= &rhs;
722	assert_eq!(value, expected);
723}
724
725#[test]
726fn test_neg() {
727	let value = Mat3(1, -2, 3, -4, 5, -6, 7, -8, 9);
728	let expected = Mat3(-1, 2, -3, 4, -5, 6, -7, 8, -9);
729	assert_eq!(-value, expected);
730	assert_eq!(-&value, expected);
731}