1use core::fmt;
2use std::ops::{Mul, Div, Add};
3
4use crate::si_unit::SiUnit;
5
6#[derive(Debug)]
7pub struct Value{
9 pub magnitude: f64,
11 pub si_units_num: Vec<SiUnit>,
13 pub si_units_den: Vec<SiUnit>
15
16}
17impl Value {
18pub 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 }
30pub fn set_magnitude(self,new_mag:f64) -> Self{
35 Self{magnitude: new_mag,..self}
36 }
37pub fn add_num(mut self,unit:SiUnit) -> Self{
43 self.si_units_num.push(unit);
44 self.simplify()
45 }
46pub fn add_den(mut self,unit:SiUnit) -> Self{
51 self.si_units_den.push(unit);
52 self.simplify()
53 }
54
55 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 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 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 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 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