Skip to main content

si_vectors/value/
mod.rs

1use core::fmt;
2use std::ops::{Mul, Div, Add};
3
4use crate::si_unit::SiUnit;
5
6#[derive(Debug)]
7/// Struct that represents a value with units
8pub struct Value{
9    ///Magnitude of Value
10    pub magnitude: f64,
11    ///Numerator
12    pub si_units_num: Vec<SiUnit>,
13    ///Denominator
14    pub si_units_den: Vec<SiUnit>
15
16}
17impl Value {
18///checks if two Values are the same
19/// ```rust
20/// let v1 = DerivedUnits::Hertz.get_value();
21/// let v2 = DerivedUnits::Newtons.get_value();
22/// assert_eq!(v1.same(v2),False);
23/// 
24    pub fn same(&self,other: &Value) -> bool{
25        let new_self = self.clone();
26        let new_other = other.clone();
27        let unit = new_self / new_other;
28        return unit.si_units_num.len() == 0 && unit.si_units_den.len() == 0;
29    }
30///sets magnitude of Value struct
31/// ```rust
32/// let v1 = DerivedUnits::Hertz.get_value().set_magnitude(50);
33/// println!("{}",v1);
34    pub fn set_magnitude(self,new_mag:f64) -> Self{
35        Self{magnitude: new_mag,..self}
36    }
37///Adds a unit to the numerator
38/// ```rust
39/// let v1 = DerivedUnits::Hertz.get_value().add_num(SiUnit::Kilogram);
40/// println!("{}",v1);
41
42    pub fn add_num(mut self,unit:SiUnit) -> Self{
43        self.si_units_num.push(unit);
44        self.simplify()
45    }
46///Adds a unit to the denominator
47/// ```rust
48/// let v1 = DerivedUnits::Hertz.get_value().add_den(SiUnit::Kilogram);
49/// println!("{}",v1);
50    pub fn add_den(mut self,unit:SiUnit) -> Self{
51        self.si_units_den.push(unit);
52        self.simplify()
53    }
54
55    /// Simplifies a Value struct by deleting units existing in both numerator and denominator
56    fn simplify(mut self) -> Self{ 
57        self.si_units_num.sort();
58        self.si_units_den.sort();
59        let (num,den) = Value::remove_duplicates(self.si_units_num, self.si_units_den);
60        Self{magnitude: self.magnitude,si_units_num: num,si_units_den: den}
61    }
62        /// Simplifies a Value struct by deleting one unit existing in both numerator and denominator
63    fn remove_one_duplicate(mut x:Vec<SiUnit>,mut y:Vec<SiUnit>) -> Result<(Vec<SiUnit>,Vec<SiUnit>),()>{
64        for i in 0..x.len(){
65            let e = &x[i];
66            match y.binary_search(e) {
67                Ok(r) => {
68                    x.remove(i);
69                    y.remove(r);
70                    
71                    return Ok((x,y));
72                },
73                Err(_) => ()
74            }
75        };
76        Err(())
77    }
78    /// Simplifies a Value struct by deleting units existing in both numerator and denominator
79    fn remove_duplicates(mut x:Vec<SiUnit>,mut y:Vec<SiUnit>) -> (Vec<SiUnit>,Vec<SiUnit>){
80        for _ in 0..=x.len(){
81            match Value::remove_one_duplicate(x.clone(), y.clone()){
82                Ok(r) => {
83                    x = r.0;
84                    y = r.1;
85                },
86                Err(_) => {return (x,y);}
87            }
88        }
89    
90        (x,y)
91    }
92    
93    /// Allows raising Value to int power;
94    pub fn powi(self,pow:i32) -> Self{
95
96        let new_mag = self.magnitude.powi(pow);
97        let mut new_num = Vec::<SiUnit>::new();
98        let mut new_den = Vec::<SiUnit>::new();
99
100        for _ in 0..pow{
101            new_num.append(&mut self.si_units_num.clone());
102            new_den.append(&mut self.si_units_den.clone());
103
104        }
105        Self{magnitude: new_mag,si_units_num: new_num,si_units_den: new_den}
106    }
107
108    /// Preform addition in a safe way
109    pub fn safe_add(self,rhs:Value) -> Result<Value,&'static str>{
110        if self.same(&rhs){
111            Ok(self + rhs)
112        }else {
113            Err("Units not Identical")
114        }
115    }
116
117}
118
119impl fmt::Display for Value{
120    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121        write!(f,"{} {:?}/ {:?} ",self.magnitude,self.si_units_num,self.si_units_den)
122    }
123}
124
125impl Mul<Value> for Value{
126    type Output = Value;
127    fn mul(self, rhs: Value) -> Self::Output {
128        let mut new_num = self.si_units_num;
129        new_num.extend(rhs.si_units_num);
130        let mut new_den= self.si_units_den;
131        new_den.extend(rhs.si_units_den);
132        let new_mag = self.magnitude*rhs.magnitude;
133        Self{magnitude: new_mag,si_units_num: new_num,si_units_den: new_den}.simplify()
134
135    }
136}
137
138impl Div<Value> for Value {
139    type Output = Value;
140    fn div(self, rhs: Value) -> Self::Output {
141        let mut new_num = self.si_units_num;
142        new_num.extend(rhs.si_units_den);
143        let mut new_den= self.si_units_den;
144        new_den.extend(rhs.si_units_num);
145        let new_mag = self.magnitude/rhs.magnitude;
146        Self{magnitude: new_mag,si_units_num: new_num,si_units_den: new_den}.simplify()
147    }
148}
149
150impl Mul<f64> for Value{
151    type Output = Value;
152    fn mul(self, rhs: f64) -> Self::Output {
153        Self{magnitude: self.magnitude * rhs,si_units_num: self.si_units_num,si_units_den: self.si_units_den}
154    }
155}
156
157impl Mul<f32> for Value{
158    type Output = Value;
159    fn mul(self, rhs: f32) -> Self::Output {
160        Self{magnitude: self.magnitude * rhs as f64,si_units_num: self.si_units_num,si_units_den: self.si_units_den}
161    }
162}
163
164impl Mul<i32> for Value{
165    type Output = Value;
166    fn mul(self, rhs: i32) -> Self::Output {
167        Self{magnitude: self.magnitude * rhs as f64,si_units_num: self.si_units_num,si_units_den: self.si_units_den}
168    }
169}
170
171impl Mul<i64> for Value{
172    type Output = Value;
173    fn mul(self, rhs: i64) -> Self::Output {
174        Self{magnitude: self.magnitude * rhs as f64,si_units_num: self.si_units_num,si_units_den: self.si_units_den}
175    }
176}
177
178impl Div<i32> for Value{
179    type Output = Value;
180    fn div(self, rhs: i32) -> Self::Output {
181        Self{magnitude: self.magnitude/rhs as f64,..self}
182    }
183}
184
185impl Div<f64> for Value{
186    type Output = Value;
187    fn div(self, rhs: f64) -> Self::Output {
188        Self{magnitude: self.magnitude/rhs,..self}
189    }
190} 
191impl Add<Value> for Value{
192    type Output = Value;
193    fn add(self, rhs: Self) -> Self::Output {
194        if self.si_units_num.len() == rhs.si_units_num.len() && self.si_units_den.len() == rhs.si_units_den.len(){
195            for unit in &self.si_units_num{
196                if !rhs.si_units_num.contains(unit){
197                    panic!("Units not Identical");
198                }
199            }
200            for unit in &self.si_units_den{
201                if !rhs.si_units_den.contains(unit){
202                    panic!("Units not Identical");
203                }
204            }
205            return Self{magnitude: self.magnitude + rhs.magnitude, ..self};
206        }
207        else{
208            panic!("Units not Identical");
209        }
210    }
211}
212
213impl Clone for Value{
214    fn clone(&self) -> Self {
215        Self{magnitude: self.magnitude,si_units_num: self.si_units_num.clone(),si_units_den: self.si_units_den.clone()}
216    }
217}
218