calcify/four_mat/
mod.rs

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