1use core::ops::{Add, Div, Mul, Neg, Rem, Sub};
3use num_traits::{Num, Zero};
4
5use super::Vector2;
7
8#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug, Default)]
19pub struct Matrix2<T> {
21 pub x_: Vector2<T>,
23 pub y_: Vector2<T>,
25}
26
27impl<T> Matrix2<T> {
28 #[inline]
52 pub const fn new(x_: Vector2<T>, y_: Vector2<T>) -> Self {
53 Matrix2 { x_, y_ }
54 }
55}
56
57impl<T: Clone + Num> Matrix2<T> {
58 #[inline]
78 pub fn det(&self) -> T {
79 self.x_.cross(&self.y_)
80 }
81
82 #[inline]
108 pub fn mdot(&self, v: &Vector2<T>) -> Vector2<T> {
109 Vector2::<T>::new(self.x_.dot(v), self.y_.dot(v))
110 }
111
112 #[inline]
134 pub fn scale(&self, alpha: T) -> Self {
135 Self::new(self.x_.clone() * alpha.clone(), self.y_.clone() * alpha)
136 }
137
138 #[inline]
162 pub fn unscale(&self, alpha: T) -> Self {
163 Self::new(self.x_.clone() / alpha.clone(), self.y_.clone() / alpha)
164 }
165}
166
167macro_rules! forward_xf_xf_binop {
168 (impl $imp:ident, $method:ident) => {
169 impl<'a, 'b, T: Clone + Num> $imp<&'b Matrix2<T>> for &'a Matrix2<T> {
170 type Output = Matrix2<T>;
171
172 #[inline]
173 fn $method(self, other: &Matrix2<T>) -> Self::Output {
174 self.clone().$method(other.clone())
175 }
176 }
177 };
178}
179
180macro_rules! forward_xf_val_binop {
181 (impl $imp:ident, $method:ident) => {
182 impl<'a, T: Clone + Num> $imp<Matrix2<T>> for &'a Matrix2<T> {
183 type Output = Matrix2<T>;
184
185 #[inline]
186 fn $method(self, other: Matrix2<T>) -> Self::Output {
187 self.clone().$method(other)
188 }
189 }
190 };
191}
192
193macro_rules! forward_val_xf_binop {
194 (impl $imp:ident, $method:ident) => {
195 impl<'a, T: Clone + Num> $imp<&'a Matrix2<T>> for Matrix2<T> {
196 type Output = Matrix2<T>;
197
198 #[inline]
199 fn $method(self, other: &Matrix2<T>) -> Self::Output {
200 self.$method(other.clone())
201 }
202 }
203 };
204}
205
206macro_rules! forward_all_binop {
207 (impl $imp:ident, $method:ident) => {
208 forward_xf_xf_binop!(impl $imp, $method);
209 forward_xf_val_binop!(impl $imp, $method);
210 forward_val_xf_binop!(impl $imp, $method);
211 };
212}
213
214forward_all_binop!(impl Add, add);
216
217impl<T: Clone + Num> Add<Matrix2<T>> for Matrix2<T> {
219 type Output = Self;
220
221 #[inline]
222 fn add(self, other: Self) -> Self::Output {
223 Self::Output::new(self.x_ + other.x_, self.y_ + other.y_)
224 }
225}
226
227forward_all_binop!(impl Sub, sub);
228
229impl<T: Clone + Num> Sub<Matrix2<T>> for Matrix2<T> {
231 type Output = Self;
232
233 #[inline]
234 fn sub(self, other: Self) -> Self::Output {
235 Self::Output::new(self.x_ - other.x_, self.y_ - other.y_)
236 }
237}
238
239mod opassign {
242 use core::ops::{AddAssign, DivAssign, MulAssign, SubAssign};
243
244 use num_traits::NumAssign;
245
246 use crate::Matrix2;
247
248 impl<T: Clone + NumAssign> AddAssign for Matrix2<T> {
249 fn add_assign(&mut self, other: Self) {
250 self.x_ += other.x_;
251 self.y_ += other.y_;
252 }
253 }
254
255 impl<T: Clone + NumAssign> SubAssign for Matrix2<T> {
256 fn sub_assign(&mut self, other: Self) {
257 self.x_ -= other.x_;
258 self.y_ -= other.y_;
259 }
260 }
261
262 impl<T: Clone + NumAssign> MulAssign<T> for Matrix2<T> {
263 fn mul_assign(&mut self, other: T) {
264 self.x_ *= other.clone();
265 self.y_ *= other;
266 }
267 }
268
269 impl<T: Clone + NumAssign> DivAssign<T> for Matrix2<T> {
270 fn div_assign(&mut self, other: T) {
271 self.x_ /= other.clone();
272 self.y_ /= other;
273 }
274 }
275
276 macro_rules! forward_op_assign1 {
277 (impl $imp:ident, $method:ident) => {
278 impl<'a, T: Clone + NumAssign> $imp<&'a Matrix2<T>> for Matrix2<T> {
279 #[inline]
280 fn $method(&mut self, other: &Self) {
281 self.$method(other.clone())
282 }
283 }
284 };
285 }
286
287 macro_rules! forward_op_assign2 {
288 (impl $imp:ident, $method:ident) => {
289 impl<'a, T: Clone + NumAssign> $imp<&'a T> for Matrix2<T> {
290 #[inline]
291 fn $method(&mut self, other: &T) {
292 self.$method(other.clone())
293 }
294 }
295 };
296 }
297
298 forward_op_assign1!(impl AddAssign, add_assign);
299 forward_op_assign1!(impl SubAssign, sub_assign);
300 forward_op_assign2!(impl MulAssign, mul_assign);
301 forward_op_assign2!(impl DivAssign, div_assign);
302}
303
304impl<T: Clone + Num + Neg<Output = T>> Neg for Matrix2<T> {
305 type Output = Self;
306
307 #[inline]
308 fn neg(self) -> Self::Output {
309 Self::Output::new(-self.x_, -self.y_)
310 }
311}
312
313impl<T: Clone + Num + Neg<Output = T>> Neg for &Matrix2<T> {
314 type Output = Matrix2<T>;
315
316 #[inline]
317 fn neg(self) -> Self::Output {
318 -self.clone()
319 }
320}
321
322macro_rules! scalar_arithmetic {
323 (@forward $imp:ident::$method:ident for $($scalar:ident),*) => (
324 impl<'a, T: Clone + Num> $imp<&'a T> for Matrix2<T> {
325 type Output = Matrix2<T>;
326
327 #[inline]
328 fn $method(self, other: &T) -> Self::Output {
329 self.$method(other.clone())
330 }
331 }
332 impl<'a, T: Clone + Num> $imp<T> for &'a Matrix2<T> {
333 type Output = Matrix2<T>;
334
335 #[inline]
336 fn $method(self, other: T) -> Self::Output {
337 self.clone().$method(other)
338 }
339 }
340 impl<'a, 'b, T: Clone + Num> $imp<&'a T> for &'b Matrix2<T> {
341 type Output = Matrix2<T>;
342
343 #[inline]
344 fn $method(self, other: &T) -> Self::Output {
345 self.clone().$method(other.clone())
346 }
347 }
348 $(
349 impl<'a> $imp<&'a Matrix2<$scalar>> for $scalar {
350 type Output = Matrix2<$scalar>;
351
352 #[inline]
353 fn $method(self, other: &Matrix2<$scalar>) -> Matrix2<$scalar> {
354 self.$method(other.clone())
355 }
356 }
357 impl<'a> $imp<Matrix2<$scalar>> for &'a $scalar {
358 type Output = Matrix2<$scalar>;
359
360 #[inline]
361 fn $method(self, other: Matrix2<$scalar>) -> Matrix2<$scalar> {
362 self.clone().$method(other)
363 }
364 }
365 impl<'a, 'b> $imp<&'a Matrix2<$scalar>> for &'b $scalar {
366 type Output = Matrix2<$scalar>;
367
368 #[inline]
369 fn $method(self, other: &Matrix2<$scalar>) -> Matrix2<$scalar> {
370 self.clone().$method(other.clone())
371 }
372 }
373 )*
374 );
375 ($($scalar:ident),*) => (
376 scalar_arithmetic!(@forward Mul::mul for $($scalar),*);
377 $(
381 impl Mul<Matrix2<$scalar>> for $scalar {
382 type Output = Matrix2<$scalar>;
383
384 #[inline]
385 fn mul(self, other: Matrix2<$scalar>) -> Self::Output {
386 Self::Output::new(self * other.x_, self * other.y_)
387 }
388 }
389
390 )*
391 );
392}
393
394impl<T: Clone + Num> Mul<T> for Matrix2<T> {
395 type Output = Matrix2<T>;
396
397 #[inline]
398 fn mul(self, other: T) -> Self::Output {
399 Self::Output::new(self.x_ * other.clone(), self.y_ * other)
400 }
401}
402
403impl<T: Clone + Num> Div<T> for Matrix2<T> {
404 type Output = Self;
405
406 #[inline]
407 fn div(self, other: T) -> Self::Output {
408 Self::Output::new(self.x_ / other.clone(), self.y_ / other)
409 }
410}
411
412impl<T: Clone + Num> Rem<T> for Matrix2<T> {
413 type Output = Matrix2<T>;
414
415 #[inline]
416 fn rem(self, other: T) -> Self::Output {
417 Self::Output::new(self.x_ % other.clone(), self.y_ % other)
418 }
419}
420
421scalar_arithmetic!(usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64);
422
423impl<T: Clone + Num> Zero for Matrix2<T> {
425 #[inline]
426 fn zero() -> Self {
427 Self::new(Zero::zero(), Zero::zero())
428 }
429
430 #[inline]
431 fn is_zero(&self) -> bool {
432 self.x_.is_zero() && self.y_.is_zero()
433 }
434
435 #[inline]
436 fn set_zero(&mut self) {
437 self.x_.set_zero();
438 self.y_.set_zero();
439 }
440}
441
442#[cfg(test)]
452mod test {
453 #![allow(non_upper_case_globals)]
454
455 use super::{Matrix2, Vector2};
457 use core::f64;
458 use num_traits::Zero;
459
460 pub const _0_0v: Vector2<f64> = Vector2 { x_: 0.0, y_: 0.0 };
461 pub const _1_0v: Vector2<f64> = Vector2 { x_: 1.0, y_: 0.0 };
462 pub const _1_1v: Vector2<f64> = Vector2 { x_: 1.0, y_: 1.0 };
463 pub const _0_1v: Vector2<f64> = Vector2 { x_: 0.0, y_: 1.0 };
464 pub const _neg1_1v: Vector2<f64> = Vector2 { x_: -1.0, y_: 1.0 };
465 pub const _05_05v: Vector2<f64> = Vector2 { x_: 0.5, y_: 0.5 };
466 pub const _4_2v: Vector2<f64> = Vector2 { x_: 4.0, y_: 2.0 };
468
469 pub const _0_0m: Matrix2<f64> = Matrix2 {
470 x_: _0_0v,
471 y_: _0_0v,
472 };
473 pub const _1_0m: Matrix2<f64> = Matrix2 {
474 x_: _1_0v,
475 y_: _0_0v,
476 };
477 pub const _1_1m: Matrix2<f64> = Matrix2 {
478 x_: _1_1v,
479 y_: _1_1v,
480 };
481 pub const _0_1m: Matrix2<f64> = Matrix2 {
482 x_: _0_0v,
483 y_: _1_0v,
484 };
485 pub const _neg1_1m: Matrix2<f64> = Matrix2 {
486 x_: _neg1_1v,
487 y_: _1_0v,
488 };
489 pub const _05_05m: Matrix2<f64> = Matrix2 {
490 x_: _05_05v,
491 y_: _05_05v,
492 };
493 pub const all_consts: [Matrix2<f64>; 5] = [_0_0m, _1_0m, _1_1m, _neg1_1m, _05_05m];
494 pub const _4_2m: Matrix2<f64> = Matrix2 {
495 x_: _4_2v,
496 y_: _4_2v,
497 };
498
499 #[test]
500 fn test_consts() {
501 assert_eq!(_0_0m, Zero::zero());
512 }
513
514 #[test]
515 fn test_scale_unscale() {
516 assert_eq!(_05_05m.scale(2.0), _1_1m);
517 assert_eq!(_1_1m.unscale(2.0), _05_05m);
518 for &c in all_consts.iter() {
519 assert_eq!(c.scale(2.0).unscale(2.0), c);
520 }
521 }
522
523 #[test]
537 fn test_new() {
538 let x = Vector2::new(1, 2);
539 let y = Vector2::new(3, 4);
540 let m = Matrix2::new(x, y);
541 assert_eq!(m.x_, x);
542 assert_eq!(m.y_, y);
543 }
544
545 #[test]
546 fn test_det() {
547 let m = Matrix2::new(Vector2::new(3, 4), Vector2::new(5, 6));
548 assert_eq!(m.det(), 3 * 6 - 4 * 5);
549
550 let m2 = Matrix2::new(Vector2::new(1.0, 2.0), Vector2::new(3.0, 4.0));
551 assert_eq!(m2.det(), -2.0);
552 }
553
554 #[test]
555 fn test_mdot() {
556 let m = Matrix2::new(Vector2::new(3, 4), Vector2::new(5, 6));
557 let v = Vector2::new(1, 1);
558 assert_eq!(m.mdot(&v), Vector2::new(7, 11));
559
560 let m2 = Matrix2::new(Vector2::new(1.0, 2.0), Vector2::new(3.0, 4.0));
561 let v2 = Vector2::new(2.0, 3.0);
562 assert_eq!(m2.mdot(&v2), Vector2::new(8.0, 18.0));
563 }
564
565 #[test]
566 fn test_scale() {
567 let m = Matrix2::new(Vector2::new(3, 4), Vector2::new(5, 6));
568 assert_eq!(
569 m.scale(2),
570 Matrix2::new(Vector2::new(6, 8), Vector2::new(10, 12))
571 );
572
573 let m2 = Matrix2::new(Vector2::new(1.5, 2.5), Vector2::new(3.5, 4.5));
574 assert_eq!(
575 m2.scale(2.0),
576 Matrix2::new(Vector2::new(3.0, 5.0), Vector2::new(7.0, 9.0))
577 );
578 }
579
580 #[test]
581 fn test_unscale() {
582 let m = Matrix2::new(Vector2::new(30, 40), Vector2::new(50, 60));
583 assert_eq!(
584 m.unscale(10),
585 Matrix2::new(Vector2::new(3, 4), Vector2::new(5, 6))
586 );
587
588 let m2 = Matrix2::new(Vector2::new(3.0, 5.0), Vector2::new(7.0, 9.0));
589 assert_eq!(
590 m2.unscale(2.0),
591 Matrix2::new(Vector2::new(1.5, 2.5), Vector2::new(3.5, 4.5))
592 );
593 }
594
595 #[test]
596 fn test_add() {
597 let m1 = Matrix2::new(Vector2::new(1, 2), Vector2::new(3, 4));
598 let m2 = Matrix2::new(Vector2::new(5, 6), Vector2::new(7, 8));
599 assert_eq!(
600 m1 + m2,
601 Matrix2::new(Vector2::new(6, 8), Vector2::new(10, 12))
602 );
603
604 let m3 = m1 + m2;
605 assert_eq!(m3, Matrix2::new(Vector2::new(6, 8), Vector2::new(10, 12)));
606
607 let m4 = m1 + &m2;
608 assert_eq!(m4, Matrix2::new(Vector2::new(6, 8), Vector2::new(10, 12)));
609 }
610
611 #[test]
612 fn test_sub() {
613 let m1 = Matrix2::new(Vector2::new(5, 6), Vector2::new(7, 8));
614 let m2 = Matrix2::new(Vector2::new(1, 2), Vector2::new(3, 4));
615 assert_eq!(
616 m1 - m2,
617 Matrix2::new(Vector2::new(4, 4), Vector2::new(4, 4))
618 );
619
620 let m3 = m1 - m2;
621 assert_eq!(m3, Matrix2::new(Vector2::new(4, 4), Vector2::new(4, 4)));
622 }
623
624 #[test]
625 fn test_neg() {
626 let m = Matrix2::new(Vector2::new(1, -2), Vector2::new(-3, 4));
627 assert_eq!(-m, Matrix2::new(Vector2::new(-1, 2), Vector2::new(3, -4)));
628 assert_eq!(-&m, Matrix2::new(Vector2::new(-1, 2), Vector2::new(3, -4)));
629 }
630
631 #[test]
632 fn test_scalar_mul() {
633 let m = Matrix2::new(Vector2::new(2, 3), Vector2::new(4, 5));
634 assert_eq!(
635 m * 4,
636 Matrix2::new(Vector2::new(8, 12), Vector2::new(16, 20))
637 );
638 assert_eq!(
639 &m * 4,
640 Matrix2::new(Vector2::new(8, 12), Vector2::new(16, 20))
641 );
642 assert_eq!(
643 4 * m,
644 Matrix2::new(Vector2::new(8, 12), Vector2::new(16, 20))
645 );
646 assert_eq!(
647 4 * &m,
648 Matrix2::new(Vector2::new(8, 12), Vector2::new(16, 20))
649 );
650 }
651
652 #[test]
653 fn test_scalar_div() {
654 let m = Matrix2::new(Vector2::new(10, 20), Vector2::new(30, 40));
655 assert_eq!(m / 5, Matrix2::new(Vector2::new(2, 4), Vector2::new(6, 8)));
656 }
657
658 #[test]
659 fn test_scalar_rem() {
660 let m = Matrix2::new(Vector2::new(10, 21), Vector2::new(32, 43));
661 assert_eq!(m % 3, Matrix2::new(Vector2::new(1, 0), Vector2::new(2, 1)));
662 }
663
664 #[test]
665 fn test_zero() {
666 let zero = Matrix2::<i32>::zero();
667 assert_eq!(zero, Matrix2::new(Vector2::zero(), Vector2::zero()));
668 assert!(zero.is_zero());
669
670 let mut m = Matrix2::new(Vector2::new(1, 2), Vector2::new(3, 4));
671 assert!(!m.is_zero());
672 m.set_zero();
673 assert!(m.is_zero());
674 }
675
676 #[test]
677 fn test_add_assign() {
678 let mut m1 = Matrix2::new(Vector2::new(1, 2), Vector2::new(3, 4));
679 let m2 = Matrix2::new(Vector2::new(5, 6), Vector2::new(7, 8));
680 m1 += m2;
681 assert_eq!(m1, Matrix2::new(Vector2::new(6, 8), Vector2::new(10, 12)));
682
683 let mut m3 = Matrix2::new(Vector2::new(1, 2), Vector2::new(3, 4));
684 m3 += &m2;
685 assert_eq!(m3, Matrix2::new(Vector2::new(6, 8), Vector2::new(10, 12)));
686 }
687
688 #[test]
689 fn test_sub_assign() {
690 let mut m1 = Matrix2::new(Vector2::new(5, 6), Vector2::new(7, 8));
691 let m2 = Matrix2::new(Vector2::new(1, 2), Vector2::new(3, 4));
692 m1 -= m2;
693 assert_eq!(m1, Matrix2::new(Vector2::new(4, 4), Vector2::new(4, 4)));
694
695 let mut m3 = Matrix2::new(Vector2::new(5, 6), Vector2::new(7, 8));
696 m3 -= &m2;
697 assert_eq!(m3, Matrix2::new(Vector2::new(4, 4), Vector2::new(4, 4)));
698 }
699
700 #[test]
701 fn test_mul_assign() {
702 let mut m = Matrix2::new(Vector2::new(1, 2), Vector2::new(3, 4));
703 m *= 3;
704 assert_eq!(m, Matrix2::new(Vector2::new(3, 6), Vector2::new(9, 12)));
705
706 let mut m2 = Matrix2::new(Vector2::new(1, 2), Vector2::new(3, 4));
707 let scalar = 3;
708 m2 *= &scalar;
709 assert_eq!(m2, Matrix2::new(Vector2::new(3, 6), Vector2::new(9, 12)));
710 }
711
712 #[test]
713 fn test_div_assign() {
714 let mut m = Matrix2::new(Vector2::new(6, 9), Vector2::new(12, 15));
715 m /= 3;
716 assert_eq!(m, Matrix2::new(Vector2::new(2, 3), Vector2::new(4, 5)));
717
718 let mut m2 = Matrix2::new(Vector2::new(6, 9), Vector2::new(12, 15));
719 let scalar = 3;
720 m2 /= &scalar;
721 assert_eq!(m2, Matrix2::new(Vector2::new(2, 3), Vector2::new(4, 5)));
722 }
723
724 #[test]
725 fn test_float_operations() {
726 let m = Matrix2::new(Vector2::new(1.5, 2.5), Vector2::new(3.5, 4.5));
727 assert_eq!(
728 m.scale(2.0),
729 Matrix2::new(Vector2::new(3.0, 5.0), Vector2::new(7.0, 9.0))
730 );
731 assert_eq!(
732 m.unscale(0.5),
733 Matrix2::new(Vector2::new(3.0, 5.0), Vector2::new(7.0, 9.0))
734 );
735 assert_eq!(m.det(), 1.5 * 4.5 - 2.5 * 3.5);
736 }
737
738 #[test]
739 fn test_clone_and_eq() {
740 let m1 = Matrix2::new(Vector2::new(1, 2), Vector2::new(3, 4));
741 let m2 = m1;
742 assert_eq!(m1, m2);
743
744 let m3 = Matrix2::new(Vector2::new(2, 1), Vector2::new(4, 3));
745 assert_ne!(m1, m3);
746 }
747
748 #[test]
749 fn test_debug() {
750 let m = Matrix2::new(Vector2::new(1, 2), Vector2::new(3, 4));
751 assert_eq!(
752 format!("{:?}", m),
753 "Matrix2 { x_: Vector2 { x_: 1, y_: 2 }, y_: Vector2 { x_: 3, y_: 4 } }"
754 );
755 }
756}