1use core::{
2 fmt::{Debug, Display},
3 hash::Hash,
4 ops::{Add, Index, IndexMut, Mul, MulAssign},
5};
6
7use crate::{
8 Aligned, Alignment, Length, Matrix, One, Scalar, SupportedLength, Unaligned, Vector, Zero,
9 utils::{transmute_mut, transmute_ref},
10};
11
12mod float;
13#[cfg(feature = "wide")]
14mod wide;
15#[cfg(feature = "wide")]
16mod wide_float;
17
18#[repr(C)]
37pub struct Affine<const N: usize, T, A: Alignment>
38where
39 Length<N>: SupportedLength,
40 T: Scalar,
41{
42 pub submatrix: Matrix<N, T, A>,
44 pub translation: Vector<N, T, A>,
46}
47
48pub type Affine2<T> = Affine<2, T, Unaligned>;
64
65pub type Affine3<T> = Affine<3, T, Unaligned>;
81
82pub type Affine2A<T> = Affine<2, T, Aligned>;
99
100pub type Affine3A<T> = Affine<3, T, Aligned>;
117
118impl<const N: usize, T, A: Alignment> Affine<N, T, A>
119where
120 Length<N>: SupportedLength,
121 T: Scalar + Zero,
122{
123 pub const ZERO: Self = Self::from_submatrix_translation(Matrix::ZERO, Vector::ZERO);
130}
131
132impl<const N: usize, T, A: Alignment> Affine<N, T, A>
133where
134 Length<N>: SupportedLength,
135 T: Scalar + Zero + One,
136{
137 pub const IDENTITY: Self = Self::from_submatrix_translation(Matrix::IDENTITY, Vector::ZERO);
139}
140
141impl<const N: usize, T, A: Alignment> Affine<N, T, A>
142where
143 Length<N>: SupportedLength,
144 T: Scalar,
145{
146 #[inline]
163 #[must_use]
164 #[track_caller]
165 pub fn from_row_fn<F>(mut f: F) -> Self
166 where
167 F: FnMut(usize) -> Vector<N, T, A>,
168 {
169 Self {
170 submatrix: Matrix::from_row_fn(&mut f),
171 translation: f(N),
172 }
173 }
174
175 #[inline]
177 #[must_use]
178 pub const fn from_scale(scale: Vector<N, T, A>) -> Self
179 where
180 T: Zero,
181 {
182 Self {
183 submatrix: Matrix::from_diagonal(scale),
184 translation: Vector::ZERO,
185 }
186 }
187
188 #[inline]
190 #[must_use]
191 pub const fn from_translation(translation: Vector<N, T, A>) -> Self
192 where
193 T: Zero + One,
194 {
195 Self {
196 submatrix: Matrix::IDENTITY,
197 translation,
198 }
199 }
200
201 #[inline]
204 #[must_use]
205 pub const fn from_submatrix(submatrix: Matrix<N, T, A>) -> Self
206 where
207 T: Zero,
208 {
209 Self {
210 submatrix,
211 translation: Vector::ZERO,
212 }
213 }
214
215 #[inline]
218 #[must_use]
219 pub const fn from_submatrix_translation(
220 submatrix: Matrix<N, T, A>,
221 translation: Vector<N, T, A>,
222 ) -> Self {
223 Self {
224 submatrix,
225 translation,
226 }
227 }
228
229 #[inline]
253 #[must_use]
254 pub const fn to_alignment<A2: Alignment>(&self) -> Affine<N, T, A2> {
255 Affine::from_submatrix_translation(
256 self.submatrix.to_alignment(),
257 self.translation.to_alignment(),
258 )
259 }
260
261 #[inline]
275 #[must_use]
276 pub const fn align(&self) -> Affine<N, T, Aligned> {
277 self.to_alignment()
278 }
279
280 #[inline]
294 #[must_use]
295 pub const fn unalign(&self) -> Affine<N, T, Unaligned> {
296 self.to_alignment()
297 }
298
299 #[inline]
301 #[must_use]
302 #[track_caller]
303 pub fn transform_point(&self, point: Vector<N, T, A>) -> Vector<N, T, A>
304 where
305 T: Add<Output = T> + Mul<Output = T>,
306 {
307 point * self.submatrix + self.translation
308 }
309
310 #[inline]
317 #[must_use]
318 #[track_caller]
319 pub fn transform_vector(&self, vector: Vector<N, T, A>) -> Vector<N, T, A>
320 where
321 T: Add<Output = T> + Mul<Output = T>,
322 {
323 vector * self.submatrix
324 }
325}
326
327impl<T, A: Alignment> Affine<2, T, A>
328where
329 T: Scalar,
330{
331 #[inline]
333 #[must_use]
334 pub const fn from_rows(rows: &[Vector<2, T, A>; 3]) -> Self {
335 Self {
336 submatrix: Matrix::from_rows(&[rows[0], rows[1]]),
337 translation: rows[2],
338 }
339 }
340
341 #[inline]
359 #[must_use]
360 pub const fn from_row_array(array: &[T; 6]) -> Self {
361 Self::from_rows(&[
362 Vector::<2, T, A>::new(array[0], array[1]),
363 Vector::<2, T, A>::new(array[2], array[3]),
364 Vector::<2, T, A>::new(array[4], array[5]),
365 ])
366 }
367
368 #[inline]
392 #[must_use]
393 pub fn from_matrix(matrix: Matrix<3, T, A>) -> Self {
394 Self::from_rows(&[matrix[0].xy(), matrix[1].xy(), matrix[2].xy()])
395 }
396
397 #[inline]
399 #[must_use]
400 pub const fn as_rows(&self) -> &[Vector<2, T, A>; 3] {
401 unsafe { transmute_ref::<Affine<2, T, A>, [Vector<2, T, A>; 3]>(self) }
405 }
406
407 #[inline]
409 #[must_use]
410 pub const fn as_mut_rows(&mut self) -> &mut [Vector<2, T, A>; 3] {
411 unsafe { transmute_mut::<Affine<2, T, A>, [Vector<2, T, A>; 3]>(self) }
415 }
416
417 #[inline]
423 #[must_use]
424 #[deprecated(since = "0.17.1", note = "renamed to `as_mut_rows`")]
425 pub const fn as_rows_mut(&mut self) -> &mut [Vector<2, T, A>; 3] {
426 self.as_mut_rows()
427 }
428}
429
430impl<T, A: Alignment> Affine<3, T, A>
431where
432 T: Scalar,
433{
434 #[inline]
436 #[must_use]
437 pub const fn from_rows(rows: &[Vector<3, T, A>; 4]) -> Self {
438 Self {
439 submatrix: Matrix::from_rows(&[rows[0], rows[1], rows[2]]),
440 translation: rows[3],
441 }
442 }
443
444 #[inline]
462 #[must_use]
463 pub const fn from_row_array(array: &[T; 12]) -> Self {
464 Self::from_rows(&[
465 Vector::<3, T, A>::new(array[0], array[1], array[2]),
466 Vector::<3, T, A>::new(array[3], array[4], array[5]),
467 Vector::<3, T, A>::new(array[6], array[7], array[8]),
468 Vector::<3, T, A>::new(array[9], array[10], array[11]),
469 ])
470 }
471
472 #[inline]
496 #[must_use]
497 pub fn from_matrix(matrix: Matrix<4, T, A>) -> Self {
498 Self::from_rows(&[
499 matrix[0].xyz(),
500 matrix[1].xyz(),
501 matrix[2].xyz(),
502 matrix[3].xyz(),
503 ])
504 }
505
506 #[inline]
508 #[must_use]
509 pub const fn as_rows(&self) -> &[Vector<3, T, A>; 4] {
510 unsafe { transmute_ref::<Affine<3, T, A>, [Vector<3, T, A>; 4]>(self) }
514 }
515
516 #[inline]
518 #[must_use]
519 pub const fn as_mut_rows(&mut self) -> &mut [Vector<3, T, A>; 4] {
520 unsafe { transmute_mut::<Affine<3, T, A>, [Vector<3, T, A>; 4]>(self) }
524 }
525
526 #[inline]
532 #[must_use]
533 #[deprecated(since = "0.17.1", note = "renamed to `as_mut_rows`")]
534 pub const fn as_rows_mut(&mut self) -> &mut [Vector<3, T, A>; 4] {
535 self.as_mut_rows()
536 }
537}
538
539impl<T, A: Alignment> Affine<4, T, A>
540where
541 T: Scalar,
542{
543 #[inline]
545 #[must_use]
546 pub const fn from_rows(rows: &[Vector<4, T, A>; 5]) -> Self {
547 Self {
548 submatrix: Matrix::from_rows(&[rows[0], rows[1], rows[2], rows[3]]),
549 translation: rows[4],
550 }
551 }
552
553 #[inline]
571 #[must_use]
572 pub const fn from_row_array(array: &[T; 20]) -> Self {
573 Self::from_rows(&[
574 Vector::<4, T, A>::new(array[0], array[1], array[2], array[3]),
575 Vector::<4, T, A>::new(array[4], array[5], array[6], array[7]),
576 Vector::<4, T, A>::new(array[8], array[9], array[10], array[11]),
577 Vector::<4, T, A>::new(array[12], array[13], array[14], array[15]),
578 Vector::<4, T, A>::new(array[16], array[17], array[18], array[19]),
579 ])
580 }
581
582 #[inline]
584 #[must_use]
585 pub const fn as_rows(&self) -> &[Vector<4, T, A>; 5] {
586 unsafe { transmute_ref::<Affine<4, T, A>, [Vector<4, T, A>; 5]>(self) }
590 }
591
592 #[inline]
594 #[must_use]
595 pub const fn as_mut_rows(&mut self) -> &mut [Vector<4, T, A>; 5] {
596 unsafe { transmute_mut::<Affine<4, T, A>, [Vector<4, T, A>; 5]>(self) }
600 }
601
602 #[inline]
608 #[must_use]
609 #[deprecated(since = "0.17.1", note = "renamed to `as_mut_rows`")]
610 pub const fn as_rows_mut(&mut self) -> &mut [Vector<4, T, A>; 5] {
611 self.as_mut_rows()
612 }
613}
614
615impl<const N: usize, T, A: Alignment> Clone for Affine<N, T, A>
616where
617 Length<N>: SupportedLength,
618 T: Scalar,
619{
620 #[inline]
621 fn clone(&self) -> Self {
622 *self
623 }
624}
625
626impl<const N: usize, T, A: Alignment> Copy for Affine<N, T, A>
627where
628 Length<N>: SupportedLength,
629 T: Scalar,
630{
631}
632
633impl<const N: usize, T, A: Alignment> Index<usize> for Affine<N, T, A>
634where
635 Length<N>: SupportedLength,
636 T: Scalar,
637{
638 type Output = Vector<N, T, A>;
639
640 #[inline]
647 #[track_caller]
648 fn index(&self, index: usize) -> &Self::Output {
649 match (N, index) {
650 (2, 0) => &self.submatrix[0],
651 (2, 1) => &self.submatrix[1],
652 (2, 2) => &self.translation,
653 (3, 0) => &self.submatrix[0],
654 (3, 1) => &self.submatrix[1],
655 (3, 2) => &self.submatrix[2],
656 (3, 3) => &self.translation,
657 (4, 0) => &self.submatrix[0],
658 (4, 1) => &self.submatrix[1],
659 (4, 2) => &self.submatrix[2],
660 (4, 3) => &self.submatrix[3],
661 (4, 4) => &self.translation,
662 _ => panic!("index out of bounds"),
663 }
664 }
665}
666
667impl<const N: usize, T, A: Alignment> IndexMut<usize> for Affine<N, T, A>
668where
669 Length<N>: SupportedLength,
670 T: Scalar,
671{
672 #[inline]
679 #[track_caller]
680 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
681 match (N, index) {
682 (2, 0) => &mut self.submatrix[0],
683 (2, 1) => &mut self.submatrix[1],
684 (2, 2) => &mut self.translation,
685 (3, 0) => &mut self.submatrix[0],
686 (3, 1) => &mut self.submatrix[1],
687 (3, 2) => &mut self.submatrix[2],
688 (3, 3) => &mut self.translation,
689 (4, 0) => &mut self.submatrix[0],
690 (4, 1) => &mut self.submatrix[1],
691 (4, 2) => &mut self.submatrix[2],
692 (4, 3) => &mut self.submatrix[3],
693 (4, 4) => &mut self.translation,
694 _ => panic!("index out of bounds"),
695 }
696 }
697}
698
699impl<const N: usize, T, A: Alignment> Debug for Affine<N, T, A>
700where
701 Length<N>: SupportedLength,
702 T: Scalar + Debug,
703{
704 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
705 match N {
706 2 => write!(
707 f,
708 "[{:?}, {:?}, {:?}]",
709 self.submatrix[0], self.submatrix[1], self.translation
710 ),
711 3 => write!(
712 f,
713 "[{:?}, {:?}, {:?}, {:?}]",
714 self.submatrix[0], self.submatrix[1], self.submatrix[2], self.translation
715 ),
716 4 => write!(
717 f,
718 "[{:?}, {:?}, {:?}, {:?}, {:?}]",
719 self.submatrix[0],
720 self.submatrix[1],
721 self.submatrix[2],
722 self.submatrix[3],
723 self.translation
724 ),
725 _ => unreachable!(),
726 }
727 }
728}
729
730impl<const N: usize, T, A: Alignment> Display for Affine<N, T, A>
731where
732 Length<N>: SupportedLength,
733 T: Scalar + Display,
734{
735 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
736 match N {
737 2 => write!(
738 f,
739 "[{}, {}, {}]",
740 self.submatrix[0], self.submatrix[1], self.translation
741 ),
742 3 => write!(
743 f,
744 "[{}, {}, {}, {}]",
745 self.submatrix[0], self.submatrix[1], self.submatrix[2], self.translation
746 ),
747 4 => write!(
748 f,
749 "[{}, {}, {}, {}, {}]",
750 self.submatrix[0],
751 self.submatrix[1],
752 self.submatrix[2],
753 self.submatrix[3],
754 self.translation
755 ),
756 _ => unreachable!(),
757 }
758 }
759}
760
761impl<const N: usize, T, A: Alignment> PartialEq for Affine<N, T, A>
762where
763 Length<N>: SupportedLength,
764 T: Scalar + PartialEq,
765{
766 #[inline]
767 fn eq(&self, other: &Self) -> bool {
768 self.submatrix == other.submatrix && self.translation == other.translation
769 }
770}
771
772impl<const N: usize, T, A: Alignment> Eq for Affine<N, T, A>
773where
774 Length<N>: SupportedLength,
775 T: Scalar + Eq,
776{
777}
778
779impl<const N: usize, T, A: Alignment> Hash for Affine<N, T, A>
780where
781 Length<N>: SupportedLength,
782 T: Scalar + Hash,
783{
784 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
785 self.submatrix.hash(state);
786 self.translation.hash(state);
787 }
788}
789
790impl<const N: usize, T, A: Alignment> Default for Affine<N, T, A>
791where
792 Length<N>: SupportedLength,
793 T: Scalar + Zero + One,
794{
795 #[inline]
799 fn default() -> Self {
800 Self::IDENTITY
801 }
802}
803
804macro_rules! impl_mul {
805 ($(#[$doc:meta])*) => {
806 impl<const N: usize, T, A: Alignment> Mul for Affine<N, T, A>
807 where
808 Length<N>: SupportedLength,
809 T: Scalar + Add<Output = T> + Mul<Output = T>,
810 {
811 type Output = Self;
812
813 $(#[$doc])*
814 #[inline]
815 #[track_caller]
816 fn mul(self, rhs: Self) -> Self::Output {
817 &self * &rhs
818 }
819 }
820
821 impl<const N: usize, T, A: Alignment> Mul<&Affine<N, T, A>> for Affine<N, T, A>
822 where
823 Length<N>: SupportedLength,
824 T: Scalar + Add<Output = T> + Mul<Output = T>,
825 {
826 type Output = Self;
827
828 $(#[$doc])*
829 #[inline]
830 #[track_caller]
831 fn mul(self, rhs: &Affine<N, T, A>) -> Self::Output {
832 &self * rhs
833 }
834 }
835
836 impl<const N: usize, T, A: Alignment> Mul<Affine<N, T, A>> for &Affine<N, T, A>
837 where
838 Length<N>: SupportedLength,
839 T: Scalar + Add<Output = T> + Mul<Output = T>,
840 {
841 type Output = Affine<N, T, A>;
842
843 $(#[$doc])*
844 #[inline]
845 #[track_caller]
846 fn mul(self, rhs: Affine<N, T, A>) -> Self::Output {
847 self * &rhs
848 }
849 }
850
851 impl<const N: usize, T, A: Alignment> Mul<&Affine<N, T, A>> for &Affine<N, T, A>
852 where
853 Length<N>: SupportedLength,
854 T: Scalar + Add<Output = T> + Mul<Output = T>,
855 {
856 type Output = Affine<N, T, A>;
857
858 $(#[$doc])*
859 #[inline]
860 #[track_caller]
861 fn mul(self, rhs: &Affine<N, T, A>) -> Self::Output {
862 Affine::from_submatrix_translation(
863 self.submatrix * rhs.submatrix,
864 self.translation * rhs.submatrix + rhs.translation,
865 )
866 }
867 }
868 };
869}
870impl_mul!(
871 );
883
884macro_rules! impl_mul_matrix {
885 ($N:literal, $N2:literal, $(#[$doc:meta])*) => {
886 impl<T, A: Alignment> Mul<Matrix<$N2, T, A>> for Affine<$N, T, A>
887 where
888 T: Scalar + Add<Output = T> + Mul<Output = T> + Zero + One,
889 {
890 type Output = Matrix<$N2, T, A>;
891
892 $(#[$doc])*
893 #[inline]
894 #[track_caller]
895 fn mul(self, rhs: Matrix<$N2, T, A>) -> Self::Output {
896 &Matrix::<$N2, T, A>::from_affine(&self) * &rhs
897 }
898 }
899
900 impl<T, A: Alignment> Mul<&Matrix<$N2, T, A>> for Affine<$N, T, A>
901 where
902 T: Scalar + Add<Output = T> + Mul<Output = T> + Zero + One,
903 {
904 type Output = Matrix<$N2, T, A>;
905
906 $(#[$doc])*
907 #[inline]
908 #[track_caller]
909 fn mul(self, rhs: &Matrix<$N2, T, A>) -> Self::Output {
910 &Matrix::<$N2, T, A>::from_affine(&self) * rhs
911 }
912 }
913
914 impl<T, A: Alignment> Mul<Matrix<$N2, T, A>> for &Affine<$N, T, A>
915 where
916 T: Scalar + Add<Output = T> + Mul<Output = T> + Zero + One,
917 {
918 type Output = Matrix<$N2, T, A>;
919
920 $(#[$doc])*
921 #[inline]
922 #[track_caller]
923 fn mul(self, rhs: Matrix<$N2, T, A>) -> Self::Output {
924 &Matrix::<$N2, T, A>::from_affine(self) * &rhs
925 }
926 }
927
928 impl<T, A: Alignment> Mul<&Matrix<$N2, T, A>> for &Affine<$N, T, A>
929 where
930 T: Scalar + Add<Output = T> + Mul<Output = T> + Zero + One,
931 {
932 type Output = Matrix<$N2, T, A>;
933
934 $(#[$doc])*
935 #[inline]
936 #[track_caller]
937 fn mul(self, rhs: &Matrix<$N2, T, A>) -> Self::Output {
938 &Matrix::<$N2, T, A>::from_affine(self) * rhs
939 }
940 }
941 };
942}
943impl_mul_matrix!(
944 2,
945 3,
946 );
957impl_mul_matrix!(
958 3,
959 4,
960 );
971
972macro_rules! impl_matrix_mul {
973 ($N:literal, $N2:literal, $(#[$doc:meta])*) => {
974 impl<T, A: Alignment> Mul<Affine<$N, T, A>> for Matrix<$N2, T, A>
975 where
976 T: Scalar + Add<Output = T> + Mul<Output = T> + Zero + One,
977 {
978 type Output = Self;
979
980 $(#[$doc])*
981 #[inline]
982 #[track_caller]
983 fn mul(self, rhs: Affine<$N, T, A>) -> Self::Output {
984 &self * &Matrix::<$N2, T, A>::from_affine(&rhs)
985 }
986 }
987
988 impl<T, A: Alignment> Mul<&Affine<$N, T, A>> for Matrix<$N2, T, A>
989 where
990 T: Scalar + Add<Output = T> + Mul<Output = T> + Zero + One,
991 {
992 type Output = Self;
993
994 $(#[$doc])*
995 #[inline]
996 #[track_caller]
997 fn mul(self, rhs: &Affine<$N, T, A>) -> Self::Output {
998 &self * &Matrix::<$N2, T, A>::from_affine(rhs)
999 }
1000 }
1001
1002 impl<T, A: Alignment> Mul<Affine<$N, T, A>> for &Matrix<$N2, T, A>
1003 where
1004 T: Scalar + Add<Output = T> + Mul<Output = T> + Zero + One,
1005 {
1006 type Output = Matrix<$N2, T, A>;
1007
1008 $(#[$doc])*
1009 #[inline]
1010 #[track_caller]
1011 fn mul(self, rhs: Affine<$N, T, A>) -> Self::Output {
1012 self * &Matrix::<$N2, T, A>::from_affine(&rhs)
1013 }
1014 }
1015
1016 impl<T, A: Alignment> Mul<&Affine<$N, T, A>> for &Matrix<$N2, T, A>
1017 where
1018 T: Scalar + Add<Output = T> + Mul<Output = T> + Zero + One,
1019 {
1020 type Output = Matrix<$N2, T, A>;
1021
1022 $(#[$doc])*
1023 #[inline]
1024 #[track_caller]
1025 fn mul(self, rhs: &Affine<$N, T, A>) -> Self::Output {
1026 self * &Matrix::<$N2, T, A>::from_affine(rhs)
1027 }
1028 }
1029 };
1030}
1031impl_matrix_mul!(
1032 2,
1033 3,
1034 );
1045impl_matrix_mul!(
1046 3,
1047 4,
1048 );
1059
1060macro_rules! impl_mul_assign {
1061 ($(#[$doc:meta])*) => {
1062 impl<const N: usize, T, A: Alignment> MulAssign for Affine<N, T, A>
1063 where
1064 Length<N>: SupportedLength,
1065 T: Scalar + Add<Output = T> + Mul<Output = T>,
1066 {
1067 $(#[$doc])*
1068 #[inline]
1069 #[track_caller]
1070 fn mul_assign(&mut self, rhs: Self) {
1071 *self = &*self * &rhs
1072 }
1073 }
1074
1075 impl<const N: usize, T, A: Alignment> MulAssign<&Affine<N, T, A>> for Affine<N, T, A>
1076 where
1077 Length<N>: SupportedLength,
1078 T: Scalar + Add<Output = T> + Mul<Output = T>,
1079 {
1080 $(#[$doc])*
1081 #[inline]
1082 #[track_caller]
1083 fn mul_assign(&mut self, rhs: &Affine<N, T, A>) {
1084 *self = &*self * rhs
1085 }
1086 }
1087 };
1088}
1089impl_mul_assign!(
1090 );
1102
1103macro_rules! impl_matrix_mul_assign {
1104 ($N:literal, $N2:literal, $(#[$doc:meta])*) => {
1105 impl<T, A: Alignment> MulAssign<Affine<$N, T, A>> for Matrix<$N2, T, A>
1106 where
1107 T: Scalar + Add<Output = T> + Mul<Output = T> + Zero + One,
1108 {
1109 $(#[$doc])*
1110 #[inline]
1111 #[track_caller]
1112 fn mul_assign(&mut self, rhs: Affine<$N, T, A>) {
1113 *self = &*self * &rhs
1114 }
1115 }
1116
1117 impl<T, A: Alignment> MulAssign<&Affine<$N, T, A>> for Matrix<$N2, T, A>
1118 where
1119 T: Scalar + Add<Output = T> + Mul<Output = T> + Zero + One,
1120 {
1121 $(#[$doc])*
1122 #[inline]
1123 #[track_caller]
1124 fn mul_assign(&mut self, rhs: &Affine<$N, T, A>) {
1125 *self = &*self * rhs
1126 }
1127 }
1128 };
1129}
1130impl_matrix_mul_assign!(
1131 2,
1132 3,
1133 );
1145impl_matrix_mul_assign!(
1146 3,
1147 4,
1148 );
1160
1161#[cfg(test)]
1162mod tests {
1163 extern crate std;
1164
1165 use std::format;
1166
1167 use crate::{
1168 Affine, Aligned, Mask, Matrix, Unaligned, Vector,
1169 test_utils::{assert_panic, assert_test_eq, for_types, random_iter},
1170 };
1171
1172 #[test]
1173 fn test_zero() {
1174 for_types!(|N, T: PrimitiveNumber, A| {
1175 assert_eq!(
1176 Affine::<N, T, A>::ZERO,
1177 Affine::from_submatrix_translation(Matrix::ZERO, Vector::ZERO)
1178 );
1179 });
1180 }
1181
1182 #[test]
1183 fn test_identity() {
1184 for_types!(|N, T: PrimitiveNumber, A| {
1185 assert_eq!(
1186 Affine::<N, T, A>::IDENTITY,
1187 Affine::from_submatrix_translation(Matrix::IDENTITY, Vector::ZERO)
1188 );
1189 });
1190 }
1191
1192 #[test]
1193 fn test_from_row_fn() {
1194 for_types!(|T: PrimitiveNumber, A| {
1195 let rows = std::array::from_fn(|r| Vector::from_fn(|c| T::as_from(r * 2 + c)));
1196 assert_eq!(
1197 Affine::<2, T, A>::from_row_fn(|i| rows[i]),
1198 Affine::<2, T, A>::from_rows(&rows)
1199 );
1200
1201 let rows = std::array::from_fn(|r| Vector::from_fn(|c| T::as_from(r * 3 + c)));
1202 assert_eq!(
1203 Affine::<3, T, A>::from_row_fn(|i| rows[i]),
1204 Affine::<3, T, A>::from_rows(&rows)
1205 );
1206
1207 let rows = std::array::from_fn(|r| Vector::from_fn(|c| T::as_from(r * 4 + c)));
1208 assert_eq!(
1209 Affine::<4, T, A>::from_row_fn(|i| rows[i]),
1210 Affine::<4, T, A>::from_rows(&rows)
1211 );
1212 });
1213 }
1214
1215 #[test]
1216 fn test_from_scale() {
1217 for_types!(|N, T: PrimitiveNumber, A| {
1218 let scale = Vector::from_fn(|i| T::as_from(i + 1));
1219
1220 assert_eq!(
1221 Affine::<N, T, A>::from_scale(scale),
1222 Affine::from_submatrix(Matrix::from_diagonal(scale))
1223 );
1224 });
1225 }
1226
1227 #[test]
1228 fn test_from_translation() {
1229 for_types!(|N, T: PrimitiveNumber, A| {
1230 let translation = Vector::from_fn(|i| T::as_from(i + 1));
1231
1232 assert_eq!(
1233 Affine::<N, T, A>::from_translation(translation),
1234 Affine::from_submatrix_translation(Matrix::IDENTITY, translation)
1235 );
1236 });
1237 }
1238
1239 #[test]
1240 fn test_from_submatrix() {
1241 for_types!(|N, T: PrimitiveNumber, A| {
1242 let submatrix = Matrix::from_row_fn(|r| Vector::from_fn(|c| T::as_from(r * N + c)));
1243
1244 assert_eq!(
1245 Affine::<N, T, A>::from_submatrix(submatrix),
1246 Affine::from_submatrix_translation(submatrix, Vector::ZERO)
1247 );
1248 });
1249 }
1250
1251 #[test]
1252 fn test_to_alignment() {
1253 for_types!(|N, T: PrimitiveNumber, A| {
1254 let affine =
1255 Affine::<N, T, A>::from_row_fn(|r| Vector::from_fn(|c| T::as_from(r * N + c)));
1256
1257 assert_eq!(
1258 affine.to_alignment(),
1259 Affine::<N, T, Aligned>::from_submatrix_translation(
1260 affine.submatrix.align(),
1261 affine.translation.align()
1262 )
1263 );
1264 assert_eq!(
1265 affine.to_alignment(),
1266 Affine::<N, T, Unaligned>::from_submatrix_translation(
1267 affine.submatrix.unalign(),
1268 affine.translation.unalign()
1269 )
1270 );
1271 });
1272 }
1273
1274 #[test]
1275 fn test_align() {
1276 for_types!(|N, T: PrimitiveNumber, A| {
1277 let affine =
1278 Affine::<N, T, A>::from_row_fn(|r| Vector::from_fn(|c| T::as_from(r * N + c)));
1279
1280 assert_eq!(
1281 affine.align(),
1282 Affine::<N, T, Aligned>::from_submatrix_translation(
1283 affine.submatrix.align(),
1284 affine.translation.align()
1285 )
1286 );
1287 });
1288 }
1289
1290 #[test]
1291 fn test_unalign() {
1292 for_types!(|N, T: PrimitiveNumber, A| {
1293 let affine =
1294 Affine::<N, T, A>::from_row_fn(|r| Vector::from_fn(|c| T::as_from(r * N + c)));
1295
1296 assert_eq!(
1297 affine.unalign(),
1298 Affine::<N, T, Unaligned>::from_submatrix_translation(
1299 affine.submatrix.unalign(),
1300 affine.translation.unalign()
1301 )
1302 );
1303 });
1304 }
1305
1306 #[test]
1307 fn test_transform_point() {
1308 for_types!(|N, T: PrimitiveFloat, A| {
1309 for (point, affine) in random_iter::<(Vector<N, T, A>, Affine<N, T, A>)>() {
1310 assert_test_eq!(
1311 affine.transform_point(point),
1312 point * affine.submatrix + affine.translation
1313 );
1314 }
1315 });
1316 }
1317
1318 #[test]
1319 fn test_transform_vector() {
1320 for_types!(|N, T: PrimitiveFloat, A| {
1321 for (point, affine) in random_iter::<(Vector<N, T, A>, Affine<N, T, A>)>() {
1322 assert_test_eq!(affine.transform_vector(point), point * affine.submatrix);
1323 }
1324 });
1325 }
1326
1327 #[test]
1328 fn test_from_rows() {
1329 for_types!(|T: PrimitiveNumber, A| {
1330 let rows = std::array::from_fn(|r| Vector::from_fn(|c| T::as_from(r * 2 + c)));
1331 assert_eq!(
1332 Affine::<2, T, A>::from_rows(&rows),
1333 Affine::<2, T, A>::from_submatrix_translation(
1334 Matrix::from_rows(&[rows[0], rows[1]]),
1335 rows[2]
1336 )
1337 );
1338
1339 let rows = std::array::from_fn(|r| Vector::from_fn(|c| T::as_from(r * 3 + c)));
1340 assert_eq!(
1341 Affine::<3, T, A>::from_rows(&rows),
1342 Affine::<3, T, A>::from_submatrix_translation(
1343 Matrix::from_rows(&[rows[0], rows[1], rows[2]]),
1344 rows[3]
1345 )
1346 );
1347
1348 let rows = std::array::from_fn(|r| Vector::from_fn(|c| T::as_from(r * 4 + c)));
1349 assert_eq!(
1350 Affine::<4, T, A>::from_rows(&rows),
1351 Affine::<4, T, A>::from_submatrix_translation(
1352 Matrix::from_rows(&[rows[0], rows[1], rows[2], rows[3]]),
1353 rows[4]
1354 )
1355 );
1356 });
1357 }
1358
1359 #[test]
1360 fn test_from_row_array() {
1361 for_types!(|T: PrimitiveNumber, A| {
1362 let [x, y, z, w, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p] =
1363 std::array::from_fn(T::as_from);
1364
1365 assert_eq!(
1366 Affine::<2, T, A>::from_row_array(&[x, y, z, w, a, b]),
1367 Affine::<2, T, A>::from_rows(&[
1368 Vector::<2, T, A>::new(x, y),
1369 Vector::<2, T, A>::new(z, w),
1370 Vector::<2, T, A>::new(a, b)
1371 ])
1372 );
1373 assert_eq!(
1374 Affine::<3, T, A>::from_row_array(&[x, y, z, w, a, b, c, d, e, f, g, h]),
1375 Affine::<3, T, A>::from_rows(&[
1376 Vector::<3, T, A>::new(x, y, z),
1377 Vector::<3, T, A>::new(w, a, b),
1378 Vector::<3, T, A>::new(c, d, e),
1379 Vector::<3, T, A>::new(f, g, h)
1380 ])
1381 );
1382 assert_eq!(
1383 Affine::<4, T, A>::from_row_array(&[
1384 x, y, z, w, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p
1385 ]),
1386 Affine::<4, T, A>::from_rows(&[
1387 Vector::<4, T, A>::new(x, y, z, w),
1388 Vector::<4, T, A>::new(a, b, c, d),
1389 Vector::<4, T, A>::new(e, f, g, h),
1390 Vector::<4, T, A>::new(i, j, k, l),
1391 Vector::<4, T, A>::new(m, n, o, p)
1392 ])
1393 );
1394 });
1395 }
1396
1397 #[test]
1398 fn test_from_matrix() {
1399 for_types!(|T: PrimitiveNumber, A| {
1400 let [x, y, z, w, a, b, c, d, e, f, g, h, i, j, k, l] =
1401 std::array::from_fn(|i| T::as_from(i + 1));
1402
1403 assert_eq!(
1404 Affine::<2, T, A>::from_matrix(Matrix::from_rows(&[
1405 Vector::<3, T, A>::new(x, y, z),
1406 Vector::<3, T, A>::new(w, a, b),
1407 Vector::<3, T, A>::new(c, d, e)
1408 ])),
1409 Affine::<2, T, A>::from_rows(&[
1410 Vector::<2, T, A>::new(x, y),
1411 Vector::<2, T, A>::new(w, a),
1412 Vector::<2, T, A>::new(c, d)
1413 ])
1414 );
1415 assert_eq!(
1416 Affine::<3, T, A>::from_matrix(Matrix::from_rows(&[
1417 Vector::<4, T, A>::new(x, y, z, w),
1418 Vector::<4, T, A>::new(a, b, c, d),
1419 Vector::<4, T, A>::new(e, f, g, h),
1420 Vector::<4, T, A>::new(i, j, k, l)
1421 ])),
1422 Affine::<3, T, A>::from_rows(&[
1423 Vector::<3, T, A>::new(x, y, z),
1424 Vector::<3, T, A>::new(a, b, c),
1425 Vector::<3, T, A>::new(e, f, g),
1426 Vector::<3, T, A>::new(i, j, k)
1427 ])
1428 );
1429 });
1430 }
1431
1432 #[test]
1433 fn test_as_rows() {
1434 for_types!(|T: PrimitiveNumber, A| {
1435 let rows = std::array::from_fn(|r| Vector::from_fn(|c| T::as_from(r * 2 + c)));
1436 assert_eq!(Affine::<2, T, A>::from_rows(&rows).as_rows(), &rows);
1437
1438 let rows = std::array::from_fn(|r| Vector::from_fn(|c| T::as_from(r * 3 + c)));
1439 assert_eq!(Affine::<3, T, A>::from_rows(&rows).as_rows(), &rows);
1440
1441 let rows = std::array::from_fn(|r| Vector::from_fn(|c| T::as_from(r * 4 + c)));
1442 assert_eq!(Affine::<4, T, A>::from_rows(&rows).as_rows(), &rows);
1443 });
1444 }
1445
1446 #[test]
1447 fn test_as_mut_rows() {
1448 for_types!(|T: PrimitiveNumber, A| {
1449 let mut rows = std::array::from_fn(|r| Vector::from_fn(|c| T::as_from(r * 2 + c)));
1450 assert_eq!(Affine::<2, T, A>::from_rows(&rows).as_mut_rows(), &mut rows);
1451
1452 let mut rows = std::array::from_fn(|r| Vector::from_fn(|c| T::as_from(r * 3 + c)));
1453 assert_eq!(Affine::<3, T, A>::from_rows(&rows).as_mut_rows(), &mut rows);
1454
1455 let mut rows = std::array::from_fn(|r| Vector::from_fn(|c| T::as_from(r * 4 + c)));
1456 assert_eq!(Affine::<4, T, A>::from_rows(&rows).as_mut_rows(), &mut rows);
1457 });
1458 }
1459
1460 #[test]
1461 fn test_index() {
1462 for_types!(|N, T: PrimitiveNumber, A| {
1463 let affine =
1464 Affine::<N, T, A>::from_row_fn(|r| Vector::from_fn(|c| T::as_from(r * N + c)));
1465
1466 for i in 0..N {
1467 assert_eq!(affine[i], affine.submatrix[i]);
1468 }
1469 assert_eq!(affine[N], affine.translation);
1470 assert_panic!(affine[N + 1]);
1471 assert_panic!(affine[N + 2]);
1472 });
1473 }
1474
1475 #[test]
1476 #[expect(clippy::clone_on_copy)]
1477 fn test_index_mut() {
1478 for_types!(|N, T: PrimitiveNumber, A| {
1479 let affine =
1480 Affine::<N, T, A>::from_row_fn(|r| Vector::from_fn(|c| T::as_from(r * N + c)));
1481
1482 for i in 0..N {
1483 assert_eq!(&mut affine.clone()[i], &mut affine.clone().submatrix[i]);
1484 }
1485 assert_eq!(&mut affine.clone()[N], &mut affine.clone().translation);
1486 assert_panic!(&mut affine.clone()[N + 1]);
1487 assert_panic!(&mut affine.clone()[N + 2]);
1488 });
1489 }
1490
1491 #[test]
1492 fn test_debug() {
1493 for_types!(|T: PrimitiveNumber, A| {
1494 let rows = std::array::from_fn(|r| Vector::from_fn(|c| T::as_from(r * 2 + c)));
1495 let [x_axis, y_axis, translation] = rows;
1496 assert_eq!(
1497 format!("{:?}", Affine::<2, T, A>::from_rows(&rows)),
1498 format!("[{x_axis:?}, {y_axis:?}, {translation:?}]")
1499 );
1500
1501 let rows = std::array::from_fn(|r| Vector::from_fn(|c| T::as_from(r * 3 + c)));
1502 let [x_axis, y_axis, z_axis, translation] = rows;
1503 assert_eq!(
1504 format!("{:?}", Affine::<3, T, A>::from_rows(&rows)),
1505 format!("[{x_axis:?}, {y_axis:?}, {z_axis:?}, {translation:?}]")
1506 );
1507
1508 let rows = std::array::from_fn(|r| Vector::from_fn(|c| T::as_from(r * 4 + c)));
1509 let [x_axis, y_axis, z_axis, w_axis, translation] = rows;
1510 assert_eq!(
1511 format!("{:?}", Affine::<4, T, A>::from_rows(&rows)),
1512 format!("[{x_axis:?}, {y_axis:?}, {z_axis:?}, {w_axis:?}, {translation:?}]")
1513 );
1514 });
1515 }
1516
1517 #[test]
1518 fn test_display() {
1519 for_types!(|T: PrimitiveNumber, A| {
1520 let rows = std::array::from_fn(|r| Vector::from_fn(|c| T::as_from(r * 2 + c)));
1521 let [x_axis, y_axis, translation] = rows;
1522 assert_eq!(
1523 format!("{}", Affine::<2, T, A>::from_rows(&rows)),
1524 format!("[{x_axis}, {y_axis}, {translation}]")
1525 );
1526
1527 let rows = std::array::from_fn(|r| Vector::from_fn(|c| T::as_from(r * 3 + c)));
1528 let [x_axis, y_axis, z_axis, translation] = rows;
1529 assert_eq!(
1530 format!("{}", Affine::<3, T, A>::from_rows(&rows)),
1531 format!("[{x_axis}, {y_axis}, {z_axis}, {translation}]")
1532 );
1533
1534 let rows = std::array::from_fn(|r| Vector::from_fn(|c| T::as_from(r * 4 + c)));
1535 let [x_axis, y_axis, z_axis, w_axis, translation] = rows;
1536 assert_eq!(
1537 format!("{}", Affine::<4, T, A>::from_rows(&rows)),
1538 format!("[{x_axis}, {y_axis}, {z_axis}, {w_axis}, {translation}]")
1539 );
1540 });
1541 }
1542
1543 #[test]
1544 fn test_eq() {
1545 for_types!(|N, T: PrimitiveNumber, A| {
1546 for ([affine, other], mask) in
1547 random_iter::<([Affine<N, T, A>; 2], [Mask<N, T, A>; 5])>()
1548 {
1549 let other = Affine::from_row_fn(|r| mask[r].select(affine[r], other[r]));
1550
1551 assert_eq!(
1552 affine == other,
1553 affine.submatrix == other.submatrix && affine.translation == other.translation
1554 );
1555 }
1556 });
1557 }
1558
1559 #[test]
1560 fn test_ne() {
1561 for_types!(|N, T: PrimitiveNumber, A| {
1562 for ([affine, other], mask) in
1563 random_iter::<([Affine<N, T, A>; 2], [Mask<N, T, A>; 5])>()
1564 {
1565 let other = Affine::from_row_fn(|r| mask[r].select(affine[r], other[r]));
1566
1567 assert_eq!(
1568 affine != other,
1569 affine.submatrix != other.submatrix || affine.translation != other.translation
1570 );
1571 }
1572 });
1573 }
1574
1575 #[test]
1576 fn test_default() {
1577 for_types!(|N, T: PrimitiveNumber, A| {
1578 assert_eq!(Affine::<N, T, A>::default(), Affine::IDENTITY);
1579 });
1580 }
1581
1582 #[test]
1583 fn test_mul() {
1584 for_types!(|N, T: PrimitiveFloat, A| {
1585 for (vector, [affine_1, affine_2]) in
1586 random_iter::<(Vector<N, T, A>, [Affine<N, T, A>; 2])>()
1587 {
1588 if !vector.is_finite()
1589 || !affine_1.is_finite()
1590 || !affine_2.is_finite()
1591 || vector.iter().any(|x| x.abs() > 1e10)
1592 || affine_1
1593 .submatrix
1594 .as_rows()
1595 .iter()
1596 .chain([&affine_1.translation])
1597 .flatten()
1598 .any(|x| x.abs() > 1e10)
1599 || affine_2
1600 .submatrix
1601 .as_rows()
1602 .iter()
1603 .chain([&affine_2.translation])
1604 .flatten()
1605 .any(|x| x.abs() > 1e10)
1606 {
1607 continue;
1608 }
1609
1610 assert_test_eq!(
1611 (affine_1 * affine_2).transform_point(vector),
1612 affine_2.transform_point(affine_1.transform_point(vector)),
1613 abs <= (affine_1 * affine_2).transform_point(vector).abs() * 1e-5 + 1e-3,
1614 0.0 = -0.0,
1615 INFINITY = NAN
1616 );
1617 assert_test_eq!(
1618 (affine_1 * affine_2).transform_vector(vector),
1619 affine_2.transform_vector(affine_1.transform_vector(vector)),
1620 abs <= (affine_1 * affine_2).transform_vector(vector).abs() * 1e-5 + 1e-3,
1621 0.0 = -0.0,
1622 INFINITY = NAN
1623 );
1624 }
1625 });
1626 }
1627
1628 #[test]
1629 fn test_mul_matrix() {
1630 for_types!(|T: PrimitiveFloat, A| {
1631 for (affine, matrix) in random_iter::<(Affine<2, T, A>, Matrix<3, T, A>)>() {
1632 assert_test_eq!(
1633 affine * matrix,
1634 Matrix::<3, T, A>::from_affine(&affine) * matrix
1635 );
1636 }
1637
1638 for (affine, matrix) in random_iter::<(Affine<3, T, A>, Matrix<4, T, A>)>() {
1639 assert_test_eq!(
1640 affine * matrix,
1641 Matrix::<4, T, A>::from_affine(&affine) * matrix
1642 );
1643 }
1644 });
1645 }
1646
1647 #[test]
1648 fn test_matrix_mul() {
1649 for_types!(|T: PrimitiveFloat, A| {
1650 for (matrix, affine) in random_iter::<(Matrix<3, T, A>, Affine<2, T, A>)>() {
1651 assert_test_eq!(
1652 matrix * affine,
1653 matrix * Matrix::<3, T, A>::from_affine(&affine)
1654 );
1655 }
1656
1657 for (matrix, affine) in random_iter::<(Matrix<4, T, A>, Affine<3, T, A>)>() {
1658 assert_test_eq!(
1659 matrix * affine,
1660 matrix * Matrix::<4, T, A>::from_affine(&affine)
1661 );
1662 }
1663 });
1664 }
1665
1666 #[test]
1667 fn test_mul_assign() {
1668 for_types!(|N, T: PrimitiveFloat, A| {
1669 for [left, right] in random_iter::<[Affine<N, T, A>; 2]>() {
1670 let mut result = left;
1671 result *= right;
1672
1673 assert_test_eq!(result, left * right);
1674 }
1675 });
1676 }
1677
1678 #[test]
1679 fn test_matrix_mul_assign() {
1680 for_types!(|T: PrimitiveFloat, A| {
1681 for (matrix, affine) in random_iter::<(Matrix<3, T, A>, Affine<2, T, A>)>() {
1682 let mut result = matrix;
1683 result *= affine;
1684
1685 assert_test_eq!(result, matrix * affine);
1686 }
1687
1688 for (matrix, affine) in random_iter::<(Matrix<4, T, A>, Affine<3, T, A>)>() {
1689 let mut result = matrix;
1690 result *= affine;
1691
1692 assert_test_eq!(result, matrix * affine);
1693 }
1694 });
1695 }
1696}