Skip to main content

ggmath/
affine.rs

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/// An `N`-dimensional affine transform which can represent translation,
19/// rotation, scaling and shear of type `T`.
20///
21/// `A` controls SIMD alignment and is either [`Unaligned`] or [`Aligned`]. See
22/// [`Alignment`] for more details.
23///
24/// Contains a matrix and a translation vector.
25///
26/// Prefer using affines over `N+1` matrices for affine transformations, because
27/// affines take less memory and perform better for select operations (see
28/// [benchmark results]).
29///
30/// # Type aliases
31///
32/// - [`Affine2<T>`] for [`Affine<2, T, Unaligned>`].
33/// - [`Affine3<T>`] for [`Affine<3, T, Unaligned>`].
34/// - [`Affine2A<T>`] for [`Affine<2, T, Aligned>`].
35/// - [`Affine3A<T>`] for [`Affine<3, T, Aligned>`].
36#[repr(C)]
37pub struct Affine<const N: usize, T, A: Alignment>
38where
39    Length<N>: SupportedLength,
40    T: Scalar,
41{
42    /// The part representing rotation, scaling and shear.
43    pub submatrix: Matrix<N, T, A>,
44    /// The part representing translation.
45    pub translation: Vector<N, T, A>,
46}
47
48/// A 2D affine transform which can represent translation, rotation, scaling and
49/// shear.
50///
51/// Contains a 2x2 matrix and a 2D translation vector.
52///
53/// Prefer using [`Affine2<T>`] over [`Mat3<T>`] for affine transformations,
54/// because it takes less memory and performs better for select operations (see
55/// [benchmark results]).
56///
57/// # No SIMD alignment
58///
59/// [`Affine2<T>`] does not have SIMD alignment, for that use [`Affine2A<T>`].
60///
61/// [`Mat3<T>`]: crate::Mat3
62/// [benchmark results]: https://github.com/Noam2Stein/ggmath/blob/main/BENCH_RESULTS.md
63pub type Affine2<T> = Affine<2, T, Unaligned>;
64
65/// A 3D affine transform which can represent translation, rotation, scaling and
66/// shear.
67///
68/// Contains a 3x3 matrix and a 3D translation vector.
69///
70/// Prefer using [`Affine3<T>`] over [`Mat4<T>`] for affine transformations,
71/// because it takes less memory and performs better for select operations (see
72/// [benchmark results]).
73///
74/// # No SIMD alignment
75///
76/// [`Affine3<T>`] does not have SIMD alignment, for that use [`Affine3A<T>`].
77///
78/// [`Mat4<T>`]: crate::Mat4
79/// [benchmark results]: https://github.com/Noam2Stein/ggmath/blob/main/BENCH_RESULTS.md
80pub type Affine3<T> = Affine<3, T, Unaligned>;
81
82/// A 2D affine transform which can represent translation, rotation, scaling and
83/// shear.
84///
85/// Contains a 2x2 matrix and a 2D translation vector.
86///
87/// Prefer using [`Affine2A<T>`] over [`Mat3A<T>`] for affine transformations,
88/// because it takes less memory and performs better for select operations (see
89/// [benchmark results]).
90///
91/// # SIMD alignment
92///
93/// For appropriate `T` types, [`Affine2A<T>`] has SIMD alignment. For no SIMD
94/// use [`Affine2<T>`].
95///
96/// [`Mat3A<T>`]: crate::Mat3A
97/// [benchmark results]: https://github.com/Noam2Stein/ggmath/blob/main/BENCH_RESULTS.md
98pub type Affine2A<T> = Affine<2, T, Aligned>;
99
100/// A 3D affine transform which can represent translation, rotation, scaling and
101/// shear.
102///
103/// Contains a 3x3 matrix and a 3D translation vector.
104///
105/// Prefer using [`Affine3A<T>`] over [`Mat4A<T>`] for affine transformations,
106/// because it takes less memory and performs better for select operations (see
107/// [benchmark results]).
108///
109/// # SIMD alignment
110///
111/// For appropriate `T` types, [`Affine3A<T>`] has SIMD alignment. For no SIMD
112/// use [`Affine3<T>`].
113///
114/// [`Mat4A<T>`]: crate::Mat4A
115/// [benchmark results]: https://github.com/Noam2Stein/ggmath/blob/main/BENCH_RESULTS.md
116pub 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    /// An affine transform with all elements set to `0`.
124    ///
125    /// This transforms all vectors to a zero vector. See [`IDENTITY`] for
126    /// an affine transform with no transformation.
127    ///
128    /// [`IDENTITY`]: Self::IDENTITY
129    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    /// An affine transform with no transformation.
138    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    /// Creates an affine transform by calling function `f` for each row index.
147    ///
148    /// Equivalent to `[f(0), f(1), f(2), ...]` where each item is a row vector.
149    ///
150    /// # Examples
151    ///
152    /// ```
153    /// # use ggmath::{Affine3, Vec3};
154    /// #
155    /// let affine = Affine3::from_row_fn(|i| Vec3::splat(i));
156    ///
157    /// assert_eq!(affine[0], Vec3::new(0, 0, 0));
158    /// assert_eq!(affine[1], Vec3::new(1, 1, 1));
159    /// assert_eq!(affine[2], Vec3::new(2, 2, 2));
160    /// assert_eq!(affine.translation, Vec3::new(3, 3, 3));
161    /// ```
162    #[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    /// Creates an affine transform from a non-uniform `scale`.
176    #[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    /// Creates an affine transform from a `translation` vector.
189    #[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    /// Creates an affine transform from `submatrix` expressing rotation and
202    /// scale, but not translation.
203    #[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    /// Creates an affine transform from `translation` and `submatrix`
216    /// expressing rotation and scale.
217    #[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    /// Conversion between [`Aligned`] and [`Unaligned`] storage.
230    ///
231    /// See [`align`] and [`unalign`] for scenarios where the output alignment
232    /// is known.
233    ///
234    /// See [`Alignment`] for more details.
235    ///
236    /// # Examples
237    ///
238    /// ```
239    /// # use ggmath::{Aligned, Affine2, Affine2A, Unaligned};
240    /// #
241    /// let unaligned = Affine2::<f32>::IDENTITY;
242    /// let aligned = unaligned.to_alignment::<Aligned>();
243    /// assert_eq!(aligned, Affine2A::IDENTITY);
244    ///
245    /// let aligned = Affine2A::<f32>::IDENTITY;
246    /// let unaligned = aligned.to_alignment::<Unaligned>();
247    /// assert_eq!(unaligned, Affine2::IDENTITY);
248    /// ```
249    ///
250    /// [`align`]: Self::align
251    /// [`unalign`]: Self::unalign
252    #[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    /// Conversion to [`Aligned`] storage.
262    ///
263    /// See [`Alignment`] for more details.
264    ///
265    /// # Examples
266    ///
267    /// ```
268    /// # use ggmath::{Affine2, Affine2A};
269    /// #
270    /// let unaligned = Affine2::<f32>::IDENTITY;
271    /// let aligned = unaligned.align();
272    /// assert_eq!(aligned, Affine2A::IDENTITY);
273    /// ```
274    #[inline]
275    #[must_use]
276    pub const fn align(&self) -> Affine<N, T, Aligned> {
277        self.to_alignment()
278    }
279
280    /// Conversion to [`Unaligned`] storage.
281    ///
282    /// See [`Alignment`] for more details.
283    ///
284    /// # Examples
285    ///
286    /// ```
287    /// # use ggmath::{Affine2, Affine2A};
288    /// #
289    /// let aligned = Affine2A::<f32>::IDENTITY;
290    /// let unaligned = aligned.unalign();
291    /// assert_eq!(unaligned, Affine2::IDENTITY);
292    /// ```
293    #[inline]
294    #[must_use]
295    pub const fn unalign(&self) -> Affine<N, T, Unaligned> {
296        self.to_alignment()
297    }
298
299    /// Transforms the given vector applying scale, rotation and translation.
300    #[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    /// Transforms the given vector applying scale and rotation, but not
311    /// translation.
312    ///
313    /// See [`transform_point`] for also applying translation.
314    ///
315    /// [`transform_point`]: Self::transform_point
316    #[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    /// Creates a 2D affine transform from three row vectors.
332    #[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    /// Creates an affine transform from a row-major array of elements.
342    ///
343    /// # Examples
344    ///
345    /// ```
346    /// # use ggmath::{Affine2, Vec2};
347    /// #
348    /// let affine = Affine2::from_row_array(&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
349    /// assert_eq!(
350    ///     affine,
351    ///     Affine2::from_rows(&[
352    ///         Vec2::new(1.0, 2.0),
353    ///         Vec2::new(3.0, 4.0),
354    ///         Vec2::new(5.0, 6.0),
355    ///     ]),
356    /// );
357    /// ```
358    #[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    /// Creates an affine transform from an affine transformation matrix,
369    /// discarding the last column.
370    ///
371    /// # Examples
372    ///
373    /// ```
374    /// # use ggmath::{Affine2, Mat3, Vec2, Vec3};
375    /// #
376    /// let matrix = Mat3::from_rows(&[
377    ///     Vec3::new(1.0, 2.0, 0.0),
378    ///     Vec3::new(3.0, 4.0, 0.0),
379    ///     Vec3::new(5.0, 6.0, 1.0),
380    /// ]);
381    ///
382    /// assert_eq!(
383    ///     Affine2::from_matrix(matrix),
384    ///     Affine2::from_rows(&[
385    ///         Vec2::new(1.0, 2.0),
386    ///         Vec2::new(3.0, 4.0),
387    ///         Vec2::new(5.0, 6.0),
388    ///     ]),
389    /// );
390    /// ```
391    #[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    /// Returns a reference to the affine transform's rows.
398    #[inline]
399    #[must_use]
400    pub const fn as_rows(&self) -> &[Vector<2, T, A>; 3] {
401        // SAFETY: `Affine<2, T, A>` is guaranteed to begin with
402        // `Matrix<2, T, A>` (two vectors) then `Vector<2, T, A>`, which is 3
403        // vectors in total.
404        unsafe { transmute_ref::<Affine<2, T, A>, [Vector<2, T, A>; 3]>(self) }
405    }
406
407    /// Returns a mutable reference to the affine transform's rows.
408    #[inline]
409    #[must_use]
410    pub const fn as_mut_rows(&mut self) -> &mut [Vector<2, T, A>; 3] {
411        // SAFETY: `Affine<2, T, A>` is guaranteed to begin with
412        // `Matrix<2, T, A>` (two vectors) then `Vector<2, T, A>`, which is 3
413        // vectors in total.
414        unsafe { transmute_mut::<Affine<2, T, A>, [Vector<2, T, A>; 3]>(self) }
415    }
416
417    /// Returns a mutable reference to the affine transform's rows.
418    ///
419    /// This function has been renamed to [`as_mut_rows`].
420    ///
421    /// [`as_mut_rows`]: Self::as_mut_rows
422    #[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    /// Creates a 3D affine transform from four row vectors.
435    #[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    /// Creates an affine transform from a row-major array of elements.
445    ///
446    /// # Examples
447    ///
448    /// ```
449    /// # use ggmath::{Affine2, Vec2};
450    /// #
451    /// let affine = Affine2::from_row_array(&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
452    /// assert_eq!(
453    ///     affine,
454    ///     Affine2::from_rows(&[
455    ///         Vec2::new(1.0, 2.0),
456    ///         Vec2::new(3.0, 4.0),
457    ///         Vec2::new(5.0, 6.0),
458    ///     ]),
459    /// );
460    /// ```
461    #[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    /// Creates an affine transform from an affine transformation matrix,
473    /// discarding the last column.
474    ///
475    /// # Examples
476    ///
477    /// ```
478    /// # use ggmath::{Affine2, Mat3, Vec2, Vec3};
479    /// #
480    /// let matrix = Mat3::from_rows(&[
481    ///     Vec3::new(1.0, 2.0, 0.0),
482    ///     Vec3::new(3.0, 4.0, 0.0),
483    ///     Vec3::new(5.0, 6.0, 1.0),
484    /// ]);
485    ///
486    /// assert_eq!(
487    ///     Affine2::from_matrix(matrix),
488    ///     Affine2::from_rows(&[
489    ///         Vec2::new(1.0, 2.0),
490    ///         Vec2::new(3.0, 4.0),
491    ///         Vec2::new(5.0, 6.0),
492    ///     ]),
493    /// );
494    /// ```
495    #[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    /// Returns a reference to the affine transform's rows.
507    #[inline]
508    #[must_use]
509    pub const fn as_rows(&self) -> &[Vector<3, T, A>; 4] {
510        // SAFETY: `Affine<3, T, A>` is guaranteed to begin with
511        // `Matrix<3, T, A>` (three vectors) then `Vector<3, T, A>`, which is 4
512        // vectors in total.
513        unsafe { transmute_ref::<Affine<3, T, A>, [Vector<3, T, A>; 4]>(self) }
514    }
515
516    /// Returns a mutable reference to the affine transform's rows.
517    #[inline]
518    #[must_use]
519    pub const fn as_mut_rows(&mut self) -> &mut [Vector<3, T, A>; 4] {
520        // SAFETY: `Affine<3, T, A>` is guaranteed to begin with
521        // `Matrix<3, T, A>` (three vectors) then `Vector<3, T, A>`, which is 4
522        // vectors in total.
523        unsafe { transmute_mut::<Affine<3, T, A>, [Vector<3, T, A>; 4]>(self) }
524    }
525
526    /// Returns a mutable reference to the affine transform's rows.
527    ///
528    /// This function has been renamed to [`as_mut_rows`].
529    ///
530    /// [`as_mut_rows`]: Self::as_mut_rows
531    #[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    /// Creates a 4D affine transform from five row vectors.
544    #[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    /// Creates an affine transform from a row-major array of elements.
554    ///
555    /// # Examples
556    ///
557    /// ```
558    /// # use ggmath::{Affine2, Vec2};
559    /// #
560    /// let affine = Affine2::from_row_array(&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
561    /// assert_eq!(
562    ///     affine,
563    ///     Affine2::from_rows(&[
564    ///         Vec2::new(1.0, 2.0),
565    ///         Vec2::new(3.0, 4.0),
566    ///         Vec2::new(5.0, 6.0),
567    ///     ]),
568    /// );
569    /// ```
570    #[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    /// Returns a reference to the affine transform's rows.
583    #[inline]
584    #[must_use]
585    pub const fn as_rows(&self) -> &[Vector<4, T, A>; 5] {
586        // SAFETY: `Affine<4, T, A>` is guaranteed to begin with
587        // `Matrix<4, T, A>` (four vectors) then `Vector<4, T, A>`, which is 5
588        // vectors in total.
589        unsafe { transmute_ref::<Affine<4, T, A>, [Vector<4, T, A>; 5]>(self) }
590    }
591
592    /// Returns a mutable reference to the affine transform's rows.
593    #[inline]
594    #[must_use]
595    pub const fn as_mut_rows(&mut self) -> &mut [Vector<4, T, A>; 5] {
596        // SAFETY: `Affine<4, T, A>` is guaranteed to begin with
597        // `Matrix<4, T, A>` (four vectors) then `Vector<4, T, A>`, which is 5
598        // vectors in total.
599        unsafe { transmute_mut::<Affine<4, T, A>, [Vector<4, T, A>; 5]>(self) }
600    }
601
602    /// Returns a mutable reference to the affine transform's rows.
603    ///
604    /// This function has been renamed to [`as_mut_rows`].
605    ///
606    /// [`as_mut_rows`]: Self::as_mut_rows
607    #[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    /// Returns the row at the given index.
641    ///
642    /// # Panics
643    ///
644    /// Panics if `index` is greater than the dimension of the affine transform.
645    /// It is fine if `index == N` because of the additional `translation` row.
646    #[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    /// Returns a mutable reference to the row at the given index.
673    ///
674    /// # Panics
675    ///
676    /// Panics if `index` is greater than the dimension of the affine transform.
677    /// It is fine if `index == N` because of the additional `translation` row.
678    #[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    /// Returns [`IDENTITY`].
796    ///
797    /// [`IDENTITY`]: Self::IDENTITY
798    #[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    /// Affine transform multiplication.
872    ///
873    /// Because vectors are treated as row matrices, affine transform
874    /// multiplication first applies the left-hand side transform, then the
875    /// right-hand side transform.
876    ///
877    /// # Consistency
878    ///
879    /// For primitive types this operation is cross-platform deterministic and
880    /// fully consistent with scalar addition and multiplication, including
881    /// floating-point precision and integer panics.
882);
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    /// Affine-transform matrix multiplication.
947    ///
948    /// Because vectors are treated as row matrices, multiplication first
949    /// applies the left-hand side transform, then the right-hand side matrix.
950    ///
951    /// # Consistency
952    ///
953    /// For primitive types this operation is cross-platform deterministic and
954    /// fully consistent with scalar addition and multiplication, including
955    /// floating-point precision and integer panics.
956);
957impl_mul_matrix!(
958    3,
959    4,
960    /// Affine-transform matrix multiplication.
961    ///
962    /// Because vectors are treated as row matrices, multiplication first
963    /// applies the left-hand side transform, then the right-hand side matrix.
964    ///
965    /// # Consistency
966    ///
967    /// For primitive types this operation is cross-platform deterministic and
968    /// fully consistent with scalar addition and multiplication, including
969    /// floating-point precision and integer panics.
970);
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    /// Matrix affine transform multiplication.
1035    ///
1036    /// Because vectors are treated as row matrices, multiplication first
1037    /// applies the left-hand side matrix, then the right-hand side transform.
1038    ///
1039    /// # Consistency
1040    ///
1041    /// For primitive types this operation is cross-platform deterministic and
1042    /// fully consistent with scalar addition and multiplication, including
1043    /// floating-point precision and integer panics.
1044);
1045impl_matrix_mul!(
1046    3,
1047    4,
1048    /// Matrix affine transform multiplication.
1049    ///
1050    /// Because vectors are treated as row matrices, multiplication first
1051    /// applies the left-hand side matrix, then the right-hand side transform.
1052    ///
1053    /// # Consistency
1054    ///
1055    /// For primitive types this operation is cross-platform deterministic and
1056    /// fully consistent with scalar addition and multiplication, including
1057    /// floating-point precision and integer panics.
1058);
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    /// Affine transform multiplication.
1091    ///
1092    /// Because vectors are treated as row matrices, affine transform
1093    /// multiplication first applies the left-hand side transform, then the
1094    /// right-hand side transform.
1095    ///
1096    /// # Consistency
1097    ///
1098    /// For primitive types this operation is cross-platform deterministic and
1099    /// fully consistent with scalar addition and multiplication, including
1100    /// floating-point precision and integer panics.
1101);
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    /// Matrix affine-transform multiplication.
1134    ///
1135    /// Because vectors are treated as row matrices, affine transform
1136    /// multiplication first applies the left-hand side matrix, then the
1137    /// right-hand side transform.
1138    ///
1139    /// # Consistency
1140    ///
1141    /// For primitive types this operation is cross-platform deterministic and
1142    /// fully consistent with scalar addition and multiplication, including
1143    /// floating-point precision and integer panics.
1144);
1145impl_matrix_mul_assign!(
1146    3,
1147    4,
1148    /// Matrix affine-transform multiplication.
1149    ///
1150    /// Because vectors are treated as row matrices, affine transform
1151    /// multiplication first applies the left-hand side matrix, then the
1152    /// right-hand side transform.
1153    ///
1154    /// # Consistency
1155    ///
1156    /// For primitive types this operation is cross-platform deterministic and
1157    /// fully consistent with scalar addition and multiplication, including
1158    /// floating-point precision and integer panics.
1159);
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}