├── .gitignore ├── src ├── field │ ├── mod.rs │ ├── three_field.rs │ └── three_vec_field.rs ├── utils │ ├── mod.rs │ ├── errors.rs │ ├── io.rs │ ├── serializable.rs │ └── consts.rs ├── lib.rs ├── tree │ ├── branch │ │ ├── collection │ │ │ ├── bin.rs │ │ │ ├── point_bin.rs │ │ │ ├── point.rs │ │ │ └── mod.rs │ │ └── mod.rs │ ├── feedtree.rs │ └── mod.rs ├── three_mat │ ├── three_vec │ │ └── mod.rs │ └── mod.rs └── four_mat │ ├── four_vec │ └── mod.rs │ └── mod.rs ├── Cargo.toml ├── RELEASENOTES.md ├── README.md └── examples └── universe_in_a_box ├── main.rs └── universe_in_a_box.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | .swp 5 | test_*.json 6 | universe_*.json 7 | *.msg 8 | scratch 9 | -------------------------------------------------------------------------------- /src/field/mod.rs: -------------------------------------------------------------------------------- 1 | mod three_field; 2 | mod three_vec_field; 3 | 4 | pub use three_field::ThreeField; 5 | pub use three_vec_field::ThreeVecField; 6 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "calcify" 3 | description = "Physics vector library" 4 | version = "0.8.2" 5 | authors = ["JTPond "] 6 | edition = "2018" 7 | readme = "README.md" 8 | repository = "https://github.com/JTPond/calcify" 9 | license = "MIT OR Apache-2.0" 10 | keywords = ["linear_algebra","vector","scientific_computing","matrix","physics"] 11 | categories = ["science", "simulation"] 12 | 13 | [dependencies] 14 | rand = "^0.6" 15 | rmp = "^0.8" 16 | 17 | [dev-dependencies] 18 | rand = "^0.6" 19 | rmp = "^0.8" 20 | lazy_static = "^1.4" 21 | chrono = "^0.4" 22 | rayon = "^1.3" 23 | 24 | [badges] 25 | maintenance = { status = "actively-developed" } 26 | -------------------------------------------------------------------------------- /src/utils/mod.rs: -------------------------------------------------------------------------------- 1 | /// consts module 2 | pub mod consts; 3 | 4 | pub mod serializable; 5 | pub use serializable::Serializable; 6 | pub use serializable::Deserializable; 7 | 8 | /// Errors module 9 | pub mod errors; 10 | 11 | /// ## File IO 12 | /// 13 | /// * Even though json is supported for both reading and writing, it's not as efficiently implemented and may lead to slowdowns when reading large files. Consider only using it for debugging, so that you can read the results of tests, otherwise use msg. 14 | /// 15 | /// * Feel free to use Serde when implementing the Serialization traits for your types 16 | /// 17 | /// ### Trees 18 | /// 19 | /// | Write | Read | 20 | /// | ----------- | ----------- | 21 | /// | Supports all subtypes | Internal types only, and not `Object`| 22 | /// 23 | /// ### FeedTrees 24 | /// 25 | /// | Write| Read | 26 | /// | -----| -----| 27 | /// | Supports all subtypes| Supports all subtypes| 28 | pub mod io; 29 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![crate_name = "calcify"] 2 | //! # Calcify 3 | //! 4 | //! A crate for 3-D and 4-D vector and matrix algebra, conceived for use in physics simulations. Builds out from a basic ThreeVec struct including most commonly used operations built in. 5 | //! Includes physics constants, 3 and 4-D vectors and matrices and many associated operations, collections, histograms, and output trees, which are serialized in json or MessagePack. 6 | //! 7 | //! ## ICalcify 8 | //! 9 | //! Python command line utility and module for analyzing Tree files. 10 | //! 11 | //! Check it out [here!](https://github.com/JTPond/ICalcify "ICalcify GitHub") 12 | 13 | mod field; 14 | mod tree; 15 | mod four_mat; 16 | mod three_mat; 17 | mod utils; 18 | 19 | pub use field::ThreeField; 20 | pub use field::ThreeVecField; 21 | 22 | pub use tree::Branch; 23 | pub use tree::Tree; 24 | pub use tree::FeedTree; 25 | pub use tree::Collection; 26 | pub use tree::Bin; 27 | pub use tree::Point; 28 | pub use tree::PointBin; 29 | 30 | pub use four_mat::Sinv; 31 | pub use four_mat::beta; 32 | pub use four_mat::gamma; 33 | pub use four_mat::boost; 34 | pub use four_mat::FourVec; 35 | pub use four_mat::FourMat; 36 | 37 | pub use three_mat::ThreeMat; 38 | pub use three_mat::ThreeVec; 39 | pub use three_mat::{radians_between, degrees_between}; 40 | 41 | pub use utils::consts; 42 | pub use utils::errors; 43 | pub use utils::io; 44 | pub use utils::Serializable; 45 | pub use utils::Deserializable; 46 | -------------------------------------------------------------------------------- /src/utils/errors.rs: -------------------------------------------------------------------------------- 1 | use std::error; 2 | use std::fmt; 3 | 4 | /// Enum of built in Error types 5 | #[derive(Debug,Clone)] 6 | pub enum CalcifyError { 7 | LightSpeedError, 8 | KeyError, 9 | ParseError, 10 | LengthError, 11 | ObjectBranchDeserializeError, 12 | } 13 | 14 | impl fmt::Display for CalcifyError { 15 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 16 | match *self { 17 | CalcifyError::LightSpeedError => write!(f,"Velocity greater than calcify::C_LIGHT."), 18 | CalcifyError::KeyError => write!(f,"Invalid Key"), 19 | CalcifyError::ParseError => write!(f,"Error on parse in Deserializable."), 20 | CalcifyError::LengthError => write!(f,"Invalid slice length"), 21 | CalcifyError::ObjectBranchDeserializeError => write!(f,"Attempted to deserialize Object Branch."), 22 | } 23 | } 24 | } 25 | 26 | impl error::Error for CalcifyError { 27 | fn description(&self) -> &str { 28 | match *self { 29 | CalcifyError::LightSpeedError => "Cannot have a velocity greater than calcify::C_LIGHT", 30 | CalcifyError::KeyError => "Convert HashMap Option behavior to Err on bad keys", 31 | CalcifyError::ParseError => "Probably a formatting error when the data was serialized, or there is a type mismatch.", 32 | CalcifyError::LengthError => "Length of slice must match Vector length", 33 | CalcifyError::ObjectBranchDeserializeError => "Cannot deserialize Object Branch.", 34 | } 35 | } 36 | 37 | fn source(&self) -> Option<&(dyn error::Error + 'static)> { 38 | // Generic error, underlying cause isn't tracked. 39 | None 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/utils/io.rs: -------------------------------------------------------------------------------- 1 | use std::error; 2 | use std::marker::Sized; 3 | 4 | use std::io::prelude::*; 5 | use std::io::BufWriter; 6 | use std::fs; 7 | 8 | use super::serializable::{Serializable, Deserializable}; 9 | use super::errors::CalcifyError; 10 | 11 | /// Trait for saving a *Tree to disk. 12 | pub trait ToFile { 13 | /// Write Self as json to file. 14 | fn write_json(&self, filename: &str) -> Result<(), Box> 15 | where Self: Serializable { 16 | let f = fs::File::create(filename)?; 17 | let mut wr = BufWriter::new(f); 18 | wr.write(self.to_json().as_bytes())?; 19 | Ok(()) 20 | } 21 | 22 | /// Write Self as msg to file. 23 | fn write_msg(&self, filename: &str) -> Result<(), Box> 24 | where Self: Serializable { 25 | let f = fs::File::create(filename)?; 26 | let mut wr = BufWriter::new(f); 27 | wr.write(self.to_msg()?.as_slice())?; 28 | Ok(()) 29 | } 30 | } 31 | 32 | /// Trait for loading a *Tree from disk. 33 | pub trait FromFile { 34 | /// Read json file to Self. 35 | fn read_json(filename: &str) -> Result> 36 | where Self: Deserializable + Sized { 37 | Self::from_json(&fs::read_to_string(filename)?) 38 | } 39 | 40 | /// Read msg file to Self. 41 | fn read_msg(filename: &str) -> Result> 42 | where Self: Deserializable + Sized { 43 | if let Ok((obj,_)) = Self::from_msg(&fs::read(filename)?) { 44 | return Ok(obj); 45 | } else { 46 | return Err(Box::new(CalcifyError::ParseError)); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /RELEASENOTES.md: -------------------------------------------------------------------------------- 1 | # Release Notes 2 | 3 | ### 0.8.2 2022-01-16: 4 | * Add PointBin 2D hist type 5 | 6 | ### 0.8.1 2020-06-13: 7 | * Implement From> and From<&[T: Serializable + Clone]> for Collection 8 | 9 | ### 0.8 2020-06-06: 10 | * **File IO for Trees and FeedTrees** 11 | * **Remove support for jsonc.** 12 | * Update extract. 13 | * Support "Object" Branches. 14 | * Reorganize files around branch. 15 | 16 | ### 0.7: 2020-04-18 17 | * Added CalcifyError. Dropped lifetime of Tree keys to 'a from 'static. Upgraded Point to be more like a TwoVec. 18 | 19 | ### 0.6 20 | * Implemented std::iter::Sum for ThreeVec and FourVec 21 | 22 | * ThreeField and ThreeVecField updated to use ThreeVec as input. This was the correct design decision from the beginning. 23 | 24 | * New types, ThreeField and ThreeVecField. These are wrapper function around function pointers. They will have limited functionality for most users, but they will be important for typing in CalcifyLab. 25 | 26 | ### Previous 27 | * Added Feed trait and FeedTree type for mutable data feeds. 28 | 29 | * Updated organization of source files. 30 | 31 | * Fixed Warnings in example and fixed deprecated code in LightSpeedError 32 | 33 | * Added LightSpeedError type for beta() 34 | 35 | * Added a compact json format to Serialization as `to_jsonc()`, which is array intensive, instead to object intensive. Also added binary Serialization to MessagePack using the rmp crate as `to_msg()`. The format is like jsonc, not json. The on disk savings of jsonc over json can be ~20%, and the savings for msg over json can be ~63%. 36 | 37 | * Now includes example of a many body simulation "universe_in_a_box" use `cargo run --example universe_in_a_box --release` This could take several seconds. 38 | 39 | * Branches can now be extracted from Trees, but this is not an ideal process. Trees should still be seen as containers for output only. 40 | 41 | * All physics constants are exported in the top in SI units. To retrieve them in Planck or natural units call calcify::Consts::planck() or calcify::Consts::natural(). 42 | 43 | * FourMat::lambda() has been replaced by fn boost(initial: FourVec, v: ThreeVec). The math has been changed. 44 | -------------------------------------------------------------------------------- /src/field/three_field.rs: -------------------------------------------------------------------------------- 1 | use std::f64; 2 | use std::ops::Mul; 3 | use std::ops::Neg; 4 | 5 | use crate::three_mat; 6 | use three_mat::ThreeVec; 7 | 8 | /// Three dimensional scalar field 9 | #[derive(Clone,Copy)] 10 | pub struct ThreeField<'a> { 11 | func: &'a dyn Fn(&ThreeVec) -> f64, 12 | multi: f64, 13 | } 14 | 15 | impl<'a> ThreeField<'a> { 16 | /// Returns a new ThreeField 17 | /// 18 | /// # Arguments 19 | /// 20 | /// * `func` - &'a dyn Fn(&ThreeVec) -> f64 21 | /// 22 | /// # Example 23 | /// ``` 24 | /// use calcify::ThreeVec; 25 | /// use calcify::ThreeField; 26 | /// 27 | /// let g = ThreeField::new(&|tv: &ThreeVec| tv.r()); 28 | /// let g2: ThreeField = 2.0*g; 29 | /// 30 | /// let test_vec = ThreeVec::new(2.0,2.0,2.0); 31 | /// 32 | /// assert_eq!(g.loc(2.0,2.0,2.0),test_vec.r()); 33 | /// assert_eq!(g.at(test_vec),test_vec.r()); 34 | /// assert_eq!(g2.loc(2.0,2.0,2.0),2.0*test_vec.r()); 35 | /// ``` 36 | pub fn new(func: &'a dyn Fn(&ThreeVec) -> f64) -> ThreeField { 37 | ThreeField { 38 | func, 39 | multi: 1.0, 40 | } 41 | } 42 | 43 | /// Return value of field from three floats. 44 | pub fn loc(&self, i: f64, j:f64, k:f64) -> f64 { 45 | let buf_vec = ThreeVec::new(i,j,k); 46 | self.multi*(self.func)(&buf_vec) 47 | } 48 | 49 | /// Return value of field at vector. 50 | pub fn at(&self, vec: ThreeVec) -> f64 { 51 | self.multi*(self.func)(&vec) 52 | } 53 | } 54 | 55 | impl<'a> Mul for ThreeField<'a> { 56 | type Output = ThreeField<'a>; 57 | 58 | /// Scale a ThreeField by float. 59 | fn mul(self, coef: f64) -> ThreeField<'a> { 60 | ThreeField { 61 | func: self.func, 62 | multi: coef*self.multi, 63 | } 64 | } 65 | } 66 | 67 | impl<'a> Mul> for f64 { 68 | type Output = ThreeField<'a>; 69 | 70 | /// Scale a ThreeField by a float from the other side. 71 | fn mul(self, other: ThreeField<'a>) -> ThreeField<'a> { 72 | ThreeField { 73 | func: other.func, 74 | multi: self*other.multi, 75 | } 76 | } 77 | } 78 | 79 | impl<'a> Neg for ThreeField<'a> { 80 | type Output = ThreeField<'a>; 81 | 82 | /// Negate a ThreeField. 83 | fn neg(self) -> ThreeField<'a> { 84 | ThreeField { 85 | func: self.func, 86 | multi: -self.multi, 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/field/three_vec_field.rs: -------------------------------------------------------------------------------- 1 | use std::f64; 2 | use std::ops::Mul; 3 | use std::ops::Neg; 4 | 5 | use crate::three_mat; 6 | use three_mat::ThreeVec; 7 | 8 | /// Three dimensional vector field 9 | #[derive(Clone,Copy)] 10 | pub struct ThreeVecField<'a> { 11 | func: &'a dyn Fn(&ThreeVec) -> ThreeVec, 12 | multi: f64, 13 | } 14 | 15 | impl<'a> ThreeVecField<'a> { 16 | /// Returns a new ThreeVecField 17 | /// 18 | /// # Arguments 19 | /// 20 | /// * `func` - &'a dyn Fn(&ThreeVec) -> ThreeVec 21 | /// 22 | /// # Example 23 | /// ``` 24 | /// use calcify::ThreeVec; 25 | /// use calcify::ThreeVecField; 26 | /// 27 | /// let g = ThreeVecField::new(&|tv: &ThreeVec| 2.0*(*tv)); 28 | /// let g2: ThreeVecField = 2.0*g; 29 | /// 30 | /// let test_vec = ThreeVec::new(2.0,2.0,2.0); 31 | /// 32 | /// assert_eq!(g.loc(2.0,2.0,2.0),2.0*test_vec); 33 | /// assert_eq!(g.at(test_vec),ThreeVec::new(4.0,4.0,4.0)); 34 | /// assert_eq!(g2.loc(2.0,2.0,2.0),ThreeVec::new(8.0,8.0,8.0)); 35 | /// ``` 36 | pub fn new(func: &'a dyn Fn(&ThreeVec) -> ThreeVec) -> ThreeVecField { 37 | ThreeVecField { 38 | func, 39 | multi: 1.0, 40 | } 41 | } 42 | 43 | /// Return value of field from three floats. 44 | pub fn loc(&self, i: f64, j:f64, k:f64) -> ThreeVec { 45 | let buf_vec = ThreeVec::new(i,j,k); 46 | self.multi*(self.func)(&buf_vec) 47 | } 48 | 49 | /// Return value of field from a ThreeVec 50 | pub fn at(&self, vec: ThreeVec) -> ThreeVec { 51 | self.multi*(self.func)(&vec) 52 | } 53 | } 54 | 55 | impl<'a> Mul for ThreeVecField<'a> { 56 | type Output = ThreeVecField<'a>; 57 | 58 | /// Scale a ThreeVecField by float. 59 | fn mul(self, coef: f64) -> ThreeVecField<'a> { 60 | ThreeVecField { 61 | func: self.func, 62 | multi: coef*self.multi, 63 | } 64 | } 65 | } 66 | 67 | impl<'a> Mul> for f64 { 68 | type Output = ThreeVecField<'a>; 69 | 70 | /// Scale a ThreeVecField by float from the other side. 71 | fn mul(self, other: ThreeVecField<'a>) -> ThreeVecField<'a> { 72 | ThreeVecField { 73 | func: other.func, 74 | multi: self*other.multi, 75 | } 76 | } 77 | } 78 | 79 | impl<'a> Neg for ThreeVecField<'a> { 80 | type Output = ThreeVecField<'a>; 81 | 82 | /// Negate a ThreeVecField. 83 | fn neg(self) -> ThreeVecField<'a> { 84 | ThreeVecField { 85 | func: self.func, 86 | multi: -self.multi, 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/utils/serializable.rs: -------------------------------------------------------------------------------- 1 | use std::marker::Sized; 2 | use std::error; 3 | 4 | extern crate rmp; 5 | use rmp::encode::*; 6 | use rmp::decode::*; 7 | /// Serialization trait which all types you intend to put in a Tree need to implement. 8 | pub trait Serializable { 9 | /// Return object intensive json string 10 | /// # I.E. 11 | /// `FourVec -> {"x0":1.0,"x1":0.0,"x2":0.0,"x3":0.0}` 12 | fn to_json(&self) -> String; 13 | /// Return Result wrapped Vec in MsgPack 14 | /// Format is *not* like to_json it is array intensive not object 15 | /// 16 | /// #Errors 17 | /// * The rmp library returns `ValueWriteError` on write errors 18 | fn to_msg(&self) -> Result,ValueWriteError> ; 19 | } 20 | /// Deserialization trait which all types you intend to get out of a Tree need to implement. 21 | /// Really only designed to work with data that was serialized with the Calcify::Serializable trait 22 | /// and will not work on arbitrarily modified tree files 23 | pub trait Deserializable { 24 | /// Return Self from string 25 | fn from_json(string: &str) -> Result> 26 | where Self: Sized; 27 | /// Return a tuple of Self and a &[u8] of remaining unparsed bytes from a byte array 28 | fn from_msg(bytes: &[u8]) -> Result<(Self,&[u8]), Box> 29 | where Self: Sized; 30 | } 31 | 32 | impl Serializable for u64 { 33 | fn to_json(&self) -> String { 34 | format!("{}",self) 35 | } 36 | 37 | fn to_msg(&self) -> Result,ValueWriteError> { 38 | let mut buf = Vec::new(); 39 | write_uint(&mut buf, *self)?; 40 | Ok(buf) 41 | } 42 | } 43 | 44 | impl Deserializable for u64 { 45 | fn from_json(string: &str) -> Result> { 46 | string.parse::().map_err(|e| e.into()) 47 | } 48 | fn from_msg(mut bytes: &[u8]) -> Result<(Self,&[u8]), Box> { 49 | Ok((read_int(&mut bytes)?,bytes)) 50 | } 51 | } 52 | 53 | 54 | impl Serializable for f64 { 55 | fn to_json(&self) -> String { 56 | format!("{}",self) 57 | } 58 | fn to_msg(&self) -> Result,ValueWriteError> { 59 | let mut buf = Vec::new(); 60 | write_f64(&mut buf, *self)?; 61 | Ok(buf) 62 | } 63 | } 64 | 65 | impl Deserializable for f64 { 66 | fn from_json(string: &str) -> Result> { 67 | string.parse::().map_err(|e| e.into()) 68 | } 69 | fn from_msg(mut bytes: &[u8]) -> Result<(Self,&[u8]), Box> { 70 | Ok((read_f64(&mut bytes)?,bytes)) 71 | } 72 | } 73 | 74 | 75 | /// Wraps the String in quotes(""). 76 | impl Serializable for String { 77 | fn to_json(&self) -> String { 78 | format!("\"{}\"",self) 79 | } 80 | fn to_msg(&self) -> Result,ValueWriteError> { 81 | let mut buf = Vec::new(); 82 | write_str(&mut buf, self.as_str())?; 83 | Ok(buf) 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/utils/consts.rs: -------------------------------------------------------------------------------- 1 | use std::f64; 2 | 3 | /// Re-export Rust's PI 4 | pub const PI: f64 = std::f64::consts::PI; 5 | 6 | /// The speed of light in a vacuum in SI (299_792_458.0 m/s) 7 | pub const C_LIGHT: f64 = 299_792_458.0; 8 | 9 | /// Boltzmann constant in SI (1.380_650_4e-23 J/K) 10 | pub const K_BOLTZ: f64 = 1.380_650_4e-23; 11 | 12 | /// Elementary charge in SI (1.602_176_487e-19 C) 13 | pub const E_CHARGE: f64 = 1.602_176_487e-19; 14 | 15 | /// Fine structure constant (7.297_352_537_6e-3 unitless) 16 | pub const Q_ALPHA: f64 = 7.297_352_537_6e-3; 17 | 18 | /// Gravitational coupling constant (1.752e-45 unitless) 19 | pub const G_ALPHA: f64 = 1.752e-45; 20 | 21 | /// **Reduced** Planck constant in SI (6.626_068_96e-34/2π J*S) 22 | pub const H_BAR: f64 = 6.626_068_96e-34/(2.0*PI); 23 | 24 | /// Permittivity of free space in SI (8.854_187_817e-12 F/m) 25 | pub const EP_NAUGHT: f64 = 8.854_187_817e-12; 26 | 27 | /// Permeability of free space in SI (4π*10^-7 N/A^2) 28 | pub const MU_NAUGHT: f64 = 4.0*PI*10.0e7; 29 | 30 | /// Gravitational constant in SI (6.674_28e-11 m^3/(kg*s^2)) 31 | pub const BIG_G: f64 = 6.674_28e-11; 32 | 33 | /// Proton mass in SI (1.672_621_637e-27 kg) 34 | pub const M_PROTON: f64 = 1.672_621_637e-27; 35 | 36 | /// Electron mass in SI (9.109_382_15e-31 kg) 37 | pub const M_ELECTRON: f64 = 9.109_382_15e-31; 38 | 39 | /// Calcify consts in different unit systems 40 | pub struct Consts { 41 | pub c_light: f64, 42 | pub k_boltz: f64, 43 | pub e_charge: f64, 44 | pub q_alpha: f64, 45 | pub g_alpha: f64, 46 | pub h_bar: f64, 47 | pub ep_naught: f64, 48 | pub mu_naught: f64, 49 | pub big_g: f64, 50 | pub m_proton: f64, 51 | pub m_electron: f64, 52 | } 53 | 54 | impl Consts { 55 | /// Return all calcify constants in a Consts struct in Planck Lorentz–Heaviside units 56 | /// 57 | /// # Example 58 | /// ``` 59 | /// use calcify::consts::Consts; 60 | /// 61 | /// let consts_planck = Consts::planck(); 62 | /// let c = consts_planck.c_light; 63 | /// let hb = consts_planck.h_bar; 64 | /// assert_eq!(c,1.0); 65 | /// assert_eq!(hb,1.0); 66 | /// ``` 67 | pub fn planck() -> Consts { 68 | Consts { 69 | c_light : 1.0, 70 | k_boltz : 1.0, 71 | e_charge : (4.0*PI*Q_ALPHA).sqrt(), 72 | q_alpha : Q_ALPHA, 73 | g_alpha : G_ALPHA, 74 | h_bar : 1.0, 75 | ep_naught : 1.0, 76 | mu_naught : 1.0, 77 | big_g : 1.0/(4.0*PI), 78 | m_proton : 1_836.152_672_47*(4.0*PI*G_ALPHA).sqrt(), 79 | m_electron : (4.0*PI*G_ALPHA).sqrt(), 80 | } 81 | } 82 | 83 | /// Return all calcify constants in a Consts struct in natural Lorentz–Heaviside units 84 | pub fn natural() -> Consts { 85 | Consts { 86 | c_light : 1.0, 87 | k_boltz : 1.0, 88 | e_charge : (4.0*PI*Q_ALPHA).sqrt(), 89 | q_alpha : Q_ALPHA, 90 | g_alpha : G_ALPHA, 91 | h_bar : 1.0, 92 | ep_naught : 1.0, 93 | mu_naught : 1.0, 94 | big_g : G_ALPHA/(511_000.0*511_000.0), 95 | m_proton : 938_000_000.0, 96 | m_electron : 511_000.0, 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/tree/branch/collection/bin.rs: -------------------------------------------------------------------------------- 1 | use std::ops::AddAssign; 2 | use std::error; 3 | use std::u64; 4 | use std::f64; 5 | 6 | extern crate rmp; 7 | use rmp::encode::*; 8 | use rmp::decode::*; 9 | 10 | use crate::utils; 11 | 12 | use utils::{Serializable, Deserializable}; 13 | use utils::errors::CalcifyError; 14 | 15 | /// A histogram is a Collection of Bins 16 | #[derive(Debug, PartialEq, Copy, Clone)] 17 | pub struct Bin { 18 | pub in_edge: f64, 19 | pub ex_edge: f64, 20 | pub count: u64, 21 | } 22 | 23 | impl Bin { 24 | /// Returns new Bin 25 | /// 26 | /// # Arguments 27 | /// 28 | /// * `in_edge` - f64 Inclusive Edge 29 | /// * `ex_edge` - f64 Exclusive Edge 30 | /// * `count` - u64 Bin value 31 | /// 32 | pub fn new(in_edge: f64, ex_edge: f64, count: u64) -> Bin { 33 | Bin { 34 | in_edge, 35 | ex_edge, 36 | count, 37 | } 38 | } 39 | } 40 | 41 | impl AddAssign for Bin { 42 | /// Increment Bin count. 43 | /// 44 | /// # Example 45 | /// ``` 46 | /// use calcify::Bin; 47 | /// let mut test_bin = Bin::new(0.0,1.0,10); 48 | /// test_bin += 1; 49 | /// 50 | /// assert_eq!(test_bin.count, 11); 51 | /// ``` 52 | fn add_assign(&mut self, other: u64) { 53 | self.count += other; 54 | } 55 | } 56 | 57 | impl Serializable for Bin { 58 | fn to_json(&self) -> String { 59 | format!("{{\"count\":{},\"range\":[{},{}]}}",self.count,self.in_edge,self.ex_edge) 60 | } 61 | 62 | fn to_msg(&self) -> Result, ValueWriteError> { 63 | let mut buf = Vec::with_capacity(5); 64 | write_array_len(&mut buf, 2)?; 65 | write_uint(&mut buf, self.count)?; 66 | write_array_len(&mut buf, 2)?; 67 | write_f64(&mut buf, self.in_edge)?; 68 | write_f64(&mut buf, self.ex_edge)?; 69 | Ok(buf) 70 | } 71 | } 72 | 73 | impl Deserializable for Bin { 74 | 75 | fn from_json(s: &str) -> Result> { 76 | let mut count: u64 = 0; 77 | let mut in_edge: f64 = f64::NAN; 78 | let mut ex_edge: f64 = f64::NAN; 79 | for (i,dim) in s.replace(":",",").replace("[",",").replace("]",",").trim_matches(|p| p == '{' || p == '}' ).split_terminator(",").enumerate() { 80 | match i { 81 | 0 => (), 82 | 1 => count = dim.parse::()? as u64, 83 | 2 => (), 84 | 3 => (), 85 | 4 => in_edge = dim.parse::()?, 86 | 5 => ex_edge = dim.parse::()?, 87 | _ => return Err(Box::new(CalcifyError::ParseError)), 88 | } 89 | } 90 | Ok(Bin{count,in_edge,ex_edge}) 91 | } 92 | 93 | fn from_msg(mut bytes: &[u8]) -> Result<(Self,&[u8]), Box> { 94 | if let Ok(2) = read_array_len(&mut bytes){ 95 | let count: u64 = read_int(&mut bytes)?; 96 | if let Ok(2) = read_array_len(&mut bytes){ 97 | let in_edge: f64 = read_f64(&mut bytes)?; 98 | let ex_edge: f64 = read_f64(&mut bytes)?; 99 | return Ok((Bin{count,in_edge,ex_edge},bytes)); 100 | } 101 | } 102 | Err(Box::new(CalcifyError::ParseError)) 103 | } 104 | } 105 | 106 | #[cfg(test)] 107 | mod tests { 108 | use super::*; 109 | #[test] 110 | fn test_parse() { 111 | let xx = Bin::new(0.0,1.0,0); 112 | let pp = xx.to_json(); 113 | assert_eq!(Bin::from_json(&pp).unwrap(),xx); 114 | } 115 | 116 | #[test] 117 | fn test_msg_parse() { 118 | let xx = Bin::new(0.0,1.0,0); 119 | let pp = xx.to_msg().unwrap(); 120 | let (oo,_) = Bin::from_msg(&pp).unwrap(); 121 | assert_eq!(oo,xx); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Calcify 2 | 3 | A crate for 3-D and 4-D vector and matrix algebra, conceived for use in physics simulations. Builds out from a basic ThreeVec struct including most commonly used operations built in. 4 | Includes physics constants, 3 and 4-D vectors and matrices and many associated operations, collections, histograms, and output trees, which are serialized in json or MessagePack. 5 | 6 | ## ICalcify 7 | 8 | Python command line utility and module for analyzing Tree files. 9 | 10 | Check it out [here!](https://github.com/JTPond/ICalcify "ICalcify GitHub") 11 | 12 | ## Usage 13 | 14 | ```rust 15 | use std::error; 16 | 17 | extern crate calcify; 18 | 19 | use calcify::Tree; 20 | use calcify::FeedTree; 21 | use calcify::Collection; 22 | use calcify::Bin; 23 | use calcify::Point; 24 | use calcify::io::ToFile; 25 | 26 | mod dummy_experiment_lib; 27 | 28 | use dummy_experiment_lib::Projectile; 29 | use dummy_experiment_lib::Lab; 30 | 31 | fn main() -> Result<(),Box> { 32 | let mut ftree = FeedTree::::new("Dummy_States","Object"); 33 | let mut ttree = Tree::new("Dummy_Data"); 34 | 35 | ftree.add_field("Desc","A FeedTree of states for a simulation that does not exist.")?; 36 | ttree.add_field("Desc","A Tree data branches for a simulation that does not exist.")?; 37 | 38 | let mut dummy_lab = Lab::new(); 39 | 40 | let init_state: Collection = Collection::from(dummy_lab.state.clone()); 41 | let init_hist: Collection = init_state.map(|x| {x.r().r()}).hist(500); 42 | let init_spread: Collection = Collection::plot(&init_state.map(|x| {*x.r().x0()}).vec, 43 | &init_state.map(|x| {*x.r().x1()}).vec) 44 | .cut(|p| p.r() <= 1.0); 45 | 46 | ftree.add_feed("init_state", init_state)?; 47 | ttree.add_branch("init_hist", init_hist, "Bin")?; 48 | ttree.add_branch("init_spread", init_spread, "Point")?; 49 | 50 | dummy_lab.run(1000); 51 | 52 | let fin_state: Collection = Collection::from(dummy_lab.state.clone()); 53 | let fin_hist: Collection = fin_state.map(|x| {x.r().r()}).hist(500); 54 | let fin_spread: Collection = Collection::plot(&fin_state.map(|x| {*x.r().x0()}).vec, 55 | &fin_state.map(|x| {*x.r().x1()}).vec) 56 | .cut(|p| p.r() <= 1.0); 57 | 58 | ftree.add_feed("fin_state", fin_state)?; 59 | ttree.add_branch("fin_hist", fin_hist, "Bin")?; 60 | ttree.add_branch("fin_spread", fin_spread, "Point")?; 61 | 62 | ftree.write_msg("dummy_states.msg")?; 63 | ttree.write_msg("dummy_data.msg")?; 64 | Ok(()) 65 | } 66 | ``` 67 | 68 | ## Example 69 | 70 | `cargo run --example universe_in_a_box --release` 71 | 72 | ## Notes about File IO 73 | 74 | * Even though json is supported for both reading and writing, it's not as efficiently implemented and may lead to slowdowns when reading large files. Consider only using it for debugging, so that you can read the results of tests, otherwise use msg. 75 | 76 | * Feel free to use Serde when implementing the Serialization traits for your types 77 | 78 | ### Trees 79 | 80 | | Write | Read | 81 | | ----------- | ----------- | 82 | | Supports all subtypes | Internal types only, and not `Object`| 83 | 84 | ### FeedTrees 85 | 86 | | Write| Read | 87 | | -----| -----| 88 | | Supports all subtypes| Supports all subtypes| 89 | 90 | ## License 91 | 92 | Licensed under either of 93 | 94 | * Apache License, Version 2.0 95 | ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) 96 | * MIT license 97 | ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) 98 | 99 | at your option. 100 | 101 | ## Contribution 102 | 103 | Unless you explicitly state otherwise, any contribution intentionally submitted 104 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall be 105 | dual licensed as above, without any additional terms or conditions. 106 | -------------------------------------------------------------------------------- /examples/universe_in_a_box/main.rs: -------------------------------------------------------------------------------- 1 | use std::error; 2 | 3 | #[macro_use] 4 | extern crate lazy_static; 5 | 6 | extern crate calcify; 7 | extern crate chrono; 8 | 9 | use chrono::prelude::*; 10 | 11 | use calcify::Tree; 12 | use calcify::FeedTree; 13 | use calcify::Collection; 14 | use calcify::Bin; 15 | use calcify::Point; 16 | use calcify::PointBin; 17 | use calcify::io::ToFile; 18 | 19 | mod universe_in_a_box; 20 | 21 | use universe_in_a_box::Particle; 22 | use universe_in_a_box::Universe; 23 | 24 | fn main() -> Result<(),Box> { 25 | lazy_static!{ 26 | static ref UNIVERSE_RANGE: f64 = 1.0; 27 | static ref UNIVERSE_NUM: usize = 500; 28 | static ref UNIVERSE_DT: f64 = 0.01; 29 | static ref RUN_T: usize = 200; 30 | static ref NOW: DateTime = Local::now(); 31 | static ref NOWS: String = NOW.format("%m/%d/%Y %H:%M").to_string(); 32 | static ref DETAILS: String = format!("Universe Range: {}, Number of Particles: {}, Delta T: {}, Time steps: {}, Total Time: {}", 33 | *UNIVERSE_RANGE, *UNIVERSE_NUM, *UNIVERSE_DT, *RUN_T, (*RUN_T as f64)*(*UNIVERSE_DT)); 34 | } 35 | let mut ftree = FeedTree::::new("states","Object"); 36 | let mut ttree = Tree::new("data"); 37 | 38 | let mut universe = Universe::cloud(*UNIVERSE_RANGE,*UNIVERSE_NUM,*UNIVERSE_DT); 39 | 40 | let init_state: Collection = Collection::from(universe.state.clone()); 41 | let init_hist: Collection = init_state.map(|x| {x.r().r()}).hist(50); 42 | let init_spread: Collection = Collection::plot(&init_state.map(|x| {*x.r().x0()}).vec, 43 | &init_state.map(|x| {*x.r().x1()}).vec) 44 | .cut(|p| p.r() <= 1.0); 45 | let init_heat: Collection = Collection::plot(&init_state.map(|x| {*x.r().x0()}).vec, 46 | &init_state.map(|x| {*x.r().x1()}).vec) 47 | .cut(|p| p.r() <= 1.0) 48 | .hist(50,50); 49 | 50 | ftree.add_field("Desc","A FeedTree of states for the simple universe in a box multiparticle simulation.")?; 51 | ftree.add_field("Details", &*DETAILS)?; 52 | ftree.add_field("Run on",&*NOWS)?; 53 | 54 | ttree.add_field("Desc","A Tree data branches for the simple universe in a box multiparticle simulation.")?; 55 | ttree.add_field("Details", &*DETAILS)?; 56 | ttree.add_field("Run on",&*NOWS)?; 57 | 58 | 59 | 60 | ftree.add_feed("init_state", init_state)?; 61 | 62 | ttree.add_branch("init_hist", init_hist, "Bin")?; 63 | ttree.add_branch("init_spread", init_spread, "Point")?; 64 | ttree.add_branch("init_heat", init_heat, "PointBin")?; 65 | 66 | universe.run(*RUN_T); 67 | 68 | let mid1_state: Collection = Collection::from(universe.state.clone()); 69 | let mid1_hist: Collection = mid1_state.map(|x| {x.r().r()}).hist(50); 70 | 71 | ftree.add_feed("mid1_state", mid1_state)?; 72 | ttree.add_branch("mid1_hist", mid1_hist, "Bin")?; 73 | 74 | universe.run(*RUN_T); 75 | 76 | let mid2_state: Collection = Collection::from(universe.state.clone()); 77 | let mid2_hist: Collection = mid2_state.map(|x| {x.r().r()}).hist(50); 78 | 79 | ftree.add_feed("mid2_state", mid2_state)?; 80 | ttree.add_branch("mid2_hist", mid2_hist, "Bin")?; 81 | 82 | universe.run(*RUN_T); 83 | 84 | let fin_state: Collection = Collection::from(universe.state.clone()); 85 | let fin_hist: Collection = fin_state.map(|x| {x.r().r()}).hist(50); 86 | let fin_spread: Collection = Collection::plot(&fin_state.map(|x| {*x.r().x0()}).vec, 87 | &fin_state.map(|x| {*x.r().x1()}).vec) 88 | .cut(|p| p.r() <= 1.0); 89 | let fin_heat: Collection = Collection::plot(&fin_state.map(|x| {*x.r().x0()}).vec, 90 | &fin_state.map(|x| {*x.r().x1()}).vec) 91 | .cut(|p| p.r() <= 1.0) 92 | .hist(50,50); 93 | 94 | ftree.add_feed("fin_state", fin_state)?; 95 | ttree.add_branch("fin_hist", fin_hist, "Bin")?; 96 | ttree.add_branch("fin_spread", fin_spread, "Point")?; 97 | ttree.add_branch("fin_heat", fin_heat, "PointBin")?; 98 | 99 | ftree.write_msg("./scratch/universe_states.msg")?; 100 | ttree.write_msg("./scratch/universe_data.msg")?; 101 | Ok(()) 102 | } 103 | -------------------------------------------------------------------------------- /src/tree/branch/collection/point_bin.rs: -------------------------------------------------------------------------------- 1 | use std::ops::AddAssign; 2 | use std::error; 3 | use std::u64; 4 | use std::f64; 5 | 6 | extern crate rmp; 7 | use rmp::encode::*; 8 | use rmp::decode::*; 9 | 10 | use crate::utils; 11 | 12 | use utils::{Serializable, Deserializable}; 13 | use utils::errors::CalcifyError; 14 | 15 | /// A 2D histogram is a Collection of PointBins 16 | #[derive(Debug, PartialEq, Copy, Clone)] 17 | pub struct PointBin { 18 | pub in_edge_x: f64, 19 | pub ex_edge_x: f64, 20 | pub in_edge_y: f64, 21 | pub ex_edge_y: f64, 22 | pub count: u64, 23 | } 24 | 25 | impl PointBin { 26 | /// Returns new PointBin 27 | /// 28 | /// # Arguments 29 | /// 30 | /// * `in_edge_x` - f64 Inclusive Edge along the X axis 31 | /// * `ex_edge_x` - f64 Exclusive Edge along the X axis 32 | /// * `in_edge_y` - f64 Inclusive Edge along the Y axis 33 | /// * `ex_edge_y` - f64 Exclusive Edge along the Y axis 34 | /// * `count` - u64 PointBin value 35 | /// 36 | /// Expectected to be created by calling [hist](./struct.Collection.html#impl-1) on a Collection 37 | pub fn new(in_edge_x: f64, ex_edge_x: f64, in_edge_y: f64, ex_edge_y: f64, count: u64) -> PointBin { 38 | PointBin { 39 | in_edge_x, 40 | ex_edge_x, 41 | in_edge_y, 42 | ex_edge_y, 43 | count, 44 | } 45 | } 46 | } 47 | 48 | impl AddAssign for PointBin { 49 | /// Increment PointBin count. 50 | /// 51 | /// # Example 52 | /// ``` 53 | /// use calcify::PointBin; 54 | /// let mut test_PointBin = PointBin::new(0.0,1.0,0.0,1.0,10); 55 | /// test_PointBin += 1; 56 | /// 57 | /// assert_eq!(test_PointBin.count, 11); 58 | /// ``` 59 | fn add_assign(&mut self, other: u64) { 60 | self.count += other; 61 | } 62 | } 63 | 64 | impl Serializable for PointBin { 65 | fn to_json(&self) -> String { 66 | format!("{{\"count\":{},\"range\":[{},{},{},{}]}}",self.count,self.in_edge_x,self.ex_edge_x,self.in_edge_y,self.ex_edge_y) 67 | } 68 | 69 | fn to_msg(&self) -> Result, ValueWriteError> { 70 | let mut buf = Vec::with_capacity(7); 71 | write_array_len(&mut buf, 2)?; 72 | write_uint(&mut buf, self.count)?; 73 | write_array_len(&mut buf, 4)?; 74 | write_f64(&mut buf, self.in_edge_x)?; 75 | write_f64(&mut buf, self.ex_edge_x)?; 76 | write_f64(&mut buf, self.in_edge_y)?; 77 | write_f64(&mut buf, self.ex_edge_y)?; 78 | Ok(buf) 79 | } 80 | } 81 | 82 | impl Deserializable for PointBin { 83 | 84 | fn from_json(s: &str) -> Result> { 85 | let mut count: u64 = 0; 86 | let mut in_edge_x: f64 = f64::NAN; 87 | let mut ex_edge_x: f64 = f64::NAN; 88 | let mut in_edge_y: f64 = f64::NAN; 89 | let mut ex_edge_y: f64 = f64::NAN; 90 | for (i,dim) in s.replace(":",",").replace("[",",").replace("]",",").trim_matches(|p| p == '{' || p == '}' ).split_terminator(",").enumerate() { 91 | match i { 92 | 0 => (), 93 | 1 => count = dim.parse::()? as u64, 94 | 2 => (), 95 | 3 => (), 96 | 4 => in_edge_x = dim.parse::()?, 97 | 5 => ex_edge_x = dim.parse::()?, 98 | 6 => in_edge_y = dim.parse::()?, 99 | 7 => ex_edge_y = dim.parse::()?, 100 | _ => return Err(Box::new(CalcifyError::ParseError)), 101 | } 102 | } 103 | Ok(PointBin{count,in_edge_x,ex_edge_x,in_edge_y,ex_edge_y}) 104 | } 105 | 106 | fn from_msg(mut bytes: &[u8]) -> Result<(Self,&[u8]), Box> { 107 | if let Ok(2) = read_array_len(&mut bytes){ 108 | let count: u64 = read_int(&mut bytes)?; 109 | if let Ok(4) = read_array_len(&mut bytes){ 110 | let in_edge_x: f64 = read_f64(&mut bytes)?; 111 | let ex_edge_x: f64 = read_f64(&mut bytes)?; 112 | let in_edge_y: f64 = read_f64(&mut bytes)?; 113 | let ex_edge_y: f64 = read_f64(&mut bytes)?; 114 | return Ok((PointBin{count,in_edge_x,ex_edge_x,in_edge_y,ex_edge_y},bytes)); 115 | } 116 | } 117 | Err(Box::new(CalcifyError::ParseError)) 118 | } 119 | } 120 | 121 | #[cfg(test)] 122 | mod tests { 123 | use super::*; 124 | #[test] 125 | fn test_parse() { 126 | let xx = PointBin::new(0.0,1.0,0.0,1.0,0); 127 | let pp = xx.to_json(); 128 | assert_eq!(PointBin::from_json(&pp).unwrap(),xx); 129 | } 130 | 131 | #[test] 132 | fn test_msg_parse() { 133 | let xx = PointBin::new(0.0,1.0,0.0,1.0,0); 134 | let pp = xx.to_msg().unwrap(); 135 | let (oo,_) = PointBin::from_msg(&pp).unwrap(); 136 | assert_eq!(oo,xx); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /examples/universe_in_a_box/universe_in_a_box.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | use std::str::FromStr; 3 | use std::error; 4 | 5 | extern crate rayon; 6 | use rayon::prelude::*; 7 | 8 | extern crate rmp; 9 | use rmp::encode::*; 10 | 11 | extern crate calcify; 12 | pub use calcify::ThreeVec; 13 | use calcify::{Serializable, Deserializable}; 14 | 15 | 16 | #[derive(Debug, PartialEq, Copy, Clone)] 17 | pub struct Particle { 18 | pid: usize, 19 | mass: f64, 20 | charge: f64, 21 | position: ThreeVec, 22 | velocity: ThreeVec, 23 | t_force: ThreeVec, 24 | } 25 | 26 | #[derive(Debug, PartialEq, Clone)] 27 | pub struct Universe { 28 | dt: f64, 29 | energy: f64, 30 | pub state: Vec, 31 | pub previous_state: Vec, 32 | } 33 | 34 | impl Particle { 35 | pub fn dust(pid: usize, max: f64) -> Particle { 36 | let mass = 100.0; 37 | let charge = 0.0; 38 | let position = ThreeVec::random(max); 39 | let velocity = ThreeVec::new(0.0,0.0,0.0); 40 | let t_force = ThreeVec::new(0.0,0.0,0.0); 41 | Particle { 42 | pid, 43 | mass, 44 | charge, 45 | position, 46 | velocity, 47 | t_force 48 | } 49 | } 50 | 51 | pub fn pid(&self) -> &usize { 52 | &self.pid 53 | } 54 | 55 | pub fn m(&self) -> &f64 { 56 | &self.mass 57 | } 58 | 59 | pub fn q(&self) -> &f64 { 60 | &self.charge 61 | } 62 | 63 | pub fn r(&self) -> &ThreeVec { 64 | &self.position 65 | } 66 | 67 | pub fn v(&self) -> &ThreeVec { 68 | &self.velocity 69 | } 70 | 71 | pub fn f(&self) -> &ThreeVec { 72 | &self.t_force 73 | } 74 | 75 | pub fn translate(&mut self, dr: &ThreeVec) { 76 | self.position += *dr; 77 | } 78 | 79 | pub fn accelerate(&mut self, dv: &ThreeVec) { 80 | self.velocity += *dv; 81 | } 82 | 83 | pub fn force(&mut self, parts2: &Vec) { 84 | let g: f64 = 6.67408e-11; 85 | self.t_force = parts2.par_iter().map(|&part2| { 86 | if *part2.pid() != self.pid { 87 | let rmrp = self.position - *part2.r(); 88 | let r2 = rmrp*rmrp; 89 | return (rmrp*(1.0/r2.sqrt()))*((-g*self.mass*part2.m())*(1.0/r2)); 90 | } else { 91 | return ThreeVec::new(0.0,0.0,0.0); 92 | } 93 | }).sum(); 94 | } 95 | 96 | } 97 | 98 | impl fmt::Display for Particle{ 99 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 100 | write!(f, "(pid:{}, m:{}, q:{}, r:{}, v:{})", self.pid(), self.m(), self.q(), self.r(), self.v()) 101 | } 102 | } 103 | 104 | impl Serializable for Particle { 105 | fn to_json(&self) -> String { 106 | format!("{{\"pid\":{},\"m\":{},\"q\":{},\"r\":{},\"v\":{}}}", self.pid(), self.m(), self.q(), self.r().to_json(), self.v().to_json()) 107 | } 108 | fn to_msg(&self) -> Result,ValueWriteError> { 109 | let mut buf = Vec::new(); 110 | write_array_len(&mut buf, 5)?; 111 | write_uint(&mut buf, *self.pid() as u64)?; 112 | buf.append(&mut self.m().to_msg()?); 113 | buf.append(&mut self.q().to_msg()?); 114 | buf.append(&mut self.r().to_msg()?); 115 | buf.append(&mut self.v().to_msg()?); 116 | Ok(buf) 117 | } 118 | } 119 | 120 | impl FromStr for Particle { 121 | type Err = Box; 122 | 123 | fn from_str(s: &str) -> Result { 124 | let mut pid: usize = 0; 125 | let mut mass: f64 = 0.0; 126 | let mut charge: f64 = 0.0; 127 | let mut position = ThreeVec::new(0.0,0.0,0.0); 128 | let mut velocity = ThreeVec::new(0.0,0.0,0.0); 129 | for (i,chunk) in s.split_terminator(",\"r\":").enumerate() { 130 | match i { 131 | 1 => { 132 | for (j,vec) in chunk.replace("}}","}!").trim_matches(|p| p == '!').split_terminator(",\"v\":").enumerate() { 133 | match j { 134 | 0 => position = ThreeVec::from_json(vec)?, 135 | 1 => velocity = ThreeVec::from_json(vec)?, 136 | _ => (), 137 | } 138 | } 139 | }, 140 | 0 => { 141 | for (_j,ky_vl) in chunk.trim_matches(|p| p == '{').split_terminator(",").enumerate() { 142 | let n_v: Vec<&str> = ky_vl.split(":").collect(); 143 | match n_v[0] { 144 | "\"pid\"" => pid = n_v[1].parse::()?, 145 | "\"m\"" => mass = n_v[1].parse::()?, 146 | "\"q\"" => charge = n_v[1].parse::()?, 147 | x => panic!("Unexpected invalid token {:?}", x), 148 | } 149 | } 150 | }, 151 | _ => (), 152 | } 153 | } 154 | 155 | Ok(Particle{pid,mass,charge,position,velocity,t_force:ThreeVec::new(0.0,0.0,0.0)}) 156 | } 157 | } 158 | 159 | impl Universe { 160 | pub fn cloud(size: f64, n: usize, dt: f64) -> Universe { 161 | let energy = 0.0; 162 | let mut state: Vec = Vec::new(); 163 | for i in 0..n{ 164 | let part: Particle = Particle::dust(i, size); 165 | state.push(part); 166 | } 167 | let previous_state = state.clone().to_vec(); 168 | Universe { 169 | dt, 170 | energy, 171 | state, 172 | previous_state, 173 | } 174 | } 175 | 176 | pub fn run(&mut self, t: usize) { 177 | let mut cur_state = self.state.clone(); 178 | // let pool = ThreadPool::new(p); 179 | // let (tx,rx) = channel(); 180 | println!("Start run"); 181 | for ti in 0..t { 182 | if ti%100 == 0 {println!("timestamp: {}", ti);} 183 | let prev_state = self.previous_state.clone(); 184 | for i in 0..self.state.len() as usize{ 185 | cur_state[i].force(&prev_state); 186 | let diff = (*cur_state[i].v()*self.dt)+(*cur_state[i].f()*0.5*self.dt*self.dt); 187 | cur_state[i].translate(&diff); 188 | } 189 | let lo_state = cur_state.clone(); 190 | for i in 0..self.state.len() as usize{ 191 | let pre_force = *cur_state[i].f(); 192 | cur_state[i].force(&lo_state); 193 | let diff = (*cur_state[i].f() + pre_force)*0.5*self.dt; 194 | cur_state[i].accelerate(&diff); 195 | } 196 | self.previous_state = cur_state.clone(); 197 | } 198 | self.state = cur_state; 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /src/tree/branch/mod.rs: -------------------------------------------------------------------------------- 1 | use std::error; 2 | use std::f64; 3 | 4 | mod collection; 5 | pub use collection::Collection; 6 | pub use collection::Bin; 7 | pub use collection::Point; 8 | pub use collection::PointBin; 9 | use crate::four_mat::FourVec; 10 | use crate::four_mat::FourMat; 11 | 12 | use crate::three_mat::ThreeMat; 13 | use crate::three_mat::ThreeVec; 14 | 15 | use crate::utils; 16 | use utils::{Serializable, Deserializable}; 17 | use utils::errors::CalcifyError; 18 | 19 | extern crate rmp; 20 | use rmp::encode::*; 21 | use rmp::decode::*; 22 | 23 | 24 | /// Branch 25 | /// 26 | /// # Note 27 | /// 28 | /// * **Not intended for direct use. Use the memebers of Tree instead.** 29 | pub struct Branch { 30 | subtype: String, 31 | branch: Box, 32 | buffer: Option>, 33 | } 34 | 35 | impl Branch{ 36 | pub fn new(subtype: String, branch: Box) -> Branch{ 37 | let buffer: Option> = None; 38 | Branch { 39 | subtype, 40 | branch, 41 | buffer, 42 | } 43 | } 44 | /// Returns a Collection of the specified subtype from the Branch 45 | /// 46 | pub fn extract(&mut self) -> Result, Box> { 47 | if self.buffer.is_none() { 48 | self.buffer = Some(self.branch.to_msg()?); 49 | } 50 | if let Ok((out, _)) = Collection::::from_msg(&mut self.buffer.as_ref().unwrap()){ 51 | return Ok(out); 52 | } 53 | Err(Box::new(CalcifyError::ParseError)) 54 | } 55 | } 56 | 57 | impl Serializable for Branch { 58 | fn to_json(&self) -> String { 59 | format!("{{\"subtype\":{},\"branch\":{}}}",self.subtype.to_json(),self.branch.to_json()) 60 | } 61 | 62 | fn to_msg(&self) -> Result, ValueWriteError> { 63 | let mut buf = Vec::new(); 64 | write_map_len(&mut buf, 2)?; 65 | write_str(&mut buf, "subtype")?; 66 | buf.append(&mut self.subtype.to_msg()?); 67 | write_str(&mut buf, "branch")?; 68 | buf.append(&mut self.branch.to_msg()?); 69 | Ok(buf) 70 | } 71 | } 72 | 73 | impl Deserializable for Branch { 74 | fn from_json(s: &str) -> Result> { 75 | let mut subtype: &str = ""; 76 | let mut branch_str: &str = ""; 77 | let pattern: Vec = "{\"subtype\":}".chars().collect(); 78 | for (i,dim) in s.trim_matches(|p| pattern.contains(&p)).split(",\"branch\":").enumerate() { 79 | match i { 80 | 0 => subtype = dim.trim_matches(|p| p == '\"'), 81 | 1 => branch_str = dim, 82 | _ => return Err(Box::new(CalcifyError::ParseError)), 83 | } 84 | } 85 | let branch: Box = match subtype { 86 | "f64" => Box::new(Collection::::from_json(&branch_str)?), 87 | "ThreeVec" => Box::new(Collection::::from_json(&branch_str)?), 88 | "ThreeMat" => Box::new(Collection::::from_json(&branch_str)?), 89 | "FourVec" => Box::new(Collection::::from_json(&branch_str)?), 90 | "FourMat" => Box::new(Collection::::from_json(&branch_str)?), 91 | "Bin" => Box::new(Collection::::from_json(&branch_str)?), 92 | "Point" => Box::new(Collection::::from_json(&branch_str)?), 93 | "PointBin" => Box::new(Collection::::from_json(&branch_str)?), 94 | _ => return Err(Box::new(CalcifyError::ParseError)), 95 | }; 96 | Ok(Branch::new(subtype.to_string(),branch)) 97 | } 98 | 99 | fn from_msg(mut bytes: &[u8]) -> Result<(Self,&[u8]), Box> { 100 | 101 | if let Ok(_len) = read_map_len(&mut bytes) { 102 | let mut unparsed = &bytes[..]; 103 | if let Ok((_,rest)) = read_str_from_slice(unparsed) { 104 | unparsed = rest; 105 | if let Ok((subtype,rest)) = read_str_from_slice(unparsed) { 106 | unparsed = rest; 107 | if let Ok((_,rest)) = read_str_from_slice(unparsed) { 108 | unparsed = rest; 109 | let (branch,rest): (Box,&[u8]) = match subtype { 110 | "f64" => { 111 | if let Ok((ot,rest)) = Collection::::from_msg(unparsed) { 112 | (Box::new(ot),rest) 113 | } else { 114 | return Err(Box::new(CalcifyError::ParseError)); 115 | } 116 | }, 117 | "ThreeVec" => { 118 | if let Ok((ot,rest)) = Collection::::from_msg(unparsed) { 119 | (Box::new(ot),rest) 120 | } else { 121 | return Err(Box::new(CalcifyError::ParseError)); 122 | } 123 | }, 124 | "ThreeMat" => { 125 | if let Ok((ot,rest)) = Collection::::from_msg(unparsed) { 126 | (Box::new(ot),rest) 127 | } else { 128 | return Err(Box::new(CalcifyError::ParseError)); 129 | } 130 | }, 131 | "FourVec" => { 132 | if let Ok((ot,rest)) = Collection::::from_msg(unparsed) { 133 | (Box::new(ot),rest) 134 | } else { 135 | return Err(Box::new(CalcifyError::ParseError)); 136 | } 137 | }, 138 | "FourMat" => { 139 | if let Ok((ot,rest)) = Collection::::from_msg(unparsed) { 140 | (Box::new(ot),rest) 141 | } else { 142 | return Err(Box::new(CalcifyError::ParseError)); 143 | } 144 | }, 145 | "Bin" => { 146 | if let Ok((ot,rest)) = Collection::::from_msg(&mut bytes) { 147 | (Box::new(ot),rest) 148 | } else { 149 | return Err(Box::new(CalcifyError::ParseError)); 150 | } 151 | }, 152 | "Point" => { 153 | if let Ok((ot,rest)) = Collection::::from_msg(&mut bytes) { 154 | (Box::new(ot),rest) 155 | } else { 156 | return Err(Box::new(CalcifyError::ParseError)); 157 | } 158 | }, 159 | "PointBin" => { 160 | if let Ok((ot,rest)) = Collection::::from_msg(&mut bytes) { 161 | (Box::new(ot),rest) 162 | } else { 163 | return Err(Box::new(CalcifyError::ParseError)); 164 | } 165 | }, 166 | "Object" => { 167 | return Err(Box::new(CalcifyError::ObjectBranchDeserializeError)); 168 | }, 169 | _ => return Err(Box::new(CalcifyError::ParseError)), 170 | }; 171 | return Ok((Branch::new(subtype.to_string(),branch),rest)); 172 | } 173 | } 174 | } 175 | } 176 | Err(Box::new(CalcifyError::ParseError)) 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /src/tree/branch/collection/point.rs: -------------------------------------------------------------------------------- 1 | extern crate rand; 2 | 3 | use std::f64; 4 | use self::f64::NAN; 5 | use std::ops::Add; 6 | use std::ops::AddAssign; 7 | use std::ops::Sub; 8 | use std::ops::SubAssign; 9 | use std::ops::Mul; 10 | use std::ops::Neg; 11 | use std::iter; 12 | use std::fmt; 13 | use std::error; 14 | 15 | extern crate rmp; 16 | use rmp::encode::*; 17 | use rmp::decode::*; 18 | 19 | use self::rand::thread_rng; 20 | use self::rand::distributions::{Distribution, Uniform}; 21 | 22 | use crate::utils; 23 | use utils::{Serializable, Deserializable}; 24 | use utils::errors::CalcifyError; 25 | 26 | /// Point, or Two Vector, depending on your perspective. 27 | /// A plot is a Collection of Points 28 | #[derive(Debug, PartialEq, Copy, Clone)] 29 | pub struct Point { 30 | pub x: f64, 31 | pub y: f64, 32 | } 33 | 34 | impl Point { 35 | /// Returns new Point 36 | /// 37 | /// # Arguments 38 | /// 39 | /// * `x` - prim@f64 Independent Variable 40 | /// * `y` - prim@f64 Dependent Variable 41 | /// 42 | pub fn new(x: f64, y: f64) -> Point { 43 | Point { 44 | x, 45 | y, 46 | } 47 | } 48 | 49 | /// Returns a new Point from a slice 50 | /// 51 | /// # Arguments 52 | /// 53 | /// * `slice` - &[prim@f64] 54 | /// 55 | /// # Example 56 | /// ``` 57 | /// use calcify::Point; 58 | /// let point: Point = Point::from(&[1.0,1.0]); 59 | /// ``` 60 | /// 61 | /// # Panics 62 | /// 63 | /// * `slice` length < 2 64 | pub fn from(slice: &[f64]) -> Point { 65 | 66 | Point { 67 | x: slice[0], 68 | y: slice[1], 69 | } 70 | } 71 | 72 | /// Returns a new Point with two random f64 from rand::Uniform between -1 and 1 73 | /// 74 | /// # Arguments 75 | /// 76 | /// * `max` - prim@f64: The absolute maximum value of each individule componant of the constituent Point 77 | /// 78 | /// # Example 79 | /// ``` 80 | /// use calcify::Point; 81 | /// let vec2 = Point::random(10.0); 82 | /// ``` 83 | pub fn random(max: f64) -> Point { 84 | let between = Uniform::new_inclusive(-1.0f64,1.0f64); 85 | let mut rng = thread_rng(); 86 | Point { 87 | x: between.sample(&mut rng)*max, 88 | y: between.sample(&mut rng)*max, 89 | } 90 | } 91 | 92 | /// Returns the length of the 2vector 93 | /// 94 | /// # Example 95 | /// ``` 96 | /// use calcify::Point; 97 | /// let vec2 = Point::new(1.0,0.0); 98 | /// assert_eq!(vec2.r(),1.0); 99 | /// ``` 100 | pub fn r(&self) -> f64 { 101 | (*self**self).sqrt() 102 | } 103 | } 104 | 105 | impl Serializable for Point { 106 | fn to_json(&self) -> String { 107 | format!("{{\"x\":{},\"y\":{}}}", self.x, self.y) 108 | } 109 | 110 | fn to_msg(&self) -> Result,ValueWriteError> { 111 | let mut buf = Vec::with_capacity(3); 112 | write_array_len(&mut buf, 2)?; 113 | write_f64(&mut buf, self.x)?; 114 | write_f64(&mut buf, self.y)?; 115 | Ok(buf) 116 | } 117 | } 118 | 119 | impl Deserializable for Point { 120 | 121 | fn from_json(s: &str) -> Result> { 122 | let mut x: f64 = NAN; 123 | let mut y: f64 = NAN; 124 | for dim in s.trim_matches(|p| p == '{' || p == '}' ).split(',') { 125 | let n_v: Vec<&str> = dim.split(':').collect(); 126 | match n_v[0] { 127 | "\"x\"" => x = n_v[1].parse::()?, 128 | "\"y\"" => y = n_v[1].parse::()?, 129 | _ => return Err(Box::new(CalcifyError::ParseError)), 130 | } 131 | } 132 | Ok(Point{x,y}) 133 | } 134 | 135 | fn from_msg(mut bytes: &[u8]) -> Result<(Self,&[u8]), Box> { 136 | if let Ok(2) = read_array_len(&mut bytes){ 137 | let mut x: [f64;2] = [NAN;2]; 138 | for i in 0..2 { 139 | x[i] = read_f64(&mut bytes)?; 140 | } 141 | Ok((Point::from(&x),bytes)) 142 | } else { 143 | Err(Box::new(CalcifyError::ParseError)) 144 | } 145 | } 146 | } 147 | 148 | impl fmt::Display for Point { 149 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 150 | write!(f, "[{:.*}, {:.*}]", 5, self.x, 5, self.y) 151 | } 152 | } 153 | 154 | impl Add for Point { 155 | type Output = Point; 156 | 157 | fn add(self, other: Point) -> Point { 158 | Point { 159 | x: self.x + other.x, 160 | y: self.y + other.y, 161 | } 162 | } 163 | } 164 | 165 | impl iter::Sum for Point { 166 | fn sum(iter: I) -> Point 167 | where I: Iterator { 168 | iter.fold(Point { x: 0.0, y: 0.0 }, |a, b| a + b) 169 | } 170 | } 171 | 172 | impl AddAssign for Point { 173 | fn add_assign(&mut self, other: Point) { 174 | self.x += other.x; 175 | self.y += other.y; 176 | } 177 | } 178 | 179 | impl Sub for Point { 180 | type Output = Point; 181 | 182 | fn sub(self, other: Point) -> Point { 183 | Point { 184 | x: self.x - other.x, 185 | y: self.y - other.y, 186 | } 187 | } 188 | } 189 | 190 | impl SubAssign for Point { 191 | fn sub_assign(&mut self, other: Point) { 192 | self.x -= other.x; 193 | self.y -= other.y; 194 | } 195 | } 196 | 197 | impl Mul for Point { 198 | type Output = Point; 199 | 200 | fn mul(self, coef: f64) -> Point { 201 | Point { 202 | x: self.x * coef, 203 | y: self.y * coef, 204 | } 205 | } 206 | } 207 | 208 | impl Mul for f64 { 209 | type Output = Point; 210 | 211 | fn mul(self, vec: Point) -> Point { 212 | Point { 213 | x: vec.x * self, 214 | y: vec.y * self, 215 | } 216 | } 217 | } 218 | 219 | impl Mul for Point { 220 | type Output = f64; 221 | /// Dot product 222 | /// 223 | /// # Example 224 | /// 225 | /// ``` 226 | /// use calcify::Point; 227 | /// let point = Point::new(2.0,2.0); 228 | /// 229 | /// assert_eq!( 230 | /// point*point, 231 | /// 8.0 232 | /// ); 233 | /// ``` 234 | fn mul(self, other: Point) -> f64 { 235 | self.x * other.x + self.y * other.y 236 | } 237 | } 238 | 239 | impl Neg for Point { 240 | type Output = Point; 241 | 242 | fn neg(self) -> Point { 243 | Point { 244 | x: -self.x, 245 | y: -self.y, 246 | } 247 | } 248 | } 249 | 250 | #[cfg(test)] 251 | mod tests { 252 | use super::*; 253 | 254 | #[test] 255 | fn test_add() { 256 | let _test_vec1 = Point::new(1.0,2.0); 257 | let _test_vec2 = Point::new(2.0,3.0); 258 | 259 | assert_eq!( 260 | _test_vec1+_test_vec2, 261 | Point::new(3.0,5.0) 262 | ); 263 | } 264 | 265 | #[test] 266 | fn test_loop_add() { 267 | let mut _test_vec1 = Point::new(1.0,1.0); 268 | for _i in 0..9999{ 269 | _test_vec1 += Point::new(1.0,1.0); 270 | } 271 | 272 | assert_eq!( 273 | _test_vec1, 274 | Point::new(10_000.0,10_000.0) 275 | ); 276 | } 277 | 278 | #[test] 279 | fn test_sub() { 280 | let _test_vec1 = Point::new(3.0,5.0); 281 | let _test_vec2 = Point::new(2.0,3.0); 282 | 283 | assert_eq!( 284 | _test_vec1-_test_vec2, 285 | Point::new(1.0,2.0) 286 | ); 287 | } 288 | 289 | #[test] 290 | fn test_loop_sub() { 291 | let mut _test_vec1 = Point::new(10_000.0,10_000.0); 292 | for _i in 0..9999{ 293 | _test_vec1 -= Point::new(1.0,1.0); 294 | } 295 | 296 | assert_eq!( 297 | _test_vec1, 298 | Point::new(1.0,1.0) 299 | ); 300 | } 301 | 302 | #[test] 303 | fn test_mul() { 304 | let _test_vec1 = Point::new(2.0,2.0); 305 | let _test_vec2 = Point::new(2.0,2.0); 306 | 307 | assert_eq!( 308 | _test_vec1*_test_vec2, 309 | 8.0 310 | ); 311 | } 312 | 313 | #[test] 314 | fn test_mul_coef() { 315 | let _test_vec1 = Point::new(2.0,2.0); 316 | 317 | assert_eq!( 318 | _test_vec1*2.0, 319 | Point::new(4.0,4.0) 320 | ); 321 | assert_eq!( 322 | 2.0*_test_vec1, 323 | Point::new(4.0,4.0) 324 | ); 325 | } 326 | 327 | #[test] 328 | fn test_neg() { 329 | let _test_vec1 = Point::new(2.0,2.0); 330 | 331 | assert_eq!( 332 | -_test_vec1, 333 | Point::new(-2.0,-2.0) 334 | ); 335 | } 336 | 337 | #[test] 338 | fn test_copy() { 339 | let xx = Point::new(1.0,1.0); 340 | let yy = xx; 341 | assert_eq!( 342 | xx+yy, 343 | Point::new(2.0,2.0) 344 | ); 345 | } 346 | 347 | #[test] 348 | fn test_parse() { 349 | let xx = Point::new(1.0,1.0); 350 | let pp = xx.to_json(); 351 | assert_eq!(Point::from_json(&pp).unwrap(),xx); 352 | } 353 | 354 | #[test] 355 | fn test_msg_parse() { 356 | let xx = Point::new(1.0,1.0); 357 | let pp = xx.to_msg().unwrap(); 358 | let (oo,_) = Point::from_msg(&pp).unwrap(); 359 | assert_eq!(oo,xx); 360 | } 361 | } 362 | -------------------------------------------------------------------------------- /src/tree/feedtree.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::error; 3 | use super::Collection; 4 | 5 | use crate::utils; 6 | use utils::{Serializable, Deserializable}; 7 | use utils::errors::CalcifyError; 8 | use utils::io::{ToFile,FromFile}; 9 | 10 | extern crate rmp; 11 | use rmp::encode::*; 12 | use rmp::decode::*; 13 | 14 | /// Tree of Collections of only a single type, which impl the Feed trait for added functionality 15 | #[derive(Debug, PartialEq, Clone)] 16 | pub struct FeedTree { 17 | metadata: HashMap, 18 | datafeeds: HashMap>, 19 | } 20 | 21 | impl FeedTree { 22 | /// Returns new FeedTree 23 | /// 24 | /// Name and subtype is the only required metadata. 25 | /// # Arguments 26 | /// 27 | /// * `name` - string 28 | /// * `subtype` - string, must match given Serializable type 29 | /// 30 | /// # Example 31 | /// ``` 32 | /// use calcify::FeedTree; 33 | /// use calcify::Collection; 34 | /// 35 | /// let f_col: Collection = Collection::from(vec![0.0,0.0]); 36 | /// let mut ftree: FeedTree = FeedTree::new("Test_Tree","f64"); 37 | /// ftree.add_field("Desc", "This is a FeedTree for testing."); 38 | /// ftree.add_feed("fcol", f_col); 39 | /// ftree.write("fcol", 1.0); 40 | /// ftree.write("fcol", 2.0); 41 | /// assert_eq!(Collection::from(vec![0.0,0.0,1.0,2.0]),*ftree.get_feed("fcol").unwrap()) 42 | /// ``` 43 | pub fn new(name: &str, subtype: &str) -> FeedTree { 44 | let mut md = HashMap::new(); 45 | md.insert(String::from("Name"),String::from(name)); 46 | md.insert(String::from("SubType"),String::from(subtype)); 47 | let df = HashMap::new(); 48 | FeedTree { 49 | metadata: md, 50 | datafeeds: df, 51 | } 52 | } 53 | 54 | pub fn add_field(&mut self, key: &str, f: &str) -> Result<(),CalcifyError> { 55 | if let Some(_) = self.metadata.insert(String::from(key),String::from(f)) { 56 | return Err(CalcifyError::KeyError); 57 | } 58 | Ok(()) 59 | } 60 | 61 | /// Inserts new Collection into FeedTree. 62 | /// 63 | /// # Arguments 64 | /// 65 | /// * `key` - Hash key, String 66 | /// * `f` - Collection 67 | pub fn add_feed(&mut self, key: &str, f: Collection) -> Result<(),CalcifyError> { 68 | if let Some(_) = self.datafeeds.insert(String::from(key),f) { 69 | return Err(CalcifyError::KeyError); 70 | } 71 | Ok(()) 72 | } 73 | 74 | pub fn get_feed(&mut self, key: &str) -> Option<&Collection> { 75 | self.datafeeds.get(key) 76 | } 77 | 78 | pub fn write(&mut self, key: &str, data: T) -> Result<(),CalcifyError> { 79 | if let Some(feed) = self.datafeeds.get_mut(key) { 80 | feed.push(data); 81 | Ok(()) 82 | } else { 83 | Err(CalcifyError::KeyError) 84 | } 85 | } 86 | } 87 | 88 | impl Serializable for FeedTree { 89 | fn to_json(&self) -> String { 90 | let mut out = String::from("{"); 91 | for (key, val) in &self.metadata { 92 | out.push_str(format!("\"{}\":\"{}\",",key,val).as_str()); 93 | } 94 | out.push_str("\"datafeeds\":{"); 95 | for (key, val) in &self.datafeeds { 96 | out.push_str(format!("\"{}\":{},",key,val.to_json()).as_str()); 97 | } 98 | out.pop(); 99 | out.push_str("}}"); 100 | out 101 | } 102 | 103 | fn to_msg(&self) -> Result, ValueWriteError> { 104 | let mut buf = Vec::new(); 105 | write_map_len(&mut buf, (self.metadata.len()+1) as u32)?; 106 | for (key, val) in &self.metadata { 107 | write_str(&mut buf, key)?; 108 | write_str(&mut buf, val)?; 109 | } 110 | write_str(&mut buf, "datafeeds")?; 111 | write_map_len(&mut buf, (self.datafeeds.len()) as u32)?; 112 | for (key, val) in &self.datafeeds { 113 | write_str(&mut buf, key)?; 114 | buf.append(&mut val.to_msg()?); 115 | } 116 | Ok(buf) 117 | } 118 | } 119 | 120 | impl Deserializable for FeedTree { 121 | fn from_json(s: &str) -> Result> { 122 | let mut metadata: HashMap = HashMap::new(); 123 | let mut datafeeds: HashMap> = HashMap::new(); 124 | for (i,dim) in s.split(",\"datafeeds\":").enumerate() { 125 | match i { 126 | 0 => { 127 | for pair in dim.trim_matches(|p| p == '{' || p == '"' ).split("\",\"") { 128 | let ar: Vec<&str> = pair.split("\":\"").collect(); 129 | metadata.insert(String::from(ar[0]),String::from(ar[1])); 130 | } 131 | }, 132 | 1 => { 133 | for pair in dim.trim_matches(|p| p == '{' || p == '}' || p == '"' ).split("],\"") { 134 | let ar: Vec<&str> = pair.split("\":").collect(); 135 | if let Ok(feed) = Collection::::from_json(&ar[1..].join("\":")){ 136 | datafeeds.insert(String::from(ar[0]),feed); 137 | } else { 138 | return Err(Box::new(CalcifyError::ParseError)); 139 | } 140 | } 141 | }, 142 | _ => return Err(Box::new(CalcifyError::ParseError)), 143 | } 144 | } 145 | Ok(FeedTree{metadata, datafeeds}) 146 | } 147 | 148 | fn from_msg(mut bytes: &[u8]) -> Result<(Self,&[u8]), Box> { 149 | let mut metadata: HashMap = HashMap::new(); 150 | let mut datafeeds: HashMap> = HashMap::new(); 151 | if let Ok(len) = read_map_len(&mut bytes) { 152 | for _ in 0..len { 153 | let mut unparsed: &[u8] = &bytes[..]; 154 | if let Ok((key,v_rest)) = read_str_from_slice(unparsed) { 155 | match key { 156 | "datafeeds" => { 157 | bytes = v_rest; 158 | break; 159 | }, 160 | _ => { 161 | if let Ok((value,rest)) = read_str_from_slice(v_rest) { 162 | unparsed = rest; 163 | metadata.insert(String::from(key),String::from(value)); 164 | } 165 | }, 166 | } 167 | 168 | } 169 | bytes = unparsed; 170 | } 171 | if let Ok(flen) = read_map_len(&mut bytes) { 172 | for _ in 0..flen { 173 | let unparsed: &[u8] = &bytes[..]; 174 | if let Ok((key,v_rest)) = read_str_from_slice(unparsed) { 175 | if let Ok((value,rest)) = Collection::::from_msg(v_rest) { 176 | bytes = rest; 177 | datafeeds.insert(String::from(key),value); 178 | } 179 | } 180 | } 181 | } 182 | } 183 | Ok((FeedTree{metadata, datafeeds},bytes)) 184 | } 185 | } 186 | 187 | impl ToFile for FeedTree{} 188 | impl FromFile for FeedTree{} 189 | 190 | #[cfg(test)] 191 | mod tests { 192 | use super::*; 193 | use crate::ThreeVec; 194 | 195 | #[test] 196 | fn test_ftree_write() -> Result<(),Box>{ 197 | let mut col_3v: Collection = Collection::empty(); 198 | for _i in 0..9 {col_3v.push(ThreeVec::new(1.0,2.0,3.0));} 199 | let mut ttree = FeedTree::new("Test_Tree","ThreeVec"); 200 | ttree.add_field("Desc", "This is a Tree for testing.")?; 201 | ttree.add_feed("fcol", col_3v)?; 202 | ttree.write_msg("./scratch/test_ftree.msg")?; 203 | Ok(()) 204 | } 205 | 206 | #[test] 207 | fn test_ftree_read() -> Result<(),Box>{ 208 | let mut col_3v: Collection = Collection::empty(); 209 | for _i in 0..9 {col_3v.push(ThreeVec::new(1.0,2.0,3.0));} 210 | let mut ttree = FeedTree::new("Test_Tree","ThreeVec"); 211 | ttree.add_field("Desc", "This is a Tree for testing.")?; 212 | ttree.add_feed("fcol", col_3v)?; 213 | 214 | let ftree: FeedTree = FeedTree::read_msg("./scratch/test_ftree.msg")?; 215 | assert_eq!(ftree,ttree); 216 | Ok(()) 217 | } 218 | 219 | #[test] 220 | fn test_ftree_json() -> Result<(),Box>{ 221 | let mut col_3v: Collection = Collection::empty(); 222 | for _i in 0..9 {col_3v.push(ThreeVec::random(1.0));} 223 | let mut ttree = FeedTree::new("Test_Tree","ThreeVec"); 224 | ttree.add_field("Desc", "This is a Tree for testing.")?; 225 | ttree.add_feed("fcol", col_3v.clone())?; 226 | ttree.add_feed("fcol1", col_3v.clone())?; 227 | ttree.add_feed("fcol2", col_3v)?; 228 | let pp = ttree.to_json(); 229 | let oo = FeedTree::::from_json(&pp)?; 230 | println!("{:?}",oo); 231 | Ok(()) 232 | } 233 | 234 | #[test] 235 | fn test_ftree_msg() -> Result<(),Box>{ 236 | let mut col_3v: Collection = Collection::empty(); 237 | for _i in 0..9 {col_3v.push(ThreeVec::random(1.0));} 238 | let mut ttree = FeedTree::new("Test_Tree","ThreeVec"); 239 | ttree.add_field("Desc", "This is a Tree for testing.")?; 240 | ttree.add_feed("fcol", col_3v.clone())?; 241 | ttree.add_feed("fcol2", col_3v)?; 242 | let pp = ttree.to_msg().unwrap(); 243 | let (oo,_) = FeedTree::::from_msg(&pp).unwrap(); 244 | assert_eq!(oo,ttree); 245 | Ok(()) 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /src/three_mat/three_vec/mod.rs: -------------------------------------------------------------------------------- 1 | extern crate rand; 2 | 3 | use std::f64; 4 | use self::f64::NAN; 5 | use std::ops::Add; 6 | use std::ops::AddAssign; 7 | use std::ops::Sub; 8 | use std::ops::SubAssign; 9 | use std::ops::Mul; 10 | use std::ops::Neg; 11 | use std::iter; 12 | use std::fmt; 13 | use std::error; 14 | 15 | use self::rand::thread_rng; 16 | use self::rand::distributions::{Distribution, Uniform}; 17 | 18 | use crate::utils; 19 | use utils::{Serializable, Deserializable}; 20 | use utils::errors::CalcifyError; 21 | 22 | extern crate rmp; 23 | use rmp::encode::*; 24 | use rmp::decode::*; 25 | 26 | /// Three Vector 27 | #[derive(Debug, PartialEq, Copy, Clone)] 28 | pub struct ThreeVec { 29 | x0: f64, 30 | x1: f64, 31 | x2: f64, 32 | } 33 | 34 | impl ThreeVec { 35 | /// Returns a new ThreeVec from three f64s 36 | /// 37 | /// # Arguments 38 | /// 39 | /// * `x0` - f64 40 | /// * `x1` - f64 41 | /// * `x2` - f64 42 | /// 43 | /// # Example 44 | /// ``` 45 | /// use calcify::ThreeVec; 46 | /// let vec3 = ThreeVec::new(1.0,2.0,3.0); 47 | /// ``` 48 | pub fn new(x0: f64, x1: f64, x2: f64) -> ThreeVec { 49 | ThreeVec { 50 | x0, 51 | x1, 52 | x2, 53 | } 54 | } 55 | 56 | /// Returns a new ThreeVec from a slice 57 | /// 58 | /// # Arguments 59 | /// 60 | /// * `slice` - &[prim@f64] 61 | /// 62 | /// # Example 63 | /// ``` 64 | /// use calcify::ThreeVec; 65 | /// let vec3: ThreeVec = ThreeVec::from(&[1.0,1.0,1.0]); 66 | /// ``` 67 | /// 68 | /// # Panics 69 | /// 70 | /// * `slice` length < 3 71 | pub fn from(slice: &[f64]) -> ThreeVec { 72 | 73 | ThreeVec { 74 | x0: slice[0], 75 | x1: slice[1], 76 | x2: slice[2], 77 | } 78 | } 79 | 80 | /// Returns a new ThreeVec with three random f64 from rand::Uniform between -1 and 1 81 | /// 82 | /// # Arguments 83 | /// 84 | /// * `max` - f64: The absolute maximum value of each individule componant of the constituent ThreeVec 85 | /// 86 | /// # Example 87 | /// ``` 88 | /// use calcify::ThreeVec; 89 | /// let vec3 = ThreeVec::random(10.0); 90 | /// ``` 91 | pub fn random(max: f64) -> ThreeVec { 92 | let between = Uniform::new_inclusive(-1.0f64,1.0f64); 93 | let mut rng = thread_rng(); 94 | ThreeVec { 95 | x0: between.sample(&mut rng)*max, 96 | x1: between.sample(&mut rng)*max, 97 | x2: between.sample(&mut rng)*max, 98 | } 99 | } 100 | 101 | /// Returns a reference to the first element of the vector 102 | /// 103 | /// # Example 104 | /// ``` 105 | /// use calcify::ThreeVec; 106 | /// let vec3 = ThreeVec::new(1.0,2.0,3.0); 107 | /// let element_zero: f64 = *vec3.x0(); 108 | /// assert_eq!(element_zero,1.0); 109 | /// ``` 110 | pub fn x0(&self) -> &f64 { 111 | &self.x0 112 | } 113 | 114 | /// Returns a reference to the second element of the vector 115 | /// 116 | /// # Example 117 | /// ``` 118 | /// use calcify::ThreeVec; 119 | /// let vec3 = ThreeVec::new(1.0,2.0,3.0); 120 | /// let element_one: f64 = *vec3.x1(); 121 | /// assert_eq!(element_one,2.0); 122 | /// ``` 123 | pub fn x1(&self) -> &f64 { 124 | &self.x1 125 | } 126 | 127 | /// Returns a reference to the third element of the vector 128 | /// 129 | /// # Example 130 | /// ``` 131 | /// use calcify::ThreeVec; 132 | /// let vec3 = ThreeVec::new(1.0,2.0,3.0); 133 | /// let element_two: f64 = *vec3.x2(); 134 | /// assert_eq!(element_two,3.0); 135 | /// ``` 136 | pub fn x2(&self) -> &f64 { 137 | &self.x2 138 | } 139 | 140 | /// Returns the length of the vector 141 | /// 142 | /// # Example 143 | /// ``` 144 | /// use calcify::ThreeVec; 145 | /// let vec3 = ThreeVec::new(1.0,0.0,0.0); 146 | /// assert_eq!(vec3.r(),1.0); 147 | /// ``` 148 | pub fn r(&self) -> f64 { 149 | (*self**self).sqrt() 150 | } 151 | } 152 | 153 | impl fmt::Display for ThreeVec { 154 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 155 | write!(f, "[{:.*}, {:.*}, {:.*}]", 5, self.x0(), 5, self.x1(), 5, self.x2()) 156 | } 157 | } 158 | 159 | impl Serializable for ThreeVec { 160 | fn to_json(&self) -> String { 161 | format!("{{\"x0\":{},\"x1\":{},\"x2\":{}}}", self.x0(), self.x1(), self.x2()) 162 | } 163 | 164 | fn to_msg(&self) -> Result,ValueWriteError> { 165 | let mut buf = Vec::with_capacity(4); 166 | write_array_len(&mut buf, 3)?; 167 | write_f64(&mut buf, *self.x0())?; 168 | write_f64(&mut buf, *self.x1())?; 169 | write_f64(&mut buf, *self.x2())?; 170 | Ok(buf) 171 | } 172 | } 173 | 174 | impl Deserializable for ThreeVec { 175 | 176 | fn from_json(s: &str) -> Result> { 177 | let mut x0: f64 = NAN; 178 | let mut x1: f64 = NAN; 179 | let mut x2: f64 = NAN; 180 | for dim in s.trim_matches(|p| p == '{' || p == '}' ).split(',') { 181 | let n_v: Vec<&str> = dim.split(':').collect(); 182 | match n_v[0] { 183 | "\"x0\"" => x0 = n_v[1].parse::()?, 184 | "\"x1\"" => x1 = n_v[1].parse::()?, 185 | "\"x2\"" => x2 = n_v[1].parse::()?, 186 | _ => return Err(Box::new(CalcifyError::ParseError)), 187 | } 188 | } 189 | Ok(ThreeVec{x0,x1,x2}) 190 | } 191 | 192 | fn from_msg(mut bytes: &[u8]) -> Result<(Self,&[u8]), Box> { 193 | if let Ok(3) = read_array_len(&mut bytes){ 194 | let mut x: [f64;3] = [NAN;3]; 195 | for i in 0..3 { 196 | x[i] = read_f64(&mut bytes)?; 197 | } 198 | Ok((ThreeVec::from(&x),bytes)) 199 | } else { 200 | Err(Box::new(CalcifyError::ParseError)) 201 | } 202 | } 203 | } 204 | 205 | impl Add for ThreeVec { 206 | type Output = ThreeVec; 207 | 208 | fn add(self, other: ThreeVec) -> ThreeVec { 209 | ThreeVec { 210 | x0: self.x0 + *other.x0(), 211 | x1: self.x1 + *other.x1(), 212 | x2: self.x2 + *other.x2(), 213 | } 214 | } 215 | } 216 | 217 | impl iter::Sum for ThreeVec { 218 | fn sum(iter: I) -> ThreeVec 219 | where I: Iterator { 220 | iter.fold(ThreeVec { x0: 0.0, x1: 0.0, x2: 0.0 }, |a, b| a + b) 221 | } 222 | } 223 | 224 | impl AddAssign for ThreeVec { 225 | fn add_assign(&mut self, other: ThreeVec) { 226 | self.x0 += *other.x0(); 227 | self.x1 += *other.x1(); 228 | self.x2 += *other.x2(); 229 | } 230 | } 231 | 232 | impl Sub for ThreeVec { 233 | type Output = ThreeVec; 234 | 235 | fn sub(self, other: ThreeVec) -> ThreeVec { 236 | ThreeVec { 237 | x0: self.x0 - *other.x0(), 238 | x1: self.x1 - *other.x1(), 239 | x2: self.x2 - *other.x2(), 240 | } 241 | } 242 | } 243 | 244 | impl SubAssign for ThreeVec { 245 | fn sub_assign(&mut self, other: ThreeVec) { 246 | self.x0 -= *other.x0(); 247 | self.x1 -= *other.x1(); 248 | self.x2 -= *other.x2(); 249 | } 250 | } 251 | 252 | impl Mul for ThreeVec { 253 | type Output = ThreeVec; 254 | 255 | fn mul(self, coef: f64) -> ThreeVec { 256 | ThreeVec { 257 | x0: self.x0 * coef, 258 | x1: self.x1 * coef, 259 | x2: self.x2 * coef, 260 | } 261 | } 262 | } 263 | 264 | impl Mul for f64 { 265 | type Output = ThreeVec; 266 | 267 | fn mul(self, vec: ThreeVec) -> ThreeVec { 268 | ThreeVec { 269 | x0: *vec.x0() * self, 270 | x1: *vec.x1() * self, 271 | x2: *vec.x2() * self, 272 | } 273 | } 274 | } 275 | 276 | impl Mul for ThreeVec { 277 | type Output = f64; 278 | /// Dot product 279 | /// 280 | /// # Example 281 | /// 282 | /// ``` 283 | /// use calcify::ThreeVec; 284 | /// let vec3 = ThreeVec::new(2.0,2.0,2.0); 285 | /// 286 | /// assert_eq!( 287 | /// vec3*vec3, 288 | /// 12.0 289 | /// ); 290 | /// ``` 291 | fn mul(self, other: ThreeVec) -> f64 { 292 | self.x0 * *other.x0() + self.x1 * *other.x1() + self.x2 * *other.x2() 293 | } 294 | } 295 | 296 | impl Neg for ThreeVec { 297 | type Output = ThreeVec; 298 | 299 | fn neg(self) -> ThreeVec { 300 | ThreeVec { 301 | x0: -self.x0, 302 | x1: -self.x1, 303 | x2: -self.x2, 304 | } 305 | } 306 | } 307 | 308 | /// Return the angle between two vectors in radians 309 | /// 310 | /// # Example 311 | /// 312 | /// ``` 313 | /// use std::f64; 314 | /// use calcify::ThreeVec; 315 | /// use calcify::radians_between; 316 | /// 317 | /// let vec1 = ThreeVec::new(1.0,0.0,0.0); 318 | /// let vec2 = ThreeVec::new(0.0,1.0,0.0); 319 | /// 320 | /// assert_eq!(radians_between(vec1,vec2),f64::consts::PI/2.0); 321 | /// ``` 322 | pub fn radians_between(one: ThreeVec, other: ThreeVec) -> f64 { 323 | let dot = one*other; 324 | let r1 = (one*one).sqrt(); 325 | let r2 = (other*other).sqrt(); 326 | (dot/(r1*r2)).acos() 327 | } 328 | 329 | /// Return the angle between two vectors in degrees 330 | /// 331 | /// # Example 332 | /// 333 | /// ``` 334 | /// use std::f64; 335 | /// use calcify::ThreeVec; 336 | /// use calcify::degrees_between; 337 | /// 338 | /// let vec1 = ThreeVec::new(1.0,0.0,0.0); 339 | /// let vec2 = ThreeVec::new(0.0,1.0,0.0); 340 | /// 341 | /// assert_eq!(degrees_between(vec1,vec2),90.0); 342 | /// ``` 343 | pub fn degrees_between(one: ThreeVec, other: ThreeVec) -> f64 { 344 | let dot = one*other; 345 | let r1 = (one*one).sqrt(); 346 | let r2 = (other*other).sqrt(); 347 | (dot/(r1*r2)).acos()*(180.0/f64::consts::PI) 348 | } 349 | 350 | #[cfg(test)] 351 | mod tests { 352 | use super::*; 353 | 354 | #[test] 355 | fn test_add() { 356 | let _test_vec1 = ThreeVec::new(1.0,2.0,3.0); 357 | let _test_vec2 = ThreeVec::new(2.0,3.0,4.0); 358 | 359 | assert_eq!( 360 | _test_vec1+_test_vec2, 361 | ThreeVec::new(3.0,5.0,7.0) 362 | ); 363 | } 364 | 365 | #[test] 366 | fn test_loop_add() { 367 | let mut _test_vec1 = ThreeVec::new(1.0,1.0,1.0); 368 | for _i in 0..9999{ 369 | _test_vec1 += ThreeVec::new(1.0,1.0,1.0); 370 | } 371 | 372 | assert_eq!( 373 | _test_vec1, 374 | ThreeVec::new(10_000.0,10_000.0,10_000.0) 375 | ); 376 | } 377 | 378 | #[test] 379 | fn test_sub() { 380 | let _test_vec1 = ThreeVec::new(3.0,5.0,7.0); 381 | let _test_vec2 = ThreeVec::new(2.0,3.0,4.0); 382 | 383 | assert_eq!( 384 | _test_vec1-_test_vec2, 385 | ThreeVec::new(1.0,2.0,3.0) 386 | ); 387 | } 388 | 389 | #[test] 390 | fn test_loop_sub() { 391 | let mut _test_vec1 = ThreeVec::new(10_000.0,10_000.0,10_000.0); 392 | for _i in 0..9999{ 393 | _test_vec1 -= ThreeVec::new(1.0,1.0,1.0); 394 | } 395 | 396 | assert_eq!( 397 | _test_vec1, 398 | ThreeVec::new(1.0,1.0,1.0) 399 | ); 400 | } 401 | 402 | #[test] 403 | fn test_mul() { 404 | let _test_vec1 = ThreeVec::new(2.0,2.0,2.0); 405 | let _test_vec2 = ThreeVec::new(2.0,2.0,2.0); 406 | 407 | assert_eq!( 408 | _test_vec1*_test_vec2, 409 | 12.0 410 | ); 411 | } 412 | 413 | #[test] 414 | fn test_mul_coef() { 415 | let _test_vec1 = ThreeVec::new(2.0,2.0,2.0); 416 | 417 | assert_eq!( 418 | _test_vec1*2.0, 419 | ThreeVec::new(4.0,4.0,4.0) 420 | ); 421 | assert_eq!( 422 | 2.0*_test_vec1, 423 | ThreeVec::new(4.0,4.0,4.0) 424 | ); 425 | } 426 | 427 | #[test] 428 | fn test_neg() { 429 | let _test_vec1 = ThreeVec::new(2.0,2.0,2.0); 430 | 431 | assert_eq!( 432 | -_test_vec1, 433 | ThreeVec::new(-2.0,-2.0,-2.0) 434 | ); 435 | } 436 | 437 | #[test] 438 | fn test_copy() { 439 | let xx = ThreeVec::new(1.0,1.0,1.0); 440 | let yy = xx; 441 | assert_eq!( 442 | xx+yy, 443 | ThreeVec::new(2.0,2.0,2.0) 444 | ); 445 | } 446 | 447 | #[test] 448 | fn test_parse() { 449 | let xx = ThreeVec::new(1.0,1.0,1.0); 450 | let pp = xx.to_json(); 451 | assert_eq!(ThreeVec::from_json(&pp).unwrap(),xx); 452 | } 453 | 454 | #[test] 455 | fn test_msg_parse() { 456 | let xx = ThreeVec::new(1.0,2.0,3.0); 457 | let pp = xx.to_msg().unwrap(); 458 | let (oo,_) = ThreeVec::from_msg(&pp).unwrap(); 459 | assert_eq!(oo,xx); 460 | } 461 | } 462 | -------------------------------------------------------------------------------- /src/four_mat/four_vec/mod.rs: -------------------------------------------------------------------------------- 1 | use std::f64; 2 | use self::f64::NAN; 3 | use std::ops::Add; 4 | use std::ops::AddAssign; 5 | use std::ops::Sub; 6 | use std::ops::SubAssign; 7 | use std::ops::Mul; 8 | use std::ops::Neg; 9 | use std::iter; 10 | use std::fmt; 11 | use std::error; 12 | 13 | use crate::three_mat; 14 | 15 | use three_mat::ThreeVec; 16 | 17 | use crate::utils; 18 | use utils::consts; 19 | use utils::{Serializable, Deserializable}; 20 | use utils::errors::CalcifyError; 21 | 22 | extern crate rmp; 23 | use rmp::encode::*; 24 | use rmp::decode::*; 25 | 26 | /// Variants of S space-time invariant 27 | #[derive(Debug, PartialEq)] 28 | pub enum Sinv { 29 | TimeLike, 30 | SpaceLike, 31 | LightLike, 32 | } 33 | 34 | /// Beta factor, |v| over the speed pf light in a vacuum, in SI. 35 | /// 36 | /// Returns a Result which contains an Ok(f64), or an error string. 37 | /// 38 | /// # Arguments 39 | /// 40 | /// * `v` - f64, |v| 41 | /// 42 | /// # Example 43 | /// 44 | /// ``` 45 | /// use calcify::beta; 46 | /// use calcify::errors::CalcifyError; 47 | /// let v = 149_896_229.0; 48 | /// assert_eq!(beta(v).unwrap(),0.5); 49 | /// assert!(beta(10e10).is_err(),CalcifyError::LightSpeedError); 50 | /// ``` 51 | pub fn beta<'a>(v: f64) -> Result { 52 | let b1 = v/consts::C_LIGHT; 53 | match b1 <= 1.0 { 54 | true => Ok(b1), 55 | false => Err(CalcifyError::LightSpeedError), 56 | } 57 | 58 | } 59 | 60 | /// Gamma, the lorentz factor, in SI. 61 | /// 62 | /// # Arguments 63 | /// 64 | /// * `beta` - f64, |v|/C, use calcify::beta(v) 65 | /// 66 | /// # Formula 67 | /// 68 | /// ```text 69 | /// // 1/sqrt(1 - beta^2) 70 | /// ``` 71 | pub fn gamma(beta: f64) -> f64 { 72 | 1.0/(1.0 - beta*beta).sqrt() 73 | } 74 | 75 | /// Four Vector 76 | #[derive(Debug, PartialEq, Copy, Clone)] 77 | pub struct FourVec { 78 | m0: f64, 79 | m1: f64, 80 | m2: f64, 81 | m3: f64, 82 | } 83 | 84 | impl FourVec { 85 | /// Returns a new FourVec from four f64s 86 | /// 87 | /// # Arguments 88 | /// 89 | /// * `m0` - f64 90 | /// * `m1` - f64 91 | /// * `m2` - f64 92 | /// * `m3` - f64 93 | /// 94 | /// # Example 95 | /// ``` 96 | /// use calcify::FourVec; 97 | /// let vec4 = FourVec::new(1.0,2.0,3.0,4.0); 98 | /// ``` 99 | pub fn new(m0: f64, m1: f64, m2: f64, m3: f64) -> FourVec { 100 | FourVec { 101 | m0, 102 | m1, 103 | m2, 104 | m3, 105 | } 106 | } 107 | 108 | /// Returns a new FourVec from a slice 109 | /// 110 | /// # Arguments 111 | /// 112 | /// * `slice` - &[prim@f64] 113 | /// 114 | /// # Example 115 | /// ``` 116 | /// use calcify::FourVec; 117 | /// let vec4: FourVec = FourVec::from(&[1.0,1.0,1.0,1.0]); 118 | /// ``` 119 | /// 120 | /// # Panics 121 | /// 122 | /// * `slice` length < 4 123 | pub fn from(slice: &[f64]) -> FourVec { 124 | 125 | FourVec { 126 | m0: slice[0], 127 | m1: slice[1], 128 | m2: slice[2], 129 | m3: slice[3], 130 | } 131 | } 132 | 133 | /// Returns a new FourVec from one f64 and a ThreeVec 134 | /// 135 | /// # Arguments 136 | /// 137 | /// * `t` - f64 138 | /// * `x` - calcify::ThreeVec 139 | /// 140 | /// # Example 141 | /// ``` 142 | /// use calcify::FourVec; 143 | /// use calcify::ThreeVec; 144 | /// 145 | /// let vec4 = FourVec::from_3vec(1.0,ThreeVec::new(2.0,3.0,4.0)); 146 | /// ``` 147 | pub fn from_3vec(t: f64, x: ThreeVec) -> FourVec { 148 | FourVec { 149 | m0: t, 150 | m1: *x.x0(), 151 | m2: *x.x1(), 152 | m3: *x.x2(), 153 | } 154 | } 155 | 156 | /// Returns a reference to the first element of the vector 157 | /// 158 | /// # Example 159 | /// ``` 160 | /// use calcify::FourVec; 161 | /// let vec4 = FourVec::new(1.0,2.0,3.0,4.0); 162 | /// let element_zero: f64 = *vec4.m0(); 163 | /// assert_eq!(element_zero,1.0); 164 | /// ``` 165 | pub fn m0(&self) -> &f64 { 166 | &self.m0 167 | } 168 | 169 | /// Returns a reference to the second element of the vector 170 | /// 171 | /// # Example 172 | /// ``` 173 | /// use calcify::FourVec; 174 | /// let vec4 = FourVec::new(1.0,2.0,3.0,4.0); 175 | /// let element_one: f64 = *vec4.m1(); 176 | /// assert_eq!(element_one,2.0); 177 | /// ``` 178 | pub fn m1(&self) -> &f64 { 179 | &self.m1 180 | } 181 | 182 | /// Returns a reference to the third element of the vector 183 | /// 184 | /// # Example 185 | /// ``` 186 | /// use calcify::FourVec; 187 | /// let vec4 = FourVec::new(1.0,2.0,3.0,4.0); 188 | /// let element_two: f64 = *vec4.m2(); 189 | /// assert_eq!(element_two,3.0); 190 | /// ``` 191 | pub fn m2(&self) -> &f64 { 192 | &self.m2 193 | } 194 | 195 | /// Returns a reference to the forth element of the vector 196 | /// 197 | /// # Example 198 | /// ``` 199 | /// use calcify::FourVec; 200 | /// let vec4 = FourVec::new(1.0,2.0,3.0,4.0); 201 | /// let element_three: f64 = *vec4.m3(); 202 | /// assert_eq!(element_three,4.0); 203 | /// ``` 204 | pub fn m3(&self) -> &f64 { 205 | &self.m3 206 | } 207 | 208 | /// Returns the covariant vector with metric [1,-1,-1,-1]. 209 | /// 210 | /// # Example 211 | /// ``` 212 | /// use calcify::FourVec; 213 | /// let vec4 = FourVec::new(1.0,2.0,3.0,4.0); 214 | /// let cov_vec4: FourVec = vec4.cov(); 215 | /// assert_eq!(cov_vec4,FourVec::new(1.0,-2.0,-3.0,-4.0)); 216 | /// 217 | /// assert_eq!(vec4.cov()*vec4, -28.0) 218 | /// ``` 219 | pub fn cov(self) -> FourVec { 220 | FourVec { 221 | m0: self.m0, 222 | m1: -self.m1, 223 | m2: -self.m2, 224 | m3: -self.m3, 225 | } 226 | } 227 | 228 | /// Returns the space-time invariant *classification* S^2 of a space-time vector. 229 | /// Returns a variant of the calcify::Sinv enum 230 | /// # Example 231 | /// ``` 232 | /// use calcify::FourVec; 233 | /// use calcify::Sinv; 234 | /// let vec4 = FourVec::new(10.0,2.0,2.0,2.0); 235 | /// let ss: Sinv = vec4.s2(); 236 | /// assert_eq!(ss,Sinv::TimeLike); 237 | /// ``` 238 | pub fn s2(&self) -> Sinv { 239 | let ss: f64 = self.cov()**self; 240 | if ss == 0.0 { 241 | Sinv::LightLike 242 | } else if ss > 0.0 { 243 | Sinv::TimeLike 244 | } else { 245 | Sinv::SpaceLike 246 | } 247 | } 248 | 249 | /// Returns the invariant of the FourVec. 250 | /// 251 | /// # Example 252 | /// ``` 253 | /// use calcify::FourVec; 254 | /// let vec4 = FourVec::new(1.0,0.0,0.0,0.0); 255 | /// assert_eq!(vec4.s(),1.0); 256 | /// ``` 257 | pub fn s(&self) -> f64 { 258 | (self.cov()**self).sqrt() 259 | } 260 | 261 | } 262 | 263 | impl fmt::Display for FourVec { 264 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 265 | write!(f, "[{:.*}, {:.*}, {:.*}, {:.*}]", 5, self.m0(), 5, self.m1(), 5, self.m2(), 5, self.m3()) 266 | } 267 | } 268 | 269 | impl Serializable for FourVec { 270 | fn to_json(&self) -> String { 271 | format!("{{\"m0\":{},\"m1\":{},\"m2\":{},\"m3\":{}}}", 272 | self.m0(), self.m1(), self.m2(), self.m3()) 273 | } 274 | fn to_msg(&self) -> Result,ValueWriteError> { 275 | let mut buf = Vec::with_capacity(5); 276 | write_array_len(&mut buf, 4)?; 277 | write_f64(&mut buf, *self.m0())?; 278 | write_f64(&mut buf, *self.m1())?; 279 | write_f64(&mut buf, *self.m2())?; 280 | write_f64(&mut buf, *self.m3())?; 281 | Ok(buf) 282 | } 283 | } 284 | 285 | impl Deserializable for FourVec { 286 | 287 | fn from_json(s: &str) -> Result> { 288 | let mut m0: f64 = NAN; 289 | let mut m1: f64 = NAN; 290 | let mut m2: f64 = NAN; 291 | let mut m3: f64 = NAN; 292 | for dim in s.trim_matches(|p| p == '{' || p == '}' ).split(',') { 293 | let n_v: Vec<&str> = dim.split(':').collect(); 294 | match n_v[0] { 295 | "\"m0\"" => m0 = n_v[1].parse::()?, 296 | "\"m1\"" => m1 = n_v[1].parse::()?, 297 | "\"m2\"" => m2 = n_v[1].parse::()?, 298 | "\"m3\"" => m3 = n_v[1].parse::()?, 299 | _ => return Err(Box::new(CalcifyError::ParseError)), 300 | } 301 | } 302 | Ok(FourVec{m0,m1,m2,m3}) 303 | } 304 | 305 | fn from_msg(mut bytes: &[u8]) -> Result<(Self,&[u8]), Box> { 306 | if let Ok(4) = read_array_len(&mut bytes){ 307 | let mut x: [f64;4] = [NAN;4]; 308 | for i in 0..4 { 309 | x[i] = read_f64(&mut bytes)?; 310 | } 311 | Ok((FourVec::from(&x),bytes)) 312 | } else { 313 | Err(Box::new(CalcifyError::ParseError)) 314 | } 315 | } 316 | } 317 | 318 | 319 | 320 | impl Add for FourVec { 321 | type Output = FourVec; 322 | 323 | fn add(self, other: FourVec) -> FourVec { 324 | FourVec { 325 | m0: self.m0 + *other.m0(), 326 | m1: self.m1 + *other.m1(), 327 | m2: self.m2 + *other.m2(), 328 | m3: self.m3 + *other.m3(), 329 | } 330 | } 331 | } 332 | 333 | impl iter::Sum for FourVec { 334 | fn sum(iter: I) -> FourVec 335 | where I: Iterator { 336 | iter.fold(FourVec { m0: 0.0, m1: 0.0, m2: 0.0, m3: 0.0 }, |a, b| a + b) 337 | } 338 | } 339 | 340 | impl AddAssign for FourVec { 341 | fn add_assign(&mut self, other: FourVec) { 342 | self.m0 += *other.m0(); 343 | self.m1 += *other.m1(); 344 | self.m2 += *other.m2(); 345 | self.m3 += *other.m3(); 346 | } 347 | } 348 | 349 | impl Sub for FourVec { 350 | type Output = FourVec; 351 | 352 | fn sub(self, other: FourVec) -> FourVec { 353 | FourVec { 354 | m0: self.m0 - *other.m0(), 355 | m1: self.m1 - *other.m1(), 356 | m2: self.m2 - *other.m2(), 357 | m3: self.m3 - *other.m3(), 358 | } 359 | } 360 | } 361 | 362 | impl SubAssign for FourVec { 363 | fn sub_assign(&mut self, other: FourVec) { 364 | self.m0 -= *other.m0(); 365 | self.m1 -= *other.m1(); 366 | self.m2 -= *other.m2(); 367 | self.m3 -= *other.m3(); 368 | } 369 | } 370 | 371 | impl Mul for FourVec { 372 | type Output = FourVec; 373 | 374 | fn mul(self, coef: f64) -> FourVec { 375 | FourVec { 376 | m0: self.m0 * coef, 377 | m1: self.m1 * coef, 378 | m2: self.m2 * coef, 379 | m3: self.m3 * coef, 380 | } 381 | } 382 | } 383 | 384 | impl Mul for f64 { 385 | type Output = FourVec; 386 | 387 | fn mul(self, vec: FourVec) -> FourVec { 388 | FourVec { 389 | m0: *vec.m0() * self, 390 | m1: *vec.m1() * self, 391 | m2: *vec.m2() * self, 392 | m3: *vec.m3() * self, 393 | } 394 | } 395 | } 396 | 397 | impl Mul for FourVec { 398 | type Output = f64; 399 | /// _Standard_ scalar product, 400 | /// 401 | /// # Example 402 | /// 403 | /// ``` 404 | /// use calcify::FourVec; 405 | /// let vec4 = FourVec::new(2.0,2.0,2.0,2.0); 406 | /// 407 | /// assert_eq!( 408 | /// vec4*vec4, 409 | /// 16.0 410 | /// ); 411 | /// ``` 412 | fn mul(self, other: FourVec) -> f64 { 413 | self.m0 * *other.m0() + self.m1 * *other.m1() + self.m2 * *other.m2() + self.m3 * *other.m3() 414 | } 415 | } 416 | 417 | impl Neg for FourVec { 418 | type Output = FourVec; 419 | 420 | fn neg(self) -> FourVec { 421 | FourVec { 422 | m0: -self.m0, 423 | m1: -self.m1, 424 | m2: -self.m2, 425 | m3: -self.m3, 426 | } 427 | } 428 | } 429 | 430 | 431 | #[cfg(test)] 432 | mod tests { 433 | use super::*; 434 | 435 | #[test] 436 | fn test_beta() { 437 | let v = 149_896_229.0; 438 | assert_eq!(beta(v).unwrap(),0.5); 439 | assert!(beta(10e10).is_err(),"Beta must be ltgt 1.0"); 440 | } 441 | 442 | #[test] 443 | fn test_sum() { 444 | let vec: Vec = vec![FourVec::new(5.0,2.0,2.0,2.0),FourVec::new(5.0,2.0,2.0,2.0)]; 445 | let res: FourVec = vec.into_iter().sum(); 446 | assert_eq!(res,FourVec::new(10.0,4.0,4.0,4.0)); 447 | } 448 | 449 | #[test] 450 | fn test_invariant() { 451 | let vec4 = FourVec::new(5.0,2.0,2.0,2.0); 452 | assert_eq!(vec4.cov()*vec4,13.0); 453 | } 454 | 455 | #[test] 456 | fn test_json() { 457 | let vec4 = FourVec::new(5.0,2.0,2.0,2.0); 458 | assert_eq!(vec4.to_json(),"{\"m0\":5,\"m1\":2,\"m2\":2,\"m3\":2}"); 459 | } 460 | 461 | #[test] 462 | fn test_parse() { 463 | let xx = FourVec::new(5.0,2.0,2.0,2.0); 464 | let pp = xx.to_json(); 465 | assert_eq!(FourVec::from_json(&pp).unwrap(),xx); 466 | } 467 | 468 | #[test] 469 | fn test_msg_parse() { 470 | let xx = FourVec::new(5.0,2.0,2.0,2.0); 471 | let pp = xx.to_msg().unwrap(); 472 | let (oo,_) = FourVec::from_msg(&pp).unwrap(); 473 | assert_eq!(oo,xx); 474 | } 475 | } 476 | -------------------------------------------------------------------------------- /src/tree/mod.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::error; 3 | 4 | mod branch; 5 | 6 | pub use branch::Collection; 7 | pub use branch::Bin; 8 | pub use branch::Point; 9 | pub use branch::PointBin; 10 | pub use branch::Branch; 11 | 12 | mod feedtree; 13 | 14 | pub use feedtree::FeedTree; 15 | 16 | use crate::utils; 17 | use utils::{Serializable, Deserializable}; 18 | use utils::errors::CalcifyError; 19 | use utils::io::{ToFile,FromFile}; 20 | 21 | extern crate rmp; 22 | use rmp::encode::*; 23 | use rmp::decode::*; 24 | 25 | /// Tree of Collections for saving to a file. 26 | pub struct Tree { 27 | metadata: HashMap, 28 | branches: HashMap, 29 | } 30 | 31 | impl Tree { 32 | /// Returns new Tree 33 | /// 34 | /// Name is the only required metadata. 35 | /// # Arguments 36 | /// 37 | /// * `name` - string 38 | /// 39 | /// # Example 40 | /// ``` 41 | /// use calcify::Tree; 42 | /// use calcify::Collection; 43 | /// use calcify::Bin; 44 | /// use calcify::ThreeVec; 45 | /// 46 | /// let f_col: Collection = Collection::from(vec![0.0,0.0]); 47 | /// let mut v3_col: Collection = Collection::empty(); 48 | /// for _i in 0..9999 {v3_col.push(ThreeVec::random(1.0));} 49 | /// let col_hist: Collection = v3_col.map(ThreeVec::r).hist(50); 50 | /// let mut ttree = Tree::new("Test_Tree"); 51 | /// ttree.add_field("Desc", "This is a Tree for testing."); 52 | /// ttree.add_branch("fcol", f_col, "f64"); 53 | /// ttree.add_branch("col_3v", v3_col, "ThreeVec"); 54 | /// ttree.add_branch("hist_3v", col_hist, "Bin"); 55 | /// ``` 56 | pub fn new(name: &str) -> Tree { 57 | let mut md = HashMap::new(); 58 | md.insert(String::from("Name"),String::from(name)); 59 | let br = HashMap::new(); 60 | Tree { 61 | metadata: md, 62 | branches: br, 63 | } 64 | } 65 | 66 | pub fn add_field(&mut self, key: &str, f: &str) -> Result<(),CalcifyError> { 67 | if let Some(_) = self.metadata.insert(String::from(key),String::from(f)) { 68 | return Err(CalcifyError::KeyError); 69 | } 70 | Ok(()) 71 | } 72 | 73 | /// Inserts new branch into Tree. 74 | /// 75 | /// # Arguments 76 | /// 77 | /// * `key` - Hash key, String 78 | /// * `b` - Branch, Collection 79 | /// * `t` - Collection subtype, String, one of "f64", "String", "ThreeVec", "ThreeMat", "FourVec", "FourMat", "Bin", "Point", "Object" 80 | /// 81 | /// # Panics 82 | /// 83 | /// * `t` is invalid 84 | pub fn add_branch(&mut self, key: &str, b: Collection, t: &str) -> Result<(),CalcifyError> { 85 | let types = ["f64","String","ThreeVec","ThreeMat","FourVec","FourMat","Bin","Point","PointBin","Object"]; 86 | if types.contains(&t) { 87 | let br = Branch::new(String::from(t),Box::new(b)); 88 | if let Some(_) = self.branches.insert(String::from(key),br) { 89 | return Err(CalcifyError::KeyError); 90 | } 91 | Ok(()) 92 | } else { 93 | panic!("Subtype must be one of \"f64\", \"String\", \"ThreeVec\", \"ThreeMat\", \"FourVec\", \"FourMat\", \"Bin\", \"Point\", \"PointBin\", \"Object\" not {}",t); 94 | } 95 | } 96 | 97 | /// Returns Branch from a Trees 98 | /// 99 | /// # Arguments 100 | /// 101 | /// `key` - String 102 | /// 103 | /// # Example 104 | /// 105 | /// ``` 106 | /// use calcify::Tree; 107 | /// use calcify::Collection; 108 | /// use calcify::Bin; 109 | /// 110 | /// let f_col: Collection = Collection::from(vec![0.0,0.0]); 111 | /// let b_col: Collection = Collection::from(vec![Bin::new(0.0,1.0,10),Bin::new(1.0,2.0,10),Bin::new(2.0,3.0,10)]); 112 | /// let mut ttree = Tree::new("Test_Tree"); 113 | /// ttree.add_branch("fcol", f_col, "f64").expect("KeyError"); 114 | /// ttree.add_branch("bCol", b_col, "Bin").expect("KeyError"); 115 | /// 116 | /// let ex_f_col: Collection = ttree.get_branch("fcol").unwrap().extract().unwrap(); 117 | /// let mut ex_b_col: Collection = ttree.get_branch("bCol").unwrap().extract().unwrap(); 118 | /// 119 | /// assert_eq!(Collection::from(vec![0.0,0.0]),ex_f_col); 120 | /// assert_eq!(Collection::from(vec![Bin::new(0.0,1.0,10),Bin::new(1.0,2.0,10),Bin::new(2.0,3.0,10)]),ex_b_col); 121 | /// ``` 122 | pub fn get_branch(&mut self, key: &str) -> Option<&mut Branch> { 123 | self.branches.get_mut(&String::from(key)) 124 | } 125 | 126 | /// Returns Collection from a Trees 127 | /// 128 | /// # Arguments 129 | /// 130 | /// `key` - String 131 | /// 132 | /// # Example 133 | /// 134 | /// ``` 135 | /// use calcify::Tree; 136 | /// use calcify::Collection; 137 | /// use calcify::Bin; 138 | /// 139 | /// let f_col: Collection = Collection::from(vec![0.0,0.0]); 140 | /// let b_col: Collection = Collection::from(vec![Bin::new(0.0,1.0,10),Bin::new(1.0,2.0,10),Bin::new(2.0,3.0,10)]); 141 | /// let mut ttree = Tree::new("Test_Tree"); 142 | /// ttree.add_branch("fcol", f_col, "f64").expect("KeyError"); 143 | /// ttree.add_branch("bCol", b_col, "Bin").expect("KeyError"); 144 | /// 145 | /// let ex_f_col: Collection = ttree.read_branch("fcol").unwrap(); 146 | /// let mut ex_b_col: Collection = ttree.read_branch("bCol").unwrap(); 147 | /// // read from buffer 148 | /// ex_b_col = ttree.read_branch("bCol").unwrap(); 149 | /// 150 | /// assert_eq!(Collection::from(vec![0.0,0.0]),ex_f_col); 151 | /// assert_eq!(Collection::from(vec![Bin::new(0.0,1.0,10),Bin::new(1.0,2.0,10),Bin::new(2.0,3.0,10)]),ex_b_col); 152 | /// ``` 153 | pub fn read_branch(&mut self, key: &str) -> Result, CalcifyError> { 154 | if let Some(branch) = self.branches.get_mut(&String::from(key)) { 155 | if let Ok(collect) = branch.extract() { 156 | return Ok(collect); 157 | } else { 158 | return Err(CalcifyError::ParseError); 159 | } 160 | } 161 | Err(CalcifyError::KeyError) 162 | } 163 | } 164 | 165 | impl Serializable for Tree { 166 | fn to_json(&self) -> String { 167 | let mut out = String::from("{"); 168 | for (key, val) in &self.metadata { 169 | out.push_str(format!("\"{}\":\"{}\",",key,val).as_str()); 170 | } 171 | out.push_str("\"branches\":{"); 172 | for (key, val) in &self.branches { 173 | out.push_str(format!("\"{}\":{},",key,val.to_json()).as_str()); 174 | } 175 | out.pop(); 176 | out.push_str("}}"); 177 | out 178 | } 179 | 180 | fn to_msg(&self) -> Result, ValueWriteError> { 181 | let mut buf = Vec::new(); 182 | write_map_len(&mut buf, (self.metadata.len()+1) as u32)?; 183 | for (key, val) in &self.metadata { 184 | write_str(&mut buf, key)?; 185 | write_str(&mut buf, val)?; 186 | } 187 | write_str(&mut buf, "branches")?; 188 | write_map_len(&mut buf, (self.branches.len()) as u32)?; 189 | for (key, val) in &self.branches { 190 | write_str(&mut buf, key)?; 191 | buf.append(&mut val.to_msg()?); 192 | } 193 | Ok(buf) 194 | } 195 | } 196 | 197 | impl Deserializable for Tree { 198 | fn from_json(s: &str) -> Result> { 199 | let mut metadata: HashMap = HashMap::new(); 200 | let mut branches: HashMap = HashMap::new(); 201 | for (i,mut dim) in s.split(",\"branches\":").enumerate() { 202 | match i { 203 | 0 => { 204 | for pair in dim.trim_matches(|p| p == '{' || p == '"' ).split("\",\"") { 205 | let ar: Vec<&str> = pair.split("\":\"").collect(); 206 | metadata.insert(String::from(ar[0]),String::from(ar[1])); 207 | } 208 | }, 209 | 1 => { 210 | dim = dim.trim_matches(|p| p == '{' || p == '}' || p == '"' ); 211 | for pair in dim.split("},\"") { 212 | let ar: Vec<&str> = pair.split("\":").collect(); 213 | if let Ok(branch) = Branch::from_json(&ar[1..].join("\":")){ 214 | branches.insert(String::from(ar[0]),branch); 215 | } else { 216 | return Err(Box::new(CalcifyError::ParseError)); 217 | } 218 | } 219 | }, 220 | _ => return Err(Box::new(CalcifyError::ParseError)), 221 | } 222 | } 223 | Ok(Tree{metadata, branches}) 224 | } 225 | 226 | fn from_msg(mut bytes: &[u8]) -> Result<(Self,&[u8]), Box> { 227 | let mut metadata: HashMap = HashMap::new(); 228 | let mut branches: HashMap = HashMap::new(); 229 | if let Ok(len) = read_map_len(&mut bytes) { 230 | for _ in 0..len { 231 | let mut unparsed: &[u8] = &bytes[..]; 232 | if let Ok((key,v_rest)) = read_str_from_slice(unparsed) { 233 | match key { 234 | "branches" => { 235 | bytes = v_rest; 236 | break; 237 | }, 238 | _ => { 239 | if let Ok((value,rest)) = read_str_from_slice(v_rest) { 240 | unparsed = rest; 241 | metadata.insert(String::from(key),String::from(value)); 242 | } 243 | }, 244 | } 245 | 246 | } 247 | bytes = unparsed; 248 | } 249 | if let Ok(flen) = read_map_len(&mut bytes) { 250 | for _ in 0..flen { 251 | let unparsed: &[u8] = &bytes[..]; 252 | if let Ok((key,v_rest)) = read_str_from_slice(unparsed) { 253 | if let Ok((value,rest)) = Branch::from_msg(v_rest) { 254 | bytes = rest; 255 | branches.insert(String::from(key),value); 256 | } 257 | } 258 | } 259 | } 260 | } 261 | Ok((Tree{metadata, branches},bytes)) 262 | } 263 | } 264 | 265 | impl ToFile for Tree{} 266 | impl FromFile for Tree{} 267 | 268 | #[cfg(test)] 269 | mod tests { 270 | use super::*; 271 | use crate::ThreeVec; 272 | 273 | #[test] 274 | fn test_tree_write() -> Result<(),Box>{ 275 | let fcol: Collection = Collection::from(vec![0.0,0.0]); 276 | let mut col_3v: Collection = Collection::empty(); 277 | for _i in 0..9 {col_3v.push(ThreeVec::new(1.0,2.0,3.0));} 278 | let mut ttree = Tree::new("Test_Tree"); 279 | ttree.add_field("Desc", "This is a Tree for testing.")?; 280 | ttree.add_branch("fcol", fcol, "f64")?; 281 | ttree.add_branch("col_3v", col_3v, "ThreeVec")?; 282 | ttree.write_msg("./scratch/test_tree.msg")?; 283 | Ok(()) 284 | } 285 | 286 | #[test] 287 | fn test_tree_read() -> Result<(),Box>{ 288 | let fcol: Collection = Collection::from(vec![0.0,0.0]); 289 | let mut col_3v: Collection = Collection::empty(); 290 | for _i in 0..9 {col_3v.push(ThreeVec::new(1.0,2.0,3.0));} 291 | 292 | let mut ftree = Tree::read_msg("./scratch/test_tree.msg")?; 293 | let ftree_branch1: Collection = ftree.read_branch("fcol")?; 294 | assert_eq!(ftree_branch1,fcol); 295 | let ftree_branch2: Collection = ftree.read_branch("col_3v")?; 296 | assert_eq!(ftree_branch2,col_3v); 297 | Ok(()) 298 | // Err(Box::new(CalcifyError::ParseError)) 299 | } 300 | 301 | #[test] 302 | fn test_tree_json() -> Result<(),Box>{ 303 | let fcol: Collection = Collection::from(vec![0.0,0.0]); 304 | let mut col_3v: Collection = Collection::empty(); 305 | for _i in 0..9 {col_3v.push(ThreeVec::random(1.0));} 306 | let mut ttree = Tree::new("Test_Tree"); 307 | ttree.add_field("Desc", "This is a Tree for testing.")?; 308 | ttree.add_branch("col_3v", col_3v.clone(), "ThreeVec")?; 309 | ttree.add_branch("fcol", fcol, "f64")?; 310 | ttree.add_branch("col_3v3", col_3v, "ThreeVec")?; 311 | let pp = ttree.to_json(); 312 | let mut oo = Tree::from_json(&pp)?; 313 | assert_eq!(oo.read_branch("fcol").unwrap(),Collection::from(vec![0.0,0.0])); 314 | Ok(()) 315 | } 316 | 317 | #[test] 318 | fn test_tree_msg() -> Result<(),Box>{ 319 | let fcol: Collection = Collection::from(vec![0.0,0.0]); 320 | let mut col_3v: Collection = Collection::empty(); 321 | for _i in 0..9 {col_3v.push(ThreeVec::random(1.0));} 322 | let mut ttree = Tree::new("Test_Tree"); 323 | ttree.add_field("Desc", "This is a Tree for testing.")?; 324 | ttree.add_branch("fcol", fcol, "f64")?; 325 | ttree.add_branch("col_3v", col_3v, "ThreeVec")?; 326 | let pp = ttree.to_msg().unwrap(); 327 | let (mut oo,_) = Tree::from_msg(&pp).unwrap(); 328 | assert_eq!(oo.read_branch("fcol").unwrap(),Collection::from(vec![0.0,0.0])); 329 | Ok(()) 330 | } 331 | } 332 | -------------------------------------------------------------------------------- /src/tree/branch/collection/mod.rs: -------------------------------------------------------------------------------- 1 | use std::iter::FromIterator; 2 | use std::iter::Extend; 3 | use std::error; 4 | use std::convert::From; 5 | 6 | mod point; 7 | mod bin; 8 | mod point_bin; 9 | 10 | pub use point::Point; 11 | pub use bin::Bin; 12 | pub use point_bin::PointBin; 13 | 14 | use crate::utils; 15 | 16 | use utils::{Serializable, Deserializable}; 17 | use utils::errors::CalcifyError; 18 | 19 | extern crate rmp; 20 | use rmp::encode::*; 21 | use rmp::decode::*; 22 | 23 | /// A wrapper around the std::vec::vec 24 | /// 25 | /// # Note 26 | /// * Collection only implements some basic functionality of real Vecs. 27 | /// The goal is not to supersede, but to add to. 28 | /// So you should use Vec in most cases, and wrap it in a Collection if you need one of those functions. 29 | #[derive(Debug, PartialEq, Clone)] 30 | pub struct Collection { 31 | pub vec: Vec, 32 | } 33 | 34 | impl Collection { 35 | /// Returns new Collection from a Vec 36 | /// 37 | /// # Example 38 | /// ``` 39 | /// use calcify::FourVec; 40 | /// use calcify::Collection; 41 | /// 42 | /// let col4V: Collection = Collection::empty(); 43 | /// ``` 44 | pub fn empty() -> Collection { 45 | Collection { 46 | vec: Vec::::new(), 47 | } 48 | } 49 | 50 | /// Returns a mutable reference to the T: Serializable at index i 51 | /// 52 | /// # Arguments 53 | /// 54 | /// * `i` - usize 55 | /// 56 | /// # Example 57 | /// ``` 58 | /// use calcify::FourVec; 59 | /// use calcify::Collection; 60 | /// 61 | /// let mut col4V = Collection::from( 62 | /// vec![FourVec::new(10.0,1.0,1.0,1.0)] 63 | /// ); 64 | /// assert_eq!(*col4V.at(0),FourVec::new(10.0,1.0,1.0,1.0)); 65 | /// *col4V.at(0) += FourVec::new(10.0,1.0,1.0,1.0); 66 | /// assert_eq!(*col4V.at(0),FourVec::new(20.0,2.0,2.0,2.0)); 67 | /// ``` 68 | pub fn at(&mut self, i: usize) -> &mut T { 69 | &mut self.vec[i] 70 | } 71 | 72 | /// Push new T: Serializable into Collection 73 | /// 74 | /// # Arguments 75 | /// 76 | /// * `nn` - T: Serializable 77 | /// 78 | /// # Example 79 | /// ``` 80 | /// use calcify::FourVec; 81 | /// use calcify::Collection; 82 | /// 83 | /// let mut col4V = Collection::empty(); 84 | /// col4V.push(FourVec::new(10.0,1.0,1.0,1.0)); 85 | /// assert_eq!(*col4V.at(0),FourVec::new(10.0,1.0,1.0,1.0)); 86 | /// ``` 87 | pub fn push(&mut self, nn: T) { 88 | self.vec.push(nn); 89 | } 90 | 91 | /// Maps a function and returns a new Collection 92 | /// 93 | /// Implements Vec::iter::map and Vec::iter::collect. 94 | /// 95 | /// # Arguments 96 | /// 97 | /// * `close` - F: FnMut(&T: Serializable) -> Z: Serializable 98 | /// 99 | /// # Example 100 | /// ``` 101 | /// use calcify::FourVec; 102 | /// use calcify::Collection; 103 | /// 104 | /// let mut col4V: Collection = Collection::empty(); 105 | /// for _i in 0..9999 { 106 | /// col4V.push(FourVec::new(1.0,0.0,0.0,0.0)); 107 | /// } 108 | /// let mut mass_col4V: Collection = Collection::empty(); 109 | /// for _i in 0..9999 { 110 | /// mass_col4V.push(1.0); 111 | /// } 112 | /// assert_eq!(col4V.map(FourVec::s), mass_col4V); 113 | /// ``` 114 | pub fn map(&self, close: F) -> Collection where 115 | F: FnMut(&T) -> Z { 116 | let vbuff: Vec = self.vec.iter().map(close).collect(); 117 | Collection::from(vbuff) 118 | } 119 | 120 | /// Cuts/Filters a function and returns a new Collection 121 | /// 122 | /// Implements Vec::iter::filter and Vec::iter::collect. 123 | /// 124 | /// # Note 125 | /// 126 | /// * This may behave differently than expected. Cut keeps the elements that *pass* the test, not fail it. 127 | /// 128 | /// # Arguments 129 | /// 130 | /// * `close` - F: FnMut(&&T: Serializable) -> bool 131 | /// 132 | /// # Example 133 | /// ``` 134 | /// use calcify::FourVec; 135 | /// use calcify::Collection; 136 | /// 137 | /// let mut col4V: Collection = Collection::empty(); 138 | /// for _i in 0..9999 { 139 | /// col4V.push(FourVec::new(1.0,0.0,0.0,0.0)); 140 | /// } 141 | /// col4V.cut(|&&x| x.s() < 10.0); 142 | /// ``` 143 | pub fn cut(&self, close: F) -> Collection where 144 | F: FnMut(&&T) -> bool, T: Clone { 145 | let new_vec: Vec = self.vec.iter().filter(close).cloned().collect(); 146 | Collection::from(new_vec) 147 | } 148 | 149 | pub fn len(&self) -> usize{ 150 | self.vec.len() 151 | } 152 | 153 | } 154 | 155 | impl From<&[T]> for Collection { 156 | /// Returns new Collection from a &[T: Serializable] 157 | /// 158 | /// # Arguments 159 | /// 160 | /// * `vec` - &[T: Serializable] 161 | /// 162 | /// # Example 163 | /// ``` 164 | /// use calcify::FourVec; 165 | /// use calcify::Collection; 166 | /// 167 | /// let a4v = [FourVec::new(10.0,1.0,1.0,1.0)]; 168 | /// let col4V = Collection::from( 169 | /// &a4v[..] 170 | /// ); 171 | /// ``` 172 | fn from(vec: &[T]) -> Self { 173 | let ivec: Vec = vec.to_vec(); 174 | Collection { 175 | vec: ivec, 176 | } 177 | } 178 | } 179 | 180 | impl From> for Collection { 181 | /// Returns new Collection from a &[T: Serializable] 182 | /// 183 | /// # Arguments 184 | /// 185 | /// * `vec` - Vec 186 | /// 187 | /// # Example 188 | /// ``` 189 | /// use calcify::FourVec; 190 | /// use calcify::Collection; 191 | /// 192 | /// let col4V = Collection::from( 193 | /// vec![FourVec::new(10.0,1.0,1.0,1.0)] 194 | /// ); 195 | /// ``` 196 | fn from(vec: Vec) -> Self { 197 | Collection { 198 | vec, 199 | } 200 | } 201 | } 202 | 203 | impl Serializable for Collection { 204 | fn to_json(&self) -> String { 205 | let str_vec: Vec = self.vec.iter().map(|x| x.to_json()).collect(); 206 | format!("[{}]",str_vec.join(",")) 207 | } 208 | 209 | fn to_msg(&self) -> Result, ValueWriteError> { 210 | let mut buf = Vec::new(); 211 | write_array_len(&mut buf, (self.vec.len()) as u32)?; 212 | for x in self.vec.iter() { 213 | buf.append(&mut x.to_msg()?); 214 | } 215 | Ok(buf) 216 | } 217 | } 218 | 219 | impl Deserializable for Collection { 220 | fn from_json(s: &str) -> Result> { 221 | let mut out: Self = Collection::empty(); 222 | let s_iter: String; 223 | if s.starts_with("[{") { 224 | s_iter = s.replace("},{","}|{"); 225 | } else { 226 | s_iter = s.replace(",","|"); 227 | } 228 | for ff in s_iter.trim_matches(|p| p == '[' || p == ']' ).split('|'){ 229 | if let Ok(f) = T::from_json(ff) { 230 | out.push(f); 231 | } 232 | else { 233 | return Err(Box::new(CalcifyError::ParseError)); 234 | } 235 | } 236 | Ok(out) 237 | } 238 | 239 | fn from_msg(mut bytes: &[u8]) -> Result<(Self,&[u8]), Box> { 240 | let mut out: Self = Collection::empty(); 241 | if let Ok(len) = read_array_len(&mut bytes){ 242 | for _ in 0..len { 243 | if let Ok((ot,rest)) = T::from_msg(&mut bytes) { 244 | out.push(ot); 245 | bytes = rest; 246 | } else { 247 | return Err(Box::new(CalcifyError::ParseError)); 248 | } 249 | } 250 | return Ok((out,bytes)); 251 | } 252 | Err(Box::new(CalcifyError::ParseError)) 253 | } 254 | } 255 | 256 | 257 | /// Collects an iterator into a Collection, i.e. provides collect(). 258 | /// 259 | /// # Example 260 | /// ``` 261 | /// use calcify::FourVec; 262 | /// use calcify::Collection; 263 | /// 264 | /// let mut col4V: Collection = Collection::empty(); 265 | /// let mut colf6: Collection = Collection::empty(); 266 | /// for _i in 0..9999 { 267 | /// col4V.push(FourVec::new(1.0,0.0,0.0,0.0)); 268 | /// colf6.push(1.0); 269 | /// } 270 | /// 271 | /// let tCol: Collection = col4V.into_iter().map(|x| x.s()).collect(); 272 | /// 273 | /// assert_eq!(colf6, tCol); 274 | /// ``` 275 | impl FromIterator for Collection { 276 | fn from_iter>(iter: I) -> Self { 277 | let mut c = Collection::empty(); 278 | for i in iter { 279 | c.push(i); 280 | } 281 | c 282 | } 283 | } 284 | 285 | /// Returns the internal Vec iterator 286 | /// 287 | /// # Example 288 | /// ``` 289 | /// use calcify::FourVec; 290 | /// use calcify::Collection; 291 | /// 292 | /// let mut col4V: Collection = Collection::empty(); 293 | /// for _i in 0..9999 { 294 | /// col4V.push(FourVec::new(1.0,0.0,0.0,0.0)); 295 | /// } 296 | /// 297 | /// assert_eq!(FourVec::new(9999.0,0.0,0.0,0.0), 298 | /// col4V.into_iter().fold(FourVec::new(0.0,0.0,0.0,0.0), |acc, x| acc + x)); 299 | /// ``` 300 | impl IntoIterator for Collection { 301 | type Item = T; 302 | type IntoIter = ::std::vec::IntoIter; 303 | 304 | fn into_iter(self) -> Self::IntoIter { 305 | self.vec.into_iter() 306 | } 307 | } 308 | 309 | /// Extends a collection by the elements in the provided Iter 310 | /// 311 | /// # Example 312 | /// ``` 313 | /// use calcify::FourVec; 314 | /// use calcify::Collection; 315 | /// 316 | /// let mut col4V_1: Collection = Collection::empty(); 317 | /// let mut col4V_2: Collection = Collection::empty(); 318 | /// for _i in 0..5000 { 319 | /// col4V_1.push(FourVec::new(1.0,0.0,0.0,0.0)); 320 | /// col4V_2.push(FourVec::new(1.0,0.0,0.0,0.0)); 321 | /// } 322 | /// 323 | /// col4V_1.extend(col4V_2.into_iter()); 324 | /// assert_eq!(col4V_1.len(),10_000); 325 | /// ``` 326 | impl Extend for Collection { 327 | 328 | fn extend>(& mut self, iter: U) { 329 | self.vec.extend(iter); 330 | } 331 | } 332 | 333 | impl Collection { 334 | /// Return Collection plot 335 | /// 336 | /// # Arguments 337 | /// 338 | /// * `ind` - Independent variable: &[prim@f64] 339 | /// * `dep` - Dependent variable: &[prim@f64] 340 | /// 341 | /// # Example 342 | /// ``` 343 | /// use calcify::Collection; 344 | /// use calcify::Point; 345 | /// 346 | /// let test_plot: Collection = Collection::plot(&vec![0.0,1.0,2.0],&vec![3.0,4.0,5.0]); 347 | /// ``` 348 | pub fn plot(ind: &[f64], dep: &[f64]) -> Collection { 349 | let mut out: Collection = Collection::empty(); 350 | for (x , y) in ind.iter().zip(dep.iter()) { 351 | out.push(Point::new(*x,*y)); 352 | } 353 | out 354 | } 355 | 356 | /// Return Collection 2D histogram 357 | /// 358 | /// # Arguments 359 | /// 360 | /// * `num_bins_x` - Number of bins along the x axis: u64 (>= 2) 361 | /// * `num_bins_y` - Number of bins along the y axis: u64 (>= 2) 362 | /// 363 | /// # Panics 364 | /// 365 | /// * If either num_bins is less than 2 366 | /// 367 | pub fn hist(&self, num_bins_x: u64, num_bins_y: u64) -> Collection { 368 | if num_bins_x < 2 || num_bins_y < 2 {panic!("num_bins must be 2 or greater.");} 369 | let mut min_x = self.vec[0].x; 370 | let mut max_x = self.vec[0].x; 371 | let mut min_y = self.vec[0].y; 372 | let mut max_y = self.vec[0].y; 373 | for b in self.vec.iter(){ 374 | if b.x > max_x {max_x = b.x;} 375 | if b.x < min_x {min_x = b.x;} 376 | if b.y > max_y {max_y = b.y;} 377 | if b.y < min_y {min_y = b.y;} 378 | } 379 | let width_x = (max_x + 0.01 - min_x)/(num_bins_x as f64); 380 | let width_y = (max_y + 0.01 - min_y)/(num_bins_y as f64); 381 | let mut outs: Vec> = Vec::new(); 382 | for i in 0..num_bins_x { 383 | outs.push(Vec::new()); 384 | let edg0x = min_x + width_x * (i as f64); 385 | let edg1x = min_x + width_x * ((i+1) as f64); 386 | for j in 0..num_bins_y { 387 | let edg0y = min_y + width_y * (j as f64); 388 | let edg1y = min_y + width_y * ((j+1) as f64); 389 | outs[i as usize].push(PointBin::new(edg0x,edg1x,edg0y,edg1y,0)); 390 | } 391 | } 392 | for p in self.vec.iter() { 393 | let x_bin: usize = ((p.x - min_x)/width_x) as usize; 394 | let y_bin: usize = ((p.y - min_y)/width_y) as usize; 395 | outs[x_bin][y_bin] += 1; 396 | } 397 | let o_vec: Vec = outs.iter().flatten().cloned().collect(); 398 | let out: Collection = Collection::from(o_vec); 399 | return out; 400 | } 401 | } 402 | 403 | impl Collection { 404 | /// Return Collection histogram 405 | /// 406 | /// # Arguments 407 | /// 408 | /// * `num_bins` - Number of bins: u64 (>= 2) 409 | /// 410 | /// # Panics 411 | /// 412 | /// * If num_bins is less than 2 413 | /// 414 | /// # Example 415 | /// ``` 416 | /// use calcify::Collection; 417 | /// use calcify::Bin; 418 | /// use calcify::ThreeVec; 419 | /// 420 | /// let mut col_3v = Collection::empty(); 421 | /// for _i in 0..99999 { 422 | /// col_3v.push(ThreeVec::random(10.0)); 423 | /// } 424 | /// let len_col: Collection = col_3v.map(ThreeVec::r); 425 | /// let histogram: Collection = len_col.hist(50); 426 | /// ``` 427 | pub fn hist(&self, num_bins: u64) -> Collection { 428 | let mut st_vec = self.vec.clone(); 429 | st_vec.sort_by(|a, b| a.partial_cmp(b).unwrap()); 430 | if num_bins < 2 {panic!("num_bins must be 2 or greater.");} 431 | let width = (st_vec[st_vec.len()-1] + 0.01 - st_vec[0])/(num_bins as f64); 432 | let mut out: Collection = Collection::empty(); 433 | for i in 0..(num_bins) { 434 | let edg0 = st_vec[0] + width * (i as f64); 435 | let edg1 = st_vec[0] + width * ((i+1) as f64); 436 | out.push(Bin::new(edg0,edg1,0)); 437 | } 438 | let mut c_bin = 0; 439 | for x in st_vec.iter() { 440 | if x >= &out.at(c_bin).in_edge && x < &out.at(c_bin).ex_edge { 441 | *out.at(c_bin) += 1; 442 | } 443 | else { 444 | c_bin += 1; 445 | *out.at(c_bin) += 1; 446 | } 447 | } 448 | out 449 | } 450 | } 451 | 452 | #[cfg(test)] 453 | mod tests { 454 | use std::io::prelude::*; 455 | use std::io::BufWriter; 456 | use std::fs::File; 457 | use crate::ThreeVec; 458 | use super::*; 459 | 460 | #[test] 461 | fn test_map() { 462 | let mut col_3v = Collection::empty(); 463 | for _i in 0..99999 { 464 | col_3v.push(ThreeVec::random(10.0)); 465 | } 466 | let _len_col: Collection = col_3v.map(ThreeVec::r); 467 | } 468 | 469 | #[test] 470 | fn test_hist() { 471 | let f = File::create("./scratch/test_hist.json").unwrap(); 472 | let mut wr = BufWriter::new(f); 473 | let mut col_3v = Collection::empty(); 474 | for _i in 0..99999 { 475 | col_3v.push(ThreeVec::random(10000.0)); 476 | } 477 | let len_col: Collection = col_3v.map(|tv| { *tv.x0()}); 478 | wr.write(len_col.hist(50).to_json().as_bytes()).unwrap(); 479 | } 480 | 481 | #[test] 482 | fn test_plot() { 483 | let f = File::create("./scratch/test_plot.json").unwrap(); 484 | let mut wr = BufWriter::new(f); 485 | let test_plot: Collection = Collection::plot(&vec![0.0,1.0,2.0],&vec![3.0,4.0,5.0]); 486 | wr.write(test_plot.to_json().as_bytes()).unwrap(); 487 | } 488 | 489 | #[test] 490 | fn test_json() { 491 | let f = File::create("./scratch/test_out.json").unwrap(); 492 | let mut wr = BufWriter::new(f); 493 | let mut col_3v = Collection::empty(); 494 | for _i in 0..9999 { 495 | col_3v.push(ThreeVec::random(10.0)); 496 | } 497 | wr.write(col_3v.map(ThreeVec::r).to_json().as_bytes()).unwrap(); 498 | } 499 | } 500 | -------------------------------------------------------------------------------- /src/four_mat/mod.rs: -------------------------------------------------------------------------------- 1 | use std::f64::NAN; 2 | 3 | use std::ops::Add; 4 | use std::ops::AddAssign; 5 | use std::ops::Sub; 6 | use std::ops::SubAssign; 7 | use std::ops::Mul; 8 | use std::ops::Neg; 9 | use std::fmt; 10 | use std::error; 11 | 12 | mod four_vec; 13 | 14 | pub use four_vec::Sinv; 15 | pub use four_vec::beta; 16 | pub use four_vec::gamma; 17 | pub use four_vec::FourVec; 18 | 19 | use crate::three_mat; 20 | use crate::utils; 21 | 22 | use three_mat::ThreeVec; 23 | 24 | use utils::{Serializable, Deserializable}; 25 | use utils::errors::CalcifyError; 26 | 27 | extern crate rmp; 28 | use rmp::encode::*; 29 | use rmp::decode::*; 30 | 31 | /// Four Matrix 32 | #[derive(Debug, PartialEq, Copy, Clone)] 33 | pub struct FourMat { 34 | /// Four rows, each a calcify::FourVec 35 | n0: FourVec, 36 | n1: FourVec, 37 | n2: FourVec, 38 | n3: FourVec, 39 | } 40 | 41 | impl 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 | 283 | impl 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 | 289 | impl 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,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 | 311 | impl Deserializable for FourMat { 312 | 313 | fn from_json(s: &str) -> Result> { 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> { 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 | 347 | impl 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 | 360 | impl 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 | 369 | impl 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 | 382 | impl 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 | 391 | impl Mul 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 | 404 | impl Mul 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 | 417 | impl Mul 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 | 453 | impl Mul 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 | 482 | impl 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 | /// ``` 521 | pub fn boost<'a>(initial: FourVec, v: ThreeVec) -> Result { 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)] 539 | mod 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 | } 562 | -------------------------------------------------------------------------------- /src/three_mat/mod.rs: -------------------------------------------------------------------------------- 1 | use std::ops::Add; 2 | use std::ops::AddAssign; 3 | use std::ops::Sub; 4 | use std::ops::SubAssign; 5 | use std::ops::Mul; 6 | use std::ops::Neg; 7 | use std::fmt; 8 | use std::error; 9 | use std::f64::NAN; 10 | 11 | /// Three Vector Module 12 | mod three_vec; 13 | pub use three_vec::ThreeVec; 14 | pub use three_vec::{radians_between, degrees_between}; 15 | 16 | use crate::utils; 17 | use utils::{Serializable, Deserializable}; 18 | use utils::errors::CalcifyError; 19 | 20 | extern crate rmp; 21 | use rmp::encode::*; 22 | use rmp::decode::*; 23 | 24 | /// Three Matrix 25 | #[derive(Debug, PartialEq, Copy, Clone)] 26 | pub struct ThreeMat { 27 | /// Three rows, each a calcify::ThreeVec 28 | r0: ThreeVec, 29 | r1: ThreeVec, 30 | r2: ThreeVec, 31 | } 32 | 33 | impl 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 | 238 | impl 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 | 244 | impl 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,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 | 262 | impl Deserializable for ThreeMat { 263 | 264 | fn from_json(s: &str) -> Result> { 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> { 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 | 295 | impl 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 | 307 | impl 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 | 315 | impl 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 | 327 | impl 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 | 335 | impl Mul 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 | 347 | impl Mul 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 | 359 | impl Mul 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 | 391 | impl Mul 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 | 419 | impl 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)] 433 | mod 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 | } 613 | --------------------------------------------------------------------------------