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
11mod 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#[derive(Debug, PartialEq, Copy, Clone)]
26pub struct ThreeMat {
27 r0: ThreeVec,
29 r1: ThreeVec,
30 r2: ThreeVec,
31}
32
33impl ThreeMat {
34 pub fn new(r0: ThreeVec, r1: ThreeVec, r2: ThreeVec) -> ThreeMat {
53 ThreeMat {
54 r0,
55 r1,
56 r2,
57 }
58 }
59
60 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 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 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 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 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 pub fn r0(&self) -> &ThreeVec {
165 &self.r0
166 }
167
168
169 pub fn r1(&self) -> &ThreeVec {
186 &self.r1
187 }
188
189 pub fn r2(&self) -> &ThreeVec {
206 &self.r2
207 }
208
209 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 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 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}