calcify/three_mat/
mod.rs

1use std::ops::Add;
2use std::ops::AddAssign;
3use std::ops::Sub;
4use std::ops::SubAssign;
5use std::ops::Mul;
6use std::ops::Neg;
7use std::fmt;
8use std::error;
9use std::f64::NAN;
10
11/// Three Vector Module
12mod three_vec;
13pub use three_vec::ThreeVec;
14pub use three_vec::{radians_between, degrees_between};
15
16use crate::utils;
17use utils::{Serializable, Deserializable};
18use utils::errors::CalcifyError;
19
20extern crate rmp;
21use rmp::encode::*;
22use rmp::decode::*;
23
24/// Three Matrix
25#[derive(Debug, PartialEq, Copy, Clone)]
26pub struct ThreeMat {
27    /// Three rows, each a calcify::ThreeVec
28    r0: ThreeVec,
29    r1: ThreeVec,
30    r2: ThreeVec,
31}
32
33impl ThreeMat {
34    /// Returns a new ThreeMat from three ThreeVecs
35    ///
36    /// # Arguments
37    ///
38    /// * `r0` - calcify::ThreeVec
39    /// * `r1` - calcify::ThreeVec
40    /// * `r2` - calcify::ThreeVec
41    ///
42    /// # Example
43    /// ```
44    /// use calcify::ThreeVec;
45    /// use calcify::ThreeMat;
46    /// let mat3 = ThreeMat::new(
47    ///               ThreeVec::new(1.0,2.0,3.0),
48    ///               ThreeVec::new(4.0,5.0,6.0),
49    ///               ThreeVec::new(7.0,8.0,9.0)
50    ///            );
51    /// ```
52    pub fn new(r0: ThreeVec, r1: ThreeVec, r2: ThreeVec) -> ThreeMat {
53        ThreeMat {
54            r0,
55            r1,
56            r2,
57        }
58    }
59
60    /// Returns a new ThreeMat from a slice
61    ///
62    /// # Arguments
63    ///
64    /// * `slice` - &[ThreeVec]
65    ///
66    /// # Panics
67    ///
68    /// * `slice` length < 3
69    pub fn from(slice: &[ThreeVec]) -> ThreeMat {
70
71        ThreeMat {
72            r0: slice[0],
73            r1: slice[1],
74            r2: slice[2],
75        }
76    }
77
78    /// Returns a new ThreeMat with three random ThreeVecs using calcify::ThreeVec::random(max: f64)
79    ///
80    /// # Arguments
81    ///
82    /// * `max` - f64: The absolute maximum value of each individule componant of the constituent ThreeVec
83    ///
84    /// # Example
85    /// ```
86    /// use calcify::ThreeMat;
87    /// let mat3 = ThreeMat::random(10.0);
88    /// ```
89    pub fn random(max: f64) -> ThreeMat {
90        ThreeMat {
91            r0: ThreeVec::random(max),
92            r1: ThreeVec::random(max),
93            r2: ThreeVec::random(max),
94        }
95    }
96
97    /// Returns a new ThreeMat identity matrix
98    ///
99    /// # Example
100    /// ```
101    /// use calcify::ThreeMat;
102    /// let mat3 = ThreeMat::eye();
103    ///
104    /// assert_eq!(*mat3.r1().x1(),1.0);
105    /// ```
106    pub fn eye() -> ThreeMat {
107        ThreeMat {
108            r0: ThreeVec::new(1.0,0.0,0.0),
109            r1: ThreeVec::new(0.0,1.0,0.0),
110            r2: ThreeVec::new(0.0,0.0,1.0),
111        }
112    }
113
114    /// Returns a new ThreeMat zero matrix
115    ///
116    /// # Example
117    /// ```
118    /// use calcify::ThreeMat;
119    /// let mat3 = ThreeMat::zero();
120    ///
121    /// assert_eq!(*mat3.r1().x1(),0.0);
122    /// ```
123    pub fn zero() -> ThreeMat {
124        ThreeMat {
125            r0: ThreeVec::new(0.0,0.0,0.0),
126            r1: ThreeVec::new(0.0,0.0,0.0),
127            r2: ThreeVec::new(0.0,0.0,0.0),
128        }
129    }
130
131    /// Returns a new ThreeMat one matrix
132    ///
133    /// # Example
134    /// ```
135    /// use calcify::ThreeMat;
136    /// let mat3 = ThreeMat::one();
137    ///
138    /// assert_eq!(*mat3.r1().x1(),1.0);
139    /// ```
140    pub fn one() -> ThreeMat {
141        ThreeMat {
142            r0: ThreeVec::new(1.0,1.0,1.0),
143            r1: ThreeVec::new(1.0,1.0,1.0),
144            r2: ThreeVec::new(1.0,1.0,1.0),
145        }
146    }
147
148    /// Returns a reference to the first row of the matrix.
149    ///
150    /// # Example
151    /// ```
152    /// use calcify::ThreeVec;
153    /// use calcify::ThreeMat;
154    /// let mat3 = ThreeMat::new(
155    ///               ThreeVec::new(1.0,2.0,3.0),
156    ///               ThreeVec::new(4.0,5.0,6.0),
157    ///               ThreeVec::new(7.0,8.0,9.0)
158    ///            );
159    /// let row_zero: ThreeVec = *mat3.r0();
160    /// let element_zero_zero: f64 = *mat3.r0().x0();
161    /// assert_eq!(row_zero,ThreeVec::new(1.0,2.0,3.0));
162    /// assert_eq!(element_zero_zero,1.0);
163    /// ```
164    pub fn r0(&self) -> &ThreeVec {
165        &self.r0
166    }
167
168
169    /// Returns a reference to the second row of the matrix.
170    ///
171    /// # Example
172    /// ```
173    /// use calcify::ThreeVec;
174    /// use calcify::ThreeMat;
175    /// let mat3 = ThreeMat::new(
176    ///               ThreeVec::new(1.0,2.0,3.0),
177    ///               ThreeVec::new(4.0,5.0,6.0),
178    ///               ThreeVec::new(7.0,8.0,9.0)
179    ///            );
180    /// let row_one: ThreeVec = *mat3.r1();
181    /// let element_one_one: f64 = *mat3.r1().x1();
182    /// assert_eq!(row_one,ThreeVec::new(4.0,5.0,6.0));
183    /// assert_eq!(element_one_one,5.0);
184    /// ```
185    pub fn r1(&self) -> &ThreeVec {
186        &self.r1
187    }
188
189    /// Returns a reference to the third row of the matrix.
190    ///
191    /// # Example
192    /// ```
193    /// use calcify::ThreeVec;
194    /// use calcify::ThreeMat;
195    /// let mat3 = ThreeMat::new(
196    ///               ThreeVec::new(1.0,2.0,3.0),
197    ///               ThreeVec::new(4.0,5.0,6.0),
198    ///               ThreeVec::new(7.0,8.0,9.0)
199    ///            );
200    /// let row_two: ThreeVec = *mat3.r2();
201    /// let element_two_two: f64 = *mat3.r2().x2();
202    /// assert_eq!(row_two,ThreeVec::new(7.0,8.0,9.0));
203    /// assert_eq!(element_two_two,9.0);
204    /// ```
205    pub fn r2(&self) -> &ThreeVec {
206        &self.r2
207    }
208
209    /// Returns a new memory ThreeVec of the first column of the matrix.
210    ///
211    /// # Example
212    /// ```
213    /// use calcify::ThreeVec;
214    /// use calcify::ThreeMat;
215    /// let mat3 = ThreeMat::new(
216    ///               ThreeVec::new(1.0,2.0,3.0),
217    ///               ThreeVec::new(4.0,5.0,6.0),
218    ///               ThreeVec::new(7.0,8.0,9.0)
219    ///            );
220    /// let col_one: ThreeVec = mat3.c0();
221    /// let element_one_one: f64 = *mat3.c0().x0();
222    /// assert_eq!(col_one,ThreeVec::new(1.0,4.0,7.0));
223    /// assert_eq!(element_one_one,1.0);
224    /// ```
225    pub fn c0(&self) -> ThreeVec {
226        ThreeVec::new(*self.r0.x0(),*self.r1.x0(),*self.r2.x0())
227    }
228
229    pub fn c1(&self) -> ThreeVec {
230        ThreeVec::new(*self.r0.x1(),*self.r1.x1(),*self.r2.x1())
231    }
232
233    pub fn c2(&self) -> ThreeVec {
234        ThreeVec::new(*self.r0.x2(),*self.r1.x2(),*self.r2.x2())
235    }
236}
237
238impl fmt::Display for ThreeMat {
239    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
240        write!(f, "[{},\n{},\n{}]", self.r0(), self.r1(), self.r2())
241    }
242}
243
244impl Serializable for ThreeMat {
245    fn to_json(&self) -> String {
246        format!("{{\"r0\":{},\"r1\":{},\"r2\":{}}}",
247            self.r0().to_json(),
248            self.r1().to_json(),
249            self.r2().to_json()
250        )
251    }
252    fn to_msg(&self) -> Result<Vec<u8>,ValueWriteError> {
253        let mut buf = Vec::new();
254        write_array_len(&mut buf, 3)?;
255        buf.append(&mut self.r0().to_msg()?);
256        buf.append(&mut self.r1().to_msg()?);
257        buf.append(&mut self.r2().to_msg()?);
258        Ok(buf)
259    }
260}
261
262impl Deserializable for ThreeMat {
263
264    fn from_json(s: &str) -> Result<Self, Box<dyn error::Error>> {
265        let mut r0: ThreeVec = ThreeVec::new(NAN,NAN,NAN);
266        let mut r1: ThreeVec = ThreeVec::new(NAN,NAN,NAN);
267        let mut r2: ThreeVec = ThreeVec::new(NAN,NAN,NAN);
268        for dim in s.replace("}}","|}").replace("},","}|").replace(":{",":!{").trim_matches(|p| p == '{' || p == '}' ).split_terminator('|') {
269            let n_v: Vec<&str> = dim.split(":!").collect();
270            match n_v[0] {
271                "\"r0\"" => r0 = ThreeVec::from_json(n_v[1])?,
272                "\"r1\"" => r1 = ThreeVec::from_json(n_v[1])?,
273                "\"r2\"" => r2 = ThreeVec::from_json(n_v[1])?,
274                _ => return Err(Box::new(CalcifyError::ParseError)),
275            }
276        }
277        Ok(ThreeMat{r0,r1,r2})
278    }
279
280    fn from_msg(mut bytes: &[u8]) -> Result<(Self,&[u8]), Box<dyn error::Error>> {
281        if let Ok(3) = read_array_len(&mut bytes){
282            let mut x: [ThreeVec;3] = [ThreeVec::new(NAN,NAN,NAN);3];
283            for i in 0..3 {
284                let (vec,rest) = ThreeVec::from_msg(&mut bytes)?;
285                x[i] = vec;
286                bytes = rest;
287            }
288            Ok((ThreeMat::from(&x),bytes))
289        } else {
290            Err(Box::new(CalcifyError::ParseError))
291        }
292    }
293}
294
295impl Add for ThreeMat {
296    type Output = ThreeMat;
297
298    fn add(self, other: ThreeMat) -> ThreeMat {
299        ThreeMat {
300            r0: self.r0 + *other.r0(),
301            r1: self.r1 + *other.r1(),
302            r2: self.r2 + *other.r2(),
303        }
304    }
305}
306
307impl AddAssign for ThreeMat {
308    fn add_assign(&mut self, other: ThreeMat) {
309        self.r0 +=*other.r0();
310        self.r1 +=*other.r1();
311        self.r2 +=*other.r2();
312    }
313}
314
315impl Sub for ThreeMat {
316    type Output = ThreeMat;
317
318    fn sub(self, other: ThreeMat) -> ThreeMat {
319        ThreeMat {
320            r0: self.r0 -*other.r0(),
321            r1: self.r1 -*other.r1(),
322            r2: self.r2 -*other.r2(),
323        }
324    }
325}
326
327impl SubAssign for ThreeMat {
328    fn sub_assign(&mut self, other: ThreeMat) {
329        self.r0 -=*other.r0();
330        self.r1 -=*other.r1();
331        self.r2 -=*other.r2();
332    }
333}
334
335impl Mul<f64> for ThreeMat {
336    type Output = ThreeMat;
337
338    fn mul(self, coef: f64) -> ThreeMat {
339        ThreeMat {
340            r0: self.r0 *coef,
341            r1: self.r1 *coef,
342            r2: self.r2 *coef,
343        }
344    }
345}
346
347impl Mul<ThreeMat> for f64 {
348    type Output = ThreeMat;
349
350    fn mul(self, vec: ThreeMat) -> ThreeMat {
351        ThreeMat {
352            r0: *vec.r0() * self,
353            r1: *vec.r1() * self,
354            r2: *vec.r2() * self,
355        }
356    }
357}
358
359impl Mul<ThreeMat> for ThreeMat {
360    type Output = ThreeMat;
361    /// Matrix multiplication
362    ///
363    /// # Example
364    ///
365    /// ```
366    /// use calcify::ThreeMat;
367    /// use calcify::ThreeVec;
368    ///
369    /// let mat3 = ThreeMat::new(ThreeVec::new(1.0,2.0,3.0),
370    ///                             ThreeVec::new(4.0,5.0,6.0),
371    ///                             ThreeVec::new(7.0,8.0,9.0));
372    ///
373    /// assert_eq!(
374    ///     mat3*mat3,
375    ///     ThreeMat::new(ThreeVec::new(30.0,36.0,42.0),
376    ///                 ThreeVec::new(66.0,81.0,96.0),
377    ///                 ThreeVec::new(102.0,126.0,150.0)));
378    /// ```
379    fn mul(self, other: ThreeMat) -> ThreeMat {
380        let c0 = other.c0();
381        let c1 = other.c1();
382        let c2 = other.c2();
383        ThreeMat {
384            r0: ThreeVec::new(self.r0*c0, self.r0*c1, self.r0*c2),
385            r1: ThreeVec::new(self.r1*c0, self.r1*c1, self.r1*c2),
386            r2: ThreeVec::new(self.r2*c0, self.r2*c1, self.r2*c2),
387        }
388    }
389}
390
391impl Mul<ThreeVec> for ThreeMat {
392    type Output = ThreeVec;
393    /// Matrix multiplication with vector
394    ///
395    /// # Note
396    ///
397    /// Only works in one direction ThreeMat*ThreeVec, implying ThreeVec as a column vector.
398    ///
399    /// # Example
400    ///
401    /// ```
402    /// use calcify::ThreeMat;
403    /// use calcify::ThreeVec;
404    ///
405    /// let mat3 = ThreeMat::new(ThreeVec::new(1.0,2.0,3.0),
406    ///                             ThreeVec::new(1.0,2.0,3.0),
407    ///                             ThreeVec::new(1.0,2.0,3.0));
408    ///
409    /// assert_eq!(
410    ///     mat3*ThreeVec::new(2.0,2.0,2.0),
411    ///     ThreeVec::new(12.0,12.0,12.0)
412    /// );
413    /// ```
414    fn mul(self, other: ThreeVec) -> ThreeVec {
415        ThreeVec::new(self.r0*other,self.r1*other,self.r2*other)
416    }
417}
418
419impl Neg for ThreeMat {
420    type Output = ThreeMat;
421
422    fn neg(self) -> ThreeMat {
423        ThreeMat {
424            r0: -self.r0,
425            r1: -self.r1,
426            r2: -self.r2,
427        }
428    }
429}
430
431
432#[cfg(test)]
433mod tests {
434    use super::*;
435
436    #[test]
437    fn test_access() {
438        let _test_mat = ThreeMat::new(ThreeVec::new(1.0,2.0,3.0),
439                                    ThreeVec::new(4.0,5.0,6.0),
440                                    ThreeVec::new(7.0,8.0,9.0));
441        assert_eq!(*_test_mat.r2().x2(),9.0);
442        assert_eq!(_test_mat.c2(),ThreeVec::new(3.0,6.0,9.0));
443        assert_eq!(*_test_mat.r2().x2(),9.0);
444    }
445
446    #[test]
447    fn test_add() {
448        let _test_mat1 = ThreeMat::new(ThreeVec::new(1.0,2.0,3.0),
449                                    ThreeVec::new(4.0,5.0,6.0),
450                                    ThreeVec::new(7.0,8.0,9.0));
451        let _test_mat2 = ThreeMat::new(ThreeVec::new(1.0,2.0,3.0),
452                                    ThreeVec::new(4.0,5.0,6.0),
453                                    ThreeVec::new(7.0,8.0,9.0));
454
455        assert_eq!(
456            _test_mat1+_test_mat2,
457            ThreeMat::new(ThreeVec::new(2.0,4.0,6.0),
458                        ThreeVec::new(8.0,10.0,12.0),
459                        ThreeVec::new(14.0,16.0,18.0))
460        );
461        assert_eq!(*_test_mat1.r2().x2(),9.0);
462    }
463
464    #[test]
465    fn test_loop_add() {
466        let mut _test_mat1 = ThreeMat::new(ThreeVec::new(1.0,1.0,1.0),
467                                    ThreeVec::new(1.0,1.0,1.0),
468                                    ThreeVec::new(1.0,1.0,1.0));
469        for _i in 0..9999{
470            _test_mat1 += ThreeMat::new(ThreeVec::new(1.0,1.0,1.0),
471                                        ThreeVec::new(1.0,1.0,1.0),
472                                        ThreeVec::new(1.0,1.0,1.0));
473        }
474
475        assert_eq!(
476            _test_mat1,
477            ThreeMat::new(ThreeVec::new(10_000.0,10_000.0,10_000.0),
478                        ThreeVec::new(10_000.0,10_000.0,10_000.0),
479                        ThreeVec::new(10_000.0,10_000.0,10_000.0))
480        );
481    }
482
483    #[test]
484    fn test_sub() {
485        let _test_mat1 = ThreeMat::new(ThreeVec::new(2.0,4.0,6.0),
486                                    ThreeVec::new(8.0,10.0,12.0),
487                                    ThreeVec::new(14.0,16.0,18.0));
488        let _test_mat2 = ThreeMat::new(ThreeVec::new(1.0,2.0,3.0),
489                                    ThreeVec::new(4.0,5.0,6.0),
490                                    ThreeVec::new(7.0,8.0,9.0));
491
492        assert_eq!(
493            _test_mat1-_test_mat2,
494            ThreeMat::new(ThreeVec::new(1.0,2.0,3.0),
495                        ThreeVec::new(4.0,5.0,6.0),
496                        ThreeVec::new(7.0,8.0,9.0))
497        );
498        assert_eq!(*_test_mat1.r2().x2(),18.0);
499    }
500
501    #[test]
502    fn test_loop_sub() {
503        let mut _test_mat1 = ThreeMat::new(ThreeVec::new(10_000.0,10_000.0,10_000.0),
504                    ThreeVec::new(10_000.0,10_000.0,10_000.0),
505                    ThreeVec::new(10_000.0,10_000.0,10_000.0));
506        for _i in 0..9999{
507            _test_mat1 -= ThreeMat::new(ThreeVec::new(1.0,1.0,1.0),
508                                        ThreeVec::new(1.0,1.0,1.0),
509                                        ThreeVec::new(1.0,1.0,1.0));
510        }
511
512        assert_eq!(
513            _test_mat1,
514            ThreeMat::new(ThreeVec::new(1.0,1.0,1.0),
515                                        ThreeVec::new(1.0,1.0,1.0),
516                                        ThreeVec::new(1.0,1.0,1.0))
517        );
518    }
519
520    #[test]
521    fn test_mul() {
522        let _test_mat = ThreeMat::new(ThreeVec::new(1.0,2.0,3.0),
523                                    ThreeVec::new(4.0,5.0,6.0),
524                                    ThreeVec::new(7.0,8.0,9.0));
525
526        assert_eq!(
527            _test_mat*_test_mat,
528            ThreeMat::new(ThreeVec::new(30.0,36.0,42.0),
529                        ThreeVec::new(66.0,81.0,96.0),
530                        ThreeVec::new(102.0,126.0,150.0))
531        );
532    }
533
534    #[test]
535    fn test_mul_vec() {
536        let _test_mat = ThreeMat::new(ThreeVec::new(1.0,2.0,3.0),
537                                    ThreeVec::new(1.0,2.0,3.0),
538                                    ThreeVec::new(1.0,2.0,3.0));
539
540        assert_eq!(
541            _test_mat*ThreeVec::new(2.0,2.0,2.0),
542            ThreeVec::new(12.0,12.0,12.0)
543        );
544    }
545
546    #[test]
547    fn test_mul_coef() {
548        let _test_mat = ThreeMat::new(ThreeVec::new(1.0,1.0,1.0),
549                                    ThreeVec::new(1.0,1.0,1.0),
550                                    ThreeVec::new(1.0,1.0,1.0));
551
552        assert_eq!(
553            _test_mat*2.0,
554            ThreeMat::new(ThreeVec::new(2.0,2.0,2.0),
555                        ThreeVec::new(2.0,2.0,2.0),
556                        ThreeVec::new(2.0,2.0,2.0))
557        );
558        assert_eq!(
559            2.0*_test_mat,
560            ThreeMat::new(ThreeVec::new(2.0,2.0,2.0),
561                        ThreeVec::new(2.0,2.0,2.0),
562                        ThreeVec::new(2.0,2.0,2.0))
563        );
564    }
565
566    #[test]
567    fn test_neg() {
568        let _test_mat = ThreeMat::new(ThreeVec::new(1.0,1.0,1.0),
569                                    ThreeVec::new(1.0,1.0,1.0),
570                                    ThreeVec::new(1.0,1.0,1.0));
571
572        assert_eq!(
573            -_test_mat,
574            ThreeMat::new(ThreeVec::new(-1.0,-1.0,-1.0),
575                        ThreeVec::new(-1.0,-1.0,-1.0),
576                        ThreeVec::new(-1.0,-1.0,-1.0))
577        );
578    }
579
580    #[test]
581    fn test_copy() {
582        let xx = ThreeMat::new(ThreeVec::new(1.0,1.0,1.0),
583                                    ThreeVec::new(1.0,1.0,1.0),
584                                    ThreeVec::new(1.0,1.0,1.0));
585        let yy = xx;
586        assert_eq!(
587            xx+yy,
588            ThreeMat::new(ThreeVec::new(2.0,2.0,2.0),
589                        ThreeVec::new(2.0,2.0,2.0),
590                        ThreeVec::new(2.0,2.0,2.0))
591        );
592    }
593
594    #[test]
595    fn test_parse() {
596        let xx = ThreeMat::new(ThreeVec::new(1.0,1.0,1.0),
597                                    ThreeVec::new(1.0,1.0,1.0),
598                                    ThreeVec::new(1.0,1.0,1.0));
599        let pp = xx.to_json();
600        assert_eq!(ThreeMat::from_json(&pp).unwrap(),xx);
601    }
602
603    #[test]
604    fn test_msg_parse() {
605        let xx = ThreeMat::new(ThreeVec::new(1.0,1.0,1.0),
606                                    ThreeVec::new(2.0,2.0,2.0),
607                                    ThreeVec::new(3.0,3.0,3.0));
608        let pp = xx.to_msg().unwrap();
609        let (oo,_) = ThreeMat::from_msg(&pp).unwrap();
610        assert_eq!(oo,xx);
611    }
612}