Fixed unit matching

pull/2/head
Mark 2023-07-28 09:28:08 -07:00
parent 625be634bf
commit 185b0415ff
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
2 changed files with 35 additions and 89 deletions

View File

@ -111,6 +111,37 @@ impl Quantity {
return Some(n.mul_no_convert(fa).div_no_convert(fb)) return Some(n.mul_no_convert(fa).div_no_convert(fb))
} }
pub fn match_units(&mut self, other: &Quantity) {
let mut new_units = Quantity::new_rational_from_string("1").unwrap();
let mut flag;
// Check every unit in `self`
for (us, ps) in self.unit.get_val() {
flag = false;
// Check if `us` matches some unit in `other`
for (uo, _) in other.unit.get_val() {
if {
uo.to_base().unit.compatible_with(&us.to_base().unit)
} {
// If it does, convert `us` to `uo`
new_units.insert_unit(uo.clone(), ps.clone());
flag = true;
break;
}
}
if !flag {
// If no unit in `other` matches `us`, don't convert `us`
new_units.insert_unit(us.clone(), ps.clone());
}
}
// Convert self to new units
*self = self.convert_to(new_units).unwrap();
}
pub fn convert_to_base(&self) -> Quantity { self.convert_to(self.unit.to_base()).unwrap() } pub fn convert_to_base(&self) -> Quantity { self.convert_to(self.unit.to_base()).unwrap() }
} }
@ -282,24 +313,13 @@ impl SubAssign for Quantity where {
} }
} }
impl Mul for Quantity { impl Mul for Quantity {
type Output = Self; type Output = Self;
fn mul(self, other: Self) -> Self::Output { fn mul(self, other: Self) -> Self::Output {
let mut o = other; let mut o = other;
if self.unit != o.unit { o.match_units(&self);
if o.unit.compatible_with(&self.unit) {
o = o.convert_to(self.clone()).unwrap()
} else {
let cf = self.unit.common_factor(&o.unit);
if let Some(f) = cf {
o = o.convert_to(f).unwrap();
}
}
}
Quantity { Quantity {
scalar: self.scalar * o.scalar, scalar: self.scalar * o.scalar,
@ -311,18 +331,8 @@ impl Mul for Quantity {
impl MulAssign for Quantity where { impl MulAssign for Quantity where {
fn mul_assign(&mut self, other: Self) { fn mul_assign(&mut self, other: Self) {
let mut o = other; let mut o = other;
if self.unit != o.unit { o.match_units(&self);
if o.unit.compatible_with(&self.unit) {
o = o.convert_to(self.clone()).unwrap()
} else {
let cf = self.unit.common_factor(&o.unit);
if let Some(f) = cf {
o = o.convert_to(f).unwrap();
}
}
}
self.scalar *= o.scalar; self.scalar *= o.scalar;
self.unit *= o.unit; self.unit *= o.unit;
@ -335,16 +345,7 @@ impl Div for Quantity {
fn div(self, other: Self) -> Self::Output { fn div(self, other: Self) -> Self::Output {
let mut o = other; let mut o = other;
if self.unit != o.unit { o.match_units(&self);
if o.unit.compatible_with(&self.unit) {
o = o.convert_to(self.clone()).unwrap()
} else {
let cf = self.unit.common_factor(&o.unit);
if let Some(f) = cf {
o = o.convert_to(f).unwrap();
}
}
}
Quantity { Quantity {
scalar: self.scalar / o.scalar, scalar: self.scalar / o.scalar,
@ -357,16 +358,7 @@ impl DivAssign for Quantity where {
fn div_assign(&mut self, other: Self) { fn div_assign(&mut self, other: Self) {
let mut o = other; let mut o = other;
if self.unit != o.unit { o.match_units(&self);
if o.unit.compatible_with(&self.unit) {
o = o.convert_to(self.clone()).unwrap()
} else {
let cf = self.unit.common_factor(&o.unit);
if let Some(f) = cf {
o = o.convert_to(f).unwrap();
}
}
}
self.scalar /= o.scalar; self.scalar /= o.scalar;
self.unit /= o.unit; self.unit /= o.unit;

View File

@ -161,52 +161,6 @@ impl Unit {
return o == s; return o == s;
} }
// True if these two units have a common factor
pub fn common_factor(&self, other: &Unit) -> Option<Quantity> {
if self.unitless() || other.unitless() { return None; }
let mut failed = false;
// What to convert `other` to before multiplying
let mut factor = Quantity::new_rational_from_string("1").unwrap();
let mut flag;
for (us, _) in self.get_val() {
flag = false;
for (uo, po) in other.get_val() {
if {
us.to_base().unit.compatible_with(&uo.to_base().unit)
} {
factor.insert_unit(us.clone(), po.clone());
flag = true;
break;
}
}
if !flag { failed = true }
}
if !failed { return Some(factor);}
let mut factor = Quantity::new_rational_from_string("1").unwrap();
for (uo, po) in other.get_val() {
flag = false;
for (us, _) in self.get_val() {
if {
us.to_base().unit.compatible_with(&uo.to_base().unit)
} {
factor.insert_unit(us.clone(), po.clone());
flag = true;
break;
}
}
if !flag { return None; }
}
return Some(factor);
}
pub fn insert(&mut self, u: FreeUnit, p: Scalar) { pub fn insert(&mut self, u: FreeUnit, p: Scalar) {
let v = self.get_val_mut(); let v = self.get_val_mut();
match v.get_mut(&u) { match v.get_mut(&u) {