mirror of https://github.com/rm-dr/daisy
Added conversion between prefixed units
parent
14ab0bd1d8
commit
84d2d68aa1
|
@ -93,7 +93,6 @@ impl Quantity {
|
||||||
pub fn set_unit(&mut self, u: Unit) { self.u = u; }
|
pub fn set_unit(&mut self, u: Unit) { self.u = u; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub fn convert_to(self, other: Quantity) -> Option<Quantity> {
|
pub fn convert_to(self, other: Quantity) -> Option<Quantity> {
|
||||||
let fa = self.u.to_base_factor();
|
let fa = self.u.to_base_factor();
|
||||||
let fb = other.u.to_base_factor();
|
let fb = other.u.to_base_factor();
|
||||||
|
@ -185,8 +184,13 @@ impl Add for Quantity {
|
||||||
fn add(self, other: Self) -> Self::Output {
|
fn add(self, other: Self) -> Self::Output {
|
||||||
if self.u != other.u { panic!() }
|
if self.u != other.u { panic!() }
|
||||||
|
|
||||||
|
let mut o = other;
|
||||||
|
if !o.u.prefixes_match(&self.u) {
|
||||||
|
o = o.convert_to(self.clone()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
Quantity {
|
Quantity {
|
||||||
v: self.v + other.v,
|
v: self.v + o.v,
|
||||||
u: self.u
|
u: self.u
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -195,7 +199,13 @@ impl Add for Quantity {
|
||||||
impl AddAssign for Quantity where {
|
impl AddAssign for Quantity where {
|
||||||
fn add_assign(&mut self, other: Self) {
|
fn add_assign(&mut self, other: Self) {
|
||||||
if self.u != other.u { panic!() }
|
if self.u != other.u { panic!() }
|
||||||
self.v += other.v
|
|
||||||
|
let mut o = other;
|
||||||
|
if !o.u.prefixes_match(&self.u) {
|
||||||
|
o = o.convert_to(self.clone()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.v += o.v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,8 +215,13 @@ impl Sub for Quantity {
|
||||||
fn sub(self, other: Self) -> Self::Output {
|
fn sub(self, other: Self) -> Self::Output {
|
||||||
if self.u != other.u { panic!() }
|
if self.u != other.u { panic!() }
|
||||||
|
|
||||||
|
let mut o = other;
|
||||||
|
if !o.u.prefixes_match(&self.u) {
|
||||||
|
o = o.convert_to(self.clone()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
Quantity {
|
Quantity {
|
||||||
v: self.v - other.v,
|
v: self.v - o.v,
|
||||||
u: self.u
|
u: self.u
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -215,7 +230,13 @@ impl Sub for Quantity {
|
||||||
impl SubAssign for Quantity where {
|
impl SubAssign for Quantity where {
|
||||||
fn sub_assign(&mut self, other: Self) {
|
fn sub_assign(&mut self, other: Self) {
|
||||||
if self.u != other.u { panic!() }
|
if self.u != other.u { panic!() }
|
||||||
self.v -= other.v
|
|
||||||
|
let mut o = other;
|
||||||
|
if !o.u.prefixes_match(&self.u) {
|
||||||
|
o = o.convert_to(self.clone()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.v -= o.v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,17 +244,22 @@ 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 f = self.u.match_prefix_factor(&other.u);
|
||||||
|
|
||||||
Quantity {
|
Quantity {
|
||||||
v: self.v * other.v,
|
v: self.v * other.v * f.v,
|
||||||
u: self.u * other.u
|
u: self.u * other.u * f.u,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MulAssign for Quantity where {
|
impl MulAssign for Quantity where {
|
||||||
fn mul_assign(&mut self, other: Self) {
|
fn mul_assign(&mut self, other: Self) {
|
||||||
self.v *= other.v;
|
let f = self.u.match_prefix_factor(&other.u);
|
||||||
self.u *= other.u;
|
|
||||||
|
self.v *= other.v * f.v;
|
||||||
|
self.u *= other.u * f.u;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::f32::consts::E;
|
use std::hash::{Hash, Hasher};
|
||||||
use std::ops::{
|
use std::ops::{
|
||||||
Mul, Div,
|
Mul, Div,
|
||||||
MulAssign, DivAssign
|
MulAssign, DivAssign
|
||||||
|
@ -142,15 +142,27 @@ impl ToString for Prefix {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Hash)]
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
#[derive(Eq, PartialEq)]
|
|
||||||
pub struct FreeUnit {
|
pub struct FreeUnit {
|
||||||
u: UnitBase,
|
u: UnitBase,
|
||||||
p: Prefix
|
p: Prefix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Hash for FreeUnit {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
self.u.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for FreeUnit {}
|
||||||
|
impl PartialEq for FreeUnit {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.u.eq(&other.u)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
macro_rules! quick_base_factor {
|
macro_rules! quick_base_factor {
|
||||||
(float, $u:expr, $s:expr, $( ($x:expr, $p:expr) ),* ) => {
|
(float, $u:expr, $s:expr, $( ($x:expr, $p:expr) ),* ) => {
|
||||||
Some(Quantity {
|
Some(Quantity {
|
||||||
|
@ -180,19 +192,17 @@ macro_rules! quick_base_factor {
|
||||||
|
|
||||||
impl FreeUnit {
|
impl FreeUnit {
|
||||||
pub fn from_base(u: UnitBase) -> FreeUnit {
|
pub fn from_base(u: UnitBase) -> FreeUnit {
|
||||||
return FreeUnit {
|
return FreeUnit { u, p: Prefix::None }
|
||||||
u,
|
|
||||||
p: Prefix::None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_base_prefix(u: UnitBase, p: Prefix) -> FreeUnit {
|
pub fn from_base_prefix(u: UnitBase, p: Prefix) -> FreeUnit { FreeUnit {u, p} }
|
||||||
return FreeUnit { u, p }
|
pub fn set_prefix(&mut self, p: Prefix) { self.p = p; }
|
||||||
|
pub fn get_prefix(&self) -> Prefix { self.p }
|
||||||
|
|
||||||
|
pub fn same_with_prefix(&self, other: &FreeUnit) -> bool {
|
||||||
|
self.u.eq(&other.u) && self.p.eq(&other.p)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_prefix(&mut self, p: Prefix) {
|
|
||||||
self.p = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_base_factor(&self) -> Quantity {
|
pub fn to_base_factor(&self) -> Quantity {
|
||||||
let q = match self.u {
|
let q = match self.u {
|
||||||
|
@ -360,6 +370,46 @@ impl Unit {
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn prefixes_match(&self, other: &Unit) -> bool {
|
||||||
|
let v = self.get_val();
|
||||||
|
for (u, _) in other.get_val() {
|
||||||
|
let k = v.get_key_value(u);
|
||||||
|
|
||||||
|
if k.is_some() {
|
||||||
|
let k = k.unwrap().0;
|
||||||
|
if !u.same_with_prefix(k) { return false; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn match_prefix_factor(&self, other: &Unit) -> Quantity {
|
||||||
|
let mut f = Quantity::new_rational(1f64).unwrap();
|
||||||
|
|
||||||
|
let v = self.get_val();
|
||||||
|
for (ou, op) in other.get_val() {
|
||||||
|
let k = v.get_key_value(ou);
|
||||||
|
|
||||||
|
if k.is_some() {
|
||||||
|
let (su, _) = k.unwrap();
|
||||||
|
|
||||||
|
// Conversion factor ou -> basic
|
||||||
|
let mut p = ou.p.to_ratio();
|
||||||
|
p.insert_unit(FreeUnit::from_base(ou.u), Scalar::new_rational(1f64).unwrap());
|
||||||
|
p.insert_unit(FreeUnit::from_base_prefix(ou.u, ou.p), Scalar::new_rational(-1f64).unwrap());
|
||||||
|
|
||||||
|
// Conversion factor su -> basic
|
||||||
|
let mut q = su.p.to_ratio();
|
||||||
|
q.insert_unit(FreeUnit::from_base(su.u), Scalar::new_rational(1f64).unwrap());
|
||||||
|
q.insert_unit(FreeUnit::from_base_prefix(su.u, su.p), Scalar::new_rational(-1f64).unwrap());
|
||||||
|
|
||||||
|
f = f * (p / q).pow(Quantity::from_scalar(op.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn unitless(&self) -> bool { self.get_val().len() == 0 }
|
pub fn unitless(&self) -> bool { self.get_val().len() == 0 }
|
||||||
|
|
||||||
pub fn insert(&mut self, u: FreeUnit, p: Scalar) {
|
pub fn insert(&mut self, u: FreeUnit, p: Scalar) {
|
||||||
|
@ -419,8 +469,19 @@ impl Unit {
|
||||||
if b.is_none() {
|
if b.is_none() {
|
||||||
if s == "kg" {
|
if s == "kg" {
|
||||||
let mut u = Unit::new();
|
let mut u = Unit::new();
|
||||||
let mut b = FreeUnit::from_base(UnitBase::Gram);
|
let b = FreeUnit::from_base_prefix(UnitBase::Gram, Prefix::Kilo);
|
||||||
b.set_prefix(Prefix::Kilo);
|
|
||||||
|
u.insert(b, Scalar::new_rational(1f64).unwrap());
|
||||||
|
|
||||||
|
let mut q = Quantity::new_rational(1f64).unwrap();
|
||||||
|
q.set_unit(u);
|
||||||
|
|
||||||
|
return Some(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
if s == "km" {
|
||||||
|
let mut u = Unit::new();
|
||||||
|
let b = FreeUnit::from_base_prefix(UnitBase::Meter, Prefix::Kilo);
|
||||||
|
|
||||||
u.insert(b, Scalar::new_rational(1f64).unwrap());
|
u.insert(b, Scalar::new_rational(1f64).unwrap());
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue