siege_math/
matrix.rs

1
2use num_traits::NumCast;
3use std::ops::{Index, IndexMut, Mul, Add};
4use std::default::Default;
5use float_cmp::{Ulps, ApproxEq};
6use vector::{Vec2, Vec3, Vec4, Direction3, Point3};
7use {Angle, FullFloat};
8
9// NOTE: we store matrices in column-major order, which means we pre-multiply.
10// This is traditional so matrices directly copied to the GPU will work with
11// most other people's code, shaders, etc.  Also, it means vectors are stored
12// contiguously in the matrix.
13//
14// However, we hide this internal storage format from the interface, and
15// provide a row-major interface (e.g. via the [] operator and the new()
16// function parameter order).  This way the programmer can write matrices
17// in the same order that mathematicians write them.
18// (Subsequently we have made the internals public so that we can define
19//  constant matrices).
20
21/// A 2x2 matrix.
22///
23/// This matrix is internally stored column-major (as that is better for
24/// GPU compatibility and possibly other reasons), but the API (e.g.
25/// the order of function parameters to the new() function) is row-major,
26/// since that is how people write matrices on paper.
27#[repr(C)]
28#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
29#[derive(Serialize, Deserialize)]
30pub struct Mat2<F> {
31    pub x: Vec2<F>,
32    pub y: Vec2<F>
33}
34
35/// A 3x3 matrix
36///
37/// This matrix is internally stored column-major (as that is better for
38/// GPU compatibility and possibly other reasons), but the API (e.g.
39/// the order of function parameters to the new() function) is row-major,
40/// since that is how people write matrices on paper.
41#[repr(C)]
42#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
43#[derive(Serialize, Deserialize)]
44pub struct Mat3<F> {
45    pub x: Vec3<F>,
46    pub y: Vec3<F>,
47    pub z: Vec3<F>
48}
49
50/// A 4x4 matrix
51///
52/// This matrix is internally stored column-major (as that is better for
53/// GPU compatibility and possibly other reasons), but the API (e.g.
54/// the order of function parameters to the new() function) is row-major,
55/// since that is how people write matrices on paper.
56#[repr(C)]
57#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
58#[derive(Serialize, Deserialize)]
59pub struct Mat4<F> {
60    pub x: Vec4<F>,
61    pub y: Vec4<F>,
62    pub z: Vec4<F>,
63    pub p: Vec4<F>
64}
65
66// -- impl Index --------------------------------------------------------------
67
68// This is defined in row-major order
69impl<F: FullFloat> Index<(usize,usize)> for Mat2<F> {
70    type Output = F;
71
72    #[inline]
73    fn index(&self, (row,col): (usize,usize)) -> &F {
74        match col {
75            0 => &self.x[row],
76            1 => &self.y[row],
77            _ => panic!("Index out of bounds for Mat2"),
78        }
79    }
80}
81
82impl<F: FullFloat> Index<(usize,usize)> for Mat3<F> {
83    type Output = F;
84
85    #[inline]
86    fn index(&self, (row,col): (usize,usize)) -> &F {
87        match col {
88            0 => &self.x[row],
89            1 => &self.y[row],
90            2 => &self.z[row],
91            _ => panic!("Index out of bounds for Mat3"),
92        }
93    }
94}
95
96impl<F: FullFloat> Index<(usize,usize)> for Mat4<F> {
97    type Output = F;
98
99    #[inline]
100    fn index(&self, (row,col): (usize,usize)) -> &F {
101        match col {
102            0 => &self.x[row],
103            1 => &self.y[row],
104            2 => &self.z[row],
105            3 => &self.p[row],
106            _ => panic!("Index out of bounds for Mat4"),
107        }
108    }
109}
110
111// -- impl IndexMut -----------------------------------------------------------
112
113impl<F: FullFloat> IndexMut<(usize,usize)> for Mat2<F> {
114    #[inline]
115    fn index_mut(&mut self, (row,col): (usize,usize)) -> &mut F {
116        match col {
117            0 => &mut self.x[row],
118            1 => &mut self.y[row],
119            _ => panic!("Index out of bounds for Mat2"),
120        }
121    }
122}
123
124impl<F: FullFloat> IndexMut<(usize,usize)> for Mat3<F> {
125    #[inline]
126    fn index_mut(&mut self, (row,col): (usize,usize)) -> &mut F {
127        match col {
128            0 => &mut self.x[row],
129            1 => &mut self.y[row],
130            2 => &mut self.z[row],
131            _ => panic!("Index out of bounds for Mat3"),
132        }
133    }
134}
135
136impl<F: FullFloat> IndexMut<(usize,usize)> for Mat4<F> {
137    #[inline]
138    fn index_mut(&mut self, (row,col): (usize,usize)) -> &mut F {
139        match col {
140            0 => &mut self.x[row],
141            1 => &mut self.y[row],
142            2 => &mut self.z[row],
143            3 => &mut self.p[row],
144            _ => panic!("Index out of bounds for Mat4"),
145        }
146    }
147}
148
149// -- new ---------------------------------------------------------------------
150
151impl<F: FullFloat> Mat2<F> {
152    /// Create a new 2x2 Matrix. Specify parameters in row-major order
153    /// (as typically written on paper and in math texts)
154    #[inline]
155    pub fn new(r0c0: F, r0c1: F,
156               r1c0: F, r1c1: F) -> Mat2<F>
157    {
158        Mat2 { // looks transposed because stored column-major
159            x: Vec2::new(r0c0, r1c0),
160            y: Vec2::new(r0c1, r1c1),
161        }
162    }
163
164    #[inline]
165    pub fn from_cols(x: Vec2<F>, y: Vec2<F>) -> Mat2<F>
166    {
167        Mat2 { x: x, y: y }
168    }
169}
170
171impl<F: FullFloat> Mat3<F> {
172    /// Create a new 3x3 Matrix. Specify parameters in row-major order
173    /// (as typically written on paper and in math texts)
174    #[inline]
175    pub fn new(r0c0: F, r0c1: F, r0c2: F,
176               r1c0: F, r1c1: F, r1c2: F,
177               r2c0: F, r2c1: F, r2c2: F) -> Mat3<F>
178    {
179        Mat3 { // looks transposed because stored column-major
180            x: Vec3::new(r0c0, r1c0, r2c0),
181            y: Vec3::new(r0c1, r1c1, r2c1),
182            z: Vec3::new(r0c2, r1c2, r2c2),
183        }
184    }
185
186    #[inline]
187    pub fn from_cols(x: Vec3<F>, y: Vec3<F>, z: Vec3<F>) -> Mat3<F>
188    {
189        Mat3 { x: x, y: y, z: z }
190    }
191}
192
193impl<F: FullFloat> Mat4<F> {
194    /// Create a new 4x4 Matrix. Specify parameters in row-major order
195    /// (as typically written on paper and in math texts)
196    #[inline]
197    pub fn new(r0c0: F, r0c1: F, r0c2: F, r0c3: F,
198               r1c0: F, r1c1: F, r1c2: F, r1c3: F,
199               r2c0: F, r2c1: F, r2c2: F, r2c3: F,
200               r3c0: F, r3c1: F, r3c2: F, r3c3: F) -> Mat4<F>
201    {
202        Mat4 { // looks transposed because stored column-major
203            x: Vec4::new(r0c0, r1c0, r2c0, r3c0),
204            y: Vec4::new(r0c1, r1c1, r2c1, r3c1),
205            z: Vec4::new(r0c2, r1c2, r2c2, r3c2),
206            p: Vec4::new(r0c3, r1c3, r2c3, r3c3),
207        }
208    }
209
210    #[inline]
211    pub fn from_cols(x: Vec4<F>, y: Vec4<F>, z: Vec4<F>, p: Vec4<F>) -> Mat4<F>
212    {
213        Mat4 { x: x, y: y, z: z, p: p }
214    }
215}
216
217impl<F: FullFloat> Mat4<F> {
218    #[inline]
219    pub fn from_components(x_dir: Direction3<F>, y_dir: Direction3<F>, z_dir: Direction3<F>,
220                           pos: Point3<F>) -> Mat4<F>
221    {
222        // get access to the direction components
223        let x_dir: Vec3<F> = From::from(x_dir);
224        let y_dir: Vec3<F> = From::from(y_dir);
225        let z_dir: Vec3<F> = From::from(z_dir);
226
227        Mat4 {  // looks transposed because stored column-major
228            x: Vec4::new(x_dir.x, x_dir.y, x_dir.z, F::zero()),
229            y: Vec4::new(y_dir.x, y_dir.y, y_dir.z, F::zero()),
230            z: Vec4::new(z_dir.x, z_dir.y, z_dir.z, F::zero()),
231            p: Vec4::new(pos.0.x, pos.0.y, pos.0.z, F::one())
232        }
233    }
234
235    #[inline]
236    pub fn from_mat3(mat3: Mat3<F>, pos: Point3<F>) -> Mat4<F>
237    {
238        Mat4 {  // looks transposed because stored column-major
239            x: Vec4::new(mat3.x.x, mat3.x.y, mat3.x.z, F::zero()),
240            y: Vec4::new(mat3.y.x, mat3.y.y, mat3.y.z, F::zero()),
241            z: Vec4::new(mat3.z.x, mat3.z.y, mat3.z.z, F::zero()),
242            p: Vec4::new( pos.0.x,  pos.0.y,  pos.0.z, F::one())
243        }
244    }
245}
246
247// -- impl Default ------------------------------------------------------------
248
249impl<F: FullFloat> Default for Mat2<F> {
250    #[inline]
251    fn default() -> Mat2<F> {
252        Mat2::new( F::default(), F::default(),
253                   F::default(), F::default() )
254    }
255}
256
257impl<F: FullFloat> Default for Mat3<F> {
258    #[inline]
259    fn default() -> Mat3<F> {
260        Mat3::new( F::default(), F::default(), F::default(),
261                   F::default(), F::default(), F::default(),
262                   F::default(), F::default(), F::default() )
263    }
264}
265
266impl<F: FullFloat> Default for Mat4<F> {
267    #[inline]
268    fn default() -> Mat4<F> {
269        Mat4::new( F::default(), F::default(), F::default(), F::default(),
270                   F::default(), F::default(), F::default(), F::default(),
271                   F::default(), F::default(), F::default(), F::default(),
272                   F::default(), F::default(), F::default(), F::default() )
273    }
274}
275
276// -- zero --------------------------------------------------------------------
277
278impl<F: FullFloat> Mat2<F> {
279    #[inline]
280    pub fn zero() -> Mat2<F>
281    {
282        Mat2::new( F::zero(), F::zero(),
283                   F::zero(), F::zero() )
284    }
285}
286
287impl<F: FullFloat> Mat3<F> {
288    #[inline]
289    pub fn zero() -> Mat3<F>
290    {
291        Mat3::new( F::zero(), F::zero(), F::zero(),
292                   F::zero(), F::zero(), F::zero(),
293                   F::zero(), F::zero(), F::zero() )
294    }
295}
296
297impl<F: FullFloat> Mat4<F> {
298    #[inline]
299    pub fn zero() -> Mat4<F>
300    {
301        Mat4::new( F::zero(), F::zero(), F::zero(), F::zero(),
302                   F::zero(), F::zero(), F::zero(), F::zero(),
303                   F::zero(), F::zero(), F::zero(), F::zero(),
304                   F::zero(), F::zero(), F::zero(), F::zero() )
305    }
306}
307
308// -- identity ---------------------------------------------------------------
309
310impl<F: FullFloat> Mat2<F> {
311    #[inline]
312    pub fn identity() -> Mat2<F>
313    {
314        Mat2::new( F::one(), F::zero(),
315                   F::zero(), F::one() )
316    }
317}
318
319impl<F: FullFloat> Mat3<F> {
320    #[inline]
321    pub fn identity() -> Mat3<F>
322    {
323        Mat3::new( F::one(), F::zero(), F::zero(),
324                   F::zero(), F::one(), F::zero(),
325                   F::zero(), F::zero(), F::one() )
326    }
327}
328
329impl<F: FullFloat> Mat4<F> {
330    #[inline]
331    pub fn identity() -> Mat4<F>
332    {
333        Mat4::new( F::one(), F::zero(), F::zero(), F::zero(),
334                   F::zero(), F::one(), F::zero(), F::zero(),
335                   F::zero(), F::zero(), F::one(), F::zero(),
336                   F::zero(), F::zero(), F::zero(), F::one() )
337    }
338}
339
340// -- transpose ---------------------------------------------------------------
341
342impl<F: FullFloat> Mat2<F> {
343    #[inline]
344    pub fn transpose(&mut self) {
345        ::std::mem::swap(&mut self.x.y, &mut self.y.x);
346    }
347}
348
349impl<F: FullFloat> Mat3<F> {
350    #[inline]
351    pub fn transpose(&mut self) {
352        ::std::mem::swap(&mut self.x.y, &mut self.y.x);
353        ::std::mem::swap(&mut self.x.z, &mut self.z.x);
354        ::std::mem::swap(&mut self.y.z, &mut self.z.y);
355    }
356}
357
358impl<F: FullFloat> Mat4<F> {
359    #[inline]
360    pub fn transpose(&mut self) {
361        ::std::mem::swap(&mut self.x.y, &mut self.y.x);
362        ::std::mem::swap(&mut self.x.z, &mut self.z.x);
363        ::std::mem::swap(&mut self.x.w, &mut self.p.x);
364        ::std::mem::swap(&mut self.y.z, &mut self.z.y);
365        ::std::mem::swap(&mut self.y.w, &mut self.p.y);
366        ::std::mem::swap(&mut self.z.w, &mut self.p.z);
367    }
368}
369
370// -- inverse -----------------------------------------------------------------
371
372impl<F: FullFloat> Mat2<F> {
373    #[inline]
374    pub fn determinant(&self) -> F {
375        self.x.x * self.y.y - self.y.x * self.x.y
376    }
377
378    #[inline]
379    pub fn inverse(&self) -> Option<Mat2<F>> {
380        let d = self.determinant();
381        if d == F::zero() { return None; }
382        Some(Mat2::new( self.y.y/d, -self.y.x/d,
383                        -self.x.y/d, self.x.x/d ))
384    }
385}
386
387impl<F: FullFloat> Mat3<F> {
388    #[inline]
389    pub fn determinant(&self) -> F {
390        self.x.x * (self.y.y * self.z.z - self.z.y * self.y.z)
391            - self.y.x * (self.x.y * self.z.z - self.z.y * self.x.z)
392            + self.z.x * (self.x.y * self.y.z - self.y.y * self.x.z)
393    }
394
395    #[inline]
396    pub fn inverse(&self) -> Option<Mat3<F>> {
397        let d = self.determinant();
398        if d == F::zero() { return None; }
399        let mut out = Mat3::from_cols(
400            self.y.cross(self.z) / d,
401            self.z.cross(self.x) / d,
402            self.x.cross(self.y) / d);
403        out.transpose();
404        Some(out)
405    }
406}
407
408impl<F: FullFloat> Mat4<F> {
409    #[inline]
410    pub fn determinant(&self) -> F {
411        self.x.x * Mat3::new( self.y.y, self.z.y, self.p.y,
412                              self.y.z, self.z.z, self.p.z,
413                              self.y.w, self.z.w, self.p.w ).determinant()
414            - self.y.x * Mat3::new( self.x.y, self.z.y, self.p.y,
415                                    self.x.z, self.z.z, self.p.z,
416                                    self.x.w, self.z.w, self.p.w ).determinant()
417            + self.z.x * Mat3::new( self.x.y, self.y.y, self.p.y,
418                                    self.x.z, self.y.z, self.p.z,
419                                    self.x.w, self.y.w, self.p.w ).determinant()
420            - self.p.x * Mat3::new( self.x.y, self.y.y, self.z.y,
421                                    self.x.z, self.y.z, self.z.z,
422                                    self.x.w, self.y.w, self.z.w ).determinant()
423    }
424
425    #[inline]
426    pub fn inverse(&self) -> Option<Mat4<F>> {
427        let d = self.determinant();
428        if d == F::zero() { return None; }
429        let id = F::one() / d;
430        let mut t = self.clone();
431        t.transpose();
432        let cf = |i, j| {
433            let mat = match i {
434                0 => Mat3::from_cols(t.y.truncate_n(j), t.z.truncate_n(j), t.p.truncate_n(j)),
435                1 => Mat3::from_cols(t.x.truncate_n(j), t.z.truncate_n(j), t.p.truncate_n(j)),
436                2 => Mat3::from_cols(t.x.truncate_n(j), t.y.truncate_n(j), t.p.truncate_n(j)),
437                3 => Mat3::from_cols(t.x.truncate_n(j), t.y.truncate_n(j), t.z.truncate_n(j)),
438                _ => panic!("out of range"),
439            };
440            let sign = if (i+j)&1 == 1 { -F::one() } else { F::one() };
441            mat.determinant() * sign *id
442        };
443
444        Some(Mat4::new( cf(0,0), cf(1,0), cf(2,0), cf(3,0),
445                        cf(0,1), cf(1,1), cf(2,1), cf(3,1),
446                        cf(0,2), cf(1,2), cf(2,2), cf(3,2),
447                        cf(0,3), cf(1,3), cf(2,3), cf(3,3) ))
448    }
449}
450
451// -- add ---------------------------------------------------------------------
452
453impl<'a, 'b, F: FullFloat> Add<&'b Mat2<F>> for &'a Mat2<F> {
454    type Output = Mat2<F>;
455
456    #[inline]
457    fn add(self, rhs: &Mat2<F>) -> Mat2<F> {
458        Mat2::new( self.x.x + rhs.x.x,  self.y.x + rhs.y.x,
459                   self.x.y + rhs.x.y,  self.y.y + rhs.y.y )
460    }
461}
462
463impl<'a, 'b, F: FullFloat> Add<&'b Mat3<F>> for &'a Mat3<F> {
464    type Output = Mat3<F>;
465
466    #[inline]
467    fn add(self, rhs: &Mat3<F>) -> Mat3<F> {
468        Mat3::new( self.x.x + rhs.x.x,  self.y.x + rhs.y.x,  self.z.x + rhs.z.x,
469                   self.x.y + rhs.x.y,  self.y.y + rhs.y.y,  self.z.y + rhs.z.y,
470                   self.x.z + rhs.x.z,  self.y.z + rhs.y.z,  self.z.z + rhs.z.z )
471    }
472}
473
474impl<'a, 'b, F: FullFloat> Add<&'b Mat4<F>> for &'a Mat4<F> {
475    type Output = Mat4<F>;
476
477    #[inline]
478    fn add(self, rhs: &Mat4<F>) -> Mat4<F> {
479        Mat4::new(
480            self.x.x + rhs.x.x, self.y.x + rhs.y.x, self.z.x + rhs.z.x, self.p.x + rhs.p.x,
481            self.x.y + rhs.x.y, self.y.y + rhs.y.y, self.z.y + rhs.z.y, self.p.y + rhs.p.y,
482            self.x.z + rhs.x.z, self.y.z + rhs.y.z, self.z.z + rhs.z.z, self.p.z + rhs.p.z,
483            self.x.w + rhs.x.w, self.y.w + rhs.y.z, self.z.w + rhs.z.w, self.p.w + rhs.p.w )
484    }
485}
486
487// -- multiply by scalar ------------------------------------------------------
488
489impl<'a, F: FullFloat> Mul<F> for &'a Mat2<F> {
490    type Output = Mat2<F>;
491
492    #[inline]
493    fn mul(self, rhs: F) -> Mat2<F> {
494        Mat2::new( self.x.x * rhs, self.y.x * rhs,
495                   self.x.y * rhs, self.y.y * rhs )
496    }
497}
498
499impl<'a, F: FullFloat> Mul<F> for &'a Mat3<F> {
500    type Output = Mat3<F>;
501
502    #[inline]
503    fn mul(self, rhs: F) -> Mat3<F> {
504        Mat3::new( self.x.x * rhs, self.y.x * rhs, self.z.x * rhs,
505                   self.x.y * rhs, self.y.y * rhs, self.z.y * rhs,
506                   self.x.z * rhs, self.y.z * rhs, self.z.z * rhs )
507    }
508}
509
510impl<'a, F: FullFloat> Mul<F> for &'a Mat4<F> {
511    type Output = Mat4<F>;
512
513    #[inline]
514    fn mul(self, rhs: F) -> Mat4<F> {
515        Mat4::new( self.x.x * rhs, self.y.x * rhs, self.z.x * rhs, self.p.x * rhs,
516                   self.x.y * rhs, self.y.y * rhs, self.z.y * rhs, self.p.y * rhs,
517                   self.x.z * rhs, self.y.z * rhs, self.z.z * rhs, self.p.z * rhs,
518                   self.x.w * rhs, self.y.w * rhs, self.z.w * rhs, self.p.w * rhs )
519    }
520}
521
522// -- multiply by matrix ------------------------------------------------------
523
524impl<'a, 'b, F: FullFloat> Mul<&'b Mat2<F>> for &'a Mat2<F> {
525    type Output = Mat2<F>;
526
527    #[inline]
528    fn mul(self, rhs: &Mat2<F>) -> Mat2<F> {
529        Mat2::new(
530            self.x.x * rhs.x.x + self.y.x * rhs.x.y,  self.x.x * rhs.y.x + self.y.x * rhs.y.y,
531            self.x.y * rhs.x.x + self.y.y * rhs.x.y,  self.x.y * rhs.y.x + self.y.y * rhs.y.y)
532    }
533}
534
535impl<'a, 'b, F: FullFloat> Mul<&'b Mat3<F>> for &'a Mat3<F> {
536    type Output = Mat3<F>;
537
538    #[inline]
539    fn mul(self, rhs: &Mat3<F>) -> Mat3<F> {
540        Mat3::new(
541            self.x.x * rhs.x.x + self.y.x * rhs.x.y + self.z.x * rhs.x.z,
542            self.x.x * rhs.y.x + self.y.x * rhs.y.y + self.z.x * rhs.y.z,
543            self.x.x * rhs.z.x + self.y.x * rhs.z.y + self.z.x * rhs.z.z,
544
545            self.x.y * rhs.x.x + self.y.y * rhs.x.y + self.z.y * rhs.x.z,
546            self.x.y * rhs.y.x + self.y.y * rhs.y.y + self.z.y * rhs.y.z,
547            self.x.y * rhs.z.x + self.y.y * rhs.z.y + self.z.y * rhs.z.z,
548
549            self.x.z * rhs.x.x + self.y.z * rhs.x.y + self.z.z * rhs.x.z,
550            self.x.z * rhs.y.x + self.y.z * rhs.y.y + self.z.z * rhs.y.z,
551            self.x.z * rhs.z.x + self.y.z * rhs.z.y + self.z.z * rhs.z.z)
552    }
553}
554
555impl<'a, 'b, F: FullFloat> Mul<&'b Mat4<F>> for &'a Mat4<F> {
556    type Output = Mat4<F>;
557
558    #[inline]
559    fn mul(self, rhs: &Mat4<F>) -> Mat4<F> {
560        Mat4::new(
561            self.x.x * rhs.x.x + self.y.x * rhs.x.y + self.z.x * rhs.x.z + self.p.x * rhs.x.w,
562            self.x.x * rhs.y.x + self.y.x * rhs.y.y + self.z.x * rhs.y.z + self.p.x * rhs.y.w,
563            self.x.x * rhs.z.x + self.y.x * rhs.z.y + self.z.x * rhs.z.z + self.p.x * rhs.z.w,
564            self.x.x * rhs.p.x + self.y.x * rhs.p.y + self.z.x * rhs.p.z + self.p.x * rhs.p.w,
565
566            self.x.y * rhs.x.x + self.y.y * rhs.x.y + self.z.y * rhs.x.z + self.p.y * rhs.x.w,
567            self.x.y * rhs.y.x + self.y.y * rhs.y.y + self.z.y * rhs.y.z + self.p.y * rhs.y.w,
568            self.x.y * rhs.z.x + self.y.y * rhs.z.y + self.z.y * rhs.z.z + self.p.y * rhs.z.w,
569            self.x.y * rhs.p.x + self.y.y * rhs.p.y + self.z.y * rhs.p.z + self.p.y * rhs.p.w,
570
571            self.x.z * rhs.x.x + self.y.z * rhs.x.y + self.z.z * rhs.x.z + self.p.z * rhs.x.w,
572            self.x.z * rhs.y.x + self.y.z * rhs.y.y + self.z.z * rhs.y.z + self.p.z * rhs.y.w,
573            self.x.z * rhs.z.x + self.y.z * rhs.z.y + self.z.z * rhs.z.z + self.p.z * rhs.z.w,
574            self.x.z * rhs.p.x + self.y.z * rhs.p.y + self.z.z * rhs.p.z + self.p.z * rhs.p.w,
575
576            self.x.w * rhs.x.x + self.y.w * rhs.x.y + self.z.w * rhs.x.z + self.p.w * rhs.x.w,
577            self.x.w * rhs.y.x + self.y.w * rhs.y.y + self.z.w * rhs.y.z + self.p.w * rhs.y.w,
578            self.x.w * rhs.z.x + self.y.w * rhs.z.y + self.z.w * rhs.z.z + self.p.w * rhs.z.w,
579            self.x.w * rhs.p.x + self.y.w * rhs.p.y + self.z.w * rhs.p.z + self.p.w * rhs.p.w )
580    }
581}
582
583// -- multiply by vector ------------------------------------------------------
584
585impl<'a, 'b, F: FullFloat> Mul<&'a Vec2<F>> for &'b Mat2<F> {
586    type Output = Vec2<F>;
587
588    #[inline]
589    fn mul(self, rhs: &Vec2<F>) -> Vec2<F> {
590        Vec2::new( self.x.x * rhs.x + self.y.x * rhs.y,
591                   self.x.y * rhs.x + self.y.y * rhs.y )
592    }
593}
594
595impl<'a, 'b, F: FullFloat> Mul<&'a Vec3<F>> for &'b Mat3<F> {
596    type Output = Vec3<F>;
597
598    #[inline]
599    fn mul(self, rhs: &Vec3<F>) -> Vec3<F> {
600        Vec3::new( self.x.x * rhs.x + self.y.x * rhs.y + self.z.x * rhs.z,
601                   self.x.y * rhs.x + self.y.y * rhs.y + self.z.y * rhs.z,
602                   self.x.z * rhs.x + self.y.z * rhs.y + self.z.z * rhs.z)
603    }
604}
605
606impl<'a, 'b, F: FullFloat> Mul<&'a Vec4<F>> for &'b Mat4<F> {
607    type Output = Vec4<F>;
608
609    #[inline]
610    fn mul(self, rhs: &Vec4<F>) -> Vec4<F> {
611        Vec4::new( self.x.x * rhs.x + self.y.x * rhs.y + self.z.x * rhs.z + self.p.x * rhs.w,
612                   self.x.y * rhs.x + self.y.y * rhs.y + self.z.y * rhs.z + self.p.y * rhs.w,
613                   self.x.z * rhs.x + self.y.z * rhs.y + self.z.z * rhs.z + self.p.z * rhs.w,
614                   self.x.w * rhs.x + self.y.w * rhs.y + self.z.w * rhs.z + self.p.w * rhs.w)
615    }
616}
617
618// -- multiply vector by matrix -----------------------------------------------
619
620impl<'a, 'b, F: FullFloat> Mul<&'a Mat2<F>> for &'a Vec2<F> {
621    type Output = Vec2<F>;
622
623    #[inline]
624    fn mul(self, rhs: &Mat2<F>) -> Vec2<F> {
625        Vec2::new( self.x * rhs.x.x + self.y * rhs.x.y,
626                   self.x * rhs.y.x + self.y * rhs.y.y )
627    }
628}
629
630impl<'a, 'b, F: FullFloat> Mul<&'a Mat3<F>> for &'a Vec3<F> {
631    type Output = Vec3<F>;
632
633    #[inline]
634    fn mul(self, rhs: &Mat3<F>) -> Vec3<F> {
635        Vec3::new( self.x * rhs.x.x + self.y * rhs.x.y + self.z * rhs.x.z,
636                   self.x * rhs.y.x + self.y * rhs.y.y + self.z * rhs.y.z,
637                   self.x * rhs.z.x + self.y * rhs.z.y + self.z * rhs.z.z)
638    }
639}
640
641impl<'a, 'b, F: FullFloat> Mul<&'a Mat4<F>> for &'a Vec4<F> {
642    type Output = Vec4<F>;
643
644    #[inline]
645    fn mul(self, rhs: &Mat4<F>) -> Vec4<F> {
646        Vec4::new( self.x * rhs.x.x + self.y * rhs.x.y + self.z * rhs.x.z + self.w * rhs.x.w,
647                   self.x * rhs.y.x + self.y * rhs.y.y + self.z * rhs.y.z + self.w * rhs.y.w,
648                   self.x * rhs.z.x + self.y * rhs.z.y + self.z * rhs.z.z + self.w * rhs.z.w,
649                   self.x * rhs.p.x + self.y * rhs.p.y + self.z * rhs.p.z + self.w * rhs.p.w)
650    }
651}
652
653// -- characteristic tests ----------------------------------------------------
654
655impl<F: FullFloat> Mat2<F> {
656    #[inline]
657    pub fn is_diagonal(&self) -> bool {
658        self.x.y == F::zero() && self.y.x == F::zero()
659    }
660}
661
662impl<F: FullFloat> Mat3<F> {
663    #[inline]
664    pub fn is_diagonal(&self) -> bool {
665        self.x.y == F::zero() && self.x.z == F::zero() &&
666            self.y.x == F::zero() && self.y.z == F::zero() &&
667            self.z.x == F::zero() && self.z.y == F::zero()
668    }
669}
670
671impl<F: FullFloat> Mat4<F> {
672    #[inline]
673    pub fn is_diagonal(&self) -> bool {
674        self.x.y == F::zero() && self.x.z == F::zero() && self.x.w == F::zero() &&
675            self.y.x == F::zero() && self.y.z == F::zero() && self.y.w == F::zero() &&
676            self.z.x == F::zero() && self.z.y == F::zero() && self.p.w == F::zero() &&
677            self.p.x == F::zero() && self.p.y == F::zero() && self.z.z == F::zero()
678    }
679}
680
681impl<F: FullFloat> Mat2<F> {
682    #[inline]
683    pub fn is_symmetric(&self) -> bool {
684        self.x.y == self.y.x
685    }
686}
687
688
689impl<F: FullFloat> Mat3<F> {
690    #[inline]
691    pub fn is_symmetric(&self) -> bool {
692        self.x.y == self.y.x &&
693            self.x.z == self.z.x &&
694            self.y.z == self.z.y
695    }
696}
697
698impl<F: FullFloat> Mat4<F> {
699    #[inline]
700    pub fn is_symmetric(&self) -> bool {
701        self.x.y == self.y.x &&
702            self.x.z == self.z.x &&
703            self.x.w == self.p.x &&
704            self.y.z == self.z.y &&
705            self.y.w == self.p.y &&
706            self.z.w == self.p.z
707    }
708}
709
710impl<F: FullFloat> Mat2<F> {
711    #[inline]
712    pub fn is_skew_symmetric(&self) -> bool {
713        self.x.y == -self.y.x
714    }
715}
716
717impl<F: FullFloat> Mat3<F> {
718    #[inline]
719    pub fn is_skew_symmetric(&self) -> bool {
720        self.x.y == -self.y.x &&
721            self.x.z == -self.z.x &&
722            self.y.z == -self.z.y
723    }
724}
725
726impl<F: FullFloat> Mat4<F> {
727    #[inline]
728    pub fn is_skew_symmetric(&self) -> bool {
729        self.x.y == -self.y.x &&
730            self.x.z == -self.z.x &&
731            self.x.w == -self.p.x &&
732            self.y.z == -self.z.y &&
733            self.y.w == -self.p.y &&
734            self.z.w == -self.p.z
735    }
736}
737
738// -- mat4 components ---------------------------------------------------------
739
740impl<F: FullFloat> Mat4<F> {
741    pub fn get_translation(&self) -> Point3<F>
742    {
743        Point3(self.p.truncate_w())
744    }
745}
746
747impl<F: FullFloat> Mat4<F> {
748    pub fn set_translation(&mut self, p: Point3<F>)
749    {
750        self.p = From::from(p);
751    }
752}
753
754// -- rotation matrices -------------------------------------------------------
755
756impl<F: FullFloat> Mat2<F> {
757    #[inline]
758    pub fn from_angle(theta: Angle<F>) -> Mat2<F> {
759        let (s, c) = theta.as_radians().sin_cos();
760        Mat2 {
761            x: Vec2::new(c, s),
762            y: Vec2::new(-s, c),
763        }
764    }
765}
766
767impl<F: FullFloat> Mat3<F> {
768    #[inline]
769    pub fn from_angle_x(theta: Angle<F>) -> Mat3<F> {
770        let (s, c) = theta.as_radians().sin_cos();
771        Mat3::new( F::one(),  F::zero(), F::zero(),
772                   F::zero(), c,         -s,
773                   F::zero(), s,         c )
774    }
775
776    #[inline]
777    pub fn from_angle_y(theta: Angle<F>) -> Mat3<F> {
778        let (s, c) = theta.as_radians().sin_cos();
779        Mat3::new( c,         F::zero(), s,
780                   F::zero(), F::one(),  F::zero(),
781                   -s,        F::zero(), c )
782    }
783
784    #[inline]
785    pub fn from_angle_z(theta: Angle<F>) -> Mat3<F> {
786        let (s, c) = theta.as_radians().sin_cos();
787        Mat3::new(  c,        -s,         F::zero(),
788                    s,         c,         F::zero(),
789                    F::zero(), F::zero(), F::one() )
790    }
791}
792
793impl<F: FullFloat> Mat3<F> {
794    // https://en.wikipedia.org/w/index.php?title=Rotation_matrix
795    //  #Rotation_matrix_from_axis_and_angle
796    pub fn rotate_axis_angle(axis: Direction3<F>, theta: Angle<F>) -> Mat3<F> {
797        let axis: Vec3<F> = From::from(axis);
798        let x = axis.x;
799        let y = axis.y;
800        let z = axis.z;
801        let (s, c) = theta.as_radians().sin_cos();
802        let ic = F::one() - c;
803        Mat3::new( x*x*ic + c   , x*y*ic - z*s ,  x*z*ic + y*s,
804                   y*x*ic + z*s , y*y*ic + c   ,  y*z*ic - x*s,
805                   z*x*ic - y*s , z*y*ic + x*s ,  z*z*ic + c   )
806    }
807}
808
809impl<F: FullFloat> Mat4<F> {
810    #[inline]
811    pub fn from_angle_x(theta: Angle<F>) -> Mat4<F> {
812        let (s, c) = theta.as_radians().sin_cos();
813        Mat4::new( F::one(),  F::zero(), F::zero(), F::zero(),
814                   F::zero(), c,        -s,         F::zero(),
815                   F::zero(), s,         c,         F::zero(),
816                   F::zero(), F::zero(), F::zero(), F::one() )
817    }
818
819    #[inline]
820    pub fn from_angle_y(theta: Angle<F>) -> Mat4<F> {
821        let (s, c) = theta.as_radians().sin_cos();
822        Mat4::new( c        , F::zero(),         s, F::zero(),
823                   F::zero(), F::one(),  F::zero(), F::zero(),
824                   -s       , F::zero(),         c, F::zero(),
825                   F::zero(), F::zero(), F::zero(), F::one()   )
826    }
827
828    #[inline]
829    pub fn from_angle_z(theta: Angle<F>) -> Mat4<F> {
830        let (s, c) = theta.as_radians().sin_cos();
831        Mat4::new( c        ,         s, F::zero(), F::zero(),
832                   -s       ,         c, F::zero(), F::zero(),
833                   F::zero(), F::zero(), F::one(),  F::zero(),
834                   F::zero(), F::zero(), F::zero(), F::one()   )
835    }
836}
837
838impl<F: FullFloat> Mat4<F> {
839    // https://en.wikipedia.org/w/index.php?title=Rotation_matrix
840    //  #Rotation_matrix_from_axis_and_angle
841    pub fn rotate_axis_angle(axis: Direction3<F>, theta: Angle<F>) -> Mat4<F> {
842        let axis: Vec3<F> = From::from(axis);
843        let x = axis.x;
844        let y = axis.y;
845        let z = axis.z;
846        let (s, c) = theta.as_radians().sin_cos();
847        let ic = F::one() - c;
848        Mat4::new( x*x*ic + c  , x*y*ic - z*s, x*z*ic + y*s,  F::zero(),
849                   y*x*ic + z*s, y*y*ic + c  , y*z*ic - x*s,  F::zero(),
850                   z*x*ic - y*s, z*y*ic + x*s, z*z*ic + c  ,  F::zero(),
851                   F::zero(),       F::zero(),    F::zero(),  F::one()  )
852    }
853}
854
855// -- Reflection --------------------------------------------------------------
856
857impl<F: FullFloat> Mat3<F> {
858    #[inline]
859    /// Reflection matrix
860    pub fn reflect_origin_plane(a: Direction3<F>) -> Mat3<F> {
861        let a: Vec3<F> = From::from(a);
862        let minus_two: F = NumCast::from(-2.0_f32).unwrap();
863        let x: F = a.x * minus_two;
864        let y: F = a.y * minus_two;
865        let z: F = a.z * minus_two;
866        let axay = x * a.y;
867        let axaz = x * a.z;
868        let ayaz = y * a.z;
869        Mat3::new( x * a.x + F::one(), axay,               axaz,
870                   axay,               y * a.y + F::one(), ayaz,
871                   axaz,               ayaz,               z * a.z + F::one() )
872    }
873}
874
875impl<F: FullFloat> Mat3<F> {
876    #[inline]
877    /// Involution matrix
878    pub fn involve_origin_plane(a: Direction3<F>) -> Mat3<F> {
879        let a: Vec3<F> = From::from(a);
880        let two: F = NumCast::from(2.0_f32).unwrap();
881        let x: F = a.x * two;
882        let y: F = a.y * two;
883        let z: F = a.z * two;
884        let axay = x * a.y;
885        let axaz = x * a.z;
886        let ayaz = y * a.z;
887        Mat3::new( x * a.x - F::one(), axay,               axaz,
888                   axay,               y * a.y - F::one(), ayaz,
889                   axaz,               ayaz,               z * a.z - F::one() )
890    }
891}
892
893// -- Scale -------------------------------------------------------------------
894
895impl<F: FullFloat> Mat3<F> {
896    #[inline]
897    /// Scale matrix
898    pub fn scale(a: &Vec3<F>) -> Mat3<F> {
899        Mat3::new(a.x, F::zero(), F::zero(),
900                  F::zero(), a.y, F::zero(),
901                  F::zero(), F::zero(), a.z)
902    }
903}
904
905impl<F: FullFloat> Mat4<F> {
906    #[inline]
907    /// Scale matrix
908    pub fn scale(a: &Vec4<F>) -> Mat4<F> {
909        Mat4::new(a.x, F::zero(), F::zero(), F::zero(),
910                  F::zero(), a.y, F::zero(), F::zero(),
911                  F::zero(), F::zero(), a.z, F::zero(),
912                  F::zero(), F::zero(), F::zero(), a.w)
913    }
914}
915
916
917impl<F: FullFloat> Mat3<F> {
918    /// Scale along vector
919    pub fn scale_in_direction(mut s: F, a: Direction3<F>) -> Mat3<F> {
920        let a: Vec3<F> = From::from(a);
921        s -= F::one();
922        let x = a.x * s;
923        let y = a.y * s;
924        let z = a.z * s;
925        let axay = x * a.y;
926        let axaz = x * a.z;
927        let ayaz = y * a.z;
928        Mat3::new(x * a.x + F::one(), axay,               axaz,
929                  axay,               y * a.y + F::one(), ayaz,
930                  axaz,               ayaz,               z * a.z + F::one())
931    }
932}
933
934impl<F: FullFloat> Mat4<F> {
935    pub fn get_x_scale(&self) -> F {
936        let scale = (self.x.x * self.x.x
937                     + self.y.x * self.y.x
938                     + self.z.x * self.z.x).sqrt();
939        if self.x.x < F::zero() { -scale } else { scale }
940    }
941
942    pub fn get_y_scale(&self) -> F {
943        let scale = (self.x.y * self.x.y
944                     + self.y.y * self.y.y
945                     + self.z.y * self.z.y).sqrt();
946        if self.y.y < F::zero() { -scale } else { scale }
947    }
948
949    pub fn get_z_scale(&self) -> F {
950        let scale = (self.x.z * self.x.z
951                     + self.y.z * self.y.z
952                     + self.z.z * self.z.z).sqrt();
953        if self.z.z < F::zero() { -scale } else { scale }
954    }
955}
956
957// -- Skew --------------------------------------------------------------------
958
959impl<F: FullFloat> Mat3<F> {
960    /// Skew by give given angle in the given direction a, based on the projected
961    /// length along the proj direction.  direction and proj MUST BE PERPENDICULAR
962    /// or else results are undefined.
963    pub fn skew(angle: Angle<F>, a: Direction3<F>, proj: Direction3<F>) -> Mat3<F> {
964        let a: Vec3<F> = From::from(a);
965        let b: Vec3<F> = From::from(proj);
966        let t = angle.as_radians().tan();
967        let x: F = a.x * t;
968        let y: F = a.y * t;
969        let z: F = a.z * t;
970        Mat3::new(x * b.x + F::one(), x * b.y,            x * b.z,
971                  y * b.x,            y * b.y + F::one(), y * b.z,
972                  z * b.x,            z * b.y,            z * b.z + F::one())
973    }
974}
975
976// ----------------------------------------------------------------------------
977// Convert between f32 and f64
978
979impl From<Mat3<f32>> for Mat3<f64> {
980    fn from(m: Mat3<f32>) -> Mat3<f64> {
981        Mat3 {
982            x: Vec3 { x: m.x.x as f64, y: m.x.y as f64, z: m.x.z as f64 },
983            y: Vec3 { x: m.y.x as f64, y: m.y.y as f64, z: m.y.z as f64 },
984            z: Vec3 { x: m.z.x as f64, y: m.z.y as f64, z: m.z.z as f64 },
985        }
986    }
987}
988
989impl From<Mat3<f64>> for Mat3<f32> {
990    fn from(m: Mat3<f64>) -> Mat3<f32> {
991        Mat3 {
992            x: Vec3 { x: m.x.x as f32, y: m.x.y as f32, z: m.x.z as f32 },
993            y: Vec3 { x: m.y.x as f32, y: m.y.y as f32, z: m.y.z as f32 },
994            z: Vec3 { x: m.z.x as f32, y: m.z.y as f32, z: m.z.z as f32 },
995        }
996    }
997}
998
999impl From<Mat4<f32>> for Mat4<f64> {
1000    fn from(m: Mat4<f32>) -> Mat4<f64> {
1001        Mat4 {
1002            x: Vec4 { x: m.x.x as f64, y: m.x.y as f64, z: m.x.z as f64, w: m.x.w as f64 },
1003            y: Vec4 { x: m.y.x as f64, y: m.y.y as f64, z: m.y.z as f64, w: m.y.w as f64 },
1004            z: Vec4 { x: m.z.x as f64, y: m.z.y as f64, z: m.z.z as f64, w: m.z.w as f64 },
1005            p: Vec4 { x: m.p.x as f64, y: m.p.y as f64, z: m.p.z as f64, w: m.p.w as f64 },
1006        }
1007    }
1008}
1009
1010impl From<Mat4<f64>> for Mat4<f32> {
1011    fn from(m: Mat4<f64>) -> Mat4<f32> {
1012        Mat4 {
1013            x: Vec4 { x: m.x.x as f32, y: m.x.y as f32, z: m.x.z as f32, w: m.x.w as f32 },
1014            y: Vec4 { x: m.y.x as f32, y: m.y.y as f32, z: m.y.z as f32, w: m.y.w as f32 },
1015            z: Vec4 { x: m.z.x as f32, y: m.z.y as f32, z: m.z.z as f32, w: m.z.w as f32 },
1016            p: Vec4 { x: m.p.x as f32, y: m.p.y as f32, z: m.p.z as f32, w: m.p.w as f32 },
1017        }
1018    }
1019}
1020
1021// ----------------------------------------------------------------------------
1022// Convert between sizes
1023
1024impl<F: FullFloat> Mat4<F> {
1025    pub fn as_mat3(&self) -> Mat3<F> {
1026        Mat3 {
1027            x: Vec3::new(self.x.x, self.x.y, self.x.z),
1028            y: Vec3::new(self.y.x, self.y.y, self.y.z),
1029            z: Vec3::new(self.z.x, self.z.y, self.z.z),
1030        }
1031    }
1032}
1033
1034impl<F: FullFloat> Mat3<F> {
1035    pub fn as_mat4(&self) -> Mat4<F> {
1036        Mat4 {
1037            x: Vec4::new(self.x.x, self.x.y, self.x.z, F::zero()),
1038            y: Vec4::new(self.y.x, self.y.y, self.y.z, F::zero()),
1039            z: Vec4::new(self.z.x, self.z.y, self.z.z, F::zero()),
1040            p: Vec4::new(F::zero(), F::zero(), F::zero(), F::one()),
1041        }
1042    }
1043}
1044
1045// ----------------------------------------------------------------------------
1046// ApproxEq
1047
1048impl<F: FullFloat> ApproxEq for Mat2<F> {
1049    type Flt = F;
1050
1051    fn approx_eq(&self, other: &Self,
1052                 epsilon: <F as ApproxEq>::Flt,
1053                 ulps: <<F as ApproxEq>::Flt as Ulps>::U) -> bool
1054    {
1055        self.x.approx_eq(&other.x, epsilon, ulps) &&
1056            self.y.approx_eq(&other.y, epsilon, ulps)
1057    }
1058}
1059
1060impl<F: FullFloat> ApproxEq for Mat3<F> {
1061    type Flt = F;
1062
1063    fn approx_eq(&self, other: &Self,
1064                 epsilon: <F as ApproxEq>::Flt,
1065                 ulps: <<F as ApproxEq>::Flt as Ulps>::U) -> bool
1066    {
1067        self.x.approx_eq(&other.x, epsilon, ulps) &&
1068            self.y.approx_eq(&other.y, epsilon, ulps) &&
1069            self.z.approx_eq(&other.z, epsilon, ulps)
1070    }
1071}
1072
1073impl<F: FullFloat> ApproxEq for Mat4<F> {
1074    type Flt = F;
1075
1076    fn approx_eq(&self, other: &Self,
1077                 epsilon: <F as ApproxEq>::Flt,
1078                 ulps: <<F as ApproxEq>::Flt as Ulps>::U) -> bool
1079    {
1080        self.x.approx_eq(&other.x, epsilon, ulps) &&
1081            self.y.approx_eq(&other.y, epsilon, ulps) &&
1082            self.z.approx_eq(&other.z, epsilon, ulps) &&
1083            self.p.approx_eq(&other.p, epsilon, ulps)
1084    }
1085}
1086
1087// ----------------------------------------------------------------------------
1088
1089#[cfg(test)]
1090mod tests {
1091    use super::{Mat2, Mat3, Mat4, Angle};
1092    use super::super::vector::{Vec2, Vec3, Vec4, Direction3};
1093
1094    #[test]
1095    fn test_index() {
1096        let m: Mat2<f32> = Mat2::new(1.0, 2.0, 3.0, 4.0);
1097        assert_eq!(m[(0,0)], 1.0);
1098        assert_eq!(m[(0,1)], 2.0);
1099        assert_eq!(m[(1,0)], 3.0);
1100        assert_eq!(m[(1,1)], 4.0);
1101    }
1102
1103    #[test]
1104    fn test_transpose() {
1105        let mut m: Mat2<f32> = Mat2::new(1.0, 2.0,
1106                                         3.0, 4.0);
1107        m.transpose();
1108        assert_eq!(m, Mat2::new(1.0, 3.0,
1109                                2.0, 4.0));
1110
1111        let mut m: Mat3<f32> = Mat3::new(1.0, 2.0, 3.0,
1112                                         4.0, 5.0, 6.0,
1113                                         7.0, 8.0, 9.0);
1114        m.transpose();
1115        assert_eq!(m, Mat3::new(1.0, 4.0, 7.0,
1116                                2.0, 5.0, 8.0,
1117                                3.0, 6.0, 9.0));
1118
1119        let mut m: Mat4<f32> = Mat4::new(1.0, 2.0, 3.0, 4.0,
1120                                         5.0, 6.0, 7.0, 8.0,
1121                                         9.0, 10.0, 11.0, 12.0,
1122                                         13.0, 14.0, 15.0, 16.0);
1123        m.transpose();
1124        assert_eq!(m, Mat4::new(1.0, 5.0, 9.0, 13.0,
1125                                2.0, 6.0, 10.0, 14.0,
1126                                3.0, 7.0, 11.0, 15.0,
1127                                4.0, 8.0, 12.0, 16.0));
1128    }
1129
1130    #[test]
1131    fn test_mul_mat() {
1132        let left: Mat2<f32> = Mat2::new(1.0, 2.0, 3.0, 4.0);
1133        let right: Mat2<f32> = Mat2::new(6.0, 7.0, 8.0, 9.0);
1134        let product = &left * &right;
1135        assert_eq!(product, Mat2::new(22.0, 25.0,
1136                                      50.0, 57.0));
1137
1138        let left: Mat3<f32> = Mat3::new(1.0, 2.0, 3.0,
1139                                        4.0, 5.0, 6.0,
1140                                        7.0, 8.0, 9.0);
1141        let right: Mat3<f32> = Mat3::new(10.0, 11.0, 12.0,
1142                                         13.0, 14.0, 15.0,
1143                                         16.0, 17.0, 18.0);
1144        let product = &left * &right;
1145        assert_eq!(product[(0,0)], 84.0);
1146        assert_eq!(product[(0,1)], 90.0);
1147        assert_eq!(product[(0,2)], 96.0);
1148        assert_eq!(product[(1,0)], 201.0);
1149        assert_eq!(product[(1,1)], 216.0);
1150        assert_eq!(product[(1,2)], 231.0);
1151        assert_eq!(product[(2,0)], 318.0);
1152        assert_eq!(product[(2,1)], 342.0);
1153        assert_eq!(product[(2,2)], 366.0);
1154
1155        let left: Mat4<f32> = Mat4::new(1.0, 2.0, 3.0, 4.0,
1156                                        4.0, 3.0, 2.0, 1.0,
1157                                        5.0, 6.0, 2.0, 4.0,
1158                                        7.0, 1.0, 0.0, 3.0);
1159        let right: Mat4<f32> = Mat4::new(1.0, 6.0, 5.0, 2.0,
1160                                         3.0, 3.0, 3.0, 3.0,
1161                                         7.0, 8.0, 4.0, 1.0,
1162                                         9.0, 2.0, 0.0, 5.0);
1163        let product = &left * &right;
1164        assert_eq!(product[(0,0)], 64.0);
1165        assert_eq!(product[(0,1)], 44.0);
1166        assert_eq!(product[(0,2)], 23.0);
1167        assert_eq!(product[(0,3)], 31.0);
1168        assert_eq!(product[(1,0)], 36.0);
1169        assert_eq!(product[(1,1)], 51.0);
1170        assert_eq!(product[(1,2)], 37.0);
1171        assert_eq!(product[(1,3)], 24.0);
1172        assert_eq!(product[(2,0)], 73.0);
1173        assert_eq!(product[(2,1)], 72.0);
1174        assert_eq!(product[(2,2)], 51.0);
1175        assert_eq!(product[(2,3)], 50.0);
1176        assert_eq!(product[(3,0)], 37.0);
1177        assert_eq!(product[(3,1)], 51.0);
1178        assert_eq!(product[(3,2)], 38.0);
1179        assert_eq!(product[(3,3)], 32.0);
1180    }
1181
1182    #[test]
1183    fn test_mul_vec() {
1184        let left: Mat2<f32> = Mat2::new(1.0, 2.0,
1185                                        3.0, 4.0);
1186        let right: Vec2<f32> = Vec2::new(10.0, 20.0);
1187        let product = &left * &right;
1188        assert_eq!(product[0], 50.0);
1189        assert_eq!(product[1], 110.0);
1190        let product = &right * &left;
1191        assert_eq!(product[0], 70.0);
1192        assert_eq!(product[1], 100.0);
1193
1194        let left: Mat3<f32> = Mat3::new(1.0, 2.0, 3.0,
1195                                        4.0, 5.0, 6.0,
1196                                        7.0, 8.0, 9.0);
1197        let right: Vec3<f32> = Vec3::new(10.0, 20.0, 30.0);
1198        let product = &left * &right;
1199        assert_eq!(product[0], 140.0);
1200        assert_eq!(product[1], 320.0);
1201        assert_eq!(product[2], 500.0);
1202        let product = &right * &left;
1203        assert_eq!(product[0], 300.0);
1204        assert_eq!(product[1], 360.0);
1205        assert_eq!(product[2], 420.0);
1206
1207        let left: Mat4<f32> = Mat4::new(1.0, 2.0, 3.0, 4.0,
1208                                        5.0, 6.0, 7.0, 8.0,
1209                                        9.0, 10.0, 11.0, 12.0,
1210                                        13.0, 14.0, 15.0, 16.0);
1211        let right: Vec4<f32> = Vec4::new(1.0, 2.0, 3.0, 4.0);
1212        let product = &left * &right;
1213        assert_eq!(product[0], 30.0);
1214        assert_eq!(product[1], 70.0);
1215        assert_eq!(product[2], 110.0);
1216        assert_eq!(product[3], 150.0);
1217        let product = &right * &left;
1218        assert_eq!(product[0], 90.0);
1219        assert_eq!(product[1], 100.0);
1220        assert_eq!(product[2], 110.0);
1221        assert_eq!(product[3], 120.0);
1222    }
1223
1224    #[test]
1225    fn test_inverse() {
1226        assert_eq!(Mat2::<f64>::identity().inverse().unwrap(), Mat2::<f64>::identity());
1227        assert_eq!(Mat3::<f64>::identity().inverse().unwrap(), Mat3::<f64>::identity());
1228        assert_eq!(Mat4::<f64>::identity().inverse().unwrap(), Mat4::<f64>::identity());
1229
1230        // This one works even with floating point inaccuracies.
1231        // But ideally we need ULPS comparison functions for vectors and matrices.
1232        let m = Mat3::new( 7.0, 2.0, 1.0,
1233                           0.0, 3.0, -1.0,
1234                           -3.0, 4.0, -2.0 );
1235        let inv = m.inverse().unwrap();
1236        assert_eq!(inv, Mat3::new( -2.0, 8.0, -5.0,
1237                                    3.0, -11.0, 7.0,
1238                                    9.0, -34.0, 21.0 ));
1239
1240        // This one works even with floating point inaccuracies.
1241        // But ideally we need ULPS comparison functions for vectors and matrices.
1242        let m = Mat4::new( 1.0, 1.0, 1.0, 0.0,
1243                           0.0, 3.0, 1.0, 2.0,
1244                           2.0, 3.0, 1.0, 0.0,
1245                           1.0, 0.0, 2.0, 1.0 );
1246        let inv = m.inverse().unwrap();
1247        assert_eq!(inv, Mat4::new( -3.0, -0.5,   1.5,   1.0,
1248                                    1.0,  0.25, -0.25, -0.5,
1249                                    3.0,  0.25, -1.25, -0.5,
1250                                    -3.0, 0.0,   1.0,   1.0 ));
1251    }
1252
1253    #[test]
1254    fn test_axis_angle() {
1255        let axis: Direction3<f32> = From::from(Vec3::new(1.0, 0.0, 0.0));
1256        let angle = Angle::new_radians(::std::f32::consts::FRAC_PI_4);
1257
1258        let start: Mat4<f32> = Mat4::new(
1259            1.0, 0.0, 0.0, 5.0,
1260            0.0, 1.0, 0.0, 5.0,
1261            0.0, 0.0, 1.0, 5.0,
1262            0.0, 0.0, 0.0, 1.0 );
1263
1264        let rot = Mat4::<f32>::rotate_axis_angle(axis, angle);
1265
1266        let end = &rot * &start;
1267
1268        let (s, c) = angle.as_radians().sin_cos();
1269        // This equality comparison works even with floating point inaccuracies.
1270        // But ideally we need ULPS comparison functions for vectors and matrices.
1271        assert_eq!(end, Mat4::new(
1272            1.0, 0.0, 0.0, 5.0,
1273            0.0, c,   -s,  0.0,
1274            0.0, s,   c,   c*10.0,
1275            0.0, 0.0, 0.0, 1.0));
1276    }
1277}