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}